remove editor/mixer selection change signals; make editor and mixer use PresentationI...
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 27 Jan 2017 18:18:33 +0000 (19:18 +0100)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 27 Jan 2017 21:17:53 +0000 (22:17 +0100)
14 files changed:
gtk2_ardour/ardour_ui_dependents.cc
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_mixer.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/editor_routes.cc
gtk2_ardour/editor_routes.h
gtk2_ardour/mixer_ui.cc
gtk2_ardour/mixer_ui.h
gtk2_ardour/public_editor.h
gtk2_ardour/route_processor_selection.cc
gtk2_ardour/route_processor_selection.h
gtk2_ardour/selection.cc
gtk2_ardour/selection.h

index a1c264cf01a19a9f0e4ff54a446d0907183931d3..4ca4648499cf9a2b8ed7073b3708fbf99482ba3b 100644 (file)
@@ -101,9 +101,6 @@ ARDOUR_UI::we_have_dependents ()
 
        ActionManager::load_menus (ARDOUR_COMMAND_LINE::menus_file);
 
-       editor->track_mixer_selection ();
-       mixer->track_editor_selection ();
-
        /* catch up on parameters */
 
        boost::function<void (std::string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
index e64e079808988464ab55ec7f4901ef768ee0bbed..c9dab0a0e5e4749bfe2a85fdfa6817c78e1ce7dd 100644 (file)
@@ -578,7 +578,6 @@ Editor::Editor ()
        _summary = new EditorSummary (this);
 
        selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
-       selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
 
        editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
 
index c2a25668733b55f0275466e669a413dbd491b7e7..2cf7f569fbb68dc68b6794563b6975c1054639fb 100644 (file)
@@ -256,7 +256,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
        Selection& get_selection() const { return *selection; }
        bool get_selection_extents (framepos_t &start, framepos_t &end) const;  // the time extents of the current selection, whether Range, Region(s), Control Points, or Notes
        Selection& get_cut_buffer() const { return *cut_buffer; }
-       void track_mixer_selection ();
 
        bool extend_selection_to_track (TimeAxisView&);
 
index 0c0348383f2a577a3423dc9144acbbc63eec6476..51691136aea6d2848aaa9a216408fb15c3bd46ad 100644 (file)
@@ -285,34 +285,3 @@ Editor::mixer_strip_width_changed ()
        editor_mixer_strip_width = current_mixer_strip->get_width_enum ();
 }
 
-void
-Editor::track_mixer_selection ()
-{
-       Mixer_UI::instance()->selection().RoutesChanged.connect (sigc::mem_fun (*this, &Editor::follow_mixer_selection));
-}
-
-void
-Editor::follow_mixer_selection ()
-{
-       if (_following_mixer_selection) {
-               return;
-       }
-
-       _following_mixer_selection = true;
-       selection->block_tracks_changed (true);
-
-       AxisViewSelection& s (Mixer_UI::instance()->selection().axes);
-
-       selection->clear_tracks ();
-
-       for (AxisViewSelection::iterator i = s.begin(); i != s.end(); ++i) {
-               TimeAxisView* tav = axis_view_from_stripable ((*i)->stripable());
-               if (tav) {
-                       selection->add (tav);
-               }
-       }
-
-       _following_mixer_selection = false;
-       selection->block_tracks_changed (false);
-       selection->TracksChanged (); /* EMIT SIGNAL */
-}
index ed83da2d80d9855bea3c505ef7f64f3afa35eeea..4df88b90252a7200014cffa138a0f85d4729bf53 100644 (file)
@@ -7379,10 +7379,10 @@ edit your ardour.rc file to set the\n\
                }
        }
 
