m->set_attribute("Type", dcp::marker_to_string(i->first));
m->add_child_text(raw_convert<string>(i->second.get()));
}
+ BOOST_FOREACH (dcp::Rating i, _ratings) {
+ i.as_xml (root->add_child("Rating"));
+ }
_playlist->as_xml (root->add_child ("Playlist"), with_content_paths);
return doc;
_markers[dcp::marker_from_string(i->string_attribute("Type"))] = DCPTime(dcp::raw_convert<DCPTime::Type>(i->content()));
}
+ BOOST_FOREACH (cxml::ConstNodePtr i, f.node_children("Rating")) {
+ _ratings.push_back (dcp::Rating(i));
+ }
+
list<string> notes;
/* This method is the only one that can return notes (so far) */
_playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), _state_version, notes);
_markers.erase (type);
}
+void
+Film::set_ratings (vector<dcp::Rating> r)
+{
+ ChangeSignaller<Film> ch (this, RATINGS);
+ _ratings = r;
+}
+
optional<DCPTime>
Film::marker (dcp::Marker type) const
{
/*
- Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
REEL_LENGTH,
UPLOAD_AFTER_MAKE_DCP,
REENCODE_J2K,
- MARKERS
+ MARKERS,
+ RATINGS
};
return _markers;
}
+ std::vector<dcp::Rating> ratings () const {
+ return _ratings;
+ }
+
/* SET */
void set_directory (boost::filesystem::path);
void set_reencode_j2k (bool);
void set_marker (dcp::Marker type, DCPTime time);
void unset_marker (dcp::Marker type);
+ void set_ratings (std::vector<dcp::Rating> r);
/** Emitted when some property has of the Film is about to change or has changed */
mutable boost::signals2::signal<void (ChangeType, Property)> Change;
/** true if the user has ever explicitly set the video frame rate of this film */
bool _user_explicit_video_frame_rate;
std::map<dcp::Marker, DCPTime> _markers;
+ std::vector<dcp::Rating> _ratings;
int _state_version;
extern void write_swaroop_chain (boost::shared_ptr<const dcp::CertificateChain> chain, boost::filesystem::path output);
#endif
+template <class T>
+std::list<T>
+vector_to_list (std::vector<T> v)
+{
+ std::list<T> l;
+ BOOST_FOREACH (T& i, v) {
+ l.push_back (i);
+ }
+ return l;
+}
+
#endif
meta.set_issue_date_now ();
cpl->set_metadata (meta);
+ cpl->set_ratings (vector_to_list(_film->ratings()));
shared_ptr<const dcp::CertificateChain> signer;
if (_film->is_signed ()) {
copy (emails.begin(), emails.end(), back_inserter (_emails));
- vector<string> columns;
- columns.push_back (wx_to_std (_("Address")));
+ vector<EditableListColumn> columns;
+ columns.push_back (EditableListColumn(wx_to_std(_("Address"))));
_email_list = new EditableList<string, EmailDialog> (
this, columns, bind (&CinemaDialog::get_emails, this), bind (&CinemaDialog::set_emails, this, _1), bind (&column, _1)
);
#include "check_box.h"
#include "dcpomatic_button.h"
#include "markers_dialog.h"
+#include "metadata_dialog.h"
#include "lib/ratio.h"
#include "lib/config.h"
#include "lib/dcp_content_type.h"
DCPPanel::DCPPanel (wxNotebook* n, shared_ptr<Film> film, weak_ptr<FilmViewer> viewer)
: _audio_dialog (0)
, _markers_dialog (0)
+ , _metadata_dialog (0)
, _film (film)
, _viewer (viewer)
, _generally_sensitive (true)
_upload_after_make_dcp = new CheckBox (_panel, _("Upload DCP to TMS after it is made"));
_markers = new Button (_panel, _("Markers..."));
+ _metadata = new Button (_panel, _("Metadata..."));
_notebook = new wxNotebook (_panel, wxID_ANY);
_sizer->Add (_notebook, 1, wxEXPAND | wxTOP, 6);
_standard->Bind (wxEVT_CHOICE, boost::bind (&DCPPanel::standard_changed, this));
_upload_after_make_dcp->Bind (wxEVT_CHECKBOX, boost::bind (&DCPPanel::upload_after_make_dcp_changed, this));
_markers->Bind (wxEVT_BUTTON, boost::bind (&DCPPanel::markers_clicked, this));
+ _metadata->Bind (wxEVT_BUTTON, boost::bind (&DCPPanel::metadata_clicked, this));
BOOST_FOREACH (DCPContentType const * i, DCPContentType::all()) {
_dcp_content_type->Append (std_to_wx (i->pretty_name ()));
_standard->Show (full);
_upload_after_make_dcp->Show (full);
_markers->Show (full);
+ _metadata->Show (full);
_reencode_j2k->Show (full);
_encrypted->Show (full);
_grid->Add (_upload_after_make_dcp, wxGBPosition (r, 0), wxGBSpan (1, 2));
++r;
- _grid->Add (_markers, wxGBPosition(r, 0), wxGBSpan(1, 2));
+ wxBoxSizer* extra = new wxBoxSizer (wxHORIZONTAL);
+ extra->Add (_markers, 1, wxRIGHT, DCPOMATIC_SIZER_X_GAP);
+ extra->Add (_metadata, 1, wxRIGHT, DCPOMATIC_SIZER_X_GAP);
+ _grid->Add (extra, wxGBPosition(r, 0), wxGBSpan(1, 2));
++r;
}
}
_markers_dialog->Show();
}
+void
+DCPPanel::metadata_clicked ()
+{
+ if (_metadata_dialog) {
+ _metadata_dialog->Destroy ();
+ _metadata_dialog = 0;
+ }
+
+ _metadata_dialog = new MetadataDialog (_panel, _film);
+ _metadata_dialog->Show ();
+}
+
void
DCPPanel::film_changed (int p)
{
_markers_dialog->Destroy ();
_markers_dialog = 0;
}
+ if (_metadata_dialog) {
+ _metadata_dialog->Destroy ();
+ _metadata_dialog = 0;
+ }
_film = film;
_reel_length->Enable (_generally_sensitive && _film && _film->reel_type() == REELTYPE_BY_LENGTH);
_upload_after_make_dcp->Enable (_generally_sensitive);
_markers->Enable (_generally_sensitive);
+ _metadata->Enable (_generally_sensitive);
_frame_rate_choice->Enable (_generally_sensitive && _film && !_film->references_dcp_video());
_frame_rate_spin->Enable (_generally_sensitive && _film && !_film->references_dcp_video());
_audio_channels->Enable (_generally_sensitive && _film && !_film->references_dcp_audio());
class AudioDialog;
class MarkersDialog;
+class MetadataDialog;
class Film;
class FilmViewer;
class Ratio;
void reel_length_changed ();
void upload_after_make_dcp_changed ();
void markers_clicked ();
+ void metadata_clicked ();
void reencode_j2k_changed ();
void setup_frame_rate_widget ();
wxSpinCtrl* _reel_length;
wxCheckBox* _upload_after_make_dcp;
wxButton* _markers;
+ wxButton* _metadata;
AudioDialog* _audio_dialog;
MarkersDialog* _markers_dialog;
+ MetadataDialog* _metadata_dialog;
boost::shared_ptr<Film> _film;
boost::weak_ptr<FilmViewer> _viewer;
#include <boost/function.hpp>
#include <vector>
+class EditableListColumn
+{
+public:
+ EditableListColumn (std::string name_)
+ : name (name_)
+ , growable (false)
+ {}
+
+ EditableListColumn (std::string name_, boost::optional<int> width_, bool growable_)
+ : name (name_)
+ , width (width_)
+ , growable (growable_)
+ {}
+
+ std::string name;
+ boost::optional<int> width;
+ bool growable;
+};
+
/** @param T type of things being edited.
* @param S dialog to edit a thing.
+ * @param get Function to get a std::vector of the things being edited.
+ * @param set Function set the things from a a std::vector.
+ * @param column Function to get the display string for a given column in a given item.
*/
template<class T, class S>
class EditableList : public wxPanel
public:
EditableList (
wxWindow* parent,
- std::vector<std::string> columns,
+ std::vector<EditableListColumn> columns,
boost::function<std::vector<T> ()> get,
boost::function<void (std::vector<T>)> set,
boost::function<std::string (T, int)> column,
bool can_edit = true,
- bool title = true,
- int column_width = 200
+ bool title = true
)
: wxPanel (parent)
, _get (get)
, _set (set)
- , _columns (columns.size ())
+ , _columns (columns)
, _column (column)
, _edit (0)
+ , _default_width (200)
{
_sizer = new wxBoxSizer (wxHORIZONTAL);
SetSizer (_sizer);
if (title) {
style |= wxLC_NO_HEADER;
}
- _list = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (columns.size() * column_width, 100), style);
- for (size_t i = 0; i < columns.size(); ++i) {
+ int total_width = 0;
+ BOOST_FOREACH (EditableListColumn i, _columns) {
+ total_width += i.width.get_value_or (_default_width);
+ }
+
+ _list = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize(total_width, 100), style);
+
+ int j = 0;
+ BOOST_FOREACH (EditableListColumn i, _columns) {
wxListItem ip;
- ip.SetId (i);
- ip.SetText (std_to_wx (columns[i]));
- ip.SetWidth (column_width);
- _list->InsertColumn (i, ip);
+ ip.SetId (j);
+ ip.SetText (std_to_wx(i.name));
+ _list->InsertColumn (j, ip);
+ ++j;
}
_sizer->Add (_list, 1, wxEXPAND);
list_item.SetId (n);
_list->InsertItem (list_item);
- for (int i = 0; i < _columns; ++i) {
+ for (size_t i = 0; i < _columns.size(); ++i) {
_list->SetItem (n, i, std_to_wx (_column (item, i)));
}
}
}
dialog->Destroy ();
- for (int i = 0; i < _columns; ++i) {
+ for (size_t i = 0; i < _columns.size(); ++i) {
_list->SetItem (item, i, std_to_wx (_column (all[item], i)));
}
void resized (wxSizeEvent& ev)
{
- int const w = GetSize().GetWidth() / _columns;
- for (int i = 0; i < _columns; ++i) {
- _list->SetColumnWidth (i, w);
+ int const w = _list->GetSize().GetWidth() - 2;
+
+ int fixed_width = 0;
+ int growable = 0;
+ int j = 0;
+ BOOST_FOREACH (EditableListColumn i, _columns) {
+ fixed_width += i.width.get_value_or (_default_width);
+ if (!i.growable) {
+ _list->SetColumnWidth (j, i.width.get_value_or(_default_width));
+ } else {
+ ++growable;
+ }
+ ++j;
+ }
+
+ j = 0;
+ BOOST_FOREACH (EditableListColumn i, _columns) {
+ if (i.growable) {
+ _list->SetColumnWidth (j, i.width.get_value_or(_default_width) + (w - fixed_width) / growable);
+ }
+ ++j;
}
+
ev.Skip ();
}
boost::function <std::vector<T> ()> _get;
boost::function <void (std::vector<T>)> _set;
- int _columns;
+ std::vector<EditableListColumn> _columns;
boost::function<std::string (T, int)> _column;
wxButton* _add;
wxButton* _remove;
wxListCtrl* _list;
wxBoxSizer* _sizer;
+ int _default_width;
};
#endif
_use_any_servers = new CheckBox (_panel, _("Search network for servers"));
_panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
- vector<string> columns;
- columns.push_back (wx_to_std (_("IP address / host name")));
+ vector<EditableListColumn> columns;
+ columns.push_back (EditableListColumn(wx_to_std(_("IP address / host name"))));
_servers_list = new EditableList<string, ServerDialog> (
_panel,
columns,
_from = new wxTextCtrl (_panel, wxID_ANY);
table->Add (_from, 1, wxEXPAND | wxALL);
- vector<string> columns;
- columns.push_back (wx_to_std (_("Address")));
+ vector<EditableListColumn> columns;
+ columns.push_back (EditableListColumn(wx_to_std(_("Address"))));
add_label_to_sizer (table, _panel, _("CC addresses"), true);
_cc = new EditableList<string, EmailDialog> (
_panel,
_to = new wxTextCtrl (_panel, wxID_ANY);
table->Add (_to, 1, wxEXPAND | wxALL);
- vector<string> columns;
- columns.push_back (wx_to_std (_("Address")));
+ vector<EditableListColumn> columns;
+ columns.push_back (EditableListColumn(wx_to_std(_("Address"))));
add_label_to_sizer (table, _panel, _("CC addresses"), true);
_cc = new EditableList<string, EmailDialog> (
_panel,
--- /dev/null
+/*
+ Copyright (C) 2019 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 "metadata_dialog.h"
+#include "editable_list.h"
+#include "rating_dialog.h"
+#include "lib/film.h"
+#include <dcp/types.h>
+#include <wx/gbsizer.h>
+
+using std::string;
+using std::vector;
+using boost::weak_ptr;
+using boost::shared_ptr;
+
+static string
+column (dcp::Rating r, int c)
+{
+ if (c == 0) {
+ return r.agency;
+ }
+
+ return r.label;
+}
+
+MetadataDialog::MetadataDialog (wxWindow* parent, weak_ptr<Film> film)
+ : wxDialog (parent, wxID_ANY, _("Metadata"))
+ , _film (film)
+{
+ wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL);
+ SetSizer (overall_sizer);
+
+ wxFlexGridSizer* sizer = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
+ sizer->AddGrowableCol (1, 1);
+
+ {
+ int flags = wxALIGN_TOP | wxLEFT | wxRIGHT | wxTOP;
+#ifdef __WXOSX__
+ flags |= wxALIGN_RIGHT;
+#endif
+ wxStaticText* m = create_label (this, _("Ratings"), true);
+ sizer->Add (m, 0, flags, DCPOMATIC_SIZER_GAP);
+ }
+
+ vector<EditableListColumn> columns;
+ columns.push_back (EditableListColumn("Agency", 200, true));
+ columns.push_back (EditableListColumn("Label", 50, false));
+ _ratings = new EditableList<dcp::Rating, RatingDialog> (
+ this,
+ columns,
+ bind(&MetadataDialog::ratings, this),
+ bind(&MetadataDialog::set_ratings, this, _1),
+ bind(&column, _1, _2),
+ true,
+ false
+ );
+ sizer->Add (_ratings, 1, wxEXPAND);
+
+ overall_sizer->Add (sizer, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER);
+
+ wxSizer* buttons = CreateSeparatedButtonSizer (wxCLOSE);
+ if (buttons) {
+ overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
+ }
+
+ overall_sizer->Layout ();
+ overall_sizer->SetSizeHints (this);
+}
+
+vector<dcp::Rating>
+MetadataDialog::ratings () const
+{
+ shared_ptr<Film> film = _film.lock ();
+ DCPOMATIC_ASSERT (film);
+ return film->ratings ();
+}
+
+void
+MetadataDialog::set_ratings (vector<dcp::Rating> r)
+{
+ shared_ptr<Film> film = _film.lock ();
+ DCPOMATIC_ASSERT (film);
+ film->set_ratings (r);
+}
--- /dev/null
+/*
+ Copyright (C) 2019 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 "editable_list.h"
+#include <dcp/types.h>
+#include <wx/wx.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <vector>
+
+class Film;
+class RatingDialog;
+
+class MetadataDialog : public wxDialog
+{
+public:
+ MetadataDialog (wxWindow* parent, boost::weak_ptr<Film> film);
+
+private:
+ std::vector<dcp::Rating> ratings () const;
+ void set_ratings (std::vector<dcp::Rating> r);
+
+ boost::weak_ptr<Film> _film;
+ EditableList<dcp::Rating, RatingDialog>* _ratings;
+};
--- /dev/null
+/*
+ Copyright (C) 2019 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 "rating_dialog.h"
+#include "wx_util.h"
+
+RatingDialog::RatingDialog (wxWindow* parent)
+ : TableDialog (parent, _("Ratings"), 2, 1, true)
+{
+ add (_("Agency"), true);
+ _agency = new wxTextCtrl (this, wxID_ANY);
+ add (_agency);
+
+ add (_("Label"), true);
+ _label = new wxTextCtrl (this, wxID_ANY);
+ add (_label);
+
+ layout ();
+}
+
+void
+RatingDialog::set (dcp::Rating r)
+{
+ _agency->SetValue (std_to_wx(r.agency));
+ _label->SetValue (std_to_wx(r.label));
+}
+
+dcp::Rating
+RatingDialog::get () const
+{
+ return dcp::Rating(wx_to_std(_agency->GetValue()), wx_to_std(_label->GetValue()));
+}
--- /dev/null
+/*
+ Copyright (C) 2019 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 "table_dialog.h"
+#include <dcp/types.h>
+
+class RatingDialog : public TableDialog
+{
+public:
+ RatingDialog (wxWindow* parent);
+
+ void set (dcp::Rating r);
+ dcp::Rating get () const;
+
+private:
+ wxTextCtrl* _agency;
+ wxTextCtrl* _label;
+};
add_label_to_sizer (_sizer, this, _("Other trusted devices"), true, wxGBPosition (r, 0));
++r;
- vector<string> columns;
- columns.push_back (wx_to_std (_("Thumbprint")));
+ vector<EditableListColumn> columns;
+ columns.push_back (EditableListColumn(wx_to_std(_("Thumbprint"))));
_trusted_device_list = new EditableList<TrustedDevice, TrustedDeviceDialog> (
this,
columns,
#
-# Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
+# Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
#
# This file is part of DCP-o-matic.
#
make_chain_dialog.cc
markers_dialog.cc
message_dialog.cc
+ metadata_dialog.cc
monitor_dialog.cc
move_to_dialog.cc
nag_dialog.cc
playhead_to_timecode_dialog.cc
playhead_to_frame_dialog.cc
question_dialog.cc
+ rating_dialog.cc
recreate_chain_dialog.cc
repeat_dialog.cc
report_problem_dialog.cc