Merge lp:~chr0x07/inkscape/trunk.fixes into lp:~inkscape.dev/inkscape/trunk

Proposed by chr[]
Status: Merged
Merged at revision: 15700
Proposed branch: lp:~chr0x07/inkscape/trunk.fixes
Merge into: lp:~inkscape.dev/inkscape/trunk
Diff against target: 816 lines (+216/-83)
21 files modified
src/live_effects/lpe-bspline.cpp (+1/-0)
src/live_effects/lpe-clone-original.cpp (+9/-3)
src/live_effects/lpe-copy_rotate.cpp (+3/-1)
src/live_effects/lpe-measure-line.cpp (+7/-4)
src/live_effects/lpe-mirror_symmetry.cpp (+3/-1)
src/live_effects/parameter/path.cpp (+2/-1)
src/object-set.h (+2/-0)
src/path-chemistry.cpp (+2/-1)
src/selection-chemistry.cpp (+52/-2)
src/sp-item-group.cpp (+1/-0)
src/sp-item.cpp (+6/-2)
src/sp-item.h (+2/-2)
src/sp-pattern.cpp (+4/-2)
src/svg/svg-affine-test.h (+3/-1)
src/ui/dialog/objects.cpp (+75/-44)
src/ui/dialog/objects.h (+4/-1)
src/ui/widget/clipmaskicon.cpp (+12/-12)
src/ui/widget/clipmaskicon.h (+2/-2)
src/verbs.cpp (+14/-0)
src/verbs.h (+2/-0)
src/widgets/stroke-marker-selector.cpp (+10/-4)
To merge this branch: bzr merge lp:~chr0x07/inkscape/trunk.fixes
Reviewer Review Type Date Requested Status
Mc Pending
Review via email: mp+324217@code.launchpad.net

Description of the change

All of lp:~chr0x07/inkscape/0.92.fixes.2

* Support Raise and Lower (z-order) for non-overlapping objects

* including polish of object panel

* fix: speed up inkscape startup time
  (due to missing icons / non cached icons)

* and some more bugfixes

To post a comment you must log in.
lp:~chr0x07/inkscape/trunk.fixes updated
15698. By Mc

merge dimon's branch: fixed xverbs

Revision history for this message
chr[] (chr0x07) wrote :

rebased: fixed the translators comment bug ;)

reddy for merge

lp:~chr0x07/inkscape/trunk.fixes updated
15699. By chr[] <email address hidden>

bugfix crash while moving objects

sp_svg_transform_write can return NULL and Glib::ustring blows up:

terminate called after throwing an instance of 'std::logic_error'
  what(): basic_string::_S_construct null not valid

 #0 0x00007fffed6ec067 in raise () from /lib/x86_64-linux-gnu/libc.so.6
 #1 0x00007fffed6ed448 in abort () from /lib/x86_64-linux-gnu/libc.so.6
 #2 0x00007fffedac2b3d in __gnu_cxx::__verbose_terminate_handler() ()
    from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
 #3 0x00007fffedac0bb6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
 #4 0x00007fffedac0c01 in std::terminate() ()
    from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
 #5 0x00007fffedac0e19 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
 #6 0x00007fffedb168b6 in std::__throw_logic_error(char const*) ()
    from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
 #7 0x00007ffff76e83d5 in char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) ()
    from /usr/bin/../lib/inkscape/libinkscape_base.so
 #8 0x00007fffedb22c46 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) ()
    from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
 #9 0x00007ffff036055e in Glib::ustring::ustring(char const*) ()
    from /usr/lib/x86_64-linux-gnu/libglibmm-2.4.so.1
 #10 0x00007ffff75650e3 in SPPattern::transform_multiply(Geom::Affine, bool) ()
    from /usr/bin/../lib/inkscape/libinkscape_base.so
 #11 0x00007ffff753d862 in SPItem::adjust_pattern(Geom::Affine const&, bool, PatternTransform) () from /usr/bin/../lib/inkscape/libinkscape_base.so
 #12 0x00007ffff7562897 in SPPath::set_transform(Geom::Affine const&) ()
    from /usr/bin/../lib/inkscape/libinkscape_base.so

15700. By chr[] <email address hidden>

fix a brunch of memory leaks

15701. By chr[] <email address hidden>

stroke-style: fix preloading no-marker

speed up inkscape startup

15702. By chr[] <email address hidden>

object manager panel: fix clip/mask icons

missing icon delayed inkscape startup of about 3-5 seconds

15703. By chr[] <email address hidden>

ObjectsPanel: Polish collapse/expand behaviour

15704. By chr[] <email address hidden>

object panel: don't scroll to layer when leaving object group

don't jump too much around in the list

15705. By chr[] <email address hidden>

selection chemistry: implement z-stack order

Bug #1395452

"raise and lower objects" used to stack objects above/below the next overlapping object,
which makes it impossible to change the z-order of objects that don't overlap.

Fixes also the object manager panel

Conflicts:
 src/selection-chemistry.cpp
 src/selection-chemistry.h
 src/sp-item.cpp

15706. By chr[] <email address hidden>

object panel: search function blocks too many keystrokes

use ctrl+f to use search

Issue: select object in the object panel, focus stays on that widget.
Press "3" (zoom to object) used to open the search function.

15707. By chr[] <email address hidden>

object panel: don't block F2 key, use return to edit cell

15708. By chr[] <email address hidden>

opject panel: rework shotcuts: let the user decide

This implemetation respect the users action shortcuts,
handled in this order:

1) Two hardcoded keystrokes:

* crtl+f engage search on tree view
* esc: defocus: next keystrokes goes to desktop

2) Try to invoke user defined shortcut action

3) RETURN-key: activate action of selected column
   currently works on the name-column only

4) shortcut goes to Treeview