-       Mixer_UI::instance()->selection().block_routes_changed (true);
-       selection->block_tracks_changed (true);
        {
+               PresentationInfo::ChangeSuspender cs;
                DisplaySuspender ds;
+
                boost::shared_ptr<RouteList> rl (new RouteList);
                for (vector<boost::shared_ptr<Route> >::iterator x = routes.begin(); x != routes.end(); ++x) {
                        rl->push_back (*x);
@@ -7393,9 +7393,6 @@ edit your ardour.rc file to set the\n\
         * destructors are called,
         * diskstream drops references, save_state is called (again for every track)
         */
-       selection->block_tracks_changed (false);
-       Mixer_UI::instance()->selection().block_routes_changed (false);
-       selection->TracksChanged (); /* EMIT SIGNAL */
 }
 
 void
index 27189f29af0346c633390671c6e5885abb5e3abc..016d5432f3bada055a7b92799d3c92ee7c8ed9c8 100644 (file)
@@ -77,6 +77,7 @@ struct ColumnInfo {
 EditorRoutes::EditorRoutes (Editor* e)
        : EditorComponent (e)
        , _ignore_reorder (false)
+       , _ignore_selection_change (false)
        , _no_redisplay (false)
        , _adding_routes (false)
        , _route_deletion_in_progress (false)
@@ -252,7 +253,7 @@ EditorRoutes::EditorRoutes (Editor* e)
        }
 
        _display.set_headers_visible (true);
-       _display.get_selection()->set_mode (SELECTION_SINGLE);
+       _display.get_selection()->set_mode (SELECTION_MULTIPLE);
        _display.get_selection()->set_select_function (sigc::mem_fun (*this, &EditorRoutes::selection_filter));
        _display.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::selection_changed));
        _display.set_reorderable (true);
@@ -318,7 +319,7 @@ EditorRoutes::EditorRoutes (Editor* e)
        _display.set_enable_search (false);
 
        Route::PluginSetup.connect_same_thread (*this, boost::bind (&EditorRoutes::plugin_setup, this, _1, _2, _3));
-       PresentationInfo::Change.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::sync_treeview_from_presentation_info, this), gui_context());
+       PresentationInfo::Change.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::presentation_info_changed, this, _1), gui_context());
 }
 
 bool
@@ -925,7 +926,6 @@ EditorRoutes::route_property_changed (const PropertyChange& what_changed, boost:
 
                        if (what_changed.contains (ARDOUR::Properties::hidden)) {
                                (*i)[_columns.visible] = !stripable->presentation_info().hidden();
-                               cerr << stripable->name() << " visibility changed, redisplay\n";
                                redisplay ();
 
                        }
@@ -1093,7 +1093,20 @@ EditorRoutes::sync_presentation_info_from_treeview ()
 }
 
 void
-EditorRoutes::sync_treeview_from_presentation_info ()
+EditorRoutes::presentation_info_changed (PropertyChange const & what_changed)
+{
+       PropertyChange soh;
+       soh.add (Properties::selected);
+       soh.add (Properties::order);
+       soh.add (Properties::hidden);
+
+       if (what_changed.contains (soh)) {
+               sync_treeview_from_presentation_info (what_changed);
+       }
+}
+
+void
+EditorRoutes::sync_treeview_from_presentation_info (PropertyChange const & what_changed)
 {
        /* Some route order key(s) have been changed, make sure that
           we update out tree/list model and GUI to reflect the change.
@@ -1105,53 +1118,85 @@ EditorRoutes::sync_treeview_from_presentation_info ()
 
        DEBUG_TRACE (DEBUG::OrderKeys, "editor sync model from presentation info.\n");
 
-       vector<int> neworder;
+       PropertyChange hidden_or_order;
+       hidden_or_order.add (Properties::hidden);
+       hidden_or_order.add (Properties::order);
+
        TreeModel::Children rows = _model->children();
-       uint32_t old_order = 0;
-       bool changed = false;
 
-       if (rows.empty()) {
-               return;
-       }
+       if (what_changed.contains (hidden_or_order)) {
 
-       OrderingKeys sorted;
-       const size_t cmp_max = rows.size ();
+               vector<int> neworder;
+               uint32_t old_order = 0;
+               bool changed = false;
 
-       for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++old_order) {
-               boost::shared_ptr<Stripable> stripable = (*ri)[_columns.stripable];
-               /* use global order */
-               sorted.push_back (OrderKeys (old_order, stripable, cmp_max));
-       }
+               if (rows.empty()) {
+                       return;
+               }
+
+               OrderingKeys sorted;
+               const size_t cmp_max = rows.size ();
+
+               for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++old_order) {
+                       boost::shared_ptr<Stripable> stripable = (*ri)[_columns.stripable];
+                       /* use global order */
+                       sorted.push_back (OrderKeys (old_order, stripable, cmp_max));
+               }
+
+               SortByNewDisplayOrder cmp;
 
