Inkscape
Vector Graphics Editor
export-lists.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/* Authors:
3 * Anshudhar Kumar Singh <anshudhar2001@gmail.com>
4 *
5 * Copyright (C) 2021 Authors
6 *
7 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
8 */
9
10#include "export-lists.h"
11
12#include <glibmm/i18n.h>
13#include <glibmm/convert.h> // filename_from_utf8
14#include <glibmm/ustring.h>
15#include <gtkmm/builder.h>
16#include <gtkmm/label.h>
17#include <gtkmm/menubutton.h>
18#include <gtkmm/popover.h>
19#include <gtkmm/spinbutton.h>
20#include <gtkmm/viewport.h>
21
22#include "extension/db.h"
23#include "extension/output.h"
24#include "file.h"
25#include "helper/png-write.h"
26#include "io/sys.h"
27#include "preferences.h"
28#include "ui/icon-loader.h"
29#include "ui/builder-utils.h"
30#include "util/units.h"
31
32namespace Inkscape::UI::Dialog {
33
35{
36 init();
37}
38
39ExtensionList::ExtensionList(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade)
40 : Gtk::ComboBoxText{cobject}
41{
42 init();
43}
44
46
48{
49 _builder = create_builder("dialog-export-prefs.glade");
50 _pref_button = &get_widget<Gtk::MenuButton>(_builder, "pref_button");
51 _pref_popover = &get_widget<Gtk::Popover> (_builder, "pref_popover");
52 _pref_holder = &get_widget<Gtk::Viewport> (_builder, "pref_holder");
53
54 _popover_signal = _pref_popover->signal_show().connect([=, this]() {
55 _pref_holder->unset_child();
56 if (auto ext = getExtension()) {
57 if (auto gui = ext->autogui(nullptr, nullptr)) {
58 _pref_holder->set_child(*gui);
59 _pref_popover->grab_focus();
60 }
61 }
62 });
63
65 _watch_pref = prefs->createObserver("/dialogs/export/show_all_extensions", [this]() { setup(); });
66 // limit size of the combobox
67 auto cell_renderer = dynamic_cast<Gtk::CellRendererText*>(get_first_cell());
68 cell_renderer->set_fixed_size(125, -1);
69 cell_renderer->property_wrap_mode().set_value(Pango::WrapMode::WORD);
70 cell_renderer->property_wrap_width().set_value(5);
71}
72
74{
75 bool has_prefs = false;
76 if (auto ext = getExtension()) {
77 has_prefs = (ext->widget_visible_count() > 0);
78 }
79 _pref_button->set_sensitive(has_prefs);
80}
81
83{
84 this->remove_all();
85
87 bool export_all = prefs->getBool("/dialogs/export/show_all_extensions", false);
88
91 for (auto omod : extensions) {
92 auto oid = Glib::ustring(omod->get_id());
93 if (!export_all && !omod->is_raster() && !omod->is_exported())
94 continue;
95 // Comboboxes don't have a disabled row property
96 if (omod->deactivated())
97 continue;
98 this->append(oid, omod->get_filetypename());
99 // Record extensions map for filename-to-combo selections
100 auto ext = omod->get_extension();
101 if (!ext_to_mod[ext]) {
102 // Some extensions have multiple of the same extension (for example PNG)
103 // we're going to pick the first in the found list to back-link to.
104 ext_to_mod[ext] = omod;
105 }
106 }
107 this->set_active_id(SP_MODULE_KEY_RASTER_PNG);
108}
109
114{
115 return dynamic_cast<Inkscape::Extension::Output *>(Inkscape::Extension::db.get(this->get_active_id().c_str()));
116}
117
122{
123 if (auto ext = getExtension()) {
124 return Glib::filename_from_utf8(ext->get_extension());
125 }
126 return "";
127}
128
132void ExtensionList::removeExtension(std::string &filename)
133{
134 auto ext = Inkscape::IO::get_file_extension(filename);
135 if (ext_to_mod[ext]) {
136 filename.erase(filename.size()-ext.size());
137 }
138}
139
140void ExtensionList::setExtensionFromFilename(std::string const &filename)
141{
142 auto ext = Inkscape::IO::get_file_extension(filename);
143 if (ext != getFileExtension()) {
144 if (auto omod = ext_to_mod[ext]) {
145 this->set_active_id(omod->get_id());
146 }
147 }
148}
149
151{
152 if (_initialised) {
153 return;
154 }
155 _initialised = true;
157 default_dpi = prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE);
158
159 auto const add_button = Gtk::make_managed<Gtk::Button>();
160 Glib::ustring label = _("Add Export");
161 add_button->set_label(label);
162 this->attach(*add_button, 0, 0, 5, 1);
163
164 this->insert_row(0);
165
166 auto const suffix_label = Gtk::make_managed<Gtk::Label>(_("Suffix"));
167 this->attach(*suffix_label, _suffix_col, 0, 1, 1);
168 suffix_label->set_visible(true);
169
170 auto const extension_label = Gtk::make_managed<Gtk::Label>(_("Format"));
171 this->attach(*extension_label, _extension_col, 0, 2, 1);
172 extension_label->set_visible(true);
173
174 auto const dpi_label = Gtk::make_managed<Gtk::Label>(_("DPI"));
175 this->attach(*dpi_label, _dpi_col, 0, 1, 1);
176 dpi_label->set_visible(true);
177
178 append_row();
179
180 add_button->signal_clicked().connect(sigc::mem_fun(*this, &ExportList::append_row));
181 add_button->set_hexpand(true);
182 add_button->set_visible(true);
183
184 this->set_row_spacing(5);
185 this->set_column_spacing(2);
186}
187
188void ExportList::removeExtension(std::string &filename)
189{
190 ExtensionList *extension_cb = dynamic_cast<ExtensionList *>(this->get_child_at(_extension_col, 1));
191 if (extension_cb) {
192 extension_cb->removeExtension(filename);
193 return;
194 }
195}
196
198{
199 int current_row = _num_rows + 1; // because we have label row at top
200 this->insert_row(current_row);
201
202 auto const suffix = Gtk::make_managed<Gtk::Entry>();
203 this->attach(*suffix, _suffix_col, current_row, 1, 1);
204 suffix->set_width_chars(2);
205 suffix->set_hexpand(true);
206 suffix->set_placeholder_text(_("Suffix"));
207 suffix->set_visible(true);
208
209 auto const extension = Gtk::make_managed<ExtensionList>();
210 auto const dpi_sb = Gtk::make_managed<Gtk::SpinButton>();
211
212 extension->setup();
213 extension->set_visible(true);
214 this->attach(*extension, _extension_col, current_row, 1, 1);
215 this->attach(*extension->getPrefButton(), _prefs_col, current_row, 1, 1);
216
217 // Disable DPI when not using a raster image output
218 extension->signal_changed().connect([=]() {
219 if (auto ext = extension->getExtension()) {
220 dpi_sb->set_sensitive(ext->is_raster());
221 }
222 });
223
224 dpi_sb->set_digits(2);
225 dpi_sb->set_increments(0.1, 1.0);
226 dpi_sb->set_range(1.0, 100000.0);
227 dpi_sb->set_value(default_dpi);
228 dpi_sb->set_sensitive(true);
229 dpi_sb->set_width_chars(6);
230 dpi_sb->set_max_width_chars(6);
231 dpi_sb->set_visible(true);
232 this->attach(*dpi_sb, _dpi_col, current_row, 1, 1);
233
234 auto const pIcon = Gtk::manage(sp_get_icon_image("window-close", Gtk::IconSize::NORMAL));
235 auto const delete_btn = Gtk::make_managed<Gtk::Button>();
236 delete_btn->set_has_frame(false);
237 delete_btn->set_child(*pIcon);
238 this->attach(*delete_btn, _delete_col, current_row, 1, 1);
239 delete_btn->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &ExportList::delete_row), delete_btn));
240
241 _num_rows++;
242}
243
244void ExportList::delete_row(Gtk::Widget *widget)
245{
246 if (widget == nullptr) {
247 return;
248 }
249 if (_num_rows <= 1) {
250 return;
251 }
252 int row, ignore;
253 query_child(*widget, ignore, row, ignore, ignore);
254 remove_row(row);
255 _num_rows--;
256 if (_num_rows <= 1) {
257 auto const d_button_0 = this->get_child_at(_delete_col, 1);
258 if (d_button_0) {
259 d_button_0->set_visible(false);
260 }
261 }
262}
263
264std::string ExportList::get_suffix(int row)
265{
266 std::string suffix = "";
267 Gtk::Entry *entry = dynamic_cast<Gtk::Entry *>(this->get_child_at(_suffix_col, row + 1));
268 if (entry == nullptr) {
269 return suffix;
270 }
271 suffix = Glib::filename_from_utf8(entry->get_text());
272 return suffix;
273}
275{
276 ExtensionList *extension_cb = dynamic_cast<ExtensionList *>(this->get_child_at(_extension_col, row + 1));
277 return extension_cb->getExtension();
278}
279
280double ExportList::get_dpi(int row)
281{
282 double dpi = default_dpi;
283 auto spin_sb = dynamic_cast<Gtk::SpinButton *>(this->get_child_at(_dpi_col, row + 1));
284 if (spin_sb == nullptr) {
285 return dpi;
286 }
287 dpi = spin_sb->get_value();
288 return dpi;
289}
290
291} // namespace Inkscape::UI::Dialog
292
293/*
294 Local Variables:
295 mode:c++
296 c-file-style:"stroustrup"
297 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
298 indent-tabs-mode:nil
299 fill-column:99
300 End:
301*/
302// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Gtk builder utilities.
std::list< Output * > OutputList
Definition: db.h:58
OutputList & get_output_list(OutputList &ou_list)
Creates a list of all the Output extensions.
Definition: db.cpp:256
Extension * get(const gchar *key) const
This function looks up a Inkscape::Extension::Extension by using its unique id. It then returns a ref...
Definition: db.cpp:101
Preference storage class.
Definition: preferences.h:63
bool getBool(Glib::ustring const &pref_path, bool def=false)
Retrieve a Boolean value.
Definition: preferences.h:363
double getDouble(Glib::ustring const &pref_path, double def=0.0, Glib::ustring const &unit="")
Retrieve a floating point value.
Definition: preferences.h:421
static Preferences * get()
Access the singleton Preferences object.
Definition: preferences.h:599
std::unique_ptr< PreferencesObserver > createObserver(Glib::ustring path, std::function< void(const Preferences::Entry &new_value)> callback)
Create an observer watching preference 'path' and calling provided function when preference changes.
void removeExtension(std::string &filename)
Inkscape::Preferences * prefs
Definition: export-lists.h:102
std::string get_suffix(int row)
Inkscape::Extension::Output * getExtension(int row)
void delete_row(Gtk::Widget *widget)
Glib::RefPtr< Gtk::Builder > _builder
Definition: export-lists.h:75
Inkscape::Extension::Output * getExtension()
Returns the Output extension currently selected in this dropdown.
void removeExtension(std::string &filename)
Removes the file extension, if it's one of the extensions in the list.
std::map< std::string, Inkscape::Extension::Output * > ext_to_mod
Definition: export-lists.h:72
std::string getFileExtension()
Returns the file extension (file ending) of the currently selected extension.
void setExtensionFromFilename(std::string const &filename)
Gtk::Image * sp_get_icon_image(Glib::ustring const &icon_name, int size)
Definition: icon-loader.cpp:27
Icon Loader.
Definition: desktop.h:51
DB db
This is the actual database object.
Definition: db.cpp:32
Glib::ustring get_file_extension(Glib::ustring const &path)
Definition: sys.cpp:207
Dialog code.
Definition: desktop.h:118
Glib::RefPtr< Gtk::Builder > create_builder(const char *filename)
static void append(std::vector< T > &target, std::vector< T > &&source)
Definition: shortcuts.cpp:515
Singleton class to access the preferences file in a convenient way.