diff options
| author | Martin Owens <doctormo@gmail.com> | 2018-09-14 16:58:18 +0000 |
|---|---|---|
| committer | Martin Owens <doctormo@gmail.com> | 2018-09-14 16:58:18 +0000 |
| commit | b92e577ea62c2a94ba38390fa67d9dcea3db88af (patch) | |
| tree | 3b48af7caf1e7fd14fd0015f6113a6545f11e9b7 | |
| parent | Merge branch 'master' of gitlab.com:jordim/inkscape (diff) | |
| download | inkscape-b92e577ea62c2a94ba38390fa67d9dcea3db88af.tar.gz inkscape-b92e577ea62c2a94ba38390fa67d9dcea3db88af.zip | |
Remove sp-xmlview-attr with attrdialog (C++) and improve interface
| -rw-r--r-- | src/ui/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/ui/dialog/attrdialog.cpp | 272 | ||||
| -rw-r--r-- | src/ui/dialog/attrdialog.h | 92 | ||||
| -rw-r--r-- | src/ui/dialog/cssdialog.cpp | 25 | ||||
| -rw-r--r-- | src/ui/dialog/cssdialog.h | 1 | ||||
| -rw-r--r-- | src/ui/dialog/xml-tree.cpp | 38 | ||||
| -rw-r--r-- | src/ui/dialog/xml-tree.h | 10 | ||||
| -rw-r--r-- | src/widgets/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/widgets/sp-xmlview-attr-list.cpp | 280 | ||||
| -rw-r--r-- | src/widgets/sp-xmlview-attr-list.h | 57 |
10 files changed, 391 insertions, 388 deletions
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 0ae3b8624..6d1ebb785 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -82,6 +82,7 @@ set(ui_SRC dialog/calligraphic-profile-rename.cpp dialog/clonetiler.cpp dialog/color-item.cpp + dialog/attrdialog.cpp dialog/cssdialog.cpp dialog/debug.cpp dialog/desktop-tracker.cpp @@ -233,6 +234,7 @@ set(ui_SRC dialog/calligraphic-profile-rename.h dialog/clonetiler.h dialog/color-item.h + dialog/attrdialog.h dialog/cssdialog.h dialog/debug.h dialog/desktop-tracker.h diff --git a/src/ui/dialog/attrdialog.cpp b/src/ui/dialog/attrdialog.cpp new file mode 100644 index 000000000..529a59720 --- /dev/null +++ b/src/ui/dialog/attrdialog.cpp @@ -0,0 +1,272 @@ +/** @file + * @brief A dialog for XML attributes + */ +/* Authors: + * Martin Owens + * + * Copyright (C) Martin Owens 2018 <doctormo@gmail.com> + * + * Released under GNU GPLv2 or later, read the file 'COPYING' for more information + */ + +#include "attrdialog.h" + +#include "verbs.h" +#include "selection.h" + +#include "helper/icon-loader.h" +#include "ui/widget/addtoicon.h" + +#include "xml/node-event-vector.h" +#include "xml/attribute-record.h" + +static void on_attr_changed (Inkscape::XML::Node * repr, + const gchar * name, + const gchar * /*old_value*/, + const gchar * new_value, + bool /*is_interactive*/, + gpointer data) +{ + ATTR_DIALOG(data)->onAttrChanged(repr, name, new_value); +} +Inkscape::XML::NodeEventVector _repr_events = { + nullptr, /* child_added */ + nullptr, /* child_removed */ + on_attr_changed, + nullptr, /* content_changed */ + nullptr /* order_changed */ +}; + +namespace Inkscape { +namespace UI { +namespace Dialog { + + +/** + * Constructor + * A treeview whose each row corresponds to an XML attribute of a selected node + * New attribute can be added by clicking '+' at bottom of the attr pane. '-' + */ +AttrDialog::AttrDialog(): + UI::Widget::Panel("/dialogs/attr", SP_VERB_DIALOG_CSS), + _desktop(nullptr), + _repr(nullptr) +{ + set_size_request(20, 15); + _mainBox.pack_start(_scrolledWindow, Gtk::PACK_EXPAND_WIDGET); + _treeView.set_headers_visible(true); + _scrolledWindow.add(_treeView); + _scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + + _store = Gtk::ListStore::create(_attrColumns); + _treeView.set_model(_store); + + Inkscape::UI::Widget::AddToIcon * addRenderer = manage(new Inkscape::UI::Widget::AddToIcon()); + addRenderer->property_active() = false; + + int addCol = _treeView.append_column("", *addRenderer) - 1; + Gtk::TreeViewColumn *col = _treeView.get_column(addCol); + if (col) { + auto add_icon = Gtk::manage(sp_get_icon_image("list-add", GTK_ICON_SIZE_SMALL_TOOLBAR)); + col->add_attribute(addRenderer->property_active(), _attrColumns._colUnsetAttr); + col->set_clickable(true); + col->set_widget(*add_icon); + add_icon->set_tooltip_text("Add a new attribute"); + add_icon->show(); + // This gets the GtkButton inside the GtkBox, inside the GtkAlignment, inside the GtkImage icon. + auto button = add_icon->get_parent()->get_parent()->get_parent(); + // Assign the button event so that create happens BEFORE delete. If this code + // isn't in this exact way, the onAttrDelete is called when the header lines are pressed. + button->signal_button_release_event().connect(sigc::mem_fun(*this, &AttrDialog::onAttrCreate), false); + } + _treeView.signal_button_release_event().connect(sigc::mem_fun(*this, &AttrDialog::onAttrDelete)); + + _nameRenderer = Gtk::manage(new Gtk::CellRendererText()); + _nameRenderer->property_editable() = true; + _nameRenderer->property_placeholder_text().set_value("Attribute Name"); + _nameRenderer->signal_edited().connect(sigc::mem_fun(*this, &AttrDialog::nameEdited)); + int nameColNum = _treeView.append_column("Name", *_nameRenderer) - 1; + _nameCol = _treeView.get_column(nameColNum); + if (_nameCol) { + _nameCol->add_attribute(_nameRenderer->property_text(), _attrColumns._attributeName); + } + + _valueRenderer = Gtk::manage(new Gtk::CellRendererText()); + _valueRenderer->property_editable() = true; + _valueRenderer->property_placeholder_text().set_value("Attribute Value"); + _valueRenderer->property_ellipsize().set_value(Pango::ELLIPSIZE_MIDDLE); + _valueRenderer->signal_edited().connect(sigc::mem_fun(*this, &AttrDialog::valueEdited)); + int valueColNum = _treeView.append_column("Value", *_valueRenderer) - 1; + _valueCol = _treeView.get_column(valueColNum); + if (_valueCol) { + _valueCol->add_attribute(_valueRenderer->property_text(), _attrColumns._attributeValue); + } + + _getContents()->pack_start(_mainBox, Gtk::PACK_EXPAND_WIDGET); + + setDesktop(getDesktop()); +} + + +/** + * @brief AttrDialog::~AttrDialog + * Class destructor + */ +AttrDialog::~AttrDialog() +{ + setDesktop(nullptr); +} + + +/** + * @brief AttrDialog::setDesktop + * @param desktop + * This function sets the 'desktop' for the CSS pane. + */ +void AttrDialog::setDesktop(SPDesktop* desktop) +{ + _desktop = desktop; +} + +/** + * @brief AttrDialog::setRepr + * Set the internal xml object that I'm working on right now. + */ +void AttrDialog::setRepr(Inkscape::XML::Node * repr) +{ + if ( repr == _repr ) return; + if (_repr) { + _store->clear(); + _repr->removeListenerByData(this); + Inkscape::GC::release(_repr); + } + _repr = repr; + if (repr) { + Inkscape::GC::anchor(_repr); + _repr->addListener(&_repr_events, this); + _repr->synthesizeEvents(&_repr_events, this); + } +} + +/** + * @brief AttrDialog::onAttrChanged + * This is called when the XML has an updated attribute + */ +void AttrDialog::onAttrChanged(Inkscape::XML::Node *repr, const gchar * name, const gchar * new_value) +{ + for(auto iter: this->_store->children()) + { + Gtk::TreeModel::Row row = *iter; + Glib::ustring col_name = row[_attrColumns._attributeName]; + if(name == col_name) { + if(new_value) { + row[_attrColumns._attributeValue] = new_value; + new_value = nullptr; // Don't make a new one + } else { + _store->erase(iter); + } + } + } + if(new_value) { + Gtk::TreeModel::Row row = *(_store->append()); + row[_attrColumns._attributeName] = name; + row[_attrColumns._attributeValue] = new_value; + } +} + +/** + * @brief AttrDialog::onAttrCreate + * This function is a slot to signal_clicked for '+' button panel. + */ +bool AttrDialog::onAttrCreate(GdkEventButton *event) +{ + if(event->type == GDK_BUTTON_RELEASE && event->button == 1 && this->_repr) { + Gtk::TreeIter iter = _store->append(); + Gtk::TreeModel::Path path = (Gtk::TreeModel::Path)iter; + _treeView.set_cursor(path, *_nameCol, true); + grab_focus(); + return true; + } + return false; +} + +/** + * @brief AttrDialog::onAttrDelete + * @param event + * @return + * Delete the attribute from the xml + */ +bool AttrDialog::onAttrDelete(GdkEventButton *event) +{ + if (event->type == GDK_BUTTON_RELEASE && event->button == 1 && this->_repr) { + if(!this->_treeView.has_focus()) { + // If the treeView doesn't have focus, then it's probably the edit + // input box or some other widget that propergates to the same click + return false; + } + int x = static_cast<int>(event->x); + int y = static_cast<int>(event->y); + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn *col = nullptr; + int x2, y2 = 0; + if (_treeView.get_path_at_pos(x, y, path, col, x2, y2)) { + Gtk::TreeModel::Row row = *_store->get_iter(path); + if (col == _treeView.get_column(0) && row) { + Glib::ustring name = row[_attrColumns._attributeName]; + this->_repr->setAttribute(name.c_str(), nullptr, false); + // Return true to prevent propergation + return true; + } + } + } + return false; +} + + +/** + * @brief AttrDialog::nameEdited + * @param event + * @return + * Called when the name is edited in the TreeView editable column + */ +void AttrDialog::nameEdited (const Glib::ustring& path, const Glib::ustring& name) +{ + + Gtk::TreeModel::Row row = *_store->get_iter(path); + if(row) { + Glib::ustring old_name = row[_attrColumns._attributeName]; + Glib::ustring value = row[_attrColumns._attributeValue]; + if(!old_name.empty()) { + // Remove named value + _repr->setAttribute(old_name, nullptr, false); + _repr->setAttribute(name, value, false); + } else { + // Move to editing value, we set the name as a temporary store value + row[_attrColumns._attributeName] = name; + Gtk::TreeModel::Path _path = (Gtk::TreeModel::Path)row; + _treeView.set_cursor(_path, *_valueCol, true); + grab_focus(); + } + } +} + +/** + * @brief AttrDialog::valueEdited + * @param event + * @return + * Called when the value is edited in the TreeView editable column + */ +void AttrDialog::valueEdited (const Glib::ustring& path, const Glib::ustring& value) +{ + + Gtk::TreeModel::Row row = *_store->get_iter(path); + if(row) { + Glib::ustring name = row[_attrColumns._attributeName]; + if(name.empty()) return; + _repr->setAttribute(name, value, false); + } +} + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape diff --git a/src/ui/dialog/attrdialog.h b/src/ui/dialog/attrdialog.h new file mode 100644 index 000000000..23ba8f321 --- /dev/null +++ b/src/ui/dialog/attrdialog.h @@ -0,0 +1,92 @@ +/** @file + * @brief A dialog for XML attributes based on Gtk TreeView + */ +/* Authors: + * Martin Owens + * + * Copyright (C) Martin Owens 2018 <doctormo@gmail.com> + * + * Released under GNU GPLv2 or later, read the file 'COPYING' for more information + */ + +#ifndef ATTRDIALOG_H +#define ATTRDIALOG_H + +#include <gtkmm/treeview.h> +#include <gtkmm/liststore.h> +#include <gtkmm/scrolledwindow.h> +#include <gtkmm/dialog.h> +#include <ui/widget/panel.h> + +#include "desktop.h" + +#define ATTR_DIALOG(obj) (dynamic_cast<Inkscape::UI::Dialog::AttrDialog*>((Inkscape::UI::Dialog::AttrDialog*)obj)) + +namespace Inkscape { +namespace UI { +namespace Dialog { + +/** + * @brief The AttrDialog class + * This dialog allows to add, delete and modify XML attributes created in the + * xml editor. + */ +class AttrDialog : public UI::Widget::Panel +{ +public: + AttrDialog(); + ~AttrDialog() override; + + static AttrDialog &getInstance() { return *new AttrDialog(); } + + // Data structure + class AttrColumns : public Gtk::TreeModel::ColumnRecord { + public: + AttrColumns() { + add(_colUnsetAttr); + add(_attributeName); + add(_attributeValue); + } + Gtk::TreeModelColumn<bool> _colUnsetAttr; + Gtk::TreeModelColumn<Glib::ustring> _attributeName; + Gtk::TreeModelColumn<Glib::ustring> _attributeValue; + }; + AttrColumns _attrColumns; + + // TreeView + Gtk::TreeView _treeView; + Glib::RefPtr<Gtk::ListStore> _store; + Gtk::CellRendererText *_nameRenderer; + Gtk::CellRendererText *_valueRenderer; + Gtk::TreeViewColumn *_nameCol; + Gtk::TreeViewColumn *_valueCol; + + // Widgets + Gtk::VBox _mainBox; + Gtk::ScrolledWindow _scrolledWindow; + Gtk::HBox _buttonBox; + Gtk::Button _buttonAddAttribute; + + // Variables - Inkscape + SPDesktop* _desktop; + Inkscape::XML::Node* _repr; + + // Helper functions + void setDesktop(SPDesktop* desktop) override; + void setRepr(Inkscape::XML::Node * repr); + + // Signal handlers + void onAttrChanged(Inkscape::XML::Node *repr, const gchar * name, const gchar * new_value); + bool onAttrCreate(GdkEventButton *event); + bool onAttrDelete(GdkEventButton *event); + void nameEdited(const Glib::ustring &path, const Glib::ustring &name); + void valueEdited(const Glib::ustring &path, const Glib::ustring &value); + +}; + + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +#endif // ATTRDIALOG_H diff --git a/src/ui/dialog/cssdialog.cpp b/src/ui/dialog/cssdialog.cpp index 901bcf36c..47922fc64 100644 --- a/src/ui/dialog/cssdialog.cpp +++ b/src/ui/dialog/cssdialog.cpp @@ -80,7 +80,11 @@ CssDialog::CssDialog(): _attrCol->add_attribute(_attrRenderer->property_text(), _cssColumns._styleAttrVal); } - _styleButton(_buttonAddProperty, "list-add", "Add a new property"); + GtkWidget *child = GTK_WIDGET(sp_get_icon_image("list-add", GTK_ICON_SIZE_SMALL_TOOLBAR)->gobj()); + gtk_widget_show(child); + _buttonAddProperty.add(*manage(Glib::wrap(child))); + _buttonAddProperty.set_relief(Gtk::RELIEF_NONE); + _buttonAddProperty.set_tooltip_text("Add a new property"); _mainBox.pack_end(_buttonBox, Gtk::PACK_SHRINK); _buttonBox.pack_start(_buttonAddProperty, Gtk::PACK_SHRINK); @@ -113,25 +117,6 @@ void CssDialog::setDesktop(SPDesktop* desktop) _desktop = desktop; } - -/** - * @brief CssDialog::_styleButton - * @param btn - * @param iconName - * @param tooltip - * This function sets the style of '+'button at the bottom of dialog. - */ -void CssDialog::_styleButton(Gtk::Button& btn, char const* iconName, - char const* tooltip) -{ - GtkWidget *child = GTK_WIDGET(sp_get_icon_image(iconName, GTK_ICON_SIZE_SMALL_TOOLBAR)->gobj()); - gtk_widget_show(child); - btn.add(*manage(Glib::wrap(child))); - btn.set_relief(Gtk::RELIEF_NONE); - btn.set_tooltip_text(tooltip); -} - - /** * @brief CssDialog::_addProperty * This function is a slot to signal_clicked for '+' button at the bottom of CSS diff --git a/src/ui/dialog/cssdialog.h b/src/ui/dialog/cssdialog.h index 76c98ee8d..6b9657599 100644 --- a/src/ui/dialog/cssdialog.h +++ b/src/ui/dialog/cssdialog.h @@ -79,7 +79,6 @@ public: // Helper functions void setDesktop(SPDesktop* desktop) override; - void _styleButton(Gtk::Button& btn, char const* iconName, char const* tooltip); // Signal handlers void _addProperty(); diff --git a/src/ui/dialog/xml-tree.cpp b/src/ui/dialog/xml-tree.cpp index e62f0232d..2e53ebf32 100644 --- a/src/ui/dialog/xml-tree.cpp +++ b/src/ui/dialog/xml-tree.cpp @@ -41,8 +41,8 @@ #include "ui/interface.h" #include "ui/tools/tool-base.h" -#include "widgets/sp-xmlview-attr-list.h" #include "widgets/sp-xmlview-tree.h" +#include "ui/dialog/attrdialog.h" #include "ui/dialog/cssdialog.h" namespace Inkscape { @@ -59,7 +59,6 @@ XmlTree::XmlTree() : selected_attr (0), selected_repr (nullptr), tree (nullptr), - attributes (nullptr), status (""), tree_toolbar(), xml_element_new_button ( _("New element node")), @@ -181,28 +180,19 @@ XmlTree::XmlTree() : node_box.pack_start(*tree_scroller); - /* node view */ + /* attributes */ + attributes = new AttrDialog; + attr_box.pack_start(*attributes); notebook_content->insert_page(attr_box, _("_Attributes"), NOTEBOOK_PAGE_ATTRS, true); notebook_content->set_tab_detachable(attr_box, true); - /* attributes */ - attributes = SP_XMLVIEW_ATTR_LIST(sp_xmlview_attr_list_new(nullptr)); - - Gtk::ScrolledWindow *attr_scroller = new Gtk::ScrolledWindow(); - attr_scroller->set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); - attr_scroller->set_shadow_type(Gtk::SHADOW_IN); - attr_scroller->set_size_request(-1, 80); - - attr_box.pack_start( *attr_scroller ); - attr_scroller->add(*Gtk::manage(Glib::wrap(GTK_WIDGET(attributes)))); - /* Signal handlers */ GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(tree)); g_signal_connect (G_OBJECT(selection), "changed", G_CALLBACK (on_tree_select_row), this); g_signal_connect_after( G_OBJECT(tree), "tree_move", G_CALLBACK(after_tree_move), this); - g_signal_connect( G_OBJECT(attributes), "row-value-changed", G_CALLBACK(on_attr_row_changed), this); - g_signal_connect( G_OBJECT(attributes), "attr-value-edited", G_CALLBACK(on_attr_edited), this); + //g_signal_connect( G_OBJECT(attributes), "row-value-changed", G_CALLBACK(on_attr_row_changed), this); + //g_signal_connect( G_OBJECT(attributes), "attr-value-edited", G_CALLBACK(on_attr_edited), this); xml_element_new_button.signal_clicked().connect(sigc::mem_fun(*this, &XmlTree::cmd_new_element_node)); xml_text_new_button.signal_clicked().connect(sigc::mem_fun(*this, &XmlTree::cmd_new_text_node)); @@ -388,9 +378,9 @@ void XmlTree::set_tree_select(Inkscape::XML::Node *repr) void XmlTree::propagate_tree_select(Inkscape::XML::Node *repr) { if (repr && (repr->type() == Inkscape::XML::ELEMENT_NODE)) { - sp_xmlview_attr_list_set_repr(attributes, repr); + attributes->setRepr(repr); } else { - sp_xmlview_attr_list_set_repr(attributes, nullptr); + attributes->setRepr(nullptr); } } @@ -482,7 +472,7 @@ void XmlTree::on_tree_select_row(GtkTreeSelection *selection, gpointer data) } -void XmlTree::after_tree_move(SPXMLViewTree * /*attributes*/, gpointer value, gpointer data) +void XmlTree::after_tree_move(SPXMLViewTree * /*tree*/, gpointer value, gpointer data) { XmlTree *self = static_cast<XmlTree *>(data); guint val = GPOINTER_TO_UINT(value); @@ -631,7 +621,7 @@ void XmlTree::on_tree_unselect_row_disable() lower_node_button.set_sensitive(false); } -void XmlTree::on_attr_edited(SPXMLViewAttrList *attributes, const gchar * name, const gchar * value, gpointer data) +/*void XmlTree::on_attr_edited(SPXMLViewAttrList *attributes, const gchar * name, const gchar * value, gpointer data) { XmlTree *self = static_cast<XmlTree *>(data); g_assert(self->selected_repr != nullptr); @@ -656,10 +646,10 @@ void XmlTree::on_attr_edited(SPXMLViewAttrList *attributes, const gchar * name, } else { DocumentUndo::done(self->current_document, SP_VERB_DIALOG_XML_EDITOR, _("Delete attribute")); } -} +}*/ -void XmlTree::on_attr_row_changed(SPXMLViewAttrList *attributes, const gchar * name, gpointer /*data*/) -{ +//void XmlTree::on_attr_row_changed(SPXMLViewAttrList *attributes, const gchar * name, gpointer /*data*/) +/*{ // Reselect the selected row if the data changes to refresh the attribute and value edit boxes. GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(attributes)); GtkTreeIter iter; @@ -679,7 +669,7 @@ void XmlTree::on_attr_row_changed(SPXMLViewAttrList *attributes, const gchar * n g_free(attr_name); attr_name = nullptr; } -} +}*/ void XmlTree::onCreateNameChanged() { diff --git a/src/ui/dialog/xml-tree.h b/src/ui/dialog/xml-tree.h index 2eff808ef..d5049bb84 100644 --- a/src/ui/dialog/xml-tree.h +++ b/src/ui/dialog/xml-tree.h @@ -27,6 +27,7 @@ #include <gtkmm/paned.h> #include <gtkmm/button.h> +#include "ui/dialog/attrdialog.h" #include "ui/dialog/cssdialog.h" #include "ui/dialog/desktop-tracker.h" #include "message.h" @@ -125,17 +126,17 @@ private: /** * Callback when a node is moved in the tree */ - static void after_tree_move(SPXMLViewTree *attributes, gpointer value, gpointer data); + static void after_tree_move(SPXMLViewTree *tree, gpointer value, gpointer data); /** * Callback for when an attribute is edited. */ - static void on_attr_edited(SPXMLViewAttrList *attributes, const gchar * name, const gchar * value, gpointer /*data*/); + //static void on_attr_edited(SPXMLViewAttrList *attributes, const gchar * name, const gchar * value, gpointer /*data*/); /** * Callback for when attribute list values change */ - static void on_attr_row_changed(SPXMLViewAttrList *attributes, const gchar * name, gpointer data); + //static void on_attr_row_changed(SPXMLViewAttrList *attributes, const gchar * name, gpointer data); /** * Enable widgets based on current selections @@ -216,7 +217,8 @@ private: /* XmlTree Widgets */ SPXMLViewTree *tree; - SPXMLViewAttrList *attributes; + //SPXMLViewAttrList *attributes; + AttrDialog *attributes; CssDialog *styles; /* XML Node Creation pop-up window */ diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt index 3853bb91a..f0beeed4a 100644 --- a/src/widgets/CMakeLists.txt +++ b/src/widgets/CMakeLists.txt @@ -21,7 +21,6 @@ set(widgets_SRC sp-attribute-widget.cpp sp-color-selector.cpp sp-widget.cpp - sp-xmlview-attr-list.cpp sp-xmlview-tree.cpp spinbutton-events.cpp spw-utilities.cpp @@ -53,7 +52,6 @@ set(widgets_SRC sp-attribute-widget.h sp-color-selector.h sp-widget.h - sp-xmlview-attr-list.h sp-xmlview-tree.h spinbutton-events.h spw-utilities.h diff --git a/src/widgets/sp-xmlview-attr-list.cpp b/src/widgets/sp-xmlview-attr-list.cpp deleted file mode 100644 index 81bd58dbc..000000000 --- a/src/widgets/sp-xmlview-attr-list.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Specialization of GtkTreeView for the XML tree view - * - * Authors: - * MenTaLguY <mental@rydia.net> - * - * Copyright (C) 2002 MenTaLguY - * - * Released under the GNU GPL; see COPYING for details - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <cstring> -#include <glibmm/i18n.h> - -#include "helper/sp-marshal.h" -#include "../xml/node-event-vector.h" -#include "sp-xmlview-attr-list.h" - -static void sp_xmlview_attr_list_destroy(GtkWidget * object); - -static void event_attr_changed (Inkscape::XML::Node * repr, const gchar * name, const gchar * old_value, const gchar * new_value, bool is_interactive, gpointer data); - -static Inkscape::XML::NodeEventVector repr_events = { - nullptr, /* child_added */ - nullptr, /* child_removed */ - event_attr_changed, - nullptr, /* content_changed */ - nullptr /* order_changed */ -}; - -GtkWidget *sp_xmlview_attr_list_new (Inkscape::XML::Node * repr) -{ - SPXMLViewAttrList * attr_list = SP_XMLVIEW_ATTR_LIST(g_object_new(SP_TYPE_XMLVIEW_ATTR_LIST, nullptr)); - - attr_list->store = gtk_list_store_new (ATTR_N_COLS, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING); - gtk_tree_view_set_model (GTK_TREE_VIEW(attr_list), GTK_TREE_MODEL(attr_list->store)); - - // Attribute name column - int colpos = 0; - GtkCellRenderer *cell = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(attr_list), colpos, _("Name"), cell, "text", ATTR_COL_NAME, NULL); - GtkTreeViewColumn *column = gtk_tree_view_get_column (GTK_TREE_VIEW(attr_list), colpos); - gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); - - gtk_tree_sortable_set_sort_func( GTK_TREE_SORTABLE(attr_list->store), ATTR_COL_NAME, attr_sort_name_iter, GINT_TO_POINTER(ATTR_COL_NAME), NULL); - gtk_tree_sortable_set_sort_column_id ( GTK_TREE_SORTABLE(attr_list->store), ATTR_COL_NAME, GTK_SORT_ASCENDING); - gtk_cell_renderer_set_padding (cell, 2, 0); - g_object_set(cell, "editable", TRUE, NULL); - g_signal_connect(cell, "edited", (GCallback) attr_name_edited, attr_list); - - // Attribute value column - colpos = 1; - cell = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(attr_list), colpos, _("Value"), cell, "text", ATTR_COL_VALUE, NULL); - column = gtk_tree_view_get_column (GTK_TREE_VIEW(attr_list), colpos); - gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_cell_renderer_set_padding (cell, 2, 0); - g_object_set(cell, "editable", TRUE, NULL); - g_signal_connect(cell, "edited", (GCallback) attr_value_edited, attr_list); - - // Final listview settings - g_signal_connect( G_OBJECT(attr_list), "key-press-event", G_CALLBACK(attr_key_pressed), NULL); - gtk_widget_set_name(GTK_WIDGET(attr_list), "attrlist"); - sp_xmlview_attr_list_set_repr (attr_list, repr); - - return GTK_WIDGET(attr_list); -} - -gint -attr_sort_name_iter (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer /*data*/) -{ - gint ret; - gchar *name1, *name2; - - gtk_tree_model_get(model, iter_a, ATTR_COL_NAME, &name1, -1); - gtk_tree_model_get(model, iter_b, ATTR_COL_NAME, &name2, -1); - if(name1[0] == 0) { return 1; } - if(name2[0] == 0) { return -1; } - ret = g_utf8_collate(name1, name2); - g_free(name1); - g_free(name2); - return ret; -} - -void -sp_xmlview_attr_list_set_repr (SPXMLViewAttrList * list, Inkscape::XML::Node * repr) -{ - if ( repr == list->repr ) return; - if (list->repr) { - gtk_list_store_clear(list->store); - sp_repr_remove_listener_by_data (list->repr, list); - Inkscape::GC::release(list->repr); - } - list->repr = repr; - if (repr) { - Inkscape::GC::anchor(repr); - sp_repr_add_listener (repr, &repr_events, list); - sp_repr_synthesize_events (repr, &repr_events, list); - - // Create an 'add-new' row to create new rows - GtkTreeIter iter; - gtk_list_store_append (list->store, &iter); - gtk_list_store_set (list->store, &iter, ATTR_COL_NAME, "", ATTR_COL_VALUE, "", ATTR_COL_ATTR, NULL, -1); - } -} - -G_DEFINE_TYPE(SPXMLViewAttrList, sp_xmlview_attr_list, GTK_TYPE_TREE_VIEW); - -void sp_xmlview_attr_list_class_init (SPXMLViewAttrListClass * klass) -{ - auto widget_class = GTK_WIDGET_CLASS(klass); - widget_class->destroy = sp_xmlview_attr_list_destroy; - - g_signal_new("row-value-changed", - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (SPXMLViewAttrListClass, row_changed), - nullptr, nullptr, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - g_signal_new("attr-value-edited", - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (SPXMLViewAttrListClass, row_changed), - nullptr, nullptr, - sp_marshal_VOID__STRING_STRING, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); -} - -void -sp_xmlview_attr_list_init (SPXMLViewAttrList * list) -{ - list->store = nullptr; - list->repr = nullptr; -} - -void sp_xmlview_attr_list_destroy(GtkWidget * object) -{ - SPXMLViewAttrList * list; - - list = SP_XMLVIEW_ATTR_LIST (object); - - g_object_unref(list->store); - sp_xmlview_attr_list_set_repr (list, nullptr); - - GTK_WIDGET_CLASS(sp_xmlview_attr_list_parent_class)->destroy (object); -} - -void sp_xmlview_attr_list_select_row_by_key(SPXMLViewAttrList * list, const gchar *name) -{ - GtkTreeIter iter; - gboolean match = false; - gboolean valid = gtk_tree_model_get_iter_first( GTK_TREE_MODEL(list->store), &iter ); - while ( valid ) { - gchar *n = nullptr; - gtk_tree_model_get (GTK_TREE_MODEL(list->store), &iter, ATTR_COL_NAME, &n, -1); - if (!strcmp(n, name)) { - match = true; - break; - } - valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(list->store), &iter); - // cppcheck-suppress nullPointer // a string was copied in n by gtk_tree_model_get - if (n) { - g_free(n); - } - } - - if (match) { - GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(list)); - gtk_tree_selection_select_iter(selection, &iter); - } -} - -void -attr_name_edited (GtkCellRendererText *cell, - gchar * path_string, - gchar * new_name, - gpointer data) { - - SPXMLViewAttrList * list = SP_XMLVIEW_ATTR_LIST (data); - GtkTreeIter iter; - gboolean valid = gtk_tree_model_get_iter_from_string( GTK_TREE_MODEL(list->store), &iter, path_string ); - if(valid) { - gchar *old_name = nullptr; - gchar *value = nullptr; - gtk_tree_model_get (GTK_TREE_MODEL(list->store), &iter, ATTR_COL_NAME, &old_name, ATTR_COL_VALUE, &value, -1); - if(old_name[0] != 0) { - // Remove named value - g_signal_emit_by_name(G_OBJECT (list), "attr-value-edited", old_name, nullptr ); - } - g_signal_emit_by_name(G_OBJECT (list), "attr-value-edited", new_name, value ); - } -} - -void -attr_value_edited (GtkCellRendererText *cell, - gchar * path_string, - gchar * new_value, - gpointer data) { - - SPXMLViewAttrList * list = SP_XMLVIEW_ATTR_LIST (data); - GtkTreeIter iter; - gboolean valid = gtk_tree_model_get_iter_from_string( GTK_TREE_MODEL(list->store), &iter, path_string ); - if(valid) { - gchar *name = nullptr; - gtk_tree_model_get (GTK_TREE_MODEL(list->store), &iter, ATTR_COL_NAME, &name, -1); - if(name[0] == 0 or name[0] == '<') { return; } - g_signal_emit_by_name(G_OBJECT (list), "attr-value-edited", name, new_value ); - } -} - -gboolean -attr_key_pressed(GtkWidget *attributes, GdkEventKey *event, gpointer /*data*/) -{ - GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(attributes)); - GtkTreeIter iter; - GtkTreeModel *model; - if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - switch (event->keyval) - { - case GDK_KEY_Delete: - case GDK_KEY_KP_Delete: - gchar *name = nullptr; - gtk_tree_model_get (model, &iter, 0, &name, -1); - g_signal_emit_by_name(G_OBJECT (attributes), "attr-value-edited", name, nullptr); - if(name) g_free(name); - return true; - } - } - return false; -} - -void -event_attr_changed (Inkscape::XML::Node * /*repr*/, - const gchar * name, - const gchar * /*old_value*/, - const gchar * new_value, - bool /*is_interactive*/, - gpointer data) -{ - gint row = -1; - SPXMLViewAttrList * list = SP_XMLVIEW_ATTR_LIST (data); - - GtkTreeIter iter; - gboolean valid = gtk_tree_model_get_iter_first( GTK_TREE_MODEL(list->store), &iter ); - gboolean match = false; - while ( valid ) { - gchar *n = nullptr; - gtk_tree_model_get (GTK_TREE_MODEL(list->store), &iter, ATTR_COL_NAME, &n, -1); - if (!strcmp(n, name)) { - match = true; - break; - } - row++; - valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(list->store), &iter); - // cppcheck-suppress nullPointer // a string was copied in n by gtk_tree_model_get - if (n) { - g_free(n); - } - } - - if (match) { - if (new_value) { - gtk_list_store_set (list->store, &iter, ATTR_COL_NAME, name, ATTR_COL_VALUE, new_value, ATTR_COL_ATTR, g_quark_from_string (name), -1); - } else { - gtk_list_store_remove (list->store, &iter); - } - } else if (new_value != nullptr) { - gtk_list_store_append (list->store, &iter); - gtk_list_store_set (list->store, &iter, ATTR_COL_NAME, name, ATTR_COL_VALUE, new_value, ATTR_COL_ATTR, g_quark_from_string (name), -1); - } - - // send a "changed" signal so widget owners will know I've updated - g_signal_emit_by_name(G_OBJECT (list), "row-value-changed", name ); -} - diff --git a/src/widgets/sp-xmlview-attr-list.h b/src/widgets/sp-xmlview-attr-list.h deleted file mode 100644 index 2d6e84fe4..000000000 --- a/src/widgets/sp-xmlview-attr-list.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef __SP_XMLVIEW_ATTR_LIST_H__ -#define __SP_XMLVIEW_ATTR_LIST_H__ - -/* - * Specialization of GtkTreeView for editing XML node attributes - * - * Authors: - * MenTaLguY <mental@rydia.net> - * - * Copyright (C) 2002 MenTaLguY - * - * Released under the GNU GPL; see COPYING for details - */ - -#include <gtk/gtk.h> - -#define SP_TYPE_XMLVIEW_ATTR_LIST (sp_xmlview_attr_list_get_type ()) -#define SP_XMLVIEW_ATTR_LIST(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_XMLVIEW_ATTR_LIST, SPXMLViewAttrList)) -#define SP_IS_XMLVIEW_ATTR_LIST(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SP_TYPE_XMLVIEW_ATTR_LIST)) -#define SP_XMLVIEW_ATTR_LIST_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SP_TYPE_XMLVIEW_ATTR_LIST)) - -struct SPXMLViewAttrList -{ - GtkTreeView list; - GtkListStore *store; - - Inkscape::XML::Node * repr; -}; - -struct SPXMLViewAttrListClass -{ - GtkTreeViewClass parent_class; - - void (* row_changed) (SPXMLViewAttrList *list, gint row); -}; - -GType sp_xmlview_attr_list_get_type (); -GtkWidget * sp_xmlview_attr_list_new (Inkscape::XML::Node * repr); - -#define SP_XMLVIEW_ATTR_LIST_GET_REPR(list) (SP_XMLVIEW_ATTR_LIST (list)->repr) - -gint attr_sort_name_iter (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer data); -void sp_xmlview_attr_list_set_repr (SPXMLViewAttrList * list, Inkscape::XML::Node * repr); -void sp_xmlview_attr_list_select_row_by_key(SPXMLViewAttrList * list, const gchar *name); -void attr_name_edited (GtkCellRendererText *cell, gchar * path_string, gchar * new_value, gpointer data); -void attr_value_edited (GtkCellRendererText *cell, gchar * path_string, gchar * new_value, gpointer data); -gboolean attr_key_pressed(GtkWidget *attributes, GdkEventKey *event, gpointer data); - -/* Attribute list store columns */ -enum { - ATTR_COL_NAME, - ATTR_COL_ATTR, - ATTR_COL_VALUE, - ATTR_N_COLS, -}; - -#endif |
