Fix route group collect option.
[ardour.git] / gtk2_ardour / editor_route_groups.cc
1 /*
2     Copyright (C) 2000 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <cstdlib>
21 #include <cmath>
22
23 #include <gtkmm2ext/stop_signal.h>
24 #include <gtkmm2ext/gtk_ui.h>
25 #include "ardour/route_group.h"
26
27 #include "editor.h"
28 #include "keyboard.h"
29 #include "marker.h"
30 #include "time_axis_view.h"
31 #include "prompter.h"
32 #include "gui_thread.h"
33 #include "editor_group_tabs.h"
34 #include "route_group_dialog.h"
35 #include "route_time_axis.h"
36 #include "editor_routes.h"
37 #include "editor_route_groups.h"
38
39 #include "ardour/route.h"
40
41 #include "i18n.h"
42
43 using namespace std;
44 using namespace sigc;
45 using namespace ARDOUR;
46 using namespace PBD;
47 using namespace Gtk;
48
49 EditorRouteGroups::EditorRouteGroups (Editor* e)
50         : EditorComponent (e),
51           _menu (0),
52           _in_row_change (false)
53
54 {
55         _model = ListStore::create (_columns);
56         _display.set_model (_model);
57
58         _display.append_column (_("Name"), _columns.text);
59
60         _display.append_column (_("G"), _columns.gain);
61         _display.append_column (_("R"), _columns.record);
62         _display.append_column (_("M"), _columns.mute);
63         _display.append_column (_("S"), _columns.solo);
64         _display.append_column (_("Sel"), _columns.select);
65         _display.append_column (_("E"), _columns.edits);
66
67         _display.append_column (_("Show"), _columns.is_visible);
68
69         _display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
70         _display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
71         _display.get_column (2)->set_data (X_("colnum"), GUINT_TO_POINTER(2));
72         _display.get_column (3)->set_data (X_("colnum"), GUINT_TO_POINTER(3));
73         _display.get_column (4)->set_data (X_("colnum"), GUINT_TO_POINTER(4));
74         _display.get_column (5)->set_data (X_("colnum"), GUINT_TO_POINTER(5));
75         _display.get_column (6)->set_data (X_("colnum"), GUINT_TO_POINTER(6));
76         _display.get_column (7)->set_data (X_("colnum"), GUINT_TO_POINTER(7));
77
78         _display.get_column (0)->set_expand (true);
79         _display.get_column (1)->set_expand (false);
80         _display.get_column (2)->set_expand (false);
81         _display.get_column (3)->set_expand (false);
82         _display.get_column (4)->set_expand (false);
83         _display.get_column (5)->set_expand (false);
84         _display.get_column (6)->set_expand (false);
85         _display.get_column (7)->set_expand (false);
86
87         _display.set_headers_visible (true);
88
89         /* name is directly editable */
90
91         CellRendererText* name_cell = dynamic_cast<CellRendererText*>(_display.get_column_cell_renderer (0));
92         name_cell->property_editable() = true;
93         name_cell->signal_edited().connect (mem_fun (*this, &EditorRouteGroups::name_edit));
94
95         /* use checkbox for the active + visible columns */
96
97         CellRendererToggle* active_cell = dynamic_cast<CellRendererToggle*>(_display.get_column_cell_renderer (1));
98         active_cell->property_activatable() = true;
99         active_cell->property_radio() = false;
100
101         active_cell = dynamic_cast<CellRendererToggle*>(_display.get_column_cell_renderer (2));
102         active_cell->property_activatable() = true;
103         active_cell->property_radio() = false;
104
105         active_cell = dynamic_cast<CellRendererToggle*>(_display.get_column_cell_renderer (3));
106         active_cell->property_activatable() = true;
107         active_cell->property_radio() = false;
108
109         active_cell = dynamic_cast<CellRendererToggle*>(_display.get_column_cell_renderer (4));
110         active_cell->property_activatable() = true;
111         active_cell->property_radio() = false;
112
113         active_cell = dynamic_cast<CellRendererToggle*>(_display.get_column_cell_renderer (5));
114         active_cell->property_activatable() = true;
115         active_cell->property_radio() = false;
116
117         active_cell = dynamic_cast<CellRendererToggle*>(_display.get_column_cell_renderer (6));
118         active_cell->property_activatable() = true;
119         active_cell->property_radio() = false;
120
121         active_cell = dynamic_cast<CellRendererToggle*>(_display.get_column_cell_renderer (7));
122         active_cell->property_activatable() = true;
123         active_cell->property_radio() = false;
124
125         _model->signal_row_changed().connect (mem_fun (*this, &EditorRouteGroups::row_change));
126
127         _display.set_name ("EditGroupList");
128         _display.get_selection()->set_mode (SELECTION_SINGLE);
129         _display.set_headers_visible (true);
130         _display.set_reorderable (false);
131         _display.set_rules_hint (true);
132         _display.set_size_request (75, -1);
133
134         _scroller.add (_display);
135         _scroller.set_policy (POLICY_AUTOMATIC, POLICY_AUTOMATIC);
136
137         _display.signal_button_press_event().connect (mem_fun(*this, &EditorRouteGroups::button_press_event), false);
138
139         _display_packer = new VBox;
140         HBox* button_box = manage (new HBox());
141         button_box->set_homogeneous (true);
142
143         Button* add_button = manage (new Button ());
144         Button* remove_button = manage (new Button ());
145
146         Widget* w;
147
148         w = manage (new Image (Stock::ADD, ICON_SIZE_BUTTON));
149         w->show();
150         add_button->add (*w);
151
152         w = manage (new Image (Stock::REMOVE, ICON_SIZE_BUTTON));
153         w->show();
154         remove_button->add (*w);
155
156         add_button->signal_clicked().connect (mem_fun (*this, &EditorRouteGroups::new_route_group));
157         remove_button->signal_clicked().connect (mem_fun (*this, &EditorRouteGroups::remove_selected));
158         
159         button_box->pack_start (*add_button);
160         button_box->pack_start (*remove_button);
161
162         _display_packer->pack_start (_scroller, true, true);
163         _display_packer->pack_start (*button_box, false, false);
164 }
165         
166
167 Gtk::Menu*
168 EditorRouteGroups::menu (RouteGroup* g)
169 {
170         using namespace Gtk::Menu_Helpers;
171
172         delete _menu;
173
174         Menu* new_from = new Menu;
175         MenuList& f = new_from->items ();
176         f.push_back (MenuElem (_("Selection..."), mem_fun (*this, &EditorRouteGroups::new_from_selection)));
177         f.push_back (MenuElem (_("Record Enabled..."), mem_fun (*this, &EditorRouteGroups::new_from_rec_enabled)));
178         f.push_back (MenuElem (_("Soloed..."), mem_fun (*this, &EditorRouteGroups::new_from_soloed)));
179
180         _menu = new Menu;
181         _menu->set_name ("ArdourContextMenu");
182         MenuList& items = _menu->items();
183
184         items.push_back (MenuElem (_("New..."), mem_fun(*this, &EditorRouteGroups::new_route_group)));
185         items.push_back (MenuElem (_("New From"), *new_from));
186         if (g) {
187                 items.push_back (MenuElem (_("Edit..."), bind (mem_fun (*this, &EditorRouteGroups::edit), g)));
188                 items.push_back (MenuElem (_("Fit to Window"), bind (mem_fun (*_editor, &Editor::fit_route_group), g)));
189                 items.push_back (MenuElem (_("Subgroup"), bind (mem_fun (*this, &EditorRouteGroups::subgroup), g)));
190                 items.push_back (MenuElem (_("Collect"), bind (mem_fun (*this, &EditorRouteGroups::collect), g)));
191         }
192         items.push_back (SeparatorElem());
193         items.push_back (MenuElem (_("Activate All"), mem_fun(*this, &EditorRouteGroups::activate_all)));
194         items.push_back (MenuElem (_("Disable All"), mem_fun(*this, &EditorRouteGroups::disable_all)));
195
196         return _menu;
197 }
198
199 void
200 EditorRouteGroups::subgroup (RouteGroup* g)
201 {
202         g->make_subgroup ();
203 }
204
205 void
206 EditorRouteGroups::unsubgroup (RouteGroup* g)
207 {
208         g->destroy_subgroup ();
209 }
210
211 void
212 EditorRouteGroups::activate_all ()
213 {
214         _session->foreach_route_group (
215                 bind (mem_fun (*this, &EditorRouteGroups::set_activation), true)
216                 );
217 }
218
219 void
220 EditorRouteGroups::disable_all ()
221 {
222         _session->foreach_route_group (
223                 bind (mem_fun (*this, &EditorRouteGroups::set_activation), false)
224                 );
225 }
226
227 void
228 EditorRouteGroups::set_activation (RouteGroup* g, bool a)
229 {
230         g->set_active (a, this);
231 }
232
233 void
234 EditorRouteGroups::new_route_group ()
235 {
236         RouteGroup* g = new RouteGroup (
237                 *_session,
238                 "",
239                 RouteGroup::Active,
240                 (RouteGroup::Property) (RouteGroup::Mute | RouteGroup::Solo | RouteGroup::Edit)
241                 );
242
243         RouteGroupDialog d (g, Gtk::Stock::NEW);
244         int const r = d.do_run ();
245
246         if (r == Gtk::RESPONSE_OK) {
247                 _session->add_route_group (g);
248         } else {
249                 delete g;
250         }
251 }
252
253 void
254 EditorRouteGroups::new_from_selection ()
255 {
256         RouteGroup* g = new RouteGroup (
257                 *_session,
258                 "",
259                 RouteGroup::Active,
260                 (RouteGroup::Property) (RouteGroup::Mute | RouteGroup::Solo | RouteGroup::Edit | RouteGroup::Select)
261                 );
262
263         RouteGroupDialog d (g, Gtk::Stock::NEW);
264         int const r = d.do_run ();
265
266         if (r == Gtk::RESPONSE_OK) {
267                 _session->add_route_group (g);
268
269                 for (TrackSelection::iterator i = _editor->get_selection().tracks.begin(); i != _editor->get_selection().tracks.end(); ++i) {
270                         RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
271                         if (rtv) {
272                                 rtv->route()->set_route_group (g, this);
273                         }
274                 }
275                 
276         } else {
277                 delete g;
278         }
279 }
280
281 void
282 EditorRouteGroups::new_from_rec_enabled ()
283 {
284         RouteGroup* g = new RouteGroup (
285                 *_session,
286                 "",
287                 RouteGroup::Active,
288                 (RouteGroup::Property) (RouteGroup::Mute | RouteGroup::Solo | RouteGroup::Edit | RouteGroup::RecEnable)
289                 );
290
291         RouteGroupDialog d (g, Gtk::Stock::NEW);
292         int const r = d.do_run ();
293
294         if (r == Gtk::RESPONSE_OK) {
295                 _session->add_route_group (g);
296
297                 for (Editor::TrackViewList::const_iterator i = _editor->get_track_views().begin(); i != _editor->get_track_views().end(); ++i) {
298                         RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
299                         if (rtv && rtv->route()->record_enabled()) {
300                                 rtv->route()->set_route_group (g, this);
301                         }
302                 }
303                 
304         } else {
305                 delete g;
306         }
307 }
308
309 void
310 EditorRouteGroups::new_from_soloed ()
311 {
312         RouteGroup* g = new RouteGroup (
313                 *_session,
314                 "",
315                 RouteGroup::Active,
316                 (RouteGroup::Property) (RouteGroup::Mute | RouteGroup::Solo | RouteGroup::Edit)
317                 );
318
319         RouteGroupDialog d (g, Gtk::Stock::NEW);
320         int const r = d.do_run ();
321
322         if (r == Gtk::RESPONSE_OK) {
323                 _session->add_route_group (g);
324
325                 for (Editor::TrackViewList::const_iterator i = _editor->get_track_views().begin(); i != _editor->get_track_views().end(); ++i) {
326                         RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
327                         if (rtv && !rtv->route()->is_master() && rtv->route()->soloed()) {
328                                 rtv->route()->set_route_group (g, this);
329                         }
330                 }
331                 
332         } else {
333                 delete g;
334         }
335 }
336
337 void
338 EditorRouteGroups::edit (RouteGroup* g)
339 {
340         RouteGroupDialog d (g, Gtk::Stock::APPLY);
341         d.do_run ();
342 }
343
344 void
345 EditorRouteGroups::remove_selected ()
346 {
347         Glib::RefPtr<TreeSelection> selection = _display.get_selection();
348         TreeView::Selection::ListHandle_Path rows = selection->get_selected_rows ();
349
350         if (rows.empty()) {
351                 return;
352         }
353
354         TreeView::Selection::ListHandle_Path::iterator i = rows.begin();
355         TreeIter iter;
356         
357         /* selection mode is single, so rows.begin() is it */
358
359         if ((iter = _model->get_iter (*i))) {
360
361                 RouteGroup* rg = (*iter)[_columns.routegroup];
362
363                 if (rg) {
364                         _session->remove_route_group (*rg);
365                 }
366         }
367 }
368
369 void
370 EditorRouteGroups::button_clicked ()
371 {
372         new_route_group ();
373 }
374
375 gint
376 EditorRouteGroups::button_press_event (GdkEventButton* ev)
377 {
378         TreeModel::Path path;
379         TreeIter iter;
380         RouteGroup* group = 0;
381         TreeViewColumn* column;
382         int cellx;
383         int celly;
384
385         bool const p = _display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly);
386
387         if (p) {
388                 iter = _model->get_iter (path);
389         }
390         
391         if (iter) {
392                 group = (*iter)[_columns.routegroup];
393         }
394
395         if (Keyboard::is_context_menu_event (ev)) {
396                 menu(group)->popup (1, ev->time);
397                 return true;
398         }
399
400         if (!p) {
401                 return 1;
402         }
403
404         switch (GPOINTER_TO_UINT (column->get_data (X_("colnum")))) {
405         case 0:
406                 if (Keyboard::is_edit_event (ev)) {
407                         if ((iter = _model->get_iter (path))) {
408                                 if ((group = (*iter)[_columns.routegroup]) != 0) {
409                                         // edit_route_group (group);
410 #ifdef GTKOSX
411                                         _display.queue_draw();
412 #endif
413                                         return true;
414                                 }
415                         }
416                         
417                 } 
418                 break;
419
420         case 1:
421                 if ((iter = _model->get_iter (path))) {
422                         bool gain = (*iter)[_columns.gain];
423                         (*iter)[_columns.gain] = !gain;
424 #ifdef GTKOSX
425                         _display.queue_draw();
426 #endif
427                         return true;
428                 }
429                 break;
430
431         case 2:
432                 if ((iter = _model->get_iter (path))) {
433                         bool record = (*iter)[_columns.record];
434                         (*iter)[_columns.record] = !record;
435 #ifdef GTKOSX
436                         _display.queue_draw();
437 #endif
438                         return true;
439                 }
440                 break;
441
442         case 3:
443                 if ((iter = _model->get_iter (path))) {
444                         bool mute = (*iter)[_columns.mute];
445                         (*iter)[_columns.mute] = !mute;
446 #ifdef GTKOSX
447                         _display.queue_draw();
448 #endif
449                         return true;
450                 }
451                 break;
452
453         case 4:
454                 if ((iter = _model->get_iter (path))) {
455                         bool solo = (*iter)[_columns.solo];
456                         (*iter)[_columns.solo] = !solo;
457 #ifdef GTKOSX
458                         _display.queue_draw();
459 #endif
460                         return true;
461                 }
462                 break;
463
464         case 5:
465                 if ((iter = _model->get_iter (path))) {
466                         bool select = (*iter)[_columns.select];
467                         (*iter)[_columns.select] = !select;
468 #ifdef GTKOSX
469                         _display.queue_draw();
470 #endif
471                         return true;
472                 }
473                 break;
474
475         case 6:
476                 if ((iter = _model->get_iter (path))) {
477                         bool edits = (*iter)[_columns.edits];
478                         (*iter)[_columns.edits] = !edits;
479 #ifdef GTKOSX
480                         _display.queue_draw();
481 #endif
482                         return true;
483                 }
484                 break;
485
486         case 7:
487                 if ((iter = _model->get_iter (path))) {
488                         bool visible = (*iter)[_columns.is_visible];
489                         (*iter)[_columns.is_visible] = !visible;
490 #ifdef GTKOSX
491                         _display.queue_draw();
492 #endif
493                         return true;
494                 }
495                 break;
496
497         default:
498                 break;
499         }
500         
501         return false;
502  }
503
504 void 
505 EditorRouteGroups::row_change (const Gtk::TreeModel::Path&, const Gtk::TreeModel::iterator& iter)
506 {
507         RouteGroup* group;
508
509         if (_in_row_change) {
510                 return;
511         }
512
513         if ((group = (*iter)[_columns.routegroup]) == 0) {
514                 return;
515         }
516
517         if ((*iter)[_columns.is_visible]) {
518                 for (Editor::TrackViewList::const_iterator j = _editor->get_track_views().begin(); j != _editor->get_track_views().end(); ++j) {
519                         if ((*j)->route_group() == group) {
520                                 _editor->_routes->show_track_in_display (**j);
521                         }
522                 }
523         } else {
524                 for (Editor::TrackViewList::const_iterator j = _editor->get_track_views().begin(); j != _editor->get_track_views().end(); ++j) {
525                         if ((*j)->route_group() == group) {
526                                 _editor->hide_track_in_display (**j);
527                         }
528                 }
529         }
530
531         group->set_property (RouteGroup::Gain, (*iter)[_columns.gain]);
532         group->set_property (RouteGroup::RecEnable, (*iter)[_columns.record]);
533         group->set_property (RouteGroup::Mute, (*iter)[_columns.mute]);
534         group->set_property (RouteGroup::Solo, (*iter)[_columns.solo]);
535         group->set_property (RouteGroup::Select, (*iter)[_columns.select]);
536         group->set_property (RouteGroup::Edit, (*iter)[_columns.edits]);
537
538         string name = (*iter)[_columns.text];
539
540         if (name != group->name()) {
541                 group->set_name (name);
542         }
543 }
544
545 void
546 EditorRouteGroups::add (RouteGroup* group)
547 {
548         ENSURE_GUI_THREAD (bind (mem_fun(*this, &EditorRouteGroups::add), group));
549         bool focus = false;
550
551         TreeModel::Row row = *(_model->append());
552         
553         row[_columns.is_visible] = !group->is_hidden();
554         row[_columns.gain] = group->property(RouteGroup::Gain);
555         row[_columns.record] = group->property(RouteGroup::RecEnable);
556         row[_columns.mute] = group->property(RouteGroup::Mute);
557         row[_columns.solo] = group->property(RouteGroup::Solo);
558         row[_columns.select] = group->property(RouteGroup::Select);
559         row[_columns.edits] = group->property(RouteGroup::Edit);
560
561         _in_row_change = true;
562
563         row[_columns.routegroup] = group;
564
565         if (!group->name().empty()) {
566                 row[_columns.text] = group->name();
567         } else {
568                 row[_columns.text] = _("unnamed");
569                 focus = true;
570         }
571
572         group->FlagsChanged.connect (bind (mem_fun (*this, &EditorRouteGroups::flags_changed), group));
573
574         if (focus) {  
575                 TreeViewColumn* col = _display.get_column (0);
576                 CellRendererText* name_cell = dynamic_cast<CellRendererText*>(_display.get_column_cell_renderer (0));
577                 _display.set_cursor (_model->get_path (row), *col, *name_cell, true);
578         }
579
580         _in_row_change = false;
581
582         _editor->_group_tabs->set_dirty ();
583 }
584
585 void
586 EditorRouteGroups::groups_changed ()
587 {
588         ENSURE_GUI_THREAD (mem_fun (*this, &EditorRouteGroups::groups_changed));
589
590         /* just rebuild the while thing */
591
592         _model->clear ();
593
594         {
595                 TreeModel::Row row;
596                 row = *(_model->append());
597                 row[_columns.is_visible] = true;
598                 row[_columns.text] = (_("-all-"));
599                 row[_columns.routegroup] = 0;
600         }
601
602         _session->foreach_route_group (mem_fun (*this, &EditorRouteGroups::add));
603 }
604
605 void
606 EditorRouteGroups::flags_changed (void* src, RouteGroup* group)
607 {
608         ENSURE_GUI_THREAD (bind (mem_fun(*this, &EditorRouteGroups::flags_changed), src, group));
609
610         _in_row_change = true;
611
612         Gtk::TreeModel::Children children = _model->children();
613
614         for(Gtk::TreeModel::Children::iterator iter = children.begin(); iter != children.end(); ++iter) {
615                 if (group == (*iter)[_columns.routegroup]) {
616                         (*iter)[_columns.is_visible] = !group->is_hidden();
617                         (*iter)[_columns.text] = group->name();
618                         (*iter)[_columns.gain] = group->property(RouteGroup::Gain);
619                         (*iter)[_columns.record] = group->property(RouteGroup::RecEnable);
620                         (*iter)[_columns.mute] = group->property(RouteGroup::Mute);
621                         (*iter)[_columns.solo] = group->property(RouteGroup::Solo);
622                         (*iter)[_columns.select] = group->property(RouteGroup::Select);
623                         (*iter)[_columns.edits] = group->property(RouteGroup::Edit);
624                 }
625         }
626
627         _in_row_change = false;
628
629         _editor->_group_tabs->set_dirty ();
630 }
631
632 void
633 EditorRouteGroups::name_edit (const Glib::ustring& path, const Glib::ustring& new_text)
634 {
635         RouteGroup* group;
636         TreeIter iter;
637         
638         if ((iter = _model->get_iter (path))) {
639         
640                 if ((group = (*iter)[_columns.routegroup]) == 0) {
641                         return;
642                 }
643                 
644                 if (new_text != group->name()) {
645                         group->set_name (new_text);
646                 }
647         }
648 }
649
650 void
651 EditorRouteGroups::clear ()
652 {
653         _display.set_model (Glib::RefPtr<Gtk::TreeStore> (0));
654         _model->clear ();
655         _display.set_model (_model);
656 }
657
658 void
659 EditorRouteGroups::connect_to_session (Session* s)
660 {
661         EditorComponent::connect_to_session (s);
662
663         _session_connections.push_back (_session->route_group_added.connect (mem_fun (*this, &EditorRouteGroups::add)));
664         _session_connections.push_back (_session->route_group_removed.connect (mem_fun (*this, &EditorRouteGroups::groups_changed)));
665
666         groups_changed ();
667 }
668
669 struct CollectSorter {
670         bool operator () (Route* a, Route* b) {
671                 return a->order_key (N_ ("editor")) < b->order_key (N_ ("editor"));
672         }
673 };
674
675 /** Collect all members of a RouteGroup so that they are together in the Editor.
676  *  @param g Group to collect.
677  */
678 void
679 EditorRouteGroups::collect (RouteGroup* g)
680 {
681         list<Route*> routes = g->route_list ();
682         routes.sort (CollectSorter ());
683         int const N = routes.size ();
684
685         list<Route*>::iterator i = routes.begin ();
686         Editor::TrackViewList::const_iterator j = _editor->get_track_views().begin();
687
688         int diff = 0;
689         int coll = -1;
690         while (i != routes.end() && j != _editor->get_track_views().end()) {
691
692                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
693                 if (rtv) {
694
695                         boost::shared_ptr<Route> r = rtv->route ();
696                         int const k = r->order_key (N_ ("editor"));
697                         
698                         if (*i == r.get()) {
699
700                                 if (coll == -1) {
701                                         coll = k;
702                                         diff = N - 1;
703                                 } else {
704                                         --diff;
705                                 }
706                                 
707                                 r->set_order_key (N_ ("editor"), coll);
708                                 
709                                 ++coll;
710                                 ++i;
711                                 
712                         } else {
713                                 
714                                 r->set_order_key (N_ ("editor"), k + diff);
715                                 
716                         }
717                 }
718                         
719                 ++j;
720         }
721
722         _editor->_routes->sync_order_keys ("");
723 }