Code

NR::Maybe => boost::optional
[inkscape.git] / src / widgets / toolbox.cpp
index 6669f5825926565a30c791b636abd906deb26506..07b388d140127087fdd2283e75babdc92a200168 100644 (file)
@@ -51,6 +51,7 @@
 #include "desktop-handles.h"
 #include "xml/repr.h"
 #include "xml/node-event-vector.h"
+#include "xml/attribute-record.h"
 #include <glibmm/i18n.h>
 #include "helper/unit-menu.h"
 #include "helper/units.h"
@@ -65,7 +66,7 @@
 
 #include "connector-context.h"
 #include "node-context.h"
-#include "draw-context.h"
+#include "pen-context.h"
 #include "shape-editor.h"
 #include "tweak-context.h"
 #include "sp-rect.h"
@@ -79,6 +80,7 @@
 #include "sp-clippath.h"
 #include "sp-mask.h"
 #include "style.h"
+#include "tools-switch.h"
 #include "selection.h"
 #include "selection-chemistry.h"
 #include "document-private.h"
@@ -220,11 +222,7 @@ static struct {
     { NULL, NULL, NULL, NULL, NULL, SP_VERB_INVALID, NULL, NULL }
 };
 
-#if GTK_CHECK_VERSION(2,12,0)
-#define TOOLBAR_SLIDER_HINT "minimal"
-#else // GTK_CHECK_VERSION(2,12,0)
 #define TOOLBAR_SLIDER_HINT "full"
-#endif // GTK_CHECK_VERSION(2,12,0)
 
 static gchar const * ui_descr =
         "<ui>"
@@ -369,23 +367,24 @@ static gchar const * ui_descr =
         "  </toolbar>"
 
         "  <toolbar name='PenToolbar'>"
-        "    <toolitem action='FreehandModeActionPenTemp' />"
         "    <toolitem action='FreehandModeActionPen' />"
+        "    <separator />"
+        "    <toolitem action='SetPenShapeAction'/>"
         "  </toolbar>"
 
         "  <toolbar name='PencilToolbar'>"
-        "    <toolitem action='FreehandModeActionPencilTemp' />"
         "    <toolitem action='FreehandModeActionPencil' />"
         "    <separator />"
         "    <toolitem action='PencilToleranceAction' />"
         "    <separator />"
         "    <toolitem action='PencilResetAction' />"
+        "    <separator />"
+        "    <toolitem action='SetPencilShapeAction'/>"
         "  </toolbar>"
 
         "  <toolbar name='CalligraphyToolbar'>"
         "    <separator />"
         "    <toolitem action='SetProfileAction'/>"
-        "    <toolitem action='SaveDeleteProfileAction'/>"
         "    <separator />"
         "    <toolitem action='CalligraphyWidthAction' />"
         "    <toolitem action='PressureAction' />"
@@ -512,7 +511,7 @@ Glib::RefPtr<VerbAction> VerbAction::create(Inkscape::Verb* verb, Inkscape::Verb
 }
 
 VerbAction::VerbAction(Inkscape::Verb* verb, Inkscape::Verb* verb2, Inkscape::UI::View::View *view, GtkTooltips *tooltips) :
-    Gtk::Action(Glib::ustring(verb->get_id()), Gtk::StockID(GTK_STOCK_ABOUT), Glib::ustring(_(verb->get_name())), Glib::ustring(_(verb->get_tip()))),
+    Gtk::Action(Glib::ustring(verb->get_id()), Gtk::StockID(verb->get_image()), Glib::ustring(_(verb->get_name())), Glib::ustring(_(verb->get_tip()))),
     verb(verb),
     verb2(verb2),
     view(view),
