remove almost-unusued stop_signal.h and clean up the one (unused) place where it...
[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/gtk_ui.h>
24 #include "ardour/route_group.h"
25
26 #include "editor.h"
27 #include "keyboard.h"
28 #include "marker.h"
29 #include "time_axis_view.h"
30 #include "prompter.h"
31 #include "gui_thread.h"
32 #include "editor_group_tabs.h"
33 #include "route_group_dialog.h"
34 #include "route_time_axis.h"
35 #include "editor_routes.h"
36 #include "editor_route_groups.h"
37
38 #include "ardour/route.h"
39 #include "ardour/session.h"
40
41 #include "i18n.h"
42
43 using namespace std;
44 using namespace ARDOUR;
45 using namespace PBD;
46 using namespace Gtk;
47 using Gtkmm2ext::Keyboard;
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 (sigc::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 (sigc::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 (sigc::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 (hide_return (sigc::mem_fun (*this, &EditorRouteGroups::new_route_group)));
157         remove_button->signal_clicked().connect (sigc::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..."), sigc::mem_fun (*this, &EditorRouteGroups::new_from_selection)));
177         f.push_back (MenuElem (_("Record Enabled..."), sigc::mem_fun (*this, &EditorRouteGroups::new_from_rec_enabled)));
178         f.push_back (MenuElem (_("Soloed..."), sigc::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..."), hide_return (sigc::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..."), sigc::bind (sigc::mem_fun (*this, &EditorRouteGroups::edit), g)));
188                 items.push_back (MenuElem (_("Fit to Window"), sigc::bind (sigc::mem_fun (*_editor, &Editor::fit_route_group), g)));
189                 items.push_back (MenuElem (_("Subgroup"), sigc::bind (sigc::mem_fun (*this, &EditorRouteGroups::subgroup), g)));
190                 items.push_back (MenuElem (_("Collect"), sigc::bind (sigc::mem_fun (*this, &EditorRouteGroups::collect), g)));
191         }
192         items.push_back (SeparatorElem());
193         items.push_back (MenuElem (_("Activate All"), sigc::mem_fun(*this, &EditorRouteGroups::activate_all)));
194         items.push_back (MenuElem (_("Disable All"), sigc::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                 sigc::bind (sigc::mem_fun (*this, &EditorRouteGroups::set_activation), true)
216                 );
217 }
218
219 void
220 EditorRouteGroups::disable_all ()
221 {
222         _session->foreach_route_group (
223                 sigc::bind (sigc::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 ARDOUR::RouteGroup *
234 EditorRouteGroups::new_route_group () const
235 {
236         PropertyList plist;
237
238         plist.add (Properties::active, true);
239         plist.add (Properties::mute, true);
240         plist.add (Properties::solo, true);
241         plist.add (Properties::edit, true);
242
243         RouteGroup* g = new RouteGroup (*_session, "");
244
245         g->set_properties (plist);
246
247         RouteGroupDialog d (g, Gtk::Stock::NEW);
248         int const r = d.do_run ();
249
250         if (r != Gtk::RESPONSE_OK) {
251                 delete g;
252                 return 0;
253         }
254         
255         _session->add_route_group (g);
256         return g;
257 }
258 void
259 EditorRouteGroups::run_new_group_dialog (const RouteList& rl)
260 {
261         PropertyList plist;
262
263         plist.add (Properties::active, true);
264         plist.add (Properties::mute, true);
265         plist.add (Properties::solo, true);
266         plist.add (Properties::recenable, true);
267         plist.add (Properties::edit, true);
268
269         RouteGroup* g = new RouteGroup (*_session, "");
270         g->set_properties (plist);
271
272         RouteGroupDialog d (g, Gtk::Stock::NEW);
273         int const r = d.do_run ();
274
275         switch (r) {
276         case Gtk::RESPONSE_OK:
277         case Gtk::RESPONSE_ACCEPT:
278                 _session->add_route_group (g);
279                 for (RouteList::const_iterator i = rl.begin(); i != rl.end(); ++i) {
280                         g->add (*i);
281                 }
282                 break;
283         default:
284                 delete g;
285         }
286 }
287
288 void
289 EditorRouteGroups::new_from_selection ()
290 {
291         if (_editor->get_selection().tracks.empty()) {
292                 return;
293         }
294
295         RouteList rl;
296
297         for (TrackSelection::iterator i = _editor->get_selection().tracks.begin(); i != _editor->get_selection().tracks.end(); ++i) {
298                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
299                 if (rtv) {
300                         rl.push_back (rtv->route());
301                 }
302         }
303
304         if (rl.empty()) {
305                 return;
306         }
307
308         run_new_group_dialog (rl);
309 }
310
311 void
312 EditorRouteGroups::new_from_rec_enabled ()
313 {
314         RouteList rl;
315
316         for (TrackViewList::const_iterator i = _editor->get_track_views().begin(); i != _editor->get_track_views().end(); ++i) {
317                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
318                 if (rtv && rtv->route()->record_enabled()) {
319                         rl.push_back (rtv->route());
320                 }
321         }
322
323         if (rl.empty()) {
324                 return;
325         }
326
327         run_new_group_dialog (rl);
328 }
329
330 void
331 EditorRouteGroups::new_from_soloed ()
332 {
333         RouteList rl;
334
335         for (TrackViewList::const_iterator i = _editor->get_track_views().begin(); i != _editor->get_track_views().end(); ++i) {
336                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
337                 if (rtv && !rtv->route()->is_master() && rtv->route()->soloed()) {
338                         rl.push_back (rtv->route());
339                 }
340         }
341
342         if (rl.empty()) {
343                 return;
344         }
345
346         run_new_group_dialog (rl);
347 }
348
349 void
350 EditorRouteGroups::edit (RouteGroup* g)
351 {
352         RouteGroupDialog d (g, Gtk::Stock::APPLY);
353         d.do_run ();
354 }
355
356 void
357 EditorRouteGroups::remove_selected ()
358 {
359         Glib::RefPtr<TreeSelection> selection = _display.get_selection();
360         TreeView::Selection::ListHandle_Path rows = selection->get_selected_rows ();
361
362         if (rows.empty()) {
363                 return;
364         }
365
366         TreeView::Selection::ListHandle_Path::iterator i = rows.begin();
367         TreeIter iter;
368
369         /* selection mode is single, so rows.begin() is it */
370
371         if ((iter = _model->get_iter (*i))) {
372
373                 RouteGroup* rg = (*iter)[_columns.routegroup];
374
375                 if (rg) {
376                         _session->remove_route_group (*rg);
377                 }
378         }
379 }
380
381 void
382 EditorRouteGroups::button_clicked ()
383 {
384         new_route_group ();
385 }
386
387 gint
388 EditorRouteGroups::button_press_event (GdkEventButton* ev)
389 {
390         TreeModel::Path path;
391         TreeIter iter;
392         RouteGroup* group = 0;
393         TreeViewColumn* column;
394         int cellx;
395         int celly;
396
397         bool const p = _display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly);
398
399         if (p) {
400                 iter = _model->get_iter (path);
401         }
402
403         if (iter) {
404                 group = (*iter)[_columns.routegroup];
405         }
406
407         if (Keyboard::is_context_menu_event (ev)) {
408                 menu(group)->popup (1, ev->time);
409                 return true;
410         }
411
412         if (!p) {
413                 return 1;
414         }
415
416         switch (GPOINTER_TO_UINT (column->get_data (X_("colnum")))) {
417         case 0:
418                 if (Keyboard::is_edit_event (ev)) {
419                         if ((iter = _model->get_iter (path))) {
420                                 if ((group = (*iter)[_columns.routegroup]) != 0) {
421                                         // edit_route_group (group);
422 #ifdef GTKOSX
423                                         _display.queue_draw();
424 #endif
425                                         return true;
426                                 }
427                         }
428
429                 }
430                 break;
431
432         case 1:
433                 if ((iter = _model->get_iter (path))) {
434                         bool gain = (*iter)[_columns.gain];
435                         (*iter)[_columns.gain] = !gain;
436 #ifdef GTKOSX
437                         _display.queue_draw();
438 #endif
439                         return true;
440                 }
441                 break;
442
443         case 2:
444                 if ((iter = _model->get_iter (path))) {
445                         bool record = (*iter)[_columns.record];
446                         (*iter)[_columns.record] = !record;
447 #ifdef GTKOSX
448                         _display.queue_draw();
449 #endif
450                         return true;
451                 }
452                 break;
453
454         case 3:
455                 if ((iter = _model->get_iter (path))) {
456                         bool mute = (*iter)[_columns.mute];
457                         (*iter)[_columns.mute] = !mute;
458 #ifdef GTKOSX
459                         _display.queue_draw();
460 #endif
461                         return true;
462                 }
463                 break;
464
465         case 4:
466                 if ((iter = _model->get_iter (path))) {
467                         bool solo = (*iter)[_columns.solo];
468                         (*iter)[_columns.solo] = !solo;
469 #ifdef GTKOSX
470                         _display.queue_draw();
471 #endif
472                         return true;
473                 }
474                 break;
475
476         case 5:
477                 if ((iter = _model->get_iter (path))) {
478                         bool select = (*iter)[_columns.select];
479                         (*iter)[_columns.select] = !select;
480 #ifdef GTKOSX
481                         _display.queue_draw();
482 #endif
483                         return true;
484                 }
485                 break;
486
487         case 6:
488                 if ((iter = _model->get_iter (path))) {
489                         bool edits = (*iter)[_columns.edits];
490                         (*iter)[_columns.edits] = !edits;
491 #ifdef GTKOSX
492                         _display.queue_draw();
493 #endif
494                         return true;
495                 }
496                 break;
497
498         case 7:
499                 if ((iter = _model->get_iter (path))) {
500                         bool visible = (*iter)[_columns.is_visible];
501                         (*iter)[_columns.is_visible] = !visible;
502 #ifdef GTKOSX
503                         _display.queue_draw();
504 #endif
505                         return true;
506                 }
507                 break;
508
509         default:
510                 break;
511         }
512
513         return false;
514  }
515
516 void
517 EditorRouteGroups::row_change (const Gtk::TreeModel::Path&, const Gtk::TreeModel::iterator& iter)
518 {
519         RouteGroup* group;
520
521         if (_in_row_change) {
522                 return;
523         }
524
525         if ((group = (*iter)[_columns.routegroup]) == 0) {
526                 return;
527         }
528
529         if ((*iter)[_columns.is_visible]) {
530                 for (TrackViewList::const_iterator j = _editor->get_track_views().begin(); j != _editor->get_track_views().end(); ++j) {
531                         if ((*j)->route_group() == group) {
532                                 _editor->_routes->show_track_in_display (**j);
533                         }
534                 }
535         } else {
536                 for (TrackViewList::const_iterator j = _editor->get_track_views().begin(); j != _editor->get_track_views().end(); ++j) {
537                         if ((*j)->route_group() == group) {
538                                 _editor->hide_track_in_display (*j);
539                         }
540                 }
541         }
542
543         PropertyList plist;
544         bool val = (*iter)[_columns.gain];
545         plist.add (Properties::gain, val);
546         val = (*iter)[_columns.record];
547         plist.add (Properties::recenable, val);
548         val = (*iter)[_columns.mute];
549         plist.add (Properties::mute, val);
550         val = (*iter)[_columns.solo];
551         plist.add (Properties::solo, val);
552         val = (*iter)[_columns.select];
553         plist.add (Properties::select, val);
554         val = (*iter)[_columns.edits];
555         plist.add (Properties::edit, val);
556         plist.add (Properties::name, string ((*iter)[_columns.text]));
557         
558         group->set_hidden (!(*iter)[_columns.is_visible], this);
559         
560         group->set_properties (plist);
561 }
562
563 void
564 EditorRouteGroups::add (RouteGroup* group)
565 {
566         ENSURE_GUI_THREAD (*this, &EditorRouteGroups::add, group)
567         bool focus = false;
568
569         TreeModel::Row row = *(_model->append());
570
571         row[_columns.is_visible] = !group->is_hidden();
572         row[_columns.gain] = group->is_gain ();
573         row[_columns.record] = group->is_recenable();
574         row[_columns.mute] = group->is_mute ();
575         row[_columns.solo] = group->is_solo ();
576         row[_columns.select] = group->is_select ();
577         row[_columns.edits] = group->is_edit ();
578
579         _in_row_change = true;
580
581         row[_columns.routegroup] = group;
582
583         if (!group->name().empty()) {
584                 row[_columns.text] = group->name();
585         } else {
586                 row[_columns.text] = _("unnamed");
587                 focus = true;
588         }
589
590         group->PropertyChanged.connect (property_changed_connection, MISSING_INVALIDATOR, ui_bind (&EditorRouteGroups::property_changed, this, group, _1), gui_context());
591
592         if (focus) {
593                 TreeViewColumn* col = _display.get_column (0);
594                 CellRendererText* name_cell = dynamic_cast<CellRendererText*>(_display.get_column_cell_renderer (0));
595                 _display.set_cursor (_model->get_path (row), *col, *name_cell, true);
596         }
597
598         _in_row_change = false;
599
600         _editor->_group_tabs->set_dirty ();
601 }
602
603 void
604 EditorRouteGroups::groups_changed ()
605 {
606         ENSURE_GUI_THREAD (*this, &EditorRouteGroups::groups_changed)
607
608         /* just rebuild the while thing */
609
610         _model->clear ();
611
612         {
613                 TreeModel::Row row;
614                 row = *(_model->append());
615                 row[_columns.is_visible] = true;
616                 row[_columns.text] = (_("-all-"));
617                 row[_columns.routegroup] = 0;
618         }
619
620         if (_session) {
621                 _session->foreach_route_group (sigc::mem_fun (*this, &EditorRouteGroups::add));
622         }
623 }
624
625 void
626 EditorRouteGroups::property_changed (RouteGroup* group, const PropertyChange& change)
627 {
628         _in_row_change = true;
629
630         Gtk::TreeModel::Children children = _model->children();
631
632         for(Gtk::TreeModel::Children::iterator iter = children.begin(); iter != children.end(); ++iter) {
633                 if (group == (*iter)[_columns.routegroup]) {
634                         (*iter)[_columns.is_visible] = !group->is_hidden();
635                         (*iter)[_columns.text] = group->name();
636                         (*iter)[_columns.gain] = group->is_gain ();
637                         (*iter)[_columns.record] = group->is_recenable ();
638                         (*iter)[_columns.mute] = group->is_mute ();
639                         (*iter)[_columns.solo] = group->is_solo ();
640                         (*iter)[_columns.select] = group->is_select ();
641                         (*iter)[_columns.edits] = group->is_edit ();
642                 }
643         }
644
645         _in_row_change = false;
646
647         if (change.contains (Properties::name) || change.contains (Properties::active)) {
648                 _editor->_group_tabs->set_dirty ();
649         }
650 }
651
652 void
653 EditorRouteGroups::name_edit (const Glib::ustring& path, const Glib::ustring& new_text)
654 {
655         RouteGroup* group;
656         TreeIter iter;
657
658         if ((iter = _model->get_iter (path))) {
659
660                 if ((group = (*iter)[_columns.routegroup]) == 0) {
661                         return;
662                 }
663
664                 if (new_text != group->name()) {
665                         group->set_name (new_text);
666                 }
667         }
668 }
669
670 void
671 EditorRouteGroups::clear ()
672 {
673         _display.set_model (Glib::RefPtr<Gtk::TreeStore> (0));
674         _model->clear ();
675         _display.set_model (_model);
676 }
677
678 void
679 EditorRouteGroups::set_session (Session* s)
680 {
681         EditorComponent::set_session (s);
682
683         if (_session) {
684                 _session->route_group_added.connect (_session_connections, MISSING_INVALIDATOR, ui_bind (&EditorRouteGroups::add, this, _1), gui_context());
685                 _session->route_group_removed.connect (_session_connections, MISSING_INVALIDATOR, boost::bind (&EditorRouteGroups::groups_changed, this), gui_context());
686         }
687
688         groups_changed ();
689 }
690
691 struct CollectSorter {
692     bool operator () (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
693                 return a->order_key (N_ ("editor")) < b->order_key (N_ ("editor"));
694         }
695 };
696
697 /** Collect all members of a RouteGroup so that they are together in the Editor.
698  *  @param g Group to collect.
699  */
700 void
701 EditorRouteGroups::collect (RouteGroup* g)
702 {
703         boost::shared_ptr<RouteList> routes = g->route_list ();
704         routes->sort (CollectSorter ());
705         int const N = routes->size ();
706
707         RouteList::iterator i = routes->begin ();
708         TrackViewList::const_iterator j = _editor->get_track_views().begin();
709
710         int diff = 0;
711         int coll = -1;
712         while (i != routes->end() && j != _editor->get_track_views().end()) {
713
714                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
715                 if (rtv) {
716
717                         boost::shared_ptr<Route> r = rtv->route ();
718                         int const k = r->order_key (N_ ("editor"));
719
720                         if (*i == r) {
721
722                                 if (coll == -1) {
723                                         coll = k;
724                                         diff = N - 1;
725                                 } else {
726                                         --diff;
727                                 }
728
729                                 r->set_order_key (N_ ("editor"), coll);
730
731                                 ++coll;
732                                 ++i;
733
734                         } else {
735
736                                 r->set_order_key (N_ ("editor"), k + diff);
737
738                         }
739                 }
740
741                 ++j;
742         }
743
744         _editor->_routes->sync_order_keys ("");
745 }