-       SortByNewDisplayOrder cmp;
+               sort (sorted.begin(), sorted.end(), cmp);
+               neworder.assign (sorted.size(), 0);
 
-       sort (sorted.begin(), sorted.end(), cmp);
-       neworder.assign (sorted.size(), 0);
+               uint32_t n = 0;
 
-       uint32_t n = 0;
+               for (OrderingKeys::iterator sr = sorted.begin(); sr != sorted.end(); ++sr, ++n) {
 
-       for (OrderingKeys::iterator sr = sorted.begin(); sr != sorted.end(); ++sr, ++n) {
+                       neworder[n] = sr->old_display_order;
 
-               neworder[n] = sr->old_display_order;
+                       if (sr->old_display_order != n) {
+                               changed = true;
+                       }
+               }
 
-               if (sr->old_display_order != n) {
-                       changed = true;
+               if (changed) {
+                       Unwinder<bool> uw (_ignore_reorder, true);
+                       /* prevent traverse_cells: assertion 'row_path != NULL'
+                        * in case of DnD re-order: row-removed + row-inserted.
+                        *
+                        * The rows (stripables) are not actually removed from the model,
+                        * but only from the display in the DnDTreeView.
+                        * ->reorder() will fail to find the row_path.
+                        * (re-order drag -> remove row -> rync PI from TV -> notify -> sync TV from PI -> crash)
+                        */
+                       _display.unset_model();
+                       _model->reorder (neworder);
+                       _display.set_model (_model);
                }
        }
 
-       if (changed) {
-               Unwinder<bool> uw (_ignore_reorder, true);
-               /* prevent traverse_cells: assertion 'row_path != NULL'
-                * in case of DnD re-order: row-removed + row-inserted.
-                *
-                * The rows (stripables) are not actually removed from the model,
-                * but only from the display in the DnDTreeView.
-                * ->reorder() will fail to find the row_path.
-                * (re-order drag -> remove row -> rync PI from TV -> notify -> sync TV from PI -> crash)
-                */
-               _display.unset_model();
-               _model->reorder (neworder);
-               _display.set_model (_model);
+       if (what_changed.contains (Properties::selected)) {
+
+               TrackViewList tvl;
+               PBD::Unwinder<bool> uw (_ignore_selection_change, true);
+
+               /* step one: set the treeview model selection state */
+               for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri) {
+                       boost::shared_ptr<Stripable> stripable = (*ri)[_columns.stripable];
+                       if (stripable && stripable->presentation_info().selected()) {
+                               TimeAxisView* tav = (*ri)[_columns.tv];
+                               if (tav) {
+                                       tvl.push_back (tav);
+                               }
+                               _display.get_selection()->select (*ri);
+                       } else {
+                               _display.get_selection()->unselect (*ri);
+                       }
+               }
+
+               /* step two: set the Selection (for stripables/routes) */
+
+               _editor->get_selection().set (tvl);
        }
 
        redisplay ();
@@ -1457,6 +1502,10 @@ EditorRoutes::button_press (GdkEventButton* ev)
 void
 EditorRoutes::selection_changed ()
 {
+       if (_ignore_selection_change) {
+               return;
+       }
+
        _editor->begin_reversible_selection_op (X_("Select Track from Route List"));
 
        if (_display.get_selection()->count_selected_rows() > 0) {
@@ -1465,8 +1514,6 @@ EditorRoutes::selection_changed ()
                TreeView::Selection::ListHandle_Path rows = _display.get_selection()->get_selected_rows ();
                TrackViewList selected;
 
-               _editor->get_selection().clear_regions ();
-
                for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) {
 
                        if ((iter = _model->get_iter (*i))) {
@@ -1545,7 +1592,8 @@ EditorRoutes::initial_display ()
        }
 
        _editor->add_stripables (s);
-       sync_treeview_from_presentation_info ();
+
+       sync_treeview_from_presentation_info (Properties::order);
 }
 
 void
index 29e8b45dba685defd3cd2bc171e0deee4d3c0ff8..e1bf61e82eb660f336ada67245d7c41ce7be7a7b 100644 (file)
@@ -78,7 +78,8 @@ private:
        void on_tv_solo_safe_toggled (std::string const &);
        void build_menu ();
        void show_menu ();
-       void sync_treeview_from_presentation_info ();
+       void presentation_info_changed (PBD::PropertyChange const &);
+       void sync_treeview_from_presentation_info (PBD::PropertyChange const &);
        void row_deleted (Gtk::TreeModel::Path const &);
        void visible_changed (std::string const &);
        void active_changed (std::string const &);
@@ -165,6 +166,7 @@ private:
        int _active_column;
 
        bool _ignore_reorder;
+       bool _ignore_selection_change;
        bool _no_redisplay;
        bool _adding_routes;
        bool _route_deletion_in_progress;
index 4ffa753e0c43d55c5191415fb00f99732a83b8b8..5192a90abc99ba98a1721063fdd6f2a90bbbf126 100644 (file)
@@ -107,7 +107,6 @@ Mixer_UI::Mixer_UI ()
        , ignore_reorder (false)
         , _in_group_rebuild_or_clear (false)
         , _route_deletion_in_progress (false)
-       , _following_editor_selection (false)
        , _maximised (false)
        , _show_mixer_list (true)
        , myactions (X_("mixer"))
@@ -116,7 +115,7 @@ Mixer_UI::Mixer_UI ()
        load_bindings ();
        _content.set_data ("ardour-bindings", bindings);
 
-       PresentationInfo::Change.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::sync_treeview_from_presentation_info, this), gui_context());
+       PresentationInfo::Change.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::presentation_info_changed, this, _1), gui_context());
 
        scroller.set_can_default (true);
        // set_default (scroller);
