diff options
| author | Carl Hetherington <cth@carlh.net> | 2023-05-20 22:51:49 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2024-05-06 20:42:50 +0200 |
| commit | a3fcbb3a76e079a5485a0552ea5d35b8d6739116 (patch) | |
| tree | 58f6476b7197c0e32b5aa3d52d0859a9b04db268 /src/wx | |
| parent | a4105c6e8dc83407abc9b12e80c958673c942888 (diff) | |
Use sqlite for cinema and DKDM recipient lists.
Diffstat (limited to 'src/wx')
| -rw-r--r-- | src/wx/kdm_dialog.cc | 17 | ||||
| -rw-r--r-- | src/wx/load_config_from_zip_dialog.cc | 59 | ||||
| -rw-r--r-- | src/wx/load_config_from_zip_dialog.h | 41 | ||||
| -rw-r--r-- | src/wx/recipients_panel.cc | 65 | ||||
| -rw-r--r-- | src/wx/recipients_panel.h | 7 | ||||
| -rw-r--r-- | src/wx/screens_panel.cc | 282 | ||||
| -rw-r--r-- | src/wx/screens_panel.h | 50 | ||||
| -rw-r--r-- | src/wx/wscript | 1 | ||||
| -rw-r--r-- | src/wx/wx_util.cc | 14 |
9 files changed, 297 insertions, 239 deletions
diff --git a/src/wx/kdm_dialog.cc b/src/wx/kdm_dialog.cc index e6f4eca5e..1a9c564d4 100644 --- a/src/wx/kdm_dialog.cc +++ b/src/wx/kdm_dialog.cc @@ -205,8 +205,21 @@ KDMDialog::make_clicked () return film->make_kdm(_cpl->cpl(), begin, end); }; - for (auto i: _screens->screens()) { - auto p = kdm_for_screen(make_kdm, i, _timing->from(), _timing->until(), _output->formulation(), !_output->forensic_mark_video(), for_audio, period_checks); + CinemaList cinemas; + + for (auto screen: _screens->screens()) { + auto p = kdm_for_screen( + make_kdm, + screen.first, + *cinemas.cinema(screen.first), + *cinemas.screen(screen.second), + _timing->from(), + _timing->until(), + _output->formulation(), + !_output->forensic_mark_video(), + for_audio, + period_checks + ); if (p) { kdms.push_back (p); } diff --git a/src/wx/load_config_from_zip_dialog.cc b/src/wx/load_config_from_zip_dialog.cc new file mode 100644 index 000000000..a7d573ded --- /dev/null +++ b/src/wx/load_config_from_zip_dialog.cc @@ -0,0 +1,59 @@ +/* + Copyright (C) 2024 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + + +#include "load_config_from_zip_dialog.h" +#include "wx_util.h" +#include "lib/config.h" +#include "lib/unzipper.h" + + +LoadConfigFromZIPDialog::LoadConfigFromZIPDialog(wxWindow* parent, boost::filesystem::path zip_file) + : TableDialog(parent, _("Load configuration from ZIP file"), 1, 0, true) +{ + _use_current = add(new wxRadioButton(this, wxID_ANY, _("Copy the cinemas in the ZIP file over the current list at"))); + auto current_path = add(new wxStaticText(this, wxID_ANY, std_to_wx(Config::instance()->cinemas_file().string()))); + auto current_path_font = current_path->GetFont(); + current_path_font.SetFamily(wxFONTFAMILY_TELETYPE); + current_path->SetFont(current_path_font); + + _use_zip = add(new wxRadioButton(this, wxID_ANY, _("Copy the cinemas in the ZIP file to the original location at"))); + auto zip_path = add(new wxStaticText(this, wxID_ANY, std_to_wx(Config::cinemas_file_from_zip(zip_file).string()))); + auto zip_path_font = zip_path->GetFont(); + zip_path_font.SetFamily(wxFONTFAMILY_TELETYPE); + zip_path->SetFont(zip_path_font); + + _ignore = add(new wxRadioButton(this, wxID_ANY, _("Do not use the cinemas in the ZIP file"))); + + layout(); +} + + +Config::CinemasAction +LoadConfigFromZIPDialog::action() const +{ + if (_use_current->GetValue()) { + return Config::CinemasAction::WRITE_TO_CURRENT_PATH; + } else if (_use_zip->GetValue()) { + return Config::CinemasAction::WRITE_TO_PATH_IN_ZIPPED_CONFIG; + } + + return Config::CinemasAction::IGNORE; +} diff --git a/src/wx/load_config_from_zip_dialog.h b/src/wx/load_config_from_zip_dialog.h new file mode 100644 index 000000000..f5f4ec6ea --- /dev/null +++ b/src/wx/load_config_from_zip_dialog.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2024 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + + +#include "table_dialog.h" +#include "lib/config.h" +#include <boost/filesystem.hpp> + + +class LoadConfigFromZIPDialog : public TableDialog +{ +public: + LoadConfigFromZIPDialog(wxWindow* parent, boost::filesystem::path zip_file); + + Config::CinemasAction action() const; + +private: + wxRadioButton* _use_current; + wxRadioButton* _use_zip; + wxRadioButton* _ignore; +}; + + + diff --git a/src/wx/recipients_panel.cc b/src/wx/recipients_panel.cc index 04ad0dd6e..9596c3cfd 100644 --- a/src/wx/recipients_panel.cc +++ b/src/wx/recipients_panel.cc @@ -23,7 +23,7 @@ #include "wx_util.h" #include "recipient_dialog.h" #include "dcpomatic_button.h" -#include "lib/config.h" +#include "lib/dkdm_recipient_list.h" #include <list> #include <iostream> @@ -103,15 +103,15 @@ RecipientsPanel::setup_sensitivity () void -RecipientsPanel::add_recipient (shared_ptr<DKDMRecipient> r) +RecipientsPanel::add_recipient(DKDMRecipientID id, DKDMRecipient const& recipient) { string const search = wx_to_std(_search->GetValue()); - if (!search.empty() && !_collator.find(search, r->name)) { + if (!search.empty() && !_collator.find(search, recipient.name)) { return; } - _recipients[_targets->AppendItem(_root, std_to_wx(r->name))] = r; + _recipients.emplace(make_pair(_targets->AppendItem(_root, std_to_wx(recipient.name)), id)); _targets->SortChildren (_root); } @@ -122,9 +122,10 @@ RecipientsPanel::add_recipient_clicked () { RecipientDialog dialog(GetParent(), _("Add recipient")); if (dialog.ShowModal() == wxID_OK) { - auto r = std::make_shared<DKDMRecipient>(dialog.name(), dialog.notes(), dialog.recipient(), dialog.emails()); - Config::instance()->add_dkdm_recipient (r); - add_recipient (r); + auto recipient = DKDMRecipient(dialog.name(), dialog.notes(), dialog.recipient(), dialog.emails()); + DKDMRecipientList recipient_list; + auto const id = recipient_list.add_dkdm_recipient(recipient); + add_recipient(id, recipient); } } @@ -136,18 +137,28 @@ RecipientsPanel::edit_recipient_clicked () return; } - auto c = *_selected.begin(); + DKDMRecipientList recipients; + auto selection = *_selected.begin(); + auto const recipient_id = selection.second; + auto recipient = recipients.dkdm_recipient(recipient_id); + DCPOMATIC_ASSERT(recipient); RecipientDialog dialog( - GetParent(), _("Edit recipient"), c.second->name, c.second->notes, c.second->emails, c.second->recipient + GetParent(), + _("Edit recipient"), + recipient->name, + recipient->notes, + recipient->emails, + recipient->recipient ); if (dialog.ShowModal() == wxID_OK) { - c.second->name = dialog.name(); - c.second->emails = dialog.emails(); - c.second->notes = dialog.notes(); - _targets->SetItemText(c.first, std_to_wx(dialog.name())); - Config::instance()->changed (Config::DKDM_RECIPIENTS); + recipient->name = dialog.name(); + recipient->emails = dialog.emails(); + recipient->notes = dialog.notes(); + recipient->recipient = dialog.recipient(); + recipients.update_dkdm_recipient(recipient_id, *recipient); + _targets->SetItemText(selection.first, std_to_wx(dialog.name())); } } @@ -156,7 +167,8 @@ void RecipientsPanel::remove_recipient_clicked () { for (auto const& i: _selected) { - Config::instance()->remove_dkdm_recipient (i.second); + DKDMRecipientList recipient_list; + recipient_list.remove_dkdm_recipient(i.second); _targets->Delete (i.first); } @@ -164,19 +176,15 @@ RecipientsPanel::remove_recipient_clicked () } -list<shared_ptr<DKDMRecipient>> +list<DKDMRecipient> RecipientsPanel::recipients () const { - list<shared_ptr<DKDMRecipient>> r; - - for (auto const& i: _selected) { - r.push_back (i.second); + list<DKDMRecipient> all; + DKDMRecipientList recipients; + for (auto const& recipient: recipients.dkdm_recipients()) { + all.push_back(recipient.second); } - - r.sort (); - r.unique (); - - return r; + return all; } @@ -202,7 +210,7 @@ RecipientsPanel::selection_changed () for (size_t i = 0; i < s.GetCount(); ++i) { RecipientMap::const_iterator j = _recipients.find (s[i]); if (j != _recipients.end ()) { - _selected[j->first] = j->second; + _selected.emplace(*j); } } @@ -216,8 +224,9 @@ RecipientsPanel::add_recipients () { _root = _targets->AddRoot ("Foo"); - for (auto i: Config::instance()->dkdm_recipients()) { - add_recipient (i); + DKDMRecipientList recipients; + for (auto const& recipient: recipients.dkdm_recipients()) { + add_recipient(recipient.first, recipient.second); } } diff --git a/src/wx/recipients_panel.h b/src/wx/recipients_panel.h index 6e1f1408f..d252b8d06 100644 --- a/src/wx/recipients_panel.h +++ b/src/wx/recipients_panel.h @@ -21,6 +21,7 @@ #include "lib/collator.h" #include "lib/dkdm_recipient.h" +#include "lib/dkdm_recipient_list.h" #include <dcp/warnings.h> LIBDCP_DISABLE_WARNINGS #include <wx/srchctrl.h> @@ -43,12 +44,12 @@ public: void setup_sensitivity (); - std::list<std::shared_ptr<DKDMRecipient>> recipients () const; + std::list<DKDMRecipient> recipients() const; boost::signals2::signal<void ()> RecipientsChanged; private: void add_recipients (); - void add_recipient (std::shared_ptr<DKDMRecipient>); + void add_recipient(DKDMRecipientID id, DKDMRecipient const& recipient); void add_recipient_clicked (); void edit_recipient_clicked (); void remove_recipient_clicked (); @@ -63,7 +64,7 @@ private: wxButton* _remove_recipient; wxTreeItemId _root; - typedef std::map<wxTreeItemId, std::shared_ptr<DKDMRecipient>> RecipientMap; + typedef std::map<wxTreeItemId, DKDMRecipientID> RecipientMap; RecipientMap _recipients; RecipientMap _selected; diff --git a/src/wx/screens_panel.cc b/src/wx/screens_panel.cc index 768d25092..fdc4dacc3 100644 --- a/src/wx/screens_panel.cc +++ b/src/wx/screens_panel.cc @@ -126,8 +126,6 @@ ScreensPanel::ScreensPanel (wxWindow* parent) _uncheck_all->Bind (wxEVT_BUTTON, boost::bind(&ScreensPanel::uncheck_all, this)); SetSizer(_overall_sizer); - - _config_connection = Config::instance()->Changed.connect(boost::bind(&ScreensPanel::config_changed, this, _1)); } @@ -189,28 +187,37 @@ ScreensPanel::convert_to_lower(string& s) bool -ScreensPanel::matches_search(shared_ptr<const Cinema> cinema, string search) +ScreensPanel::matches_search(Cinema const& cinema, string search) { if (search.empty()) { return true; } - return _collator.find(search, cinema->name); + return _collator.find(search, cinema.name); } +/** Add an existing cinema to the GUI */ optional<wxTreeListItem> -ScreensPanel::add_cinema (shared_ptr<Cinema> cinema, wxTreeListItem previous) +ScreensPanel::add_cinema(CinemaID cinema_id, wxTreeListItem previous) { + CinemaList cinemas; + auto cinema = cinemas.cinema(cinema_id); + DCPOMATIC_ASSERT(cinema); + auto const search = wx_to_std(_search->GetValue()); - if (!matches_search(cinema, search)) { + if (!matches_search(*cinema, search)) { return {}; } + auto screens = cinemas.screens(cinema_id); + if (_show_only_checked->get()) { - auto screens = cinema->screens(); - auto iter = std::find_if(screens.begin(), screens.end(), [this](shared_ptr<dcpomatic::Screen> screen) { - return _checked_screens.find(screen) != _checked_screens.end(); + auto iter = std::find_if(screens.begin(), screens.end(), [this](pair<ScreenID, dcpomatic::Screen> const& screen) { + auto iter2 = std::find_if(_checked_screens.begin(), _checked_screens.end(), [screen](pair<CinemaID, ScreenID> const& checked) { + return checked.second == screen.first; + }); + return iter2 != _checked_screens.end(); }); if (iter == screens.end()) { return {}; @@ -219,29 +226,34 @@ ScreensPanel::add_cinema (shared_ptr<Cinema> cinema, wxTreeListItem previous) auto id = _targets->InsertItem(_targets->GetRootItem(), previous, std_to_wx(cinema->name)); - _item_to_cinema[id] = cinema; - _cinema_to_item[cinema] = id; + _item_to_cinema.emplace(make_pair(id, cinema_id)); + _cinema_to_item[cinema_id] = id; - for (auto screen: cinema->screens()) { - add_screen (cinema, screen); + for (auto screen: screens) { + add_screen(cinema_id, screen.first); } return id; } +/** Add an existing screen to the GUI */ optional<wxTreeListItem> -ScreensPanel::add_screen (shared_ptr<Cinema> cinema, shared_ptr<Screen> screen) +ScreensPanel::add_screen(CinemaID cinema_id, ScreenID screen_id) { - auto item = cinema_to_item(cinema); + auto item = cinema_to_item(cinema_id); if (!item) { return {}; } + CinemaList cinemas; + auto screen = cinemas.screen(screen_id); + DCPOMATIC_ASSERT(screen); + auto id = _targets->AppendItem(*item, std_to_wx(screen->name)); - _item_to_screen[id] = screen; - _screen_to_item[screen] = id; + _item_to_screen.emplace(make_pair(id, make_pair(cinema_id, screen_id))); + _screen_to_item[screen_id] = id; return item; } @@ -253,44 +265,31 @@ ScreensPanel::add_cinema_clicked () CinemaDialog dialog(GetParent(), _("Add Cinema")); if (dialog.ShowModal() == wxID_OK) { - auto cinema = make_shared<Cinema>(dialog.name(), dialog.emails(), dialog.notes(), dialog.utc_offset()); + auto cinema = Cinema(dialog.name(), dialog.emails(), dialog.notes(), dialog.utc_offset()); - auto cinemas = sorted_cinemas(); + CinemaList cinemas; + auto existing_cinemas = cinemas.cinemas(); - try { - _ignore_cinemas_changed = true; - dcp::ScopeGuard sg = [this]() { _ignore_cinemas_changed = false; }; - Config::instance()->add_cinema(cinema); - } catch (FileError& e) { - error_dialog( - GetParent(), - variant::wx::insert_dcpomatic( - _("Could not write cinema details to the cinemas.xml file. Check that the location of " - "cinemas.xml is valid in %s's preferences.") - ), - std_to_wx(e.what()) - ); - return; - } + auto const cinema_id = cinemas.add_cinema(cinema); wxTreeListItem previous = wxTLI_FIRST; bool found = false; auto const search = wx_to_std(_search->GetValue()); - for (auto existing_cinema: cinemas) { - if (!matches_search(existing_cinema, search)) { + for (auto existing_cinema: existing_cinemas) { + if (!matches_search(existing_cinema.second, search)) { continue; } - if (_collator.compare(dialog.name(), existing_cinema->name) < 0) { + if (_collator.compare(dialog.name(), existing_cinema.second.name) < 0) { /* existing_cinema should be after the one we're inserting */ found = true; break; } - auto item = cinema_to_item(existing_cinema); + auto item = cinema_to_item(existing_cinema.first); DCPOMATIC_ASSERT(item); previous = *item; } - auto item = add_cinema(cinema, found ? previous : wxTLI_LAST); + auto item = add_cinema(cinema_id, found ? previous : wxTLI_LAST); if (item) { _targets->UnselectAll (); @@ -302,13 +301,13 @@ ScreensPanel::add_cinema_clicked () } -shared_ptr<Cinema> +optional<CinemaID> ScreensPanel::cinema_for_operation () const { if (_selected_cinemas.size() == 1) { return _selected_cinemas[0]; } else if (_selected_screens.size() == 1) { - return _selected_screens[0]->cinema; + return _selected_screens[0].first; } return {}; @@ -318,25 +317,29 @@ ScreensPanel::cinema_for_operation () const void ScreensPanel::edit_cinema_clicked () { - auto cinema = cinema_for_operation (); - if (cinema) { - edit_cinema(cinema); + auto cinema_id = cinema_for_operation(); + if (cinema_id) { + edit_cinema(*cinema_id); } } void -ScreensPanel::edit_cinema(shared_ptr<Cinema> cinema) +ScreensPanel::edit_cinema(CinemaID cinema_id) { + CinemaList cinemas; + auto cinema = cinemas.cinema(cinema_id); + DCPOMATIC_ASSERT(cinema); + CinemaDialog dialog(GetParent(), _("Edit cinema"), cinema->name, cinema->emails, cinema->notes, cinema->utc_offset); if (dialog.ShowModal() == wxID_OK) { - cinema->name = dialog.name(); cinema->emails = dialog.emails(); + cinema->name = dialog.name(); cinema->notes = dialog.notes(); cinema->utc_offset = dialog.utc_offset(); - notify_cinemas_changed(); - auto item = cinema_to_item(cinema); + cinemas.update_cinema(cinema_id, *cinema); + auto item = cinema_to_item(cinema_id); DCPOMATIC_ASSERT(item); _targets->SetItemText (*item, std_to_wx(dialog.name())); } @@ -346,8 +349,11 @@ ScreensPanel::edit_cinema(shared_ptr<Cinema> cinema) void ScreensPanel::remove_cinema_clicked () { + CinemaList cinemas; + if (_selected_cinemas.size() == 1) { - if (!confirm_dialog(this, wxString::Format(_("Are you sure you want to remove the cinema '%s'?"), std_to_wx(_selected_cinemas[0]->name)))) { + auto cinema = cinemas.cinema(_selected_cinemas[0]); + if (!confirm_dialog(this, wxString::Format(_("Are you sure you want to remove the cinema '%s'?"), std_to_wx(cinema->name)))) { return; } } else { @@ -358,14 +364,12 @@ ScreensPanel::remove_cinema_clicked () auto cinemas_to_remove = _selected_cinemas; - for (auto const& cinema: cinemas_to_remove) { - _ignore_cinemas_changed = true; - dcp::ScopeGuard sg = [this]() { _ignore_cinemas_changed = false; }; - for (auto screen: cinema->screens()) { - _checked_screens.erase(screen); + for (auto const& cinema_id: cinemas_to_remove) { + for (auto screen: cinemas.screens(cinema_id)) { + _checked_screens.erase({cinema_id, screen.first}); } - Config::instance()->remove_cinema(cinema); - auto item = cinema_to_item(cinema); + cinemas.remove_cinema(cinema_id); + auto item = cinema_to_item(cinema_id); DCPOMATIC_ASSERT(item); _targets->DeleteItem(*item); } @@ -378,8 +382,8 @@ ScreensPanel::remove_cinema_clicked () void ScreensPanel::add_screen_clicked () { - auto cinema = cinema_for_operation (); - if (!cinema) { + auto cinema_id = cinema_for_operation(); + if (!cinema_id) { return; } @@ -389,8 +393,10 @@ ScreensPanel::add_screen_clicked () return; } - for (auto screen: cinema->screens()) { - if (screen->name == dialog.name()) { + CinemaList cinemas; + + for (auto screen: cinemas.screens(*cinema_id)) { + if (screen.second.name == dialog.name()) { error_dialog ( GetParent(), wxString::Format ( @@ -402,11 +408,10 @@ 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 screen = Screen(dialog.name(), dialog.notes(), dialog.recipient(), dialog.recipient_file(), dialog.trusted_devices()); + auto const screen_id = cinemas.add_screen(*cinema_id, screen); - auto id = add_screen (cinema, screen); + auto id = add_screen(*cinema_id, screen_id); if (id) { _targets->Expand (id.get ()); } @@ -417,30 +422,33 @@ void ScreensPanel::edit_screen_clicked () { if (_selected_screens.size() == 1) { - edit_screen(_selected_screens[0]); + edit_screen(_selected_screens[0].first, _selected_screens[0].second); } } void -ScreensPanel::edit_screen(shared_ptr<Screen> edit_screen) +ScreensPanel::edit_screen(CinemaID cinema_id, ScreenID screen_id) { + CinemaList cinemas; + auto screen = cinemas.screen(screen_id); + DCPOMATIC_ASSERT(screen); + ScreenDialog dialog( GetParent(), _("Edit screen"), - edit_screen->name, - edit_screen->notes, - edit_screen->recipient, - edit_screen->recipient_file, - edit_screen->trusted_devices + screen->name, + screen->notes, + screen->recipient, + screen->recipient_file, + screen->trusted_devices ); if (dialog.ShowModal() != wxID_OK) { return; } - auto cinema = edit_screen->cinema; - for (auto screen: cinema->screens()) { - if (screen != edit_screen && screen->name == dialog.name()) { + for (auto screen: cinemas.screens(cinema_id)) { + if (screen.first != screen_id && screen.second.name == dialog.name()) { error_dialog ( GetParent(), wxString::Format ( @@ -452,14 +460,14 @@ ScreensPanel::edit_screen(shared_ptr<Screen> edit_screen) } } - edit_screen->name = dialog.name(); - edit_screen->notes = dialog.notes(); - edit_screen->recipient = dialog.recipient(); - edit_screen->recipient_file = dialog.recipient_file(); - edit_screen->trusted_devices = dialog.trusted_devices(); - notify_cinemas_changed(); + screen->name = dialog.name(); + screen->notes = dialog.notes(); + screen->recipient = dialog.recipient(); + screen->recipient_file = dialog.recipient_file(); + screen->trusted_devices = dialog.trusted_devices(); + cinemas.update_screen(screen_id, *screen); - auto item = screen_to_item(edit_screen); + auto item = screen_to_item(screen_id); DCPOMATIC_ASSERT (item); _targets->SetItemText(*item, std_to_wx(dialog.name())); } @@ -468,8 +476,12 @@ ScreensPanel::edit_screen(shared_ptr<Screen> edit_screen) void ScreensPanel::remove_screen_clicked () { + CinemaList cinemas; + if (_selected_screens.size() == 1) { - if (!confirm_dialog(this, wxString::Format(_("Are you sure you want to remove the screen '%s'?"), std_to_wx(_selected_screens[0]->name)))) { + auto screen = cinemas.screen(_selected_screens[0].second); + DCPOMATIC_ASSERT(screen); + if (!confirm_dialog(this, wxString::Format(_("Are you sure you want to remove the screen '%s'?"), std_to_wx(screen->name)))) { return; } } else { @@ -478,10 +490,10 @@ ScreensPanel::remove_screen_clicked () } } - for (auto screen: _selected_screens) { - _checked_screens.erase(screen); - screen->cinema->remove_screen(screen); - auto item = screen_to_item(screen); + for (auto screen_id: _selected_screens) { + _checked_screens.erase(screen_id); + cinemas.remove_screen(screen_id.second); + auto item = screen_to_item(screen_id.second); DCPOMATIC_ASSERT(item); _targets->DeleteItem(*item); } @@ -490,17 +502,14 @@ ScreensPanel::remove_screen_clicked () * as well. */ selection_changed(); - notify_cinemas_changed(); setup_show_only_checked(); } -vector<shared_ptr<Screen>> +std::set<pair<CinemaID, ScreenID>> ScreensPanel::screens () const { - vector<shared_ptr<Screen>> output; - std::copy (_checked_screens.begin(), _checked_screens.end(), std::back_inserter(output)); - return output; + return _checked_screens; } @@ -526,10 +535,10 @@ ScreensPanel::selection_changed () for (size_t i = 0; i < selection.size(); ++i) { if (auto cinema = item_to_cinema(selection[i])) { - _selected_cinemas.push_back(cinema); + _selected_cinemas.push_back(*cinema); } if (auto screen = item_to_screen(selection[i])) { - _selected_screens.push_back(screen); + _selected_screens.push_back(*screen); } } @@ -537,24 +546,12 @@ ScreensPanel::selection_changed () } -list<shared_ptr<Cinema>> -ScreensPanel::sorted_cinemas() const -{ - auto cinemas = Config::instance()->cinemas(); - - cinemas.sort( - [this](shared_ptr<Cinema> a, shared_ptr<Cinema> b) { return _collator.compare(a->name, b->name) < 0; } - ); - - return cinemas; -} - - void ScreensPanel::add_cinemas () { - for (auto cinema: sorted_cinemas()) { - add_cinema (cinema, wxTLI_LAST); + CinemaList cinemas; + for (auto cinema: cinemas.cinemas()) { + add_cinema (cinema.first, wxTLI_LAST); } } @@ -588,7 +585,7 @@ ScreensPanel::display_filter_changed() } for (auto const& selection: _selected_screens) { - if (auto item = screen_to_item(selection)) { + if (auto item = screen_to_item(selection.second)) { _targets->Select (*item); } } @@ -598,7 +595,7 @@ ScreensPanel::display_filter_changed() _ignore_check_change = true; for (auto const& checked: _checked_screens) { - if (auto item = screen_to_item(checked)) { + if (auto item = screen_to_item(checked.second)) { _targets->CheckItem(*item, wxCHK_CHECKED); setup_cinema_checked_state(*item); } @@ -614,9 +611,9 @@ ScreensPanel::set_screen_checked (wxTreeListItem item, bool checked) auto screen = item_to_screen(item); DCPOMATIC_ASSERT(screen); if (checked) { - _checked_screens.insert(screen); + _checked_screens.insert({screen->first, screen->second}); } else { - _checked_screens.erase(screen); + _checked_screens.erase({screen->first, screen->second}); } setup_show_only_checked(); @@ -670,7 +667,7 @@ ScreensPanel::checkbox_changed (wxTreeListEvent& ev) } -shared_ptr<Cinema> +optional<CinemaID> ScreensPanel::item_to_cinema (wxTreeListItem item) const { auto iter = _item_to_cinema.find (item); @@ -682,7 +679,7 @@ ScreensPanel::item_to_cinema (wxTreeListItem item) const } -shared_ptr<Screen> +optional<pair<CinemaID, ScreenID>> ScreensPanel::item_to_screen (wxTreeListItem item) const { auto iter = _item_to_screen.find (item); @@ -695,7 +692,7 @@ ScreensPanel::item_to_screen (wxTreeListItem item) const optional<wxTreeListItem> -ScreensPanel::cinema_to_item (shared_ptr<Cinema> cinema) const +ScreensPanel::cinema_to_item(CinemaID cinema) const { auto iter = _cinema_to_item.find (cinema); if (iter == _cinema_to_item.end()) { @@ -707,7 +704,7 @@ ScreensPanel::cinema_to_item (shared_ptr<Cinema> cinema) const optional<wxTreeListItem> -ScreensPanel::screen_to_item (shared_ptr<Screen> screen) const +ScreensPanel::screen_to_item(ScreenID screen) const { auto iter = _screen_to_item.find (screen); if (iter == _screen_to_item.end()) { @@ -718,39 +715,6 @@ ScreensPanel::screen_to_item (shared_ptr<Screen> screen) const } -bool -ScreensPanel::notify_cinemas_changed() -{ - _ignore_cinemas_changed = true; - dcp::ScopeGuard sg = [this]() { _ignore_cinemas_changed = false; }; - - try { - Config::instance()->changed(Config::CINEMAS); - } catch (FileError& e) { - error_dialog( - GetParent(), - variant::wx::insert_dcpomatic( - _("Could not write cinema details to the cinemas.xml file. Check that the location of " - "cinemas.xml is valid in %s'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(); - } -} - - void ScreensPanel::item_activated(wxTreeListEvent& ev) { @@ -760,7 +724,7 @@ ScreensPanel::item_activated(wxTreeListEvent& ev) } else { auto iter = _item_to_screen.find(ev.GetItem()); if (iter != _item_to_screen.end()) { - edit_screen(iter->second); + edit_screen(iter->second.first, iter->second.second); } } } @@ -783,20 +747,12 @@ ScreensPanel::setup_show_only_checked() dcp::UTCOffset ScreensPanel::best_utc_offset() const { - auto all_screens = screens(); - if (all_screens.empty()) { - return {}; - } - - dcp::UTCOffset const first = all_screens[0]->cinema->utc_offset; - - for (auto screen = std::next(all_screens.begin()); screen != all_screens.end(); ++screen) { - if ((*screen)->cinema->utc_offset != first) { - /* Not unique */ - return dcp::UTCOffset(); - } + std::set<CinemaID> unique_cinema_ids; + for (auto const& screen: screens()) { + unique_cinema_ids.insert(screen.first); } - return first; + CinemaList cinema_list; + return cinema_list.unique_utc_offset(unique_cinema_ids).get_value_or(dcp::UTCOffset()); } diff --git a/src/wx/screens_panel.h b/src/wx/screens_panel.h index 1e07b6236..98ec2c631 100644 --- a/src/wx/screens_panel.h +++ b/src/wx/screens_panel.h @@ -19,6 +19,7 @@ */ +#include "lib/cinema_list.h" #include "lib/collator.h" #include "lib/config.h" #include <dcp/warnings.h> @@ -38,7 +39,6 @@ namespace dcpomatic { } -class Cinema; class CheckBox; @@ -48,7 +48,7 @@ public: explicit ScreensPanel (wxWindow* parent); ~ScreensPanel (); - std::vector<std::shared_ptr<dcpomatic::Screen>> screens () const; + std::set<std::pair<CinemaID, ScreenID>> screens() const; void setup_sensitivity (); dcp::UTCOffset best_utc_offset() const; @@ -57,38 +57,35 @@ public: private: void add_cinemas (); - boost::optional<wxTreeListItem> add_cinema (std::shared_ptr<Cinema>, wxTreeListItem previous); - boost::optional<wxTreeListItem> add_screen (std::shared_ptr<Cinema>, std::shared_ptr<dcpomatic::Screen>); + boost::optional<wxTreeListItem> add_cinema(CinemaID cinema, wxTreeListItem previous); + boost::optional<wxTreeListItem> add_screen(CinemaID cinema, ScreenID screen); void add_cinema_clicked (); void edit_cinema_clicked (); - void edit_cinema(std::shared_ptr<Cinema> cinema); + void edit_cinema(CinemaID cinema_id); void remove_cinema_clicked (); void add_screen_clicked (); void edit_screen_clicked (); - void edit_screen(std::shared_ptr<dcpomatic::Screen> screen); + void edit_screen(CinemaID cinema_id, ScreenID screen_id); void remove_screen_clicked (); void selection_changed_shim (wxTreeListEvent &); void selection_changed (); void display_filter_changed(); void checkbox_changed (wxTreeListEvent& ev); void item_activated(wxTreeListEvent& ev); - std::shared_ptr<Cinema> cinema_for_operation () const; + boost::optional<CinemaID> cinema_for_operation() const; void set_screen_checked (wxTreeListItem item, bool checked); void setup_cinema_checked_state (wxTreeListItem screen); void check_all (); void uncheck_all (); - bool notify_cinemas_changed(); void clear_and_re_add(); - void config_changed(Config::Property); void convert_to_lower(std::string& s); - bool matches_search(std::shared_ptr<const Cinema> cinema, std::string search); - std::list<std::shared_ptr<Cinema>> sorted_cinemas() const; + bool matches_search(Cinema const& cinema, std::string search); void setup_show_only_checked(); - std::shared_ptr<Cinema> item_to_cinema (wxTreeListItem item) const; - std::shared_ptr<dcpomatic::Screen> item_to_screen (wxTreeListItem item) const; - boost::optional<wxTreeListItem> cinema_to_item (std::shared_ptr<Cinema> cinema) const; - boost::optional<wxTreeListItem> screen_to_item (std::shared_ptr<dcpomatic::Screen> screen) const; + boost::optional<CinemaID> item_to_cinema(wxTreeListItem item) const; + boost::optional<std::pair<CinemaID, ScreenID>> item_to_screen(wxTreeListItem item) const; + boost::optional<wxTreeListItem> cinema_to_item(CinemaID cinema) const; + boost::optional<wxTreeListItem> screen_to_item(ScreenID screen) const; wxBoxSizer* _overall_sizer; wxSearchCtrl* _search; @@ -106,24 +103,19 @@ private: /* We want to be able to search (and so remove selected things from the view) * but not deselect them, so we maintain lists of selected cinemas and screens. */ - std::vector<std::shared_ptr<Cinema>> _selected_cinemas; - std::vector<std::shared_ptr<dcpomatic::Screen>> _selected_screens; - /* Likewise with checked screens, except that we can work out which cinemas - * are checked from which screens are checked, so we don't need to store the - * cinemas. - */ - std::set<std::shared_ptr<dcpomatic::Screen>> _checked_screens; + std::vector<CinemaID> _selected_cinemas; + /* List of cinema_id, screen_id */ + std::vector<std::pair<CinemaID, ScreenID>> _selected_screens; + /* Likewise with checked screens */ + std::set<std::pair<CinemaID, ScreenID>> _checked_screens; - std::map<wxTreeListItem, std::shared_ptr<Cinema>> _item_to_cinema; - std::map<wxTreeListItem, std::shared_ptr<dcpomatic::Screen>> _item_to_screen; - std::map<std::shared_ptr<Cinema>, wxTreeListItem> _cinema_to_item; - std::map<std::shared_ptr<dcpomatic::Screen>, wxTreeListItem> _screen_to_item; + std::map<wxTreeListItem, CinemaID> _item_to_cinema; + std::map<wxTreeListItem, std::pair<CinemaID, ScreenID>> _item_to_screen; + std::map<CinemaID, wxTreeListItem> _cinema_to_item; + std::map<ScreenID, wxTreeListItem> _screen_to_item; bool _ignore_selection_change = false; bool _ignore_check_change = false; Collator _collator; - - boost::signals2::scoped_connection _config_connection; - bool _ignore_cinemas_changed = false; }; diff --git a/src/wx/wscript b/src/wx/wscript index b37d26d6d..a41e3827e 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -113,6 +113,7 @@ sources = """ language_subtag_panel.cc language_tag_dialog.cc language_tag_widget.cc + load_config_from_zip_dialog.cc kdm_choice.cc make_chain_dialog.cc markers.cc diff --git a/src/wx/wx_util.cc b/src/wx/wx_util.cc index 7d8fb0a76..1c04a4755 100644 --- a/src/wx/wx_util.cc +++ b/src/wx/wx_util.cc @@ -810,20 +810,6 @@ report_config_load_failure(wxWindow* parent, Config::LoadFailure what) case Config::LoadFailure::CONFIG: message_dialog(parent, _("The existing configuration failed to load. Default values will be used instead. These may take a short time to create.")); break; - case Config::LoadFailure::CINEMAS: - message_dialog( - parent, - _(wxString::Format("The cinemas list for creating KDMs (cinemas.xml) failed to load. Please check the numbered backup files in %s", - std_to_wx(Config::instance()->cinemas_file().parent_path().string()))) - ); - break; - case Config::LoadFailure::DKDM_RECIPIENTS: - message_dialog( - parent, - _(wxString::Format("The recipients list for creating DKDMs (dkdm_recipients.xml) failed to load. Please check the numbered backup files in %s", - std_to_wx(Config::instance()->dkdm_recipients_file().parent_path().string()))) - ); - break; } } |