For the testers:

The new verbs "stack up/down" are not bound to keystrokes. Set them up as you like via
preferences / interface / keyboard shortcuts / selection / stack up and down

Try keystrokes with focus on desktop, on object-panel and compare with layer-panel:

PageUp/Down + - shift, ctrl

esc esc

arrow esc arrow

ctrl+f

V, H - may(!) flip objects

ctrl+a (!)

! invert selection

Beside user definable keystrokes, there are some hardcoded:

arrow-up/down + shift,ctrl

[ ] - rotate objects - not user defined actions, so does not work in panel focus

/ * also keypad / * is usually fold/unfold tree but * actually selects the "star tool",
which can be disabled if you don't like that

Conflicts:
 src/ui/dialog/objects.cpp

15709. By chr[] <email address hidden>

bugfix: change active layer

note: the actions "LayerNext"/"LayerPrev" (ctrl+pageup/down)
never clear the selection, they ignore the user setting
"clear selection on layer change"

So the object panel will only change if there is no selection!

15710. By chr[] <email address hidden>

fix a brunch of memory leaks pt.2

I'd like to see the crappy API fixed,
to avoid this stupid mistakes.

15711. By chr[] <email address hidden>

selection chemistry: cancel if we hit top/bottom

avoid unpredictable results in multi selections

Revision history for this message
chr[] (chr0x07) wrote :

just for the record:

