summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Moss <moss@lindenlab.com>2007-09-10 20:15:48 +0000
committerAdam Moss <moss@lindenlab.com>2007-09-10 20:15:48 +0000
commit96830697b2f3bb8d1d7e1c4a3a6872845a38926c (patch)
tree7663da01ec8eefb6fcdc4d4396d95c96f89cc970
parent80dfa222fdc3747be9f5b64b9ace35907edf1c4e (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.cpp42
-rw-r--r--indra/newview/lldirpicker.cpp54
-rw-r--r--indra/newview/lldirpicker.h7
-rw-r--r--indra/newview/llfilepicker.cpp270
-rw-r--r--indra/newview/llfilepicker.h15
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();