From 0f42e807a707249cd1a60fa6e476cb47a4147c5a Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 9 May 2017 13:44:43 +0100 Subject: Basica save-as (duplicate) (#746). --- src/lib/film.cc | 14 +++- src/lib/film.h | 4 ++ src/tools/dcpomatic.cc | 134 +++++++++++++++++++++++++---------- src/wx/film_name_location_dialog.cc | 136 ++++++++++++++++++++++++++++++++++++ src/wx/film_name_location_dialog.h | 50 +++++++++++++ src/wx/new_film_dialog.cc | 102 --------------------------- src/wx/new_film_dialog.h | 49 ------------- src/wx/wscript | 2 +- 8 files changed, 298 insertions(+), 193 deletions(-) create mode 100644 src/wx/film_name_location_dialog.cc create mode 100644 src/wx/film_name_location_dialog.h delete mode 100644 src/wx/new_film_dialog.cc delete mode 100644 src/wx/new_film_dialog.h (limited to 'src') diff --git a/src/lib/film.cc b/src/lib/film.cc index 04ff00250..36221fb9a 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -98,6 +98,8 @@ using dcp::raw_convert; #define LOG_GENERAL(...) log()->log (String::compose (__VA_ARGS__), LogEntry::TYPE_GENERAL); #define LOG_GENERAL_NC(...) log()->log (__VA_ARGS__, LogEntry::TYPE_GENERAL); +string const Film::metadata_file = "metadata.xml"; + /* 5 -> 6 * AudioMapping XML changed. * 6 -> 7 @@ -399,7 +401,7 @@ Film::write_metadata () const DCPOMATIC_ASSERT (directory()); boost::filesystem::create_directories (directory().get()); shared_ptr doc = metadata (); - doc->write_to_file_formatted (file("metadata.xml").string ()); + doc->write_to_file_formatted (file(metadata_file).string ()); _dirty = false; } @@ -419,11 +421,11 @@ list Film::read_metadata (optional path) { if (!path) { - if (boost::filesystem::exists (file ("metadata")) && !boost::filesystem::exists (file ("metadata.xml"))) { + if (boost::filesystem::exists (file ("metadata")) && !boost::filesystem::exists (file (metadata_file))) { throw runtime_error (_("This film was created with an older version of DCP-o-matic, and unfortunately it cannot be loaded into this version. You will need to create a new Film, re-add your content and set it up again. Sorry!")); } - path = file ("metadata.xml"); + path = file (metadata_file); } cxml::Document f ("Metadata"); @@ -1575,3 +1577,9 @@ Film::speed_up_range (int dcp_frame_rate) const { return _playlist->speed_up_range (dcp_frame_rate); } + +void +Film::copy_from (shared_ptr film) +{ + read_metadata (film->file (metadata_file)); +} diff --git a/src/lib/film.h b/src/lib/film.h index fdd4674d5..ec64c3913 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -96,6 +96,8 @@ public: void write_template (boost::filesystem::path path) const; boost::shared_ptr metadata (bool with_content_paths = true) const; + void copy_from (boost::shared_ptr film); + std::string isdcf_name (bool if_created_now) const; std::string dcp_name (bool if_created_now = false) const; @@ -337,6 +339,8 @@ private: void maybe_add_content (boost::weak_ptr, boost::weak_ptr); void audio_analysis_finished (); + static std::string const metadata_file; + /** Log to write to */ boost::shared_ptr _log; boost::shared_ptr _playlist; diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index eca9d2689..6543db551 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -27,7 +27,7 @@ #include "wx/job_manager_view.h" #include "wx/config_dialog.h" #include "wx/wx_util.h" -#include "wx/new_film_dialog.h" +#include "wx/film_name_location_dialog.h" #include "wx/wx_signal_manager.h" #include "wx/about_dialog.h" #include "wx/kdm_dialog.h" @@ -103,10 +103,10 @@ using boost::dynamic_pointer_cast; using boost::optional; using dcp::raw_convert; -class FilmChangedDialog : public boost::noncopyable +class FilmChangedClosingDialog : public boost::noncopyable { public: - FilmChangedDialog (string name) + FilmChangedClosingDialog (string name) { _dialog = new wxMessageDialog ( 0, @@ -122,7 +122,40 @@ public: ); } - ~FilmChangedDialog () + ~FilmChangedClosingDialog () + { + _dialog->Destroy (); + } + + int run () + { + return _dialog->ShowModal (); + } + +private: + wxMessageDialog* _dialog; +}; + +class FilmChangedDuplicatingDialog : public boost::noncopyable +{ +public: + FilmChangedDuplicatingDialog (string name) + { + _dialog = new wxMessageDialog ( + 0, + wxString::Format (_("Save changes to film \"%s\" before duplicating?"), std_to_wx (name).data()), + /// TRANSLATORS: this is the heading for a dialog box, which tells the user that the current + /// project (Film) has been changed since it was last saved. + _("Film changed"), + wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxICON_QUESTION + ); + + _dialog->SetYesNoCancelLabels ( + _("Save film and duplicate"), _("Duplicate without saving film"), _("Don't duplicate") + ); + } + + ~FilmChangedDuplicatingDialog () { _dialog->Destroy (); } @@ -149,6 +182,8 @@ enum { ID_file_open, ID_file_save, ID_file_save_as_template, + ID_file_duplicate, + ID_file_duplicate_and_open, ID_file_history, /* Allow spare IDs after _history for the recent files list */ ID_content_scale_to_fit_width = 100, @@ -223,6 +258,8 @@ public: Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_open, this), ID_file_open); Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_save, this), ID_file_save); Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_save_as_template, this), ID_file_save_as_template); + Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_duplicate, this), ID_file_duplicate); + Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_duplicate_and_open, this), ID_file_duplicate_and_open); Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_history, this, _1), ID_file_history, ID_file_history + HISTORY_SIZE); Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_exit, this), wxID_EXIT); Bind (wxEVT_MENU, boost::bind (&DOMFrame::edit_preferences, this), wxID_PREFERENCES); @@ -295,8 +332,8 @@ public: if (template_name) { film->use_template (template_name.get()); } - film->write_metadata (); film->set_name (path.filename().generic_string()); + film->write_metadata (); set_film (film); } @@ -357,33 +394,11 @@ private: void file_new () { - NewFilmDialog* d = new NewFilmDialog (this); + FilmNameLocationDialog* d = new FilmNameLocationDialog (this, _("New Film"), true); int const r = d->ShowModal (); - if (r == wxID_OK) { - - if (boost::filesystem::is_directory (d->path()) && !boost::filesystem::is_empty(d->path())) { - if (!confirm_dialog ( - this, - std_to_wx ( - String::compose (wx_to_std (_("The directory %1 already exists and is not empty. " - "Are you sure you want to use it?")), - d->path().string().c_str()) - ) - )) { - return; - } - } else if (boost::filesystem::is_regular_file (d->path())) { - error_dialog ( - this, - String::compose (wx_to_std (_("%1 already exists as a file, so you cannot use it for a new film.")), d->path().c_str()) - ); - return; - } - - if (maybe_save_then_delete_film ()) { - new_film (d->path(), d->template_name()); - } + if (r == wxID_OK && d->check_path() && maybe_save_then_delete_film()) { + new_film (d->path(), d->template_name()); } d->Destroy (); @@ -408,7 +423,7 @@ private: } } - if (r == wxID_OK && maybe_save_then_delete_film()) { + if (r == wxID_OK && maybe_save_then_delete_film()) { load_film (wx_to_std (c->GetPath ())); } @@ -430,11 +445,42 @@ private: d->Destroy (); } + void file_duplicate () + { + FilmNameLocationDialog* d = new FilmNameLocationDialog (this, _("Duplicate Film"), false); + int const r = d->ShowModal (); + + if (r == wxID_OK && d->check_path() && maybe_save_film()) { + shared_ptr film (new Film (d->path())); + film->copy_from (_film); + film->set_name (d->path().filename().generic_string()); + film->write_metadata (); + } + + d->Destroy (); + } + + void file_duplicate_and_open () + { + FilmNameLocationDialog* d = new FilmNameLocationDialog (this, _("Duplicate Film"), false); + int const r = d->ShowModal (); + + if (r == wxID_OK && d->check_path() && maybe_save_film()) { + shared_ptr film (new Film (d->path())); + film->copy_from (_film); + film->set_name (d->path().filename().generic_string()); + film->write_metadata (); + set_film (film); + } + + d->Destroy (); + } + void file_history (wxCommandEvent& event) { vector history = Config::instance()->history (); int n = event.GetId() - ID_file_history; - if (n >= 0 && n < static_cast (history.size ()) && maybe_save_then_delete_film()) { + if (n >= 0 && n < static_cast (history.size ()) && maybe_save_then_delete_film()) { load_film (history[n]); } } @@ -792,7 +838,7 @@ private: if (_film && _film->dirty ()) { - FilmChangedDialog* dialog = new FilmChangedDialog (_film->name ()); + FilmChangedClosingDialog* dialog = new FilmChangedClosingDialog (_film->name ()); int const r = dialog->run (); delete dialog; @@ -858,29 +904,39 @@ private: /** @return true if the operation that called this method * should continue, false to abort it. */ - bool maybe_save_then_delete_film () + template + bool maybe_save_film () { if (!_film) { return true; } if (_film->dirty ()) { - FilmChangedDialog d (_film->name ()); + T d (_film->name ()); switch (d.run ()) { case wxID_NO: - break; + return true; case wxID_YES: _film->write_metadata (); - break; + return true; case wxID_CANCEL: return false; } } - _film.reset (); return true; } + template + bool maybe_save_then_delete_film () + { + bool const r = maybe_save_film (); + if (r) { + _film.reset (); + } + return r; + } + void add_item (wxMenu* menu, wxString text, int id, int sens) { wxMenuItem* item = menu->Append (id, text); @@ -896,6 +952,8 @@ private: add_item (_file_menu, _("&Save\tCtrl-S"), ID_file_save, NEEDS_FILM); _file_menu->AppendSeparator (); add_item (_file_menu, _("Save as &template..."), ID_file_save_as_template, NEEDS_FILM); + add_item (_file_menu, _("Duplicate..."), ID_file_duplicate, NEEDS_FILM); + add_item (_file_menu, _("Duplicate and open..."), ID_file_duplicate_and_open, NEEDS_FILM); _history_position = _file_menu->GetMenuItems().GetCount(); diff --git a/src/wx/film_name_location_dialog.cc b/src/wx/film_name_location_dialog.cc new file mode 100644 index 000000000..d91171acb --- /dev/null +++ b/src/wx/film_name_location_dialog.cc @@ -0,0 +1,136 @@ +/* + Copyright (C) 2012-2017 Carl Hetherington + + 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 . + +*/ + +#include "wx_util.h" +#include "film_name_location_dialog.h" +#ifdef DCPOMATIC_USE_OWN_PICKER +#include "dir_picker_ctrl.h" +#endif +#include "lib/config.h" +#include "lib/compose.hpp" +#include +#include +#include + +using namespace std; +using namespace boost; + +boost::optional FilmNameLocationDialog::_directory; + +FilmNameLocationDialog::FilmNameLocationDialog (wxWindow* parent, wxString title, bool offer_templates) + : TableDialog (parent, title, 2, 1, true) +{ + add (_("Film name"), true); + _name = add (new wxTextCtrl (this, wxID_ANY)); + + add (_("Create in folder"), true); + +#ifdef DCPOMATIC_USE_OWN_PICKER + _folder = new DirPickerCtrl (this); +#else + _folder = new wxDirPickerCtrl (this, wxID_ANY, wxEmptyString, wxDirSelectorPromptStr, wxDefaultPosition, wxSize (300, -1)); +#endif + + if (!_directory) { + _directory = Config::instance()->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())); + } + + _folder->SetPath (std_to_wx (_directory.get().string())); + add (_folder); + + if (offer_templates) { + _use_template = new wxCheckBox (this, wxID_ANY, _("From template")); + add (_use_template); + _template_name = new wxChoice (this, wxID_ANY); + add (_template_name); + } + + _name->SetFocus (); + + if (offer_templates) { + _template_name->Enable (false); + + BOOST_FOREACH (string i, Config::instance()->templates ()) { + _template_name->Append (std_to_wx (i)); + } + + _use_template->Bind (wxEVT_CHECKBOX, bind (&FilmNameLocationDialog::use_template_clicked, this)); + } + + layout (); +} + +void +FilmNameLocationDialog::use_template_clicked () +{ + _template_name->Enable (_use_template->GetValue ()); +} + +FilmNameLocationDialog::~FilmNameLocationDialog () +{ + _directory = wx_to_std (_folder->GetPath ()); +} + +boost::filesystem::path +FilmNameLocationDialog::path () const +{ + filesystem::path p; + p /= wx_to_std (_folder->GetPath ()); + p /= wx_to_std (_name->GetValue ()); + return p; +} + +optional +FilmNameLocationDialog::template_name () const +{ + if (!_use_template->GetValue() || _template_name->GetSelection() == -1) { + return optional (); + } + + return wx_to_std (_template_name->GetString(_template_name->GetSelection())); +} + +/** Check the path that is in our controls and offer confirmations or errors as required. + * @return true if the path should be used. + */ +bool +FilmNameLocationDialog::check_path () +{ + if (boost::filesystem::is_directory (path()) && !boost::filesystem::is_empty(path())) { + if (!confirm_dialog ( + this, + std_to_wx ( + String::compose (wx_to_std (_("The directory %1 already exists and is not empty. " + "Are you sure you want to use it?")), + path().string().c_str()) + ) + )) { + return false; + } + } else if (boost::filesystem::is_regular_file (path())) { + error_dialog ( + this, + String::compose (wx_to_std (_("%1 already exists as a file, so you cannot use it for a film.")), path().c_str()) + ); + return false; + } + + return true; +} diff --git a/src/wx/film_name_location_dialog.h b/src/wx/film_name_location_dialog.h new file mode 100644 index 000000000..cfa296701 --- /dev/null +++ b/src/wx/film_name_location_dialog.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2012-2014 Carl Hetherington + + 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 . + +*/ + +#include +#include +#include "wx_util.h" +#include "table_dialog.h" + +class DirPickerCtrl; + +class FilmNameLocationDialog : public TableDialog +{ +public: + FilmNameLocationDialog (wxWindow *, wxString title, bool offer_templates); + ~FilmNameLocationDialog (); + + boost::filesystem::path path () const; + bool check_path (); + boost::optional template_name () const; + +private: + void use_template_clicked (); + + wxTextCtrl* _name; +#ifdef DCPOMATIC_USE_OWN_PICKER + DirPickerCtrl* _folder; +#else + wxDirPickerCtrl* _folder; +#endif + wxCheckBox* _use_template; + wxChoice* _template_name; + static boost::optional _directory; +}; diff --git a/src/wx/new_film_dialog.cc b/src/wx/new_film_dialog.cc deleted file mode 100644 index ef072c9fc..000000000 --- a/src/wx/new_film_dialog.cc +++ /dev/null @@ -1,102 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - 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 . - -*/ - -#include "lib/config.h" -#include "new_film_dialog.h" -#include "wx_util.h" -#ifdef DCPOMATIC_USE_OWN_PICKER -#include "dir_picker_ctrl.h" -#endif -#include -#include -#include - -using namespace std; -using namespace boost; - -boost::optional NewFilmDialog::_directory; - -NewFilmDialog::NewFilmDialog (wxWindow* parent) - : TableDialog (parent, _("New Film"), 2, 1, true) -{ - add (_("Film name"), true); - _name = add (new wxTextCtrl (this, wxID_ANY)); - - add (_("Create in folder"), true); - -#ifdef DCPOMATIC_USE_OWN_PICKER - _folder = new DirPickerCtrl (this); -#else - _folder = new wxDirPickerCtrl (this, wxID_ANY, wxEmptyString, wxDirSelectorPromptStr, wxDefaultPosition, wxSize (300, -1)); -#endif - - if (!_directory) { - _directory = Config::instance()->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())); - } - - _folder->SetPath (std_to_wx (_directory.get().string())); - add (_folder); - - _use_template = new wxCheckBox (this, wxID_ANY, _("From template")); - add (_use_template); - _template_name = new wxChoice (this, wxID_ANY); - add (_template_name); - - _name->SetFocus (); - _template_name->Enable (false); - - BOOST_FOREACH (string i, Config::instance()->templates ()) { - _template_name->Append (std_to_wx (i)); - } - - _use_template->Bind (wxEVT_CHECKBOX, bind (&NewFilmDialog::use_template_clicked, this)); - - layout (); -} - -void -NewFilmDialog::use_template_clicked () -{ - _template_name->Enable (_use_template->GetValue ()); -} - -NewFilmDialog::~NewFilmDialog () -{ - _directory = wx_to_std (_folder->GetPath ()); -} - -boost::filesystem::path -NewFilmDialog::path () const -{ - filesystem::path p; - p /= wx_to_std (_folder->GetPath ()); - p /= wx_to_std (_name->GetValue ()); - return p; -} - -optional -NewFilmDialog::template_name () const -{ - if (!_use_template->GetValue() || _template_name->GetSelection() == -1) { - return optional (); - } - - return wx_to_std (_template_name->GetString(_template_name->GetSelection())); -} diff --git a/src/wx/new_film_dialog.h b/src/wx/new_film_dialog.h deleted file mode 100644 index 81dd29fea..000000000 --- a/src/wx/new_film_dialog.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright (C) 2012-2014 Carl Hetherington - - 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 . - -*/ - -#include -#include -#include "wx_util.h" -#include "table_dialog.h" - -class DirPickerCtrl; - -class NewFilmDialog : public TableDialog -{ -public: - NewFilmDialog (wxWindow *); - ~NewFilmDialog (); - - boost::filesystem::path path () const; - boost::optional template_name () const; - -private: - void use_template_clicked (); - - wxTextCtrl* _name; -#ifdef DCPOMATIC_USE_OWN_PICKER - DirPickerCtrl* _folder; -#else - wxDirPickerCtrl* _folder; -#endif - wxCheckBox* _use_template; - wxChoice* _template_name; - static boost::optional _directory; -}; diff --git a/src/wx/wscript b/src/wx/wscript index 332a04ac5..8297f37c9 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -51,6 +51,7 @@ sources = """ download_certificate_panel.cc file_picker_ctrl.cc film_editor.cc + film_name_location_dialog.cc film_viewer.cc filter_dialog.cc filter_editor.cc @@ -70,7 +71,6 @@ sources = """ move_to_dialog.cc nag_dialog.cc name_format_editor.cc - new_film_dialog.cc normal_job_view.cc playhead_to_timecode_dialog.cc playhead_to_frame_dialog.cc -- cgit v1.2.3