Files
SingularityViewer/indra/plugins/filepicker/llfilepicker.cpp
Router Gray 34a7ebf53f [Linux] Port some bits from Alchemy & future to stop using dark-ages deprecated GDK/GTK.
Todo: Revisit this and clean up some code duplication I stumbled over in the process. (legacy.cpp llwindowsdl.cpp)
2020-05-19 21:48:57 -05:00

1739 lines
44 KiB
C++

/**
* @file llfilepicker.cpp
* @brief OS-specific file picker
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* 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://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* 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://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* 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.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llfilepicker.h"
#include "llerror.h"
#include "basic_plugin_base.h" // For PLS_INFOS etc.
#if LL_SDL
#if LL_GTK
extern "C" {
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#if GTK_CHECK_VERSION(2, 24, 0)
#include <gdk/gdkx.h>
#endif
}
#include <clocale>
#endif // LL_GTK
#endif // LL_SDL
//
// Globals
//
LLFilePicker LLFilePicker::sInstance;
#if LL_WINDOWS
// <edit>
#define SOUND_FILTER L"Sounds (*.wav; *.ogg)\0*.wav;*.ogg\0"
#define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png; *.jp2; *.j2k; *.j2c)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png;*.jp2;*.j2k;*.j2c\0"
#define INVGZ_FILTER L"Inv cache (*.inv; *.inv.gz)\0*.inv;*.inv.gz\0"
#define AO_FILTER L"Animation Override (*.ao)\0*.ao\0"
#define BLACKLIST_FILTER L"Asset Blacklist (*.blacklist)\0*.blacklist\0"
// </edit>
#define ANIM_FILTER L"Animations (*.bvh; *.anim)\0*.bvh;*.anim\0"
#define COLLADA_FILTER L"Scene (*.dae)\0*.dae\0"
#ifdef _CORY_TESTING
#define GEOMETRY_FILTER L"SL Geometry (*.slg)\0*.slg\0"
#endif
#define XML_FILTER L"XML files (*.xml)\0*.xml\0"
#define SLOBJECT_FILTER L"Objects (*.slobject)\0*.slobject\0"
#define RAW_FILTER L"RAW files (*.raw)\0*.raw\0"
#define MODEL_FILTER L"Model files (*.dae)\0*.dae\0"
#define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0"
#define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0"
#endif
//
// Implementation
//
LLFilePickerBase::LLFilePickerBase()
: mCurrentFile(0),
mLocked(FALSE)
{
reset();
#if LL_WINDOWS
mOFN.lStructSize = sizeof(OPENFILENAMEW);
mOFN.hwndOwner = NULL; // Set later with setWindowID
mOFN.hInstance = NULL;
mOFN.lpstrCustomFilter = NULL;
mOFN.nMaxCustFilter = 0;
mOFN.lpstrFile = NULL; // set in open and close
mOFN.nMaxFile = LL_MAX_PATH;
mOFN.lpstrFileTitle = NULL;
mOFN.nMaxFileTitle = 0;
mOFN.lpstrInitialDir = NULL;
mOFN.lpstrTitle = NULL;
mOFN.Flags = 0; // set in open and close
mOFN.nFileOffset = 0;
mOFN.nFileExtension = 0;
mOFN.lpstrDefExt = NULL;
mOFN.lCustData = 0L;
mOFN.lpfnHook = NULL;
mOFN.lpTemplateName = NULL;
#endif
#if LL_DARWIN
memset(&mNavOptions, 0, sizeof(mNavOptions));
OSStatus error = NavGetDefaultDialogCreationOptions(&mNavOptions);
if (error == noErr)
{
mNavOptions.modality = kWindowModalityAppModal;
}
#endif
}
const std::string LLFilePickerBase::getFirstFile()
{
mCurrentFile = 0;
return getNextFile();
}
const std::string LLFilePickerBase::getNextFile()
{
if (mCurrentFile >= getFileCount())
{
mLocked = FALSE;
return std::string();
}
else
{
return mFiles[mCurrentFile++];
}
}
const std::string LLFilePickerBase::getCurFile()
{
if (mCurrentFile >= getFileCount())
{
mLocked = FALSE;
return std::string();
}
else
{
return mFiles[mCurrentFile];
}
}
void LLFilePickerBase::reset()
{
mLocked = FALSE;
mFiles.clear();
mCurrentFile = 0;
}
#if LL_WINDOWS
bool LLFilePickerBase::setupFilter(ELoadFilter filter)
{
bool res = TRUE;
switch (filter)
{
case FFLOAD_ALL:
mOFN.lpstrFilter = L"All Files (*.*)\0*.*\0" \
SOUND_FILTER \
IMAGE_FILTER \
ANIM_FILTER \
L"\0";
break;
case FFLOAD_WAV:
mOFN.lpstrFilter = SOUND_FILTER \
L"\0";
break;
case FFLOAD_IMAGE:
mOFN.lpstrFilter = IMAGE_FILTER \
L"\0";
break;
case FFLOAD_ANIM:
mOFN.lpstrFilter = ANIM_FILTER \
L"\0";
break;
case FFLOAD_COLLADA:
mOFN.lpstrFilter = COLLADA_FILTER \
L"\0";
break;
#ifdef _CORY_TESTING
case FFLOAD_GEOMETRY:
mOFN.lpstrFilter = GEOMETRY_FILTER \
L"\0";
break;
#endif
case FFLOAD_XML:
mOFN.lpstrFilter = XML_FILTER \
L"\0";
break;
case FFLOAD_SLOBJECT:
mOFN.lpstrFilter = SLOBJECT_FILTER \
L"\0";
break;
case FFLOAD_RAW:
mOFN.lpstrFilter = RAW_FILTER \
L"\0";
break;
case FFLOAD_MODEL:
mOFN.lpstrFilter = MODEL_FILTER \
L"\0";
break;
case FFLOAD_SCRIPT:
mOFN.lpstrFilter = SCRIPT_FILTER \
L"\0";
break;
case FFLOAD_DICTIONARY:
mOFN.lpstrFilter = DICTIONARY_FILTER \
L"\0";
break;
// <edit>
case FFLOAD_INVGZ:
mOFN.lpstrFilter = INVGZ_FILTER \
L"\0";
break;
case FFLOAD_AO:
mOFN.lpstrFilter = AO_FILTER \
L"\0";
break;
case FFLOAD_BLACKLIST:
mOFN.lpstrFilter = BLACKLIST_FILTER \
L"\0";
break;
// </edit>
default:
res = FALSE;
break;
}
return res;
}
bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder)
{
if( mLocked )
{
return FALSE;
}
bool success = FALSE;
llutf16string tstring = utf8str_to_utf16str(folder);
mOFN.lpstrInitialDir = (LPCTSTR)tstring.data();
mFilesW[0] = '\0';
mOFN.lpstrFile = mFilesW;
mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE;
mOFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR ;
mOFN.nFilterIndex = 1;
setupFilter(filter);
reset();
// NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
success = GetOpenFileName(&mOFN);
if (success)
{
std::string filename = utf16str_to_utf8str(llutf16string(mFilesW));
mFiles.push_back(filename);
}
return success;
}
bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string const& folder)
{
if( mLocked )
{
return FALSE;
}
bool success = FALSE;
llutf16string tstring = utf8str_to_utf16str(folder);
mOFN.lpstrInitialDir = (LPCTSTR)tstring.data();
mFilesW[0] = '\0';
mOFN.lpstrFile = mFilesW;
mOFN.nFilterIndex = 1;
mOFN.nMaxFile = FILENAME_BUFFER_SIZE;
mOFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR |
OFN_EXPLORER | OFN_ALLOWMULTISELECT;
setupFilter(filter);
reset();
// NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
success = GetOpenFileName(&mOFN); // pauses until ok or cancel.
if( success )
{
// The getopenfilename api doesn't tell us if we got more than
// one file, so we have to test manually by checking string
// lengths.
if( wcslen(mOFN.lpstrFile) > mOFN.nFileOffset ) /*Flawfinder: ignore*/
{
std::string filename = utf16str_to_utf8str(llutf16string(mFilesW));
mFiles.push_back(filename);
}
else
{
mLocked = TRUE;
WCHAR* tptrw = mFilesW;
std::string dirname;
while(1)
{
if (*tptrw == 0 && *(tptrw+1) == 0) // double '\0'
break;
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();
}
}
}
return success;
}
bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filename, std::string const& folder)
{
if( mLocked )
{
return FALSE;
}
bool success = FALSE;
llutf16string tstring = utf8str_to_utf16str(folder);
mOFN.lpstrInitialDir = (LPCTSTR)tstring.data();
mOFN.lpstrFile = mFilesW;
if (!filename.empty())
{
llutf16string tstring = utf8str_to_utf16str(filename);
wcsncpy(mFilesW, tstring.data(), FILENAME_BUFFER_SIZE); } /*Flawfinder: ignore*/
else
{
mFilesW[0] = '\0';
}
switch( filter )
{
case FFSAVE_ALL:
mOFN.lpstrDefExt = NULL;
mOFN.lpstrFilter =
L"All Files (*.*)\0*.*\0" \
L"WAV Sounds (*.wav)\0*.wav\0" \
L"Targa, Bitmap Images (*.tga; *.bmp)\0*.tga;*.bmp\0" \
L"\0";
break;
case FFSAVE_WAV:
if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.wav", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
mOFN.lpstrDefExt = L"wav";
mOFN.lpstrFilter =
L"WAV Sounds (*.wav)\0*.wav\0" \
L"\0";
break;
case FFSAVE_TGA:
if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.tga", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
mOFN.lpstrDefExt = L"tga";
mOFN.lpstrFilter =
L"Targa Images (*.tga)\0*.tga\0" \
L"\0";
break;
case FFSAVE_BMP:
if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.bmp", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
mOFN.lpstrDefExt = L"bmp";
mOFN.lpstrFilter =
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.jpg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
mOFN.lpstrDefExt = L"jpg";
mOFN.lpstrFilter =
L"JPEG Images (*.jpg *.jpeg)\0*.jpg;*.jpeg\0" \
L"\0";
break;
case FFSAVE_AVI:
if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.avi", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
mOFN.lpstrDefExt = L"avi";
mOFN.lpstrFilter =
L"AVI Movie File (*.avi)\0*.avi\0" \
L"\0";
break;
case FFSAVE_ANIM:
if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.xaf", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
mOFN.lpstrDefExt = L"xaf";
mOFN.lpstrFilter =
L"XAF Anim File (*.xaf)\0*.xaf\0" \
L"\0";
break;
#ifdef _CORY_TESTING
case FFSAVE_GEOMETRY:
if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.slg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
mOFN.lpstrDefExt = L"slg";
mOFN.lpstrFilter =
L"SLG SL Geometry File (*.slg)\0*.slg\0" \
L"\0";
break;
#endif
case FFSAVE_XML:
if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.xml", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
mOFN.lpstrDefExt = L"xml";
mOFN.lpstrFilter =
L"XML File (*.xml)\0*.xml\0" \
L"\0";
break;
case FFSAVE_COLLADA:
if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.collada", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
mOFN.lpstrDefExt = L"collada";
mOFN.lpstrFilter =
L"COLLADA File (*.collada)\0*.collada\0" \
L"\0";
break;
case FFSAVE_RAW:
if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.raw", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
mOFN.lpstrDefExt = L"raw";
mOFN.lpstrFilter = RAW_FILTER \
L"\0";
break;
case FFSAVE_J2C:
if (filename.empty())
{
wcsncpy( mFilesW,L"untitled.j2c", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"j2c";
mOFN.lpstrFilter =
L"Compressed Images (*.j2c)\0*.j2c\0" \
L"\0";
break;
// <edit>
case FFSAVE_ANIMATN:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.animatn", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"animatn";
mOFN.lpstrFilter =
L"SL Animations (*.animatn)\0*.animatn\0" \
L"\0";
break;
case FFSAVE_OGG:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.ogg", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"ogg";
mOFN.lpstrFilter =
L"Ogg (*.ogg)\0*.ogg\0" \
L"\0";
break;
case FFSAVE_NOTECARD:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.notecard", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"notecard";
mOFN.lpstrFilter =
L"Notecards (*.notecard)\0*.notecard\0" \
L"\0";
break;
case FFSAVE_GESTURE:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.gesture", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"gesture";
mOFN.lpstrFilter =
L"Gestures (*.gesture)\0*.gesture\0" \
L"\0";
break;
case FFSAVE_SCRIPT:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.lsl", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"lsl";
mOFN.lpstrFilter = L"LSL Files (*.lsl)\0*.lsl\0" L"\0";
break;
case FFSAVE_SHAPE:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.shape", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"shape";
mOFN.lpstrFilter =
L"Shapes (*.shape)\0*.shape\0" \
L"\0";
break;
case FFSAVE_SKIN:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.skin", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"skin";
mOFN.lpstrFilter =
L"Skins (*.skin)\0*.skin\0" \
L"\0";
break;
case FFSAVE_HAIR:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.hair", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"hair";
mOFN.lpstrFilter =
L"Hair (*.hair)\0*.hair\0" \
L"\0";
break;
case FFSAVE_EYES:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.eyes", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"eyes";
mOFN.lpstrFilter =
L"Eyes (*.eyes)\0*.eyes\0" \
L"\0";
break;
case FFSAVE_SHIRT:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.shirt", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"shirt";
mOFN.lpstrFilter =
L"Shirts (*.shirt)\0*.shirt\0" \
L"\0";
break;
case FFSAVE_PANTS:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.pants", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"pants";
mOFN.lpstrFilter =
L"Pants (*.pants)\0*.pants\0" \
L"\0";
break;
case FFSAVE_SHOES:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.shoes", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"shoes";
mOFN.lpstrFilter =
L"Shoes (*.shoes)\0*.shoes\0" \
L"\0";
break;
case FFSAVE_SOCKS:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.socks", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"socks";
mOFN.lpstrFilter =
L"Socks (*.socks)\0*.socks\0" \
L"\0";
break;
case FFSAVE_JACKET:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.jacket", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"jacket";
mOFN.lpstrFilter =
L"Jackets (*.jacket)\0*.jacket\0" \
L"\0";
break;
case FFSAVE_GLOVES:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.gloves", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"gloves";
mOFN.lpstrFilter =
L"Gloves (*.gloves)\0*.gloves\0" \
L"\0";
break;
case FFSAVE_UNDERSHIRT:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.undershirt", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"undershirt";
mOFN.lpstrFilter =
L"Undershirts (*.undershirt)\0*.undershirt\0" \
L"\0";
break;
case FFSAVE_UNDERPANTS:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.underpants", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"underpants";
mOFN.lpstrFilter =
L"Underpants (*.underpants)\0*.underpants\0" \
L"\0";
break;
case FFSAVE_SKIRT:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.skirt", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"skirt";
mOFN.lpstrFilter =
L"Skirts (*.skirt)\0*.skirt\0" \
L"\0";
break;
case FFSAVE_LANDMARK:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.landmark", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"landmark";
mOFN.lpstrFilter =
L"Landmarks (*.landmark)\0*.landmark\0" \
L"\0";
break;
case FFSAVE_AO:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.ao", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"ao";
mOFN.lpstrFilter =
L"Animation overrides (*.ao)\0*.ao\0" \
L"\0";
break;
case FFSAVE_INVGZ:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.inv", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L".inv";
mOFN.lpstrFilter =
L"InvCache (*.inv)\0*.inv\0" \
L"\0";
break;
case FFSAVE_BLACKLIST:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.blacklist", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L".blacklist";
mOFN.lpstrFilter =
L"Asset Blacklists (*.blacklist)\0*.blacklist\0" \
L"\0";
break;
case FFSAVE_PHYSICS:
if(filename.empty())
{
wcsncpy( mFilesW,L"untitled.phy", FILENAME_BUFFER_SIZE);
}
mOFN.lpstrDefExt = L"phy";
mOFN.lpstrFilter =
L"Landmarks (*.phy)\0*.phy\0" \
L"\0";
break;
case FFSAVE_IMAGE:
mOFN.lpstrDefExt = NULL;
mOFN.lpstrFilter =
L"Image (*.bmp *.dxt *.jpg *.jpeg *.j2c *.mip *.png *.tga)\0*.bmp;*.dxt;*.jpg;*.jpeg;*.j2c;*.mip;*.png;*.tga\0" \
L"PNG Image (*.png)\0*.png\0" \
L"Targa Image (*.tga)\0*.tga\0" \
L"Bitmap Image (*.bmp)\0*.bmp\0" \
L"JPEG Image (*.jpg *.jpeg)\0*.jpg;*.jpeg\0" \
L"Compressed Image (*.j2c)\0*.j2c\0" \
L"DXT Image (*.dxt *.mip)\0*.dxt;*.mip\0" \
L"\0";
break;
// </edit>
default:
return FALSE;
}
mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE;
mOFN.Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
reset();
{
// NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!!
success = GetSaveFileName(&mOFN);
if (success)
{
std::string filename = utf16str_to_utf8str(llutf16string(mFilesW));
mFiles.push_back(filename);
}
}
return success;
}
#elif LL_DARWIN
Boolean LLFilePickerBase::navOpenFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode)
{
LLFilePickerBase* picker = (LLFilePickerBase*)callBackUD;
Boolean result = true;
ELoadFilter filter = picker->getLoadFilter();
OSStatus error = noErr;
if (filterMode == kNavFilteringBrowserList && filter != FFLOAD_ALL && (theItem->descriptorType == typeFSRef || theItem->descriptorType == typeFSS))
{
// navInfo is only valid for typeFSRef and typeFSS
NavFileOrFolderInfo *navInfo = (NavFileOrFolderInfo*) info;
if (!navInfo->isFolder)
{
AEDesc desc;
error = AECoerceDesc(theItem, typeFSRef, &desc);
if (error == noErr)
{
FSRef fileRef;
error = AEGetDescData(&desc, &fileRef, sizeof(fileRef));
if (error == noErr)
{
LSItemInfoRecord fileInfo;
error = LSCopyItemInfoForRef(&fileRef, kLSRequestExtension | kLSRequestTypeCreator, &fileInfo);
if (error == noErr)
{
if (filter == FFLOAD_IMAGE)
{
if (fileInfo.filetype != 'JPEG' && fileInfo.filetype != 'JPG ' &&
fileInfo.filetype != 'BMP ' && fileInfo.filetype != 'TGA ' &&
fileInfo.filetype != 'BMPf' && fileInfo.filetype != 'TPIC' &&
fileInfo.filetype != 'PNG ' && fileInfo.filetype != 'JP2 ' &&
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("jpeg"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
CFStringCompare(fileInfo.extension, CFSTR("jpg"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
CFStringCompare(fileInfo.extension, CFSTR("bmp"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
CFStringCompare(fileInfo.extension, CFSTR("tga"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
CFStringCompare(fileInfo.extension, CFSTR("png"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
CFStringCompare(fileInfo.extension, CFSTR("jp2"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
CFStringCompare(fileInfo.extension, CFSTR("j2k"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
CFStringCompare(fileInfo.extension, CFSTR("j2c"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
)
{
result = false;
}
}
else if (filter == FFLOAD_WAV)
{
if (fileInfo.filetype != 'WAVE' && fileInfo.filetype != 'WAV ' &&
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("wave"), kCFCompareCaseInsensitive) != kCFCompareEqualTo &&
CFStringCompare(fileInfo.extension, CFSTR("wav"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
)
{
result = false;
}
}
else if (filter == FFLOAD_ANIM)
{
if (fileInfo.filetype != 'BVH ' && fileInfo.filetype != 'ANIM' &&
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("bvh"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) &&
CFStringCompare(fileInfo.extension, CFSTR("anim"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
{
result = false;
}
}
else if (filter == FFLOAD_COLLADA)
{
if (fileInfo.filetype != 'DAE ' &&
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("dae"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
)
{
result = false;
}
}
else if (filter == FFLOAD_XML)
{
if (fileInfo.filetype != 'XML ' &&
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("xml"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
)
{
result = false;
}
}
#ifdef _CORY_TESTING
else if (filter == FFLOAD_GEOMETRY)
{
if (fileInfo.filetype != 'SLG ' &&
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("slg"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
)
{
result = false;
}
}
#endif
else if (filter == FFLOAD_SLOBJECT)
{
PLS_WARNS << "*** navOpenFilterProc: FFLOAD_SLOBJECT NOT IMPLEMENTED ***" << PLS_ENDL;
}
else if (filter == FFLOAD_RAW)
{
if (fileInfo.filetype != '\?\?\?\?' &&
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("raw"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
)
{
result = false;
}
}
else if (filter == FFLOAD_SCRIPT)
{
if (fileInfo.filetype != 'LSL ' &&
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("lsl"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) )
{
result = false;
}
}
else if (filter == FFLOAD_DICTIONARY)
{
if (fileInfo.filetype != 'DIC ' &&
fileInfo.filetype != 'XCU ' &&
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("dic"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) &&
fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("xcu"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)))
{
result = false;
}
}
if (fileInfo.extension)
{
CFRelease(fileInfo.extension);
}
}
}
AEDisposeDesc(&desc);
}
}
}
return result;
}
//static
pascal void LLFilePickerBase::doNavCallbackEvent(NavEventCallbackMessage callBackSelector,
NavCBRecPtr callBackParms, void* callBackUD)
{
switch(callBackSelector)
{
case kNavCBStart:
{
LLFilePickerBase* picker = reinterpret_cast<LLFilePickerBase*>(callBackUD);
if (picker->getFolder().empty()) break;
OSStatus error = noErr;
AEDesc theLocation = {typeNull, NULL};
FSSpec outFSSpec;
//Convert string to a FSSpec
FSRef myFSRef;
const char* folder = picker->getFolder().c_str();
error = FSPathMakeRef ((UInt8*)folder, &myFSRef, NULL);
if (error != noErr) break;
error = FSGetCatalogInfo (&myFSRef, kFSCatInfoNone, NULL, NULL, &outFSSpec, NULL);
if (error != noErr) break;
error = AECreateDesc(typeFSS, &outFSSpec, sizeof(FSSpec), &theLocation);
if (error != noErr) break;
error = NavCustomControl(callBackParms->context,
kNavCtlSetLocation, (void*)&theLocation);
}
}
}
OSStatus LLFilePickerBase::doNavChooseDialog(ELoadFilter filter, std::string const& folder)
{
OSStatus error = noErr;
NavDialogRef navRef = NULL;
NavReplyRecord navReply;
memset(&navReply, 0, sizeof(navReply));
mLoadFilter = filter;
mFolder = folder;
NavEventUPP eventProc = NewNavEventUPP(doNavCallbackEvent);
// 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.
// (It is destroyed by NavDialogDispose() below.)
error = NavCreateChooseFileDialog(&mNavOptions, NULL, eventProc, NULL, navOpenFilterProc, (void*)this, &navRef);
//gViewerWindow->getWindow()->beforeDialog();
if (error == noErr)
{
PLS_FLUSH;
error = NavDialogRun(navRef);
}
//gViewerWindow->getWindow()->afterDialog();
if (error == noErr)
error = NavDialogGetReply(navRef, &navReply);
if (navRef)
NavDialogDispose(navRef);
if (error == noErr && navReply.validRecord)
{
SInt32 count = 0;
SInt32 index;
// AE indexes are 1 based...
error = AECountItems(&navReply.selection, &count);
for (index = 1; index <= count; index++)
{
FSRef fsRef;
AEKeyword theAEKeyword;
DescType typeCode;
Size actualSize = 0;
char path[MAX_PATH]; /*Flawfinder: ignore*/
memset(&fsRef, 0, sizeof(fsRef));
error = AEGetNthPtr(&navReply.selection, index, typeFSRef, &theAEKeyword, &typeCode, &fsRef, sizeof(fsRef), &actualSize);
if (error == noErr)
error = FSRefMakePath(&fsRef, (UInt8*) path, sizeof(path));
if (error == noErr)
mFiles.push_back(std::string(path));
}
}
if (eventProc)
DisposeNavEventUPP(eventProc);
return error;
}
OSStatus LLFilePickerBase::doNavSaveDialog(ESaveFilter filter, std::string const& filename, std::string const& folder)
{
OSStatus error = noErr;
NavDialogRef navRef = NULL;
NavReplyRecord navReply;
memset(&navReply, 0, sizeof(navReply));
// Setup the type, creator, and extension
OSType type, creator;
CFStringRef extension = NULL;
switch (filter)
{
case FFSAVE_WAV:
type = 'WAVE';
creator = 'TVOD';
extension = CFSTR(".wav");
break;
case FFSAVE_TGA:
type = 'TPIC';
creator = 'prvw';
extension = CFSTR(".tga");
break;
case FFSAVE_BMP:
type = 'BMPf';
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 = '\?\?\?\?';
extension = CFSTR(".mov");
break;
case FFSAVE_ANIM:
type = '\?\?\?\?';
creator = '\?\?\?\?';
extension = CFSTR(".xaf");
break;
#ifdef _CORY_TESTING
case FFSAVE_GEOMETRY:
type = L'\?\?\?\?';
creator = L'\?\?\?\?';
extension = CFSTR(".slg");
break;
#endif
case FFSAVE_RAW:
type = '\?\?\?\?';
creator = '\?\?\?\?';
extension = CFSTR(".raw");
break;
case FFSAVE_J2C:
type = '\?\?\?\?';
creator = 'prvw';
extension = CFSTR(".j2c");
break;
case FFSAVE_SCRIPT:
type = 'LSL ';
creator = '\?\?\?\?';
extension = CFSTR(".lsl");
break;
case FFSAVE_ALL:
default:
type = '\?\?\?\?';
creator = '\?\?\?\?';
extension = CFSTR("");
break;
}
NavEventUPP eventUPP = NewNavEventUPP(NULL); //TODO: test filepicker
mFolder = folder;
// Create the dialog
error = NavCreatePutFileDialog(&mNavOptions, type, creator, eventUPP, (void*)this, &navRef);
if (error == noErr)
{
CFStringRef nameString = NULL;
bool hasExtension = true;
// Create a CFString of the initial file name
if (!filename.empty())
nameString = CFStringCreateWithCString(NULL, filename.c_str(), kCFStringEncodingUTF8);
else
nameString = CFSTR("Untitled");
// Add the extension if one was not provided
if (nameString && !CFStringHasSuffix(nameString, extension))
{
CFStringRef tempString = nameString;
hasExtension = false;
nameString = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), tempString, extension);
CFRelease(tempString);
}
// Set the name in the dialog
if (nameString)
{
error = NavDialogSetSaveFileName(navRef, nameString);
CFRelease(nameString);
}
else
{
error = paramErr;
}
}
//gViewerWindow->getWindow()->beforeDialog();
// Run the dialog
if (error == noErr)
{
PLS_FLUSH;
error = NavDialogRun(navRef);
}
//gViewerWindow->getWindow()->afterDialog();
if (error == noErr)
error = NavDialogGetReply(navRef, &navReply);
if (navRef)
NavDialogDispose(navRef);
if (error == noErr && navReply.validRecord)
{
SInt32 count = 0;
// AE indexes are 1 based...
error = AECountItems(&navReply.selection, &count);
if (count > 0)
{
// Get the FSRef to the containing folder
FSRef fsRef;
AEKeyword theAEKeyword;
DescType typeCode;
Size actualSize = 0;
memset(&fsRef, 0, sizeof(fsRef));
error = AEGetNthPtr(&navReply.selection, 1, typeFSRef, &theAEKeyword, &typeCode, &fsRef, sizeof(fsRef), &actualSize);
if (error == noErr)
{
char path[PATH_MAX]; /*Flawfinder: ignore*/
char newFileName[SINGLE_FILENAME_BUFFER_SIZE]; /*Flawfinder: ignore*/
error = FSRefMakePath(&fsRef, (UInt8*)path, PATH_MAX);
if (error == noErr)
{
if (CFStringGetCString(navReply.saveFileName, newFileName, sizeof(newFileName), kCFStringEncodingUTF8))
{
mFiles.push_back(std::string(path) + "/" + std::string(newFileName));
}
else
{
error = paramErr;
}
}
else
{
error = paramErr;
}
}
}
}
if (eventUPP)
DisposeNavEventUPP(eventUPP);
return error;
}
bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder)
{
if( mLocked )
return FALSE;
bool success = FALSE;
OSStatus error = noErr;
reset();
mNavOptions.optionFlags &= ~kNavAllowMultipleFiles;
{
error = doNavChooseDialog(filter, folder);
}
if (error == noErr)
{
if (getFileCount())
success = true;
}
return success;
}
bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string const& folder)
{
if( mLocked )
return FALSE;
bool success = FALSE;
OSStatus error = noErr;
reset();
mNavOptions.optionFlags |= kNavAllowMultipleFiles;
{
error = doNavChooseDialog(filter, folder);
}
if (error == noErr)
{
if (getFileCount())
success = true;
if (getFileCount() > 1)
mLocked = TRUE;
}
return success;
}
bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filename, std::string const& folder)
{
if( mLocked )
return FALSE;
bool success = FALSE;
OSStatus error = noErr;
reset();
mNavOptions.optionFlags &= ~kNavAllowMultipleFiles;
{
error = doNavSaveDialog(filter, filename, folder);
}
if (error == noErr)
{
if (getFileCount())
success = true;
}
return success;
}
#elif LL_LINUX || LL_SOLARIS
# if LL_GTK
// static
void LLFilePickerBase::add_to_selectedfiles(gpointer data, gpointer user_data)
{
// We need to run g_filename_to_utf8 in the user's locale
std::string saved_locale(setlocale(LC_ALL, NULL));
setlocale(LC_ALL, "");
LLFilePickerBase* picker = (LLFilePickerBase*) user_data;
GError *error = NULL;
// gchar* filename_utf8 = g_filename_to_utf8((gchar*)data,
// -1, NULL, NULL, &error);
gchar* filename_utf8 = g_filename_display_name ((gchar*) data);
if (error)
{
// *FIXME.
// This condition should really be notified to the user, e.g.
// through a message box. Just logging it is inappropriate.
// Ghhhh. g_filename_display_name is new to glib 2.6, and it
// is too new for SL! (Note that the latest glib as of this
// writing is 2.22. *sigh*) LL supplied *makeASCII family are
// also unsuitable since they allow control characters...
// muhahaha ... Imprudence can !
PLS_WARNS << "g_filename_display_name failed on" << filename_utf8 << ": "<< error->message << PLS_ENDL;
}
if (filename_utf8)
{
picker->mFiles.push_back(std::string(filename_utf8));
PLS_DEBUGS << "ADDED FILE " << filename_utf8 << PLS_ENDL;
g_free(filename_utf8);
}
setlocale(LC_ALL, saved_locale.c_str());
}
// static
void LLFilePickerBase::chooser_responder(GtkWidget *widget, gint response, gpointer user_data)
{
LLFilePicker* picker = (LLFilePicker*)user_data;
PLS_DEBUGS << "GTK DIALOG RESPONSE " << response << PLS_ENDL;
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_selectedfiles, picker);
g_slist_foreach(file_list, (GFunc)g_free, NULL);
g_slist_free (file_list);
}
gtk_widget_destroy(widget);
gtk_main_quit();
}
GtkWindow* LLFilePickerBase::buildFilePicker(bool is_save, bool is_folder, std::string const& folder)
{
if (LLWindowSDL::ll_try_gtk_init())
{
GtkWidget *win = 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,
(gchar *)NULL);
if (!folder.empty())
{
PLS_DEBUGS << "Calling gtk_file_chooser_set_current_folder(\"" << folder << "\")." << PLS_ENDL;
gtk_file_chooser_set_current_folder
(GTK_FILE_CHOOSER(win),
folder.c_str());
}
# if LL_X11
// 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.
if (None != mX11WindowID)
{
gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin
#if GTK_CHECK_VERSION(2, 24, 0)
GdkWindow *gdkwin = gdk_x11_window_foreign_new_for_display(gdk_display_get_default(), static_cast<Window>(mX11WindowID));
#else
GdkWindow *gdkwin = gdk_window_foreign_new(static_cast<GdkNativeWindow>(mX11WindowID));
#endif
gdk_window_set_transient_for(gtk_widget_get_window(GTK_WIDGET(win)), gdkwin);
}
else
{
LL_WARNS() << "Hmm, couldn't get xwid to use for transient." << LL_ENDL;
}
# endif //LL_X11
g_signal_connect (GTK_FILE_CHOOSER(win),
"response",
G_CALLBACK(LLFilePickerBase::chooser_responder),
this);
PLS_FLUSH;
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
{
return NULL;
}
}
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, 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);
}
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",
LLTrans::getString("sound_files") + " (*.wav)");
}
static std::string add_anim_filter_to_gtkchooser(GtkWindow *picker)
{
GtkFileFilter *gfilter = gtk_file_filter_new();
gtk_file_filter_add_pattern(gfilter, "*.bvh");
gtk_file_filter_add_pattern(gfilter, "*.anim");
std::string filtername = LLTrans::getString("animation_files") + " (*.bvh; *.anim)";
add_common_filters_to_gtkchooser(gfilter, picker, filtername);
return filtername;
}
static std::string add_xml_filter_to_gtkchooser(GtkWindow *picker)
{
return add_simple_mime_filter_to_gtkchooser(picker, "text/xml",
LLTrans::getString("xml_file") + " (*.xml)");
}
static std::string add_collada_filter_to_gtkchooser(GtkWindow *picker)
{
return add_simple_pattern_filter_to_gtkchooser(picker, "*.dae",
LLTrans::getString("scene_files") + " (*.dae)");
}
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");
gtk_file_filter_add_mime_type(gfilter, "image/jp2");
std::string filtername = LLTrans::getString("image_files") + " (*.tga; *.bmp; *.jpg; *.png; *.jp2; *.j2k; *.j2c)";
add_common_filters_to_gtkchooser(gfilter, picker, filtername);
return filtername;
}
static std::string add_imagesave_filter_to_gtkchooser(GtkWindow *picker)
{
GtkFileFilter *gfilter = gtk_file_filter_new();
gtk_file_filter_add_mime_type(gfilter, "image/bmp");
gtk_file_filter_add_pattern(gfilter, "*.dxt");
gtk_file_filter_add_mime_type(gfilter, "image/jpeg");
gtk_file_filter_add_pattern(gfilter, "*.j2c");
gtk_file_filter_add_pattern(gfilter, "*.mip");
gtk_file_filter_add_mime_type(gfilter, "image/png");
gtk_file_filter_add_pattern(gfilter, "*.tga");
std::string filtername = LLTrans::getString("image_files") + "(*.bmp; *.dxt; *.jpg; *.jpeg; *.j2c; *.mip; *.png; *.tga)";
add_common_filters_to_gtkchooser(gfilter, picker, filtername);
return filtername;
}
static std::string add_script_filter_to_gtkchooser(GtkWindow *picker)
{
return add_simple_mime_filter_to_gtkchooser(picker, "text/plain",
LLTrans::getString("script_files") + " (*.lsl)");
}
static std::string add_dictionary_filter_to_gtkchooser(GtkWindow *picker)
{
return add_simple_mime_filter_to_gtkchooser(picker, "text/plain",
LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)");
}
bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filename, std::string const& folder)
{
bool rtn = FALSE;
//gViewerWindow->getWindow()->beforeDialog();
reset();
GtkWindow* picker = buildFilePicker(true, false, folder);
if (picker)
{
std::string suggest_name = "untitled";
std::string suggest_ext = "";
std::string caption = LLTrans::getString("save_file_verb") + " ";
switch (filter)
{
case FFSAVE_WAV:
caption += add_wav_filter_to_gtkchooser(picker);
suggest_ext = ".wav";
break;
case FFSAVE_TGA:
caption += add_simple_pattern_filter_to_gtkchooser
(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", LLTrans::getString("bitmap_image_files") + " (*.bmp)");
suggest_ext = ".bmp";
break;
case FFSAVE_AVI:
caption += add_simple_mime_filter_to_gtkchooser
(picker, "video/x-msvideo",
LLTrans::getString("avi_movie_file") + " (*.avi)");
suggest_ext = ".avi";
break;
case FFSAVE_ANIM:
caption += add_simple_pattern_filter_to_gtkchooser
(picker, "*.xaf", LLTrans::getString("xaf_animation_file") + " (*.xaf)");
suggest_ext = ".xaf";
break;
case FFSAVE_XML:
caption += add_simple_pattern_filter_to_gtkchooser
(picker, "*.xml", LLTrans::getString("xml_file") + " (*.xml)");
suggest_ext = ".xml";
break;
case FFSAVE_RAW:
caption += add_simple_pattern_filter_to_gtkchooser
(picker, "*.raw", LLTrans::getString("raw_file") + " (*.raw)");
suggest_ext = ".raw";
break;
case FFSAVE_J2C:
caption += add_simple_mime_filter_to_gtkchooser
(picker, "images/jp2",
LLTrans::getString("compressed_image_files") + " (*.j2c)");
suggest_ext = ".j2c";
break;
case FFSAVE_SCRIPT:
caption += add_script_filter_to_gtkchooser(picker);
suggest_ext = ".lsl";
break;
case FFSAVE_IMAGE:
caption += add_imagesave_filter_to_gtkchooser(picker);
suggest_ext = ".png";
break;
default:;
break;
}
gtk_window_set_title(GTK_WINDOW(picker), caption.c_str());
if (filename.empty())
{
suggest_name += suggest_ext;
gtk_file_chooser_set_current_name
(GTK_FILE_CHOOSER(picker),
suggest_name.c_str());
}
else
{
gtk_file_chooser_set_current_name
(GTK_FILE_CHOOSER(picker), filename.c_str());
}
gtk_widget_show_all(GTK_WIDGET(picker));
PLS_FLUSH;
gtk_main();
rtn = (getFileCount() == 1);
}
//gViewerWindow->getWindow()->afterDialog();
return rtn;
}
bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder)
{
bool rtn = FALSE;
//gViewerWindow->getWindow()->beforeDialog();
reset();
GtkWindow* picker = buildFilePicker(false, false, folder);
if (picker)
{
std::string caption = LLTrans::getString("load_file_verb") + " ";
std::string filtername = "";
switch (filter)
{
case FFLOAD_WAV:
filtername = add_wav_filter_to_gtkchooser(picker);
break;
case FFLOAD_ANIM:
filtername = add_anim_filter_to_gtkchooser(picker);
break;
case FFLOAD_COLLADA:
filtername = add_collada_filter_to_gtkchooser(picker);
break;
case FFLOAD_IMAGE:
filtername = add_imageload_filter_to_gtkchooser(picker);
break;
case FFLOAD_SCRIPT:
filtername = add_script_filter_to_gtkchooser(picker);
break;
case FFLOAD_DICTIONARY:
filtername = add_dictionary_filter_to_gtkchooser(picker);
break;
case FFLOAD_XML:
filtername = add_xml_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));
PLS_FLUSH;
gtk_main();
rtn = (getFileCount() == 1);
}
//gViewerWindow->getWindow()->afterDialog();
return rtn;
}
bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string const& folder)
{
bool rtn = FALSE;
//gViewerWindow->getWindow()->beforeDialog();
reset();
GtkWindow* picker = buildFilePicker(false, false, folder);
if (picker)
{
gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(picker),
TRUE);
gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("load_files").c_str());
gtk_widget_show_all(GTK_WIDGET(picker));
PLS_FLUSH;
gtk_main();
rtn = !mFiles.empty();
}
//gViewerWindow->getWindow()->afterDialog();
return rtn;
}
# else // LL_GTK
// Hacky stubs designed to facilitate fake getSaveFile and getLoadFile with
// static results, when we don't have a real filepicker.
bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filename, std::string const& folder)
{
reset();
PLS_INFOS << "getSaveFile suggested filename is [" << filename << "]" << PLS_ENDL;
if (!filename.empty())
{
mFiles.push_back(gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + filename);
return TRUE;
}
return FALSE;
}
bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder)
{
reset();
// HACK: Static filenames for 'open' until we implement filepicker
std::string filename = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + "upload";
switch (filter)
{
case FFLOAD_WAV: filename += ".wav"; break;
case FFLOAD_IMAGE: filename += ".tga"; break;
case FFLOAD_ANIM: filename += ".bvh"; break;
case FFLOAD_XML: filename += ".xml"; break;
default: break;
}
mFiles.push_back(filename);
PLS_INFOS << "getLoadFile: Will try to open file: " << hackyfilename << PLS_ENDL;
return TRUE;
}
bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string const& folder)
{
reset();
return FALSE;
}
#endif // LL_GTK
#else // not implemented
bool LLFilePickerBase::getSaveFile(ESaveFilter filter, std::string const& filename, std::string const& folder)
{
reset();
return FALSE;
}
bool LLFilePickerBase::getLoadFile(ELoadFilter filter, std::string const& folder)
{
reset();
return FALSE;
}
bool LLFilePickerBase::getMultipleLoadFiles(ELoadFilter filter, std::string const& folder)
{
reset();
return FALSE;
}
#endif