@@ -384,12 +383,6 @@ Mixer_UI::escape ()
        select_none ();
 }
 
-void
-Mixer_UI::track_editor_selection ()
-{
-       PublicEditor::instance().get_selection().TracksChanged.connect (sigc::mem_fun (*this, &Mixer_UI::follow_editor_selection));
-}
-
 Gtk::Window*
 Mixer_UI::use_own_window (bool and_fill_it)
 {
@@ -687,6 +680,19 @@ Mixer_UI::remove_strip (MixerStrip* strip)
        }
 }
 
+void
+Mixer_UI::presentation_info_changed (PropertyChange const & what_changed)
+{
+       PropertyChange soh;
+       soh.add (Properties::selected);
+       soh.add (Properties::order);
+       soh.add (Properties::hidden);
+
+       if (what_changed.contains (soh)) {
+               sync_treeview_from_presentation_info (what_changed);
+       }
+}
+
 void
 Mixer_UI::sync_presentation_info_from_treeview ()
 {
@@ -780,7 +786,7 @@ Mixer_UI::sync_presentation_info_from_treeview ()
 }
 
 void
-Mixer_UI::sync_treeview_from_presentation_info ()
+Mixer_UI::sync_treeview_from_presentation_info (PropertyChange const & what_changed)
 {
        if (!_session || _session->deletion_in_progress()) {
                return;
@@ -831,35 +837,21 @@ Mixer_UI::sync_treeview_from_presentation_info ()
                track_model->reorder (neworder);
        }
 
-       redisplay_track_list ();
-}
-
-void
-Mixer_UI::follow_editor_selection ()
-{
-       if (_following_editor_selection) {
-               return;
-       }
-
-       _following_editor_selection = true;
-       _selection.block_routes_changed (true);
-
-       TrackSelection& s (PublicEditor::instance().get_selection().tracks);
+       if (what_changed.contains (Properties::selected)) {
 
-       _selection.clear_routes ();
+               PresentationInfo::ChangeSuspender cs;
 
-       for (TrackViewList::iterator i = s.begin(); i != s.end(); ++i) {
-               TimeAxisView* tav = dynamic_cast<TimeAxisView*> (*i);
-               if (tav) {
-                       AxisView* axis = axis_by_stripable (tav->stripable());
-                       if (axis) {
-                               _selection.add (axis);
+               for (list<MixerStrip *>::const_iterator i = strips.begin(); i != strips.end(); ++i) {
+                       boost::shared_ptr<Stripable> stripable = (*i)->stripable();
+                       if (stripable && stripable->presentation_info().selected()) {
+                               _selection.add (*i);
+                       } else {
+                               _selection.remove (*i);
                        }
                }
        }
 
-       _following_editor_selection = false;
-       _selection.block_routes_changed (false);
+       redisplay_track_list ();
 }
 
 
@@ -1537,8 +1529,7 @@ Mixer_UI::initial_track_display ()
                add_stripables (sl);
        }
 
-       redisplay_track_list ();
-       sync_treeview_from_presentation_info ();
+       sync_treeview_from_presentation_info (Properties::order);
 }
 
 void
index 8e5bbddfd0eb67e09a1db1657b9fcab02799cbbb..a96ce697345cccd20eb06f389ebdd955620bc4ba 100644 (file)
@@ -86,7 +86,6 @@ class Mixer_UI : public Gtkmm2ext::Tabbable, public PBD::ScopedConnectionList, p
        void show_window ();
 
        void set_session (ARDOUR::Session *);
-       void track_editor_selection ();
 
        PluginSelector* plugin_selector();
 
@@ -337,8 +336,9 @@ class Mixer_UI : public Gtkmm2ext::Tabbable, public PBD::ScopedConnectionList, p
 
        Width _strip_width;
 
+       void presentation_info_changed (PBD::PropertyChange const &);
+       void sync_treeview_from_presentation_info (PBD::PropertyChange const &);
        void sync_presentation_info_from_treeview ();
-       void sync_treeview_from_presentation_info ();
 
        bool ignore_reorder;
 
@@ -362,9 +362,6 @@ class Mixer_UI : public Gtkmm2ext::Tabbable, public PBD::ScopedConnectionList, p
 
        friend class MixerGroupTabs;
 
-       void follow_editor_selection ();
-       bool _following_editor_selection;
-
        void monitor_section_going_away ();
 
        void monitor_section_attached ();
index cdae2480ec2518a9f7db3a2beab2f3e8079b0c09..64c35e2ecdef54d8c12367f433f2ece6c177b77e 100644 (file)
@@ -207,7 +207,6 @@ class PublicEditor : public Gtkmm2ext::Tabbable {
        virtual Selection& get_selection () const = 0;
        virtual bool get_selection_extents (framepos_t &start, framepos_t &end) const = 0;
        virtual Selection& get_cut_buffer () const = 0;
-       virtual void track_mixer_selection () = 0;
        virtual bool extend_selection_to_track (TimeAxisView&) = 0;
        virtual void play_selection () = 0;
        virtual void play_with_preroll () = 0;
index 7428267b50b4d77d8d7398f10ca90d390a9ca77c..6b7592efd4357a545bc9f9a7f362f92af135777d 100644 (file)
@@ -32,7 +32,7 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
-unsigned int RouteProcessorSelection::_no_route_change_signal = 0;
+
 RouteProcessorSelection::RouteProcessorSelection()
 {
 }
@@ -71,14 +71,13 @@ RouteProcessorSelection::clear_processors ()
 void
 RouteProcessorSelection::clear_routes ()
 {
+       PresentationInfo::ChangeSuspender cs;
+
        for (AxisViewSelection::iterator i = axes.begin(); i != axes.end(); ++i) {
                (*i)->set_selected (false);
        }
        axes.clear ();
        drop_connections ();
-       if (0 == _no_route_change_signal) {
-               RoutesChanged ();
-       }
 }
 
 void
@@ -109,10 +108,6 @@ RouteProcessorSelection::add (AxisView* r)
                if (ms) {
                        ms->CatchDeletion.connect (*this, invalidator (*this), boost::bind (&RouteProcessorSelection::remove, this, _1), gui_context());
                }
-
-               if (0 == _no_route_change_signal) {
-                       RoutesChanged();
-               }
        }
 }
 
