Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

juce_linux_FileChooser.cpp 6.4KB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. static bool exeIsAvailable (const char* const executable)
  18. {
  19. ChildProcess child;
  20. const bool ok = child.start ("which " + String (executable))
  21. && child.readAllProcessOutput().trim().isNotEmpty();
  22. child.waitForProcessToFinish (60 * 1000);
  23. return ok;
  24. }
  25. bool FileChooser::isPlatformDialogAvailable()
  26. {
  27. #if JUCE_DISABLE_NATIVE_FILECHOOSERS
  28. return false;
  29. #else
  30. static bool canUseNativeBox = exeIsAvailable ("zenity") || exeIsAvailable ("kdialog");
  31. return canUseNativeBox;
  32. #endif
  33. }
  34. static uint64 getTopWindowID() noexcept
  35. {
  36. if (TopLevelWindow* top = TopLevelWindow::getActiveTopLevelWindow())
  37. return (uint64) (pointer_sized_uint) top->getWindowHandle();
  38. return 0;
  39. }
  40. static bool isKdeFullSession()
  41. {
  42. return SystemStats::getEnvironmentVariable ("KDE_FULL_SESSION", String())
  43. .equalsIgnoreCase ("true");
  44. }
  45. static void addKDialogArgs (StringArray& args, String& separator,
  46. const String& title, const File& file, const String& filters,
  47. bool isDirectory, bool isSave, bool selectMultipleFiles)
  48. {
  49. args.add ("kdialog");
  50. if (title.isNotEmpty())
  51. args.add ("--title=" + title);
  52. if (uint64 topWindowID = getTopWindowID())
  53. {
  54. args.add ("--attach");
  55. args.add (String (topWindowID));
  56. }
  57. if (selectMultipleFiles)
  58. {
  59. separator = "\n";
  60. args.add ("--multiple");
  61. args.add ("--separate-output");
  62. args.add ("--getopenfilename");
  63. }
  64. else
  65. {
  66. if (isSave) args.add ("--getsavefilename");
  67. else if (isDirectory) args.add ("--getexistingdirectory");
  68. else args.add ("--getopenfilename");
  69. }
  70. File startPath;
  71. if (file.exists())
  72. {
  73. startPath = file;
  74. }
  75. else if (file.getParentDirectory().exists())
  76. {
  77. startPath = file.getParentDirectory();
  78. }
  79. else
  80. {
  81. startPath = File::getSpecialLocation (File::userHomeDirectory);
  82. if (isSave)
  83. startPath = startPath.getChildFile (file.getFileName());
  84. }
  85. args.add (startPath.getFullPathName());
  86. args.add (filters.replaceCharacter (';', ' '));
  87. }
  88. static void addZenityArgs (StringArray& args, String& separator,
  89. const String& title, const File& file, const String& filters,
  90. bool isDirectory, bool isSave, bool selectMultipleFiles)
  91. {
  92. args.add ("zenity");
  93. args.add ("--file-selection");
  94. if (title.isNotEmpty())
  95. args.add ("--title=" + title);
  96. if (selectMultipleFiles)
  97. {
  98. separator = ":";
  99. args.add ("--multiple");
  100. args.add ("--separator=" + separator);
  101. }
  102. else
  103. {
  104. if (isDirectory) args.add ("--directory");
  105. if (isSave) args.add ("--save");
  106. }
  107. if (filters.isNotEmpty() && filters != "*" && filters != "*.*")
  108. {
  109. StringArray tokens;
  110. tokens.addTokens (filters, ";,|", "\"");
  111. for (int i = 0; i < tokens.size(); ++i)
  112. args.add ("--file-filter='" + tokens[i] + "'");
  113. }
  114. if (file.isDirectory())
  115. file.setAsCurrentWorkingDirectory();
  116. else if (file.getParentDirectory().exists())
  117. file.getParentDirectory().setAsCurrentWorkingDirectory();
  118. else
  119. File::getSpecialLocation (File::userHomeDirectory).setAsCurrentWorkingDirectory();
  120. if (! file.getFileName().isEmpty())
  121. args.add ("--filename=" + file.getFileName());
  122. // supplying the window ID of the topmost window makes sure that Zenity pops up..
  123. if (uint64 topWindowID = getTopWindowID())
  124. setenv ("WINDOWID", String (topWindowID).toRawUTF8(), true);
  125. }
  126. void FileChooser::showPlatformDialog (Array<File>& results,
  127. const String& title, const File& file, const String& filters,
  128. bool isDirectory, bool /* selectsFiles */,
  129. bool isSave, bool /* warnAboutOverwritingExistingFiles */,
  130. bool selectMultipleFiles, FilePreviewComponent*)
  131. {
  132. const File previousWorkingDirectory (File::getCurrentWorkingDirectory());
  133. StringArray args;
  134. String separator;
  135. // use kdialog for KDE sessions or if zenity is missing
  136. if (exeIsAvailable ("kdialog") && (isKdeFullSession() || ! exeIsAvailable ("zenity")))
  137. addKDialogArgs (args, separator, title, file, filters, isDirectory, isSave, selectMultipleFiles);
  138. else
  139. addZenityArgs (args, separator, title, file, filters, isDirectory, isSave, selectMultipleFiles);
  140. args.add ("2>/dev/null"); // (to avoid logging info ending up in the results)
  141. ChildProcess child;
  142. if (child.start (args, ChildProcess::wantStdOut))
  143. {
  144. const String result (child.readAllProcessOutput().trim());
  145. if (result.isNotEmpty())
  146. {
  147. StringArray tokens;
  148. if (selectMultipleFiles)
  149. tokens.addTokens (result, separator, "\"");
  150. else
  151. tokens.add (result);
  152. for (int i = 0; i < tokens.size(); ++i)
  153. results.add (File::getCurrentWorkingDirectory().getChildFile (tokens[i]));
  154. }
  155. child.waitForProcessToFinish (60 * 1000);
  156. }
  157. previousWorkingDirectory.setAsCurrentWorkingDirectory();
  158. }