/indra/newview/lldirpicker.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 381 lines · 244 code · 84 blank · 53 comment · 44 complexity · abeee8146bd8f7f695b9d469be8ab16e MD5 · raw file

  1. /**
  2. * @file lldirpicker.cpp
  3. * @brief OS-specific file picker
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "lldirpicker.h"
  28. //#include "llviewermessage.h"
  29. #include "llworld.h"
  30. #include "llviewerwindow.h"
  31. #include "llkeyboard.h"
  32. #include "lldir.h"
  33. #include "llframetimer.h"
  34. #include "lltrans.h"
  35. #include "llwindow.h" // beforeDialog()
  36. #include "llviewercontrol.h"
  37. #if LL_LINUX || LL_SOLARIS
  38. # include "llfilepicker.h"
  39. #endif
  40. //
  41. // Globals
  42. //
  43. LLDirPicker LLDirPicker::sInstance;
  44. #if LL_WINDOWS
  45. #include <shlobj.h>
  46. #endif
  47. //
  48. // Implementation
  49. //
  50. // utility function to check if access to local file system via file browser
  51. // is enabled and if not, tidy up and indicate we're not allowed to do this.
  52. bool LLDirPicker::check_local_file_access_enabled()
  53. {
  54. // if local file browsing is turned off, return without opening dialog
  55. bool local_file_system_browsing_enabled = gSavedSettings.getBOOL("LocalFileSystemBrowsingEnabled");
  56. if ( ! local_file_system_browsing_enabled )
  57. {
  58. mDir.clear(); // Windows
  59. mFileName = NULL; // Mac/Linux
  60. return false;
  61. }
  62. return true;
  63. }
  64. #if LL_WINDOWS
  65. LLDirPicker::LLDirPicker() :
  66. mFileName(NULL),
  67. mLocked(false)
  68. {
  69. }
  70. LLDirPicker::~LLDirPicker()
  71. {
  72. // nothing
  73. }
  74. BOOL LLDirPicker::getDir(std::string* filename)
  75. {
  76. if( mLocked )
  77. {
  78. return FALSE;
  79. }
  80. // if local file browsing is turned off, return without opening dialog
  81. if ( check_local_file_access_enabled() == false )
  82. {
  83. return FALSE;
  84. }
  85. BOOL success = FALSE;
  86. // Modal, so pause agent
  87. send_agent_pause();
  88. BROWSEINFO bi;
  89. memset(&bi, 0, sizeof(bi));
  90. bi.ulFlags = BIF_USENEWUI;
  91. bi.hwndOwner = (HWND)gViewerWindow->getPlatformWindow();
  92. bi.lpszTitle = NULL;
  93. ::OleInitialize(NULL);
  94. LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);
  95. if(pIDL != NULL)
  96. {
  97. WCHAR buffer[_MAX_PATH] = {'\0'};
  98. if(::SHGetPathFromIDList(pIDL, buffer) != 0)
  99. {
  100. // Set the string value.
  101. mDir = utf16str_to_utf8str(llutf16string(buffer));
  102. success = TRUE;
  103. }
  104. // free the item id list
  105. CoTaskMemFree(pIDL);
  106. }
  107. ::OleUninitialize();
  108. send_agent_resume();
  109. // Account for the fact that the app has been stalled.
  110. LLFrameTimer::updateFrameTime();
  111. return success;
  112. }
  113. std::string LLDirPicker::getDirName()
  114. {
  115. return mDir;
  116. }
  117. /////////////////////////////////////////////DARWIN
  118. #elif LL_DARWIN
  119. LLDirPicker::LLDirPicker() :
  120. mFileName(NULL),
  121. mLocked(false)
  122. {
  123. reset();
  124. memset(&mNavOptions, 0, sizeof(mNavOptions));
  125. OSStatus error = NavGetDefaultDialogCreationOptions(&mNavOptions);
  126. if (error == noErr)
  127. {
  128. mNavOptions.modality = kWindowModalityAppModal;
  129. }
  130. }
  131. LLDirPicker::~LLDirPicker()
  132. {
  133. // nothing
  134. }
  135. //static
  136. pascal void LLDirPicker::doNavCallbackEvent(NavEventCallbackMessage callBackSelector,
  137. NavCBRecPtr callBackParms, void* callBackUD)
  138. {
  139. switch(callBackSelector)
  140. {
  141. case kNavCBStart:
  142. {
  143. if (!sInstance.mFileName) break;
  144. OSStatus error = noErr;
  145. AEDesc theLocation = {typeNull, NULL};
  146. FSSpec outFSSpec;
  147. //Convert string to a FSSpec
  148. FSRef myFSRef;
  149. const char* filename=sInstance.mFileName->c_str();
  150. error = FSPathMakeRef ((UInt8*)filename, &myFSRef, NULL);
  151. if (error != noErr) break;
  152. error = FSGetCatalogInfo (&myFSRef, kFSCatInfoNone, NULL, NULL, &outFSSpec, NULL);
  153. if (error != noErr) break;
  154. error = AECreateDesc(typeFSS, &outFSSpec, sizeof(FSSpec), &theLocation);
  155. if (error != noErr) break;
  156. error = NavCustomControl(callBackParms->context,
  157. kNavCtlSetLocation, (void*)&theLocation);
  158. }
  159. }
  160. }
  161. OSStatus LLDirPicker::doNavChooseDialog()
  162. {
  163. OSStatus error = noErr;
  164. NavDialogRef navRef = NULL;
  165. NavReplyRecord navReply;
  166. memset(&navReply, 0, sizeof(navReply));
  167. // NOTE: we are passing the address of a local variable here.
  168. // This is fine, because the object this call creates will exist for less than the lifetime of this function.
  169. // (It is destroyed by NavDialogDispose() below.)
  170. error = NavCreateChooseFolderDialog(&mNavOptions, &doNavCallbackEvent, NULL, NULL, &navRef);
  171. gViewerWindow->getWindow()->beforeDialog();
  172. if (error == noErr)
  173. error = NavDialogRun(navRef);
  174. gViewerWindow->getWindow()->afterDialog();
  175. if (error == noErr)
  176. error = NavDialogGetReply(navRef, &navReply);
  177. if (navRef)
  178. NavDialogDispose(navRef);
  179. if (error == noErr && navReply.validRecord)
  180. {
  181. FSRef fsRef;
  182. AEKeyword theAEKeyword;
  183. DescType typeCode;
  184. Size actualSize = 0;
  185. char path[LL_MAX_PATH]; /*Flawfinder: ignore*/
  186. memset(&fsRef, 0, sizeof(fsRef));
  187. error = AEGetNthPtr(&navReply.selection, 1, typeFSRef, &theAEKeyword, &typeCode, &fsRef, sizeof(fsRef), &actualSize);
  188. if (error == noErr)
  189. error = FSRefMakePath(&fsRef, (UInt8*) path, sizeof(path));
  190. if (error == noErr)
  191. mDir = path;
  192. }
  193. return error;
  194. }
  195. BOOL LLDirPicker::getDir(std::string* filename)
  196. {
  197. if( mLocked ) return FALSE;
  198. BOOL success = FALSE;
  199. OSStatus error = noErr;
  200. // if local file browsing is turned off, return without opening dialog
  201. if ( check_local_file_access_enabled() == false )
  202. {
  203. return FALSE;
  204. }
  205. mFileName = filename;
  206. // mNavOptions.saveFileName
  207. // Modal, so pause agent
  208. send_agent_pause();
  209. {
  210. error = doNavChooseDialog();
  211. }
  212. send_agent_resume();
  213. if (error == noErr)
  214. {
  215. if (mDir.length() > 0)
  216. success = true;
  217. }
  218. // Account for the fact that the app has been stalled.
  219. LLFrameTimer::updateFrameTime();
  220. return success;
  221. }
  222. std::string LLDirPicker::getDirName()
  223. {
  224. return mDir;
  225. }
  226. void LLDirPicker::reset()
  227. {
  228. mLocked = false;
  229. mDir.clear();
  230. }
  231. #elif LL_LINUX || LL_SOLARIS
  232. LLDirPicker::LLDirPicker() :
  233. mFileName(NULL),
  234. mLocked(false)
  235. {
  236. mFilePicker = new LLFilePicker();
  237. reset();
  238. }
  239. LLDirPicker::~LLDirPicker()
  240. {
  241. delete mFilePicker;
  242. }
  243. void LLDirPicker::reset()
  244. {
  245. if (mFilePicker)
  246. mFilePicker->reset();
  247. }
  248. BOOL LLDirPicker::getDir(std::string* filename)
  249. {
  250. reset();
  251. // if local file browsing is turned off, return without opening dialog
  252. if ( check_local_file_access_enabled() == false )
  253. {
  254. return FALSE;
  255. }
  256. if (mFilePicker)
  257. {
  258. GtkWindow* picker = mFilePicker->buildFilePicker(false, true,
  259. "dirpicker");
  260. if (picker)
  261. {
  262. gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("choose_the_directory").c_str());
  263. gtk_widget_show_all(GTK_WIDGET(picker));
  264. gtk_main();
  265. return (!mFilePicker->getFirstFile().empty());
  266. }
  267. }
  268. return FALSE;
  269. }
  270. std::string LLDirPicker::getDirName()
  271. {
  272. if (mFilePicker)
  273. {
  274. return mFilePicker->getFirstFile();
  275. }
  276. return "";
  277. }
  278. #else // not implemented
  279. LLDirPicker::LLDirPicker()
  280. {
  281. reset();
  282. }
  283. LLDirPicker::~LLDirPicker()
  284. {
  285. }
  286. void LLDirPicker::reset()
  287. {
  288. }
  289. BOOL LLDirPicker::getDir(std::string* filename)
  290. {
  291. return FALSE;
  292. }
  293. std::string LLDirPicker::getDirName()
  294. {
  295. return "";
  296. }
  297. #endif