@@ -125,9 +120,6 @@ RouteProcessorSelection::remove (AxisView* r)
        if ((i = find (axes.begin(), axes.end(), r)) != axes.end()) {
                (*i)->set_selected (false);
                axes.erase (i);
-               if (0 == _no_route_change_signal) {
-                       RoutesChanged ();
-               }
        }
 }
 
@@ -149,14 +141,3 @@ RouteProcessorSelection::empty ()
 {
        return processors.empty () && axes.empty ();
 }
-
-void
-RouteProcessorSelection::block_routes_changed (bool yn)
-{
-       if (yn) {
-               ++_no_route_change_signal;
-       } else {
-               assert (_no_route_change_signal > 0);
-               --_no_route_change_signal;
-       }
-}
index a4d6f0f1a49ba8cc184927316746a3c73f520ebd..c708723e4dff87ef8640d5a123da4af02d266b55 100644 (file)
@@ -37,9 +37,6 @@ class RouteProcessorSelection : public PBD::ScopedConnectionList, public sigc::t
        RouteProcessorSelection& operator= (const RouteProcessorSelection& other);
 
        sigc::signal<void> ProcessorsChanged;
-       sigc::signal<void> RoutesChanged;
-
-       void block_routes_changed (bool);
 
        void clear ();
        bool empty();
