diff options
author | Adam Moss <moss@lindenlab.com> | 2007-09-10 20:15:48 +0000 |
---|---|---|
committer | Adam Moss <moss@lindenlab.com> | 2007-09-10 20:15:48 +0000 |
commit | 96830697b2f3bb8d1d7e1c4a3a6872845a38926c (patch) | |
tree | 7663da01ec8eefb6fcdc4d4396d95c96f89cc970 | |
parent | 80dfa222fdc3747be9f5b64b9ace35907edf1c4e (diff) |
SL-53811, SL-53812, SL-53823, SL-26604, SL-54282 Linux filepickers
revamp.
Passed by QA. Reviewed by bos.
svn merge svn+ssh://svn.lindenlab.com/svn/linden/release@68938
svn+ssh://svn.lindenlab.com/svn/linden/branches/moss/SL-26604-based-on-r68938
-> release
-rw-r--r-- | indra/llwindow/llwindowsdl.cpp | 42 | ||||
-rw-r--r-- | indra/newview/lldirpicker.cpp | 54 | ||||
-rw-r--r-- | indra/newview/lldirpicker.h | 7 | ||||
-rw-r--r-- | indra/newview/llfilepicker.cpp | 270 | ||||
-rw-r--r-- | indra/newview/llfilepicker.h | 15 |
5 files changed, 271 insertions, 117 deletions
diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 501e9119fb..86c9e8fdc6 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -2005,20 +2005,16 @@ void LLWindowSDL::gatherInput() SDLReallyCaptureInput(TRUE); if (event.key.keysym.unicode) - { - handleUnicodeUTF16(event.key.keysym.unicode, - gKeyboard->currentMask(FALSE)); - } + { + handleUnicodeUTF16(event.key.keysym.unicode, + gKeyboard->currentMask(FALSE)); + } break; case SDL_KEYUP: if (SDLCheckGrabbyKeys(event.key.keysym.sym, FALSE) == 0) SDLReallyCaptureInput(FALSE); // part of the fix for SL-13243 - // This is a testing hack to pop up a dialog when 4 is pressed - //if (event.key.keysym.sym == SDLK_4) - //OSMessageBox("a whole bunch of text goes right here, whee! test test test.", "this is the title!", OSMB_YESNO); - gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod); break; @@ -2099,9 +2095,9 @@ void LLWindowSDL::gatherInput() else if (event.button.button == SDL_BUTTON_RIGHT) // right ... yes, it's 3, not 2, in SDL... mCallbacks->handleRightMouseUp(this, openGlCoord, mask); else if (event.button.button == SDL_BUTTON_MIDDLE) // middle - { - mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask); - } + { + mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask); + } // don't handle mousewheel here... break; @@ -2155,18 +2151,18 @@ void LLWindowSDL::gatherInput() } if (event.active.state & SDL_APPACTIVE) { - // Change in iconification/minimization state. - if ((!event.active.gain) != mIsMinimized) - { - mCallbacks->handleActivate(this, !!event.active.gain); - llinfos << "SDL deiconification state switched to " << BOOL(event.active.gain) << llendl; - - mIsMinimized = (!event.active.gain); - } - else - { - llinfos << "Ignored bogus redundant SDL deiconification state switch to " << BOOL(event.active.gain) << llendl; - } + // Change in iconification/minimization state. + if ((!event.active.gain) != mIsMinimized) + { + mCallbacks->handleActivate(this, !!event.active.gain); + llinfos << "SDL deiconification state switched to " << BOOL(event.active.gain) << llendl; + + mIsMinimized = (!event.active.gain); + } + else + { + llinfos << "Ignored bogus redundant SDL deiconification state switch to " << BOOL(event.active.gain) << llendl; + } } break; diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp index 178cfb4e61..54b815e3a4 100644 --- a/indra/newview/lldirpicker.cpp +++ b/indra/newview/lldirpicker.cpp @@ -17,6 +17,10 @@ #include "lldir.h" #include "llframetimer.h" +#if LL_LINUX +# include "llfilepicker.h" +#endif + // // Globals // @@ -237,6 +241,56 @@ void LLDirPicker::reset() mDir = NULL; } +#elif LL_LINUX + +LLDirPicker::LLDirPicker() +{ + mFilePicker = new LLFilePicker(); + reset(); +} + +LLDirPicker::~LLDirPicker() +{ + delete mFilePicker; +} + + +void LLDirPicker::reset() +{ + if (mFilePicker) + mFilePicker->reset(); +} + +BOOL LLDirPicker::getDir(LLString* filename) +{ + reset(); + if (mFilePicker) + { + GtkWindow* picker = mFilePicker->buildFilePicker(false, true, + "dirpicker"); + + if (picker) + { + gtk_window_set_title(GTK_WINDOW(picker), "Choose Directory"); + gtk_widget_show_all(GTK_WIDGET(picker)); + gtk_main(); + return (NULL != mFilePicker->getFirstFile()); + } + } + return FALSE; +} + +LLString LLDirPicker::getDirName() +{ + if (mFilePicker) + { + const char* name = mFilePicker->getFirstFile(); + if (name) + return name; + } + return ""; +} + #else // not implemented LLDirPicker::LLDirPicker() diff --git a/indra/newview/lldirpicker.h b/indra/newview/lldirpicker.h index 7a80d047e1..062e368d06 100644 --- a/indra/newview/lldirpicker.h +++ b/indra/newview/lldirpicker.h @@ -33,6 +33,8 @@ #include <commdlg.h> #endif +class LLFilePicker; + class LLDirPicker { public: @@ -64,6 +66,11 @@ private: #endif +#if LL_LINUX + // On Linux we just implement LLDirPicker on top of LLFilePicker + LLFilePicker *mFilePicker; +#endif + char mDirs[DIRNAME_BUFFER_SIZE]; /*Flawfinder: ignore*/ LLString* mFileName; LLString mDir; diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 51e918e1d5..174e3b2381 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -9,8 +9,6 @@ #include "llviewerprecompiledheaders.h" #include "llfilepicker.h" -//#include "viewer.h" -//#include "llviewermessage.h" #include "llworld.h" #include "llviewerwindow.h" #include "llkeyboard.h" @@ -937,6 +935,10 @@ void LLFilePicker::reset() #elif LL_LINUX # if LL_GTK +// This caches the previously-accessed path for a given context of the file +// chooser, for user convenience. +std::map <std::string, std::string> LLFilePicker::sContextToPathMap; + LLFilePicker::LLFilePicker() { reset(); @@ -946,51 +948,83 @@ LLFilePicker::~LLFilePicker() { } -static void store_filenames(GtkWidget *widget, gpointer user_data) { + +static void add_to_sfs(gpointer data, gpointer user_data) +{ StoreFilenamesStruct *sfs = (StoreFilenamesStruct*) user_data; - GtkWidget *win = sfs->win; + gchar* filename_utf8 = g_filename_to_utf8((gchar*)data, + -1, NULL, + NULL, + NULL); + sfs->fileVector.push_back(LLString(filename_utf8)); + g_free(filename_utf8); +} - llinfos <<"store_filesnames: marker A" << llendl; - // get NULL-terminated list of strings allocated for us by GTK - gchar** string_list = - gtk_file_selection_get_selections(GTK_FILE_SELECTION(win)); +void chooser_responder(GtkWidget *widget, + gint response, + gpointer user_data) { + StoreFilenamesStruct *sfs = (StoreFilenamesStruct*) user_data; - llinfos <<"store_filesnames: marker B" << llendl; + lldebugs << "GTK DIALOG RESPONSE " << response << llendl; - int idx = 0; - while (string_list[idx]) + if (response == GTK_RESPONSE_ACCEPT) { - // platform-string to utf8 - gchar* filename_utf8 = g_filename_from_utf8(string_list[idx], - -1, NULL, - NULL, - NULL); - sfs->fileVector.push_back(LLString(filename_utf8)); - ++idx; + GSList *file_list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget)); + g_slist_foreach(file_list, (GFunc)add_to_sfs, sfs); + g_slist_foreach(file_list, (GFunc)g_free, NULL); + g_slist_free (file_list); } - llinfos <<"store_filesnames: marker C" << llendl; + // set the default path for this usage context. + LLFilePicker::sContextToPathMap[sfs->contextName] = + gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget)); - g_strfreev(string_list); - - llinfos <<"store_filesnames: marker D" << llendl; - - llinfos << sfs->fileVector.size() << " filename(s) selected:" << llendl; - U32 x; - for (x=0; x<sfs->fileVector.size(); ++x) - llinfos << x << ":" << sfs->fileVector[x] << llendl; + gtk_widget_destroy(widget); + gtk_main_quit(); } -GtkWindow* LLFilePicker::buildFilePicker(void) + +GtkWindow* LLFilePicker::buildFilePicker(bool is_save, bool is_folder, + std::string context) { if (ll_try_gtk_init() && ! gViewerWindow->getWindow()->getFullscreen()) { GtkWidget *win = NULL; - - win = gtk_file_selection_new(NULL); + GtkFileChooserAction pickertype = + is_save? + (is_folder? + GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER : + GTK_FILE_CHOOSER_ACTION_SAVE) : + (is_folder? + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER : + GTK_FILE_CHOOSER_ACTION_OPEN); + + win = gtk_file_chooser_dialog_new(NULL, NULL, + pickertype, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + is_folder ? + GTK_STOCK_APPLY : + (is_save ? + GTK_STOCK_SAVE : + GTK_STOCK_OPEN), + GTK_RESPONSE_ACCEPT, + NULL); mStoreFilenames.win = win; + mStoreFilenames.contextName = context; + + // get the default path for this usage context if it's been + // seen before. + std::map<std::string,std::string>::iterator + this_path = sContextToPathMap.find(context); + if (this_path != sContextToPathMap.end()) + { + gtk_file_chooser_set_current_folder + (GTK_FILE_CHOOSER(win), + this_path->second.c_str()); + } # if LL_X11 // Make GTK tell the window manager to associate this @@ -1010,33 +1044,17 @@ GtkWindow* LLFilePicker::buildFilePicker(void) } # endif //LL_X11 - g_signal_connect (G_OBJECT(win), "destroy", - G_CALLBACK(gtk_main_quit), NULL); - - // on 'ok', grab the file selection list - g_signal_connect (GTK_FILE_SELECTION(win)->ok_button, - "clicked", - G_CALLBACK(store_filenames), + g_signal_connect (GTK_FILE_CHOOSER(win), + "response", + G_CALLBACK(chooser_responder), &mStoreFilenames); - // both 'ok' and 'cancel' will end the dialog - g_signal_connect_swapped (G_OBJECT(GTK_FILE_SELECTION(win)-> - ok_button), - "clicked", - G_CALLBACK(gtk_widget_destroy), - G_OBJECT(win)); - g_signal_connect_swapped (G_OBJECT(GTK_FILE_SELECTION(win)-> - cancel_button), - "clicked", - G_CALLBACK(gtk_widget_destroy), - G_OBJECT(win)); - - gtk_file_selection_show_fileop_buttons(GTK_FILE_SELECTION(win)); - gtk_file_selection_set_select_multiple(GTK_FILE_SELECTION(win), - FALSE); - gtk_window_set_modal(GTK_WINDOW(win), TRUE); + /* GTK 2.6: if (is_folder) + gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(win), + TRUE); */ + return GTK_WINDOW(win); } else @@ -1045,6 +1063,65 @@ GtkWindow* LLFilePicker::buildFilePicker(void) } } +static void add_common_filters_to_gtkchooser(GtkFileFilter *gfilter, + GtkWindow *picker, + std::string filtername) +{ + gtk_file_filter_set_name(gfilter, filtername.c_str()); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), + gfilter); + GtkFileFilter *allfilter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(allfilter, "*"); + gtk_file_filter_set_name(allfilter, "All Files"); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), allfilter); + gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(picker), gfilter); +} + +static std::string add_simple_pattern_filter_to_gtkchooser(GtkWindow *picker, + std::string pattern, + std::string filtername) +{ + GtkFileFilter *gfilter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(gfilter, pattern.c_str()); + add_common_filters_to_gtkchooser(gfilter, picker, filtername); + return filtername; +} + +static std::string add_simple_mime_filter_to_gtkchooser(GtkWindow *picker, + std::string mime, + std::string filtername) +{ + GtkFileFilter *gfilter = gtk_file_filter_new(); + gtk_file_filter_add_mime_type(gfilter, mime.c_str()); + add_common_filters_to_gtkchooser(gfilter, picker, filtername); + return filtername; +} + +static std::string add_wav_filter_to_gtkchooser(GtkWindow *picker) +{ + return add_simple_mime_filter_to_gtkchooser(picker, "audio/x-wav", + "Sounds (*.wav)"); +} + +static std::string add_bvh_filter_to_gtkchooser(GtkWindow *picker) +{ + return add_simple_pattern_filter_to_gtkchooser(picker, "*.bvh", + "Animations (*.bvh)"); +} + +static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker) +{ + GtkFileFilter *gfilter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(gfilter, "*.tga"); + gtk_file_filter_add_mime_type(gfilter, "image/jpeg"); + gtk_file_filter_add_mime_type(gfilter, "image/png"); + gtk_file_filter_add_mime_type(gfilter, "image/bmp"); + std::string filtername = "Images (*.tga; *.bmp; *.jpg; *.png)"; + add_common_filters_to_gtkchooser(gfilter, picker, filtername); + return filtername; +} + + BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const char* filename ) { BOOL rtn = FALSE; @@ -1052,7 +1129,7 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const char* filename ) gViewerWindow->mWindow->beforeDialog(); reset(); - GtkWindow* picker = buildFilePicker(); + GtkWindow* picker = buildFilePicker(true, false, "savefile"); if (picker) { @@ -1062,36 +1139,45 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const char* filename ) switch (filter) { case FFSAVE_WAV: - caption += "Sounds (*.wav)"; - suggest_ext += ".wav"; + caption += add_wav_filter_to_gtkchooser(picker); + suggest_ext = ".wav"; break; case FFSAVE_TGA: - caption += "Targa Images (*.tga)"; - suggest_ext += ".tga"; + caption += add_simple_pattern_filter_to_gtkchooser + (picker, "*.tga", "Targa Images (*.tga)"); + suggest_ext = ".tga"; break; case FFSAVE_BMP: - caption += "Bitmap Images (*.bmp)"; - suggest_ext += ".bmp"; + caption += add_simple_mime_filter_to_gtkchooser + (picker, "image/bmp", "Bitmap Images (*.bmp)"); + suggest_ext = ".bmp"; break; case FFSAVE_AVI: - caption += "AVI Movie File (*.avi)"; - suggest_ext += ".avi"; + caption += add_simple_mime_filter_to_gtkchooser + (picker, "video/x-msvideo", + "AVI Movie File (*.avi)"); + suggest_ext = ".avi"; break; case FFSAVE_ANIM: - caption += "XAF Anim File (*.xaf)"; - suggest_ext += ".xaf"; + caption += add_simple_pattern_filter_to_gtkchooser + (picker, "*.xaf", "XAF Anim File (*.xaf)"); + suggest_ext = ".xaf"; break; case FFSAVE_XML: - caption += "XML File (*.xml)"; - suggest_ext += ".xml"; + caption += add_simple_pattern_filter_to_gtkchooser + (picker, "*.xml", "XML File (*.xml)"); + suggest_ext = ".xml"; break; case FFSAVE_RAW: - caption += "RAW File (*.raw)"; - suggest_ext += ".raw"; + caption += add_simple_pattern_filter_to_gtkchooser + (picker, "*.raw", "RAW File (*.raw)"); + suggest_ext = ".raw"; break; case FFSAVE_J2C: - caption += "Compressed Images (*.j2c)"; - suggest_ext += ".j2c"; + caption += add_simple_mime_filter_to_gtkchooser + (picker, "images/jp2", + "Compressed Images (*.j2c)"); + suggest_ext = ".j2c"; break; default:; break; @@ -1103,27 +1189,19 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const char* filename ) { suggest_name += suggest_ext; - gtk_file_selection_set_filename - (GTK_FILE_SELECTION(picker), - g_filename_from_utf8(suggest_name.c_str(), - -1, NULL, - NULL, - NULL)); - gtk_editable_select_region(GTK_EDITABLE(GTK_FILE_SELECTION(picker)->selection_entry), 0, suggest_name.length() - suggest_ext.length() ); + gtk_file_chooser_set_current_name + (GTK_FILE_CHOOSER(picker), + suggest_name.c_str()); } else { - gtk_file_selection_set_filename - (GTK_FILE_SELECTION(picker), - g_filename_from_utf8(filename, - -1, NULL, - NULL, - NULL)); - gtk_editable_select_region(GTK_EDITABLE(GTK_FILE_SELECTION(picker)->selection_entry), 0, -1 ); + gtk_file_chooser_set_current_name + (GTK_FILE_CHOOSER(picker), filename); } gtk_widget_show_all(GTK_WIDGET(picker)); gtk_main(); + rtn = (mStoreFilenames.fileVector.size() == 1); } @@ -1139,27 +1217,34 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter ) gViewerWindow->mWindow->beforeDialog(); reset(); - GtkWindow* picker = buildFilePicker(); + GtkWindow* picker = buildFilePicker(false, false, "openfile"); if (picker) { std::string caption = "Load "; + std::string filtername = ""; switch (filter) { case FFLOAD_WAV: - caption += "Sounds (*.wav)"; break; + filtername = add_wav_filter_to_gtkchooser(picker); + break; case FFLOAD_ANIM: - caption += "Animations (*.bvh)"; break; + filtername = add_bvh_filter_to_gtkchooser(picker); + break; case FFLOAD_IMAGE: - caption += "Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)"; break; + filtername = add_imageload_filter_to_gtkchooser(picker); + break; default:; break; } + + caption += filtername; gtk_window_set_title(GTK_WINDOW(picker), caption.c_str()); gtk_widget_show_all(GTK_WIDGET(picker)); gtk_main(); + rtn = (mStoreFilenames.fileVector.size() == 1); } @@ -1175,12 +1260,12 @@ BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter ) gViewerWindow->mWindow->beforeDialog(); reset(); - GtkWindow* picker = buildFilePicker(); + GtkWindow* picker = buildFilePicker(false, false, "openfile"); if (picker) { - gtk_file_selection_set_select_multiple(GTK_FILE_SELECTION(picker), - TRUE); + gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(picker), + TRUE); gtk_window_set_title(GTK_WINDOW(picker), "Load Files"); @@ -1221,7 +1306,8 @@ const char* LLFilePicker::getDirname() const char* fullpath = mStoreFilenames.fileVector[index].c_str(); const char* finalpart = NULL; const char* thispart = fullpath; - // walk through the string looking for the final dirsep, i.e. / + // (Hmm, is the strstr of dirsep UTF-8-correct? Yes, reckon.) + // Walk through the string looking for the final dirsep, i.e. / do { thispart = strstr(thispart, dirsep); diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index c04279ee91..bb63e33fe5 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -50,11 +50,16 @@ typedef struct { GtkWidget *win; std::vector<LLString> fileVector; + std::string contextName; } StoreFilenamesStruct; #endif // LL_GTK class LLFilePicker { +#ifdef LL_GTK + friend class LLDirPicker; + friend void chooser_responder(GtkWidget *, gint, gpointer); +#endif // LL_GTK public: // calling this before main() is undefined static LLFilePicker& instance( void ) { return sInstance; } @@ -146,9 +151,9 @@ private: #if LL_GTK StoreFilenamesStruct mStoreFilenames; - - GtkWindow* buildFilePicker(void); U32 mNextFileIndex; + // we remember the last path that was accessed for a particular usage + static std::map <std::string, std::string> sContextToPathMap; #endif char mFiles[FILENAME_BUFFER_SIZE]; /*Flawfinder: ignore*/ @@ -159,6 +164,12 @@ private: static LLFilePicker sInstance; +protected: +#if LL_GTK + GtkWindow* buildFilePicker(bool is_save, bool is_folder, + std::string context = "generic"); +#endif + public: // don't call these directly please. LLFilePicker(); |