summaryrefslogtreecommitdiff
path: root/indra/newview/llfilepicker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llfilepicker.cpp')
-rw-r--r--indra/newview/llfilepicker.cpp664
1 files changed, 253 insertions, 411 deletions
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 0108ac205e..c14be89641 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -2,30 +2,25 @@
* @file llfilepicker.cpp
* @brief OS-specific file picker
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -37,6 +32,8 @@
#include "llkeyboard.h"
#include "lldir.h"
#include "llframetimer.h"
+#include "lltrans.h"
+#include "llwindow.h" // beforeDialog()
#if LL_SDL
#include "llwindowsdl.h" // for some X/GTK utils to help with filepickers
@@ -63,12 +60,14 @@ LLFilePicker LLFilePicker::sInstance;
//
// Implementation
//
-#if LL_WINDOWS
+LLFilePicker::LLFilePicker()
+ : mCurrentFile(0),
+ mLocked(false)
-LLFilePicker::LLFilePicker()
{
reset();
+#if LL_WINDOWS
mOFN.lStructSize = sizeof(OPENFILENAMEW);
mOFN.hwndOwner = NULL; // Set later
mOFN.hInstance = NULL;
@@ -87,6 +86,17 @@ LLFilePicker::LLFilePicker()
mOFN.lCustData = 0L;
mOFN.lpfnHook = NULL;
mOFN.lpTemplateName = NULL;
+ mFilesW[0] = '\0';
+#endif
+
+#if LL_DARWIN
+ memset(&mNavOptions, 0, sizeof(mNavOptions));
+ OSStatus error = NavGetDefaultDialogCreationOptions(&mNavOptions);
+ if (error == noErr)
+ {
+ mNavOptions.modality = kWindowModalityAppModal;
+ }
+#endif
}
LLFilePicker::~LLFilePicker()
@@ -94,6 +104,48 @@ LLFilePicker::~LLFilePicker()
// nothing
}
+
+const std::string LLFilePicker::getFirstFile()
+{
+ mCurrentFile = 0;
+ return getNextFile();
+}
+
+const std::string LLFilePicker::getNextFile()
+{
+ if (mCurrentFile >= getFileCount())
+ {
+ mLocked = false;
+ return std::string();
+ }
+ else
+ {
+ return mFiles[mCurrentFile++];
+ }
+}
+
+const std::string LLFilePicker::getCurFile()
+{
+ if (mCurrentFile >= getFileCount())
+ {
+ mLocked = false;
+ return std::string();
+ }
+ else
+ {
+ return mFiles[mCurrentFile];
+ }
+}
+
+void LLFilePicker::reset()
+{
+ mLocked = false;
+ mFiles.clear();
+ mCurrentFile = 0;
+}
+
+#if LL_WINDOWS
+
BOOL LLFilePicker::setupFilter(ELoadFilter filter)
{
BOOL res = TRUE;
@@ -150,7 +202,6 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter)
return FALSE;
}
BOOL success = FALSE;
- mMultiFile = FALSE;
// don't provide default file selection
mFilesW[0] = '\0';
@@ -165,13 +216,15 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter)
// Modal, so pause agent
send_agent_pause();
+
+ reset();
+
// NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
success = GetOpenFileName(&mOFN);
if (success)
{
- LLString tstr = utf16str_to_utf8str(llutf16string(mFilesW));
- memcpy(mFiles, tstr.c_str(), tstr.size()+1); /*Flawfinder: ignore*/
- mCurrentFile = mFiles;
+ std::string filename = utf16str_to_utf8str(llutf16string(mFilesW));
+ mFiles.push_back(filename);
}
send_agent_resume();
@@ -187,7 +240,6 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
return FALSE;
}
BOOL success = FALSE;
- mMultiFile = FALSE;
// don't provide default file selection
mFilesW[0] = '\0';
@@ -200,6 +252,8 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
OFN_EXPLORER | OFN_ALLOWMULTISELECT;
setupFilter(filter);
+
+ reset();
// Modal, so pause agent
send_agent_pause();
@@ -212,31 +266,26 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
// lengths.
if( wcslen(mOFN.lpstrFile) > mOFN.nFileOffset ) /*Flawfinder: ignore*/
{
- mMultiFile = FALSE;
- mCurrentFile = mFiles;
- LLString tstr = utf16str_to_utf8str(llutf16string(mFilesW));
- memcpy(mFiles, tstr.c_str(), tstr.size()+1); /*Flawfinder: ignore*/
-
- mCurrentFile = &mFiles[mOFN.nFileOffset];
+ std::string filename = utf16str_to_utf8str(llutf16string(mFilesW));
+ mFiles.push_back(filename);
}
else
{
- mMultiFile = TRUE;
- mCurrentFile = 0;
- mLocked = TRUE;
+ mLocked = true;
WCHAR* tptrw = mFilesW;
- char* tptr = mFiles;
- memset( mFiles, 0, FILENAME_BUFFER_SIZE );
+ std::string dirname;
while(1)
{
if (*tptrw == 0 && *(tptrw+1) == 0) // double '\0'
break;
- if (*tptrw == 0 && !mCurrentFile)
- mCurrentFile = tptr+1;
- S32 tlen16,tlen8;
- tlen16 = utf16chars_to_utf8chars(tptrw, tptr, &tlen8);
- tptrw += tlen16;
- tptr += tlen8;
+ if (*tptrw == 0)
+ tptrw++; // shouldn't happen?
+ std::string filename = utf16str_to_utf8str(llutf16string(tptrw));
+ if (dirname.empty())
+ dirname = filename + "\\";
+ else
+ mFiles.push_back(dirname + filename);
+ tptrw += filename.size();
}
}
}
@@ -247,17 +296,16 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
return success;
}
-BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
+BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
{
if( mLocked )
{
return FALSE;
}
BOOL success = FALSE;
- mMultiFile = FALSE;
mOFN.lpstrFile = mFilesW;
- if (filename)
+ if (!filename.empty())
{
llutf16string tstring = utf8str_to_utf16str(filename);
wcsncpy(mFilesW, tstring.c_str(), FILENAME_BUFFER_SIZE); } /*Flawfinder: ignore*/
@@ -278,7 +326,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
L"\0";
break;
case FFSAVE_WAV:
- if (!filename)
+ if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.wav", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
@@ -288,7 +336,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
L"\0";
break;
case FFSAVE_TGA:
- if (!filename)
+ if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.tga", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
@@ -298,7 +346,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
L"\0";
break;
case FFSAVE_BMP:
- if (!filename)
+ if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.bmp", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
@@ -307,8 +355,28 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
L"Bitmap Images (*.bmp)\0*.bmp\0" \
L"\0";
break;
+ case FFSAVE_PNG:
+ if (filename.empty())
+ {
+ wcsncpy( mFilesW,L"untitled.png", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ }
+ mOFN.lpstrDefExt = L"png";
+ mOFN.lpstrFilter =
+ L"PNG Images (*.png)\0*.png\0" \
+ L"\0";
+ break;
+ case FFSAVE_JPEG:
+ if (filename.empty())
+ {
+ wcsncpy( mFilesW,L"untitled.jpeg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ }
+ mOFN.lpstrDefExt = L"jpeg";
+ mOFN.lpstrFilter =
+ L"JPEG Images (*.jpeg)\0*.jpeg\0" \
+ L"\0";
+ break;
case FFSAVE_AVI:
- if (!filename)
+ if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.avi", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
@@ -318,7 +386,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
L"\0";
break;
case FFSAVE_ANIM:
- if (!filename)
+ if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.xaf", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
@@ -329,7 +397,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
break;
#ifdef _CORY_TESTING
case FFSAVE_GEOMETRY:
- if (!filename)
+ if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.slg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
@@ -340,7 +408,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
break;
#endif
case FFSAVE_XML:
- if (!filename)
+ if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.xml", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
@@ -351,7 +419,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
L"\0";
break;
case FFSAVE_COLLADA:
- if (!filename)
+ if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.collada", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
@@ -361,7 +429,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
L"\0";
break;
case FFSAVE_RAW:
- if (!filename)
+ if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.raw", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
@@ -370,7 +438,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
L"\0";
break;
case FFSAVE_J2C:
- if (!filename)
+ if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.j2c", FILENAME_BUFFER_SIZE);
}
@@ -387,6 +455,8 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE;
mOFN.Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
+ reset();
+
// Modal, so pause agent
send_agent_pause();
{
@@ -394,9 +464,8 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
success = GetSaveFileName(&mOFN);
if (success)
{
- LLString tstr = utf16str_to_utf8str(llutf16string(mFilesW));
- memcpy(mFiles, tstr.c_str(), tstr.size()+1); /*Flawfinder: ignore*/
- mCurrentFile = mFiles;
+ std::string filename = utf16str_to_utf8str(llutf16string(mFilesW));
+ mFiles.push_back(filename);
}
gKeyboard->resetKeys();
}
@@ -407,84 +476,8 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
return success;
}
-const char* LLFilePicker::getFirstFile()
-{
- if(mMultiFile)
- {
- buildFilename();
- return mFilename;
- }
- return mFiles;
-}
-
-const char* LLFilePicker::getNextFile()
-{
- if(mMultiFile)
- {
- mCurrentFile += strlen(mCurrentFile) + 1; /*Flawfinder: ignore*/
- if( '\0' != mCurrentFile[0] )
- {
- buildFilename();
- return mFilename;
- }
- else
- {
- mLocked = FALSE;
- }
- }
- return NULL;
-}
-
-const char* LLFilePicker::getDirname()
-{
- if( '\0' != mCurrentFile[0] )
- {
- return mCurrentFile;
- }
- return NULL;
-}
-
-void LLFilePicker::reset()
-{
- mLocked = FALSE;
- memset( mFiles, 0, FILENAME_BUFFER_SIZE );
- memset( mFilename, 0, LL_MAX_PATH );
- mCurrentFile = mFiles;
-}
-
-void LLFilePicker::buildFilename( void )
-{
- strncpy( mFilename, mFiles, LL_MAX_PATH );
- mFilename[LL_MAX_PATH-1] = '\0'; // stupid strncpy
- S32 len = strlen( mFilename );
-
- strncat(mFilename,gDirUtilp->getDirDelimiter().c_str(), sizeof(mFilename)-len+1); /*Flawfinder: ignore*/
- len += strlen(gDirUtilp->getDirDelimiter().c_str()); /*Flawfinder: ignore*/
-
-// mFilename[len++] = '\\';
- LLString::copy( mFilename + len, mCurrentFile, LL_MAX_PATH - len );
-}
-
#elif LL_DARWIN
-LLFilePicker::LLFilePicker()
-{
- reset();
-
- memset(&mNavOptions, 0, sizeof(mNavOptions));
- OSStatus error = NavGetDefaultDialogCreationOptions(&mNavOptions);
- if (error == noErr)
- {
- mNavOptions.modality = kWindowModalityAppModal;
- }
- mFileIndex = 0;
-}
-
-LLFilePicker::~LLFilePicker()
-{
- // nothing
-}
-
Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode)
{
Boolean result = true;
@@ -589,8 +582,6 @@ OSStatus LLFilePicker::doNavChooseDialog(ELoadFilter filter)
NavReplyRecord navReply;
memset(&navReply, 0, sizeof(navReply));
- mFiles[0] = '\0';
- mFileVector.clear();
// NOTE: we are passing the address of a local variable here.
// This is fine, because the object this call creates will exist for less than the lifetime of this function.
@@ -632,22 +623,20 @@ OSStatus LLFilePicker::doNavChooseDialog(ELoadFilter filter)
error = FSRefMakePath(&fsRef, (UInt8*) path, sizeof(path));
if (error == noErr)
- mFileVector.push_back(LLString(path));
+ mFiles.push_back(std::string(path));
}
}
return error;
}
-OSStatus LLFilePicker::doNavSaveDialog(ESaveFilter filter, const char* filename)
+OSStatus LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filename)
{
OSStatus error = noErr;
NavDialogRef navRef = NULL;
NavReplyRecord navReply;
memset(&navReply, 0, sizeof(navReply));
- mFiles[0] = '\0';
- mFileVector.clear();
// Setup the type, creator, and extension
OSType type, creator;
@@ -671,7 +660,16 @@ OSStatus LLFilePicker::doNavSaveDialog(ESaveFilter filter, const char* filename)
creator = 'prvw';
extension = CFSTR(".bmp");
break;
-
+ case FFSAVE_JPEG:
+ type = 'JPEG';
+ creator = 'prvw';
+ extension = CFSTR(".jpeg");
+ break;
+ case FFSAVE_PNG:
+ type = 'PNG ';
+ creator = 'prvw';
+ extension = CFSTR(".png");
+ break;
case FFSAVE_AVI:
type = '\?\?\?\?';
creator = '\?\?\?\?';
@@ -719,8 +717,8 @@ OSStatus LLFilePicker::doNavSaveDialog(ESaveFilter filter, const char* filename)
bool hasExtension = true;
// Create a CFString of the initial file name
- if (filename)
- nameString = CFStringCreateWithCString(NULL, filename, kCFStringEncodingUTF8);
+ if (!filename.empty())
+ nameString = CFStringCreateWithCString(NULL, filename.c_str(), kCFStringEncodingUTF8);
else
nameString = CFSTR("Untitled");
@@ -786,7 +784,7 @@ OSStatus LLFilePicker::doNavSaveDialog(ESaveFilter filter, const char* filename)
{
if (CFStringGetCString(navReply.saveFileName, newFileName, sizeof(newFileName), kCFStringEncodingUTF8))
{
- mFileVector.push_back(LLString(path) + LLString("/") + LLString(newFileName));
+ mFiles.push_back(std::string(path) + "/" + std::string(newFileName));
}
else
{
@@ -806,14 +804,23 @@ OSStatus LLFilePicker::doNavSaveDialog(ESaveFilter filter, const char* filename)
BOOL LLFilePicker::getOpenFile(ELoadFilter filter)
{
- if( mLocked ) return FALSE;
- mMultiFile = FALSE;
+ if( mLocked )
+ return FALSE;
+
BOOL success = FALSE;
OSStatus error = noErr;
- mFileVector.clear();
+ reset();
+
mNavOptions.optionFlags &= ~kNavAllowMultipleFiles;
+
+ if(filter == FFLOAD_ALL) // allow application bundles etc. to be traversed; important for DEV-16869, but generally useful
+ {
+ // mNavOptions.optionFlags |= kNavAllowOpenPackages;
+ mNavOptions.optionFlags |= kNavSupportPackages;
+ }
+
// Modal, so pause agent
send_agent_pause();
{
@@ -822,7 +829,7 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter)
send_agent_resume();
if (error == noErr)
{
- if (mFileVector.size())
+ if (getFileCount())
success = true;
}
@@ -833,13 +840,15 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter)
BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
{
- if( mLocked ) return FALSE;
- mMultiFile = TRUE;
+ if( mLocked )
+ return FALSE;
+
BOOL success = FALSE;
OSStatus error = noErr;
+
+ reset();
- mFileVector.clear();
mNavOptions.optionFlags |= kNavAllowMultipleFiles;
// Modal, so pause agent
send_agent_pause();
@@ -849,10 +858,10 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
send_agent_resume();
if (error == noErr)
{
- if (mFileVector.size())
+ if (getFileCount())
success = true;
- if (mFileVector.size() > 1)
- mLocked = TRUE;
+ if (getFileCount() > 1)
+ mLocked = true;
}
// Account for the fact that the app has been stalled.
@@ -860,38 +869,15 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter)
return success;
}
-void LLFilePicker::getFilePath(SInt32 index)
-{
- mFiles[0] = 0;
- if (mFileVector.size())
- {
- strncpy(mFiles, mFileVector[index].c_str(), sizeof(mFiles));
- mFiles[sizeof(mFiles)-1] = '\0'; // stupid strncpy
- }
-}
-
-void LLFilePicker::getFileName(SInt32 index)
-{
- mFilename[0] = 0;
- if (mFileVector.size())
- {
- char *start = strrchr(mFileVector[index].c_str(), '/');
- if (start && ((start + 1 - mFileVector[index].c_str()) < (mFileVector[index].size())))
- {
- strncpy(mFilename, start + 1, sizeof(mFilename));
- mFilename[sizeof(mFilename)-1] = '\0';// stupid strncpy
- }
- }
-}
-
-BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
+BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename)
{
- if( mLocked ) return FALSE;
+ if( mLocked )
+ return FALSE;
BOOL success = FALSE;
OSStatus error = noErr;
- mFileVector.clear();
- mMultiFile = FALSE;
+ reset();
+
mNavOptions.optionFlags &= ~kNavAllowMultipleFiles;
// Modal, so pause agent
@@ -902,7 +888,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
send_agent_resume();
if (error == noErr)
{
- if (mFileVector.size())
+ if (getFileCount())
success = true;
}
@@ -911,98 +897,64 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename)
return success;
}
-const char* LLFilePicker::getFirstFile()
-{
- mFileIndex = 0;
- getFilePath(mFileIndex);
- return mFiles;
-}
+#elif LL_LINUX || LL_SOLARIS
+
+# if LL_GTK
-const char* LLFilePicker::getNextFile()
+// static
+void LLFilePicker::add_to_selectedfiles(gpointer data, gpointer user_data)
{
- if(mMultiFile)
+ // We need to run g_filename_to_utf8 in the user's locale
+ std::string saved_locale(setlocale(LC_ALL, NULL));
+ setlocale(LC_ALL, "");
+
+ LLFilePicker* picker = (LLFilePicker*) user_data;
+ GError *error = NULL;
+ gchar* filename_utf8 = g_filename_to_utf8((gchar*)data,
+ -1, NULL, NULL, &error);
+ if (error)
{
- mFileIndex++;
- if (mFileIndex < mFileVector.size())
- {
- getFilePath(mFileIndex);
- return mFiles;
- }
- else
+ // *FIXME.
+ // This condition should really be notified to the user, e.g.
+ // through a message box. Just logging it is inappropriate.
+
+ // g_filename_display_name is ideal, but >= glib 2.6, so:
+ // a hand-rolled hacky makeASCII which disallows control chars
+ std::string display_name;
+ for (const gchar *str = (const gchar *)data; *str; str++)
{
- mLocked = FALSE;
+ display_name += (char)((*str >= 0x20 && *str <= 0x7E) ? *str : '?');
}
+ llwarns << "g_filename_to_utf8 failed on \"" << display_name << "\": " << error->message << llendl;
}
- return NULL;
-}
-const char* LLFilePicker::getDirname()
-{
- if (mFileIndex < mFileVector.size())
+ if (filename_utf8)
{
- getFileName(mFileIndex);
- return mFilename;
+ picker->mFiles.push_back(std::string(filename_utf8));
+ lldebugs << "ADDED FILE " << filename_utf8 << llendl;
+ g_free(filename_utf8);
}
- return NULL;
-}
-
-void LLFilePicker::reset()
-{
- mLocked = FALSE;
- memset( mFiles, 0, FILENAME_BUFFER_SIZE );
- memset( mFilename, 0, LL_MAX_PATH );
- mCurrentFile = mFiles;
-
- mFileIndex = 0;
- mFileVector.clear();
-}
-
-#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();
-}
-LLFilePicker::~LLFilePicker()
-{
+ setlocale(LC_ALL, saved_locale.c_str());
}
-
-static void add_to_sfs(gpointer data, gpointer user_data)
+// static
+void LLFilePicker::chooser_responder(GtkWidget *widget, gint response, gpointer user_data)
{
- StoreFilenamesStruct *sfs = (StoreFilenamesStruct*) user_data;
- gchar* filename_utf8 = g_filename_to_utf8((gchar*)data,
- -1, NULL,
- NULL,
- NULL);
- sfs->fileVector.push_back(LLString(filename_utf8));
- g_free(filename_utf8);
-}
-
-
-void chooser_responder(GtkWidget *widget,
- gint response,
- gpointer user_data) {
- StoreFilenamesStruct *sfs = (StoreFilenamesStruct*) user_data;
+ LLFilePicker* picker = (LLFilePicker*)user_data;
lldebugs << "GTK DIALOG RESPONSE " << response << llendl;
if (response == GTK_RESPONSE_ACCEPT)
{
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)add_to_selectedfiles, user_data);
g_slist_foreach(file_list, (GFunc)g_free, NULL);
g_slist_free (file_list);
}
// set the default path for this usage context.
- LLFilePicker::sContextToPathMap[sfs->contextName] =
+ picker->mContextToPathMap[picker->mCurContextName] =
gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget));
gtk_widget_destroy(widget);
@@ -1010,11 +962,9 @@ void chooser_responder(GtkWidget *widget,
}
-GtkWindow* LLFilePicker::buildFilePicker(bool is_save, bool is_folder,
- std::string context)
+GtkWindow* LLFilePicker::buildFilePicker(bool is_save, bool is_folder, std::string context)
{
- if (ll_try_gtk_init() &&
- ! gViewerWindow->getWindow()->getFullscreen())
+ if (LLWindowSDL::ll_try_gtk_init())
{
GtkWidget *win = NULL;
GtkFileChooserAction pickertype =
@@ -1037,14 +987,13 @@ GtkWindow* LLFilePicker::buildFilePicker(bool is_save, bool is_folder,
GTK_STOCK_OPEN),
GTK_RESPONSE_ACCEPT,
(gchar *)NULL);
- mStoreFilenames.win = win;
- mStoreFilenames.contextName = context;
+ mCurContextName = 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())
+ this_path = mContextToPathMap.find(context);
+ if (this_path != mContextToPathMap.end())
{
gtk_file_chooser_set_current_folder
(GTK_FILE_CHOOSER(win),
@@ -1055,7 +1004,7 @@ GtkWindow* LLFilePicker::buildFilePicker(bool is_save, bool is_folder,
// Make GTK tell the window manager to associate this
// dialog with our non-GTK raw X11 window, which should try
// to keep it on top etc.
- Window XWindowID = get_SDL_XWindowID();
+ Window XWindowID = LLWindowSDL::get_SDL_XWindowID();
if (None != XWindowID)
{
gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin
@@ -1071,8 +1020,8 @@ GtkWindow* LLFilePicker::buildFilePicker(bool is_save, bool is_folder,
g_signal_connect (GTK_FILE_CHOOSER(win),
"response",
- G_CALLBACK(chooser_responder),
- &mStoreFilenames);
+ G_CALLBACK(LLFilePicker::chooser_responder),
+ this);
gtk_window_set_modal(GTK_WINDOW(win), TRUE);
@@ -1097,7 +1046,7 @@ static void add_common_filters_to_gtkchooser(GtkFileFilter *gfilter,
gfilter);
GtkFileFilter *allfilter = gtk_file_filter_new();
gtk_file_filter_add_pattern(allfilter, "*");
- gtk_file_filter_set_name(allfilter, "All Files");
+ gtk_file_filter_set_name(allfilter, LLTrans::getString("all_files").c_str());
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), allfilter);
gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(picker), gfilter);
}
@@ -1125,13 +1074,13 @@ static std::string add_simple_mime_filter_to_gtkchooser(GtkWindow *picker,
static std::string add_wav_filter_to_gtkchooser(GtkWindow *picker)
{
return add_simple_mime_filter_to_gtkchooser(picker, "audio/x-wav",
- "Sounds (*.wav)");
+ LLTrans::getString("sound_files") + " (*.wav)");
}
static std::string add_bvh_filter_to_gtkchooser(GtkWindow *picker)
{
return add_simple_pattern_filter_to_gtkchooser(picker, "*.bvh",
- "Animations (*.bvh)");
+ LLTrans::getString("animation_files") + " (*.bvh)");
}
static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker)
@@ -1141,26 +1090,27 @@ static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker)
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)";
+ std::string filtername = LLTrans::getString("image_files") + " (*.tga; *.bmp; *.jpg; *.png)";
add_common_filters_to_gtkchooser(gfilter, picker, filtername);
return filtername;
}
-BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const char* filename )
+BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename )
{
BOOL rtn = FALSE;
gViewerWindow->mWindow->beforeDialog();
reset();
+
GtkWindow* picker = buildFilePicker(true, false, "savefile");
if (picker)
{
std::string suggest_name = "untitled";
std::string suggest_ext = "";
- std::string caption = "Save ";
+ std::string caption = LLTrans::getString("save_file_verb") + " ";
switch (filter)
{
case FFSAVE_WAV:
@@ -1169,39 +1119,39 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const char* filename )
break;
case FFSAVE_TGA:
caption += add_simple_pattern_filter_to_gtkchooser
- (picker, "*.tga", "Targa Images (*.tga)");
+ (picker, "*.tga", LLTrans::getString("targa_image_files") + " (*.tga)");
suggest_ext = ".tga";
break;
case FFSAVE_BMP:
caption += add_simple_mime_filter_to_gtkchooser
- (picker, "image/bmp", "Bitmap Images (*.bmp)");
+ (picker, "image/bmp", LLTrans::getString("bitmap_image_files") + " (*.bmp)");
suggest_ext = ".bmp";
break;
case FFSAVE_AVI:
caption += add_simple_mime_filter_to_gtkchooser
(picker, "video/x-msvideo",
- "AVI Movie File (*.avi)");
+ LLTrans::getString("avi_movie_file") + " (*.avi)");
suggest_ext = ".avi";
break;
case FFSAVE_ANIM:
caption += add_simple_pattern_filter_to_gtkchooser
- (picker, "*.xaf", "XAF Anim File (*.xaf)");
+ (picker, "*.xaf", LLTrans::getString("xaf_animation_file") + " (*.xaf)");
suggest_ext = ".xaf";
break;
case FFSAVE_XML:
caption += add_simple_pattern_filter_to_gtkchooser
- (picker, "*.xml", "XML File (*.xml)");
+ (picker, "*.xml", LLTrans::getString("xml_file") + " (*.xml)");
suggest_ext = ".xml";
break;
case FFSAVE_RAW:
caption += add_simple_pattern_filter_to_gtkchooser
- (picker, "*.raw", "RAW File (*.raw)");
+ (picker, "*.raw", LLTrans::getString("raw_file") + " (*.raw)");
suggest_ext = ".raw";
break;
case FFSAVE_J2C:
caption += add_simple_mime_filter_to_gtkchooser
(picker, "images/jp2",
- "Compressed Images (*.j2c)");
+ LLTrans::getString("compressed_image_files") + " (*.j2c)");
suggest_ext = ".j2c";
break;
default:;
@@ -1210,7 +1160,7 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const char* filename )
gtk_window_set_title(GTK_WINDOW(picker), caption.c_str());
- if (!filename)
+ if (filename.empty())
{
suggest_name += suggest_ext;
@@ -1221,13 +1171,13 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const char* filename )
else
{
gtk_file_chooser_set_current_name
- (GTK_FILE_CHOOSER(picker), filename);
+ (GTK_FILE_CHOOSER(picker), filename.c_str());
}
gtk_widget_show_all(GTK_WIDGET(picker));
gtk_main();
- rtn = (mStoreFilenames.fileVector.size() == 1);
+ rtn = (getFileCount() == 1);
}
gViewerWindow->mWindow->afterDialog();
@@ -1242,11 +1192,12 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter )
gViewerWindow->mWindow->beforeDialog();
reset();
+
GtkWindow* picker = buildFilePicker(false, false, "openfile");
if (picker)
{
- std::string caption = "Load ";
+ std::string caption = LLTrans::getString("load_file_verb") + " ";
std::string filtername = "";
switch (filter)
{
@@ -1270,7 +1221,7 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter )
gtk_widget_show_all(GTK_WIDGET(picker));
gtk_main();
- rtn = (mStoreFilenames.fileVector.size() == 1);
+ rtn = (getFileCount() == 1);
}
gViewerWindow->mWindow->afterDialog();
@@ -1285,6 +1236,7 @@ BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter )
gViewerWindow->mWindow->beforeDialog();
reset();
+
GtkWindow* picker = buildFilePicker(false, false, "openfile");
if (picker)
@@ -1292,11 +1244,11 @@ BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter )
gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(picker),
TRUE);
- gtk_window_set_title(GTK_WINDOW(picker), "Load Files");
+ gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("load_files").c_str());
gtk_widget_show_all(GTK_WIDGET(picker));
gtk_main();
- rtn = !mStoreFilenames.fileVector.empty();
+ rtn = !mFiles.empty();
}
gViewerWindow->mWindow->afterDialog();
@@ -1304,179 +1256,69 @@ BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter )
return rtn;
}
-const char* LLFilePicker::getFirstFile()
-{
- mNextFileIndex = 0;
- return getNextFile();
-}
-
-const char* LLFilePicker::getNextFile()
-{
- if (mStoreFilenames.fileVector.size() > mNextFileIndex)
- return mStoreFilenames.fileVector[mNextFileIndex++].c_str();
- else
- return NULL;
-}
-
-const char* LLFilePicker::getDirname()
-{
- // getDirname is badly named... it really means getBasename.
- S32 index = mNextFileIndex - 1; // want index before the 'next' cursor
- if (index >= 0 && index < (S32)mStoreFilenames.fileVector.size())
- {
- // we do this using C strings so we don't have to
- // convert a LLString/std::string character offset into a
- // byte-offset for the return (which is a C string anyway).
- const char* dirsep = gDirUtilp->getDirDelimiter().c_str();
- const char* fullpath = mStoreFilenames.fileVector[index].c_str();
- const char* finalpart = NULL;
- const char* thispart = fullpath;
- // (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);
- if (NULL != thispart)
- finalpart = thispart = &thispart[1];
- }
- while (NULL != thispart);
- return finalpart;
- }
- else
- return NULL;
-}
-
-void LLFilePicker::reset()
-{
- llinfos << "GTK LLFilePicker::reset()" << llendl;
- mNextFileIndex = 0;
- mStoreFilenames.win = NULL;
- mStoreFilenames.fileVector.clear();
-}
-
# else // LL_GTK
// Hacky stubs designed to facilitate fake getSaveFile and getOpenFile with
// static results, when we don't have a real filepicker.
-static LLString hackyfilename;
-
-LLFilePicker::LLFilePicker()
+BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename )
{
reset();
-}
-
-LLFilePicker::~LLFilePicker()
-{
-}
-
-BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const char* filename )
-{
+
llinfos << "getSaveFile suggested filename is [" << filename
<< "]" << llendl;
- if (filename && filename[0])
+ if (!filename.empty())
{
- hackyfilename.assign(gDirUtilp->getLindenUserDir());
- hackyfilename += gDirUtilp->getDirDelimiter();
- hackyfilename += filename;
+ mFiles.push_back(gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + filename);
return TRUE;
}
- hackyfilename.clear();
return FALSE;
}
BOOL LLFilePicker::getOpenFile( ELoadFilter filter )
{
+ reset();
+
// HACK: Static filenames for 'open' until we implement filepicker
- hackyfilename.assign(gDirUtilp->getLindenUserDir());
- hackyfilename += gDirUtilp->getDirDelimiter();
- hackyfilename += "upload";
+ std::string filename = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + "upload";
switch (filter)
{
- case FFLOAD_WAV: hackyfilename += ".wav"; break;
- case FFLOAD_IMAGE: hackyfilename += ".tga"; break;
- case FFLOAD_ANIM: hackyfilename += ".bvh"; break;
+ case FFLOAD_WAV: filename += ".wav"; break;
+ case FFLOAD_IMAGE: filename += ".tga"; break;
+ case FFLOAD_ANIM: filename += ".bvh"; break;
default: break;
}
- llinfos << "getOpenFile: Will try to open file: " << hackyfilename
- << llendl;
+ mFiles.push_back(filename);
+ llinfos << "getOpenFile: Will try to open file: " << hackyfilename << llendl;
return TRUE;
}
BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter )
{
- hackyfilename.clear();
+ reset();
return FALSE;
}
-const char* LLFilePicker::getFirstFile()
-{
- if (!hackyfilename.empty())
- {
- return hackyfilename.c_str();
- }
- return NULL;
-}
-
-const char* LLFilePicker::getNextFile()
-{
- hackyfilename.clear();
- return NULL;
-}
-
-const char* LLFilePicker::getDirname()
-{
- return NULL;
-}
-
-void LLFilePicker::reset()
-{
-}
#endif // LL_GTK
#else // not implemented
-LLFilePicker::LLFilePicker()
-{
- reset();
-}
-
-LLFilePicker::~LLFilePicker()
-{
-}
-
-BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const char* filename )
+BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename )
{
+ reset();
return FALSE;
}
BOOL LLFilePicker::getOpenFile( ELoadFilter filter )
{
+ reset();
return FALSE;
}
BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter )
{
+ reset();
return FALSE;
}
-const char* LLFilePicker::getFirstFile()
-{
- return NULL;
-}
-
-const char* LLFilePicker::getNextFile()
-{
- return NULL;
-}
-
-const char* LLFilePicker::getDirname()
-{
- return NULL;
-}
-
-void LLFilePicker::reset()
-{
-}
-
#endif