summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2017-05-09 13:44:43 +0100
committerCarl Hetherington <cth@carlh.net>2017-05-09 13:44:43 +0100
commit0f42e807a707249cd1a60fa6e476cb47a4147c5a (patch)
tree62307e5723e9787501ea05b76f5ded2b237c7075 /src
parent89ae13638097f259f3e50b4b61068dd23451107d (diff)
Basica save-as (duplicate) (#746).
Diffstat (limited to 'src')
-rw-r--r--src/lib/film.cc14
-rw-r--r--src/lib/film.h4
-rw-r--r--src/tools/dcpomatic.cc134
-rw-r--r--src/wx/film_name_location_dialog.cc (renamed from src/wx/new_film_dialog.cc)72
-rw-r--r--src/wx/film_name_location_dialog.h (renamed from src/wx/new_film_dialog.h)7
-rw-r--r--src/wx/wscript2
6 files changed, 169 insertions, 64 deletions
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<xmlpp::Document> 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<string>
Film::read_metadata (optional<boost::filesystem::path> 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<const Film> 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<xmlpp::Document> metadata (bool with_content_paths = true) const;
+ void copy_from (boost::shared_ptr<const Film> 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<Job>, boost::weak_ptr<Content>);
void audio_analysis_finished ();
+ static std::string const metadata_file;
+
/** Log to write to */
boost::shared_ptr<Log> _log;
boost::shared_ptr<Playlist> _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<FilmChangedClosingDialog>()) {
+ 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<FilmChangedClosingDialog>()) {
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<FilmChangedDuplicatingDialog>()) {
+ shared_ptr<Film> 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<FilmChangedDuplicatingDialog>()) {
+ shared_ptr<Film> 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<boost::filesystem::path> history = Config::instance()->history ();
int n = event.GetId() - ID_file_history;
- if (n >= 0 && n < static_cast<int> (history.size ()) && maybe_save_then_delete_film()) {
+ if (n >= 0 && n < static_cast<int> (history.size ()) && maybe_save_then_delete_film<FilmChangedClosingDialog>()) {
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 <class T>
+ 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 <class T>
+ bool maybe_save_then_delete_film ()
+ {
+ bool const r = maybe_save_film<T> ();
+ 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/new_film_dialog.cc b/src/wx/film_name_location_dialog.cc
index ef072c9fc..d91171acb 100644
--- a/src/wx/new_film_dialog.cc
+++ b/src/wx/film_name_location_dialog.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
@@ -18,12 +18,13 @@
*/
-#include "lib/config.h"
-#include "new_film_dialog.h"
#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 <wx/stdpaths.h>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
@@ -31,10 +32,10 @@
using namespace std;
using namespace boost;
-boost::optional<boost::filesystem::path> NewFilmDialog::_directory;
+boost::optional<boost::filesystem::path> FilmNameLocationDialog::_directory;
-NewFilmDialog::NewFilmDialog (wxWindow* parent)
- : TableDialog (parent, _("New Film"), 2, 1, true)
+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));
@@ -54,36 +55,41 @@ NewFilmDialog::NewFilmDialog (wxWindow* parent)
_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);
+ 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 ();
- _template_name->Enable (false);
- BOOST_FOREACH (string i, Config::instance()->templates ()) {
- _template_name->Append (std_to_wx (i));
- }
+ 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 (&NewFilmDialog::use_template_clicked, this));
+ _use_template->Bind (wxEVT_CHECKBOX, bind (&FilmNameLocationDialog::use_template_clicked, this));
+ }
layout ();
}
void
-NewFilmDialog::use_template_clicked ()
+FilmNameLocationDialog::use_template_clicked ()
{
_template_name->Enable (_use_template->GetValue ());
}
-NewFilmDialog::~NewFilmDialog ()
+FilmNameLocationDialog::~FilmNameLocationDialog ()
{
_directory = wx_to_std (_folder->GetPath ());
}
boost::filesystem::path
-NewFilmDialog::path () const
+FilmNameLocationDialog::path () const
{
filesystem::path p;
p /= wx_to_std (_folder->GetPath ());
@@ -92,7 +98,7 @@ NewFilmDialog::path () const
}
optional<string>
-NewFilmDialog::template_name () const
+FilmNameLocationDialog::template_name () const
{
if (!_use_template->GetValue() || _template_name->GetSelection() == -1) {
return optional<string> ();
@@ -100,3 +106,31 @@ NewFilmDialog::template_name () const
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/new_film_dialog.h b/src/wx/film_name_location_dialog.h
index 81dd29fea..cfa296701 100644
--- a/src/wx/new_film_dialog.h
+++ b/src/wx/film_name_location_dialog.h
@@ -25,13 +25,14 @@
class DirPickerCtrl;
-class NewFilmDialog : public TableDialog
+class FilmNameLocationDialog : public TableDialog
{
public:
- NewFilmDialog (wxWindow *);
- ~NewFilmDialog ();
+ FilmNameLocationDialog (wxWindow *, wxString title, bool offer_templates);
+ ~FilmNameLocationDialog ();
boost::filesystem::path path () const;
+ bool check_path ();
boost::optional<std::string> template_name () const;
private:
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