Fix wxWidgets assertion on opening the video filters selector.
[dcpomatic.git] / src / wx / screens_panel.cc
index fa9373e36bb7252c06b8e8b2ad3cca21750005b9..562ea8f3895d0d67423ee135ae8b76bf4ef35900 100644 (file)
@@ -45,6 +45,9 @@ using std::shared_ptr;
 using std::string;
 using std::vector;
 using boost::optional;
+#if BOOST_VERSION >= 106100
+using namespace boost::placeholders;
+#endif
 using namespace dcpomatic;
 
 
@@ -113,7 +116,7 @@ ScreensPanel::ScreensPanel (wxWindow* parent)
        _remove_screen->Bind (wxEVT_BUTTON, boost::bind (&ScreensPanel::remove_screen_clicked, this));
 
        _check_all->Bind     (wxEVT_BUTTON, boost::bind(&ScreensPanel::check_all, this));
-       _uncheck_all->Bind     (wxEVT_BUTTON, boost::bind(&ScreensPanel::uncheck_all, this));
+       _uncheck_all->Bind   (wxEVT_BUTTON, boost::bind(&ScreensPanel::uncheck_all, this));
 
        SetSizer (sizer);
 
@@ -124,6 +127,8 @@ ScreensPanel::ScreensPanel (wxWindow* parent)
                ucol_setAttribute(_collator, UCOL_STRENGTH, UCOL_PRIMARY, &status);
                ucol_setAttribute(_collator, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status);
        }
+
+       _config_connection = Config::instance()->Changed.connect(boost::bind(&ScreensPanel::config_changed, this, _1));
 }
 
 
@@ -237,25 +242,34 @@ ScreensPanel::add_cinema_clicked ()
                        [this](shared_ptr<Cinema> a, shared_ptr<Cinema> b) { return compare(a->name, b->name) < 0; }
                        );
 
-               optional<wxTreeListItem> item;
+               try {
+                       _ignore_cinemas_changed = true;
+                       ScopeGuard sg = [this]() { _ignore_cinemas_changed = false; };
+                       Config::instance()->add_cinema(cinema);
+               } catch (FileError& e) {
+                       error_dialog(GetParent(), _("Could not write cinema details to the cinemas.xml file.  Check that the location of cinemas.xml is valid in DCP-o-matic's preferences."), std_to_wx(e.what()));
+                       return;
+               }
+
+               wxTreeListItem previous = wxTLI_FIRST;
+               bool found = false;
                for (auto existing_cinema: cinemas) {
-                       if (!item && compare(dialog->name(), existing_cinema->name) < 0) {
-                               if (auto existing_item = cinema_to_item(existing_cinema)) {
-                                       item = add_cinema (cinema, *existing_item);
-                               }
+                       if (compare(dialog->name(), existing_cinema->name) < 0) {
+                               /* existing_cinema should be after the one we're inserting */
+                               found = true;
+                               break;
                        }
+                       auto item = cinema_to_item(existing_cinema);
+                       DCPOMATIC_ASSERT(item);
+                       previous = *item;
                }
 
-               if (!item) {
-                       item = add_cinema (cinema, wxTLI_LAST);
-               }
+               auto item = add_cinema(cinema, found ? previous : wxTLI_LAST);
 
                if (item) {
                        _targets->UnselectAll ();
                        _targets->Select (*item);
                }
-
-               Config::instance()->add_cinema (cinema);
        }
 
        selection_changed ();
@@ -294,10 +308,10 @@ ScreensPanel::edit_cinema_clicked ()
                cinema->notes = dialog->notes();
                cinema->set_utc_offset_hour(dialog->utc_offset_hour());
                cinema->set_utc_offset_minute(dialog->utc_offset_minute());
+               notify_cinemas_changed();
                auto item = cinema_to_item(cinema);
                DCPOMATIC_ASSERT(item);
                _targets->SetItemText (*item, std_to_wx(dialog->name()));
-               Config::instance()->changed (Config::CINEMAS);
        }
 }
 
@@ -316,6 +330,8 @@ ScreensPanel::remove_cinema_clicked ()
        }
 
        for (auto const& cinema: _selected_cinemas) {
+               _ignore_cinemas_changed = true;
+               ScopeGuard sg = [this]() { _ignore_cinemas_changed = false; };
                Config::instance()->remove_cinema(cinema);
                auto item = cinema_to_item(cinema);
                DCPOMATIC_ASSERT(item);
@@ -356,12 +372,12 @@ ScreensPanel::add_screen_clicked ()
 
        auto screen = std::make_shared<Screen>(dialog->name(), dialog->notes(), dialog->recipient(), dialog->recipient_file(), dialog->trusted_devices());
        cinema->add_screen (screen);
+       notify_cinemas_changed();
+
        auto id = add_screen (cinema, screen);
        if (id) {
                _targets->Expand (id.get ());
        }
-
-       Config::instance()->changed (Config::CINEMAS);
 }
 
 
@@ -407,10 +423,11 @@ ScreensPanel::edit_screen_clicked ()
        edit_screen->recipient = dialog->recipient();
        edit_screen->recipient_file = dialog->recipient_file();
        edit_screen->trusted_devices = dialog->trusted_devices();
+       notify_cinemas_changed();
+
        auto item = screen_to_item(edit_screen);
        DCPOMATIC_ASSERT (item);
        _targets->SetItemText (*item, std_to_wx(dialog->name()));
-       Config::instance()->changed (Config::CINEMAS);
 }
 
 
@@ -434,7 +451,7 @@ ScreensPanel::remove_screen_clicked ()
                _targets->DeleteItem(*item);
        }
 
-       Config::instance()->changed (Config::CINEMAS);
+       notify_cinemas_changed();
 }
 
 
@@ -495,7 +512,7 @@ ScreensPanel::add_cinemas ()
 
 
 void
-ScreensPanel::search_changed ()
+ScreensPanel::clear_and_re_add()
 {
        _targets->DeleteAllItems ();
 
@@ -505,6 +522,13 @@ ScreensPanel::search_changed ()
        _screen_to_item.clear ();
 
        add_cinemas ();
+}
+
+
+void
+ScreensPanel::search_changed ()
+{
+       clear_and_re_add();
 
        _ignore_selection_change = true;
 
@@ -657,3 +681,31 @@ ScreensPanel::compare (string const& utf8_a, string const& utf8_b)
                return strcoll(utf8_a.c_str(), utf8_b.c_str());
        }
 }
+
+
+bool
+ScreensPanel::notify_cinemas_changed()
+{
+       _ignore_cinemas_changed = true;
+       ScopeGuard sg = [this]() { _ignore_cinemas_changed = false; };
+
+       try {
+               Config::instance()->changed(Config::CINEMAS);
+       } catch (FileError& e) {
+               error_dialog(GetParent(), _("Could not write cinema details to the cinemas.xml file.  Check that the location of cinemas.xml is valid in DCP-o-matic's preferences."), std_to_wx(e.what()));
+               return false;
+       }
+
+       return true;
+}
+
+
+void
+ScreensPanel::config_changed(Config::Property property)
+{
+       if (property == Config::Property::CINEMAS && !_ignore_cinemas_changed) {
+               clear_and_re_add();
+       }
+}
+
+