GTK: use native file chooser dialog, if available.
This requires GTK 3.24+ and (at least for GTK 3.24) the environment variable GTK_USE_PORTAL to be set to 1.
This commit is contained in:
parent
e7b75f19c3
commit
bc3e09edbf
@ -81,6 +81,7 @@ Other new features:
|
|||||||
* The "=" key is bound to "Zoom In", like "+" key.
|
* The "=" key is bound to "Zoom In", like "+" key.
|
||||||
* The numpad decimal separator key is bound to "." regardless of locale.
|
* The numpad decimal separator key is bound to "." regardless of locale.
|
||||||
* On Windows, full-screen mode is implemented.
|
* On Windows, full-screen mode is implemented.
|
||||||
|
* On Linux, native file chooser dialog can be used.
|
||||||
|
|
||||||
Bugs fixed:
|
Bugs fixed:
|
||||||
* A point in 3d constrained to any line whose length is free no longer
|
* A point in 3d constrained to any line whose length is free no longer
|
||||||
|
@ -13,6 +13,14 @@ endif()
|
|||||||
|
|
||||||
set(HAVE_SPACEWARE ${SPACEWARE_FOUND})
|
set(HAVE_SPACEWARE ${SPACEWARE_FOUND})
|
||||||
|
|
||||||
|
if(NOT WIN32 OR APPLE)
|
||||||
|
if(GTKMM_gtkmm-3.0_VERSION VERSION_LESS "3.24.0")
|
||||||
|
set(HAVE_GTK_FILECHOOSERNATIVE 0)
|
||||||
|
else()
|
||||||
|
set(HAVE_GTK_FILECHOOSERNATIVE 1)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
|
|
||||||
|
@ -16,4 +16,7 @@
|
|||||||
#cmakedefine HAVE_BACKTRACE
|
#cmakedefine HAVE_BACKTRACE
|
||||||
#define BACKTRACE_HEADER @BACKTRACE_HEADER@
|
#define BACKTRACE_HEADER @BACKTRACE_HEADER@
|
||||||
|
|
||||||
|
/* If we use GTK, can we use the native file chooser? */
|
||||||
|
#cmakedefine HAVE_GTK_FILECHOOSERNATIVE
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
#include <gtkmm/cssprovider.h>
|
#include <gtkmm/cssprovider.h>
|
||||||
#include <gtkmm/entry.h>
|
#include <gtkmm/entry.h>
|
||||||
#include <gtkmm/filechooserdialog.h>
|
#include <gtkmm/filechooserdialog.h>
|
||||||
|
#define HAVE_GTK_FILECHOOSERNATIVE
|
||||||
|
#if defined(HAVE_GTK_FILECHOOSERNATIVE)
|
||||||
|
# include <gtkmm/filechoosernative.h>
|
||||||
|
#endif
|
||||||
#include <gtkmm/fixed.h>
|
#include <gtkmm/fixed.h>
|
||||||
#include <gtkmm/glarea.h>
|
#include <gtkmm/glarea.h>
|
||||||
#include <gtkmm/main.h>
|
#include <gtkmm/main.h>
|
||||||
@ -1187,32 +1191,27 @@ MessageDialogRef CreateMessageDialog(WindowRef parentWindow) {
|
|||||||
// File dialogs
|
// File dialogs
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
class FileDialogImplGtk final : public FileDialog {
|
class FileDialogImplGtk : public FileDialog {
|
||||||
public:
|
public:
|
||||||
Gtk::FileChooserDialog gtkDialog;
|
Gtk::FileChooser *gtkChooser;
|
||||||
std::vector<std::string> extensions;
|
std::vector<std::string> extensions;
|
||||||
|
|
||||||
FileDialogImplGtk(Gtk::FileChooserDialog &&dialog)
|
void InitFileChooser(Gtk::FileChooser &chooser) {
|
||||||
: gtkDialog(std::move(dialog))
|
gtkChooser = &chooser;
|
||||||
{
|
gtkChooser->property_filter().signal_changed().
|
||||||
gtkDialog.property_filter().signal_changed().
|
|
||||||
connect(sigc::mem_fun(this, &FileDialogImplGtk::FilterChanged));
|
connect(sigc::mem_fun(this, &FileDialogImplGtk::FilterChanged));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetTitle(std::string title) override {
|
|
||||||
gtkDialog.set_title(PrepareTitle(title));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetCurrentName(std::string name) override {
|
void SetCurrentName(std::string name) override {
|
||||||
gtkDialog.set_current_name(name);
|
gtkChooser->set_current_name(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Platform::Path GetFilename() override {
|
Platform::Path GetFilename() override {
|
||||||
return Path::From(gtkDialog.get_filename());
|
return Path::From(gtkChooser->get_filename());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFilename(Platform::Path path) override {
|
void SetFilename(Platform::Path path) override {
|
||||||
gtkDialog.set_filename(path.raw);
|
gtkChooser->set_filename(path.raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddFilter(std::string name, std::vector<std::string> extensions) override {
|
void AddFilter(std::string name, std::vector<std::string> extensions) override {
|
||||||
@ -1233,13 +1232,13 @@ public:
|
|||||||
gtkFilter->set_name(name + " (" + desc + ")");
|
gtkFilter->set_name(name + " (" + desc + ")");
|
||||||
|
|
||||||
this->extensions.push_back(extensions.front());
|
this->extensions.push_back(extensions.front());
|
||||||
gtkDialog.add_filter(gtkFilter);
|
gtkChooser->add_filter(gtkFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetExtension() {
|
std::string GetExtension() {
|
||||||
auto filters = gtkDialog.list_filters();
|
auto filters = gtkChooser->list_filters();
|
||||||
size_t filterIndex =
|
size_t filterIndex =
|
||||||
std::find(filters.begin(), filters.end(), gtkDialog.get_filter()) -
|
std::find(filters.begin(), filters.end(), gtkChooser->get_filter()) -
|
||||||
filters.begin();
|
filters.begin();
|
||||||
if(filterIndex < extensions.size()) {
|
if(filterIndex < extensions.size()) {
|
||||||
return extensions[filterIndex];
|
return extensions[filterIndex];
|
||||||
@ -1249,14 +1248,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SetExtension(std::string extension) {
|
void SetExtension(std::string extension) {
|
||||||
auto filters = gtkDialog.list_filters();
|
auto filters = gtkChooser->list_filters();
|
||||||
size_t extensionIndex =
|
size_t extensionIndex =
|
||||||
std::find(extensions.begin(), extensions.end(), extension) -
|
std::find(extensions.begin(), extensions.end(), extension) -
|
||||||
extensions.begin();
|
extensions.begin();
|
||||||
if(extensionIndex < filters.size()) {
|
if(extensionIndex < filters.size()) {
|
||||||
gtkDialog.set_filter(filters[extensionIndex]);
|
gtkChooser->set_filter(filters[extensionIndex]);
|
||||||
} else {
|
} else {
|
||||||
gtkDialog.set_filter(filters.front());
|
gtkChooser->set_filter(filters.front());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1270,21 +1269,46 @@ public:
|
|||||||
|
|
||||||
void FreezeChoices(SettingsRef settings, const std::string &key) override {
|
void FreezeChoices(SettingsRef settings, const std::string &key) override {
|
||||||
settings->FreezeString("Dialog_" + key + "_Folder",
|
settings->FreezeString("Dialog_" + key + "_Folder",
|
||||||
gtkDialog.get_current_folder());
|
gtkChooser->get_current_folder());
|
||||||
settings->FreezeString("Dialog_" + key + "_Filter", GetExtension());
|
settings->FreezeString("Dialog_" + key + "_Filter", GetExtension());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThawChoices(SettingsRef settings, const std::string &key) override {
|
void ThawChoices(SettingsRef settings, const std::string &key) override {
|
||||||
gtkDialog.set_current_folder(settings->ThawString("Dialog_" + key + "_Folder"));
|
gtkChooser->set_current_folder(settings->ThawString("Dialog_" + key + "_Folder"));
|
||||||
SetExtension(settings->ThawString("Dialog_" + key + "_Filter"));
|
SetExtension(settings->ThawString("Dialog_" + key + "_Filter"));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RunModal() override {
|
void CheckForUntitledFile() {
|
||||||
if(gtkDialog.get_action() == Gtk::FILE_CHOOSER_ACTION_SAVE &&
|
if(gtkChooser->get_action() == Gtk::FILE_CHOOSER_ACTION_SAVE &&
|
||||||
Path::From(gtkDialog.get_current_name()).FileStem().empty()) {
|
Path::From(gtkChooser->get_current_name()).FileStem().empty()) {
|
||||||
gtkDialog.set_current_name(std::string(_("untitled")) + "." + GetExtension());
|
gtkChooser->set_current_name(std::string(_("untitled")) + "." + GetExtension());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FileDialogGtkImplGtk final : public FileDialogImplGtk {
|
||||||
|
public:
|
||||||
|
Gtk::FileChooserDialog gtkDialog;
|
||||||
|
|
||||||
|
FileDialogGtkImplGtk(Gtk::Window >kParent, bool isSave)
|
||||||
|
: gtkDialog(gtkParent,
|
||||||
|
isSave ? C_("title", "Save File")
|
||||||
|
: C_("title", "Open File"),
|
||||||
|
isSave ? Gtk::FILE_CHOOSER_ACTION_SAVE
|
||||||
|
: Gtk::FILE_CHOOSER_ACTION_OPEN) {
|
||||||
|
gtkDialog.add_button(C_("button", "_Cancel"), Gtk::RESPONSE_CANCEL);
|
||||||
|
gtkDialog.add_button(isSave ? C_("button", "_Save")
|
||||||
|
: C_("button", "_Open"), Gtk::RESPONSE_OK);
|
||||||
|
gtkDialog.set_default_response(Gtk::RESPONSE_OK);
|
||||||
|
InitFileChooser(gtkDialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTitle(std::string title) override {
|
||||||
|
gtkDialog.set_title(PrepareTitle(title));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RunModal() override {
|
||||||
|
CheckForUntitledFile();
|
||||||
if(gtkDialog.run() == Gtk::RESPONSE_OK) {
|
if(gtkDialog.run() == Gtk::RESPONSE_OK) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -1293,26 +1317,56 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(HAVE_GTK_FILECHOOSERNATIVE)
|
||||||
|
|
||||||
|
class FileDialogNativeImplGtk final : public FileDialogImplGtk {
|
||||||
|
public:
|
||||||
|
Glib::RefPtr<Gtk::FileChooserNative> gtkNative;
|
||||||
|
|
||||||
|
FileDialogNativeImplGtk(Gtk::Window >kParent, bool isSave) {
|
||||||
|
gtkNative = Gtk::FileChooserNative::create(
|
||||||
|
isSave ? C_("title", "Save File")
|
||||||
|
: C_("title", "Open File"),
|
||||||
|
gtkParent,
|
||||||
|
isSave ? Gtk::FILE_CHOOSER_ACTION_SAVE
|
||||||
|
: Gtk::FILE_CHOOSER_ACTION_OPEN,
|
||||||
|
isSave ? C_("button", "_Save")
|
||||||
|
: C_("button", "_Open"),
|
||||||
|
C_("button", "_Cancel"));
|
||||||
|
// Seriously, GTK?!
|
||||||
|
InitFileChooser(*gtkNative.operator->());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTitle(std::string title) override {
|
||||||
|
gtkNative->set_title(PrepareTitle(title));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RunModal() override {
|
||||||
|
CheckForUntitledFile();
|
||||||
|
if(gtkNative->run() == Gtk::RESPONSE_ACCEPT) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_GTK_FILECHOOSERNATIVE)
|
||||||
|
# define FILE_DIALOG_IMPL FileDialogNativeImplGtk
|
||||||
|
#else
|
||||||
|
# define FILE_DIALOG_IMPL FileDialogGtkImplGtk
|
||||||
|
#endif
|
||||||
|
|
||||||
FileDialogRef CreateOpenFileDialog(WindowRef parentWindow) {
|
FileDialogRef CreateOpenFileDialog(WindowRef parentWindow) {
|
||||||
Gtk::Window >kParent = std::static_pointer_cast<WindowImplGtk>(parentWindow)->gtkWindow;
|
Gtk::Window >kParent = std::static_pointer_cast<WindowImplGtk>(parentWindow)->gtkWindow;
|
||||||
Gtk::FileChooserDialog gtkDialog(gtkParent, C_("title", "Open File"),
|
return std::make_shared<FILE_DIALOG_IMPL>(gtkParent, /*isSave=*/false);
|
||||||
Gtk::FILE_CHOOSER_ACTION_OPEN);
|
|
||||||
gtkDialog.add_button(C_("button", "_Cancel"), Gtk::RESPONSE_CANCEL);
|
|
||||||
gtkDialog.add_button(C_("button", "_Open"), Gtk::RESPONSE_OK);
|
|
||||||
gtkDialog.set_default_response(Gtk::RESPONSE_OK);
|
|
||||||
return std::make_shared<FileDialogImplGtk>(std::move(gtkDialog));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileDialogRef CreateSaveFileDialog(WindowRef parentWindow) {
|
FileDialogRef CreateSaveFileDialog(WindowRef parentWindow) {
|
||||||
Gtk::Window >kParent = std::static_pointer_cast<WindowImplGtk>(parentWindow)->gtkWindow;
|
Gtk::Window >kParent = std::static_pointer_cast<WindowImplGtk>(parentWindow)->gtkWindow;
|
||||||
Gtk::FileChooserDialog gtkDialog(gtkParent, C_("title", "Save File"),
|
return std::make_shared<FILE_DIALOG_IMPL>(gtkParent, /*isSave=*/true);
|
||||||
Gtk::FILE_CHOOSER_ACTION_SAVE);
|
|
||||||
gtkDialog.set_do_overwrite_confirmation(true);
|
|
||||||
gtkDialog.add_button(C_("button", "_Cancel"), Gtk::RESPONSE_CANCEL);
|
|
||||||
gtkDialog.add_button(C_("button", "_Save"), Gtk::RESPONSE_OK);
|
|
||||||
gtkDialog.set_default_response(Gtk::RESPONSE_OK);
|
|
||||||
return std::make_shared<FileDialogImplGtk>(std::move(gtkDialog));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user