Code

marked forgotten translatable message
[inkscape.git] / src / ui / dialog / inkscape-preferences.cpp
1 /** @file
2  * @brief Inkscape Preferences dialog - implementation
3  */
4 /* Authors:
5  *   Carl Hetherington
6  *   Marco Scholten
7  *   Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
8  *   Bruno Dilly <bruno.dilly@gmail.com>
9  *
10  * Copyright (C) 2004-2007 Authors
11  *
12  * Released under GNU GPL.  Read the file 'COPYING' for more information.
13  */
15 #ifdef HAVE_CONFIG_H
16 # include <config.h>
17 #endif
19 #include <gtkmm/main.h>
20 #include <gtkmm/frame.h>
21 #include <gtkmm/scrolledwindow.h>
22 #include <gtkmm/alignment.h>
24 #include "preferences.h"
25 #include "inkscape-preferences.h"
26 #include "verbs.h"
27 #include "selcue.h"
28 #include "unit-constants.h"
29 #include <iostream>
30 #include "enums.h"
31 // #include "inkscape.h"
32 #include "desktop-handles.h"
33 #include "message-stack.h"
34 #include "style.h"
35 #include "selection.h"
36 #include "selection-chemistry.h"
37 #include "xml/repr.h"
38 #include "ui/widget/style-swatch.h"
39 #include "display/nr-filter-gaussian.h"
40 #include "display/nr-filter-types.h"
41 #include "color-profile-fns.h"
42 #include "display/canvas-grid.h"
44 namespace Inkscape {
45 namespace UI {
46 namespace Dialog {
48 InkscapePreferences::InkscapePreferences()
49     : UI::Widget::Panel ("", "/dialogs/preferences", SP_VERB_DIALOG_DISPLAY),
50       _max_dialog_width(0),
51       _max_dialog_height(0),
52       _current_page(0)
53 {
54     //get the width of a spinbutton
55     Gtk::SpinButton* sb = new Gtk::SpinButton;
56     sb->set_width_chars(6);
57     _getContents()->add(*sb);
58     show_all_children();
59     Gtk::Requisition sreq;
60     sb->size_request(sreq);
61     _sb_width = sreq.width;
62     _getContents()->remove(*sb);
63     delete sb;
65     //Main HBox
66     Gtk::HBox* hbox_list_page = Gtk::manage(new Gtk::HBox());
67     hbox_list_page->set_border_width(12);
68     hbox_list_page->set_spacing(12);
69     _getContents()->add(*hbox_list_page);
71     //Pagelist
72     Gtk::Frame* list_frame = Gtk::manage(new Gtk::Frame());
73     Gtk::ScrolledWindow* scrolled_window = Gtk::manage(new Gtk::ScrolledWindow());
74     hbox_list_page->pack_start(*list_frame, false, true, 0);
75     _page_list.set_headers_visible(false);
76     scrolled_window->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
77     scrolled_window->add(_page_list);
78     list_frame->set_shadow_type(Gtk::SHADOW_IN);
79     list_frame->add(*scrolled_window);
80     _page_list_model = Gtk::TreeStore::create(_page_list_columns);
81     _page_list.set_model(_page_list_model);
82     _page_list.append_column("name",_page_list_columns._col_name);
83     Glib::RefPtr<Gtk::TreeSelection> page_list_selection = _page_list.get_selection();
84     page_list_selection->signal_changed().connect(sigc::mem_fun(*this, &InkscapePreferences::on_pagelist_selection_changed));
85     page_list_selection->set_mode(Gtk::SELECTION_BROWSE);
87     //Pages
88     Gtk::VBox* vbox_page = Gtk::manage(new Gtk::VBox());
89     Gtk::Frame* title_frame = Gtk::manage(new Gtk::Frame());
91     Gtk::ScrolledWindow* pageScroller = Gtk::manage(new Gtk::ScrolledWindow());
92     pageScroller->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
93     pageScroller->add(*vbox_page);
94     hbox_list_page->pack_start(*pageScroller, true, true, 0);
96     title_frame->add(_page_title);
97     vbox_page->pack_start(*title_frame, false, false, 0);
98     vbox_page->pack_start(_page_frame, true, true, 0);
99     _page_frame.set_shadow_type(Gtk::SHADOW_IN);
100     title_frame->set_shadow_type(Gtk::SHADOW_IN);
102     initPageTools();
103     initPageSelecting();
104     initPageTransforms();
105     initPageClones();
106     initPageMasks();
107     initPageFilters();
108     initPageBitmaps();
109     initPageCMS();
110     initPageGrids();
111     initPageSVGOutput();
112     initPageAutosave();
113     initPageImportExport();
114     initPageUI();
115     initPageMouse();
116     initPageScrolling();
117     initPageSnapping();
118     initPageSteps();
119     initPageWindows();
120     initPageMisc();
122     signalPresent().connect(sigc::mem_fun(*this, &InkscapePreferences::_presentPages));
124     //calculate the size request for this dialog
125     this->show_all_children();
126     _page_list.expand_all();
127     _page_list_model->foreach_iter(sigc::mem_fun(*this, &InkscapePreferences::SetMaxDialogSize));
128     _getContents()->set_size_request(_max_dialog_width, _max_dialog_height);
129     _page_list.collapse_all();
132 InkscapePreferences::~InkscapePreferences()
136 Gtk::TreeModel::iterator InkscapePreferences::AddPage(DialogPage& p, Glib::ustring title, int id)
138     return AddPage(p, title, Gtk::TreeModel::iterator() , id);
141 Gtk::TreeModel::iterator InkscapePreferences::AddPage(DialogPage& p, Glib::ustring title, Gtk::TreeModel::iterator parent, int id)
143     Gtk::TreeModel::iterator iter;
144     if (parent)
145        iter = _page_list_model->append((*parent).children());
146     else
147        iter = _page_list_model->append();
148     Gtk::TreeModel::Row row = *iter;
149     row[_page_list_columns._col_name] = title;
150     row[_page_list_columns._col_id] = id;
151     row[_page_list_columns._col_page] = &p;
152     return iter;
155 void InkscapePreferences::initPageMouse()
157     this->AddPage(_page_mouse, _("Mouse"), PREFS_PAGE_MOUSE);
158     _mouse_sens.init ( "/options/cursortolerance/value", 0.0, 30.0, 1.0, 1.0, 8.0, true, false);
159     _page_mouse.add_line( false, _("Grab sensitivity:"), _mouse_sens, _("pixels"),
160                            _("How close on the screen you need to be to an object to be able to grab it with mouse (in screen pixels)"), false);
161     _mouse_thres.init ( "/options/dragtolerance/value", 0.0, 20.0, 1.0, 1.0, 4.0, true, false);
162     _page_mouse.add_line( false, _("Click/drag threshold:"), _mouse_thres, _("pixels"),
163                            _("Maximum mouse drag (in screen pixels) which is considered a click, not a drag"), false);
165     _mouse_use_ext_input.init( _("Use pressure-sensitive tablet (requires restart)"), "/options/useextinput/value", true);
166     _page_mouse.add_line(true, "",_mouse_use_ext_input, "",
167                         _("Use the capabilities of a tablet or other pressure-sensitive device. Disable this only if you have problems with the tablet (you can still use it as a mouse)"));
169     _mouse_switch_on_ext_input.init( _("Switch tool based on tablet device (requires restart)"), "/options/switchonextinput/value", false);
170     _page_mouse.add_line(true, "",_mouse_switch_on_ext_input, "",
171                         _("Change tool as different devices are used on the tablet (pen, eraser, mouse)"));
174 void InkscapePreferences::initPageScrolling()
176     this->AddPage(_page_scrolling, _("Scrolling"), PREFS_PAGE_SCROLLING);
177     _scroll_wheel.init ( "/options/wheelscroll/value", 0.0, 1000.0, 1.0, 1.0, 40.0, true, false);
178     _page_scrolling.add_line( false, _("Mouse wheel scrolls by:"), _scroll_wheel, _("pixels"),
179                            _("One mouse wheel notch scrolls by this distance in screen pixels (horizontally with Shift)"), false);
180     _page_scrolling.add_group_header( _("Ctrl+arrows"));
181     _scroll_arrow_px.init ( "/options/keyscroll/value", 0.0, 1000.0, 1.0, 1.0, 10.0, true, false);
182     _page_scrolling.add_line( true, _("Scroll by:"), _scroll_arrow_px, _("pixels"),
183                            _("Pressing Ctrl+arrow key scrolls by this distance (in screen pixels)"), false);
184     _scroll_arrow_acc.init ( "/options/scrollingacceleration/value", 0.0, 5.0, 0.01, 1.0, 0.35, false, false);
185     _page_scrolling.add_line( true, _("Acceleration:"), _scroll_arrow_acc, "",
186                            _("Pressing and holding Ctrl+arrow will gradually speed up scrolling (0 for no acceleration)"), false);
187     _page_scrolling.add_group_header( _("Autoscrolling"));
188     _scroll_auto_speed.init ( "/options/autoscrollspeed/value", 0.0, 5.0, 0.01, 1.0, 0.7, false, false);
189     _page_scrolling.add_line( true, _("Speed:"), _scroll_auto_speed, "",
190                            _("How fast the canvas autoscrolls when you drag beyond canvas edge (0 to turn autoscroll off)"), false);
191     _scroll_auto_thres.init ( "/options/autoscrolldistance/value", -600.0, 600.0, 1.0, 1.0, -10.0, true, false);
192     _page_scrolling.add_line( true, _("Threshold:"), _scroll_auto_thres, _("pixels"),
193                            _("How far (in screen pixels) you need to be from the canvas edge to trigger autoscroll; positive is outside the canvas, negative is within the canvas"), false);
194     _scroll_space.init ( _("Left mouse button pans when Space is pressed"), "/options/spacepans/value", false);
195     _page_scrolling.add_line( false, "", _scroll_space, "",
196                             _("When on, pressing and holding Space and dragging with left mouse button pans canvas (as in Adobe Illustrator). When off, Space temporarily switches to Selector tool (default)."));
197     _wheel_zoom.init ( _("Mouse wheel zooms by default"), "/options/wheelzooms/value", false);
198     _page_scrolling.add_line( false, "", _wheel_zoom, "",
199                             _("When on, mouse wheel zooms without Ctrl and scrolls canvas with Ctrl; when off, it zooms with Ctrl and scrolls without Ctrl."));
202 void InkscapePreferences::initPageSnapping()
204         
205         _snap_indicator.init( _("Enable snap indicator"), "/options/snapindicator/value", true);
206         _page_snapping.add_line( false, "", _snap_indicator, "",
207                         _("After snapping, a symbol is drawn at the point that has snapped"));
208             
209         _snap_delay.init("/options/snapdelay/value", 0, 1000, 50, 100, 300, 0);
210         _page_snapping.add_line( false, _("Delay (in msec):"), _snap_delay, "",
211                         _("Postpone snapping as long as the mouse is moving, and then wait an additional fraction of a second. This additional delay is specified here. When set to zero or to a very small number, snapping will be immediate"), true);
212         
213         _snap_closest_only.init( _("Only snap the node closest to the pointer"), "/options/snapclosestonly/value", false);
214         _page_snapping.add_line( false, "", _snap_closest_only, "",
215         _("Only try to snap the node that is initialy closest to the mouse pointer"));
216         
217         _snap_weight.init("/options/snapweight/value", 0, 1, 0.1, 0.2, 0.5, 1);
218         _page_snapping.add_line( false, _("Weight factor:"), _snap_weight, "",
219                         _("When multiple snap solutions are found, then Inkscape can either prefer the closest transformation (when set to 0), or prefer the node that was initially the closest to the pointer (when set to 1)"), true);
220         
221         this->AddPage(_page_snapping, _("Snapping"), PREFS_PAGE_SNAPPING);
224 void InkscapePreferences::initPageSteps()
226     this->AddPage(_page_steps, _("Steps"), PREFS_PAGE_STEPS);
228     _steps_arrow.init ( "/options/nudgedistance/value", 0.0, 1000.0, 0.01, 1.0, 2.0, false, false);
229     //nudgedistance is limited to 1000 in select-context.cpp: use the same limit here
230     _page_steps.add_line( false, _("Arrow keys move by:"), _steps_arrow, _("px"),
231                           _("Pressing an arrow key moves selected object(s) or node(s) by this distance (in px units)"), false);
232     _steps_scale.init ( "/options/defaultscale/value", 0.0, 1000.0, 0.01, 1.0, 2.0, false, false);
233     //defaultscale is limited to 1000 in select-context.cpp: use the same limit here
234     _page_steps.add_line( false, _("> and < scale by:"), _steps_scale, _("px"),
235                           _("Pressing > or < scales selection up or down by this increment (in px units)"), false);
236     _steps_inset.init ( "/options/defaultoffsetwidth/value", 0.0, 3000.0, 0.01, 1.0, 2.0, false, false);
237     _page_steps.add_line( false, _("Inset/Outset by:"), _steps_inset, _("px"),
238                           _("Inset and Outset commands displace the path by this distance (in px units)"), false);
239     _steps_compass.init ( _("Compass-like display of angles"), "/options/compassangledisplay/value", true);
240     _page_steps.add_line( false, "", _steps_compass, "",
241                             _("When on, angles are displayed with 0 at north, 0 to 360 range, positive clockwise; otherwise with 0 at east, -180 to 180 range, positive counterclockwise"));
242     int const num_items = 17;
243     Glib::ustring labels[num_items] = {"90", "60", "45", "36", "30", "22.5", "18", "15", "12", "10", "7.5", "6", "3", "2", "1", "0.5", _("None")};
244     int values[num_items] = {2, 3, 4, 5, 6, 8, 10, 12, 15, 18, 24, 30, 60, 90, 180, 360, 0};
245     _steps_rot_snap.set_size_request(_sb_width);
246     _steps_rot_snap.init("/options/rotationsnapsperpi/value", labels, values, num_items, 12);
247     _page_steps.add_line( false, _("Rotation snaps every:"), _steps_rot_snap, _("degrees"),
248                            _("Rotating with Ctrl pressed snaps every that much degrees; also, pressing [ or ] rotates by this amount"), false);
249     _steps_zoom.init ( "/options/zoomincrement/value", 101.0, 500.0, 1.0, 1.0, 1.414213562, true, true);
250     _page_steps.add_line( false, _("Zoom in/out by:"), _steps_zoom, _("%"),
251                           _("Zoom tool click, +/- keys, and middle click zoom in and out by this multiplier"), false);
254 void InkscapePreferences::AddSelcueCheckbox(DialogPage &p, Glib::ustring const &prefs_path, bool def_value)
256     PrefCheckButton* cb = Gtk::manage( new PrefCheckButton);
257     cb->init ( _("Show selection cue"), prefs_path + "/selcue", def_value);
258     p.add_line( false, "", *cb, "", _("Whether selected objects display a selection cue (the same as in selector)"));
261 void InkscapePreferences::AddGradientCheckbox(DialogPage &p, Glib::ustring const &prefs_path, bool def_value)
263     PrefCheckButton* cb = Gtk::manage( new PrefCheckButton);
264     cb->init ( _("Enable gradient editing"), prefs_path + "/gradientdrag", def_value);
265     p.add_line( false, "", *cb, "", _("Whether selected objects display gradient editing controls"));
268 void InkscapePreferences::AddConvertGuidesCheckbox(DialogPage &p, Glib::ustring const &prefs_path, bool def_value) {
269     PrefCheckButton* cb = Gtk::manage( new PrefCheckButton);
270     cb->init ( _("Conversion to guides uses edges instead of bounding box"), prefs_path + "/convertguides", def_value);
271     p.add_line( false, "", *cb, "", _("Converting an object to guides places these along the object's true edges (imitating the object's shape), not along the bounding box."));
274 void InkscapePreferences::AddDotSizeSpinbutton(DialogPage &p, Glib::ustring const &prefs_path, double def_value)
276     PrefSpinButton* sb = Gtk::manage( new PrefSpinButton);
277     sb->init ( prefs_path + "/dot-size", 0.0, 1000.0, 0.1, 10.0, def_value, false, false);
278     p.add_line( false, _("Ctrl+click dot size:"), *sb, _("times current stroke width"),
279                        _("Size of dots created with Ctrl+click (relative to current stroke width)"),
280                        false );
284 void StyleFromSelectionToTool(Glib::ustring const &prefs_path, StyleSwatch *swatch)
286     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
287     if (desktop == NULL)
288         return;
290     Inkscape::Selection *selection = sp_desktop_selection(desktop);
292     if (selection->isEmpty()) {
293         sp_desktop_message_stack(desktop)->flash(Inkscape::ERROR_MESSAGE,
294                                        _("<b>No objects selected</b> to take the style from."));
295         return;
296     }
297     SPItem *item = selection->singleItem();
298     if (!item) {
299         /* TODO: If each item in the selection has the same style then don't consider it an error.
300          * Maybe we should try to handle multiple selections anyway, e.g. the intersection of the
301          * style attributes for the selected items. */
302         sp_desktop_message_stack(desktop)->flash(Inkscape::ERROR_MESSAGE,
303                                        _("<b>More than one object selected.</b>  Cannot take style from multiple objects."));
304         return;
305     }
307     SPCSSAttr *css = take_style_from_item (item);
309     if (!css) return;
311     // only store text style for the text tool
312     if (prefs_path == "/tools/text") {
313         css = sp_css_attr_unset_text (css);
314     }
316     // we cannot store properties with uris - they will be invalid in other documents
317     css = sp_css_attr_unset_uris (css);
319     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
320     prefs->setStyle(prefs_path + "/style", css);
321     sp_repr_css_attr_unref (css);
323     // update the swatch
324     if (swatch) {
325         SPCSSAttr *css = prefs->getInheritedStyle(prefs_path + "/style");
326         swatch->setStyle (css);
327         sp_repr_css_attr_unref(css);
328     }
331 void InkscapePreferences::AddNewObjectsStyle(DialogPage &p, Glib::ustring const &prefs_path, const gchar *banner)
333     if (banner)
334         p.add_group_header(banner);
335     else
336         p.add_group_header( _("Create new objects with:"));
337     PrefRadioButton* current = Gtk::manage( new PrefRadioButton);
338     current->init ( _("Last used style"), prefs_path + "/usecurrent", 1, true, 0);
339     p.add_line( true, "", *current, "",
340                 _("Apply the style you last set on an object"));
342     PrefRadioButton* own = Gtk::manage( new PrefRadioButton);
343     Gtk::HBox* hb = Gtk::manage( new Gtk::HBox);
344     Gtk::Alignment* align = Gtk::manage( new Gtk::Alignment);
345     own->init ( _("This tool's own style:"), prefs_path + "/usecurrent", 0, false, current);
346     align->set(0,0,0,0);
347     align->add(*own);
348     hb->add(*align);
349     p.set_tip( *own, _("Each tool may store its own style to apply to the newly created objects. Use the button below to set it."));
350     p.add_line( true, "", *hb, "", "");
352     // style swatch
353     Gtk::Button* button = Gtk::manage( new Gtk::Button(_("Take from selection"),true));
354     StyleSwatch *swatch = 0;
355     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
356     
357     SPCSSAttr *css = prefs->getStyle(prefs_path + "/style");
358     swatch = new StyleSwatch(css, _("This tool's style of new objects"));
359     hb->add(*swatch);
360     sp_repr_css_attr_unref(css);
362     button->signal_clicked().connect( sigc::bind( sigc::ptr_fun(StyleFromSelectionToTool), prefs_path, swatch)  );
363     own->changed_signal.connect( sigc::mem_fun(*button, &Gtk::Button::set_sensitive) );
364     p.add_line( true, "", *button, "",
365                 _("Remember the style of the (first) selected object as this tool's style"));
368 void InkscapePreferences::initPageTools()
370     Gtk::TreeModel::iterator iter_tools = this->AddPage(_page_tools, _("Tools"), PREFS_PAGE_TOOLS);
371     _path_tools = _page_list.get_model()->get_path(iter_tools);
373     _page_tools.add_group_header( _("Bounding box to use:"));
374     _t_bbox_visual.init ( _("Visual bounding box"), "/tools/bounding_box", 0, false, 0); // 0 means visual
375     _page_tools.add_line( true, "", _t_bbox_visual, "",
376                             _("This bounding box includes stroke width, markers, filter margins, etc."));
377     _t_bbox_geometric.init ( _("Geometric bounding box"), "/tools/bounding_box", 1, true, &_t_bbox_visual); // 1 means geometric
378     _page_tools.add_line( true, "", _t_bbox_geometric, "",
379                             _("This bounding box includes only the bare path"));
381     _page_tools.add_group_header( _("Conversion to guides:"));
382     _t_cvg_keep_objects.init ( _("Keep objects after conversion to guides"), "/tools/cvg_keep_objects", false);
383     _page_tools.add_line( true, "", _t_cvg_keep_objects, "",
384                             _("When converting an object to guides, don't delete the object after the conversion."));
385     _t_cvg_convert_whole_groups.init ( _("Treat groups as a single object"), "/tools/cvg_convert_whole_groups", false);
386     _page_tools.add_line( true, "", _t_cvg_convert_whole_groups, "",
387                             _("Treat groups as a single object during conversion to guides rather than converting each child separately."));
389     _calligrapy_use_abs_size.init ( _("Width is in absolute units"), "/tools/calligraphic/abs_width", false);
390     _calligrapy_keep_selected.init ( _("Select new path"), "/tools/calligraphic/keep_selected", true);
391     _connector_ignore_text.init( _("Don't attach connectors to text objects"), "/tools/connector/ignoretext", true);
393     //Selector
394     this->AddPage(_page_selector, _("Selector"), iter_tools, PREFS_PAGE_TOOLS_SELECTOR);
396     AddSelcueCheckbox(_page_selector, "/tools/select", false);
397     _page_selector.add_group_header( _("When transforming, show:"));
398     _t_sel_trans_obj.init ( _("Objects"), "/tools/select/show", "content", true, 0);
399     _page_selector.add_line( true, "", _t_sel_trans_obj, "",
400                             _("Show the actual objects when moving or transforming"));
401     _t_sel_trans_outl.init ( _("Box outline"), "/tools/select/show", "outline", false, &_t_sel_trans_obj);
402     _page_selector.add_line( true, "", _t_sel_trans_outl, "",
403                             _("Show only a box outline of the objects when moving or transforming"));
404     _page_selector.add_group_header( _("Per-object selection cue:"));
405     _t_sel_cue_none.init ( _("None"), "/options/selcue/value", Inkscape::SelCue::NONE, false, 0);
406     _page_selector.add_line( true, "", _t_sel_cue_none, "",
407                             _("No per-object selection indication"));
408     _t_sel_cue_mark.init ( _("Mark"), "/options/selcue/value", Inkscape::SelCue::MARK, true, &_t_sel_cue_none);
409     _page_selector.add_line( true, "", _t_sel_cue_mark, "",
410                             _("Each selected object has a diamond mark in the top left corner"));
411     _t_sel_cue_box.init ( _("Box"), "/options/selcue/value", Inkscape::SelCue::BBOX, false, &_t_sel_cue_none);
412     _page_selector.add_line( true, "", _t_sel_cue_box, "",
413                             _("Each selected object displays its bounding box"));
415     //Node
416     this->AddPage(_page_node, _("Node"), iter_tools, PREFS_PAGE_TOOLS_NODE);
417     AddSelcueCheckbox(_page_node, "/tools/nodes", true);
418     AddGradientCheckbox(_page_node, "/tools/nodes", true);
419     _page_node.add_group_header( _("Path outline:"));
420     _t_node_pathoutline_color.init(_("Path outline color"), "/tools/nodes/highlight_color", 0xff0000ff);
421     _page_node.add_line( false, _("Path outline color"), _t_node_pathoutline_color, "", _("Selects the color used for showing the path outline."), false);
422     _t_node_pathflash_enabled.init ( _("Path outline flash on mouse-over"), "/tools/nodes/pathflash_enabled", false);
423     _page_node.add_line( true, "", _t_node_pathflash_enabled, "", _("When hovering over a path, briefly flash its outline."));
424     _t_node_pathflash_timeout.init("/tools/nodes/pathflash_timeout", 0, 10000.0, 100.0, 100.0, 1000.0, true, false);
425     _page_node.add_line( false, _("Flash time"), _t_node_pathflash_timeout, "ms", _("Specifies how long the path outline will be visible after a mouse-over (in milliseconds). Specify 0 to have the outline shown until mouse leaves the path."), false);
427     //Tweak
428     this->AddPage(_page_tweak, _("Tweak"), iter_tools, PREFS_PAGE_TOOLS_TWEAK);
429     this->AddNewObjectsStyle(_page_tweak, "/tools/tweak", _("Paint objects with:"));
430     AddSelcueCheckbox(_page_tweak, "/tools/tweak", true);
431     AddGradientCheckbox(_page_tweak, "/tools/tweak", false);
433     //Zoom
434     this->AddPage(_page_zoom, _("Zoom"), iter_tools, PREFS_PAGE_TOOLS_ZOOM);
435     AddSelcueCheckbox(_page_zoom, "/tools/zoom", true);
436     AddGradientCheckbox(_page_zoom, "/tools/zoom", false);
438     //Shapes
439     Gtk::TreeModel::iterator iter_shapes = this->AddPage(_page_shapes, _("Shapes"), iter_tools, PREFS_PAGE_TOOLS_SHAPES);
440     _path_shapes = _page_list.get_model()->get_path(iter_shapes);
441     this->AddSelcueCheckbox(_page_shapes, "/tools/shapes", true);
442     this->AddGradientCheckbox(_page_shapes, "/tools/shapes", true);
444     //Rectangle
445     this->AddPage(_page_rectangle, _("Rectangle"), iter_shapes, PREFS_PAGE_TOOLS_SHAPES_RECT);
446     this->AddNewObjectsStyle(_page_rectangle, "/tools/shapes/rect");
447     this->AddConvertGuidesCheckbox(_page_rectangle, "/tools/shapes/rect", true);
449     //3D box
450     this->AddPage(_page_3dbox, _("3D Box"), iter_shapes, PREFS_PAGE_TOOLS_SHAPES_3DBOX);
451     this->AddNewObjectsStyle(_page_3dbox, "/tools/shapes/3dbox");
452     this->AddConvertGuidesCheckbox(_page_3dbox, "/tools/shapes/3dbox", true);
454     //ellipse
455     this->AddPage(_page_ellipse, _("Ellipse"), iter_shapes, PREFS_PAGE_TOOLS_SHAPES_ELLIPSE);
456     this->AddNewObjectsStyle(_page_ellipse, "/tools/shapes/arc");
458     //star
459     this->AddPage(_page_star, _("Star"), iter_shapes, PREFS_PAGE_TOOLS_SHAPES_STAR);
460     this->AddNewObjectsStyle(_page_star, "/tools/shapes/star");
462     //spiral
463     this->AddPage(_page_spiral, _("Spiral"), iter_shapes, PREFS_PAGE_TOOLS_SHAPES_SPIRAL);
464     this->AddNewObjectsStyle(_page_spiral, "/tools/shapes/spiral");
466     //Pencil
467     this->AddPage(_page_pencil, _("Pencil"), iter_tools, PREFS_PAGE_TOOLS_PENCIL);
468     this->AddSelcueCheckbox(_page_pencil, "/tools/freehand/pencil", true);
469     this->AddNewObjectsStyle(_page_pencil, "/tools/freehand/pencil");
470     this->AddDotSizeSpinbutton(_page_pencil, "/tools/freehand/pencil", 3.0);
472     //Pen
473     this->AddPage(_page_pen, _("Pen"), iter_tools, PREFS_PAGE_TOOLS_PEN);
474     this->AddSelcueCheckbox(_page_pen, "/tools/freehand/pen", true);
475     this->AddNewObjectsStyle(_page_pen, "/tools/freehand/pen");
476     this->AddDotSizeSpinbutton(_page_pen, "/tools/freehand/pen", 3.0);
478     //Calligraphy
479     this->AddPage(_page_calligraphy, _("Calligraphy"), iter_tools, PREFS_PAGE_TOOLS_CALLIGRAPHY);
480     this->AddSelcueCheckbox(_page_calligraphy, "/tools/calligraphic", false);
481     this->AddNewObjectsStyle(_page_calligraphy, "/tools/calligraphic");
482     _page_calligraphy.add_line( false, "", _calligrapy_use_abs_size, "",
483                             _("If on, pen width is in absolute units (px) independent of zoom; otherwise pen width depends on zoom so that it looks the same at any zoom"));
484     _page_calligraphy.add_line( false, "", _calligrapy_keep_selected, "",
485                             _("If on, each newly created object will be selected (deselecting previous selection)"));
486     //Paint Bucket
487     this->AddPage(_page_paintbucket, _("Paint Bucket"), iter_tools, PREFS_PAGE_TOOLS_PAINTBUCKET);
488     this->AddSelcueCheckbox(_page_paintbucket, "/tools/paintbucket", false);
489     this->AddNewObjectsStyle(_page_paintbucket, "/tools/paintbucket");
491     //Eraser
492     this->AddPage(_page_eraser, _("Eraser"), iter_tools, PREFS_PAGE_TOOLS_ERASER);
493     this->AddNewObjectsStyle(_page_eraser, "/tools/eraser");
495     //LPETool
496     this->AddPage(_page_lpetool, _("LPE Tool"), iter_tools, PREFS_PAGE_TOOLS_LPETOOL);
497     this->AddNewObjectsStyle(_page_lpetool, "/tools/lpetool");
499     //Text
500     this->AddPage(_page_text, _("Text"), iter_tools, PREFS_PAGE_TOOLS_TEXT);
501     this->AddSelcueCheckbox(_page_text, "/tools/text", true);
502     this->AddGradientCheckbox(_page_text, "/tools/text", true);
503     this->AddNewObjectsStyle(_page_text, "/tools/text");
505     //Gradient
506     this->AddPage(_page_gradient, _("Gradient"), iter_tools, PREFS_PAGE_TOOLS_GRADIENT);
507     this->AddSelcueCheckbox(_page_gradient, "/tools/gradient", true);
509     //Connector
510     this->AddPage(_page_connector, _("Connector"), iter_tools, PREFS_PAGE_TOOLS_CONNECTOR);
511     this->AddSelcueCheckbox(_page_connector, "/tools/connector", true);
512     _page_connector.add_line(false, "", _connector_ignore_text, "",
513             _("If on, connector attachment points will not be shown for text objects"));
514     //Dropper
515     this->AddPage(_page_dropper, _("Dropper"), iter_tools, PREFS_PAGE_TOOLS_DROPPER);
516     this->AddSelcueCheckbox(_page_dropper, "/tools/dropper", true);
517     this->AddGradientCheckbox(_page_dropper, "/tools/dropper", true);
520 void InkscapePreferences::initPageWindows()
522     _win_save_geom.init ( _("Save and restore window geometry for each document"), "/options/savewindowgeometry/value", 1, true, 0);
523     _win_save_geom_prefs.init ( _("Remember and use last window's geometry"), "/options/savewindowgeometry/value", 2, false, &_win_save_geom);
524     _win_save_geom_off.init ( _("Don't save window geometry"), "/options/savewindowgeometry/value", 0, false, &_win_save_geom);
526     _win_dockable.init ( _("Dockable"), "/options/dialogtype/value", 1, true, 0);
527     _win_floating.init ( _("Floating"), "/options/dialogtype/value", 0, false, &_win_dockable);
529     _win_hide_task.init ( _("Dialogs are hidden in taskbar"), "/options/dialogsskiptaskbar/value", true);
530     _win_zoom_resize.init ( _("Zoom when window is resized"), "/options/stickyzoom/value", false);
531     _win_show_close.init ( _("Show close button on dialogs"), "/dialogs/showclose", false);
532     _win_ontop_none.init ( _("None"), "/options/transientpolicy/value", 0, false, 0);
533     _win_ontop_normal.init ( _("Normal"), "/options/transientpolicy/value", 1, true, &_win_ontop_none);
534     _win_ontop_agressive.init ( _("Aggressive"), "/options/transientpolicy/value", 2, false, &_win_ontop_none);
536     _page_windows.add_group_header( _("Saving window geometry (size and position):"));
537     _page_windows.add_line( true, "", _win_save_geom_off, "",
538                             _("Let the window manager determine placement of all windows"));
539     _page_windows.add_line( true, "", _win_save_geom_prefs, "",
540                             _("Remember and use the last window's geometry (saves geometry to user preferences)"));
541     _page_windows.add_line( true, "", _win_save_geom, "",
542                             _("Save and restore window geometry for each document (saves geometry in the document)"));
544     _page_windows.add_group_header( _("Dialog behavior (requires restart):"));
545     _page_windows.add_line( true, "", _win_dockable, "",
546                             _("Dockable"));
547     _page_windows.add_line( true, "", _win_floating, "",
548                             _("Floating"));
550 #ifndef WIN32 // non-Win32 special code to enable transient dialogs
551     _page_windows.add_group_header( _("Dialogs on top:"));
553     _page_windows.add_line( true, "", _win_ontop_none, "",
554                             _("Dialogs are treated as regular windows"));
555     _page_windows.add_line( true, "", _win_ontop_normal, "",
556                             _("Dialogs stay on top of document windows"));
557     _page_windows.add_line( true, "", _win_ontop_agressive, "",
558                             _("Same as Normal but may work better with some window managers"));
559 #endif
561 #if GTK_VERSION_GE(2, 12)
562         _page_windows.add_group_header( _("Dialog Transparency:"));
563         _win_trans_focus.init("/dialogs/transparency/on-focus", 0.5, 1.0, 0.01, 0.1, 1.0, false, false);
564         _page_windows.add_line( true, _("Opacity when focused:"), _win_trans_focus, "", "");
565         _win_trans_blur.init("/dialogs/transparency/on-blur", 0.0, 1.0, 0.01, 0.1, 0.5, false, false);
566         _page_windows.add_line( true, _("Opacity when unfocused:"), _win_trans_blur, "", "");
567         _win_trans_time.init("/dialogs/transparency/animate-time", 0, 1000, 10, 100, 100, true, false);
568         _page_windows.add_line( true, _("Time of opacity change animation:"), _win_trans_time, "ms", "");
569 #endif
571     _page_windows.add_group_header( _("Miscellaneous:"));
572 #ifndef WIN32 // FIXME: Temporary Win32 special code to enable transient dialogs
573     _page_windows.add_line( false, "", _win_hide_task, "",
574                             _("Whether dialog windows are to be hidden in the window manager taskbar"));
575 #endif
576     _page_windows.add_line( false, "", _win_zoom_resize, "",
577                             _("Zoom drawing when document window is resized, to keep the same area visible (this is the default which can be changed in any window using the button above the right scrollbar)"));
578     _page_windows.add_line( false, "", _win_show_close, "",
579                             _("Whether dialog windows have a close button (requires restart)"));
580     this->AddPage(_page_windows, _("Windows"), PREFS_PAGE_WINDOWS);
583 void InkscapePreferences::initPageClones()
585     _clone_option_parallel.init ( _("Move in parallel"), "/options/clonecompensation/value",
586                                   SP_CLONE_COMPENSATION_PARALLEL, true, 0);
587     _clone_option_stay.init ( _("Stay unmoved"), "/options/clonecompensation/value",
588                                   SP_CLONE_COMPENSATION_UNMOVED, false, &_clone_option_parallel);
589     _clone_option_transform.init ( _("Move according to transform"), "/options/clonecompensation/value",
590                                   SP_CLONE_COMPENSATION_NONE, false, &_clone_option_parallel);
591     _clone_option_unlink.init ( _("Are unlinked"), "/options/cloneorphans/value",
592                                   SP_CLONE_ORPHANS_UNLINK, true, 0);
593     _clone_option_delete.init ( _("Are deleted"), "/options/cloneorphans/value",
594                                   SP_CLONE_ORPHANS_DELETE, false, &_clone_option_unlink);
596     _page_clones.add_group_header( _("When the original moves, its clones and linked offsets:"));
597     _page_clones.add_line( true, "", _clone_option_parallel, "",
598                            _("Clones are translated by the same vector as their original."));
599     _page_clones.add_line( true, "", _clone_option_stay, "",
600                            _("Clones preserve their positions when their original is moved."));
601     _page_clones.add_line( true, "", _clone_option_transform, "",
602                            _("Each clone moves according to the value of its transform= attribute. For example, a rotated clone will move in a different direction than its original."));
603     _page_clones.add_group_header( _("When the original is deleted, its clones:"));
604     _page_clones.add_line( true, "", _clone_option_unlink, "",
605                            _("Orphaned clones are converted to regular objects."));
606     _page_clones.add_line( true, "", _clone_option_delete, "",
607                            _("Orphaned clones are deleted along with their original."));
609     _page_clones.add_group_header( _("When duplicating original+clones:"));
611     _clone_relink_on_duplicate.init ( _("Relink duplicated clones"), "/options/relinkclonesonduplicate/value", false);
612     _page_clones.add_line(true, "", _clone_relink_on_duplicate, "",
613                         _("When duplicating a selection containing both a clone and its original (possibly in groups), relink the duplicated clone to the duplicated original instead of the old original"));
615     //TRANSLATORS: Heading for the Inkscape Preferences "Clones" Page
616     this->AddPage(_page_clones, _("Clones"), PREFS_PAGE_CLONES);
619 void InkscapePreferences::initPageMasks()
621     _mask_mask_on_top.init ( _("When applying, use the topmost selected object as clippath/mask"), "/options/maskobject/topmost", true);
622     _page_mask.add_line(true, "", _mask_mask_on_top, "",
623                         _("Uncheck this to use the bottom selected object as the clipping path or mask"));
624     _mask_mask_remove.init ( _("Remove clippath/mask object after applying"), "/options/maskobject/remove", true);
625     _page_mask.add_line(true, "", _mask_mask_remove, "",
626                         _("After applying, remove the object used as the clipping path or mask from the drawing"));
627     this->AddPage(_page_mask, _("Clippaths and masks"), PREFS_PAGE_MASKS);
630 void InkscapePreferences::initPageTransforms()
632     _trans_scale_stroke.init ( _("Scale stroke width"), "/options/transform/stroke", true);
633     _trans_scale_corner.init ( _("Scale rounded corners in rectangles"), "/options/transform/rectcorners", false);
634     _trans_gradient.init ( _("Transform gradients"), "/options/transform/gradient", true);
635     _trans_pattern.init ( _("Transform patterns"), "/options/transform/pattern", false);
636     _trans_optimized.init ( _("Optimized"), "/options/preservetransform/value", 0, true, 0);
637     _trans_preserved.init ( _("Preserved"), "/options/preservetransform/value", 1, false, &_trans_optimized);
639     _page_transforms.add_line( false, "", _trans_scale_stroke, "",
640                                _("When scaling objects, scale the stroke width by the same proportion"));
641     _page_transforms.add_line( false, "", _trans_scale_corner, "",
642                                _("When scaling rectangles, scale the radii of rounded corners"));
643     _page_transforms.add_line( false, "", _trans_gradient, "",
644                                _("Move gradients (in fill or stroke) along with the objects"));
645     _page_transforms.add_line( false, "", _trans_pattern, "",
646                                _("Move patterns (in fill or stroke) along with the objects"));
647     _page_transforms.add_group_header( _("Store transformation:"));
648     _page_transforms.add_line( true, "", _trans_optimized, "",
649                                _("If possible, apply transformation to objects without adding a transform= attribute"));
650     _page_transforms.add_line( true, "", _trans_preserved, "",
651                                _("Always store transformation as a transform= attribute on objects"));
653     this->AddPage(_page_transforms, _("Transforms"), PREFS_PAGE_TRANSFORMS);
656 void InkscapePreferences::initPageFilters()
658     /* blur quality */
659     _blur_quality_best.init ( _("Best quality (slowest)"), "/options/blurquality/value",
660                                   BLUR_QUALITY_BEST, false, 0);
661     _blur_quality_better.init ( _("Better quality (slower)"), "/options/blurquality/value",
662                                   BLUR_QUALITY_BETTER, false, &_blur_quality_best);
663     _blur_quality_normal.init ( _("Average quality"), "/options/blurquality/value",
664                                   BLUR_QUALITY_NORMAL, true, &_blur_quality_best);
665     _blur_quality_worse.init ( _("Lower quality (faster)"), "/options/blurquality/value",
666                                   BLUR_QUALITY_WORSE, false, &_blur_quality_best);
667     _blur_quality_worst.init ( _("Lowest quality (fastest)"), "/options/blurquality/value",
668                                   BLUR_QUALITY_WORST, false, &_blur_quality_best);
670     _page_filters.add_group_header( _("Gaussian blur quality for display:"));
671     _page_filters.add_line( true, "", _blur_quality_best, "",
672                            _("Best quality, but display may be very slow at high zooms (bitmap export always uses best quality)"));
673     _page_filters.add_line( true, "", _blur_quality_better, "",
674                            _("Better quality, but slower display"));
675     _page_filters.add_line( true, "", _blur_quality_normal, "",
676                            _("Average quality, acceptable display speed"));
677     _page_filters.add_line( true, "", _blur_quality_worse, "",
678                            _("Lower quality (some artifacts), but display is faster"));
679     _page_filters.add_line( true, "", _blur_quality_worst, "",
680                            _("Lowest quality (considerable artifacts), but display is fastest"));
682     /* filter quality */
683     _filter_quality_best.init ( _("Best quality (slowest)"), "/options/filterquality/value",
684                                   NR::FILTER_QUALITY_BEST, false, 0);
685     _filter_quality_better.init ( _("Better quality (slower)"), "/options/filterquality/value",
686                                   NR::FILTER_QUALITY_BETTER, false, &_filter_quality_best);
687     _filter_quality_normal.init ( _("Average quality"), "/options/filterquality/value",
688                                   NR::FILTER_QUALITY_NORMAL, true, &_filter_quality_best);
689     _filter_quality_worse.init ( _("Lower quality (faster)"), "/options/filterquality/value",
690                                   NR::FILTER_QUALITY_WORSE, false, &_filter_quality_best);
691     _filter_quality_worst.init ( _("Lowest quality (fastest)"), "/options/filterquality/value",
692                                   NR::FILTER_QUALITY_WORST, false, &_filter_quality_best);
694     _page_filters.add_group_header( _("Filter effects quality for display:"));
695     _page_filters.add_line( true, "", _filter_quality_best, "",
696                            _("Best quality, but display may be very slow at high zooms (bitmap export always uses best quality)"));
697     _page_filters.add_line( true, "", _filter_quality_better, "",
698                            _("Better quality, but slower display"));
699     _page_filters.add_line( true, "", _filter_quality_normal, "",
700                            _("Average quality, acceptable display speed"));
701     _page_filters.add_line( true, "", _filter_quality_worse, "",
702                            _("Lower quality (some artifacts), but display is faster"));
703     _page_filters.add_line( true, "", _filter_quality_worst, "",
704                            _("Lowest quality (considerable artifacts), but display is fastest"));
706     /* show infobox */
707     _show_filters_info_box.init( _("Show filter primitives infobox"), "/options/showfiltersinfobox/value", true);
708     _page_filters.add_line(true, "", _show_filters_info_box, "",
709                         _("Show icons and descriptions for the filter primitives available at the filter effects dialog."));
711     this->AddPage(_page_filters, _("Filters"), PREFS_PAGE_FILTERS);
715 void InkscapePreferences::initPageSelecting()
717     _sel_all.init ( _("Select in all layers"), "/options/kbselection/inlayer", PREFS_SELECTION_ALL, false, 0);
718     _sel_current.init ( _("Select only within current layer"), "/options/kbselection/inlayer", PREFS_SELECTION_LAYER, true, &_sel_all);
719     _sel_recursive.init ( _("Select in current layer and sublayers"), "/options/kbselection/inlayer", PREFS_SELECTION_LAYER_RECURSIVE, false, &_sel_all);
720     _sel_hidden.init ( _("Ignore hidden objects and layers"), "/options/kbselection/onlyvisible", true);
721     _sel_locked.init ( _("Ignore locked objects and layers"), "/options/kbselection/onlysensitive", true);
722     _sel_layer_deselects.init ( _("Deselect upon layer change"), "/options/selection/layerdeselect", true);
724     _page_select.add_group_header( _("Ctrl+A, Tab, Shift+Tab:"));
725     _page_select.add_line( true, "", _sel_all, "",
726                            _("Make keyboard selection commands work on objects in all layers"));
727     _page_select.add_line( true, "", _sel_current, "",
728                            _("Make keyboard selection commands work on objects in current layer only"));
729     _page_select.add_line( true, "", _sel_recursive, "",
730                            _("Make keyboard selection commands work on objects in current layer and all its sublayers"));
731     _page_select.add_line( true, "", _sel_hidden, "",
732                            _("Uncheck this to be able to select objects that are hidden (either by themselves or by being in a hidden layer)"));
733     _page_select.add_line( true, "", _sel_locked, "",
734                            _("Uncheck this to be able to select objects that are locked (either by themselves or by being in a locked layer)"));
736     _page_select.add_line( false, "", _sel_layer_deselects, "",
737                            _("Uncheck this to be able to keep the current objects selected when the current layer changes"));
739     this->AddPage(_page_select, _("Selecting"), PREFS_PAGE_SELECTING);
743 void InkscapePreferences::initPageImportExport()
745     _importexport_export.init("/dialogs/export/defaultxdpi/value", 0.0, 6000.0, 1.0, 1.0, PX_PER_IN, true, false);
746     _page_importexport.add_line( false, _("Default export resolution:"), _importexport_export, _("dpi"),
747                             _("Default bitmap resolution (in dots per inch) in the Export dialog"), false);
748     _importexport_ocal_url.init("/options/ocalurl/str", true, g_strdup_printf("openclipart.org"));
749     _page_importexport.add_line( false, _("Open Clip Art Library Server Name:"), _importexport_ocal_url, "",
750         _("The server name of the Open Clip Art Library webdav server. It's used by the Import and Export to OCAL function."), true);
751     _importexport_ocal_username.init("/options/ocalusername/str", true);
752     _page_importexport.add_line( false, _("Open Clip Art Library Username:"), _importexport_ocal_username, "",
753             _("The username used to log into Open Clip Art Library."), true);
754     _importexport_ocal_password.init("/options/ocalpassword/str", false);
755     _page_importexport.add_line( false, _("Open Clip Art Library Password:"), _importexport_ocal_password, "",
756             _("The password used to log into Open Clip Art Library."), true);
758     this->AddPage(_page_importexport, _("Import/Export"), PREFS_PAGE_IMPORTEXPORT);
761 #if ENABLE_LCMS
762 static void profileComboChanged( Gtk::ComboBoxText* combo )
764     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
765     int rowNum = combo->get_active_row_number();
766     if ( rowNum < 1 ) {
767         prefs->setString("/options/displayprofile/uri", "");
768     } else {
769         Glib::ustring active = combo->get_active_text();
771         Glib::ustring path = get_path_for_profile(active);
772         if ( !path.empty() ) {
773             prefs->setString("/options/displayprofile/uri", path);
774         }
775     }
778 static void proofComboChanged( Gtk::ComboBoxText* combo )
780     Glib::ustring active = combo->get_active_text();
781     Glib::ustring path = get_path_for_profile(active);
782     
783     if ( !path.empty() ) {
784         Inkscape::Preferences *prefs = Inkscape::Preferences::get();
785         prefs->setString("/options/softproof/uri", path);
786     }
789 static void gamutColorChanged( Gtk::ColorButton* btn ) {
790     Gdk::Color color = btn->get_color();
791     gushort r = color.get_red();
792     gushort g = color.get_green();
793     gushort b = color.get_blue();
795     gchar* tmp = g_strdup_printf("#%02x%02x%02x", (r >> 8), (g >> 8), (b >> 8) );
797     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
798     prefs->setString("/options/softproof/gamutcolor", tmp);
799     g_free(tmp);
801 #endif // ENABLE_LCMS
803 void InkscapePreferences::initPageCMS()
805     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
806     int const numIntents = 4;
807     /* TRANSLATORS: see http://www.newsandtech.com/issues/2004/03-04/pt/03-04_rendering.htm */
808     Glib::ustring intentLabels[numIntents] = {_("Perceptual"), _("Relative Colorimetric"), _("Saturation"), _("Absolute Colorimetric")};
809     int intentValues[numIntents] = {0, 1, 2, 3};
811 #if !ENABLE_LCMS
812     Gtk::Label* lbl = new Gtk::Label(_("(Note: Color management has been disabled in this build)"));
813     _page_cms.add_line( false, "", *lbl, "", "", true);
814 #endif // !ENABLE_LCMS
816     _page_cms.add_group_header( _("Display adjustment"));
818     _page_cms.add_line( false, _("Display profile:"), _cms_display_profile, "",
819                         _("The ICC profile to use to calibrate display output."), false);
821     _cms_from_display.init( _("Retrieve profile from display"), "/options/displayprofile/from_display", false);
822     _page_cms.add_line( false, "", _cms_from_display, "",
823 #ifdef GDK_WINDOWING_X11
824                         _("Retrieve profiles from those attached to displays via XICC."), false);
825 #else
826                         _("Retrieve profiles from those attached to displays."), false);
827 #endif // GDK_WINDOWING_X11
830     _cms_intent.init("/options/displayprofile/intent", intentLabels, intentValues, numIntents, 0);
831     _page_cms.add_line( false, _("Display rendering intent:"), _cms_intent, "",
832                         _("The rendering intent to use to calibrate display output."), false);
834     _page_cms.add_group_header( _("Proofing"));
836     _cms_softproof.init( _("Simulate output on screen"), "/options/softproof/enable", false);
837     _page_cms.add_line( false, "", _cms_softproof, "",
838                         _("Simulates output of target device."), false);
840     _cms_gamutwarn.init( _("Mark out of gamut colors"), "/options/softproof/gamutwarn", false);
841     _page_cms.add_line( false, "", _cms_gamutwarn, "",
842                         _("Highlights colors that are out of gamut for the target device."), false);
844     Glib::ustring colorStr = prefs->getString("/options/softproof/gamutcolor");
845     Gdk::Color tmpColor( colorStr.empty() ? "#00ff00" : colorStr);
846     _cms_gamutcolor.set_color( tmpColor );
847     _page_cms.add_line( true, _("Out of gamut warning color:"), _cms_gamutcolor, "",
848                         _("Selects the color used for out of gamut warning."), false);
850     _page_cms.add_line( false, _("Device profile:"), _cms_proof_profile, "",
851                         _("The ICC profile to use to simulate device output."), false);
853     _cms_proof_intent.init("/options/softproof/intent", intentLabels, intentValues, numIntents, 0);
854     _page_cms.add_line( false, _("Device rendering intent:"), _cms_proof_intent, "",
855                         _("The rendering intent to use to calibrate display output."), false);
857     _cms_proof_blackpoint.init( _("Black point compensation"), "/options/softproof/bpc", false);
858     _page_cms.add_line( false, "", _cms_proof_blackpoint, "",
859                         _("Enables black point compensation."), false);
861     _cms_proof_preserveblack.init( _("Preserve black"), "/options/softproof/preserveblack", false);
862     _page_cms.add_line( false, "", _cms_proof_preserveblack,
863 #if defined(cmsFLAGS_PRESERVEBLACK)
864                         "",
865 #else
866                         _("(LittleCMS 1.15 or later required)"),
867 #endif // defined(cmsFLAGS_PRESERVEBLACK)
868                         _("Preserve K channel in CMYK -> CMYK transforms"), false);
870 #if !defined(cmsFLAGS_PRESERVEBLACK)
871     _cms_proof_preserveblack.set_sensitive( false );
872 #endif // !defined(cmsFLAGS_PRESERVEBLACK)
875 #if ENABLE_LCMS
876     {
877         std::vector<Glib::ustring> names = ::Inkscape::colorprofile_get_display_names();
878         Glib::ustring current = prefs->getString( "/options/displayprofile/uri" );
880         gint index = 0;
881         _cms_display_profile.append_text(_("<none>"));
882         index++;
883         for ( std::vector<Glib::ustring>::iterator it = names.begin(); it != names.end(); ++it ) {
884             _cms_display_profile.append_text( *it );
885             Glib::ustring path = get_path_for_profile(*it);
886             if ( !path.empty() && path == current ) {
887                 _cms_display_profile.set_active(index);
888             }
889             index++;
890         }
891         if ( current.empty() ) {
892             _cms_display_profile.set_active(0);
893         }
895         names = ::Inkscape::colorprofile_get_softproof_names();
896         current = prefs->getString("/options/softproof/uri");
897         index = 0;
898         for ( std::vector<Glib::ustring>::iterator it = names.begin(); it != names.end(); ++it ) {
899             _cms_proof_profile.append_text( *it );
900             Glib::ustring path = get_path_for_profile(*it);
901             if ( !path.empty() && path == current ) {
902                 _cms_proof_profile.set_active(index);
903             }
904             index++;
905         }
906     }
908     _cms_gamutcolor.signal_color_set().connect( sigc::bind( sigc::ptr_fun(gamutColorChanged), &_cms_gamutcolor) );
910     _cms_display_profile.signal_changed().connect( sigc::bind( sigc::ptr_fun(profileComboChanged), &_cms_display_profile) );
911     _cms_proof_profile.signal_changed().connect( sigc::bind( sigc::ptr_fun(proofComboChanged), &_cms_proof_profile) );
912 #else
913     // disable it, but leave it visible
914     _cms_intent.set_sensitive( false );
915     _cms_display_profile.set_sensitive( false );
916     _cms_from_display.set_sensitive( false );
917     _cms_softproof.set_sensitive( false );
918     _cms_gamutwarn.set_sensitive( false );
919     _cms_gamutcolor.set_sensitive( false );
920     _cms_proof_intent.set_sensitive( false );
921     _cms_proof_profile.set_sensitive( false );
922     _cms_proof_blackpoint.set_sensitive( false );
923     _cms_proof_preserveblack.set_sensitive( false );
924 #endif // ENABLE_LCMS
926     this->AddPage(_page_cms, _("Color management"), PREFS_PAGE_CMS);
929 void InkscapePreferences::initPageGrids()
931     _page_grids.add_group_header( _("Major grid line emphasizing"));
933     _grids_no_emphasize_on_zoom.init( _("Don't emphasize gridlines when zoomed out"), "/options/grids/no_emphasize_when_zoomedout", false);
934     _page_grids.add_line( false, "", _grids_no_emphasize_on_zoom, "", _("If set and zoomed out, the gridlines will be shown in normal color instead of major grid line color."), false);
936     _page_grids.add_group_header( _("Default grid settings"));
938     _page_grids.add_line( false, "", _grids_notebook, "", "", false);
939     _grids_notebook.append_page(_grids_xy,     CanvasGrid::getName( GRID_RECTANGULAR ));
940     _grids_notebook.append_page(_grids_axonom, CanvasGrid::getName( GRID_AXONOMETRIC ));
941         _grids_xy_units.init("/options/grids/units");
942         _grids_xy.add_line( false, _("Grid units:"), _grids_xy_units, "", "", false);
943         _grids_xy_origin_x.init("/options/grids/xy/origin_x", -10000.0, 10000.0, 0.1, 1.0, 0.0, false, false);
944         _grids_xy_origin_y.init("/options/grids/xy/origin_y", -10000.0, 10000.0, 0.1, 1.0, 0.0, false, false);
945         _grids_xy.add_line( false, _("Origin X:"), _grids_xy_origin_x, "", _("X coordinate of grid origin"), false);
946         _grids_xy.add_line( false, _("Origin Y:"), _grids_xy_origin_y, "", _("Y coordinate of grid origin"), false);
947         _grids_xy_spacing_x.init("/options/grids/xy/spacing_x", -10000.0, 10000.0, 0.1, 1.0, 1.0, false, false);
948         _grids_xy_spacing_y.init("/options/grids/xy/spacing_y", -10000.0, 10000.0, 0.1, 1.0, 1.0, false, false);
949         _grids_xy.add_line( false, _("Spacing X:"), _grids_xy_spacing_x, "", _("Distance between vertical grid lines"), false);
950         _grids_xy.add_line( false, _("Spacing Y:"), _grids_xy_spacing_y, "", _("Distance between horizontal grid lines"), false);
952         _grids_xy_color.init(_("Grid line color:"), "/options/grids/xy/color", 0x0000ff20);
953         _grids_xy.add_line( false, _("Grid line color:"), _grids_xy_color, "", _("Color used for normal grid lines"), false);
954         _grids_xy_empcolor.init(_("Major grid line color:"), "/options/grids/xy/empcolor", 0x0000ff40);
955         _grids_xy.add_line( false, _("Major grid line color:"), _grids_xy_empcolor, "", _("Color used for major (highlighted) grid lines"), false);
956         _grids_xy_empspacing.init("/options/grids/xy/empspacing", 1.0, 1000.0, 1.0, 5.0, 5.0, true, false);
957         _grids_xy.add_line( false, _("Major grid line every:"), _grids_xy_empspacing, "", "", false);
958         _grids_xy_dotted.init( _("Show dots instead of lines"), "/options/grids/xy/dotted", false);
959         _grids_xy.add_line( false, "", _grids_xy_dotted, "", _("If set, display dots at gridpoints instead of gridlines"), false);
961     // CanvasAxonomGrid properties:
962         _grids_axonom_units.init("/options/grids/axonom/units");
963         _grids_axonom.add_line( false, _("Grid units:"), _grids_axonom_units, "", "", false);
964         _grids_axonom_origin_x.init("/options/grids/axonom/origin_x", -10000.0, 10000.0, 0.1, 1.0, 0.0, false, false);
965         _grids_axonom_origin_y.init("/options/grids/axonom/origin_y", -10000.0, 10000.0, 0.1, 1.0, 0.0, false, false);
966         _grids_axonom.add_line( false, _("Origin X:"), _grids_axonom_origin_x, "", _("X coordinate of grid origin"), false);
967         _grids_axonom.add_line( false, _("Origin Y:"), _grids_axonom_origin_y, "", _("Y coordinate of grid origin"), false);
968         _grids_axonom_spacing_y.init("/options/grids/axonom/spacing_y", -10000.0, 10000.0, 0.1, 1.0, 1.0, false, false);
969         _grids_axonom.add_line( false, _("Spacing Y:"), _grids_axonom_spacing_y, "", _("Base length of z-axis"), false);
970         _grids_axonom_angle_x.init("/options/grids/axonom/angle_x", -360.0, 360.0, 1.0, 10.0, 30.0, false, false);
971         _grids_axonom_angle_z.init("/options/grids/axonom/angle_z", -360.0, 360.0, 1.0, 10.0, 30.0, false, false);
972         _grids_axonom.add_line( false, _("Angle X:"), _grids_axonom_angle_x, "", _("Angle of x-axis"), false);
973         _grids_axonom.add_line( false, _("Angle Z:"), _grids_axonom_angle_z, "", _("Angle of z-axis"), false);
974         _grids_axonom_color.init(_("Grid line color:"), "/options/grids/axonom/color", 0x0000ff20);
975         _grids_axonom.add_line( false, _("Grid line color:"), _grids_axonom_color, "", _("Color used for normal grid lines"), false);
976         _grids_axonom_empcolor.init(_("Major grid line color:"), "/options/grids/axonom/empcolor", 0x0000ff40);
977         _grids_axonom.add_line( false, _("Major grid line color:"), _grids_axonom_empcolor, "", _("Color used for major (highlighted) grid lines"), false);
978         _grids_axonom_empspacing.init("/options/grids/axonom/empspacing", 1.0, 1000.0, 1.0, 5.0, 5.0, true, false);
979         _grids_axonom.add_line( false, _("Major grid line every:"), _grids_axonom_empspacing, "", "", false);
981     this->AddPage(_page_grids, _("Grids"), PREFS_PAGE_GRIDS);
984 void InkscapePreferences::initPageSVGOutput()
986     _svgoutput_usenamedcolors.init( _("Use named colors"), "/options/svgoutput/usenamedcolors", false);
987     _page_svgoutput.add_line( false, "", _svgoutput_usenamedcolors, "", _("If set, write the CSS name of the color when available (e.g. 'red' or 'magenta') instead of the numeric value"), false);
989     _page_svgoutput.add_group_header( _("XML formatting"));
991     _svgoutput_inlineattrs.init( _("Inline attributes"), "/options/svgoutput/inlineattrs", false);
992     _page_svgoutput.add_line( false, "", _svgoutput_inlineattrs, "", _("Put attributes on the same line as the element tag"), false);
994     _svgoutput_indent.init("/options/svgoutput/indent", 0.0, 1000.0, 1.0, 2.0, 2.0, true, false);
995     _page_svgoutput.add_line( false, _("Indent, spaces:"), _svgoutput_indent, "", _("The number of spaces to use for indenting nested elements; set to 0 for no indentation"), false);
997     _page_svgoutput.add_group_header( _("Path data"));
999     _svgoutput_allowrelativecoordinates.init( _("Allow relative coordinates"), "/options/svgoutput/allowrelativecoordinates", true);
1000     _page_svgoutput.add_line( false, "", _svgoutput_allowrelativecoordinates, "", _("If set, relative coordinates may be used in path data"), false);
1002     _svgoutput_forcerepeatcommands.init( _("Force repeat commands"), "/options/svgoutput/forcerepeatcommands", false);
1003     _page_svgoutput.add_line( false, "", _svgoutput_forcerepeatcommands, "", _("Force repeating of the same path command (for example, 'L 1,2 L 3,4' instead of 'L 1,2 3,4')"), false);
1005     _page_svgoutput.add_group_header( _("Numbers"));
1007     _svgoutput_numericprecision.init("/options/svgoutput/numericprecision", 1.0, 16.0, 1.0, 2.0, 8.0, true, false);
1008     _page_svgoutput.add_line( false, _("Numeric precision:"), _svgoutput_numericprecision, "", _("How many digits to write after the decimal dot"), false);
1010     _svgoutput_minimumexponent.init("/options/svgoutput/minimumexponent", -32.0, -1, 1.0, 2.0, -8.0, true, false);
1011     _page_svgoutput.add_line( false, _("Minimum exponent:"), _svgoutput_minimumexponent, "", _("The smallest number written to SVG is 10 to the power of this exponent; anything smaller is written as zero."), false);
1013     this->AddPage(_page_svgoutput, _("SVG output"), PREFS_PAGE_SVGOUTPUT);
1016 void InkscapePreferences::initPageUI()
1018      Glib::ustring sizeLabels[] = {_("Normal"), _("Medium"), _("Small")};
1019     int sizeValues[] = {0, 1, 2};
1021     _misc_small_toolbar.init( "/toolbox/small", sizeLabels, sizeValues, G_N_ELEMENTS(sizeLabels), 0 );
1022     _page_ui.add_line( false, _("Commands bar icon size"), _misc_small_toolbar, "",
1023                               _("Set the size for the commands toolbar to use (requires restart)"), false);
1025     _misc_small_secondary.init( "/toolbox/secondary", sizeLabels, sizeValues, G_N_ELEMENTS(sizeLabels), 1 );
1026     _page_ui.add_line( false, _("Tool controls bar icon size"), _misc_small_secondary, "",
1027                               _("Set the size for the secondary toolbar to use (requires restart)"), false);
1029     _misc_small_tools.init( "/toolbox/tools/small", sizeLabels, sizeValues, G_N_ELEMENTS(sizeLabels), 0 );
1030     _page_ui.add_line( false, _("Main toolbar icon size"), _misc_small_tools, "",
1031                               _("Set the size for the main tools to use (requires restart)"), false);
1033     _misc_recent.init("/options/maxrecentdocuments/value", 0.0, 1000.0, 1.0, 1.0, 1.0, true, false);
1034     _page_ui.add_line( false, _("Maximum documents in Open Recent:"), _misc_recent, "",
1035                               _("The maximum length of the Open Recent list in the File menu"), false);
1037     _ui_zoom_correction.init(300, 30, 1.00, 200.0, 1.0, 10.0, 1.0);
1038     _page_ui.add_line( false, _("Zoom correction factor (in %):"), _ui_zoom_correction, "",
1039                               _("Adjust the slider until the length of the ruler on your screen matches its real length. This information is used when zooming to 1:1, 1:2, etc., to display objects in their true sizes"), true);
1041     this->AddPage(_page_ui, _("Interface"), PREFS_PAGE_UI);
1045 void InkscapePreferences::initPageAutosave()
1047     // Autosave options 
1048     _autosave_autosave_enable.init( _("Enable autosave (requires restart)"), "/options/autosave/enable", false);
1049     _page_autosave.add_line(false, "", _autosave_autosave_enable, "", _("Automatically save the current document(s) at a given interval, thus minimizing loss in case of a crash"), false);
1050     _autosave_autosave_interval.init("/options/autosave/interval", 1.0, 10800.0, 1.0, 10.0, 10.0, true, false);
1051     _page_autosave.add_line(true, _("Interval (in minutes):"), _autosave_autosave_interval, "", _("Interval (in minutes) at which document will be autosaved"), false);
1052     _autosave_autosave_path.init("/options/autosave/path", true);
1053     _page_autosave.add_line(true, _("Path:"), _autosave_autosave_path, "", _("The directory where autosaves will be written"), false);
1054     _autosave_autosave_max.init("/options/autosave/max", 1.0, 100.0, 1.0, 10.0, 10.0, true, false);
1055     _page_autosave.add_line(true, _("Maximum number of autosaves:"), _autosave_autosave_max, "", _("Maximum number of autosaved files; use this to limit the storage space used"), false);
1057     /* When changing the interval or enabling/disabling the autosave function,
1058      * update our running configuration
1059      *
1060      * FIXME!
1061      * the inkscape_autosave_init should be called AFTER the values have been changed
1062      * (which cannot be guaranteed from here) - use a PrefObserver somewhere
1063      */
1064     /*
1065     _autosave_autosave_enable.signal_toggled().connect( sigc::ptr_fun(inkscape_autosave_init), TRUE );
1066     _autosave_autosave_interval.signal_changed().connect( sigc::ptr_fun(inkscape_autosave_init), TRUE );
1067     */
1069     // -----------
1071     this->AddPage(_page_autosave, _("Autosave"), PREFS_PAGE_AUTOSAVE);
1074 void InkscapePreferences::initPageBitmaps()
1076     {
1077         Glib::ustring labels[] = {_("None"), _("2x2"), _("4x4"), _("8x8"), _("16x16")};
1078         int values[] = {0, 1, 2, 3, 4};
1079         _misc_overs_bitmap.set_size_request(_sb_width);
1080         _misc_overs_bitmap.init("/options/bitmapoversample/value", labels, values, G_N_ELEMENTS(values), 1);
1081         _page_bitmaps.add_line( false, _("Oversample bitmaps:"), _misc_overs_bitmap, "", "", false);
1082     }
1084     _misc_bitmap_autoreload.init(_("Automatically reload bitmaps"), "/options/bitmapautoreload/value", true);
1085     _page_bitmaps.add_line( false, "", _misc_bitmap_autoreload, "",
1086                            _("Automatically reload linked images when file is changed on disk"));
1087     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1088     Glib::ustring choices = prefs->getString("/options/bitmapeditor/choices");
1089     if (!choices.empty()) {
1090         gchar** splits = g_strsplit(choices.data(), ",", 0);
1091         gint numIems = g_strv_length(splits);
1093         Glib::ustring labels[numIems];
1094         int values[numIems];
1095         for ( gint i = 0; i < numIems; i++) {
1096             values[i] = i;
1097             labels[i] = splits[i];
1098         }
1099         _misc_bitmap_editor.init("/options/bitmapeditor/value", labels, values, numIems, 0);
1100         _page_bitmaps.add_line( false, _("Bitmap editor:"), _misc_bitmap_editor, "", "", false);
1102         g_strfreev(splits);
1103     }
1105     _bitmap_copy_res.init("/options/createbitmap/resolution", 1.0, 6000.0, 1.0, 1.0, PX_PER_IN, true, false);
1106     _page_bitmaps.add_line( false, _("Resolution for Create Bitmap Copy:"), _bitmap_copy_res, _("dpi"),
1107                             _("Resolution used by the Create Bitmap Copy command"), false);
1109     this->AddPage(_page_bitmaps, _("Bitmaps"), PREFS_PAGE_BITMAPS);
1113 void InkscapePreferences::initPageMisc()
1115     _misc_comment.init( _("Add label comments to printing output"), "/printing/debug/show-label-comments", false);
1116     _page_misc.add_line( false, "", _misc_comment, "",
1117                            _("When on, a comment will be added to the raw print output, marking the rendered output for an object with its label"), true);
1119     _misc_forkvectors.init( _("Prevent sharing of gradient definitions"), "/options/forkgradientvectors/value", true);
1120     _page_misc.add_line( false, "", _misc_forkvectors, "",
1121                            _("When on, shared gradient definitions are automatically forked on change; uncheck to allow sharing of gradient definitions so that editing one object may affect other objects using the same gradient"), true);
1123     _misc_simpl.init("/options/simplifythreshold/value", 0.0001, 1.0, 0.0001, 0.0010, 0.0010, false, false);
1124     _page_misc.add_line( false, _("Simplification threshold:"), _misc_simpl, "",
1125                            _("How strong is the Simplify command by default. If you invoke this command several times in quick succession, it will act more and more aggressively; invoking it again after a pause restores the default threshold."), false);
1127     _misc_latency_skew.init("/debug/latency/skew", 0.5, 2.0, 0.01, 0.10, 1.0, false, false);
1128     _page_misc.add_line( false, _("Latency skew:"), _misc_latency_skew, _("(requires restart)"),
1129                            _("Factor by which the event clock is skewed from the actual time (0.9766 on some systems)."), false);
1131     _misc_namedicon_delay.init( _("Pre-render named icons"), "/options/iconrender/named_nodelay", false);
1132     _page_misc.add_line( false, "", _misc_namedicon_delay, "",
1133                            _("When on, named icons will be rendered before displaying the ui. This is for working around bugs in GTK+ named icon notification"), true);
1135     this->AddPage(_page_misc, _("Misc"), PREFS_PAGE_MISC);
1138 bool InkscapePreferences::SetMaxDialogSize(const Gtk::TreeModel::iterator& iter)
1140     Gtk::TreeModel::Row row = *iter;
1141     DialogPage* page = row[_page_list_columns._col_page];
1142     _page_frame.add(*page);
1143     this->show_all_children();
1144     Gtk:: Requisition sreq;
1145     this->size_request(sreq);
1146     _max_dialog_width=std::max(_max_dialog_width, sreq.width);
1147     _max_dialog_height=std::max(_max_dialog_height, sreq.height);
1148     _page_frame.remove();
1149     return false;
1152 bool InkscapePreferences::PresentPage(const Gtk::TreeModel::iterator& iter)
1154     Gtk::TreeModel::Row row = *iter;
1155     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1156     int desired_page = prefs->getInt("/dialogs/preferences/page", 0);
1157     if (desired_page == row[_page_list_columns._col_id])
1158     {
1159         if (desired_page >= PREFS_PAGE_TOOLS && desired_page <= PREFS_PAGE_TOOLS_DROPPER)
1160             _page_list.expand_row(_path_tools, false);
1161         if (desired_page >= PREFS_PAGE_TOOLS_SHAPES && desired_page <= PREFS_PAGE_TOOLS_SHAPES_SPIRAL)
1162             _page_list.expand_row(_path_shapes, false);
1163         _page_list.get_selection()->select(iter);
1164         return true;
1165     }
1166     return false;
1169 void InkscapePreferences::on_pagelist_selection_changed()
1171     // show new selection
1172     Glib::RefPtr<Gtk::TreeSelection> selection = _page_list.get_selection();
1173     Gtk::TreeModel::iterator iter = selection->get_selected();
1174     if(iter)
1175     {
1176         if (_current_page)
1177             _page_frame.remove();
1178         Gtk::TreeModel::Row row = *iter;
1179         _current_page = row[_page_list_columns._col_page];
1180         Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1181         prefs->setInt("/dialogs/preferences/page", row[_page_list_columns._col_id]);
1182         _page_title.set_markup("<span size='large'><b>" + row[_page_list_columns._col_name] + "</b></span>");
1183         _page_frame.add(*_current_page);
1184         _current_page->show();
1185         while (Gtk::Main::events_pending())
1186         {
1187             Gtk::Main::iteration();
1188         }
1189         this->show_all_children();
1190     }
1193 void InkscapePreferences::_presentPages()
1195     _page_list_model->foreach_iter(sigc::mem_fun(*this, &InkscapePreferences::PresentPage));
1198 } // namespace Dialog
1199 } // namespace UI
1200 } // namespace Inkscape
1202 /*
1203   Local Variables:
1204   mode:c++
1205   c-file-style:"stroustrup"
1206   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1207   indent-tabs-mode:nil
1208   fill-column:99
1209   End:
1210 */
1211 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :