for (auto i: node->node_children("Email")) {
emails.push_back (i->content ());
}
+
+ int hour = 0;
+
+ if (node->optional_number_child<int>("UTCOffset")) {
+ hour = node->number_child<int>("UTCOffset");
+ } else {
+ hour = node->optional_number_child<int>("UTCOffsetHour").get_value_or(0);
+ }
+
+ int minute = node->optional_number_child<int>("UTCOffsetMinute").get_value_or(0);
+
+ utc_offset= { hour, minute };
}
/* This is necessary so that we can use shared_from_this in add_screen (which cannot be done from
cxml::add_text_child(parent, "Notes", notes);
+ cxml::add_text_child(parent, "UTCOffsetHour", raw_convert<string>(utc_offset.hour()));
+ cxml::add_text_child(parent, "UTCOffsetMinute", raw_convert<string>(utc_offset.minute()));
+
for (auto i: _screens) {
i->as_xml(cxml::add_child(parent, "Screen"));
}
*/
+#include <dcp/utc_offset.h>
#include <libcxml/cxml.h>
#include <memory>
class Cinema : public std::enable_shared_from_this<Cinema>
{
public:
- Cinema(std::string const & name_, std::vector<std::string> const & e, std::string notes_)
+ Cinema(std::string const & name_, std::vector<std::string> const & e, std::string notes_, dcp::UTCOffset utc_offset_)
: name (name_)
, emails (e)
, notes (notes_)
+ , utc_offset(std::move(utc_offset_))
{}
explicit Cinema (cxml::ConstNodePtr);
std::string name;
std::vector<std::string> emails;
std::string notes;
+ dcp::UTCOffset utc_offset;
std::vector<std::shared_ptr<dcpomatic::Screen>> screens() const {
return _screens;
(for lookup) and by creating a Cinema which the next Screen will be added to.
*/
cinema_name = optarg;
- cinema = make_shared<Cinema>(optarg, vector<string>(), "");
+ cinema = make_shared<Cinema>(optarg, vector<string>(), "", dcp::UTCOffset());
break;
case 'S':
/* Similarly, this could be the name of a new (temporary) screen or the name of a screen
/* Instantly save any config changes when using a DCP-o-matic GUI */
Config::instance()->Changed.connect (boost::bind (&Config::write, Config::instance ()));
- _screens->ScreensChanged.connect (boost::bind (&DOMFrame::setup_sensitivity, this));
+ _screens->ScreensChanged.connect(boost::bind(&DOMFrame::screens_changed, this));
_create->Bind (wxEVT_BUTTON, bind (&DOMFrame::create_kdms, this));
_dkdm->Bind(wxEVT_TREE_SEL_CHANGED, boost::bind(&DOMFrame::dkdm_selection_changed, this));
_dkdm->Bind (wxEVT_TREE_BEGIN_DRAG, boost::bind (&DOMFrame::dkdm_begin_drag, this, _1));
update_dkdm_view();
}
+ void screens_changed()
+ {
+ _timing->suggest_utc_offset(_screens->best_utc_offset());
+ setup_sensitivity();
+ }
+
wxPreferencesEditor* _config_dialog;
ScreensPanel* _screens;
KDMTimingPanel* _timing;
#include "cinema_dialog.h"
+#include "dcpomatic_choice.h"
#include "wx_util.h"
#include "lib/dcpomatic_assert.h"
#include "lib/util.h"
#endif
-CinemaDialog::CinemaDialog(wxWindow* parent, wxString title, string name, vector<string> emails, string notes)
+CinemaDialog::CinemaDialog(wxWindow* parent, wxString title, string name, vector<string> emails, string notes, dcp::UTCOffset utc_offset)
: wxDialog (parent, wxID_ANY, title)
{
auto overall_sizer = new wxBoxSizer (wxVERTICAL);
sizer->Add (_name, wxGBPosition(r, 1));
++r;
+ add_label_to_sizer(sizer, this, _("UTC offset (time zone)"), true, wxGBPosition(r, 0));
+ _utc_offset = new Choice(this);
+ sizer->Add(_utc_offset, wxGBPosition(r, 1));
+ ++r;
+
add_label_to_sizer (sizer, this, _("Notes"), true, wxGBPosition(r, 0));
_notes = new wxTextCtrl (this, wxID_ANY, std_to_wx(notes), wxDefaultPosition, wxSize(500, -1));
sizer->Add (_notes, wxGBPosition(r, 1));
overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
}
+ /* Default to UTC */
+ size_t sel = get_offsets(_offsets);
+ for (size_t i = 0; i < _offsets.size(); ++i) {
+ _utc_offset->add_entry(_offsets[i].name);
+ if (_offsets[i].offset == utc_offset) {
+ sel = i;
+ }
+ }
+
+ _utc_offset->set(sel);
+
overall_sizer->Layout ();
overall_sizer->SetSizeHints (this);
{
return wx_to_std (_notes->GetValue());
}
+
+
+dcp::UTCOffset
+CinemaDialog::utc_offset() const
+{
+ auto const sel = _utc_offset->GetSelection();
+ if (sel < 0 || sel > int(_offsets.size())) {
+ return {};
+ }
+
+ return _offsets[sel].offset;
+}
#include <vector>
+class Choice;
+
+
class CinemaDialog : public wxDialog
{
public:
wxString,
std::string name = "",
std::vector<std::string> emails = std::vector<std::string>(),
- std::string notes = ""
+ std::string notes = "",
+ dcp::UTCOffset = {}
);
std::string name () const;
std::string notes () const;
std::vector<std::string> emails () const;
+ dcp::UTCOffset utc_offset() const;
private:
void set_emails (std::vector<std::string>);
wxTextCtrl* _notes;
EditableList<std::string, EmailDialog>* _email_list;
std::vector<std::string> _emails;
+ Choice* _utc_offset;
+ std::vector<Offset> _offsets;
};
/* Bind */
- _screens->ScreensChanged.connect (boost::bind (&KDMDialog::setup_sensitivity, this));
+ _screens->ScreensChanged.connect(boost::bind(&KDMDialog::screens_changed, this));
_timing->TimingChanged.connect (boost::bind (&KDMDialog::setup_sensitivity, this));
_make->Bind (wxEVT_BUTTON, boost::bind (&KDMDialog::make_clicked, this));
_cpl->Changed.connect(boost::bind(&KDMDialog::cpl_changed, this));
}
+void
+KDMDialog::screens_changed()
+{
+ _timing->suggest_utc_offset(_screens->best_utc_offset());
+ setup_sensitivity();
+}
+
+
void
KDMDialog::cpl_changed()
{
void make_clicked ();
bool confirm_overwrite (boost::filesystem::path path);
void cpl_changed();
+ void screens_changed();
std::weak_ptr<const Film> _film;
ScreensPanel* _screens;
_warning->SetFont(font);
/* Default to UTC */
- size_t sel = get_offsets(_offsets);
- for (size_t i = 0; i < _offsets.size(); ++i) {
- _utc_offset->add_entry(_offsets[i].name);
- if (_offsets[i].hour == 0 && _offsets[i].minute == 0) {
- sel = i;
- }
+ auto const sel = get_offsets(_offsets);
+ for (auto const& offset: _offsets) {
+ _utc_offset->add_entry(offset.name);
}
-
_utc_offset->set(sel);
/* I said I've been to the year 3000. Not much has changed but they live underwater. And your In-in-in-interop DCP
_until_date->Bind (wxEVT_DATE_CHANGED, bind (&KDMTimingPanel::changed, this));
_from_time->Changed.connect (bind (&KDMTimingPanel::changed, this));
_until_time->Changed.connect (bind (&KDMTimingPanel::changed, this));
- _utc_offset->bind(&KDMTimingPanel::changed, this);
+ _utc_offset->bind(&KDMTimingPanel::utc_offset_changed, this);
SetSizer (overall_sizer);
}
return {};
}
- auto const& offset = _offsets[*sel];
- int const minute_scale = offset.hour < 0 ? -1 : 1;
+ return _offsets[*sel].offset;
+}
+
- return { offset.hour, minute_scale * offset.minute };
+void
+KDMTimingPanel::utc_offset_changed()
+{
+ _utc_offset_changed_once = true;
+ changed();
}
+void
+KDMTimingPanel::suggest_utc_offset(dcp::UTCOffset offset)
+{
+ if (!_utc_offset_changed_once) {
+ for (size_t i = 0; i < _offsets.size(); ++i) {
+ if (_offsets[i].offset == offset) {
+ _utc_offset->set(i);
+ break;
+ }
+ }
+ }
+}
+
bool valid () const;
+ /** Give a UTC offset from a cinema that the user just selected. If the user
+ * never changed the UTC offset in the panel, the suggested UTC will be set.
+ */
+ void suggest_utc_offset(dcp::UTCOffset offset);
+
boost::signals2::signal<void ()> TimingChanged;
private:
void changed () const;
+ void utc_offset_changed();
dcp::UTCOffset utc_offset() const;
static dcp::LocalTime local_time(wxDatePickerCtrl *, TimePicker *, dcp::UTCOffset offset);
TimePicker* _from_time;
TimePicker* _until_time;
Choice* _utc_offset;
+ bool _utc_offset_changed_once = false;
wxStaticText* _warning;
std::vector<Offset> _offsets;
};
CinemaDialog dialog(GetParent(), _("Add Cinema"));
if (dialog.ShowModal() == wxID_OK) {
- auto cinema = make_shared<Cinema>(dialog.name(), dialog.emails(), dialog.notes());
+ auto cinema = make_shared<Cinema>(dialog.name(), dialog.emails(), dialog.notes(), dialog.utc_offset());
auto cinemas = sorted_cinemas();
void
ScreensPanel::edit_cinema(shared_ptr<Cinema> cinema)
{
- CinemaDialog dialog(GetParent(), _("Edit cinema"), cinema->name, cinema->emails, cinema->notes);
+ 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->notes = dialog.notes();
+ cinema->utc_offset = dialog.utc_offset();
notify_cinemas_changed();
auto item = cinema_to_item(cinema);
DCPOMATIC_ASSERT(item);
setup_sensitivity();
}
+
+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();
+ }
+ }
+
+ return first;
+}
+
std::vector<std::shared_ptr<dcpomatic::Screen>> screens () const;
void setup_sensitivity ();
+ dcp::UTCOffset best_utc_offset() const;
+
boost::signals2::signal<void ()> ScreensChanged;
private:
int
get_offsets (vector<Offset>& offsets)
{
- offsets.push_back (Offset(_("UTC-11"), -11, 0));
- offsets.push_back (Offset(_("UTC-10"), -10, 0));
- offsets.push_back (Offset(_("UTC-9"), -9, 0));
- offsets.push_back (Offset(_("UTC-8"), -8, 0));
- offsets.push_back (Offset(_("UTC-7"), -7, 0));
- offsets.push_back (Offset(_("UTC-6"), -6, 0));
- offsets.push_back (Offset(_("UTC-5"), -5, 0));
- offsets.push_back (Offset(_("UTC-4:30"), -4, 30));
- offsets.push_back (Offset(_("UTC-4"), -4, 0));
- offsets.push_back (Offset(_("UTC-3:30"), -3, 30));
- offsets.push_back (Offset(_("UTC-3"), -3, 0));
- offsets.push_back (Offset(_("UTC-2"), -2, 0));
- offsets.push_back (Offset(_("UTC-1"), -1, 0));
+ offsets.push_back({_("UTC-11"), dcp::UTCOffset(-11, 0)});
+ offsets.push_back({_("UTC-10"), dcp::UTCOffset(-10, 0)});
+ offsets.push_back({_("UTC-9"), dcp::UTCOffset( -9, 0)});
+ offsets.push_back({_("UTC-8"), dcp::UTCOffset( -8, 0)});
+ offsets.push_back({_("UTC-7"), dcp::UTCOffset( -7, 0)});
+ offsets.push_back({_("UTC-6"), dcp::UTCOffset( -6, 0)});
+ offsets.push_back({_("UTC-5"), dcp::UTCOffset( -5, 0)});
+ offsets.push_back({_("UTC-4:30"),dcp::UTCOffset( -4, -30)});
+ offsets.push_back({_("UTC-4"), dcp::UTCOffset( -4, 0)});
+ offsets.push_back({_("UTC-3:30"),dcp::UTCOffset( -3, -30)});
+ offsets.push_back({_("UTC-3"), dcp::UTCOffset( -3, 0)});
+ offsets.push_back({_("UTC-2"), dcp::UTCOffset( -2, 0)});
+ offsets.push_back({_("UTC-1"), dcp::UTCOffset( -1, 0)});
int utc = offsets.size();
- offsets.push_back (Offset(_("UTC") , 0, 0));
- offsets.push_back (Offset(_("UTC+1"), 1, 0));
- offsets.push_back (Offset(_("UTC+2"), 2, 0));
- offsets.push_back (Offset(_("UTC+3"), 3, 0));
- offsets.push_back (Offset(_("UTC+4"), 4, 0));
- offsets.push_back (Offset(_("UTC+5"), 5, 0));
- offsets.push_back (Offset(_("UTC+5:30"), 5, 30));
- offsets.push_back (Offset(_("UTC+6"), 6, 0));
- offsets.push_back (Offset(_("UTC+7"), 7, 0));
- offsets.push_back (Offset(_("UTC+8"), 8, 0));
- offsets.push_back (Offset(_("UTC+9"), 9, 0));
- offsets.push_back (Offset(_("UTC+9:30"), 9, 30));
- offsets.push_back (Offset(_("UTC+10"), 10, 0));
- offsets.push_back (Offset(_("UTC+11"), 11, 0));
- offsets.push_back (Offset(_("UTC+12"), 12, 0));
+ offsets.push_back({_("UTC") , dcp::UTCOffset( 0, 0)});
+ offsets.push_back({_("UTC+1"), dcp::UTCOffset( 1, 0)});
+ offsets.push_back({_("UTC+2"), dcp::UTCOffset( 2, 0)});
+ offsets.push_back({_("UTC+3"), dcp::UTCOffset( 3, 0)});
+ offsets.push_back({_("UTC+4"), dcp::UTCOffset( 4, 0)});
+ offsets.push_back({_("UTC+5"), dcp::UTCOffset( 5, 0)});
+ offsets.push_back({_("UTC+5:30"),dcp::UTCOffset( 5, 30)});
+ offsets.push_back({_("UTC+6"), dcp::UTCOffset( 6, 0)});
+ offsets.push_back({_("UTC+7"), dcp::UTCOffset( 7, 0)});
+ offsets.push_back({_("UTC+8"), dcp::UTCOffset( 8, 0)});
+ offsets.push_back({_("UTC+9"), dcp::UTCOffset( 9, 0)});
+ offsets.push_back({_("UTC+9:30"),dcp::UTCOffset( 9, 30)});
+ offsets.push_back({_("UTC+10"), dcp::UTCOffset( 10, 0)});
+ offsets.push_back({_("UTC+11"), dcp::UTCOffset( 11, 0)});
+ offsets.push_back({_("UTC+12"), dcp::UTCOffset( 12, 0)});
return utc;
}
#include "wx_ptr.h"
#include "lib/config.h"
#include "lib/dcpomatic_time.h"
+#include <dcp/utc_offset.h>
#include <dcp/warnings.h>
LIBDCP_DISABLE_WARNINGS
#include <wx/gbsizer.h>
extern int search_ctrl_height ();
extern void report_config_load_failure(wxWindow* parent, Config::LoadFailure what);
+
struct Offset
{
- Offset (wxString n, int h, int m)
- : name (n)
- , hour (h)
- , minute (m)
+ Offset(wxString name_, dcp::UTCOffset offset_)
+ : name(name_)
+ , offset(offset_)
{}
wxString name;
- int hour;
- int minute;
+ dcp::UTCOffset offset;
};
extern int get_offsets (std::vector<Offset>& offsets);
Config::instance()->write();
- Config::instance()->add_cinema(make_shared<Cinema>("My Great Cinema", vector<string>(), ""));
+ Config::instance()->add_cinema(make_shared<Cinema>("My Great Cinema", vector<string>(), "", dcp::UTCOffset()));
Config::instance()->write();
boost::filesystem::copy_file (dir / "cinemas.xml", dir / "backup_for_test.xml");
auto config = Config::instance();
auto const cert = dcp::Certificate(dcp::file_to_string("test/data/cert.pem"));
- auto cinema_a = std::make_shared<Cinema>("Dean's Screens", vector<string>(), "");
+ auto cinema_a = std::make_shared<Cinema>("Dean's Screens", vector<string>(), "", dcp::UTCOffset());
cinema_a->add_screen(std::make_shared<dcpomatic::Screen>("Screen 1", "", cert, boost::none, std::vector<TrustedDevice>()));
cinema_a->add_screen(std::make_shared<dcpomatic::Screen>("Screen 2", "", cert, boost::none, std::vector<TrustedDevice>()));
cinema_a->add_screen(std::make_shared<dcpomatic::Screen>("Screen 3", "", cert, boost::none, std::vector<TrustedDevice>()));
config->add_cinema(cinema_a);
- auto cinema_b = std::make_shared<Cinema>("Floyd's Celluloid", vector<string>(), "");
+ auto cinema_b = std::make_shared<Cinema>("Floyd's Celluloid", vector<string>(), "", dcp::UTCOffset());
cinema_b->add_screen(std::make_shared<dcpomatic::Screen>("Foo", "", cert, boost::none, std::vector<TrustedDevice>()));
cinema_b->add_screen(std::make_shared<dcpomatic::Screen>("Bar", "", cert, boost::none, std::vector<TrustedDevice>()));
config->add_cinema(cinema_b);
auto crypt_cert = c->decryption_chain()->leaf();
- auto cinema_a = make_shared<Cinema>("Cinema A", vector<string>(), "");
+ auto cinema_a = make_shared<Cinema>("Cinema A", vector<string>(), "", dcp::UTCOffset{4, 30});
cinema_a_screen_1 = std::make_shared<dcpomatic::Screen>("Screen 1", "", crypt_cert, boost::none, vector<TrustedDevice>());
cinema_a->add_screen (cinema_a_screen_1);
cinema_a_screen_2 = std::make_shared<dcpomatic::Screen>("Screen 2", "", crypt_cert, boost::none, vector<TrustedDevice>());
cinema_a->add_screen (cinema_a_screen_2);
c->add_cinema (cinema_a);
- auto cinema_b = make_shared<Cinema>("Cinema B", vector<string>(), "");
+ auto cinema_b = make_shared<Cinema>("Cinema B", vector<string>(), "", dcp::UTCOffset{-1, 0});
cinema_b_screen_x = std::make_shared<dcpomatic::Screen>("Screen X", "", crypt_cert, boost::none, vector<TrustedDevice>());
cinema_b->add_screen (cinema_b_screen_x);
cinema_b_screen_y = std::make_shared<dcpomatic::Screen>("Screen Y", "", crypt_cert, boost::none, vector<TrustedDevice>());
auto sign_cert = c->signer_chain()->leaf();
dcp::LocalTime from = sign_cert.not_before();
- from.set_offset({ 4, 30 });
from.add_months (2);
dcp::LocalTime until = sign_cert.not_after();
- until.set_offset({ 4, 30 });
until.add_months (-2);
std::vector<KDMCertificatePeriod> period_checks;