Code

adding a "scripting" tab to document properties dialog that allow the user to manage...
authorJucaBlues <JucaBlues@users.sourceforge.net>
Thu, 15 Jan 2009 18:01:02 +0000 (18:01 +0000)
committerJucaBlues <JucaBlues@users.sourceforge.net>
Thu, 15 Jan 2009 18:01:02 +0000 (18:01 +0000)
(also only working for "Inkscape SVG")

src/sp-script.cpp
src/sp-script.h
src/ui/dialog/document-properties.cpp
src/ui/dialog/document-properties.h
src/verbs.h

index 2b855e4554d803989747da7da56ab2fdd1147516..a4013245003c339ea3b91e47e177921cdfae84e7 100644 (file)
@@ -12,6 +12,9 @@
  */
 
 #include "sp-script.h"
+#include "attributes.h"
+#include <cstring>
+#include "document.h"
 
 static void sp_script_class_init(SPScriptClass *sc);
 static void sp_script_init(SPScript *script);
@@ -19,6 +22,8 @@ static void sp_script_init(SPScript *script);
 static void sp_script_release(SPObject *object);
 static void sp_script_update(SPObject *object, SPCtx *ctx, guint flags);
 static void sp_script_modified(SPObject *object, guint flags);
+static void sp_script_set(SPObject *object, unsigned int key, gchar const *value);
+static void sp_script_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
 static Inkscape::XML::Node *sp_script_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
 
 static SPObjectClass *parent_class;
@@ -51,10 +56,12 @@ static void sp_script_class_init(SPScriptClass *sc)
     parent_class = (SPObjectClass *) g_type_class_ref(SP_TYPE_OBJECT);
     SPObjectClass *sp_object_class = (SPObjectClass *) sc;
 
+    sp_object_class->build = sp_script_build;
     sp_object_class->release = sp_script_release;
     sp_object_class->update = sp_script_update;
     sp_object_class->modified = sp_script_modified;
     sp_object_class->write = sp_script_write;
+    sp_object_class->set = sp_script_set;
 }
 
 static void sp_script_init(SPScript */*script*/)
@@ -62,11 +69,34 @@ static void sp_script_init(SPScript */*script*/)
 
 }
 