@@ -58,8 +55,6 @@ class RouteProcessorSelection : public PBD::ScopedConnectionList, public sigc::t
 
   private:
        void removed (AxisView*);
-       static unsigned int _no_route_change_signal;
-
 };
 
 bool operator==(const RouteProcessorSelection& a, const RouteProcessorSelection& b);
index 98b5d62c1043f2a4faa289ba8a6e40438e6eb99b..36a4a087a936b037808f16c366dfe4ff0ce047db 100644 (file)
@@ -57,7 +57,6 @@ Selection::Selection (const PublicEditor* e)
        : tracks (e)
        , editor (e)
        , next_time_id (0)
-       , _no_tracks_changed (false)
 {
        clear ();
 
@@ -132,13 +131,13 @@ void
 Selection::clear_tracks (bool with_signal)
 {
        if (!tracks.empty()) {
+               PresentationInfo::ChangeSuspender cs;
+
                for (TrackViewList::iterator x = tracks.begin(); x != tracks.end(); ++x) {
                        (*x)->set_selected (false);
                }
+
                tracks.clear ();
-               if (!_no_tracks_changed && with_signal) {
-                       TracksChanged();
-               }
        }
 }
 
@@ -290,9 +289,6 @@ Selection::toggle (TimeAxisView* track)
                tracks.erase (i);
        }
 
-       if (!_no_tracks_changed) {
-               TracksChanged();
-       }
 }
 
 void
@@ -429,19 +425,18 @@ Selection::add (const list<boost::shared_ptr<Playlist> >& pllist)
 }
 
 void
-Selection::add (const TrackViewList& track_list)
+Selection::add (TrackViewList const & track_list)
 {
        clear_objects();  //enforce object/range exclusivity
 
+       PresentationInfo::ChangeSuspender cs;
+
        TrackViewList added = tracks.add (track_list);
 
        if (!added.empty()) {
                for (TrackViewList::iterator x = added.begin(); x != added.end(); ++x) {
                        (*x)->set_selected (true);
                }
-               if (!_no_tracks_changed) {
-                       TracksChanged ();
-               }
        }
 }
 