@@ -527,6 +526,11 @@ VerbAction::~VerbAction()
 
 Gtk::Widget* VerbAction::create_menu_item_vfunc()
 {
+// First call in to get the icon rendered if present in SVG
+    Gtk::Widget *widget = sp_icon_get_icon( property_stock_id().get_value().get_string(), Inkscape::ICON_SIZE_MENU );
+    delete widget;
+    widget = 0;
+
     Gtk::Widget* widg = Gtk::Action::create_menu_item_vfunc();
 //     g_message("create_menu_item_vfunc() = %p  for '%s'", widg, verb->get_id());
     return widg;
@@ -1093,18 +1097,18 @@ sp_node_toolbox_coord_changed(gpointer /*shape_editor*/, GObject *tbl)
         } else {
             gtk_action_set_sensitive(xact, TRUE);
             gtk_action_set_sensitive(yact, TRUE);
-            NR::Coord oldx = sp_units_get_pixels(gtk_adjustment_get_value(xadj), *unit);
-            NR::Coord oldy = sp_units_get_pixels(gtk_adjustment_get_value(xadj), *unit);
+            Geom::Coord oldx = sp_units_get_pixels(gtk_adjustment_get_value(xadj), *unit);
+            Geom::Coord oldy = sp_units_get_pixels(gtk_adjustment_get_value(xadj), *unit);
 
             if (n_selected == 1) {
-                NR::Point sel_node = nodepath->singleSelectedCoords();
-                if (oldx != sel_node[NR::X] || oldy != sel_node[NR::Y]) {
-                    gtk_adjustment_set_value(xadj, sp_pixels_get_units(sel_node[NR::X], *unit));
-                    gtk_adjustment_set_value(yadj, sp_pixels_get_units(sel_node[NR::Y], *unit));
+                Geom::Point sel_node = nodepath->singleSelectedCoords();
+                if (oldx != sel_node[Geom::X] || oldy != sel_node[Geom::Y]) {
+                    gtk_adjustment_set_value(xadj, sp_pixels_get_units(sel_node[Geom::X], *unit));
+                    gtk_adjustment_set_value(yadj, sp_pixels_get_units(sel_node[Geom::Y], *unit));
                 }
             } else {
-                NR::Maybe<NR::Coord> x = sp_node_selected_common_coord(nodepath, NR::X);
-                NR::Maybe<NR::Coord> y = sp_node_selected_common_coord(nodepath, NR::Y);
+                boost::optional<Geom::Coord> x = sp_node_selected_common_coord(nodepath, Geom::X);
+                boost::optional<Geom::Coord> y = sp_node_selected_common_coord(nodepath, Geom::Y);
                 if ((x && ((*x) != oldx)) || (y && ((*y) != oldy))) {
                     /* Note: Currently x and y will always have a value, even if the coordinates of the
                        selected nodes don't coincide (in this case we use the coordinates of the center
@@ -1149,10 +1153,10 @@ sp_node_path_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *value_
     if (shape_editor && shape_editor->has_nodepath()) {
         double val = sp_units_get_pixels(gtk_adjustment_get_value(adj), *unit);
         if (!strcmp(value_name, "x")) {
-            sp_node_selected_move_absolute(shape_editor->get_nodepath(), val, NR::X);
+            sp_node_selected_move_absolute(shape_editor->get_nodepath(), val, Geom::X);
         }
         if (!strcmp(value_name, "y")) {
-            sp_node_selected_move_absolute(shape_editor->get_nodepath(), val, NR::Y);
+            sp_node_selected_move_absolute(shape_editor->get_nodepath(), val, Geom::Y);
         }
     }
 
@@ -1597,7 +1601,7 @@ setup_tool_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
 
 
 static void
-update_tool_toolbox( SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget *toolbox )
+update_tool_toolbox( SPDesktop *desktop, SPEventContext *eventcontext, GtkWidget */*toolbox*/ )
 {
     gchar const *const tname = ( eventcontext
                                  ? gtk_type_name(GTK_OBJECT_TYPE(eventcontext))
@@ -3261,34 +3265,40 @@ static void sp_spiral_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActio
 }
 
 //########################
-//##     Pen/Pencil    ##
+//##     Pen/Pencil     ##
 //########################
 
-static void sp_pc_spiro_spline_mode_changed(EgeSelectOneAction* act, GObject* /*tbl*/)
+/* This is used in generic functions below to share large portions of code between pen and pencil tool */
+static char const *
+freehand_tool_name(GObject *dataKludge)
 {
-    prefs_set_int_attribute("tools.freehand", "spiro-spline-mode", ege_select_one_action_get_active(act));
+    SPDesktop *desktop = (SPDesktop *) g_object_get_data(dataKludge, "desktop");
+    return ( tools_isactive(desktop, TOOLS_FREEHAND_PEN)
+             ? "tools.freehand.pen"
+             : "tools.freehand.pencil" );
 }
 
-static void sp_add_spiro_toggle(GtkActionGroup* mainActions, GObject* holder, bool tool_is_pencil)
+static void freehand_mode_changed(EgeSelectOneAction* act, GObject* tbl)
 {
-    // FIXME: No action is needed, we only want a simple label. But sp_toolbox_add_label() always
-    //        adds the label at the end of the toolbar, whence this workarund. How to avoid this?
-    {
-        EgeOutputAction* act = ege_output_action_new(
-            tool_is_pencil ?
-            "FreehandModeActionPencilTemp" :
-            "FreehandModeActionPenTemp",
-            _("<b>Mode:</b>"), "", 0 );
-        ege_output_action_set_use_markup( act, TRUE );
-        gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
-        g_object_set_data( holder, "freehand_mode_action", act );
+    gint mode = ege_select_one_action_get_active(act);
+
+    prefs_set_int_attribute(freehand_tool_name(tbl), "freehand-mode", mode);
+
+    SPDesktop *desktop = (SPDesktop *) g_object_get_data(tbl, "desktop");
+
+    // in pen tool we have more options than in pencil tool; if one of them was chosen, we do any
+    // preparatory work here
+    if (SP_IS_PEN_CONTEXT(desktop->event_context)) {
+        SPPenContext *pc = SP_PEN_CONTEXT(desktop->event_context);
+        pc->polylines_only = (mode == 2);
     }
+}
 
+static void sp_add_freehand_mode_toggle(GtkActionGroup* mainActions, GObject* holder, bool tool_is_pencil)
+{
     /* Freehand mode toggle buttons */
     {
-        //gchar const *flatsidedstr = prefs_get_string_attribute( "tools.shapes.star", "isflatsided" );
-        //bool isSpiroMode = flatsidedstr ? (strcmp(flatsidedstr, "false") != 0) : true;
-        guint spiroMode = prefs_get_int_attribute("tools.freehand", "spiro-spline-mode", 0);
+        guint freehandMode = prefs_get_int_attribute(tool_is_pencil ? "tools.freehand.pencil" : "tools.freehand.pen", "freehand-mode", 0);
         Inkscape::IconSize secondarySize = prefToSize("toolbox", "secondary", 1);
 
         {
@@ -3297,24 +3307,32 @@ static void sp_add_spiro_toggle(GtkActionGroup* mainActions, GObject* holder, bo
             GtkTreeIter iter;
             gtk_list_store_append( model, &iter );
             gtk_list_store_set( model, &iter,
-                                0, _("Bézier"),
-                                1, _("Regular Bézier mode"),
+                                0, _("Bezier"),
+                                1, _("Create regular Bezier path"),
                                 2, "bezier_mode",
                                 -1 );
 
             gtk_list_store_append( model, &iter );
             gtk_list_store_set( model, &iter,
                                 0, _("Spiro"),
-                                1, _("Spiro splines mode"),
+                                1, _("Create Spiro path"),
                                 2, "spiro_splines_mode",
                                 -1 );
 
+            if (!tool_is_pencil) {
+                gtk_list_store_append( model, &iter );
+                gtk_list_store_set( model, &iter,
+                                    0, _("Zigzag"),
+                                    1, _("Create a sequence of straight line segments"),
+                                    2, "polylines_mode",
+                                    -1 );
+            }
+
             EgeSelectOneAction* act = ege_select_one_action_new(tool_is_pencil ?
                                                                 "FreehandModeActionPencil" :
                                                                 "FreehandModeActionPen",
-                                                                (""), (""), NULL, GTK_TREE_MODEL(model) );
+                                                                (_("Mode:")), ("Mode"), NULL, GTK_TREE_MODEL(model) );
             gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
-            g_object_set_data( holder, "freehande_mode_action", act );
 
             ege_select_one_action_set_appearance( act, "full" );
             ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE );
@@ -3323,15 +3341,65 @@ static void sp_add_spiro_toggle(GtkActionGroup* mainActions, GObject* holder, bo
             ege_select_one_action_set_icon_size( act, secondarySize );
             ege_select_one_action_set_tooltip_column( act, 1  );
 
-            ege_select_one_action_set_active( act, spiroMode);
-            g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_pc_spiro_spline_mode_changed), holder);
+            ege_select_one_action_set_active( act, freehandMode);
+            g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(freehand_mode_changed), holder);
+        }
+    }
+}
+
+static void freehand_change_shape(EgeSelectOneAction* act, GObject *dataKludge) {
+    gint shape = ege_select_one_action_get_active( act );
+    prefs_set_int_attribute(freehand_tool_name(dataKludge), "shape", shape);
+}
+
+/**
+ * \brief Generate the list of freehand advanced shape option entries.
+ */
+GList * freehand_shape_dropdown_items_list() {
+    GList *glist = NULL;
+
+    glist = g_list_append (glist, _("None"));
+    glist = g_list_append (glist, _("Triangle in"));
+    glist = g_list_append (glist, _("Triangle out"));
+    glist = g_list_append (glist, _("Ellipse"));
+    glist = g_list_append (glist, _("From clipboard"));
+
+    return glist;
+}
+
+static void
+freehand_add_advanced_shape_options(GtkActionGroup* mainActions, GObject* holder, bool tool_is_pencil) {
+    /*advanced shape options */
+    {
+        GtkListStore* model = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT );
+
+        GList* items = 0;
+        gint count = 0;
+        for ( items = freehand_shape_dropdown_items_list(); items ; items = g_list_next(items) )
+        {
+            GtkTreeIter iter;
+            gtk_list_store_append( model, &iter );
+            gtk_list_store_set( model, &iter, 0, reinterpret_cast<gchar*>(items->data), 1, count, -1 );
+            count++;
         }
+        g_list_free( items );
+        items = 0;
+        EgeSelectOneAction* act1 = ege_select_one_action_new(
+            tool_is_pencil ? "SetPencilShapeAction" : "SetPenShapeAction",
+            _("Shape:"), ("Shape"), NULL, GTK_TREE_MODEL(model));
+        g_object_set( act1, "short_label", _("Shape:"), NULL );
+        ege_select_one_action_set_appearance( act1, "compact" );
+        ege_select_one_action_set_active( act1, prefs_get_int_attribute(tool_is_pencil ? "tools.freehand.pencil" : "tools.freehand.pen", "shape", 0) );
+        g_signal_connect( G_OBJECT(act1), "changed", G_CALLBACK(freehand_change_shape), holder );
+        gtk_action_group_add_action( mainActions, GTK_ACTION(act1) );
+        g_object_set_data( holder, "shape_action", act1 );
     }
 }
 
 static void sp_pen_toolbox_prep(SPDesktop */*desktop*/, GtkActionGroup* mainActions, GObject* holder)
 {
-    sp_add_spiro_toggle(mainActions, holder, false);
+    sp_add_freehand_mode_toggle(mainActions, holder, false);
+    freehand_add_advanced_shape_options(mainActions, holder, false);
 }
 
 
@@ -3371,11 +3439,11 @@ sp_pencil_tb_tolerance_value_changed(GtkAdjustment *adj, GObject *tbl)
 
 
 static void
-sp_pencil_tb_tolerance_value_changed_external(Inkscape::XML::Node *repr,
-                                              const gchar *key,
-                                              const gchar *oldval,
-                                              const gchar *newval,
-                                              bool is_interactive,
+sp_pencil_tb_tolerance_value_changed_external(Inkscape::XML::Node */*repr*/,
+                                              const gchar */*key*/,
+                                              const gchar */*oldval*/,
+                                              const gchar */*newval*/,
+                                              bool /*is_interactive*/,
                                               void * data)
 {
     GObject* tbl = G_OBJECT(data);
@@ -3407,22 +3475,23 @@ static Inkscape::XML::NodeEventVector pencil_node_events =
 
 static void sp_pencil_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
 {
-    sp_add_spiro_toggle(mainActions, holder, true);
+    sp_add_freehand_mode_toggle(mainActions, holder, true);
 
     EgeAdjustmentAction* eact = 0;
 
     /* Tolerance */
     {
-
+        gchar const* labels[] = {_("(many nodes, rough)"), ("(default)"), 0, 0, 0, 0, ("(few nodes, smooth)")};
+        gdouble values[] = {1, 10, 20, 30, 50, 75, 100};
         eact = create_adjustment_action( "PencilToleranceAction",
-                 _("Number of pixels allowed in interpolating"),
-                                         _("Tolerance:"), _("Tolerance"),
+                                         _("Smoothing:"), _("Smoothing: "),
+                 _("How much smoothing (simplifying) is applied to the line"),
                                          "tools.freehand.pencil", "tolerance",
                                          3.0,
                                          GTK_WIDGET(desktop->canvas), NULL,
                                          holder, TRUE, "altx-pencil",
-                                         0.5, 100.0, 0.5, 0,
-                                         NULL, NULL, 0,
+                                         1, 100.0, 0.5, 0,
+                                         labels, values, G_N_ELEMENTS(labels),
                                          sp_pencil_tb_tolerance_value_changed,
                                          1, 2);
         ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
@@ -3434,6 +3503,10 @@ static void sp_pencil_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActio
         g_object_set_data(G_OBJECT(holder), "repr", repr);
 
     }
+
+    /* advanced shape options */
+    freehand_add_advanced_shape_options(mainActions, holder, true);
+
     /* Reset */
     {
         InkAction* inky = ink_action_new( "PencilResetAction",
@@ -3745,22 +3818,75 @@ static void sp_tweak_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction
 //########################
 //##     Calligraphy    ##
 //########################
-static void update_presets_list(GObject *dataKludge ){
-    EgeSelectOneAction *sel = static_cast<EgeSelectOneAction *>(g_object_get_data(dataKludge, "profile_selector"));
-    if (sel) {
-        ege_select_one_action_set_active(sel, 0 );
+static void update_presets_list (GObject *tbl)
+{
+    if (g_object_get_data(tbl, "presets_blocked"))
+        return;
+
+    EgeSelectOneAction *sel = static_cast<EgeSelectOneAction *>(g_object_get_data(tbl, "profile_selector"));
+    if (!sel) {
+        ege_select_one_action_set_active(sel, 0);
+        return;
+    }
+
+    int total_prefs = pref_path_number_of_children("tools.calligraphic.preset");
+
+    for (int i = 1; i <= total_prefs; i++) {
+        gchar *preset_path = get_pref_nth_child("tools.calligraphic.preset", i);
+        Inkscape::XML::Node *preset_repr = inkscape_get_repr(INKSCAPE, preset_path);
+
+        bool match = true;
+
+        for ( Inkscape::Util::List<Inkscape::XML::AttributeRecord const> iter = preset_repr->attributeList();
+              iter; 
+              ++iter ) {
+            const gchar *attr_name = g_quark_to_string(iter->key);
+            if (!strcmp(attr_name, "id") || !strcmp(attr_name, "name"))
+                continue;
+            void *widget = g_object_get_data(tbl, attr_name);
+            if (widget) {
+                if (GTK_IS_ADJUSTMENT(widget)) {
+                    double v = prefs_get_double_attribute(preset_path, attr_name, 0); // fixme: no min/max checks here, add?
+                    GtkAdjustment* adj = static_cast<GtkAdjustment *>(widget);
+                    //std::cout << "compared adj " << attr_name << gtk_adjustment_get_value(adj) << " to " << v << "\n";
+                    if (fabs(gtk_adjustment_get_value(adj) - v) > 1e-6) {
+                        match = false;
+                        break;
+                    }
+                } else if (GTK_IS_TOGGLE_ACTION(widget)) {
+                    int v = prefs_get_int_attribute(preset_path, attr_name, 0); // fixme: no min/max checks here, add?
+                    GtkToggleAction* toggle = static_cast<GtkToggleAction *>(widget);
+                    //std::cout << "compared toggle " << attr_name << gtk_toggle_action_get_active(toggle) << " to " << v << "\n";
+                    if (gtk_toggle_action_get_active(toggle) != v) {
+                        match = false;
+                        break;
+                    }
+                } 
+            } 
+        }
+
+        if (match) {
+            // newly added item is at the same index as the 
+            // save command, so we need to change twice for it to take effect
+            ege_select_one_action_set_active(sel, 0);
+            ege_select_one_action_set_active(sel, i);
+            return;
+        }
     }
+
+    // no match found
+    ege_select_one_action_set_active(sel, 0);
 }
 
 static void sp_ddc_mass_value_changed( GtkAdjustment *adj, GObject* tbl )
 {
-    prefs_set_double_attribute( "tools.calligraphic", "mass", adj->value );
+    prefs_set_double_attribute( "tools.calligraphic", "mass", adj->value * 0.01 );
     update_presets_list(tbl);
 }
 
 static void sp_ddc_wiggle_value_changed( GtkAdjustment *adj, GObject* tbl )
 {
-    prefs_set_double_attribute( "tools.calligraphic", "wiggle", adj->value );
+    prefs_set_double_attribute( "tools.calligraphic", "wiggle", adj->value * 0.01 );
     update_presets_list(tbl);
 }
 
@@ -3778,19 +3904,19 @@ static void sp_ddc_width_value_changed( GtkAdjustment *adj, GObject *tbl )
 
 static void sp_ddc_velthin_value_changed( GtkAdjustment *adj, GObject* tbl )
 {
-    prefs_set_double_attribute("tools.calligraphic", "thinning", adj->value);
+    prefs_set_double_attribute("tools.calligraphic", "thinning", adj->value * 0.01 );
     update_presets_list(tbl);
 }
 
 static void sp_ddc_flatness_value_changed( GtkAdjustment *adj, GObject* tbl )
 {
-    prefs_set_double_attribute( "tools.calligraphic", "flatness", adj->value );
+    prefs_set_double_attribute( "tools.calligraphic", "flatness", adj->value * 0.01);
     update_presets_list(tbl);
 }
 
 static void sp_ddc_tremor_value_changed( GtkAdjustment *adj, GObject* tbl )
 {
-    prefs_set_double_attribute( "tools.calligraphic", "tremor", adj->value );
+    prefs_set_double_attribute( "tools.calligraphic", "tremor", adj->value * 0.01 );
     update_presets_list(tbl);
 }
 
@@ -3814,7 +3940,7 @@ static void sp_ddc_trace_background_changed( GtkToggleAction *act, GObject*  tbl
 
 static void sp_ddc_tilt_state_changed( GtkToggleAction *act, GObject*  tbl )
 {
-    GtkAction * calligraphy_angle = static_cast<GtkAction *> (g_object_get_data(tbl,"angle"));
+    GtkAction * calligraphy_angle = static_cast<GtkAction *> (g_object_get_data(tbl,"angle_action"));
     prefs_set_int_attribute( "tools.calligraphic", "usetilt", gtk_toggle_action_get_active( act ) ? 1 : 0 );
     update_presets_list(tbl);
     if (calligraphy_angle )
@@ -3822,103 +3948,185 @@ static void sp_ddc_tilt_state_changed( GtkToggleAction *act, GObject*  tbl )
 }
 
 
-#define PROFILE_FLOAT_SIZE 7
-#define PROFILE_INT_SIZE 4
-struct ProfileFloatElement {
-    char const *name;
-    double def;
-    double min;
-    double max;
-};
-struct ProfileIntElement {
-    char const *name;
-    int def;
-    int min;
-    int max;
+static gchar const *const widget_names[] = {
+    "width",
+    "mass",
+    "wiggle",
+    "angle",
+    "thinning",
+    "tremor",
+    "flatness",
+    "cap_rounding",
+    "usepressure",
+    "tracebackground",
+    "usetilt"
 };
 
 
+static void sp_dcc_build_presets_list(GObject *tbl) 
+{
+    g_object_set_data(tbl, "presets_blocked", GINT_TO_POINTER(TRUE));
 
-static ProfileFloatElement f_profile[PROFILE_FLOAT_SIZE] = {
-    {"mass",0.02, 0.0, 1.0},
-    {"wiggle",0.0, 0.0, 1.0},
-    {"angle",30.0, -90.0, 90.0},
-    {"thinning",0.1, -1.0, 1.0},
-    {"tremor",0.0, 0.0, 1.0},
-    {"flatness",0.9, 0.0, 1.0},
-    {"cap_rounding",0.0, 0.0, 5.0}
-};
-static ProfileIntElement i_profile[PROFILE_INT_SIZE] = {
-    {"width",15, 1, 100},
-    {"usepressure",1,0,1},
-    {"tracebackground",0,0,1},
-    {"usetilt",1,0,1},
-};
+    EgeSelectOneAction* selector = static_cast<EgeSelectOneAction *>(g_object_get_data(tbl, "profile_selector"));
+    GtkListStore* model = GTK_LIST_STORE(ege_select_one_action_get_model(selector));
+    gtk_list_store_clear (model);
+
+    {
+        GtkTreeIter iter;
+        gtk_list_store_append( model, &iter );
+        gtk_list_store_set( model, &iter, 0, _("No preset"), 1, 0, -1 );
+    }
+
+    //TODO: switch back to prefs API
+    Inkscape::XML::Node *repr = inkscape_get_repr(INKSCAPE, "tools.calligraphic.preset" );
+    Inkscape::XML::Node *child_repr = sp_repr_children(repr);
+    int ii=1;
+    while (child_repr) {
+        GtkTreeIter iter;
+        char *preset_name = (char *) child_repr->attribute("name");
+        gtk_list_store_append( model, &iter );
+        gtk_list_store_set( model, &iter, 0, preset_name, 1, ++ii, -1 );
+        child_repr = sp_repr_next(child_repr);
+    }
 
+    {
+        GtkTreeIter iter;
+        gtk_list_store_append( model, &iter );
+        gtk_list_store_set( model, &iter, 0, _("Save..."), 1, ii, -1 );
+        g_object_set_data(tbl, "save_presets_index", GINT_TO_POINTER(ii));
+    }
 
+    g_object_set_data(tbl, "presets_blocked", GINT_TO_POINTER(FALSE));
 
-static void sp_dcc_save_profile( GtkWidget */*widget*/, GObject *dataKludge ){
-    SPDesktop *desktop = (SPDesktop *) g_object_get_data( dataKludge, "desktop" );
+    update_presets_list (tbl);
+}
+
+static void sp_dcc_save_profile (GtkWidget */*widget*/, GObject *tbl)
+{
+    SPDesktop *desktop = (SPDesktop *) g_object_get_data(tbl, "desktop" );
     if (! desktop) return;
 
+    if (g_object_get_data(tbl, "presets_blocked")) 
+        return;
+
     Inkscape::UI::Dialogs::CalligraphicProfileDialog::show(desktop);
-    if ( ! Inkscape::UI::Dialogs::CalligraphicProfileDialog::applied()) return;
+    if ( ! Inkscape::UI::Dialogs::CalligraphicProfileDialog::applied()) {
+        // dialog cancelled
+        update_presets_list (tbl);
+        return;
+    }
     Glib::ustring profile_name = Inkscape::UI::Dialogs::CalligraphicProfileDialog::getProfileName();
 
-    unsigned int new_index = pref_path_number_of_children("tools.calligraphic.preset") +1;
-    gchar *profile_id = g_strdup_printf("dcc%d", new_index);
-    gchar *pref_path = create_pref("tools.calligraphic.preset",profile_id);
+    if (!profile_name.c_str() || *profile_name.c_str() == 0) {
+        // empty name entered
+        update_presets_list (tbl);
+        return;
+    }
+
+    g_object_set_data(tbl, "presets_blocked", GINT_TO_POINTER(TRUE));
 
-    for (unsigned i = 0; i < PROFILE_FLOAT_SIZE; ++i) {
-        ProfileFloatElement const &pe = f_profile[i];
-        double v = prefs_get_double_attribute_limited("tools.calligraphic",pe.name, pe.def, pe.min, pe.max);
-        prefs_set_double_attribute(pref_path,pe.name,v);
+    int new_index = -1;
+    gchar *pref_path = NULL;
+    int total_prefs = pref_path_number_of_children("tools.calligraphic.preset");
+
+    for (int i = 1; i <= total_prefs; i++) {
+        gchar *path = get_pref_nth_child("tools.calligraphic.preset", i);
+        const gchar *name = prefs_get_string_attribute(path, "name");
+        if (name && !strcmp(name, profile_name.c_str())) {
+            // we already have preset with this name, replace its values
+            new_index = i;
+            pref_path = g_strdup(path);
+            break;
+        }
     }
-    for (unsigned i = 0; i < PROFILE_INT_SIZE; ++i) {
-        ProfileIntElement const &pe = i_profile[i];
-        int v = prefs_get_int_attribute_limited("tools.calligraphic",pe.name, pe.def,pe.min, pe.max);
-        prefs_set_int_attribute(pref_path,pe.name,v);
+
+    if (new_index == -1) {
+        // no preset with this name, create 
+        new_index = total_prefs + 1;
+        gchar *profile_id = g_strdup_printf("dcc%d", new_index);
+        pref_path = create_pref("tools.calligraphic.preset", profile_id);
+        g_free(profile_id);
+    }
+
+    for (unsigned i = 0; i < G_N_ELEMENTS(widget_names); ++i) {
+        gchar const *const widget_name = widget_names[i];
+        void *widget = g_object_get_data(tbl, widget_name);
+        if (widget) {
+            if (GTK_IS_ADJUSTMENT(widget)) {
+                GtkAdjustment* adj = static_cast<GtkAdjustment *>(widget);
+                double v = gtk_adjustment_get_value(adj);
+                prefs_set_double_attribute(pref_path, widget_name, v);
+                //std::cout << "wrote adj " << widget_name << ": " << v << "\n";
+            } else if (GTK_IS_TOGGLE_ACTION(widget)) {
+                GtkToggleAction* toggle = static_cast<GtkToggleAction *>(widget);
+                int v = gtk_toggle_action_get_active(toggle);
+                prefs_set_int_attribute(pref_path, widget_name, v);
+                //std::cout << "wrote tog " << widget_name << ": " << v << "\n";
+            } else {
+               g_warning("Unknown widget type for preset: %s\n", widget_name);
+            }
+        } else {
+            g_warning("Bad key when writing preset: %s\n", widget_name);
+        }
     }
-    prefs_set_string_attribute(pref_path,"name",profile_name.c_str());
+    prefs_set_string_attribute(pref_path, "name", profile_name.c_str());
 
-    EgeSelectOneAction* selector = static_cast<EgeSelectOneAction *>(g_object_get_data(dataKludge, "profile_selector"));
-    GtkListStore* model = GTK_LIST_STORE(ege_select_one_action_get_model(selector));
-    GtkTreeIter iter;
-    gtk_list_store_append( model, &iter );
-    gtk_list_store_set( model, &iter, 0, profile_name.c_str(), 1, new_index, -1 );
+    g_object_set_data(tbl, "presets_blocked", GINT_TO_POINTER(FALSE));
 
-    free(profile_id);
-    free(pref_path);
+    sp_dcc_build_presets_list (tbl);
 
-    ege_select_one_action_set_active(selector, new_index);
+    g_free(pref_path);
 }
 
 
-static void sp_ddc_change_profile(EgeSelectOneAction* act, GObject *dataKludge) {
+static void sp_ddc_change_profile(EgeSelectOneAction* act, GObject* tbl) {
 
     gint preset_index = ege_select_one_action_get_active( act );
-    gchar *profile_name = get_pref_nth_child("tools.calligraphic.preset", preset_index);
-
-    if ( profile_name) {
-        g_object_set_data(dataKludge, "profile_selector",NULL); //temporary hides the selector so no one will updadte it
-        for (unsigned i = 0; i < PROFILE_FLOAT_SIZE; ++i) {
-            ProfileFloatElement const &pe = f_profile[i];
-            double v = prefs_get_double_attribute_limited(profile_name, pe.name, pe.def, pe.min, pe.max);
-            GtkAdjustment* adj = static_cast<GtkAdjustment *>(g_object_get_data(dataKludge, pe.name));
-            if ( adj ) {
-                gtk_adjustment_set_value(adj, v);
+    gint save_presets_index = GPOINTER_TO_INT(g_object_get_data(tbl, "save_presets_index"));
+
+    if (preset_index == save_presets_index) {
+        // this is the Save command
+        sp_dcc_save_profile(NULL, tbl);
+        return;
+    }
+
+    if (g_object_get_data(tbl, "presets_blocked")) 
+        return;
+
+    gchar *const preset_path = get_pref_nth_child("tools.calligraphic.preset", preset_index);
+
+    if (preset_path) {
+        g_object_set_data(tbl, "presets_blocked", GINT_TO_POINTER(TRUE)); //temporarily block the selector so no one will updadte it while we're reading it
+
+        Inkscape::XML::Node *preset_repr = inkscape_get_repr(INKSCAPE, preset_path);
+
+        for ( Inkscape::Util::List<Inkscape::XML::AttributeRecord const> iter = preset_repr->attributeList();
+              iter; 
+              ++iter ) {
+            const gchar *attr_name = g_quark_to_string(iter->key);
+            if (!strcmp(attr_name, "id") || !strcmp(attr_name, "name"))
+                continue;
+            void *widget = g_object_get_data(tbl, attr_name);
+            if (widget) {
+                if (GTK_IS_ADJUSTMENT(widget)) {
+                    double v = prefs_get_double_attribute(preset_path, attr_name, 0); // fixme: no min/max checks here, add?
+                    GtkAdjustment* adj = static_cast<GtkAdjustment *>(widget);
+                    gtk_adjustment_set_value(adj, v);
+                    //std::cout << "set adj " << attr_name << " to " << v << "\n";
+                } else if (GTK_IS_TOGGLE_ACTION(widget)) {
+                    int v = prefs_get_int_attribute(preset_path, attr_name, 0); // fixme: no min/max checks here, add?
+                    GtkToggleAction* toggle = static_cast<GtkToggleAction *>(widget);
+                    gtk_toggle_action_set_active(toggle, v);
+                    //std::cout << "set toggle " << attr_name << " to " << v << "\n";
+                } else {
+                    g_warning("Unknown widget type for preset: %s\n", attr_name);
+                }
+            } else {
+                g_warning("Bad key found in a preset record: %s\n", attr_name);
             }
         }
-        for (unsigned i = 0; i < PROFILE_INT_SIZE; ++i) {
-            ProfileIntElement const &pe = i_profile[i];
-            int v = prefs_get_int_attribute_limited(profile_name, pe.name, pe.def, pe.min, pe.max);
-            GtkToggleAction* toggle = static_cast<GtkToggleAction *>(g_object_get_data(dataKludge, pe.name));
-            if ( toggle ) {
-                gtk_toggle_action_set_active(toggle, v);
-            } else printf("No toggle");
-        }
-        free(profile_name);
-        g_object_set_data(dataKludge, "profile_selector",act); //restore selector visibility
+        g_free(preset_path);
+        g_object_set_data(tbl, "presets_blocked", GINT_TO_POINTER(FALSE));
     }
 
 }
@@ -3927,6 +4135,8 @@ static void sp_ddc_change_profile(EgeSelectOneAction* act, GObject *dataKludge)
 static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
 {
     {
+        g_object_set_data(holder, "presets_blocked", GINT_TO_POINTER(TRUE));
+
         EgeAdjustmentAction* calligraphy_angle = 0;
 
         {
@@ -3949,15 +4159,15 @@ static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main
         {
         /* Thinning */
             gchar const* labels[] = {_("(speed blows up stroke)"), 0, 0, _("(slight widening)"), _("(constant width)"), _("(slight thinning, default)"), 0, 0, _("(speed deflates stroke)")};
-            gdouble values[] = {-1, -0.4, -0.2, -0.1, 0, 0.1, 0.2, 0.4, 1};
+            gdouble values[] = {-100, -40, -20, -10, 0, 10, 20, 40, 100};
         EgeAdjustmentAction* eact = create_adjustment_action( "ThinningAction",
                                                               _("Stroke Thinning"), _("Thinning:"),
                                                               _("How much velocity thins the stroke (> 0 makes fast strokes thinner, < 0 makes them broader, 0 makes width independent of velocity)"),
-                                                              "tools.calligraphic", "thinning", 0.1,
+                                                              "tools.calligraphic", "thinning", 10,
                                                               GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
-                                                              -1.0, 1.0, 0.01, 0.1,
+                                                              -100, 100, 1, 0.1,
                                                               labels, values, G_N_ELEMENTS(labels),
-                                                              sp_ddc_velthin_value_changed, 0.01, 2);
+                                                              sp_ddc_velthin_value_changed, 0.01, 0, 100);
         gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
         gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
         }
@@ -3975,23 +4185,23 @@ static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main
                                                               labels, values, G_N_ELEMENTS(labels),
                                                               sp_ddc_angle_value_changed, 1, 0 );
         gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+        g_object_set_data( holder, "angle_action", eact );
         gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
-        g_object_set_data( holder, "angle", eact );
         calligraphy_angle = eact;
         }
 
         {
         /* Fixation */
             gchar const* labels[] = {_("(perpendicular to stroke, \"brush\")"), 0, 0, 0, _("(almost fixed, default)"), _("(fixed by Angle, \"pen\")")};
-        gdouble values[] = {0, 0.2, 0.4, 0.6, 0.9, 1.0};
+        gdouble values[] = {0, 20, 40, 60, 90, 100};
         EgeAdjustmentAction* eact = create_adjustment_action( "FixationAction",
                                                               _("Fixation"), _("Fixation:"),
                                                               _("Angle behavior (0 = nib always perpendicular to stroke direction, 1 = fixed angle)"),
-                                                              "tools.calligraphic", "flatness", 0.9,
+                                                              "tools.calligraphic", "flatness", 90,
                                                               GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
-                                                              0.0, 1.0, 0.01, 0.1,
+                                                              0.0, 100, 1.0, 10.0,
                                                               labels, values, G_N_ELEMENTS(labels),
-                                                              sp_ddc_flatness_value_changed, 0.01, 2 );
+                                                              sp_ddc_flatness_value_changed, 0.01, 0, 100 );
         gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
         gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
         }
@@ -4016,15 +4226,15 @@ static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main
         {
         /* Tremor */
             gchar const* labels[] = {_("(smooth line)"), _("(slight tremor)"), _("(noticeable tremor)"), 0, 0, _("(maximum tremor)")};
-        gdouble values[] = {0, 0.1, 0.2, 0.4, 0.6, 1.0};
+        gdouble values[] = {0, 10, 20, 40, 60, 100};
         EgeAdjustmentAction* eact = create_adjustment_action( "TremorAction",
                                                               _("Stroke Tremor"), _("Tremor:"),
                                                               _("Increase to make strokes rugged and trembling"),
                                                               "tools.calligraphic", "tremor", 0.0,
                                                               GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
-                                                              0.0, 1.0, 0.01, 0.0,
+                                                              0.0, 100, 1, 0.0,
                                                               labels, values, G_N_ELEMENTS(labels),
-                                                              sp_ddc_tremor_value_changed, 0.01, 2 );
+                                                              sp_ddc_tremor_value_changed, 0.01, 0, 100 );
 
         ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
         gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
@@ -4034,15 +4244,15 @@ static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main
         {
         /* Wiggle */
         gchar const* labels[] = {_("(no wiggle)"), _("(slight deviation)"), 0, 0, _("(wild waves and curls)")};
-        gdouble values[] = {0, 0.2, 0.4, 0.6, 1.0};
+        gdouble values[] = {0, 20, 40, 60, 100};
         EgeAdjustmentAction* eact = create_adjustment_action( "WiggleAction",
                                                               _("Pen Wiggle"), _("Wiggle:"),
                                                               _("Increase to make the pen waver and wiggle"),
                                                               "tools.calligraphic", "wiggle", 0.0,
                                                               GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
-                                                              0.0, 1.0, 0.01, 0.0,
+                                                              0.0, 100, 1, 0.0,
                                                               labels, values, G_N_ELEMENTS(labels),
-                                                              sp_ddc_wiggle_value_changed, 0.01, 2 );
+                                                              sp_ddc_wiggle_value_changed, 0.01, 0, 100 );
         ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
         gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
         gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
@@ -4051,15 +4261,15 @@ static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main
         {
         /* Mass */
             gchar const* labels[] = {_("(no inertia)"), _("(slight smoothing, default)"), _("(noticeable lagging)"), 0, 0, _("(maximum inertia)")};
-        gdouble values[] = {0.0, 0.02, 0.1, 0.2, 0.5, 1.0};
+        gdouble values[] = {0.0, 2, 10, 20, 50, 100};
         EgeAdjustmentAction* eact = create_adjustment_action( "MassAction",
                                                               _("Pen Mass"), _("Mass:"),
                                                               _("Increase to make the pen drag behind, as if slowed by inertia"),
-                                                              "tools.calligraphic", "mass", 0.02,
+                                                              "tools.calligraphic", "mass", 2.0,
                                                               GTK_WIDGET(desktop->canvas), NULL, holder, FALSE, NULL,
-                                                              0.0, 1.0, 0.01, 0.0,
+                                                              0.0, 100, 1, 0.0,
                                                               labels, values, G_N_ELEMENTS(labels),
-                                                              sp_ddc_mass_value_changed, 0.01, 2 );
+                                                              sp_ddc_mass_value_changed, 0.01, 0, 100 );
         ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
         gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
         gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
@@ -4108,47 +4318,17 @@ static void sp_calligraphy_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main
 
         /*calligraphic profile */
         {
-            GtkListStore* model = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT );
-            gchar *pref_path;
+            GtkListStore* model = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
+            EgeSelectOneAction* act1 = ege_select_one_action_new ("SetProfileAction", "" , (_("Choose a preset")), NULL, GTK_TREE_MODEL(model));
+            ege_select_one_action_set_appearance (act1, "compact");
+            g_object_set_data (holder, "profile_selector", act1 );
 
+            g_object_set_data(holder, "presets_blocked", GINT_TO_POINTER(FALSE));
 
-            GtkTreeIter iter;
-            gtk_list_store_append( model, &iter );
-            gtk_list_store_set( model, &iter, 0, _("No preset"), 1, 0, -1 );
-
-            //TODO: switch back to prefs API
-            Inkscape::XML::Node *repr = inkscape_get_repr(INKSCAPE, "tools.calligraphic.preset" );
-            Inkscape::XML::Node *child_repr = sp_repr_children(repr);
-            int ii=1;
-            while (child_repr) {
-                GtkTreeIter iter;
-                char *preset_name = (char *) child_repr->attribute("name");
-                gtk_list_store_append( model, &iter );
-                gtk_list_store_set( model, &iter, 0, preset_name, 1, ++ii, -1 );
-                child_repr = sp_repr_next(child_repr);
-            }
-
-            pref_path = NULL;
-            EgeSelectOneAction* act1 = ege_select_one_action_new( "SetProfileAction", "" , (_("Change calligraphic profile")), NULL, GTK_TREE_MODEL(model) );
-            ege_select_one_action_set_appearance( act1, "compact" );
-            g_signal_connect( G_OBJECT(act1), "changed", G_CALLBACK(sp_ddc_change_profile), holder );
-            gtk_action_group_add_action( mainActions, GTK_ACTION(act1) );
-            g_object_set_data( holder, "profile_selector", act1 );
+            sp_dcc_build_presets_list (holder);
 
-        }
-
-        /*Save or delete calligraphic profile */
-        {
-            GtkAction* act = gtk_action_new( "SaveDeleteProfileAction",
-                                             _("Defaults"),
-                                             _("Save current settings as new profile"),
-                                             GTK_STOCK_SAVE );
-            g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(sp_dcc_save_profile), holder );
-
-
-            gtk_action_group_add_action( mainActions, act );
-            gtk_action_set_sensitive( act, TRUE );
-            g_object_set_data( holder, "profile_save_delete", act );
+            g_signal_connect(G_OBJECT(act1), "changed", G_CALLBACK(sp_ddc_change_profile), holder);
+            gtk_action_group_add_action(mainActions, GTK_ACTION(act1));
         }
     }
 }
@@ -4717,18 +4897,24 @@ sp_text_toolbox_selection_changed (Inkscape::Selection */*selection*/, GObject *
     gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
 
     // If querying returned nothing, read the style from the text tool prefs (default style for new texts)
-    if (result_family == QUERY_STYLE_NOTHING || result_style == QUERY_STYLE_NOTHING || result_numbers == QUERY_STYLE_NOTHING)
-    {
+    if (result_family == QUERY_STYLE_NOTHING || result_style == QUERY_STYLE_NOTHING || result_numbers == QUERY_STYLE_NOTHING) {
+        // there are no texts in selection, read from prefs
         Inkscape::XML::Node *repr = inkscape_get_repr (INKSCAPE, "tools.text");
-
-        if (repr)
-        {
+        if (repr) {
             sp_style_read_from_repr (query, repr);
-        }
-        else
-        {
+            if (g_object_get_data(tbl, "text_style_from_prefs")) {
+                // do not reset the toolbar style from prefs if we already did it last time
+                sp_style_unref(query);
+                return;
+            }
+            g_object_set_data(tbl, "text_style_from_prefs", GINT_TO_POINTER(TRUE));
+        } else {
+            sp_style_unref(query);
             return;
         }
+    } else {
+        g_object_set_data(tbl, "text_style_from_prefs", GINT_TO_POINTER(FALSE));
     }
 
     if (query->text)
@@ -4758,6 +4944,7 @@ sp_text_toolbox_selection_changed (Inkscape::Selection */*selection*/, GObject *
                 path = Inkscape::FontLister::get_instance()->get_row_for_font (familyName);
             } catch (...) {
                 g_warning("Family name %s does not have an entry in the font lister.", familyName.c_str());
+                sp_style_unref(query);
                 return;
             }
 
@@ -4773,12 +4960,14 @@ sp_text_toolbox_selection_changed (Inkscape::Selection */*selection*/, GObject *
         }
 
         //Size
-        GtkWidget *cbox = GTK_WIDGET (g_object_get_data (G_OBJECT (tbl), "combo-box-size"));
-        char *str = g_strdup_printf ("%.5g", query->font_size.computed);
-        g_object_set_data (tbl, "size-block", gpointer(1));
-        gtk_entry_set_text (GTK_ENTRY(GTK_BIN (cbox)->child), str);
-        g_object_set_data (tbl, "size-block", gpointer(0));
-        free (str);
+        {
+            GtkWidget *cbox = GTK_WIDGET(g_object_get_data(G_OBJECT(tbl), "combo-box-size"));
+            gchar *const str = g_strdup_printf("%.5g", query->font_size.computed);
+            g_object_set_data(tbl, "size-block", gpointer(1));
+            gtk_entry_set_text(GTK_ENTRY(GTK_BIN(cbox)->child), str);
+            g_object_set_data(tbl, "size-block", gpointer(0));
+            g_free(str);
+        }
 
         //Anchor
         if (query->text_align.computed == SP_CSS_TEXT_ALIGN_JUSTIFY)
@@ -4973,7 +5162,7 @@ sp_text_toolbox_family_changed (GtkTreeSelection    *selection,
     sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT,
                                    _("Text: Change font family"));
     sp_repr_css_attr_unref (css);
-    free (family);
+    g_free(family);
     gtk_widget_hide (GTK_WIDGET (g_object_get_data (G_OBJECT(tbl), "warning-image")));
 
     gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas));
@@ -5247,14 +5436,17 @@ sp_text_toolbox_size_changed  (GtkComboBox *cbox,
     if (gtk_combo_box_get_active (cbox) < 0 && !g_object_get_data (tbl, "enter-pressed"))
         return;
 
-    gchar *endptr;
     gdouble value = -1;
-    char *text = gtk_combo_box_get_active_text (cbox);
-    if (text) {
-        value = g_strtod (text, &endptr);
-        if (endptr == text) // conversion failed, non-numeric input
-            value = -1;
-        free (text);
+    {
+        gchar *endptr;
+        gchar *const text = gtk_combo_box_get_active_text(cbox);
+        if (text) {
+            value = g_strtod(text, &endptr);
+            if (endptr == text) {  // Conversion failed, non-numeric input.
+                value = -1;
+            }
+            g_free(text);
+        }
     }
     if (value <= 0) {
         return; // could not parse value
@@ -5407,24 +5599,21 @@ cell_data_func  (GtkTreeViewColumn */*column*/,
                  GtkTreeIter       *iter,
                  gpointer           /*data*/)
 {
-    char        *family,
-        *family_escaped,
-        *sample_escaped;
-
-    static const char *sample = _("AaBbCcIiPpQq12369$\342\202\254\302\242?.;/()");
+    gchar *family;
+    gtk_tree_model_get(tree_model, iter, 0, &family, -1);
+    gchar *const family_escaped = g_markup_escape_text(family, -1);
 
-    gtk_tree_model_get (tree_model, iter, 0, &family, -1);
-
-    family_escaped = g_markup_escape_text (family, -1);
-    sample_escaped = g_markup_escape_text (sample, -1);
+    static char const *const sample = _("AaBbCcIiPpQq12369$\342\202\254\302\242?.;/()");
+    gchar *const sample_escaped = g_markup_escape_text(sample, -1);
 
     std::stringstream markup;
-    markup << family_escaped << "  <span foreground='darkgray' font_family='" << family_escaped << "'>" << sample_escaped << "</span>";
+    markup << family_escaped << "  <span foreground='darkgray' font_family='"
+           << family_escaped << "'>" << sample_escaped << "</span>";
     g_object_set (G_OBJECT (cell), "markup", markup.str().c_str(), NULL);
 
-    free (family);
-    free (family_escaped);
-    free (sample_escaped);
+    g_free(family);
+    g_free(family_escaped);
+    g_free(sample_escaped);
 }
 
 static void delete_completion(GObject */*obj*/, GtkWidget *entry) {
@@ -5523,14 +5712,16 @@ sp_text_toolbox_new (SPDesktop *desktop)
     g_signal_connect_swapped (G_OBJECT (tbl), "show", G_CALLBACK (gtk_widget_hide), box);
 
     ////////////Size
-    const char *sizes[] = {
+    gchar const *const sizes[] = {
         "4", "6", "8", "9", "10", "11", "12", "13", "14",
         "16", "18", "20", "22", "24", "28",
         "32", "36", "40", "48", "56", "64", "72", "144"
     };
 
     GtkWidget *cbox = gtk_combo_box_entry_new_text ();
-    for (unsigned int n = 0; n < G_N_ELEMENTS (sizes); gtk_combo_box_append_text (GTK_COMBO_BOX(cbox), sizes[n++]));
+    for (unsigned int i = 0; i < G_N_ELEMENTS(sizes); ++i) {
+        gtk_combo_box_append_text(GTK_COMBO_BOX(cbox), sizes[i]);
+    }
     gtk_widget_set_size_request (cbox, 80, -1);
     gtk_toolbar_append_widget( tbl, cbox, "", "");
     g_object_set_data (G_OBJECT (tbl), "combo-box-size", cbox);
@@ -5964,7 +6155,7 @@ static void paintbucket_offset_changed(GtkAdjustment *adj, GObject *tbl)
     prefs_set_string_attribute("tools.paintbucket", "offsetunits", sp_unit_get_abbreviation(unit));
 }
 
-static void paintbucket_defaults(GtkWidget *, GObject *dataKludge)
+static void paintbucket_defaults (GtkWidget *, GObject *tbl)
 {
     // FIXME: make defaults settable via Inkscape Options
     struct KeyValue {
@@ -5977,15 +6168,15 @@ static void paintbucket_defaults(GtkWidget *, GObject *dataKludge)
 
     for (unsigned i = 0; i < G_N_ELEMENTS(key_values); ++i) {
         KeyValue const &kv = key_values[i];
-        GtkAdjustment* adj = static_cast<GtkAdjustment *>(g_object_get_data(dataKludge, kv.key));
+        GtkAdjustment* adj = static_cast<GtkAdjustment *>(g_object_get_data(tbl, kv.key));
         if ( adj ) {
             gtk_adjustment_set_value(adj, kv.value);
         }
     }
 
-    EgeSelectOneAction* channels_action = EGE_SELECT_ONE_ACTION( g_object_get_data( dataKludge, "channels_action" ) );
+    EgeSelectOneAction* channels_action = EGE_SELECT_ONE_ACTION( g_object_get_data (tbl, "channels_action" ) );
     ege_select_one_action_set_active( channels_action, FLOOD_CHANNELS_RGB );
-    EgeSelectOneAction* autogap_action = EGE_SELECT_ONE_ACTION( g_object_get_data( dataKludge, "autogap_action" ) );
+    EgeSelectOneAction* autogap_action = EGE_SELECT_ONE_ACTION( g_object_get_data (tbl, "autogap_action" ) );
     ege_select_one_action_set_active( autogap_action, 0 );
 }