X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Ftools%2Fdcpomatic.cc;h=001d1859eec93fd51219f229b02ee386ab333c89;hb=d4f13e8091c119622458a12be837d9e5138dbd81;hp=e9302c6a0a4a461b4b793f849f37c5b52b3908fc;hpb=809bcfd85fad2ef7d4131c054be4cccd5bcc9d05;p=dcpomatic.git diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index e9302c6a0..001d1859e 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -56,7 +56,7 @@ #include "wx/wx_util.h" #include "lib/analytics.h" #include "lib/audio_content.h" -#include "lib/check_content_change_job.h" +#include "lib/check_content_job.h" #include "lib/cinema.h" #include "lib/compose.hpp" #include "lib/config.h" @@ -78,6 +78,7 @@ #include "lib/kdm_with_metadata.h" #include "lib/log.h" #include "lib/make_dcp.h" +#include "lib/release_notes.h" #include "lib/screen.h" #include "lib/send_kdm_email_job.h" #include "lib/signal_manager.h" @@ -269,11 +270,58 @@ enum { }; +class LimitedFrameSplitter : public wxSplitterWindow +{ +public: + LimitedFrameSplitter(wxWindow* parent) + : wxSplitterWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER | wxSP_3DSASH | wxSP_LIVE_UPDATE) + { + /* This value doesn't really mean much but we just want to stop double-click on the + divider from shrinking the left panel. + */ + SetMinimumPaneSize(64); + + Bind(wxEVT_SIZE, boost::bind(&LimitedFrameSplitter::sized, this, _1)); + } + + bool OnSashPositionChange(int new_position) override + { + /* Try to stop the left bit of the splitter getting too small */ + auto const ok = new_position > _left_panel_minimum_size; + if (ok) { + Config::instance()->set_main_divider_sash_position(new_position); + } + return ok; + } + +private: + void sized(wxSizeEvent& ev) + { + if (GetSize().GetWidth() > _left_panel_minimum_size && GetSashPosition() < _left_panel_minimum_size) { + /* The window is now fairly big but the left panel is small; this happens when the DCP-o-matic window + * is shrunk and then made larger again. Try to set a sensible left panel size in this case. + */ + SetSashPosition(Config::instance()->main_divider_sash_position().get_value_or(_left_panel_minimum_size)); + } + + ev.Skip(); + } + + int const _left_panel_minimum_size = 200; +}; + + class DOMFrame : public wxFrame { public: explicit DOMFrame (wxString const& title) : wxFrame (nullptr, -1, title) + /* Use a panel as the only child of the Frame so that we avoid + the dark-grey background on Windows. + */ + , _splitter(new LimitedFrameSplitter(this)) + , _right_panel(new wxPanel(_splitter, wxID_ANY)) + , _film_viewer(_right_panel) { #if defined(DCPOMATIC_WINDOWS) if (Config::instance()->win32_console()) { @@ -347,33 +395,33 @@ public: Bind (wxEVT_CLOSE_WINDOW, boost::bind (&DOMFrame::close, this, _1)); Bind (wxEVT_SHOW, boost::bind (&DOMFrame::show, this, _1)); - /* Use a panel as the only child of the Frame so that we avoid - the dark-grey background on Windows. - */ - auto overall_panel = new wxPanel (this, wxID_ANY); + auto left_panel = new wxPanel(_splitter, wxID_ANY); + + _film_editor = new FilmEditor(left_panel, _film_viewer); + + auto left_sizer = new wxBoxSizer(wxHORIZONTAL); + left_sizer->Add(_film_editor, 1, wxEXPAND); - _film_viewer.reset (new FilmViewer (overall_panel)); - _controls = new StandardControls (overall_panel, _film_viewer, true); - _film_editor = new FilmEditor (overall_panel, _film_viewer); - auto job_manager_view = new JobManagerView (overall_panel, false); + left_panel->SetSizerAndFit(left_sizer); + + _controls = new StandardControls(_right_panel, _film_viewer, true); + auto job_manager_view = new JobManagerView(_right_panel, false); auto right_sizer = new wxBoxSizer (wxVERTICAL); - right_sizer->Add (_film_viewer->panel(), 2, wxEXPAND | wxALL, 6); + right_sizer->Add(_film_viewer.panel(), 2, wxEXPAND | wxALL, 6); right_sizer->Add (_controls, 0, wxEXPAND | wxALL, 6); right_sizer->Add (job_manager_view, 1, wxEXPAND | wxALL, 6); - wxBoxSizer* main_sizer = new wxBoxSizer (wxHORIZONTAL); - main_sizer->Add (_film_editor, 0, wxEXPAND | wxALL, 6); - main_sizer->Add (right_sizer, 1, wxEXPAND | wxALL, 6); + _right_panel->SetSizer(right_sizer); + + _splitter->SplitVertically(left_panel, _right_panel, Config::instance()->main_divider_sash_position().get_value_or(left_panel->GetSize().GetWidth() + 8)); set_menu_sensitivity (); _film_editor->content_panel()->SelectionChanged.connect (boost::bind (&DOMFrame::set_menu_sensitivity, this)); set_title (); - JobManager::instance()->ActiveJobsChanged.connect (boost::bind (&DOMFrame::set_menu_sensitivity, this)); - - overall_panel->SetSizer (main_sizer); + JobManager::instance()->ActiveJobsChanged.connect(boost::bind(&DOMFrame::active_jobs_changed, this)); UpdateChecker::instance()->StateChanged.connect(boost::bind(&DOMFrame::update_checker_state_changed, this)); @@ -458,7 +506,7 @@ public: set_film (film); - JobManager::instance()->add(shared_ptr(new CheckContentChangeJob(film))); + JobManager::instance()->add(make_shared(film)); } catch (FileNotFoundError& e) { auto const dir = e.file().parent_path(); @@ -480,8 +528,8 @@ public: void set_film (shared_ptr film) { _film = film; - _film_viewer->set_film (_film); - _film_editor->set_film (_film); + _film_viewer.set_film(_film); + _film_editor->set_film(_film); _controls->set_film (_film); if (_video_waveform_dialog) { _video_waveform_dialog->Destroy (); @@ -1041,7 +1089,7 @@ private: void view_closed_captions () { - _film_viewer->show_closed_captions (); + _film_viewer.show_closed_captions (); } void view_video_waveform () @@ -1199,6 +1247,15 @@ private: ev.Skip (); } + void active_jobs_changed() + { + /* ActiveJobsChanged can be called while JobManager holds a lock on its mutex, making + * the call to JobManager::get() in set_menu_sensitivity() deadlock unless we work around + * it by using an idle callback. This feels quite unpleasant. + */ + signal_manager->when_idle(boost::bind(&DOMFrame::set_menu_sensitivity, this)); + } + void set_menu_sensitivity () { auto jobs = JobManager::instance()->get (); @@ -1496,10 +1553,10 @@ private: void start_stop_pressed () { - if (_film_viewer->playing()) { - _film_viewer->stop(); + if (_film_viewer.playing()) { + _film_viewer.stop(); } else { - _film_viewer->start(); + _film_viewer.start(); } } @@ -1510,12 +1567,12 @@ private: void back_frame () { - _film_viewer->seek_by (-_film_viewer->one_video_frame(), true); + _film_viewer.seek_by(-_film_viewer.one_video_frame(), true); } void forward_frame () { - _film_viewer->seek_by (_film_viewer->one_video_frame(), true); + _film_viewer.seek_by(_film_viewer.one_video_frame(), true); } void analytics_message (string title, string html) @@ -1541,7 +1598,9 @@ private: } FilmEditor* _film_editor; - std::shared_ptr _film_viewer; + LimitedFrameSplitter* _splitter; + wxPanel* _right_panel; + FilmViewer _film_viewer; StandardControls* _controls; VideoWaveformDialog* _video_waveform_dialog = nullptr; SystemInformationDialog* _system_information_dialog = nullptr; @@ -1596,7 +1655,7 @@ private: try { wxInitAllImageHandlers (); - Config::FailedToLoad.connect (boost::bind (&App::config_failed_to_load, this)); + Config::FailedToLoad.connect(boost::bind(&App::config_failed_to_load, this, _1)); Config::Warning.connect (boost::bind (&App::config_warning, this, _1)); _splash = maybe_show_splash (); @@ -1686,6 +1745,14 @@ private: if (Config::instance()->check_for_updates ()) { UpdateChecker::instance()->run (); } + + auto release_notes = find_release_notes(gui_is_dark()); + if (release_notes) { + auto notes = new HTMLDialog(nullptr, _("Release notes"), std_to_wx(*release_notes), true); + notes->Centre(); + notes->ShowModal(); + notes->Destroy(); + } } catch (exception& e) { @@ -1810,9 +1877,9 @@ private: } } - void config_failed_to_load () + void config_failed_to_load (Config::LoadFailure what) { - message_dialog (_frame, _("The existing configuration failed to load. Default values will be used instead. These may take a short time to create.")); + report_config_load_failure(_frame, what); } void config_warning (string m)