Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
xml-tree.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
6/* Authors:
7 * Lauris Kaplinski <lauris@kaplinski.com>
8 * MenTaLguY <mental@rydia.net>
9 * bulia byak <buliabyak@users.sf.net>
10 * Johan Engelen <goejendaagh@zonnet.nl>
11 * David Turner
12 * Jon A. Cruz <jon@joncruz.org>
13 * Abhishek Sharma
14 * Mike Kowalski
15 *
16 * Copyright (C) l99-2006 Authors
17 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
18 *
19 */
20
21#include "xml-tree.h"
22
23#include <glibmm/i18n.h>
24#include <glibmm/ustring.h>
25#include <glibmm/variant.h>
26#include <giomm/simpleactiongroup.h>
27#include <gtkmm/button.h>
28#include <gtkmm/box.h>
29#include <gtkmm/enums.h>
30#include <gtkmm/entry.h>
31#include <gtkmm/image.h>
32#include <gtkmm/menubutton.h>
33#include <gtkmm/object.h>
34#include <gtkmm/paned.h>
35#include <gtkmm/scrolledwindow.h>
36#include <gtkmm/treeview.h>
37
38#include "desktop.h"
39#include "document.h"
40#include "document-undo.h"
41#include "inkscape.h"
42#include "layer-manager.h"
43#include "selection.h"
44#include "preferences.h"
45#include "object/sp-root.h"
46#include "ui/builder-utils.h"
47#include "ui/dialog-events.h"
48#include "ui/icon-loader.h"
49#include "ui/icon-names.h"
50#include "ui/pack.h"
51#include "ui/syntax.h"
52#include "ui/tools/tool-base.h"
53#include "ui/util.h"
55#include "util/trim.h"
56
57namespace {
58
64void paned_set_vertical(Gtk::Paned &paned, bool vertical)
65{
66 auto& first = *paned.get_start_child();
67 auto& second = *paned.get_end_child();
68 const int space = 1;
69 paned.set_resize_start_child(vertical);
70 first.set_margin_bottom(vertical ? space : 0);
71 first.set_margin_end(vertical ? 0 : space);
72 second.set_margin_top(vertical ? space : 0);
73 second.set_margin_start(vertical ? 0 : space);
74 paned.set_resize_end_child(!vertical);
75 paned.set_orientation(vertical ? Gtk::Orientation::VERTICAL : Gtk::Orientation::HORIZONTAL);
76}
77
78} // namespace
79
80namespace Inkscape::UI::Dialog {
81
83 : DialogBase("/dialogs/xml/", "XMLEditor")
84 , _builder(create_builder("dialog-xml.glade"))
85 , _paned(get_widget<Gtk::Paned>(_builder, "pane"))
86 , xml_element_new_button(get_widget<Gtk::Button>(_builder, "new-elem"))
87 , xml_text_new_button(get_widget<Gtk::Button>(_builder, "new-text"))
88 , xml_node_delete_button(get_widget<Gtk::Button>(_builder, "del"))
89 , xml_node_duplicate_button(get_widget<Gtk::Button>(_builder, "dup"))
90 , unindent_node_button(get_widget<Gtk::Button>(_builder, "unindent"))
91 , indent_node_button(get_widget<Gtk::Button>(_builder, "indent"))
92 , lower_node_button(get_widget<Gtk::Button>(_builder, "lower"))
93 , raise_node_button(get_widget<Gtk::Button>(_builder, "raise"))
94 , _syntax_theme("/theme/syntax-color-theme")
95 , _mono_font("/dialogs/xml/mono-font", false)
96{
97 /* tree view */
98 _xml_treeview = Gtk::make_managed<Inkscape::UI::Widget::XmlTreeView>();
99 _xml_treeview->set_tooltip_text( _("Drag to reorder nodes") );
100
101 Gtk::ScrolledWindow& tree_scroller = get_widget<Gtk::ScrolledWindow>(_builder, "tree-wnd");
102 tree_scroller.set_child(*_xml_treeview);
103 fix_inner_scroll(tree_scroller);
104
106
107 /* attributes */
108 attributes = Gtk::make_managed<AttrDialog>();
109 attributes->set_margin_top(0);
110 attributes->set_margin_bottom(0);
111 attributes->set_margin_start(0);
112 attributes->set_margin_end(0);
113 attributes->get_scrolled_window().set_has_frame(true);
114 attributes->set_visible(true);
115 attributes->get_status_box().set_visible(false);
116 _paned.set_end_child(*attributes);
117 _paned.set_resize_end_child(true);
118
119 /* Signal handlers */
120 _xml_treeview->get_selection()->signal_changed().connect([this]() {
121 if (blocked || !getDesktop()) {
122 return;
123 }
124 if (!_tree_select_idle) {
125 // Defer the update after all events have been processed.
126 _tree_select_idle = Glib::signal_idle().connect(sigc::mem_fun(*this, &XmlTree::deferred_on_tree_select_row));
127 }
128 });
129
130 xml_element_new_button.signal_clicked().connect(sigc::mem_fun(*this, &XmlTree::cmd_new_element_node));
131 xml_text_new_button.signal_clicked().connect(sigc::mem_fun(*this, &XmlTree::cmd_new_text_node));
132 xml_node_duplicate_button.signal_clicked().connect(sigc::mem_fun(*this, &XmlTree::cmd_duplicate_node));
133 xml_node_delete_button.signal_clicked().connect(sigc::mem_fun(*this, &XmlTree::cmd_delete_node));
134 unindent_node_button.signal_clicked().connect(sigc::mem_fun(*this, &XmlTree::cmd_unindent_node));
135 indent_node_button.signal_clicked().connect(sigc::mem_fun(*this, &XmlTree::cmd_indent_node));
136 raise_node_button.signal_clicked().connect(sigc::mem_fun(*this, &XmlTree::cmd_raise_node));
137 lower_node_button.signal_clicked().connect(sigc::mem_fun(*this, &XmlTree::cmd_lower_node));
138
139 set_name("XMLAndAttributesDialog");
140 set_spacing(0);
141
142 int panedpos = prefs->getInt("/dialogs/xml/panedpos", 200);
143 _paned.property_position() = panedpos;
144 _paned.property_position().signal_changed().connect(sigc::mem_fun(*this, &XmlTree::_resized));
145
146 append(_bin);
147 _bin.set_child(get_widget<Gtk::Box>(_builder, "main"));
148 _bin.set_expand(true);
149
150 int min_width = 0, dummy;
151 measure(Gtk::Orientation::HORIZONTAL, -1, min_width, dummy, dummy, dummy);
152
153 auto auto_arrange_panels = [=, this] (int width, int height) {
154 // skip bogus sizes
155 if (width < 10 || height < 10) return;
156
157 // minimal width times fudge factor to arrive at "narrow" dialog with automatic vertical layout:
158 bool const narrow = width < min_width * 1.5;
159 paned_set_vertical(_paned, narrow);
160 };
161
162 auto arrange_panels = [=, this] (DialogLayout layout, int width, int height) {
163 switch (layout) {
164 case Auto:
165 auto_arrange_panels(width, height);
166 break;
167 case Horizontal:
168 paned_set_vertical(_paned, false);
169 break;
170 case Vertical:
171 paned_set_vertical(_paned, true);
172 break;
173 }
174 };
175
176 _bin.connectBeforeResize([=, this] (int width, int height, int) {
177 arrange_panels(_layout, width, height);
178 });
179
180 auto& popup = get_widget<Gtk::MenuButton>(_builder, "layout-btn");
181 popup.set_has_tooltip();
182 popup.signal_query_tooltip().connect([this](int x, int y, bool kbd, const Glib::RefPtr<Gtk::Tooltip>& tooltip){
183 auto tip = "";
184 switch (_layout) {
185 case Auto: tip = _("Automatic panel layout:\nchanges with dialog size");
186 break;
187 case Horizontal: tip = _("Horizontal panel layout");
188 break;
189 case Vertical: tip = _("Vertical panel layout");
190 break;
191 }
192 tooltip->set_text(tip);
193 return true;
194 }, true);
195
196 auto set_layout = [=, this] (DialogLayout layout) {
197 Glib::ustring icon = "layout-auto";
198 if (layout == Horizontal) {
199 icon = "layout-horizontal";
200 } else if (layout == Vertical) {
201 icon = "layout-vertical";
202 }
203 get_widget<Gtk::MenuButton>(_builder, "layout-btn").set_icon_name(icon + "-symbolic");
204 prefs->setInt("/dialogs/xml/layout", layout);
205 arrange_panels(layout, get_width(), get_height());
206 _layout = layout;
207 };
208
209 _layout = static_cast<DialogLayout>(prefs->getIntLimited("/dialogs/xml/layout", Auto, Auto, Vertical));
210 auto action_group = Gio::SimpleActionGroup::create();
211 auto action = action_group->add_action_radio_integer("layout", _layout);
212 action->property_state().signal_changed().connect([=, &popup]
213 {
214 popup.set_active(false);
215 int target; action->get_state(target); set_layout(static_cast<DialogLayout>(target));
216 });
217 insert_action_group("xml-tree", std::move(action_group));
218 set_layout(_layout);
219
220 // establish initial layout to prevent unwanted panels resize in auto layout mode
221 paned_set_vertical(_paned, true);
222
223 _syntax_theme.action = [this]() {
225 // rebuild tree to change markup
226 rebuildTree();
227 };
228
230
231 _mono_font.action = [this]() {
232 Glib::ustring mono("mono-font");
233 if (_mono_font) {
234 _xml_treeview->add_css_class(mono);
235 } else {
236 _xml_treeview->remove_css_class(mono);
237 }
239 };
241
242 auto renderer = _xml_treeview->get_renderer();
243 renderer->signal_editing_canceled().connect([this]() {
244 stopNodeEditing(false, "", "");
245 });
246
247 renderer->signal_edited().connect([this](const Glib::ustring& path, const Glib::ustring& name) {
248 stopNodeEditing(true, path, name);
249 });
250
251 renderer->signal_editing_started().connect([this](Gtk::CellEditable* cell, const Glib::ustring& path) {
252 startNodeEditing(cell, path);
253 });
254}
255
260
268
270{
272 prefs->setInt("/dialogs/xml/panedpos", _paned.property_position());
273}
274
276{
277 _tree_select_idle.disconnect();
278}
279
281{
283 if (auto document = getDocument()) {
284 // TODO: Why is this a document property?
286
289 } else {
290 _xml_treeview->build_tree(nullptr);
291 set_tree_select(nullptr);
292 }
293}
294
296{
297 if (!blocked++) {
300 }
301 blocked--;
302}
303
305{
306 selected_repr = repr; // Can be nullptr.
307
308 if (auto document = getDocument()) {
310 }
311
312 _xml_treeview->select_node(repr, edit);
314}
315
316
317// Update attributes panel, repr can be nullptr.
319{
320 if (repr &&
324 {
325 attributes->setRepr(repr);
326 } else {
327 attributes->setRepr(nullptr);
328 }
329}
330
331
333{
334 if (auto selection = getSelection()) {
335 return selection->singleRepr();
336 }
337 return nullptr;
338}
339
340
344static bool isRealLayer(SPObject const *object)
345{
346 auto group = cast<SPGroup>(object);
347 return group && group->layerMode() == SPGroup::LAYER;
348}
349
351{
352 auto document = getDocument();
353 if (!document)
354 return;
355
356 SPObject *object;
357 if (repr) {
358 while ( ( repr->type() != Inkscape::XML::NodeType::ELEMENT_NODE )
359 && repr->parent() )
360 {
361 repr = repr->parent();
362 } // end of while loop
363
364 object = document->getObjectByRepr(repr);
365 } else {
366 object = nullptr;
367 }
368
369 blocked++;
370
371 if (!object || !in_dt_coordsys(*object)) {
372 // object not on canvas
373 } else if (isRealLayer(object)) {
375 } else {
376 if (is<SPGroup>(object->parent)) {
378 }
379
380 getSelection()->set(cast<SPItem>(object));
381 }
382
384 blocked--;
385}
386
388{
389 if (selected_repr) {
390 selected_repr = nullptr;
391 }
392
393 auto selection = _xml_treeview->get_selection();
394 auto iter = selection->get_selected();
395 if (!iter) {
396 propagate_tree_select(nullptr);
397 set_dt_select(nullptr);
399 return false;
400 }
401
402 auto repr = _xml_treeview->get_repr(*iter);
403 assert(repr != nullptr);
404
405 selected_repr = repr;
406
410
411 return false;
412}
413
414void XmlTree::_set_status_message(Inkscape::MessageType /*type*/, const gchar *message, GtkWidget *widget)
415{
416 if (widget) {
417 gtk_label_set_markup(GTK_LABEL(widget), message ? message : "");
418 }
419}
420
422{
423 assert (node);
424
425 // If mutable:
426 bool is_mutable = xml_tree_node_mutable(node);
427 xml_node_duplicate_button.set_sensitive(is_mutable);
428 xml_node_delete_button.set_sensitive( is_mutable);
429
430 // If element node:
431 bool is_element = (node->type() == Inkscape::XML::NodeType::ELEMENT_NODE);
432 xml_element_new_button.set_sensitive(is_element);
433 xml_text_new_button.set_sensitive( is_element);
434
435 // If unindentable (not child of top svg:svg):
436 bool unindentable = false;
437 auto parent=node->parent();
438 if (parent) {
439 auto grandparent = parent->parent();
440 if (grandparent && grandparent->parent()) {
441 unindentable = true; // XML tree root is actually 'xml' and not 'svg:svg'!
442 }
443 }
444 unindent_node_button.set_sensitive(unindentable);
445
446 // If indentable:
447 bool indentable = false;
450
451 if (parent && node != parent->firstChild()) {
452 assert (parent->firstChild());
453
454 // Skip to the child just before the current node.
455 for ( prev = parent->firstChild() ;
456 prev && prev->next() != node ;
457 prev = prev->next() ){};
458
459 if (prev && (prev->type() == Inkscape::XML::NodeType::ELEMENT_NODE)) {
460 indentable = true;
461 }
462 }
463 }
464 indent_node_button.set_sensitive(indentable);
465
466 // If not first child:
467 if (parent && node != parent->firstChild()) {
468 raise_node_button.set_sensitive(true);
469 } else {
470 raise_node_button.set_sensitive(false);
471 }
472
473 // If not last child:
474 if (parent && node->next()) {
475 lower_node_button.set_sensitive(true);
476 } else {
477 lower_node_button.set_sensitive(false);
478 }
479}
480
482{
483 assert(node);
484
485 // Top-level is immutable, obviously.
486 auto parent = node->parent();
487 if (!parent) {
488 return false;
489 }
490
491 // If not in base level (where namedview, defs, etc go), we're mutable.
492 if (parent->parent()) {
493 return true;
494 }
495
496 // Don't let "defs" or "namedview" disappear.
497 if ( !strcmp(node->name(),"svg:defs") ||
498 !strcmp(node->name(),"sodipodi:namedview") ) {
499 return false;
500 }
501
502 // Everyone else is okay, I guess. :)
503 return true;
504}
505
507{
508 xml_text_new_button.set_sensitive(false);
509 xml_element_new_button.set_sensitive(false);
510 xml_node_delete_button.set_sensitive(false);
511 xml_node_duplicate_button.set_sensitive(false);
512 unindent_node_button.set_sensitive(false);
513 indent_node_button.set_sensitive(false);
514 raise_node_button.set_sensitive(false);
515 lower_node_button.set_sensitive(false);
516}
517
519{
520 Glib::ustring text = name_entry->get_text();
521 /* TODO: need to do checking a little more rigorous than this */
522 create_button->set_sensitive(!text.empty());
523}
524
526{
527 auto document = getDocument();
528 if (!document)
529 return;
530
531 // Enable in-place node name editing.
532 auto renderer = _xml_treeview->get_renderer();
533 renderer->property_editable() = true;
534
535 auto dummy = ""; // this element has no corresponding SP* object and its construction is silent
536 auto xml_doc = document->getReprDoc();
537 _dummy = xml_doc->createElement(dummy); // create dummy placeholder so we can have a new temporary row in xml tree
538
539 assert (selected_repr);
540 _node_parent = selected_repr; // remember where the node is inserted
542 set_tree_select(_dummy, true); // enter in-place node name editing
543}
544
545void XmlTree::startNodeEditing(Gtk::CellEditable* cell, const Glib::ustring& path)
546{
547 if (!cell) {
548 return;
549 }
550 // remove dummy element name so user can start with an empty name
551 auto entry = dynamic_cast<Gtk::Entry *>(cell);
552 entry->get_buffer()->set_text("");
553}
554
555void XmlTree::stopNodeEditing(bool ok, const Glib::ustring& path, Glib::ustring element)
556{
557 auto renderer = _xml_treeview->get_renderer();
558 renderer->property_editable() = false;
559
560 auto document = getDocument();
561 if (!document) {
562 return;
563 }
564 // delete dummy node
565 if (_dummy) {
567
568 auto parent = _dummy->parent();
570 if (parent) {
571 auto parentobject = document->getObjectByRepr(parent);
572 if (parentobject) {
573 parentobject->requestDisplayUpdate(SP_OBJECT_CHILD_MODIFIED_FLAG);
574 }
575 }
576
577 _dummy = nullptr;
578 }
579
580 Util::trim(element);
581 if (!ok || element.empty() || !_node_parent) {
582 return;
583 }
584
586 // Extract tag name
587 {
588 static auto const extract_tagname = Glib::Regex::create("^<?\\s*(\\w[\\w:\\-\\d]*)");
589 Glib::MatchInfo match_info;
590 extract_tagname->match(element, match_info);
591 if (!match_info.matches()) {
592 return;
593 }
594 element = match_info.fetch(1);
595 }
596
597 // prepend "svg:" namespace if none is given
598 if (element.find(':') == Glib::ustring::npos) {
599 element = "svg:" + element;
600 }
601 auto repr = xml_doc->createElement(element.c_str());
603 set_dt_select(repr);
604 set_tree_select(repr, true);
605 _node_parent = nullptr;
606
607 DocumentUndo::done(document, Q_("Undo History / XML Editor|Create new element node"), INKSCAPE_ICON("dialog-xml-editor"));
608}
609
611{
612 auto document = getDocument();
613 if (!document)
614 return;
615
616 g_assert(selected_repr != nullptr);
617
619 Inkscape::XML::Node *text = xml_doc->createTextNode("");
621
622 DocumentUndo::done(document, Q_("Undo History / XML Editor|Create new text node"), INKSCAPE_ICON("dialog-xml-editor"));
623
624 set_tree_select(text);
625 set_dt_select(text);
626}
627
629{
630 auto document = getDocument();
631 if (!document)
632 return;
633
634 g_assert(selected_repr != nullptr);
635
639
640 DocumentUndo::done(document, Q_("Undo History / XML Editor|Duplicate node"), INKSCAPE_ICON("dialog-xml-editor"));
641
643}
644
646{
647 auto document = getDocument();
648 if (!document)
649 return;
650
651 g_assert(selected_repr != nullptr);
652
654
656
658 selected_repr = nullptr;
659
660 if (parent) {
661 auto parentobject = document->getObjectByRepr(parent);
662 if (parentobject) {
663 parentobject->requestDisplayUpdate(SP_OBJECT_CHILD_MODIFIED_FLAG);
664 }
665 }
666
667 DocumentUndo::done(document, Q_("Undo History / XML Editor|Delete node"), INKSCAPE_ICON("dialog-xml-editor"));
668}
669
671{
672 auto document = getDocument();
673 if (!document)
674 return;
675
676 g_assert(selected_repr != nullptr);
677
679 g_return_if_fail(parent != nullptr);
680 g_return_if_fail(parent->firstChild() != selected_repr);
681
682 Inkscape::XML::Node *ref = nullptr;
684 while (before && (before->next() != selected_repr)) {
685 ref = before;
686 before = before->next();
687 }
688
690
691 DocumentUndo::done(document, Q_("Undo History / XML Editor|Raise node"), INKSCAPE_ICON("dialog-xml-editor"));
692
695}
696
697
698
700{
701 auto document = getDocument();
702 if (!document)
703 return;
704
705 g_assert(selected_repr != nullptr);
706
707 g_return_if_fail(selected_repr->next() != nullptr);
709
711
712 DocumentUndo::done(document, Q_("Undo History / XML Editor|Lower node"), INKSCAPE_ICON("dialog-xml-editor"));
713
716}
717
719{
720 auto document = getDocument();
721 if (!document)
722 return;
723
724 assert (selected_repr);
726
728 g_return_if_fail(parent != nullptr);
729 g_return_if_fail(parent->firstChild() != repr);
730
732 while (prev && (prev->next() != repr)) {
733 prev = prev->next();
734 }
735 g_return_if_fail(prev != nullptr);
736 g_return_if_fail(prev->type() == Inkscape::XML::NodeType::ELEMENT_NODE);
737
738 Inkscape::XML::Node* ref = nullptr;
739 if (prev->firstChild()) {
740 for( ref = prev->firstChild() ; ref->next() ; ref = ref->next() ){};
741 }
742
743 parent->removeChild(repr);
744 prev->addChild(repr, ref);
745
746 DocumentUndo::done(document, Q_("Undo History / XML Editor|Indent node"), INKSCAPE_ICON("dialog-xml-editor"));
747 set_tree_select(repr);
748 set_dt_select(repr);
749
750} // end of cmd_indent_node()
751
752
753
755{
756 auto document = getDocument();
757 if (!document) {
758 return;
759 }
760
762 g_assert(repr != nullptr);
763
765 g_return_if_fail(parent);
766
767 Inkscape::XML::Node *grandparent = parent->parent();
768 g_return_if_fail(grandparent);
769
770 parent->removeChild(repr);
771 grandparent->addChild(repr, parent);
772
773 DocumentUndo::done(document, Q_("Undo History / XML Editor|Unindent node"), INKSCAPE_ICON("dialog-xml-editor"));
774
775 set_tree_select(repr);
776 set_dt_select(repr);
777
778} // end of cmd_unindent_node()
779
786{
787 /* Definition based on sp_item_i2doc_affine. */
788 SPObject const *child = &item;
789 while (is<SPItem>(child)) {
790 SPObject const * const parent = child->parent;
791 if (parent == nullptr) {
792 g_assert(is<SPRoot>(child));
793 if (child == &item) {
794 // item is root
795 return false;
796 }
797 return true;
798 }
799 child = parent;
800 }
801 g_assert(!is<SPRoot>(child));
802 return false;
803}
804
806 // subdialog does not receive desktopReplace calls, we need to propagate desktop change
807 if (attributes) {
809 }
810}
811
813{
814 _xml_treeview->set_style(new_style);
815}
816
817} // namespace Inkscape::UI::Dialog
818
819/*
820 Local Variables:
821 mode:c++
822 c-file-style:"stroustrup"
823 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
824 indent-tabs-mode:nil
825 fill-column:99
826 End:
827*/
828// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Gtk builder utilities.
static void done(SPDocument *document, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
void setCurrentLayer(SPObject *object, bool clear=false)
Sets the current layer of the desktop.
XML::Node * singleRepr()
Returns a single selected object's xml node.
std::function< void()> action
The action to perform when the value changes, if any.
Preference storage class.
Definition preferences.h:66
static Preferences * get()
Access the singleton Preferences object.
int getInt(Glib::ustring const &pref_path, int def=0)
Retrieve an integer.
void setInt(Glib::ustring const &pref_path, int value)
Set an integer value.
int getIntLimited(Glib::ustring const &pref_path, int def=0, int min=INT_MIN, int max=INT_MAX)
Retrieve a limited integer.
The set of selected SPObjects for a given document and layer model.
Definition selection.h:80
void set(XML::Node *repr)
Set the selection to an XML node's SPObject.
Definition selection.h:118
Gtk::ScrolledWindow & get_scrolled_window()
Definition attrdialog.h:62
void setRepr(Inkscape::XML::Node *repr)
AttrDialog::setRepr Set the internal xml object that I'm working on right now.
DialogBase is the base class for the dialog system.
Definition dialog-base.h:42
Selection * getSelection() const
Definition dialog-base.h:84
void setDesktop(SPDesktop *new_desktop)
Called when the desktop might have changed for this dialog.
SPDocument * getDocument() const
Definition dialog-base.h:83
void fix_inner_scroll(Gtk::ScrolledWindow &scrollwin)
SPDesktop * getDesktop() const
Definition dialog-base.h:79
void cmd_new_element_node()
Callbacks for toolbar buttons being pressed.
Definition xml-tree.cpp:525
void desktopReplaced() final
Called when the desktop has certainly changed.
Definition xml-tree.cpp:805
Gtk::Button & raise_node_button
Definition xml-tree.h:176
static void _set_status_message(Inkscape::MessageType type, const gchar *message, GtkWidget *dialog)
Callbacks for changes in desktop selection and current document.
Definition xml-tree.cpp:414
Inkscape::XML::Node * selected_repr
Signal handlers.
Definition xml-tree.h:153
void set_tree_select(Inkscape::XML::Node *repr, bool edit=false)
Select a node in the xml tree.
Definition xml-tree.cpp:304
Gtk::Button & xml_node_duplicate_button
Definition xml-tree.h:173
Inkscape::XML::Node * _dummy
Definition xml-tree.h:185
Inkscape::XML::Node * get_dt_select()
Find the current desktop selection.
Definition xml-tree.cpp:332
Pref< Glib::ustring > _syntax_theme
Definition xml-tree.h:183
void selectionChanged(Selection *selection) final
Definition xml-tree.cpp:295
Gtk::Button & lower_node_button
Definition xml-tree.h:177
void set_dt_select(Inkscape::XML::Node *repr)
Select the current desktop selection.
Definition xml-tree.cpp:350
Inkscape::XML::Node * _node_parent
Definition xml-tree.h:186
Gtk::Button & unindent_node_button
Definition xml-tree.h:174
bool in_dt_coordsys(SPObject const &item)
Returns true iff item is suitable to be included in the selection, in particular whether it has a bou...
Definition xml-tree.cpp:785
void on_tree_select_row_enable(Inkscape::XML::Node *node)
Enable widgets based on current selections.
Definition xml-tree.cpp:421
void propagate_tree_select(Inkscape::XML::Node *repr)
Set the attribute list to match the selected node in the tree.
Definition xml-tree.cpp:318
gint blocked
Flag to ensure only one operation is performed at once.
Definition xml-tree.h:148
bool xml_tree_node_mutable(Inkscape::XML::Node *node)
Is the selected tree node editable.
Definition xml-tree.cpp:481
sigc::scoped_connection _tree_select_idle
Callback for deferring the on_tree_select_row response in order to skip invalid intermediate selectio...
Definition xml-tree.h:107
Gtk::Button & xml_node_delete_button
Definition xml-tree.h:172
Inkscape::UI::Widget::XmlTreeView * _xml_treeview
Definition xml-tree.h:156
void startNodeEditing(Gtk::CellEditable *cell, Glib::ustring const &path)
Definition xml-tree.cpp:545
void stopNodeEditing(bool ok, Glib::ustring const &path, Glib::ustring name)
Definition xml-tree.cpp:555
void setSyntaxStyle(Inkscape::UI::Syntax::XMLStyles const &new_style)
Definition xml-tree.cpp:812
Gtk::Button & indent_node_button
Definition xml-tree.h:175
Gtk::Button & xml_element_new_button
Definition xml-tree.h:170
Gtk::Button & xml_text_new_button
Definition xml-tree.h:171
Glib::RefPtr< Gtk::Builder > _builder
Definition xml-tree.h:161
sigc::connection connectBeforeResize(F &&slot)
Register a handler to run immediately before a resize operation.
Definition bin.h:53
void set_child(Gtk::Widget *child)
Sets (parents) the child widget, or unsets (unparents) it if child is null.
Definition bin.cpp:40
void build_tree(SPDocument *document)
void set_style(Inkscape::UI::Syntax::XMLStyles const &new_style)
Gtk::CellRendererText * get_renderer()
void select_node(Inkscape::XML::Node *node, bool edit=false)
Select node in tree, if edit, move cursor.
Inkscape::XML::Node * get_repr(Gtk::TreeModel::ConstRow const &row) const
Interface for refcounted XML nodes.
Definition node.h:80
virtual Node * parent()=0
Get the parent of this node.
virtual Node * next()=0
Get the next sibling of this node.
virtual void addChild(Node *child, Node *after)=0
Insert another node as a child of this node.
virtual void changeOrder(Node *child, Node *after)=0
Move a given node in this node's child order.
virtual void appendChild(Node *child)=0
Append a node as the last child of this node.
virtual char const * name() const =0
Get the name of the element node.
virtual Node * duplicate(Document *doc) const =0
Create a duplicate of this node.
virtual Node * firstChild()=0
Get the first child of this node.
virtual void removeChild(Node *child)=0
Remove a child of this node.
virtual NodeType type() const =0
Get the type of the node.
Inkscape::LayerManager & layerManager()
Definition desktop.h:287
void setXMLDialogSelectedObject(SPObject *activexmltree)
Definition document.h:157
Inkscape::XML::Node * getReprRoot()
Definition document.h:206
Inkscape::XML::Document * getReprDoc()
Our Inkscape::XML::Document.
Definition document.h:211
SPObject * getObjectByRepr(Inkscape::XML::Node *repr) const
SPObject is an abstract base class of all of the document nodes at the SVG document level.
Definition sp-object.h:160
SPObject * parent
Definition sp-object.h:189
void requestDisplayUpdate(unsigned int flags)
Queues an deferred update of this object's display.
Editable view implementation.
Event handler for dialog windows.
static char const *const parent
Definition dir-util.cpp:70
TODO: insert short description here.
Icon Loader.
Macro for icon names used in Inkscape.
SPItem * item
Inkscape::XML::Node * node
Definition desktop.h:50
Dialog code.
Definition desktop.h:117
static bool isRealLayer(SPObject const *object)
Like SPDesktop::isLayer(), but ignores SPGroup::effectiveLayerMode().
Definition xml-tree.cpp:344
XMLStyles build_xml_styles(const Glib::ustring &syntax_theme)
Build XML styles from a GTKSourceView syntax color theme.
Definition syntax.cpp:129
static constexpr int height
W & get_widget(const Glib::RefPtr< Gtk::Builder > &builder, const char *id)
Glib::RefPtr< Gtk::Builder > create_builder(const char *filename)
void trim(Glib::ustring &input, Glib::ustring const &also_remove="")
Modifies a string in place, removing leading and trailing whitespace characters.
Definition trim.h:34
@ COMMENT_NODE
Comment node, e.g. <!– some comment –>.
@ ELEMENT_NODE
Regular element node, e.g. <group />.
@ TEXT_NODE
Text node, e.g. "Some text" in <group>Some text</group> is represented by a text node.
static void append(std::vector< T > &target, std::vector< T > &&source)
MessageType
A hint about the meaning of a message; is it an ordinary message, a message advising the user of some...
Definition message.h:25
@ HORIZONTAL
The x-dimension (0).
Definition rectangle.h:43
Helpers for using Gtk::Boxes, encapsulating large changes between GTK3 & GTK4.
Singleton class to access the preferences file in a convenient way.
Ocnode * child[8]
Definition quantize.cpp:33
Ocnode ** ref
Definition quantize.cpp:32
void sp_repr_unparent(Inkscape::XML::Node *repr)
Remove repr from children of its parent node.
Definition repr.h:107
SPRoot: SVG <svg> implementation.
The styles used for simple XML syntax highlighting.
Definition syntax.h:46
Interface for XML documents.
Definition document.h:43
virtual Node * createTextNode(char const *content)=0
virtual Node * createElement(char const *name)=0
double width
Glib::ustring name
Definition toolbars.cpp:55
Inkscape::Util::trim - trim whitespace and other characters.
This is XML tree editor, which allows direct modifying of all elements of Inkscape document,...