Code

Cleaned up DOS line ends that had snuck in.
[inkscape.git] / src / extension / paramnotebook.cpp
index cd8bddcaa0e435ceb59de3bafaa41d08922bd448..e8bd1e902273b6c768a80d20d25b67d3b4010670 100644 (file)
-/** \file\r
- * Notebook and NotebookPage parameters for extensions.\r
- */\r
-\r
-/*\r
- * Author:\r
- *   Johan Engelen <johan@shouraizou.nl>\r
- *\r
- * Copyright (C) 2006 Author\r
- *\r
- * Released under GNU GPL, read the file 'COPYING' for more information\r
- */\r
-\r
-#ifdef HAVE_CONFIG_H\r
-# include "config.h"\r
-#endif\r
-\r
-\r
-#include <gtkmm/adjustment.h>\r
-#include <gtkmm/box.h>\r
-#include <gtkmm/spinbutton.h>\r
-#include <gtkmm/notebook.h>\r
-#include <gtkmm/tooltips.h>\r
-\r
-#include <glibmm/i18n.h>\r
-\r
-#include <xml/node.h>\r
-\r
-#include "extension.h"\r
-#include "prefs-utils.h"\r
-#include "document-private.h"\r
-#include "sp-object.h"\r
-\r
-#include "paramnotebook.h"\r
-\r
-/** \brief  The root directory in the preferences database for extension\r
-            related parameters. */\r
-#define PREF_DIR "extensions"\r
-\r
-namespace Inkscape {\r
-namespace Extension {\r
-\r
-\r
-// \brief  A class to represent the pages of a notebookparameter of an extension\r
-class ParamNotebookPage : public Parameter {\r
-private:\r
-    GSList * parameters; /**< A table to store the parameters for this page.\r
-                              This only gets created if there are parameters on this\r
-                              page */\r
-    Gtk::Tooltips * _tooltips;\r
-    \r
-public:\r
-    static ParamNotebookPage * makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext);\r
-\r
-    ParamNotebookPage(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);\r
-    ~ParamNotebookPage(void);\r
-    Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);\r
-    Glib::ustring * paramString (void);\r
-    gchar * get_guitext (void) {return _text;};\r
-    \r
-}; /* class ParamNotebookPage */\r
-\r
-\r
-ParamNotebookPage::ParamNotebookPage (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :\r
-    Parameter(name, guitext, desc, scope, ext)\r
-{\r
-    parameters = NULL;\r
-        \r
-    // Read XML to build page\r
-    if (xml != NULL) {\r
-        Inkscape::XML::Node *child_repr = sp_repr_children(xml);\r
-        while (child_repr != NULL) {\r
-            char const * chname = child_repr->name();\r
-            if (chname[0] == '_') // Allow _ for translation of tags\r
-                chname++;\r
-            if (!strcmp(chname, "param") || !strcmp(chname, "_param")) {\r
-                Parameter * param;\r
-                param = Parameter::make(child_repr, ext);\r
-                if (param != NULL) parameters = g_slist_append(parameters, param);\r
-            }\r
-            child_repr = sp_repr_next(child_repr);\r
-        }\r
-    }\r
-    \r
-    return;\r
-}\r
-\r
-ParamNotebookPage::~ParamNotebookPage (void)\r
-{\r
-    if (_tooltips) delete _tooltips;\r
-    //destroy parameters\r
-    for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {\r
-        Parameter * param = reinterpret_cast<Parameter *>(list->data);\r
-        delete param;\r
-    }\r
-    g_slist_free(parameters);\r
-}\r
-\r
-/** \brief  Return the value as a string */\r
-Glib::ustring *\r
-ParamNotebookPage::paramString (void)\r
-{\r
-    Glib::ustring * param_string = new Glib::ustring("");\r
-\r
-    for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {\r
-        Parameter * param = reinterpret_cast<Parameter *>(list->data);\r
-\r
-        *param_string += " --";\r
-        *param_string += param->name();\r
-        *param_string += "=";\r
-        Glib::ustring * paramstr = param->string();\r
-        *param_string += *paramstr;\r
-        delete paramstr;\r
-    }\r
-\r
-    return param_string;\r
-}\r
-\r
-\r
-/**\r
-    \return None\r
-    \brief  This function creates a page that can be used later.  This\r
-            is typically done in the creation of the notebook and defined\r
-            in the XML file describing the extension (it's private so people\r
-            have to use the system) :)\r
-    \param  in_repr  The XML describing the page\r
-\r
-    This function first grabs all of the data out of the Repr and puts\r
-    it into local variables.  Actually, these are just pointers, and the\r
-    data is not duplicated so we need to be careful with it.  If there\r
-    isn't a name in the XML, then no page is created as\r
-    the function just returns.\r
-\r
-    From this point on, we're pretty committed as we've allocated an\r
-    object and we're starting to fill it.  The name is set first, and\r
-    is created with a strdup to actually allocate memory for it.  Then\r
-    there is a case statement (roughly because strcmp requires 'ifs')\r
-    based on what type of parameter this is.  Depending which type it\r
-    is, the value is interpreted differently, but they are relatively\r
-    straight forward.  In all cases the value is set to the default\r
-    value from the XML and the type is set to the interpreted type.\r
-*/\r
-ParamNotebookPage *\r
-ParamNotebookPage::makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)\r
-{\r
-    const char * name;\r
-    const char * guitext;\r
-    const char * desc;\r
-    const char * scope_str;\r
-    Parameter::_scope_t scope = Parameter::SCOPE_USER;\r
-\r
-    name = in_repr->attribute("name");\r
-    guitext = in_repr->attribute("gui-text");\r
-    if (guitext == NULL)\r
-        guitext = in_repr->attribute("_gui-text");\r
-    desc = in_repr->attribute("gui-description");\r
-    if (desc == NULL)\r
-        desc = in_repr->attribute("_gui-description");\r
-    scope_str = in_repr->attribute("scope");\r
-\r
-    /* In this case we just don't have enough information */\r
-    if (name == NULL) {\r
-        return NULL;\r
-    }\r
-\r
-    if (scope_str != NULL) {\r
-        if (!strcmp(scope_str, "user")) {\r
-            scope = Parameter::SCOPE_USER;\r
-        } else if (!strcmp(scope_str, "document")) {\r
-            scope = Parameter::SCOPE_DOCUMENT;\r
-        } else if (!strcmp(scope_str, "node")) {\r
-            scope = Parameter::SCOPE_NODE;\r
-        }\r
-    }\r
-\r
-    ParamNotebookPage * page = new ParamNotebookPage(name, guitext, desc, scope, in_ext, in_repr);\r
-    \r
-    /* Note: page could equal NULL */\r
-    return page;\r
-}\r
-\r
-\r
-\r
-/**\r
-    \brief  Creates a notebookpage widget for a notebook\r
-\r
-    Builds a notebook page (a vbox) and puts parameters on it.\r
-*/\r
-Gtk::Widget *\r
-ParamNotebookPage::get_widget (SPDocument * doc, Inkscape::XML::Node * node)\r
-{                      \r
-    if (!_tooltips) _tooltips = new Gtk::Tooltips();\r
-    \r
-    Gtk::VBox * vbox = Gtk::manage(new Gtk::VBox);\r
-    vbox->set_border_width(5);  \r
-    \r
-    // add parameters onto page (if any)    \r
-    for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {\r
-        Parameter * param = reinterpret_cast<Parameter *>(list->data);\r
-        Gtk::Widget * widg = param->get_widget(doc, node);\r
-        gchar const * tip = param->get_tooltip();\r
-        \r
-        vbox->pack_start(*widg, true, true, 2);\r
-        if (tip != NULL) {\r
-            _tooltips->set_tip(*widg, Glib::ustring(tip));\r
-        }\r
-    }\r
-        \r
-    vbox->show();\r
-    \r
-    return dynamic_cast<Gtk::Widget *>(vbox);\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-ParamNotebook::ParamNotebook (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :\r
-    Parameter(name, guitext, desc, scope, ext)\r
-{\r
-    pages = NULL;\r
-    \r
-    // Read XML tree to add pages:\r
-    if (xml != NULL) {\r
-        Inkscape::XML::Node *child_repr = sp_repr_children(xml);\r
-        while (child_repr != NULL) {\r
-            char const * chname = child_repr->name();\r
-            if (chname[0] == '_') // Allow _ for translation of tags\r
-                chname++;\r
-            if (!strcmp(chname, "page")) {\r
-                ParamNotebookPage * page;\r
-                page = ParamNotebookPage::makepage(child_repr, ext);\r
-                if (page != NULL) pages = g_slist_append(pages, page);\r
-            }\r
-            child_repr = sp_repr_next(child_repr);\r
-        }\r
-    }\r
-    \r
-    // Initialize _value with the current page\r
-    const char * defaultval = NULL;\r
-    // set first page as default\r
-    if (pages != NULL) {\r
-        ParamNotebookPage * defpage = reinterpret_cast<ParamNotebookPage *>(pages->data);\r
-        defaultval = defpage->name();\r
-    }\r
-\r
-    gchar * pref_name = this->pref_name();\r
-    const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);\r
-    g_free(pref_name);\r
-\r
-    if (paramval != NULL)\r
-        defaultval = paramval;\r
-    if (defaultval != NULL)\r
-        _value = g_strdup(defaultval);  // allocate space for _value\r
-        \r
-    return;\r
-}\r
-\r
-ParamNotebook::~ParamNotebook (void)\r
-{\r
-    //destroy pages\r
-    for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {\r
-        ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);\r
-        delete page;\r
-    }\r
-    g_slist_free(pages);\r
-\r
-    g_free(_value);\r
-}\r
-\r
-\r
-/** \brief  A function to set the \c _value\r
-    \param  in   The number of the page which value must be set\r
-    \param  doc  A document that should be used to set the value.\r
-    \param  node The node where the value may be placed\r
-\r
-    This function sets the internal value, but it also sets the value\r
-    in the preferences structure.  To put it in the right place, \c PREF_DIR\r
-    and \c pref_name() are used.\r
-\r
-    To copy the data into _value the old memory must be free'd first.\r
-    It is important to note that \c g_free handles \c NULL just fine.  Then\r
-    the passed in value is duplicated using \c g_strdup().\r
-*/\r
-const gchar *\r
-ParamNotebook::set (const int in, SPDocument * doc, Inkscape::XML::Node * node)\r
-{\r
-    ParamNotebookPage * page = NULL;\r
-    int i = 0;\r
-    for (GSList * list = pages; (list != NULL) && (i <= in); list = g_slist_next(list)) {\r
-        page = reinterpret_cast<ParamNotebookPage *>(list->data);\r
-        i++;\r
-    }\r
-    \r
-    if (page == NULL) return _value;\r
-   \r
-    if (_value != NULL) g_free(_value);\r
-    _value = g_strdup(page->name());\r
-\r
-    gchar * prefname = this->pref_name();\r
-    prefs_set_string_attribute(PREF_DIR, prefname, _value);\r
-    g_free(prefname);\r
-\r
-    return _value;\r
-}\r
-\r
-\r
-/**\r
-    \brief  A function to get the currentpage and the parameters in a string form\r
-    \return A string with the 'value' and all the parameters on all pages as command line arguments\r
-\r
-    This is really a hack. The function is called by Extension::paramString() to build\r
-    the commandline string like: '--param1name=\"param1value\" --param2name=\"param2value\" ...'\r
-    Extension::paramString expects this function to return '\"param1value\"'; but instead, \r
-    this function returns: '\"param1value\" --page1param1name=\"page1param1value\" ...'\r
-\r
-    \TODO  Do this better. For example, make Parameter::paramString() that returns '--name=\"value\"'\r
-    instead of just returning '\"value\"'.\r
-*/\r
-Glib::ustring *\r
-ParamNotebook::string (void)\r
-{\r
-    Glib::ustring * param_string = new Glib::ustring("");\r
-\r
-    *param_string += "\"";\r
-    *param_string += _value;  // the name of the current page\r
-    *param_string += "\"";\r
-\r
-    for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {\r
-        ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);\r
-\r
-        Glib::ustring * pageparamstr = page->paramString();\r
-        *param_string += *pageparamstr;\r
-        delete pageparamstr;\r
-    }\r
-\r
-    return param_string;\r
-}\r
-\r
-/** \brief  A special category of Gtk::Notebook to handle notebook parameters */\r
-class ParamNotebookWdg : public Gtk::Notebook {\r
-private:\r
-    ParamNotebook * _pref;\r
-    SPDocument * _doc;\r
-    Inkscape::XML::Node * _node;\r
-public:\r
-    /** \brief  Build a notebookpage preference for the given parameter\r
-        \param  pref  Where to get the string (pagename) from, and where to put it\r
-                      when it changes.\r
-    */\r
-    ParamNotebookWdg (ParamNotebook * pref, SPDocument * doc, Inkscape::XML::Node * node) :\r
-        Gtk::Notebook(), _pref(pref), _doc(doc), _node(node), activated(false) {\r
-        // don't have to set the correct page: this is done in ParamNotebook::get_widget.\r
-        // hook function\r
-        this->signal_switch_page().connect(sigc::mem_fun(this, &ParamNotebookWdg::changed_page));\r
-        return;\r
-    };\r
-    void changed_page(GtkNotebookPage *page, guint pagenum);\r
-    bool activated;\r
-};\r
-\r
-/** \brief  Respond to the selected page of notebook changing\r
-    This function responds to the changing by reporting it to\r
-    ParamNotebook. The change is only reported when the notebook\r
-    is actually visible. This to exclude 'fake' changes when the\r
-    notebookpages are added or removed.\r
-*/\r
-void\r
-ParamNotebookWdg::changed_page(GtkNotebookPage *page,\r
-                                   guint pagenum)\r
-{\r
-    if (is_visible()) {\r
-        _pref->set((int)pagenum, _doc, _node);\r
-    }\r
-    return;\r
-}\r
-\r
-\r
-\r
-/**\r
-    \brief  Creates a Notebook widget for a notebook parameter\r
-\r
-    Builds a notebook and puts pages in it.\r
-*/\r
-Gtk::Widget *\r
-ParamNotebook::get_widget (SPDocument * doc, Inkscape::XML::Node * node)\r
-{\r
-    ParamNotebookWdg * nb = Gtk::manage(new ParamNotebookWdg(this, doc, node));\r
-\r
-    // add pages (if any)    \r
-    int i = -1;\r
-    int pagenr = i;\r
-    for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {\r
-        i++;  \r
-        ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);\r
-        Gtk::Widget * widg = page->get_widget(doc, node);\r
-        nb->append_page(*widg, _(page->get_guitext()));\r
-        if (!strcmp(_value, page->name())) {\r
-            pagenr = i; // this is the page to be displayed?\r
-        }\r
-    }\r
-\r
-    nb->show();\r
-    \r
-    if (pagenr >= 0) nb->set_current_page(pagenr);\r
-\r
-    return dynamic_cast<Gtk::Widget *>(nb);\r
-}\r
-\r
-\r
-}  /* namespace Extension */\r
-}  /* namespace Inkscape */\r
-\r
-/*\r
-  Local Variables:\r
-  mode:c++\r
-  c-file-style:"stroustrup"\r
-  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
-  indent-tabs-mode:nil\r
-  fill-column:99\r
-  End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r
+/** \file
+ * Notebook and NotebookPage parameters for extensions.
+ */
+
+/*
+ * Author:
+ *   Johan Engelen <johan@shouraizou.nl>
+ *
+ * Copyright (C) 2006 Author
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+
+#include <gtkmm/adjustment.h>
+#include <gtkmm/box.h>
+#include <gtkmm/spinbutton.h>
+#include <gtkmm/notebook.h>
+#include <gtkmm/tooltips.h>
+
+#include <glibmm/i18n.h>
+
+#include <xml/node.h>
+
+#include "extension.h"
+#include "prefs-utils.h"
+#include "document-private.h"
+#include "sp-object.h"
+
+#include "paramnotebook.h"
+
+/** \brief  The root directory in the preferences database for extension
+            related parameters. */
+#define PREF_DIR "extensions"
+
+namespace Inkscape {
+namespace Extension {
+
+
+// \brief  A class to represent the pages of a notebookparameter of an extension
+class ParamNotebookPage : public Parameter {
+private:
+    GSList * parameters; /**< A table to store the parameters for this page.
+                              This only gets created if there are parameters on this
+                              page */
+    Gtk::Tooltips * _tooltips;
+    
+public:
+    static ParamNotebookPage * makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext);
+
+    ParamNotebookPage(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
+    ~ParamNotebookPage(void);
+    Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
+    Glib::ustring * paramString (void);
+    gchar * get_guitext (void) {return _text;};
+    
+}; /* class ParamNotebookPage */
+
+
+ParamNotebookPage::ParamNotebookPage (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
+    Parameter(name, guitext, desc, scope, ext)
+{
+    parameters = NULL;
+        
+    // Read XML to build page
+    if (xml != NULL) {
+        Inkscape::XML::Node *child_repr = sp_repr_children(xml);
+        while (child_repr != NULL) {
+            char const * chname = child_repr->name();
+            if (chname[0] == '_') // Allow _ for translation of tags
+                chname++;
+            if (!strcmp(chname, "param") || !strcmp(chname, "_param")) {
+                Parameter * param;
+                param = Parameter::make(child_repr, ext);
+                if (param != NULL) parameters = g_slist_append(parameters, param);
+            }
+            child_repr = sp_repr_next(child_repr);
+        }
+    }
+    
+    return;
+}
+
+ParamNotebookPage::~ParamNotebookPage (void)
+{
+    if (_tooltips) delete _tooltips;
+    //destroy parameters
+    for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {
+        Parameter * param = reinterpret_cast<Parameter *>(list->data);
+        delete param;
+    }
+    g_slist_free(parameters);
+}
+
+/** \brief  Return the value as a string */
+Glib::ustring *
+ParamNotebookPage::paramString (void)
+{
+    Glib::ustring * param_string = new Glib::ustring("");
+
+    for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {
+        Parameter * param = reinterpret_cast<Parameter *>(list->data);
+
+        *param_string += " --";
+        *param_string += param->name();
+        *param_string += "=";
+        Glib::ustring * paramstr = param->string();
+        *param_string += *paramstr;
+        delete paramstr;
+    }
+
+    return param_string;
+}
+
+
+/**
+    \return None
+    \brief  This function creates a page that can be used later.  This
+            is typically done in the creation of the notebook and defined
+            in the XML file describing the extension (it's private so people
+            have to use the system) :)
+    \param  in_repr  The XML describing the page
+
+    This function first grabs all of the data out of the Repr and puts
+    it into local variables.  Actually, these are just pointers, and the
+    data is not duplicated so we need to be careful with it.  If there
+    isn't a name in the XML, then no page is created as
+    the function just returns.
+
+    From this point on, we're pretty committed as we've allocated an
+    object and we're starting to fill it.  The name is set first, and
+    is created with a strdup to actually allocate memory for it.  Then
+    there is a case statement (roughly because strcmp requires 'ifs')
+    based on what type of parameter this is.  Depending which type it
+    is, the value is interpreted differently, but they are relatively
+    straight forward.  In all cases the value is set to the default
+    value from the XML and the type is set to the interpreted type.
+*/
+ParamNotebookPage *
+ParamNotebookPage::makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
+{
+    const char * name;
+    const char * guitext;
+    const char * desc;
+    const char * scope_str;
+    Parameter::_scope_t scope = Parameter::SCOPE_USER;
+
+    name = in_repr->attribute("name");
+    guitext = in_repr->attribute("gui-text");
+    if (guitext == NULL)
+        guitext = in_repr->attribute("_gui-text");
+    desc = in_repr->attribute("gui-description");
+    if (desc == NULL)
+        desc = in_repr->attribute("_gui-description");
+    scope_str = in_repr->attribute("scope");
+
+    /* In this case we just don't have enough information */
+    if (name == NULL) {
+        return NULL;
+    }
+
+    if (scope_str != NULL) {
+        if (!strcmp(scope_str, "user")) {
+            scope = Parameter::SCOPE_USER;
+        } else if (!strcmp(scope_str, "document")) {
+            scope = Parameter::SCOPE_DOCUMENT;
+        } else if (!strcmp(scope_str, "node")) {
+            scope = Parameter::SCOPE_NODE;
+        }
+    }
+
+    ParamNotebookPage * page = new ParamNotebookPage(name, guitext, desc, scope, in_ext, in_repr);
+    
+    /* Note: page could equal NULL */
+    return page;
+}
+
+
+
+/**
+    \brief  Creates a notebookpage widget for a notebook
+
+    Builds a notebook page (a vbox) and puts parameters on it.
+*/
+Gtk::Widget *
+ParamNotebookPage::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
+{                      
+    if (!_tooltips) _tooltips = new Gtk::Tooltips();
+    
+    Gtk::VBox * vbox = Gtk::manage(new Gtk::VBox);
+    vbox->set_border_width(5);  
+    
+    // add parameters onto page (if any)    
+    for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {
+        Parameter * param = reinterpret_cast<Parameter *>(list->data);
+        Gtk::Widget * widg = param->get_widget(doc, node);
+        gchar const * tip = param->get_tooltip();
+        
+        vbox->pack_start(*widg, true, true, 2);
+        if (tip != NULL) {
+            _tooltips->set_tip(*widg, Glib::ustring(tip));
+        }
+    }
+        
+    vbox->show();
+    
+    return dynamic_cast<Gtk::Widget *>(vbox);
+}
+
+
+
+
+
+
+
+
+
+ParamNotebook::ParamNotebook (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
+    Parameter(name, guitext, desc, scope, ext)
+{
+    pages = NULL;
+    
+    // Read XML tree to add pages:
+    if (xml != NULL) {
+        Inkscape::XML::Node *child_repr = sp_repr_children(xml);
+        while (child_repr != NULL) {
+            char const * chname = child_repr->name();
+            if (chname[0] == '_') // Allow _ for translation of tags
+                chname++;
+            if (!strcmp(chname, "page")) {
+                ParamNotebookPage * page;
+                page = ParamNotebookPage::makepage(child_repr, ext);
+                if (page != NULL) pages = g_slist_append(pages, page);
+            }
+            child_repr = sp_repr_next(child_repr);
+        }
+    }
+    
+    // Initialize _value with the current page
+    const char * defaultval = NULL;
+    // set first page as default
+    if (pages != NULL) {
+        ParamNotebookPage * defpage = reinterpret_cast<ParamNotebookPage *>(pages->data);
+        defaultval = defpage->name();
+    }
+
+    gchar * pref_name = this->pref_name();
+    const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
+    g_free(pref_name);
+
+    if (paramval != NULL)
+        defaultval = paramval;
+    if (defaultval != NULL)
+        _value = g_strdup(defaultval);  // allocate space for _value
+        
+    return;
+}
+
+ParamNotebook::~ParamNotebook (void)
+{
+    //destroy pages
+    for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {
+        ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);
+        delete page;
+    }
+    g_slist_free(pages);
+
+    g_free(_value);
+}
+
+
+/** \brief  A function to set the \c _value
+    \param  in   The number of the page which value must be set
+    \param  doc  A document that should be used to set the value.
+    \param  node The node where the value may be placed
+
+    This function sets the internal value, but it also sets the value
+    in the preferences structure.  To put it in the right place, \c PREF_DIR
+    and \c pref_name() are used.
+
+    To copy the data into _value the old memory must be free'd first.
+    It is important to note that \c g_free handles \c NULL just fine.  Then
+    the passed in value is duplicated using \c g_strdup().
+*/
+const gchar *
+ParamNotebook::set (const int in, SPDocument * doc, Inkscape::XML::Node * node)
+{
+    ParamNotebookPage * page = NULL;
+    int i = 0;
+    for (GSList * list = pages; (list != NULL) && (i <= in); list = g_slist_next(list)) {
+        page = reinterpret_cast<ParamNotebookPage *>(list->data);
+        i++;
+    }
+    
+    if (page == NULL) return _value;
+   
+    if (_value != NULL) g_free(_value);
+    _value = g_strdup(page->name());
+
+    gchar * prefname = this->pref_name();
+    prefs_set_string_attribute(PREF_DIR, prefname, _value);
+    g_free(prefname);
+
+    return _value;
+}
+
+
+/**
+    \brief  A function to get the currentpage and the parameters in a string form
+    \return A string with the 'value' and all the parameters on all pages as command line arguments
+
+    This is really a hack. The function is called by Extension::paramString() to build
+    the commandline string like: '--param1name=\"param1value\" --param2name=\"param2value\" ...'
+    Extension::paramString expects this function to return '\"param1value\"'; but instead, 
+    this function returns: '\"param1value\" --page1param1name=\"page1param1value\" ...'
+
+    \TODO  Do this better. For example, make Parameter::paramString() that returns '--name=\"value\"'
+    instead of just returning '\"value\"'.
+*/
+Glib::ustring *
+ParamNotebook::string (void)
+{
+    Glib::ustring * param_string = new Glib::ustring("");
+
+    *param_string += "\"";
+    *param_string += _value;  // the name of the current page
+    *param_string += "\"";
+
+    for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {
+        ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);
+
+        Glib::ustring * pageparamstr = page->paramString();
+        *param_string += *pageparamstr;
+        delete pageparamstr;
+    }
+
+    return param_string;
+}
+
+/** \brief  A special category of Gtk::Notebook to handle notebook parameters */
+class ParamNotebookWdg : public Gtk::Notebook {
+private:
+    ParamNotebook * _pref;
+    SPDocument * _doc;
+    Inkscape::XML::Node * _node;
+public:
+    /** \brief  Build a notebookpage preference for the given parameter
+        \param  pref  Where to get the string (pagename) from, and where to put it
+                      when it changes.
+    */
+    ParamNotebookWdg (ParamNotebook * pref, SPDocument * doc, Inkscape::XML::Node * node) :
+        Gtk::Notebook(), _pref(pref), _doc(doc), _node(node), activated(false) {
+        // don't have to set the correct page: this is done in ParamNotebook::get_widget.
+        // hook function
+        this->signal_switch_page().connect(sigc::mem_fun(this, &ParamNotebookWdg::changed_page));
+        return;
+    };
+    void changed_page(GtkNotebookPage *page, guint pagenum);
+    bool activated;
+};
+
+/** \brief  Respond to the selected page of notebook changing
+    This function responds to the changing by reporting it to
+    ParamNotebook. The change is only reported when the notebook
+    is actually visible. This to exclude 'fake' changes when the
+    notebookpages are added or removed.
+*/
+void
+ParamNotebookWdg::changed_page(GtkNotebookPage *page,
+                                   guint pagenum)
+{
+    if (is_visible()) {
+        _pref->set((int)pagenum, _doc, _node);
+    }
+    return;
+}
+
+
+
+/**
+    \brief  Creates a Notebook widget for a notebook parameter
+
+    Builds a notebook and puts pages in it.
+*/
+Gtk::Widget *
+ParamNotebook::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
+{
+    ParamNotebookWdg * nb = Gtk::manage(new ParamNotebookWdg(this, doc, node));
+
+    // add pages (if any)    
+    int i = -1;
+    int pagenr = i;
+    for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {
+        i++;  
+        ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);
+        Gtk::Widget * widg = page->get_widget(doc, node);
+        nb->append_page(*widg, _(page->get_guitext()));
+        if (!strcmp(_value, page->name())) {
+            pagenr = i; // this is the page to be displayed?
+        }
+    }
+
+    nb->show();
+    
+    if (pagenr >= 0) nb->set_current_page(pagenr);
+
+    return dynamic_cast<Gtk::Widget *>(nb);
+}
+
+
+}  /* namespace Extension */
+}  /* namespace Inkscape */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :