+2016-07-29 c.hetherington <cth@carlh.net>
+
+ * Allow configuration of KDM filename format.
+
2016-07-28 Carl Hetherington <cth@carlh.net>
* Version 2.9.7 released.
#include "emailer.h"
#include "compose.hpp"
#include "log.h"
+#include "kdm_name_format.h"
#include <zip.h>
#include <boost/foreach.hpp>
using boost::shared_ptr;
void
-CinemaKDMs::make_zip_file (string film_name, boost::filesystem::path zip_file) const
+CinemaKDMs::make_zip_file (boost::filesystem::path zip_file, KDMNameFormat name_format, NameFormat::Map name_values) const
{
int error;
struct zip* zip = zip_open (zip_file.string().c_str(), ZIP_CREATE | ZIP_EXCL, &error);
list<shared_ptr<string> > kdm_strings;
+ name_values["cinema"] = cinema->name;
+
BOOST_FOREACH (ScreenKDM const & i, screen_kdms) {
shared_ptr<string> kdm (new string (i.kdm.as_xml ()));
kdm_strings.push_back (kdm);
throw runtime_error ("could not create ZIP source");
}
- if (zip_add (zip, i.filename(film_name).c_str(), source) == -1) {
+ name_values["screen"] = i.screen->name;
+ string const name = name_format.get(name_values) + ".xml";
+ if (zip_add (zip, name.c_str(), source) == -1) {
throw runtime_error ("failed to add KDM to ZIP archive");
}
}
}
}
+/** Collect a list of ScreenKDMs into a list of CinemaKDMs so that each
+ * CinemaKDM contains the KDMs for its cinema.
+ */
list<CinemaKDMs>
CinemaKDMs::collect (list<ScreenKDM> screen_kdms)
{
return cinema_kdms;
}
+/** Write one ZIP file per cinema into a directory */
void
-CinemaKDMs::write_zip_files (string film_name, list<CinemaKDMs> cinema_kdms, boost::filesystem::path directory)
+CinemaKDMs::write_zip_files (
+ list<CinemaKDMs> cinema_kdms,
+ boost::filesystem::path directory,
+ KDMNameFormat name_format,
+ NameFormat::Map name_values
+ )
{
+ /* No specific screen */
+ name_values["screen"] = "";
+
BOOST_FOREACH (CinemaKDMs const & i, cinema_kdms) {
boost::filesystem::path path = directory;
- path /= tidy_for_filename (i.cinema->name) + ".zip";
- i.make_zip_file (film_name, path);
+ name_values["cinema"] = i.cinema->name;
+ path /= name_format.get(name_values) + ".zip";
+ i.make_zip_file (path, name_format, name_values);
}
}
-/** @param log Log to write email session transcript to, or 0 */
-/* XXX: should probably get from/to from the KDMs themselves */
+/** Email one ZIP file per cinema to the cinema.
+ * @param log Log to write email session transcript to, or 0.
+ */
void
CinemaKDMs::email (
- string film_name, string cpl_name, list<CinemaKDMs> cinema_kdms, dcp::LocalTime from, dcp::LocalTime to, shared_ptr<Log> log
+ list<CinemaKDMs> cinema_kdms,
+ KDMNameFormat name_format,
+ NameFormat::Map name_values,
+ string cpl_name,
+ shared_ptr<Log> log
)
{
Config* config = Config::instance ();
throw NetworkError (_("No mail server configured in preferences"));
}
+ /* No specific screen */
+ name_values["screen"] = "";
+
BOOST_FOREACH (CinemaKDMs const & i, cinema_kdms) {
+ name_values["cinema"] = i.cinema->name;
+
boost::filesystem::path zip_file = boost::filesystem::temp_directory_path ();
zip_file /= boost::filesystem::unique_path().string() + ".zip";
- i.make_zip_file (film_name, zip_file);
+ i.make_zip_file (zip_file, name_format, name_values);
string subject = config->kdm_subject();
- locked_stringstream start;
- start << from.date() << " " << from.time_of_day();
- locked_stringstream end;
- end << to.date() << " " << to.time_of_day();
boost::algorithm::replace_all (subject, "$CPL_NAME", cpl_name);
- boost::algorithm::replace_all (subject, "$START_TIME", start.str ());
- boost::algorithm::replace_all (subject, "$END_TIME", end.str ());
+ boost::algorithm::replace_all (subject, "$START_TIME", name_values["from"]);
+ boost::algorithm::replace_all (subject, "$END_TIME", name_values["to"]);
boost::algorithm::replace_all (subject, "$CINEMA_NAME", i.cinema->name);
string body = config->kdm_email().c_str();
boost::algorithm::replace_all (body, "$CPL_NAME", cpl_name);
- boost::algorithm::replace_all (body, "$START_TIME", start.str ());
- boost::algorithm::replace_all (body, "$END_TIME", end.str ());
+ boost::algorithm::replace_all (body, "$START_TIME", name_values["from"]);
+ boost::algorithm::replace_all (body, "$END_TIME", name_values["to"]);
boost::algorithm::replace_all (body, "$CINEMA_NAME", i.cinema->name);
locked_stringstream screens;
email.add_bcc (config->kdm_bcc ());
}
- string const name = tidy_for_filename(i.cinema->name) + "_" + tidy_for_filename(film_name) + ".zip";
- email.add_attachment (zip_file, name, "application/zip");
+ email.add_attachment (zip_file, name_format.get(name_values) + ".zip", "application/zip");
Config* c = Config::instance ();
class CinemaKDMs
{
public:
- void make_zip_file (std::string film_name, boost::filesystem::path zip_file) const;
+ void make_zip_file (boost::filesystem::path zip_file, KDMNameFormat name_format, NameFormat::Map name_values) const;
static std::list<CinemaKDMs> collect (std::list<ScreenKDM> kdms);
- static void write_zip_files (std::string film_name, std::list<CinemaKDMs> cinema_kdms, boost::filesystem::path directory);
+
+ static void write_zip_files (
+ std::list<CinemaKDMs> cinema_kdms,
+ boost::filesystem::path directory,
+ KDMNameFormat name_format,
+ NameFormat::Map name_values
+ );
+
static void email (
- std::string film_name,
- std::string cpl_name,
std::list<CinemaKDMs> cinema_kdms,
- dcp::LocalTime from,
- dcp::LocalTime to,
+ KDMNameFormat name_format,
+ NameFormat::Map name_values,
+ std::string cpl_name,
boost::shared_ptr<Log> log
);
#include "util.h"
#include "cross.h"
#include "raw_convert.h"
+#include "kdm_name_format.h"
#include <dcp/colour_matrix.h>
#include <dcp/certificate_chain.h>
#include <libcxml/cxml.h>
#endif
_cinemas_file = path ("cinemas.xml");
_show_hints_before_make_dcp = true;
+ _kdm_filename_format = KDMNameFormat ("KDM %f %c %s");
_allowed_dcp_frame_rates.clear ();
_allowed_dcp_frame_rates.push_back (24);
_cinemas_file = f.optional_string_child("CinemasFile").get_value_or (path ("cinemas.xml").string ());
_show_hints_before_make_dcp = f.optional_bool_child("ShowHintsBeforeMakeDCP").get_value_or (true);
+ _kdm_filename_format = KDMNameFormat (f.optional_string_child("KDMFilenameFormat").get_value_or ("KDM %f %c %s"));
/* Replace any cinemas from config.xml with those from the configured file */
if (boost::filesystem::exists (_cinemas_file)) {
root->add_child("CinemasFile")->add_child_text (_cinemas_file.string());
root->add_child("ShowHintsBeforeMakeDCP")->add_child_text (_show_hints_before_make_dcp ? "1" : "0");
+ root->add_child("KDMFilenameFormat")->add_child_text (_kdm_filename_format.specification ());
try {
doc.write_to_file_formatted (path("config.xml").string ());
/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
#define DCPOMATIC_CONFIG_H
#include "isdcf_metadata.h"
+#include "kdm_name_format.h"
#include "types.h"
#include <dcp/certificate_chain.h>
#include <dcp/encrypted_kdm.h>
return _show_hints_before_make_dcp;
}
+ KDMNameFormat kdm_filename_format () const {
+ return _kdm_filename_format;
+ }
+
/** @param n New number of local encoding threads */
void set_num_local_encoding_threads (int n) {
maybe_set (_num_local_encoding_threads, n);
maybe_set (_show_hints_before_make_dcp, s);
}
+ void set_kdm_filename_format (KDMNameFormat n) {
+ maybe_set (_kdm_filename_format, n);
+ }
+
void clear_history () {
_history.clear ();
changed ();
std::vector<dcp::EncryptedKDM> _dkdms;
boost::filesystem::path _cinemas_file;
bool _show_hints_before_make_dcp;
+ KDMNameFormat _kdm_filename_format;
/** Singleton instance, or 0 */
static Config* _instance;
--- /dev/null
+/*
+ Copyright (C) 2016 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 "kdm_name_format.h"
+
+using std::string;
+
+KDMNameFormat::KDMNameFormat (string specification)
+ : NameFormat (specification)
+{
+ add ("film_name", 'f', "film name");
+ add ("cinema", 'c', "cinema");
+ add ("screen", 's', "screen");
+ add ("from", 'b', "from date/time");
+ add ("to", 'e', "to date/time");
+}
--- /dev/null
+/*
+ Copyright (C) 2016 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/>.
+
+*/
+
+#ifndef DCPOMATIC_KDM_NAME_FORMAT
+#define DCPOMATIC_KDM_NAME_FORMAT
+
+#include "name_format.h"
+
+class KDMNameFormat : public NameFormat
+{
+public:
+ KDMNameFormat () {}
+ KDMNameFormat (std::string specification);
+};
+
+#endif
--- /dev/null
+/*
+ Copyright (C) 2016 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 "name_format.h"
+#include <boost/optional.hpp>
+#include <boost/foreach.hpp>
+
+using std::string;
+using std::map;
+using boost::optional;
+
+static char
+filter (char c)
+{
+ if (c == '/' || c == ':') {
+ c = '-';
+ } else if (c == ' ') {
+ c = '_';
+ }
+
+ return c;
+}
+
+static string
+filter (string c)
+{
+ string o;
+
+ for (size_t i = 0; i < c.length(); ++i) {
+ o += filter (c[i]);
+ }
+
+ return o;
+}
+
+void
+NameFormat::add (string name, char placeholder, string title)
+{
+ _components.push_back (Component (name, placeholder, title));
+}
+
+optional<NameFormat::Component>
+NameFormat::component_by_placeholder (char p) const
+{
+ BOOST_FOREACH (Component const & i, _components) {
+ if (i.placeholder == p) {
+ return i;
+ }
+ }
+
+ return optional<Component> ();
+}
+
+string
+NameFormat::get (Map values) const
+{
+ string result;
+ for (size_t i = 0; i < _specification.length(); ++i) {
+ bool done = false;
+ if (_specification[i] == '%' && (i < _specification.length() - 1)) {
+ optional<Component> c = component_by_placeholder (_specification[i + 1]);
+ if (c) {
+ result += filter (values[c->name]);
+ ++i;
+ done = true;
+ }
+ }
+
+ if (!done) {
+ result += filter (_specification[i]);
+ }
+ }
+
+ return result;
+}
+
+bool
+operator== (NameFormat const & a, NameFormat const & b)
+{
+ return a.specification() == b.specification();
+}
--- /dev/null
+/*
+ Copyright (C) 2016 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/>.
+
+*/
+
+#ifndef DCPOMATIC_NAME_FORMAT
+#define DCPOMATIC_NAME_FORMAT
+
+#include <boost/optional.hpp>
+#include <map>
+#include <list>
+
+class NameFormat
+{
+public:
+ struct Component
+ {
+ Component (std::string name_, char placeholder_, std::string title_)
+ : name (name_)
+ , placeholder (placeholder_)
+ , title (title_)
+ {}
+
+ std::string name;
+ char placeholder;
+ std::string title;
+ };
+
+ std::list<Component> components () const {
+ return _components;
+ }
+
+ std::string specification () const {
+ return _specification;
+ }
+
+ void set_specification (std::string specification) {
+ _specification = specification;
+ }
+
+ typedef std::map<std::string, std::string> Map;
+
+ std::string get (Map) const;
+
+protected:
+ NameFormat () {}
+
+ NameFormat (std::string specification)
+ : _specification (specification)
+ {}
+
+ void add (std::string name, char placeholder, std::string title);
+
+private:
+ boost::optional<NameFormat::Component> component_by_placeholder (char p) const;
+
+ std::list<Component> _components;
+ std::string _specification;
+};
+
+extern bool operator== (NameFormat const & a, NameFormat const & b);
+
+#endif
return a.screen == b.screen && a.kdm == b.kdm;
}
-string
-ScreenKDM::filename (string film_name) const
-{
- return tidy_for_filename (film_name) + "_" + tidy_for_filename (screen->cinema->name) + "_" + tidy_for_filename (screen->name) + ".kdm.xml";
-}
-
void
-ScreenKDM::write_files (string film_name, list<ScreenKDM> screen_kdms, boost::filesystem::path directory)
+ScreenKDM::write_files (list<ScreenKDM> screen_kdms, boost::filesystem::path directory, KDMNameFormat name_format, NameFormat::Map name_values)
{
/* Write KDMs to the specified directory */
BOOST_FOREACH (ScreenKDM const & i, screen_kdms) {
- boost::filesystem::path out = directory / i.filename(film_name);
+ name_values["cinema"] = i.screen->cinema->name;
+ name_values["screen"] = i.screen->name;
+ boost::filesystem::path out = directory / (name_format.get(name_values) + ".xml");
i.kdm.as_xml (out);
}
}
#ifndef DCPOMATIC_SCREEN_KDM_H
#define DCPOMATIC_SCREEN_KDM_H
+#include "kdm_name_format.h"
#include <dcp/encrypted_kdm.h>
#include <boost/shared_ptr.hpp>
, kdm (k)
{}
- std::string filename (std::string film_name) const;
-
- static void write_files (std::string film_name, std::list<ScreenKDM> screen_kdms, boost::filesystem::path directory);
+ static void write_files (
+ std::list<ScreenKDM> screen_kdms, boost::filesystem::path directory,
+ KDMNameFormat name_format, NameFormat::Map name_values
+ );
boost::shared_ptr<Screen> screen;
dcp::EncryptedKDM kdm;
/** @param log Log to write to, or 0 */
SendKDMEmailJob::SendKDMEmailJob (
- string film_name,
- string cpl_name,
- boost::posix_time::ptime from,
- boost::posix_time::ptime to,
list<CinemaKDMs> cinema_kdms,
+ KDMNameFormat name_format,
+ NameFormat::Map name_values,
+ string cpl_name,
shared_ptr<Log> log
)
: Job (shared_ptr<Film>())
- , _film_name (film_name)
+ , _name_format (name_format)
+ , _name_values (name_values)
, _cpl_name (cpl_name)
- , _from (from)
- , _to (to)
, _cinema_kdms (cinema_kdms)
, _log (log)
{
string
SendKDMEmailJob::name () const
{
- if (_film_name.empty ()) {
+ NameFormat::Map::const_iterator i = _name_values.find ("film_name");
+ if (i == _name_values.end() || i->second.empty ()) {
return _("Email KDMs");
}
- return String::compose (_("Email KDMs for %1"), _film_name);
+ return String::compose (_("Email KDMs for %1"), i->second);
}
string
SendKDMEmailJob::run ()
{
set_progress_unknown ();
- CinemaKDMs::email (_film_name, _cpl_name, _cinema_kdms, dcp::LocalTime (_from), dcp::LocalTime (_to), _log);
+ CinemaKDMs::email (_cinema_kdms, _name_format, _name_values, _cpl_name, _log);
set_progress (1);
set_state (FINISHED_OK);
}
*/
#include "job.h"
+#include "kdm_name_format.h"
#include <dcp/types.h>
#include <boost/filesystem.hpp>
{
public:
SendKDMEmailJob (
- std::string film_name,
- std::string cpl_name,
- boost::posix_time::ptime from,
- boost::posix_time::ptime to,
std::list<CinemaKDMs> cinema_kdms,
+ KDMNameFormat name_format,
+ NameFormat::Map name_values,
+ std::string cpl_name,
boost::shared_ptr<Log> log
);
void run ();
private:
- std::string _film_name;
+ KDMNameFormat _name_format;
+ NameFormat::Map _name_values;
std::string _cpl_name;
- boost::posix_time::ptime _from;
- boost::posix_time::ptime _to;
std::list<CinemaKDMs> _cinema_kdms;
boost::shared_ptr<Log> _log;
};
job.cc
job_manager.cc
json_server.cc
+ kdm_name_format.cc
log.cc
log_entry.cc
magick_image_proxy.cc
mid_side_decoder.cc
+ name_format.cc
overlaps.cc
player.cc
player_subtitles.cc
try {
list<ScreenKDM> screen_kdms = _film->make_kdms (d->screens(), d->cpl(), d->from(), d->until(), d->formulation());
+
+ NameFormat::Map name_values;
+ name_values["film_name"] = _film->name();
+ name_values["from"] = dcp::LocalTime(d->from()).date() + " " + dcp::LocalTime(d->from()).time_of_day();
+ name_values["to"] = dcp::LocalTime(d->until()).date() + " " + dcp::LocalTime(d->until()).time_of_day();
+
if (d->write_to ()) {
ScreenKDM::write_files (
- _film->name(),
screen_kdms,
- d->directory()
+ d->directory(),
+ d->name_format(),
+ name_values
);
} else {
JobManager::instance()->add (
shared_ptr<Job> (new SendKDMEmailJob (
- _film->name(),
- _film->dcp_name(),
- d->from(),
- d->until(),
CinemaKDMs::collect (screen_kdms),
+ d->name_format(),
+ name_values,
+ _film->dcp_name(),
_film->log()
))
);
screen_kdms.push_back (ScreenKDM (i, kdm.encrypt (signer, i->recipient.get(), i->trusted_devices, _output->formulation())));
}
+ NameFormat::Map name_values;
+ name_values["film_name"] = decrypted.content_title_text();
+ name_values["from"] = dcp::LocalTime(_timing->from()).date() + " " + dcp::LocalTime(_timing->from()).time_of_day();
+ name_values["to"] = dcp::LocalTime(_timing->until()).date() + " " + dcp::LocalTime(_timing->until()).time_of_day();
+
if (_output->write_to()) {
- ScreenKDM::write_files (decrypted.content_title_text(), screen_kdms, _output->directory());
+ ScreenKDM::write_files (screen_kdms, _output->directory(), _output->name_format(), name_values);
/* XXX: proper plural form support in wxWidgets? */
wxString s = screen_kdms.size() == 1 ? _("%d KDM written to %s") : _("%d KDMs written to %s");
message_dialog (
film_name = decrypted.content_title_text ();
}
shared_ptr<Job> job (new SendKDMEmailJob (
- film_name,
- decrypted.content_title_text(),
- _timing->from(), _timing->until(),
CinemaKDMs::collect (screen_kdms),
+ _output->name_format(),
+ name_values,
+ decrypted.content_title_text(),
shared_ptr<Log> ()
));
output = ".";
}
+ NameFormat::Map values;
+ values["film_name"] = film->name();
+ values["from"] = dcp::LocalTime(valid_from.get()).date() + " " + dcp::LocalTime(valid_from.get()).time_of_day();
+ values["to"] = dcp::LocalTime(valid_to.get()).date() + " " + dcp::LocalTime(valid_to.get()).time_of_day();
+
try {
list<ScreenKDM> screen_kdms = film->make_kdms (
(*i)->screens(), cpl, valid_from.get(), valid_to.get(), formulation
);
if (zip) {
- CinemaKDMs::write_zip_files (film->name(), CinemaKDMs::collect (screen_kdms), output);
+ CinemaKDMs::write_zip_files (
+ CinemaKDMs::collect (screen_kdms),
+ output,
+ Config::instance()->kdm_filename_format(),
+ values
+ );
if (verbose) {
cout << "Wrote ZIP files to " << output << "\n";
}
} else {
- ScreenKDM::write_files (film->name(), screen_kdms, output);
+ ScreenKDM::write_files (screen_kdms, output, Config::instance()->kdm_filename_format(), values);
if (verbose) {
cout << "Wrote KDM files to " << output << "\n";
{
return _output->formulation ();
}
+
+KDMNameFormat
+KDMDialog::name_format () const
+{
+ return _output->name_format ();
+}
+
+int
+KDMDialog::ShowModal ()
+{
+ int const r = wxDialog::ShowModal ();
+ _output->save_kdm_name_format ();
+ return r;
+}
*/
#include "wx_util.h"
+#include "lib/kdm_name_format.h"
#include <dcp/types.h>
#include <wx/wx.h>
#include <boost/shared_ptr.hpp>
boost::filesystem::path directory () const;
bool write_to () const;
dcp::Formulation formulation () const;
+ KDMNameFormat name_format () const;
+
+ int ShowModal ();
private:
void setup_sensitivity ();
*/
+#include "lib/config.h"
#include "kdm_output_panel.h"
#include "wx_util.h"
+#include "name_format_editor.h"
#include <dcp/types.h>
#ifdef DCPOMATIC_USE_OWN_PICKER
#include "dir_picker_ctrl.h"
table->Add (_type, 1, wxEXPAND);
_type->SetSelection (0);
+ {
+ int flags = wxALIGN_TOP | wxTOP;
+ wxString t = _("Filename format");
+#ifdef __WXOSX__
+ flags |= wxALIGN_RIGHT;
+ t += wxT (":");
+#endif
+ wxStaticText* m = new wxStaticText (this, wxID_ANY, t);
+ table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
+ }
+
+ _filename_format = new NameFormatEditor<KDMNameFormat> (this, Config::instance()->kdm_filename_format());
+ NameFormat::Map ex;
+ ex["film_name"] = "Bambi";
+ ex["cinema"] = "Lumière";
+ ex["screen"] = "Screen 1";
+ ex["from"] = "2012/03/15 12:30";
+ ex["to"] = "2012/03/22 02:30";
+ _filename_format->set_example (ex);
+ table->Add (_filename_format->panel(), 1, wxEXPAND);
+
_write_to = new wxRadioButton (this, wxID_ANY, _("Write to"));
table->Add (_write_to, 1, wxEXPAND);
{
return (dcp::Formulation) reinterpret_cast<intptr_t> (_type->GetClientData (_type->GetSelection()));
}
+
+void
+KDMOutputPanel::save_kdm_name_format () const
+{
+ Config::instance()->set_kdm_filename_format (name_format ());
+}
+
+KDMNameFormat
+KDMOutputPanel::name_format () const
+{
+ return _filename_format->get ();
+}
*/
#include "wx_util.h"
+#include "name_format_editor.h"
+#include "lib/kdm_name_format.h"
#include <dcp/types.h>
#include <wx/wx.h>
#include <boost/filesystem.hpp>
boost::filesystem::path directory () const;
bool write_to () const;
dcp::Formulation formulation () const;
+ KDMNameFormat name_format () const;
void setup_sensitivity ();
+ void save_kdm_name_format () const;
private:
wxChoice* _type;
+ NameFormatEditor<KDMNameFormat>* _filename_format;
wxRadioButton* _write_to;
#ifdef DCPOMATIC_USE_OWN_PICKER
DirPickerCtrl* _folder;
--- /dev/null
+/*
+ Copyright (C) 2016 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/>.
+
+*/
+
+#ifndef DCPOMATIC_NAME_FORMAT_EDITOR_H
+#define DCPOMATIC_NAME_FORMAT_EDITOR_H
+
+#include "lib/name_format.h"
+#include "lib/compose.hpp"
+#include <wx/wx.h>
+#include <boost/foreach.hpp>
+
+template <class T>
+class NameFormatEditor
+{
+public:
+ NameFormatEditor (wxWindow* parent, T name)
+ : _panel (new wxPanel (parent))
+ , _example (new wxStaticText (_panel, wxID_ANY, ""))
+ , _sizer (new wxBoxSizer (wxVERTICAL))
+ , _specification (new wxTextCtrl (_panel, wxID_ANY, ""))
+ , _name (name)
+ {
+ _sizer->Add (_specification, 0, wxEXPAND, DCPOMATIC_SIZER_Y_GAP);
+ _sizer->Add (_example, 0, wxBOTTOM, DCPOMATIC_SIZER_Y_GAP);
+ _panel->SetSizer (_sizer);
+
+ BOOST_FOREACH (NameFormat::Component c, name.components ()) {
+ wxStaticText* t = new wxStaticText (_panel, wxID_ANY, std_to_wx (String::compose ("%%%1 %2", c.placeholder, c.title)));
+ _sizer->Add (t);
+ wxFont font = t->GetFont();
+ font.SetStyle (wxFONTSTYLE_ITALIC);
+ font.SetPointSize (font.GetPointSize() - 1);
+ t->SetFont (font);
+ t->SetForegroundColour (wxColour (0, 0, 204));
+ }
+
+ _specification->SetValue (std_to_wx (_name.specification ()));
+ _specification->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&NameFormatEditor::update_example, this));
+
+ update_example ();
+ }
+
+ wxPanel* panel () const
+ {
+ return _panel;
+ }
+
+ void set_example (NameFormat::Map v) {
+ _example_values = v;
+ update_example ();
+ }
+
+ T get () const {
+ return _name;
+ }
+
+private:
+
+ virtual void update_example ()
+ {
+ _name.set_specification (wx_to_std (_specification->GetValue ()));
+ _example->SetLabel (wxString::Format (_("e.g. %s"), _name.get (_example_values)));
+ }
+
+ wxPanel* _panel;
+ wxStaticText* _example;
+ wxSizer* _sizer;
+ wxTextCtrl* _specification;
+
+ T _name;
+ NameFormat::Map _example_values;
+};
+
+#endif