+
+/**
+ * Reads the Inkscape::XML::Node, and initializes SPScript variables.  For this to get called,
+ * our name must be associated with a repr via "sp_object_type_register".  Best done through
+ * sp-object-repr.cpp's repr_name_entries array.
+ */
+static void
+sp_script_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
+{
+    if (((SPObjectClass *) parent_class)->build) {
+        ((SPObjectClass *) parent_class)->build(object, document, repr);
+    }
+
+    //Read values of key attributes from XML nodes into object.
+    sp_object_read_attr(object, "xlink:href");
+
+    sp_document_add_resource(document, "script", object);
+}
+
 static void sp_script_release(SPObject *object)
 {
-    if (((SPObjectClass *) (parent_class))->release) {
-        ((SPObjectClass *) (parent_class))->release(object);
+    if (SP_OBJECT_DOCUMENT(object)) {
+        /* Unregister ourselves */
+        sp_document_remove_resource(SP_OBJECT_DOCUMENT(object), "script", SP_OBJECT(object));
     }
+
+    if (((SPObjectClass *) parent_class)->release)
+        ((SPObjectClass *) parent_class)->release(object);
 }
 
 static void sp_script_update(SPObject */*object*/, SPCtx */*ctx*/, guint /*flags*/)
@@ -77,6 +107,24 @@ static void sp_script_modified(SPObject */*object*/, guint /*flags*/)
 {
 }
 
+static void
+sp_script_set(SPObject *object, unsigned int key, gchar const *value)
+{
+    SPScript *scr = SP_SCRIPT(object);
+
+    switch (key) {
+       case SP_ATTR_XLINK_HREF:
+            if (scr->xlinkhref) g_free(scr->xlinkhref);
+            scr->xlinkhref = g_strdup(value);
+            object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+            break;
+       default:
+            if (((SPObjectClass *) parent_class)->set)
+                ((SPObjectClass *) parent_class)->set(object, key, value);
+            break;
+    }
+}
+
 static Inkscape::XML::Node *sp_script_write(SPObject */*object*/, Inkscape::XML::Document */*xml_doc*/, Inkscape::XML::Node *repr, guint /*flags*/)
 {
 /*
index 8a48f9b929d29c2815079bfa443198e6648b27f5..fa1906052d816d81c597da1d26762b9e98f06e90 100644 (file)
@@ -23,6 +23,7 @@
 /* SPScript */
 
 struct SPScript : public SPObject {
+       gchar *xlinkhref;
 };
 
 struct SPScriptClass {
index 277652596aa95ac0e0ad36f349cd8b51fe104f2f..b2b3d1e8155ede6efc8062a2126fe2ca8e2c205c 100644 (file)
@@ -32,6 +32,7 @@
 #include "sp-namedview.h"
 #include "sp-object-repr.h"
 #include "sp-root.h"
+#include "sp-script.h"
 #include "ui/widget/color-picker.h"
 #include "ui/widget/scalar-unit.h"
 #include "verbs.h"
@@ -87,7 +88,7 @@ DocumentProperties::getInstance()
 DocumentProperties::DocumentProperties()
     : UI::Widget::Panel ("", "/dialogs/documentoptions", SP_VERB_DIALOG_NAMEDVIEW),
       _page_page(1, 1, true, true), _page_guides(1, 1),
-      _page_snap(1, 1), _page_snap_dtls(1, 1), _page_cms(1, 1),
+      _page_snap(1, 1), _page_snap_dtls(1, 1), _page_cms(1, 1), _page_scripting(1, 1),
     //---------------------------------------------------------------
       _rcb_canb(_("Show page _border"), _("If set, rectangular page border is shown"), "showborder", _wr, false),
       _rcb_bord(_("Border on _top of drawing"), _("If set, border is always on top of the drawing"), "borderlayer", _wr, false),
@@ -141,6 +142,7 @@ DocumentProperties::DocumentProperties()
     _notebook.append_page(_page_snap,      _("Snap"));
     _notebook.append_page(_page_snap_dtls, _("Snap points"));
     _notebook.append_page(_page_cms, _("Color Management"));
+    _notebook.append_page(_page_scripting, _("Scripting"));
 
     build_page();
     build_guides();
@@ -150,6 +152,7 @@ DocumentProperties::DocumentProperties()
 #if ENABLE_LCMS
     build_cms();
 #endif // ENABLE_LCMS
+    build_scripting();
 
     _grids_button_new.signal_clicked().connect(sigc::mem_fun(*this, &DocumentProperties::onNewGrid));
     _grids_button_remove.signal_clicked().connect(sigc::mem_fun(*this, &DocumentProperties::onRemoveGrid));
@@ -511,6 +514,13 @@ DocumentProperties::populate_linked_profiles_box()
     }
 }
 
+void DocumentProperties::external_scripts_list_button_release(GdkEventButton* event)
+{
+    if((event->type == GDK_BUTTON_RELEASE) && (event->button == 3)) {
+        _ExternalScriptsContextMenu.popup(event->button, event->time);
+    }
+}
+
 void DocumentProperties::linked_profiles_list_button_release(GdkEventButton* event)
 {
     if((event->type == GDK_BUTTON_RELEASE) && (event->button == 3)) {
@@ -518,7 +528,7 @@ void DocumentProperties::linked_profiles_list_button_release(GdkEventButton* eve
     }
 }
 
-void DocumentProperties::create_popup_menu(Gtk::Widget& parent, sigc::slot<void> rem)
+void DocumentProperties::cms_create_popup_menu(Gtk::Widget& parent, sigc::slot<void> rem)
 {
     Gtk::MenuItem* mi = Gtk::manage(new Gtk::ImageMenuItem(Gtk::Stock::REMOVE));
     _EmbProfContextMenu.append(*mi);
@@ -527,6 +537,16 @@ void DocumentProperties::create_popup_menu(Gtk::Widget& parent, sigc::slot<void>
     _EmbProfContextMenu.accelerate(parent);
 }
 
+
+void DocumentProperties::scripting_create_popup_menu(Gtk::Widget& parent, sigc::slot<void> rem)
+{
+    Gtk::MenuItem* mi = Gtk::manage(new Gtk::ImageMenuItem(Gtk::Stock::REMOVE));
+    _ExternalScriptsContextMenu.append(*mi);
+    mi->signal_activate().connect(rem);
+    mi->show();
+    _ExternalScriptsContextMenu.accelerate(parent);
+}
+
 void DocumentProperties::removeSelectedProfile(){
     Glib::ustring name;
     if(_LinkedProfilesList.get_selection()) {
@@ -609,7 +629,7 @@ DocumentProperties::build_cms()
     _link_btn.signal_clicked().connect(sigc::mem_fun(*this, &DocumentProperties::linkSelectedProfile));
 
     _LinkedProfilesList.signal_button_release_event().connect_notify(sigc::mem_fun(*this, &DocumentProperties::linked_profiles_list_button_release));
-    create_popup_menu(_LinkedProfilesList, sigc::mem_fun(*this, &DocumentProperties::removeSelectedProfile));
+    cms_create_popup_menu(_LinkedProfilesList, sigc::mem_fun(*this, &DocumentProperties::removeSelectedProfile));
 
     const GSList *current = sp_document_get_resource_list( SP_ACTIVE_DOCUMENT, "defs" );
     if (current) {
@@ -619,6 +639,121 @@ DocumentProperties::build_cms()
 }
 #endif // ENABLE_LCMS
 
+void
+DocumentProperties::build_scripting()
+{
+    _page_scripting.show();
+
+    Gtk::Label *label_script= manage (new Gtk::Label("", Gtk::ALIGN_LEFT));
+    label_script->set_markup (_("<b>External script files:</b>"));
+
+    _add_btn.set_label(_("Add"));
+
+    _page_scripting.set_spacing(4);
+    gint row = 0;
+
+    label_script->set_alignment(0.0);
+    _page_scripting.table().attach(*label_script, 0, 3, row, row + 1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0, 0, 0);
+    row++;
+    _page_scripting.table().attach(_ExternalScriptsListScroller, 0, 3, row, row + 1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0, 0, 0);
+    row++;
+
+    Gtk::HBox* spacer = Gtk::manage(new Gtk::HBox());
+    spacer->set_size_request(SPACE_SIZE_X, SPACE_SIZE_Y);
+    _page_scripting.table().attach(*spacer, 0, 3, row, row + 1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0, 0, 0);
+    row++;
+
+    _page_scripting.table().attach(_script_entry, 0, 2, row, row + 1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0, 0, 0);
+    _page_scripting.table().attach(_add_btn, 2, 3, row, row + 1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0, 0, 0);
+    row++;
+
+    //# Set up the External Scripts box
+    _ExternalScriptsListStore = Gtk::ListStore::create(_ExternalScriptsListColumns);
+    _ExternalScriptsList.set_model(_ExternalScriptsListStore);
+    _ExternalScriptsList.append_column(_("Filename"), _ExternalScriptsListColumns.filenameColumn);
+    _ExternalScriptsList.set_headers_visible(true);
+// TODO restore?    _ExternalScriptsList.set_fixed_height_mode(true);
+
+    populate_external_scripts_box();
+
+    _ExternalScriptsListScroller.add(_ExternalScriptsList);
+    _ExternalScriptsListScroller.set_shadow_type(Gtk::SHADOW_IN);
+    _ExternalScriptsListScroller.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS);
+    _ExternalScriptsListScroller.set_size_request(-1, 90);
+
+    _add_btn.signal_clicked().connect(sigc::mem_fun(*this, &DocumentProperties::addExternalScript));
+
+    _ExternalScriptsList.signal_button_release_event().connect_notify(sigc::mem_fun(*this, &DocumentProperties::external_scripts_list_button_release));
+    scripting_create_popup_menu(_ExternalScriptsList, sigc::mem_fun(*this, &DocumentProperties::removeExternalScript));
+
+//TODO: review this observers code:
+    const GSList *current = sp_document_get_resource_list( SP_ACTIVE_DOCUMENT, "script" );
+    if (current) {
+        _ext_scripts_observer.set(SP_OBJECT(current->data)->parent);
+    }
+    _ext_scripts_observer.signal_changed().connect(sigc::mem_fun(*this, &DocumentProperties::populate_external_scripts_box));
+}
+
+
+void DocumentProperties::addExternalScript(){
+    SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+    if (!desktop){
+        g_warning("No active desktop");
+    } else {
+        Inkscape::XML::Document *xml_doc = sp_document_repr_doc(desktop->doc());
+        Inkscape::XML::Node *scriptRepr = xml_doc->createElement("svg:script");
+        scriptRepr->setAttribute("xlink:href", (gchar*) _script_entry.get_text().c_str());
+        _script_entry.set_text("");
+
+        xml_doc->root()->addChild(scriptRepr, NULL);
+
+        // inform the document, so we can undo
+        sp_document_done(desktop->doc(), SP_VERB_EDIT_ADD_EXTERNAL_SCRIPT, _("Add external script..."));
+
+        populate_external_scripts_box();
+    }
+}
+
+void DocumentProperties::removeExternalScript(){
+    Glib::ustring name;
+    if(_ExternalScriptsList.get_selection()) {
+        Gtk::TreeModel::iterator i = _ExternalScriptsList.get_selection()->get_selected();
+
+        if(i){
+            name = (*i)[_ExternalScriptsListColumns.filenameColumn];
+        } else {
+            return;
+        }
+    }
+
+    const GSList *current = sp_document_get_resource_list( SP_ACTIVE_DOCUMENT, "script" );
+    while ( current ) {
+        SPObject* obj = SP_OBJECT(current->data);
+        SPScript* script = (SPScript*) obj;
+        if (!name.compare(script->xlinkhref)){
+            sp_repr_unparent(obj->repr);
+            sp_document_done(SP_ACTIVE_DOCUMENT, SP_VERB_EDIT_REMOVE_EXTERNAL_SCRIPT, _("Remove external script"));
+        }
+        current = g_slist_next(current);
+    }
+
+    populate_external_scripts_box();
+
+}
+
+void DocumentProperties::populate_external_scripts_box(){
+    _ExternalScriptsListStore->clear();
+    const GSList *current = sp_document_get_resource_list( SP_ACTIVE_DOCUMENT, "script" );
+    if (current) _ext_scripts_observer.set(SP_OBJECT(current->data)->parent);
+    while ( current ) {
+        SPObject* obj = SP_OBJECT(current->data);
+        SPScript* script = (SPScript*) obj;
+        Gtk::TreeModel::Row row = *(_ExternalScriptsListStore->append());
+        row[_ExternalScriptsListColumns.filenameColumn] = script->xlinkhref;
+        current = g_slist_next(current);
+    }
+}
+
 /**
 * Called for _updating_ the dialog (e.g. when a new grid was manually added in XML)
 */
index f4d5724bec922fdded0e8e43b6c89b5db102dff2..df16edca7b4c52eb1d6aef9cba96972ac2b8e441 100644 (file)
@@ -52,6 +52,7 @@ protected:
 #if ENABLE_LCMS
     void  build_cms();
 #endif // ENABLE_LCMS
+    void  build_scripting();
     void  init();
 
     virtual void  on_response (int);
@@ -61,19 +62,25 @@ protected:
     void  linkSelectedProfile();
     void  removeSelectedProfile();
     void  linked_profiles_list_button_release(GdkEventButton* event);
-    void  create_popup_menu(Gtk::Widget& parent, sigc::slot<void> rem);
+    void  cms_create_popup_menu(Gtk::Widget& parent, sigc::slot<void> rem);
 #endif // ENABLE_LCMS
 
+    void  external_scripts_list_button_release(GdkEventButton* event);
+    void  populate_external_scripts_box();
+    void  addExternalScript();
+    void  removeExternalScript();
+    void  scripting_create_popup_menu(Gtk::Widget& parent, sigc::slot<void> rem);
+
     void _handleDocumentReplaced(SPDesktop* desktop, SPDocument *document);
     void _handleActivateDesktop(Inkscape::Application *application, SPDesktop *desktop);
     void _handleDeactivateDesktop(Inkscape::Application *application, SPDesktop *desktop);
 
-    Inkscape::XML::SignalObserver _emb_profiles_observer;
+    Inkscape::XML::SignalObserver _emb_profiles_observer, _ext_scripts_observer;
     Gtk::Tooltips _tt;
     Gtk::Notebook  _notebook;
 
     NotebookPage   _page_page, _page_guides;
-    NotebookPage   _page_snap, _page_snap_dtls, _page_cms;
+    NotebookPage   _page_snap, _page_snap_dtls, _page_cms, _page_scripting;
     Gtk::VBox      _grids_vbox;
 
     Registry _wr;
@@ -109,7 +116,24 @@ protected:
     Gtk::TreeView _LinkedProfilesList;
     Gtk::ScrolledWindow _LinkedProfilesListScroller;
     Gtk::Menu _EmbProfContextMenu;
+
     //---------------------------------------------------------------
+    Gtk::Button         _add_btn;
+    class ExternalScriptsColumns : public Gtk::TreeModel::ColumnRecord
+        {
+        public:
+            ExternalScriptsColumns()
+               { add(filenameColumn); }
+            Gtk::TreeModelColumn<Glib::ustring> filenameColumn;
+        };
+    ExternalScriptsColumns _ExternalScriptsListColumns;
+    Glib::RefPtr<Gtk::ListStore> _ExternalScriptsListStore;
+    Gtk::TreeView _ExternalScriptsList;
+    Gtk::ScrolledWindow _ExternalScriptsListScroller;
+    Gtk::Menu _ExternalScriptsContextMenu;
+    Gtk::Entry _script_entry;
+    //---------------------------------------------------------------
+
     Gtk::Notebook   _grids_notebook;
     Gtk::HBox       _grids_hbox_crea;
     Gtk::Label      _grids_label_crea;
index 28812dde618f31de0610cb62749bbe2931c64438..7798f63640fec566f999bf96984e543cdb5dc31b 100644 (file)
@@ -274,6 +274,9 @@ enum {
     /* Color management */
     SP_VERB_EDIT_LINK_COLOR_PROFILE,
     SP_VERB_EDIT_REMOVE_COLOR_PROFILE,
+    /*Scripting*/
+    SP_VERB_EDIT_ADD_EXTERNAL_SCRIPT,
+    SP_VERB_EDIT_REMOVE_EXTERNAL_SCRIPT,
     /* Footer */
     SP_VERB_LAST
 };