@@ -639,31 +634,18 @@ Selection::remove (TimeAxisView* track)
        if ((i = find (tracks.begin(), tracks.end(), track)) != tracks.end()) {
                track->set_selected (false);
                tracks.erase (i);
-
-               if (!_no_tracks_changed) {
-                       TracksChanged();
-               }
        }
 }
 
 void
 Selection::remove (const TrackViewList& track_list)
 {
-       bool changed = false;
-
        for (TrackViewList::const_iterator i = track_list.begin(); i != track_list.end(); ++i) {
 
                TrackViewList::iterator x = find (tracks.begin(), tracks.end(), *i);
                if (x != tracks.end()) {
                        (*i)->set_selected (false);
                        tracks.erase (x);
-                       changed = true;
-               }
-       }
-
-       if (changed) {
-               if (!_no_tracks_changed) {
-                       TracksChanged();
                }
        }
 }
@@ -797,7 +779,23 @@ void
 Selection::set (TimeAxisView* track)
 {
        clear_objects ();  //enforce object/range exclusivity
-       clear_tracks (false);
+
+       PresentationInfo::ChangeSuspender cs;
+
+       if (!tracks.empty()) {
+
+               if (tracks.size() == 1 && tracks.front() == track) {
+                       /* already single selection: nothing to do */
+                       return;
+               }
+
+               for (TrackViewList::iterator x = tracks.begin(); x != tracks.end(); ++x) {
+                       (*x)->set_selected (false);
+               }
+
+               tracks.clear ();
+       }
+
        add (track);
 }
 
@@ -805,7 +803,40 @@ void
 Selection::set (const TrackViewList& track_list)
 {
        clear_objects();  //enforce object/range exclusivity
-       clear_tracks (false);
+
+       PresentationInfo::ChangeSuspender cs;
+
+       if (!tracks.empty()) {
+
+               /* cannot use set<T>::operator== (set<T> const &) here, because
+                * apparently the ordering used within 2 sets is not
+                * necessarily the same.
+                */
+
+               if (tracks.size() == track_list.size()) {
+                       bool missing = false;
+
+                       for (TrackViewList::const_iterator x = track_list.begin(); x != track_list.end(); ++x) {
+                               if (find (tracks.begin(), tracks.end(), *x) == tracks.end()) {
+                                       missing = true;
+                               }
+                       }
+
+                       if (!missing) {
+                               /* already same selection: nothing to do */
+                               return;
+                       }
+               }
+
+               /* argument is different from existing selection */
+
+               for (TrackViewList::iterator x = tracks.begin(); x != tracks.end(); ++x) {
+                       (*x)->set_selected (false);
+               }
+
+               tracks.clear ();
+       }
+
        add (track_list);
 }
 
@@ -1551,9 +1582,3 @@ Selection::remove_regions (TimeAxisView* t)
                i = tmp;
        }
 }
-
-void
-Selection::block_tracks_changed (bool yn)
-{
-       _no_tracks_changed = yn;
-}
index 8599da70d8287d478f0dbc1f289ba53006a18513..daa81ab1d694d56c6fc822f1cf41c29d7435d14a 100644 (file)
@@ -95,7 +95,6 @@ class Selection : public sigc::trackable, public PBD::ScopedConnectionList
        // Selection& operator= (const Selection& other);
 
        sigc::signal<void> RegionsChanged;
-       sigc::signal<void> TracksChanged;
        sigc::signal<void> TimeChanged;
        sigc::signal<void> LinesChanged;
        sigc::signal<void> PlaylistsChanged;
@@ -104,8 +103,6 @@ class Selection : public sigc::trackable, public PBD::ScopedConnectionList
        sigc::signal<void> MidiNotesChanged;
        sigc::signal<void> MidiRegionsChanged;
 
-       void block_tracks_changed (bool);
-
        void clear ();
 
        /** check if all selections are empty
@@ -231,7 +228,6 @@ class Selection : public sigc::trackable, public PBD::ScopedConnectionList
   private:
        PublicEditor const * editor;
        uint32_t next_time_id;
-       bool _no_tracks_changed;
 };
 
 bool operator==(const Selection& a, const Selection& b);