itsssssssssssssss Monty Pythons Flying Circus now

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/live_effects/lpe-bspline.cpp'
2--- src/live_effects/lpe-bspline.cpp 2017-05-05 16:52:19 +0000
3+++ src/live_effects/lpe-bspline.cpp 2017-05-23 19:51:06 +0000
4@@ -168,6 +168,7 @@
5 doBSplineFromWidget(curve, weight_ammount/100.0);
6 gchar *str = sp_svg_write_path(curve->get_pathvector());
7 path->getRepr()->setAttribute("inkscape:original-d", str);
8+ g_free(str);
9 }
10 }
11
12
13=== modified file 'src/live_effects/lpe-clone-original.cpp'
14--- src/live_effects/lpe-clone-original.cpp 2017-05-01 01:21:44 +0000
15+++ src/live_effects/lpe-clone-original.cpp 2017-05-23 19:51:06 +0000
16@@ -138,10 +138,14 @@
17 dest_affine *= Geom::Translate(preserve_affine.translation());
18 affine_previous = preserve_affine;
19 preserve_affine = Geom::identity();
20- SP_ITEM(dest)->getRepr()->setAttribute("transform",sp_svg_transform_write(dest_affine));
21+ gchar * str = sp_svg_transform_write(dest_affine);
22+ SP_ITEM(dest)->getRepr()->setAttribute("transform", str);
23+ g_free(str);
24 }
25 } else {
26- SP_ITEM(dest)->getRepr()->setAttribute("transform",sp_svg_transform_write(affine_origin));
27+ gchar * str = sp_svg_transform_write(affine_origin);
28+ SP_ITEM(dest)->getRepr()->setAttribute("transform", str);
29+ g_free(str);
30 }
31 } else if ( shape_dest && shape_origin && live && (std::strcmp(attribute, "d") == 0)) {
32 SPCurve *c = NULL;
33@@ -176,7 +180,9 @@
34 c->set_pathvector(c_pv);
35 if (!path_origin) {
36 shape_dest->setCurveInsync(c, TRUE);
37- dest->getRepr()->setAttribute(attribute, sp_svg_write_path(c_pv));
38+ gchar *str = sp_svg_write_path(c_pv);
39+ dest->getRepr()->setAttribute(attribute, str);
40+ g_free(str);
41 } else {
42 shape_dest->setCurve(c, TRUE);
43 }
44
45=== modified file 'src/live_effects/lpe-copy_rotate.cpp'
46--- src/live_effects/lpe-copy_rotate.cpp 2017-05-12 17:09:47 +0000
47+++ src/live_effects/lpe-copy_rotate.cpp 2017-05-23 19:51:06 +0000
48@@ -274,7 +274,9 @@
49 Inkscape::GC::release(phantom);
50 }
51 cloneD(SP_OBJECT(sp_lpe_item), elemref, true, reset);
52- elemref->getRepr()->setAttribute("transform" , sp_svg_transform_write(transform));
53+ gchar *str = sp_svg_transform_write(transform);
54+ elemref->getRepr()->setAttribute("transform" , str);
55+ g_free(str);
56 SP_ITEM(elemref)->setHidden(false);
57 if (elemref->parent != container) {
58 Inkscape::XML::Node *copy = phantom->duplicate(xml_doc);
59
60=== modified file 'src/live_effects/lpe-measure-line.cpp'
61--- src/live_effects/lpe-measure-line.cpp 2017-05-01 01:21:44 +0000
62+++ src/live_effects/lpe-measure-line.cpp 2017-05-23 19:51:06 +0000
63@@ -260,7 +260,7 @@
64 rtspan = xml_doc->createElement("svg:tspan");
65 rtspan->setAttribute("sodipodi:role", "line");
66 }
67- const char * transform;
68+ gchar * transform;
69 Geom::Affine affine = Geom::Affine(Geom::Translate(pos).inverse());
70 angle = std::fmod(angle, 2*M_PI);
71 if (angle < 0) angle += 2*M_PI;
72@@ -276,6 +276,7 @@
73 transform = NULL;
74 }
75 rtext->setAttribute("transform", transform);
76+ g_free(transform);
77 SPCSSAttr *css = sp_repr_css_attr_new();
78 sp_repr_css_attr_add_from_string(css, anotation_format.param_getSVGValue());
79 Inkscape::FontLister *fontlister = Inkscape::FontLister::get_instance();
80@@ -317,7 +318,7 @@
81 g_snprintf(length_str, 64, "%.*f", (int)precision, length);
82 setlocale (LC_NUMERIC, oldlocale);
83 g_free (oldlocale);
84- Glib::ustring label_value = Glib::ustring(format.param_getSVGValue());
85+ Glib::ustring label_value(format.param_getSVGValue());
86 size_t s = label_value.find(Glib::ustring("{measure}"),0);
87 if(s < label_value.length()) {
88 label_value.replace(s,s+9,length_str);
89@@ -413,17 +414,19 @@
90 }
91 line = elemref->getRepr();
92
93- const char * line_str = sp_svg_write_path( line_pathv );
94+ gchar * line_str = sp_svg_write_path( line_pathv );
95 line->setAttribute("d" , line_str);
96 line->setAttribute("transform", NULL);
97+ g_free(line_str);
98 } else {
99 if (remove) {
100 return;
101 }
102 line = xml_doc->createElement("svg:path");
103 line->setAttribute("id", id);
104- const char * line_str = sp_svg_write_path( line_pathv );
105+ gchar * line_str = sp_svg_write_path( line_pathv );
106 line->setAttribute("d" , line_str);
107+ g_free(line_str);
108 }
109 line->setAttribute("sodipodi:insensitive", "true");
110 line_pathv.clear();
111
112=== modified file 'src/live_effects/lpe-mirror_symmetry.cpp'
113--- src/live_effects/lpe-mirror_symmetry.cpp 2017-05-07 17:16:47 +0000
114+++ src/live_effects/lpe-mirror_symmetry.cpp 2017-05-23 19:51:06 +0000
115@@ -291,7 +291,9 @@
116 Inkscape::GC::release(phantom);
117 }
118 cloneD(SP_OBJECT(sp_lpe_item), elemref, true, true);
119- elemref->getRepr()->setAttribute("transform" , sp_svg_transform_write(transform));
120+ gchar *str = sp_svg_transform_write(transform);
121+ elemref->getRepr()->setAttribute("transform" , str);
122+ g_free(str);
123 if (elemref->parent != container) {
124 Inkscape::XML::Node *copy = phantom->duplicate(xml_doc);
125 copy->setAttribute("id", elemref_id);
126
127=== modified file 'src/live_effects/parameter/path.cpp'
128--- src/live_effects/parameter/path.cpp 2017-04-29 00:01:22 +0000
129+++ src/live_effects/parameter/path.cpp 2017-05-23 19:51:06 +0000
130@@ -245,8 +245,9 @@
131 r.lpe_key = param_key;
132 Geom::PathVector stored_pv = _pathvector;
133 param_write_to_repr("M0,0 L1,0");
134- const char *svgd = sp_svg_write_path(stored_pv);
135+ gchar *svgd = sp_svg_write_path(stored_pv);
136 param_write_to_repr(svgd);
137+ g_free(svgd);
138 } else {
139 r.item = ref.getObject();
140 }
141
142=== modified file 'src/object-set.h'
143--- src/object-set.h 2017-02-28 22:07:32 +0000
144+++ src/object-set.h 2017-05-23 19:51:06 +0000
145@@ -377,8 +377,10 @@
146
147 //z-order management
148 //in selection-chemistry.cpp
149+ void stackUp(bool skip_undo = false);
150 void raise(bool skip_undo = false);
151 void raiseToTop(bool skip_undo = false);
152+ void stackDown(bool skip_undo = false);
153 void lower(bool skip_undo = false);
154 void lowerToBottom(bool skip_undo = false);
155 void toNextLayer(bool skip_undo = false);
156
157=== modified file 'src/path-chemistry.cpp'
158--- src/path-chemistry.cpp 2017-02-04 10:22:35 +0000
159+++ src/path-chemistry.cpp 2017-05-23 19:51:06 +0000
160@@ -255,8 +255,9 @@
161 repr->setAttribute("inkscape:original-d", str);
162 else
163 repr->setAttribute("d", str);
164+ str = sp_svg_transform_write(transform);
165+ repr->setAttribute("transform", str);
166 g_free(str);
167- repr->setAttribute("transform", sp_svg_transform_write(transform));
168
169 // add the new repr to the parent
170 parent->appendChild(repr);
171
172=== modified file 'src/selection-chemistry.cpp'
173--- src/selection-chemistry.cpp 2017-03-13 14:22:22 +0000
174+++ src/selection-chemistry.cpp 2017-05-23 19:51:06 +0000
175@@ -1140,6 +1140,53 @@
176 }
177 }
178
179+void ObjectSet::stackUp(bool skip_undo) {
180+ if (isEmpty()) {
181+ selection_display_message(desktop(), Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to stack up."));
182+ return;
183+ }
184+
185+ std::vector<SPItem*> selection(items().begin(), items().end());
186+ sort(selection.begin(), selection.end(), sp_item_repr_compare_position_bool);
187+
188+ for (auto item: selection | boost::adaptors::reversed) {
189+ if (!item->raiseOne()) { // stop if top was reached
190+ if(document() && !skip_undo)
191+ DocumentUndo::cancel(document());
192+ selection_display_message(desktop(), Inkscape::WARNING_MESSAGE, _("We hit top."));
193+ return;
194+ }
195+ }
196+
197+ if(document() && !skip_undo)
198+ DocumentUndo::done(document(), SP_VERB_SELECTION_STACK_UP,
199+ //TRANSLATORS: undo history: "stack up" means to raise an object of its ordinal position by 1
200+ C_("Undo action", "stack up"));
201+}
202+
203+void ObjectSet::stackDown(bool skip_undo) {
204+ if (isEmpty()) {
205+ selection_display_message(desktop(), Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to stack down."));
206+ return;
207+ }
208+
209+ std::vector<SPItem*> selection(items().begin(), items().end());
210+ sort(selection.begin(), selection.end(), sp_item_repr_compare_position_bool);
211+
212+ for (auto item: selection) {
213+ if (!item->lowerOne()) { // stop if bottom was reached
214+ if(document() && !skip_undo)
215+ DocumentUndo::cancel(document());
216+ selection_display_message(desktop(), Inkscape::WARNING_MESSAGE, _("We hit bottom."));
217+ return;
218+ }
219+ }
220+
221+ if(document() && !skip_undo)
222+ DocumentUndo::done(document(), SP_VERB_SELECTION_STACK_DOWN,
223+ //TRANSLATORS: undo history: "stack down" means to lower an object of its ordinal position by 1
224+ C_("Undo action", "stack down"));
225+}
226
227 void
228 sp_undo(SPDesktop *desktop, SPDocument *)
229@@ -3175,8 +3222,11 @@
230 the_parent_repr->appendChild(clone);
231
232 if( single_group && transform.isTranslation() ) {
233- if( !transform.isIdentity() )
234- clone->setAttribute("transform", sp_svg_transform_write( transform ));
235+ if( !transform.isIdentity() ) {
236+ gchar *c = sp_svg_transform_write( transform );
237+ clone->setAttribute("transform", c);
238+ g_free(c);
239+ }
240 }
241
242 // Change selection to new <use> element.
243
244=== modified file 'src/sp-item-group.cpp'
245--- src/sp-item-group.cpp 2017-01-24 09:36:22 +0000
246+++ src/sp-item-group.cpp 2017-05-23 19:51:06 +0000
247@@ -594,6 +594,7 @@
248 Geom::Affine ttrans = ctrans.inverse() * SP_ITEM(text)->transform * ctrans;
249 gchar *affinestr = sp_svg_transform_write(ttrans);
250 nrepr->setAttribute("transform", affinestr);
251+ g_free(affinestr);
252 }
253 } else {
254 nrepr->setAttribute("transform", affinestr);
255
256=== modified file 'src/sp-item.cpp'
257--- src/sp-item.cpp 2017-02-05 16:04:35 +0000
258+++ src/sp-item.cpp 2017-05-23 19:51:06 +0000
259@@ -306,15 +306,17 @@
260 }
261 }
262
263-void SPItem::raiseOne() {
264+bool SPItem::raiseOne() {
265 auto next_higher = std::find_if(++parent->children.iterator_to(*this), parent->children.end(), &is_item);
266 if (next_higher != parent->children.end()) {
267 Inkscape::XML::Node *ref = next_higher->getRepr();
268 getRepr()->parent()->changeOrder(getRepr(), ref);
269+ return true;
270 }
271+ return false;
272 }
273
274-void SPItem::lowerOne() {
275+bool SPItem::lowerOne() {
276 using Inkscape::Algorithms::find_last_if;
277
278 auto next_lower = find_last_if(parent->children.begin(), parent->children.iterator_to(*this), &is_item);
279@@ -325,7 +327,9 @@
280 ref = next_lower->getRepr();
281 }
282 getRepr()->parent()->changeOrder(getRepr(), ref);
283+ return true;
284 }
285+ return false;
286 }
287
288 void SPItem::lowerToBottom() {
289
290=== modified file 'src/sp-item.h'
291--- src/sp-item.h 2016-11-02 23:08:41 +0000
292+++ src/sp-item.h 2017-05-23 19:51:06 +0000
293@@ -212,8 +212,8 @@
294
295 Geom::Affine getRelativeTransform(SPObject const *obj) const;
296
297- void raiseOne();
298- void lowerOne();
299+ bool raiseOne();
300+ bool lowerOne();
301 void raiseToTop();
302 void lowerToBottom();
303
304
305=== modified file 'src/sp-pattern.cpp'
306--- src/sp-pattern.cpp 2017-02-05 16:04:35 +0000
307+++ src/sp-pattern.cpp 2017-05-23 19:51:06 +0000
308@@ -372,8 +372,9 @@
309 }
310 _pattern_transform_set = true;
311
312- Glib::ustring c = sp_svg_transform_write(_pattern_transform);
313+ gchar *c = sp_svg_transform_write(_pattern_transform);
314 getRepr()->setAttribute("patternTransform", c);
315+ g_free(c);
316 }
317
318 const gchar *SPPattern::produce(const std::vector<Inkscape::XML::Node *> &reprs, Geom::Rect bounds,
319@@ -390,8 +391,9 @@
320 sp_repr_set_svg_double(repr, "height", bounds.dimensions()[Geom::Y]);
321 //TODO: Maybe is better handle it in sp_svg_transform_write
322 if(transform != Geom::Affine()){
323- Glib::ustring t = sp_svg_transform_write(transform);
324+ gchar *t = sp_svg_transform_write(transform);
325 repr->setAttribute("patternTransform", t);
326+ g_free(t);
327 }
328 defsrepr->appendChild(repr);
329 const gchar *pat_id = repr->attribute("id");
330
331=== modified file 'src/svg/svg-affine-test.h'
332--- src/svg/svg-affine-test.h 2014-11-09 16:38:49 +0000
333+++ src/svg/svg-affine-test.h 2017-05-23 19:51:06 +0000
334@@ -67,7 +67,9 @@
335
336 void testWriteIdentity()
337 {
338- TS_ASSERT_EQUALS(sp_svg_transform_write(Geom::identity()) , (void*)0)
339+ gchar str = sp_svg_transform_write(Geom::identity());
340+ TS_ASSERT_EQUALS(str, NULL);
341+ g_free(str);
342 }
343
344 void testReadMatrix()
345
346=== modified file 'src/ui/dialog/objects.cpp'
347--- src/ui/dialog/objects.cpp 2016-12-27 15:49:22 +0000
348+++ src/ui/dialog/objects.cpp 2017-05-23 19:51:06 +0000
349@@ -30,6 +30,7 @@
350 #include "helper/action.h"
351 #include "inkscape.h"
352 #include "layer-manager.h"
353+#include "shortcuts.h"
354 #include "sp-clippath.h"
355 #include "sp-mask.h"
356 #include "sp-root.h"
357@@ -308,11 +309,13 @@
358 SPRoot* root = document->getRoot();
359 if ( root ) {
360 _selectedConnection.block();
361+ _documentChangedCurrentLayer.block();
362 //Clear the tree store
363 _store->clear();
364 //Add all items recursively
365 _addObject( root, 0 );
366 _selectedConnection.unblock();
367+ _documentChangedCurrentLayer.unblock();
368 //Set the tree selection
369 _objectsSelected(_desktop->selection);
370 //Handle button sensitivity
371@@ -350,13 +353,17 @@
372 row[_model->_colLocked] = !item->isSensitive();
373 row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0;
374 row[_model->_colHighlight] = item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00;
375- row[_model->_colClipMask] = item->clip_ref && item->clip_ref->getObject() ? 1 : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0);
376+ row[_model->_colClipMask] = item ? (
377+ (item->clip_ref && item->clip_ref->getObject() ? 1 : 0) |
378+ (item->mask_ref && item->mask_ref->getObject() ? 2 : 0)
379+ ) : 0;
380 //row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0;
381
382 //If our parent object is a group and it's expanded, expand the tree
383 if (SP_IS_GROUP(obj) && SP_GROUP(obj)->expanded())
384 {
385 _tree.expand_to_path( _store->get_path(iter) );
386+ _tree.collapse_row( _store->get_path(iter) );
387 }
388
389 //Add an object watcher to the item
390@@ -413,7 +420,10 @@
391 row[_model->_colLocked] = item ? !item->isSensitive() : false;
392 row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0;
393 row[_model->_colHighlight] = item ? (item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00) : 0;
394- row[_model->_colClipMask] = item ? (item->clip_ref && item->clip_ref->getObject() ? 1 : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0)) : 0;
395+ row[_model->_colClipMask] = item ? (
396+ (item->clip_ref && item->clip_ref->getObject() ? 1 : 0) |
397+ (item->mask_ref && item->mask_ref->getObject() ? 2 : 0)
398+ ) : 0;
399 //row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0;
400
401 return true;
402@@ -473,13 +483,13 @@
403 _setCompositingValues(item);
404 setOpacity = false;
405 }
406- _store->foreach(sigc::bind<SPItem *, bool>( sigc::mem_fun(*this, &ObjectsPanel::_checkForSelected), item, (*i)==items.back()));
407+ _store->foreach(sigc::bind<SPItem *, bool>( sigc::mem_fun(*this, &ObjectsPanel::_checkForSelected), item, (*i)==items.back(), false));
408 }
409 if (!item) {
410 if (_desktop->currentLayer() && SP_IS_ITEM(_desktop->currentLayer())) {
411 item = SP_ITEM(_desktop->currentLayer());
412 _setCompositingValues(item);
413- _store->foreach(sigc::bind<SPItem *, bool>( sigc::mem_fun(*this, &ObjectsPanel::_checkForSelected), item, true));
414+ _store->foreach(sigc::bind<SPItem *, bool>( sigc::mem_fun(*this, &ObjectsPanel::_checkForSelected), item, false, true));
415 }
416 }
417 _selectedConnection.unblock();
418@@ -545,7 +555,7 @@
419 * @param scrollto Whether to scroll to the item
420 * @return Whether to continue searching the tree
421 */
422-bool ObjectsPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPItem* item, bool scrollto)
423+bool ObjectsPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPItem* item, bool scrollto, bool expand)
424 {
425 bool stopGoing = false;
426
427@@ -554,13 +564,16 @@
428 {
429 //We found the item! Expand to the path and select it in the tree.
430 _tree.expand_to_path( path );
431+ if (!expand)
432+ // but don't expand itself, just the path
433+ _tree.collapse_row(path);
434
435 Glib::RefPtr<Gtk::TreeSelection> select = _tree.get_selection();
436
437 select->select(iter);
438 if (scrollto) {
439 //Scroll to the item in the tree
440- _tree.scroll_to_row(path);
441+ _tree.scroll_to_row(path, 0.5);
442 }
443
444 stopGoing = true;
445@@ -577,6 +590,7 @@
446 if ( _desktop && _desktop->currentRoot() ) {
447 //block connections for selection and compositing values to prevent interference
448 _selectionChangedConnection.block();
449+ _documentChangedCurrentLayer.block();
450
451 //Clear the selection and then iterate over the tree selection, pushing each item to the desktop
452 _desktop->selection->clear();
453@@ -584,6 +598,7 @@
454 _tree.get_selection()->selected_foreach_iter( sigc::bind<bool *>(sigc::mem_fun(*this, &ObjectsPanel::_selected_row_callback), &setOpacity));
455 //unblock connections
456 _selectionChangedConnection.unblock();
457+ _documentChangedCurrentLayer.unblock();
458
459 _checkTreeSelection();
460 }
461@@ -682,53 +697,63 @@
462 */
463 bool ObjectsPanel::_handleKeyEvent(GdkEventKey *event)
464 {
465-
466+ if (!_desktop)
467+ return false;
468+
469+ unsigned int shortcut;
470+ shortcut = Inkscape::UI::Tools::get_group0_keyval(event) |
471+ ( event->state & GDK_SHIFT_MASK ?
472+ SP_SHORTCUT_SHIFT_MASK : 0 ) |
473+ ( event->state & GDK_CONTROL_MASK ?
474+ SP_SHORTCUT_CONTROL_MASK : 0 ) |
475+ ( event->state & GDK_MOD1_MASK ?
476+ SP_SHORTCUT_ALT_MASK : 0 );
477+
478+ switch (shortcut) {
479+ // how to get users key binding for the action “start-interactive-search” ??
480+ // ctrl+f is just the default
481+ case GDK_KEY_f | SP_SHORTCUT_CONTROL_MASK:
482+ return false;
483+ break;
484+ // shall we slurp ctrl+w to close panel?
485+
486+ // defocus:
487+ case GDK_KEY_Escape:
488+ if (_desktop->canvas) {
489+ gtk_widget_grab_focus (GTK_WIDGET(_desktop->canvas));
490+ return true;
491+ }
492+ break;
493+ }
494+
495+ // invoke user defined shortcuts first
496+ bool done = sp_shortcut_invoke(shortcut, _desktop);
497+ if (done)
498+ return true;
499+
500+ // handle events for the treeview
501 bool empty = _desktop->selection->isEmpty();
502
503 switch (Inkscape::UI::Tools::get_group0_keyval(event)) {
504 case GDK_KEY_Return:
505 case GDK_KEY_KP_Enter:
506- case GDK_KEY_F2:
507 {
508- Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected();
509- if (iter && !_text_renderer->property_editable()) {
510+ Gtk::TreeModel::Path path;
511+ Gtk::TreeViewColumn *focus_column = 0;
512+
513+ _tree.get_cursor(path, focus_column);
514+ if (focus_column == _name_column && !_text_renderer->property_editable()) {
515 //Rename item
516- Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter);
517 _text_renderer->property_editable() = true;
518- _tree.set_cursor(*path, *_name_column, true);
519+ _tree.set_cursor(path, *_name_column, true);
520 grab_focus();
521 return true;
522 }
523- }
524- break;
525- case GDK_KEY_Home:
526- //Move item(s) to top of containing group/layer
527- _fireAction( empty ? SP_VERB_LAYER_TO_TOP : SP_VERB_SELECTION_TO_FRONT );
528- break;
529- case GDK_KEY_End:
530- //Move item(s) to bottom of containing group/layer
531- _fireAction( empty ? SP_VERB_LAYER_TO_BOTTOM : SP_VERB_SELECTION_TO_BACK );
532- break;
533- case GDK_KEY_Page_Up:
534- {
535- //Move item(s) up in containing group/layer
536- int ch = event->state & GDK_SHIFT_MASK ? SP_VERB_LAYER_MOVE_TO_NEXT : SP_VERB_SELECTION_RAISE;
537- _fireAction( empty ? SP_VERB_LAYER_RAISE : ch );
538- break;
539- }
540- case GDK_KEY_Page_Down:
541- {
542- //Move item(s) down in containing group/layer
543- int ch = event->state & GDK_SHIFT_MASK ? SP_VERB_LAYER_MOVE_TO_PREV : SP_VERB_SELECTION_LOWER;
544- _fireAction( empty ? SP_VERB_LAYER_LOWER : ch );
545- break;
546- }
547-
548- //TODO: Handle Ctrl-A, etc.
549- default:
550 return false;
551+ break;
552+ }
553 }
554- return true;
555+ return false;
556 }
557
558 /**
559@@ -1172,7 +1197,7 @@
560 }
561 else
562 {
563- _fireAction( SP_VERB_SELECTION_RAISE );
564+ _fireAction( SP_VERB_SELECTION_STACK_UP );
565 }
566 }
567 break;
568@@ -1184,7 +1209,7 @@
569 }
570 else
571 {
572- _fireAction( SP_VERB_SELECTION_LOWER );
573+ _fireAction( SP_VERB_SELECTION_STACK_DOWN );
574 }
575 }
576 break;
577@@ -1734,6 +1759,8 @@
578 //Set the expander and search columns
579 _tree.set_expander_column( *_tree.get_column(nameColNum) );
580 _tree.set_search_column(_model->_colLabel);
581+ // use ctrl+f to start search
582+ _tree.set_enable_search(false);
583
584 //Set up the tree selection
585 _tree.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);
586@@ -1893,8 +1920,8 @@
587
588 _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
589
590- _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_RAISE, "gtk-go-up", _("Up"), (int)BUTTON_UP ) );
591- _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_LOWER, "gtk-go-down", _("Down"), (int)BUTTON_DOWN ) );
592+ _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_STACK_UP, "gtk-go-up", _("Up"), (int)BUTTON_UP ) );
593+ _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_STACK_DOWN, "gtk-go-down", _("Down"), (int)BUTTON_DOWN ) );
594
595 _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
596
597@@ -2033,6 +2060,7 @@
598
599 if ( desktop != _desktop ) {
600 _documentChangedConnection.disconnect();
601+ _documentChangedCurrentLayer.disconnect();
602 _selectionChangedConnection.disconnect();
603 if ( _desktop ) {
604 _desktop = 0;
605@@ -2042,6 +2070,9 @@
606 if ( _desktop ) {
607 //Connect desktop signals
608 _documentChangedConnection = _desktop->connectDocumentReplaced( sigc::mem_fun(*this, &ObjectsPanel::setDocument));
609+
610+ _documentChangedCurrentLayer = _desktop->connectCurrentLayerChanged( sigc::mem_fun(*this, &ObjectsPanel::_objectsChanged));
611+
612 _selectionChangedConnection = _desktop->selection->connectChanged( sigc::mem_fun(*this, &ObjectsPanel::_objectsSelected));
613
614 setDocument(_desktop, _desktop->doc());
615
616=== modified file 'src/ui/dialog/objects.h'
617--- src/ui/dialog/objects.h 2016-07-28 15:16:18 +0000
618+++ src/ui/dialog/objects.h 2017-05-23 19:51:06 +0000
619@@ -77,6 +77,9 @@
620 //Connection for when the document changes
621 sigc::connection _documentChangedConnection;
622
623+ //Connection for when the active layer changes
624+ sigc::connection _documentChangedCurrentLayer;
625+
626 //Connection for when the active selection in the document changes
627 sigc::connection _selectionChangedConnection;
628
629@@ -216,7 +219,7 @@
630 bool _checkForUpdated(const Gtk::TreeIter& iter, SPObject* obj);
631
632 void _objectsSelected(Selection *sel);
633- bool _checkForSelected(const Gtk::TreePath& path, const Gtk::TreeIter& iter, SPItem* item, bool scrollto);
634+ bool _checkForSelected(const Gtk::TreePath& path, const Gtk::TreeIter& iter, SPItem* item, bool scrollto, bool expand);
635
636 void _objectsChanged(SPObject *obj);
637 void _addObject( SPObject* obj, Gtk::TreeModel::Row* parentRow );
638
639=== modified file 'src/ui/widget/clipmaskicon.cpp'
640--- src/ui/widget/clipmaskicon.cpp 2016-08-04 11:26:03 +0000
641+++ src/ui/widget/clipmaskicon.cpp 2017-05-23 19:51:06 +0000
642@@ -27,13 +27,13 @@
643 ClipMaskIcon::ClipMaskIcon() :
644 Glib::ObjectBase(typeid(ClipMaskIcon)),
645 Gtk::CellRendererPixbuf(),
646- _pixClipName(INKSCAPE_ICON("path-intersection")),
647- _pixInverseName(INKSCAPE_ICON("path-difference")),
648- _pixMaskName(INKSCAPE_ICON("mask-intersection")),
649+ _pixClipName(INKSCAPE_ICON("path-cut")),
650+ _pixMaskName(INKSCAPE_ICON("path-difference")),
651+ _pixBothName(INKSCAPE_ICON("bitmap-trace")),
652 _property_active(*this, "active", 0),
653 _property_pixbuf_clip(*this, "pixbuf_on", Glib::RefPtr<Gdk::Pixbuf>(0)),
654- _property_pixbuf_inverse(*this, "pixbuf_on", Glib::RefPtr<Gdk::Pixbuf>(0)),
655- _property_pixbuf_mask(*this, "pixbuf_off", Glib::RefPtr<Gdk::Pixbuf>(0))
656+ _property_pixbuf_mask(*this, "pixbuf_off", Glib::RefPtr<Gdk::Pixbuf>(0)),
657+ _property_pixbuf_both(*this, "pixbuf_on", Glib::RefPtr<Gdk::Pixbuf>(0))
658 {
659
660 property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE;
661@@ -43,22 +43,22 @@
662 if (!icon_theme->has_icon(_pixClipName)) {
663 Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixClipName.data()), Inkscape::ICON_SIZE_DECORATION );
664 }
665- if (!icon_theme->has_icon(_pixInverseName)) {
666- Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixInverseName.data()), Inkscape::ICON_SIZE_DECORATION );
667- }
668 if (!icon_theme->has_icon(_pixMaskName)) {
669 Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixMaskName.data()), Inkscape::ICON_SIZE_DECORATION );
670 }
671+ if (!icon_theme->has_icon(_pixBothName)) {
672+ Inkscape::queueIconPrerender( INKSCAPE_ICON(_pixBothName.data()), Inkscape::ICON_SIZE_DECORATION );
673+ }
674
675 if (icon_theme->has_icon(_pixClipName)) {
676 _property_pixbuf_clip = icon_theme->load_icon(_pixClipName, phys, (Gtk::IconLookupFlags)0);
677 }
678- if (icon_theme->has_icon(_pixInverseName)) {
679- _property_pixbuf_inverse = icon_theme->load_icon(_pixInverseName, phys, (Gtk::IconLookupFlags)0);
680- }
681 if (icon_theme->has_icon(_pixMaskName)) {
682 _property_pixbuf_mask = icon_theme->load_icon(_pixMaskName, phys, (Gtk::IconLookupFlags)0);
683 }
684+ if (icon_theme->has_icon(_pixBothName)) {
685+ _property_pixbuf_both = icon_theme->load_icon(_pixBothName, phys, (Gtk::IconLookupFlags)0);
686+ }
687
688 property_pixbuf() = Glib::RefPtr<Gdk::Pixbuf>(0);
689 }
690@@ -108,7 +108,7 @@
691 property_pixbuf() = _property_pixbuf_mask;
692 break;
693 case 3:
694- property_pixbuf() = _property_pixbuf_inverse;
695+ property_pixbuf() = _property_pixbuf_both;
696 break;
697 default:
698 property_pixbuf() = Glib::RefPtr<Gdk::Pixbuf>(0);
699
700=== modified file 'src/ui/widget/clipmaskicon.h'
701--- src/ui/widget/clipmaskicon.h 2016-07-28 12:19:42 +0000
702+++ src/ui/widget/clipmaskicon.h 2017-05-23 19:51:06 +0000
703@@ -58,13 +58,13 @@
704 int phys;
705
706 Glib::ustring _pixClipName;
707- Glib::ustring _pixInverseName;
708 Glib::ustring _pixMaskName;
709+ Glib::ustring _pixBothName;
710
711 Glib::Property<int> _property_active;
712 Glib::Property< Glib::RefPtr<Gdk::Pixbuf> > _property_pixbuf_clip;
713- Glib::Property< Glib::RefPtr<Gdk::Pixbuf> > _property_pixbuf_inverse;
714 Glib::Property< Glib::RefPtr<Gdk::Pixbuf> > _property_pixbuf_mask;
715+ Glib::Property< Glib::RefPtr<Gdk::Pixbuf> > _property_pixbuf_both;
716
717 };
718
719
720=== modified file 'src/verbs.cpp'
721--- src/verbs.cpp 2017-03-22 19:03:41 +0000
722+++ src/verbs.cpp 2017-05-23 19:51:06 +0000
723@@ -1179,6 +1179,12 @@
724 case SP_VERB_SELECTION_LOWER:
725 selection->lower();
726 break;
727+ case SP_VERB_SELECTION_STACK_UP:
728+ selection->stackUp();
729+ break;
730+ case SP_VERB_SELECTION_STACK_DOWN:
731+ selection->stackDown();
732+ break;
733 case SP_VERB_SELECTION_GROUP:
734 selection->group();
735 break;
736@@ -2685,6 +2691,14 @@
737 N_("Raise selection one step"), INKSCAPE_ICON("selection-raise")),
738 new SelectionVerb(SP_VERB_SELECTION_LOWER, "SelectionLower", N_("_Lower"),
739 N_("Lower selection one step"), INKSCAPE_ICON("selection-lower")),
740+
741+
742+ new SelectionVerb(SP_VERB_SELECTION_STACK_UP, "SelectionStackUp", N_("_Stack up"),
743+ N_("Stack selection one step up"), INKSCAPE_ICON("layer-raise")),
744+ new SelectionVerb(SP_VERB_SELECTION_STACK_DOWN, "SelectionStackDown", N_("_Stack down"),
745+ N_("Stack selection one step down"), INKSCAPE_ICON("layer-lower")),
746+
747+
748 new SelectionVerb(SP_VERB_SELECTION_GROUP, "SelectionGroup", N_("_Group"),
749 N_("Group selected objects"), INKSCAPE_ICON("object-group")),
750 new SelectionVerb(SP_VERB_SELECTION_UNGROUP, "SelectionUnGroup", N_("_Ungroup"),
751
752=== modified file 'src/verbs.h'
753--- src/verbs.h 2017-03-22 19:03:41 +0000
754+++ src/verbs.h 2017-05-23 19:51:06 +0000
755@@ -116,6 +116,8 @@
756 SP_VERB_SELECTION_TO_BACK,
757 SP_VERB_SELECTION_RAISE,
758 SP_VERB_SELECTION_LOWER,
759+ SP_VERB_SELECTION_STACK_UP,
760+ SP_VERB_SELECTION_STACK_DOWN,
761 SP_VERB_SELECTION_GROUP,
762 SP_VERB_SELECTION_UNGROUP,
763 SP_VERB_SELECTION_UNGROUP_POP_SELECTION,
764
765=== modified file 'src/widgets/stroke-marker-selector.cpp'
766--- src/widgets/stroke-marker-selector.cpp 2016-08-03 14:56:48 +0000
767+++ src/widgets/stroke-marker-selector.cpp 2017-05-23 19:51:06 +0000
768@@ -54,8 +54,13 @@
769 set_cell_data_func(image_renderer, sigc::mem_fun(*this, &MarkerComboBox::prepareImageRenderer));
770 gtk_combo_box_set_row_separator_func(GTK_COMBO_BOX(gobj()), MarkerComboBox::separator_cb, NULL, NULL);
771
772+ Glib::ustring no_marker("no-marker");
773+ Glib::RefPtr<Gtk::IconTheme> iconTheme = Gtk::IconTheme::get_default();
774+ if (!iconTheme->has_icon(no_marker)) {
775+ Inkscape::queueIconPrerender( INKSCAPE_ICON(no_marker.data()), Inkscape::ICON_SIZE_SMALL_TOOLBAR );
776+ }
777 empty_image = new Gtk::Image( Glib::wrap(
778- sp_pixbuf_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON("no-marker") ) ) );
779+ sp_pixbuf_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON(no_marker.data()) ) ) );
780
781 sandbox = ink_markers_preview_doc ();
782 desktop = SP_ACTIVE_DESKTOP;
783@@ -71,6 +76,7 @@
784 MarkerComboBox::~MarkerComboBox() {
785 delete combo_id;
786 delete sandbox;
787+ delete empty_image;
788
789 if (doc) {
790 modified_connection.disconnect();
791@@ -393,7 +399,7 @@
792 gchar const *markid = repr->attribute("inkscape:stockid") ? repr->attribute("inkscape:stockid") : repr->attribute("id");
793
794 // generate preview
795- Gtk::Image *prv = create_marker_image (22, repr->attribute("id"), source, drawing, visionkey);
796+ Gtk::Image *prv = create_marker_image (24, repr->attribute("id"), source, drawing, visionkey);
797 prv->show();
798
799 // Add history before separator, others after
800@@ -424,14 +430,14 @@
801 MarkerComboBox::update_marker_image(gchar const *mname)
802 {
803 gchar *cache_name = g_strconcat(combo_id, mname, NULL);
804- Glib::ustring key = svg_preview_cache.cache_key(doc->getURI(), cache_name, 22);
805+ Glib::ustring key = svg_preview_cache.cache_key(doc->getURI(), cache_name, 24);
806 g_free (cache_name);
807 svg_preview_cache.remove_preview_from_cache(key);
808
809 Inkscape::Drawing drawing;
810 unsigned const visionkey = SPItem::display_key_new(1);
811 drawing.setRoot(sandbox->getRoot()->invoke_show(drawing, visionkey, SP_ITEM_SHOW_DISPLAY));
812- Gtk::Image *prv = create_marker_image(22, mname, doc, drawing, visionkey);
813+ Gtk::Image *prv = create_marker_image(24, mname, doc, drawing, visionkey);
814 if (prv) {
815 prv->show();
816 }