Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
choose-file.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2
3#include "choose-file.h"
4
5#include <glib/gi18n.h>
6#include <giomm/liststore.h>
7#include <gtkmm/error.h>
8#include <gtkmm/filedialog.h>
9
10#include "preferences.h"
11#include "choose-file-utils.h"
12
13namespace Inkscape {
14
15Glib::RefPtr<Gtk::FileDialog> create_file_dialog(Glib::ustring const &title,
16 Glib::ustring const &accept_label)
17{
18 auto const file_dialog = Gtk::FileDialog::create();
19 file_dialog->set_title(title);
20 file_dialog->set_accept_label(accept_label);
21 return file_dialog;
22}
23
24void set_filters(Gtk::FileDialog &file_dialog,
25 Glib::RefPtr<Gio::ListStore<Gtk::FileFilter>> const &filters)
26{
27 file_dialog.set_filters(filters);
28 if (filters->get_n_items() > 0) {
29 file_dialog.set_default_filter(filters->get_item(0));
30 }
31}
32
33void set_filter(Gtk::FileDialog &file_dialog, Glib::RefPtr<Gtk::FileFilter> const &filter)
34{
35 auto const filters = Gio::ListStore<Gtk::FileFilter>::create();
36 filters->append(filter);
37 set_filters(file_dialog, filters);
38}
39
40using StartMethod = void (Gtk::FileDialog::*)
41 (Gtk::Window &, Gio::SlotAsyncReady const &,
42 Glib::RefPtr<Gio::Cancellable> const &);
43
44using FinishMethod = Glib::RefPtr<Gio::File> (Gtk::FileDialog::*)
45 (Glib::RefPtr<Gio::AsyncResult> const &);
46
47[[nodiscard]] static auto run(Gtk::FileDialog &file_dialog, Gtk::Window &parent,
48 std::string &current_folder,
49 StartMethod const start, FinishMethod const finish)
50{
51 file_dialog.set_initial_folder(Gio::File::create_for_path(current_folder));
52
53 bool responded = false;
54 Glib::RefPtr<Gio::File> file;
55
56 (file_dialog.*start)(parent, [&](Glib::RefPtr<Gio::AsyncResult> const &result)
57 {
58 try {
59 responded = true;
60
61 file = (file_dialog.*finish)(result);
62 if (!file) {
63 return;
64 }
65
66 current_folder = file->get_parent()->get_path();
67 } catch (Gtk::DialogError const &error) {
68 if (error.code() == Gtk::DialogError::Code::DISMISSED) {
69 responded = true;
70 } else {
71 throw;
72 }
73 }
74 }, Glib::RefPtr<Gio::Cancellable>{});
75
76 auto const main_context = Glib::MainContext::get_default();
77 while (!responded) {
78 main_context->iteration(true);
79 }
80
81 return file;
82}
83
84Glib::RefPtr<Gio::File> choose_file_save(Glib::ustring const &title, Gtk::Window *parent,
85 Glib::RefPtr<Gio::ListStore<Gtk::FileFilter>> const &filters_model,
86 std::string const &file_name,
87 std::string &current_folder)
88{
89 if (!parent) return {};
90
91 if (current_folder.empty()) {
92 current_folder = Glib::get_home_dir();
93 }
94
95 auto const file_dialog = create_file_dialog(title, _("Save"));
96
97 if (filters_model) {
98 set_filters(*file_dialog, filters_model);
99 // for (int i = 0; i < filters_model->get_n_items(); ++i) {
100 // std::cout << filters_model->get_item(i)->get_name() << std::endl;
101 // }
102 }
103
104 file_dialog->set_initial_name(file_name);
105
106 return run(*file_dialog, *parent, current_folder,
107 &Gtk::FileDialog::save, &Gtk::FileDialog::save_finish);
108}
109
110Glib::RefPtr<Gio::File> choose_file_save(Glib::ustring const &title, Gtk::Window *parent,
111 Glib::ustring const &mime_type,
112 std::string const &file_name,
113 std::string &current_folder)
114{
115 if (!parent) return {};
116
117 auto filters_model = Gio::ListStore<Gtk::FileFilter>::create();
118 auto filter = Gtk::FileFilter::create();
119 if (!mime_type.empty()) {
120 auto filter = Gtk::FileFilter::create();
121 filter->add_mime_type(mime_type);
122 }
123
124 return choose_file_save(title, parent, filters_model, file_name, current_folder);
125}
126
127Glib::RefPtr<Gio::File> choose_file_open(Glib::ustring const &title, Gtk::Window *parent,
128 Glib::RefPtr<Gio::ListStore<Gtk::FileFilter>> const &filters_model,
129 std::string &current_folder,
130 Glib::ustring const &accept)
131{
132 if (!parent) return Glib::RefPtr<Gio::File>();
133
134 if (current_folder.empty()) {
135 current_folder = Glib::get_home_dir();
136 }
137
138 auto const file_dialog = create_file_dialog(title, accept.empty() ? _("Open") : accept);
139
140 if (filters_model) {
141 set_filters(*file_dialog, filters_model);
142 }
143
144 return run(*file_dialog, *parent, current_folder,
145 &Gtk::FileDialog::open, &Gtk::FileDialog::open_finish);
146}
147
148Glib::RefPtr<Gio::File> choose_file_open(Glib::ustring const &title, Gtk::Window *parent,
149 std::vector<Glib::ustring> const &mime_types,
150 std::string &current_folder,
151 Glib::ustring const &accept)
152{
153 auto filters_model = Gio::ListStore<Gtk::FileFilter>::create();
154 auto filter = Gtk::FileFilter::create();
155 for (auto const &t : mime_types) {
156 filter->add_mime_type(t);
157 }
158 filters_model->append(filter);
159
160 return choose_file_open(title, parent, filters_model, current_folder, accept);
161}
162
163Glib::RefPtr<Gio::File> choose_file_open(Glib::ustring const &title, Gtk::Window *parent,
164 std::vector<std::pair<Glib::ustring, Glib::ustring>> const &filters,
165 std::string &current_folder,
166 Glib::ustring const &accept)
167{
168 auto filters_model = Gio::ListStore<Gtk::FileFilter>::create();
169
170 auto all_supported = Gtk::FileFilter::create();
171 if (filters.size() > 1) {
172 all_supported->set_name(_("All Supported Formats"));
173 filters_model->append(all_supported);
174 }
175
176 for (auto const &f : filters) {
177 auto filter = Gtk::FileFilter::create();
178 filter->set_name(f.first);
179 filter->add_pattern(f.second);
180 filters_model->append(filter);
181 all_supported->add_pattern(f.second);
182 }
183
184 return choose_file_open(title, parent, filters_model, current_folder, accept);
185}
186
187// Open one or more image files.
188std::vector<Glib::RefPtr<Gio::File>> choose_file_open_images(Glib::ustring const &title,
189 Gtk::Window* parent,
190 std::string const &pref_path,
191 Glib::ustring const &accept)
192{
193 auto const file_dialog = create_file_dialog(title, accept);
194 auto filter_model = Inkscape::UI::Dialog::create_open_filters();
195 set_filters(*file_dialog, filter_model);
196
197 std::string current_folder;
198 Inkscape::UI::Dialog::get_start_directory(current_folder, pref_path, true);
199 if (current_folder.empty()) {
200 current_folder = Glib::get_home_dir();
201 }
202 file_dialog->set_initial_folder(Gio::File::create_for_path(current_folder));
203
204 bool responded = false;
205 std::vector<Glib::RefPtr<Gio::File>> files;
206
207 file_dialog->open_multiple(*parent, [&](Glib::RefPtr<Gio::AsyncResult> const &result)
208 {
209 try {
210 responded = true;
211
212 files = file_dialog->open_multiple_finish(result);
213 if (files.size() == 0) {
214 return;
215 }
216 if (files.size() == 1) {
217 // Save current_folder.
218 current_folder = files[0]->get_parent()->get_path();
219 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
220 prefs->setString(pref_path, current_folder);
221 }
222 } catch (Gtk::DialogError const &error) {
223 if (error.code() == Gtk::DialogError::Code::DISMISSED) {
224 responded = true;
225 } else {
226 throw;
227 }
228 }
229 }, Glib::RefPtr<Gio::Cancellable>{});
230
231 auto const main_context = Glib::MainContext::get_default();
232 while (!responded) {
233 main_context->iteration(true);
234 }
235
236 return files;
237}} // namespace Inkscape
238
239/*
240 Local Variables:
241 mode:c++
242 c-file-style:"stroustrup"
243 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
244 indent-tabs-mode:nil
245 fill-column:99
246 End:
247*/
248// vim:filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99:
Css & result
std::string file_name
static char const *const parent
Definition dir-util.cpp:70
Geom::Point start
Definition desktop.h:50
void get_start_directory(std::string &start_path, Glib::ustring const &prefs_path, bool try_document_dir)
Find the start directory for a file dialog.
Glib::RefPtr< Gio::ListStore< Gtk::FileFilter > > create_open_filters()
Create a Gtk::FileFilter for all image file types.
Helper class to stream background task notifications as a series of messages.
static auto run(Gtk::FileDialog &file_dialog, Gtk::Window &parent, std::string &current_folder, StartMethod const start, FinishMethod const finish)
Glib::RefPtr< Gtk::FileDialog > create_file_dialog(Glib::ustring const &title, Glib::ustring const &accept_label)
Create a Gtk::FileDialog with the given title and label for its default/accept button.
void set_filters(Gtk::FileDialog &file_dialog, Glib::RefPtr< Gio::ListStore< Gtk::FileFilter > > const &filters)
Set available filters to a given list, & default to its 1st filter (if any).
Glib::RefPtr< Gio::File > choose_file_save(Glib::ustring const &title, Gtk::Window *parent, Glib::RefPtr< Gio::ListStore< Gtk::FileFilter > > const &filters_model, std::string const &file_name, std::string &current_folder)
Synchronously run a Gtk::FileDialog to select a file for saving data.
void(Gtk::FileDialog::*)(Gtk::Window &, Gio::SlotAsyncReady const &, Glib::RefPtr< Gio::Cancellable > const &) StartMethod
std::vector< Glib::RefPtr< Gio::File > > choose_file_open_images(Glib::ustring const &title, Gtk::Window *parent, std::string const &pref_path, Glib::ustring const &accept)
Synchronously run a Gtk::FileDialog to open a one or more image files.
Glib::RefPtr< Gio::File > choose_file_open(Glib::ustring const &title, Gtk::Window *parent, Glib::RefPtr< Gio::ListStore< Gtk::FileFilter > > const &filters_model, std::string &current_folder, Glib::ustring const &accept)
Synchronously run a Gtk::FileDialog to open a single file for reading data.
void set_filter(Gtk::FileDialog &file_dialog, Glib::RefPtr< Gtk::FileFilter > const &filter)
Set the available filters & the default filter, to the single filter passed.
Glib::RefPtr< Gio::File >(Gtk::FileDialog::*)(Glib::RefPtr< Gio::AsyncResult > const &) FinishMethod
Singleton class to access the preferences file in a convenient way.