Files
SingularityViewer/indra/plugins/filepicker/llfilepicker.cpp
Inusaito Sayori e5f2d5f76e Fix Save Preview As... for textures, now save as any type we can encode to!
Removes the previous method and condenses the menu entries back into one.
 - Translations have been updated except for German, German will need to update the translation for "Save Preview As..." since the name hasn't changed.
Adds FFSAVE_IMAGE to the filepicker enums
Crossplatformity:
 - The Windows version works nicely
 - The Linux version may not work or even compile but it should..
 - The Mac version hasn't been added, instead it will default to accept any(all filter), should the provided file extension be invalid a notification will display.
2013-09-14 21:21:36 -04:00

1714 lines
43 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.
//
// 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\0*.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 (mX11WindowID != None)
{
gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin
GdkWindow *gdkwin = gdk_window_foreign_new(mX11WindowID);
gdk_window_set_transient_for(GTK_WIDGET(win)->window, gdkwin);
}
# 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