BsLinuxBrowseDialogs.cpp 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Utility/BsEditorUtility.h"
  4. #include <gtk/gtk.h>
  5. #include <String/BsUnicode.h>
  6. namespace bs
  7. {
  8. // Note: Code below is the only reason we depend on GTK. Ideally we replace the GTK file dialog with built-in file
  9. // dialog that can be used transparently across platforms, in which case we can also drop GTK.
  10. bool EditorUtility::openBrowseDialog(FileDialogType type, const Path& defaultPath, const String& filterList,
  11. Vector<Path>& paths)
  12. {
  13. GtkWidget* fakeParent = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  14. const char* titleString;
  15. const char* cancelString;
  16. const char* acceptString;
  17. GtkFileChooserAction action;
  18. if(((int)type & (int)FileDialogType::OpenFile) != 0)
  19. {
  20. titleString = "Open File";
  21. cancelString = "Cancel";
  22. acceptString = "Open";
  23. action = GTK_FILE_CHOOSER_ACTION_OPEN;
  24. }
  25. else if(((int)type & (int)FileDialogType::OpenFolder) != 0)
  26. {
  27. titleString = "Open Folder";
  28. cancelString = "Cancel";
  29. acceptString = "Open";
  30. action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
  31. }
  32. else // Save dialog
  33. {
  34. titleString = "Save File";
  35. cancelString = "Cancel";
  36. acceptString = "Save";
  37. action = GTK_FILE_CHOOSER_ACTION_SAVE;
  38. }
  39. GtkWidget* fileDialog = gtk_file_chooser_dialog_new(titleString,
  40. GTK_WINDOW(fakeParent), action, cancelString, GTK_RESPONSE_CANCEL,
  41. acceptString, GTK_RESPONSE_ACCEPT, nullptr);
  42. GtkFileChooser* chooser = GTK_FILE_CHOOSER(fileDialog);
  43. gboolean selectMultiple = ((int)type & (int)FileDialogType::Multiselect) != 0;
  44. gtk_file_chooser_set_select_multiple(chooser, selectMultiple);
  45. gtk_file_chooser_set_do_overwrite_confirmation(chooser, true);
  46. String defaultPathStr = defaultPath.toString();
  47. if(!defaultPathStr.empty())
  48. gtk_file_chooser_set_current_folder(chooser, defaultPathStr.c_str());
  49. if(!filterList.empty())
  50. {
  51. GtkFileFilter* fileFilter = gtk_file_filter_new();
  52. gtk_file_filter_set_name(fileFilter, filterList.c_str());
  53. gtk_file_filter_add_pattern(fileFilter, filterList.c_str());
  54. gtk_file_chooser_add_filter(chooser, fileFilter);
  55. }
  56. // TODO - Can't set transient-for because the windows belong to two different X11 displays. I'd have to use gtk
  57. // display as the primary display (which is too awkward to be worth it)
  58. //GdkDisplay* gdkDisplay = gdk_x11_lookup_xdisplay(x11display);// gtk_widget_get_display(fileDialog);;
  59. //GdkWindow* parentWindow = gdk_x11_window_foreign_new_for_display(gdkDisplay, xParent);
  60. //gdk_window_set_transient_for(gtk_widget_get_window(fileDialog), parentWindow);
  61. gint response = gtk_dialog_run(GTK_DIALOG(fileDialog));
  62. if(response == GTK_RESPONSE_ACCEPT)
  63. {
  64. GSList* filenames = gtk_file_chooser_get_filenames(chooser);
  65. guint numElems = g_slist_length(filenames);
  66. for(guint i = 0; i < numElems; ++i)
  67. {
  68. char* filename = (char*)g_slist_nth_data(filenames, i);
  69. paths.push_back(String(filename));
  70. g_free(filename);
  71. }
  72. g_slist_free(filenames);
  73. }
  74. gtk_widget_destroy(fileDialog);
  75. gtk_widget_destroy(fakeParent);
  76. // Make sure the destroy events are processed
  77. while(gtk_events_pending())
  78. gtk_main_iteration();
  79. return response == GTK_RESPONSE_ACCEPT;
  80. }
  81. }