Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
template.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Authors:
4 * Martin Owens <doctormo@geek-2.com>
5 *
6 * Copyright (C) 2022 Authors
7 *
8 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
9 */
10
11#include "template.h"
12
13#include <string>
14#include <glibmm/i18n.h>
15#include <glibmm/fileutils.h>
16#include <glibmm/miscutils.h>
17#include <glibmm/regex.h>
18
19#include "document.h"
20#include "document-undo.h"
22#include "io/file.h"
23#include "io/resource.h"
25#include "xml/repr.h"
26
27using namespace Inkscape::IO::Resource;
28
29namespace Inkscape {
30namespace Extension {
31
35TemplatePreset::TemplatePreset(Template *mod, const Inkscape::XML::Node *repr, TemplatePrefs const prefs, int priority)
36 : _mod(mod)
37 , _prefs(prefs)
38 , _name("Unnamed")
39 , _label("")
40 , _visibility(mod->get_visibility())
41 , _priority(priority)
42{
43 // Default icon and priority aren't a prefs, though they may at first look like it.
44 _icon = mod->get_icon();
45 _category = mod->get_category();
46
47 if (repr) {
48 for (const auto &iter : repr->attributeList()) {
49 std::string name = g_quark_to_string(iter.key);
50 std::string value = std::string(iter.value);
51 if (name == "name")
52 _name = value.empty() ? "?" : value;
53 else if (name == "label")
54 _label = value;
55 else if (name == "desc")
56 _desc = value;
57 else if (name == "icon")
58 _icon = value;
59 else if (name == "priority")
60 _priority = std::stoi(value);
61 else if (name == "visibility") {
62 _visibility = mod->parse_visibility(value);
63 } else {
64 _prefs[name] = value;
65 }
66 }
67 }
68 // Generate a standard name that can be used to recall this preset.
69 _key = std::string(mod->get_id()) + "." + _name;
70 transform(_key.begin(), _key.end(), _key.begin(), ::tolower);
71}
72
73/*
74 * Return the best full path to the icon.
75 *
76 * 1. Searches the template/icons folder.
77 * 2. Searches the inx folder location (if any)
78 * 3. Returns a default icon file path.
79 */
81{
82 static auto default_icon = _get_icon_path("default");
83 auto filename = _get_icon_path(_icon);
84 return filename.empty() ? default_icon : filename;
85}
86
87std::string TemplatePreset::_get_icon_path(std::string const &name) const
88{
89 auto filename = name + ".svg";
90
91 auto const filepath = Glib::build_filename("icons", filename);
92 auto const fullpath = get_filename(TEMPLATES, filepath.c_str(), false, true);
93 if (!fullpath.empty()) return fullpath;
94
95 auto base = _mod->get_base_directory();
96 if (!base.empty()) {
97 auto base_icon = Glib::build_filename(base, "icons", filename);
98 if (Glib::file_test(base_icon, Glib::FileTest::EXISTS)) {
99 return base_icon;
100 }
101 }
102 return {};
103}
104
115{
117 _add_prefs(others);
118
119 bool ret = _mod->prefs();
120 for (auto pref : _prefs) {
121 try {
122 _mod->set_param_hidden(pref.first.c_str(), false);
124 // pass
125 }
126 }
127 return ret;
128}
129
134{
135 for (auto pref : prefs) {
136 try {
137 _mod->set_param_any(pref.first.c_str(), pref.second);
138 _mod->set_param_hidden(pref.first.c_str(), true);
140 // pass
141 }
142 }
143}
144
150std::unique_ptr<SPDocument> TemplatePreset::new_from_template(TemplatePrefs const &others)
151{
152 if (setup_prefs(others)) {
153 return _mod->new_from_template();
154 }
155 return nullptr;
156}
157
162{
163 if (_mod->can_resize() && setup_prefs(others)) {
165 }
166}
167
171bool TemplatePreset::match_size(double width, double height, const TemplatePrefs &others)
172{
175 _add_prefs(others);
176 return _mod->imp->match_template_size(_mod, width, height);
177 }
178 return false;
179}
180
186Template::Template(Inkscape::XML::Node *in_repr, ImplementationHolder implementation, std::string *base_directory)
187 : Extension(in_repr, std::move(implementation), base_directory)
188{
189 if (!repr) {
190 return;
191 }
192 auto const t_node = sp_repr_lookup_name(repr, INKSCAPE_EXTENSION_NS "template", 1);
193 if (!t_node) {
194 return;
195 }
196 _source = sp_repr_lookup_content(repr, INKSCAPE_EXTENSION_NS "source");
197 _desc = sp_repr_lookup_content(repr, INKSCAPE_EXTENSION_NS "description");
198 _category = sp_repr_lookup_content(repr, INKSCAPE_EXTENSION_NS "category", N_("Other"));
199
200 // Remember any global/default preferences from the root node.
202 for (const auto &iter : t_node->attributeList()) {
203 std::string name = g_quark_to_string(iter.key);
204 std::string value = std::string(iter.value);
205 if (name == "icon") {
206 _icon = value;
207 } else if (name == "visibility") {
209 } else if (name == "priority") {
210 set_sort_priority(std::stoi(value));
211 } else {
212 prefs[name] = value;
213 }
214 }
215
216 // Default priority will increment to keep inx order where possible.
217 int priority = get_sort_priority();
218 for (auto p_node : sp_repr_lookup_name_many(t_node, INKSCAPE_EXTENSION_NS "preset")) {
219 auto preset = new TemplatePreset(this, p_node, prefs, priority);
220 _presets.emplace_back(preset);
221 priority += 1;
222 // If any preset is resizable, then the module is considered to support it.
223 if ( preset->is_visible(TEMPLATE_SIZE_SEARCH)
224 || preset->is_visible(TEMPLATE_SIZE_LIST)) {
225 _can_resize = true;
226 }
227 }
228 // Keep presets sorted internally for simple use cases.
229 std::sort(std::begin(_presets), std::end(_presets),
230 [](std::shared_ptr<TemplatePreset> const &a,
231 std::shared_ptr<TemplatePreset> const &b) {
232 return a->get_sort_priority() < b->get_sort_priority();
233 });
234}
235
239int Template::parse_visibility(const std::string &value)
240{
241 int ret = 0;
242 auto values = Glib::Regex::split_simple("," , value.c_str());
243 for (auto const &val : values) {
244 ret |= (val == "icon") * TEMPLATE_NEW_ICON;
245 ret |= (val == "list") * TEMPLATE_SIZE_LIST;
246 ret |= (val == "search") * TEMPLATE_SIZE_SEARCH;
247 ret |= (val == "all") * TEMPLATE_ALL;
248 }
249 return ret;
250}
251
261{
262 if (_category.empty()) {
263 return false;
264 }
265 return Extension::check();
266}
267
274std::unique_ptr<SPDocument> Template::new_from_template()
275{
276 if (!loaded()) {
278 }
279 if (!loaded()) {
280 return nullptr;
281 }
282
283 auto doc = imp->new_from_template(this);
284 DocumentUndo::clearUndo(doc.get());
285 doc->setModifiedSinceSave(false);
286 return doc;
287}
288
296{
297 if (!loaded()) {
299 }
300 if (!loaded()) {
301 return;
302 }
303 imp->resize_to_template(this, doc, page);
304}
305
310{
311 auto all_presets = _presets;
312 imp->get_template_presets(this, all_presets);
313
314 TemplatePresets ret;
315 for (auto preset : all_presets) {
316 if (preset->is_visible(visibility)) {
317 ret.push_back(preset);
318 }
319 }
320 return ret;
321}
322
326std::shared_ptr<TemplatePreset> Template::get_preset(const std::string &key)
327{
328 for (auto preset : get_presets()) {
329 if (preset->get_key() == key) {
330 return preset;
331 }
332 }
333 return nullptr;
334}
335
339std::shared_ptr<TemplatePreset> Template::get_preset(double width, double height)
340{
341 for (auto preset : get_presets()) {
342 if (preset->match_size(width, height)) {
343 return preset;
344 }
345 }
346 return nullptr;
347}
348
352std::shared_ptr<TemplatePreset> Template::get_any_preset(const std::string &key)
353{
356 for (auto tmod : extensions) {
357 if (auto preset = tmod->get_preset(key)) {
358 return preset;
359 }
360 }
361 return nullptr;
362}
363
367std::shared_ptr<TemplatePreset> Template::get_any_preset(double width, double height)
368{
371 for (auto tmod : extensions) {
372 if (!tmod->can_resize())
373 continue;
374 if (auto preset = tmod->get_preset(width, height)) {
375 return preset;
376 }
377 }
378 return nullptr;
379}
380
384Glib::RefPtr<Gio::File> Template::get_template_filename() const
385{
386 Glib::RefPtr<Gio::File> file;
387
388 if (!_source.empty()) {
389 auto const filename = get_filename(TEMPLATES, _source.c_str(), true);
390 file = Gio::File::create_for_path(filename);
391 }
392 if (!file) {
393 // Failure to open, so open up a new document instead.
394 auto const filename = get_filename(TEMPLATES, "default.svg", true);
395 file = Gio::File::create_for_path(filename);
396
397 if (!file) {
398 g_error("Can not find default.svg template!");
399 }
400 }
401 return file;
402}
403
407std::unique_ptr<SPDocument> Template::get_template_document() const
408{
409 if (auto file = get_template_filename()) {
410 return ink_file_new(file->get_path());
411 }
412 return nullptr;
413}
414
415} // namespace Extension
416} // namespace Inkscape
417
418/*
419 Local Variables:
420 mode:c++
421 c-file-style:"stroustrup"
422 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
423 indent-tabs-mode:nil
424 fill-column:99
425 End:
426*/
427// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
TODO: insert short description here.
uint64_t page
Definition canvas.cpp:171
static void clearUndo(SPDocument *document)
TemplateList & get_template_list(TemplateList &ou_list)
Create a list of all the Template extensions.
Definition db.cpp:228
std::list< Template * > TemplateList
Definition db.h:57
An error class for when a parameter is looked for that just simply doesn't exist.
Definition extension.h:215
The object that is the basis for the Extension system.
Definition extension.h:133
@ STATE_LOADED
The extension has been loaded successfully.
Definition extension.h:137
Inkscape::XML::Node * repr
The XML description of the Extension.
Definition extension.h:156
ImplementationHolder imp
An Implementation object provides the actual implementation of the Extension.
Definition extension.h:162
virtual bool check()
A function to check the validity of the extension.
void set_state(state_t in_state)
A function to set whether the extension should be loaded or unloaded.
auto const & get_base_directory() const
Definition extension.h:192
void set_param_hidden(char const *name, bool hidden)
bool loaded()
A quick function to test the state of the extension.
void set_sort_priority(int priority)
Definition extension.h:200
virtual bool prefs()
Create a dialog for preference for this extension.
void set_param_any(char const *name, std::string const &value)
Parses the given string value and sets a parameter identified by name.
TemplatePreset(Template *mod, const Inkscape::XML::Node *repr, TemplatePrefs prefs={}, int priority=0)
Parse the inx xml node for preset information.
Definition template.cpp:35
void _add_prefs(const TemplatePrefs &prefs)
Called by setup_prefs to save the given prefs into this extension.
Definition template.cpp:133
std::string _get_icon_path(std::string const &name) const
Definition template.cpp:87
bool setup_prefs(const TemplatePrefs &others={})
Setup the preferences and ask the user to fill in the remaineder.
Definition template.cpp:114
std::unique_ptr< SPDocument > new_from_template(TemplatePrefs const &others={})
Generate a new document from this preset.
Definition template.cpp:150
std::string get_icon_path() const
Definition template.cpp:80
void resize_to_template(SPDocument *doc, SPPage *page, const TemplatePrefs &others={})
Resize the given page to however the page format requires it to be.
Definition template.cpp:161
bool match_size(double width, double height, const TemplatePrefs &others={})
Reverse match for templates, allowing page duplication and labeling.
Definition template.cpp:171
bool is_visible(TemplateShow mode)
Definition template.h:63
static std::shared_ptr< TemplatePreset > get_any_preset(const std::string &key)
Return the template preset based on the key from any template class (static method).
Definition template.cpp:352
void resize_to_template(SPDocument *doc, SPPage *page)
Takes an existing page and resizes it to the required dimentions.
Definition template.cpp:295
Glib::RefPtr< Gio::File > get_template_filename() const
Get the template filename, or return the default template.
Definition template.cpp:384
Template(Inkscape::XML::Node *in_repr, ImplementationHolder implementation, std::string *base_directory)
Builds a Template object from a XML description.
Definition template.cpp:186
bool check() override
Validate this extension.
Definition template.cpp:260
std::unique_ptr< SPDocument > new_from_template()
This function creates a document from a template.
Definition template.cpp:274
std::shared_ptr< TemplatePreset > get_preset(const std::string &key)
Return the template preset based on the key from this template class.
Definition template.cpp:326
static int parse_visibility(const std::string &value)
Parse the expected value for the visibility value, turn into enum.
Definition template.cpp:239
std::unique_ptr< SPDocument > get_template_document() const
Get the raw document svg for this template (pre-processing).
Definition template.cpp:407
TemplatePresets get_presets(TemplateShow visibility=TEMPLATE_ANY) const
Return a list of all template presets.
Definition template.cpp:309
Interface for refcounted XML nodes.
Definition node.h:80
virtual const AttributeVector & attributeList() const =0
Get a list of the node's attributes.
Typed SVG document implementation.
Definition document.h:103
TODO: insert short description here.
std::unique_ptr< SPDocument > ink_file_new(std::string const &Template)
Create a blank document, remove any template data.
Definition file.cpp:34
DB db
This is the actual database object.
Definition db.cpp:32
std::map< std::string, std::string > TemplatePrefs
Definition template.h:45
std::vector< std::shared_ptr< TemplatePreset > > TemplatePresets
std::string get_filename(Type type, char const *filename, bool localized, bool silent)
Definition resource.cpp:170
Helper class to stream background task notifications as a series of messages.
STL namespace.
static cairo_user_data_key_t key
std::vector< Inkscape::XML::Node const * > sp_repr_lookup_name_many(Inkscape::XML::Node const *repr, gchar const *name, gint maxdepth)
Glib::ustring sp_repr_lookup_content(Inkscape::XML::Node const *repr, gchar const *name, Glib::ustring otherwise)
Inkscape::XML::Node const * sp_repr_lookup_name(Inkscape::XML::Node const *repr, gchar const *name, gint maxdepth)
C facade to Inkscape::XML::Node.
Inkscape::IO::Resource - simple resource API.
double height
double width
Glib::ustring name
Definition toolbars.cpp:55