+2015-11-13 c.hetherington <cth@carlh.net>
+
+ * Allow multiple recipients of KDM emails (#745).
+
2015-11-12 Carl Hetherington <cth@carlh.net>
* Version 2.5.2 released.
#include "screen.h"
#include <libcxml/cxml.h>
#include <libxml++/libxml++.h>
+#include <boost/foreach.hpp>
using std::list;
+using std::string;
using boost::shared_ptr;
Cinema::Cinema (cxml::ConstNodePtr node)
: name (node->string_child ("Name"))
- , email (node->string_child ("Email"))
{
-
+ BOOST_FOREACH (cxml::ConstNodePtr i, node->node_children("Email")) {
+ emails.push_back (i->content ());
+ }
}
/* This is necessary so that we can use shared_from_this in add_screen (which cannot be done from
Cinema::as_xml (xmlpp::Element* parent) const
{
parent->add_child("Name")->add_child_text (name);
- parent->add_child("Email")->add_child_text (email);
- for (list<shared_ptr<Screen> >::const_iterator i = _screens.begin(); i != _screens.end(); ++i) {
- (*i)->as_xml (parent->add_child ("Screen"));
+ BOOST_FOREACH (string i, emails) {
+ parent->add_child("Email")->add_child_text (i);
+ }
+
+ BOOST_FOREACH (shared_ptr<Screen> i, _screens) {
+ i->as_xml (parent->add_child ("Screen"));
}
}
/** @class Cinema
* @brief A description of a Cinema for KDM generation.
*
- * This is a cinema name, contact email address and a list of
+ * This is a cinema name, contact email addresses and a list of
* Screen objects.
*/
class Cinema : public boost::enable_shared_from_this<Cinema>
{
public:
- Cinema (std::string const & n, std::string const & e)
+ Cinema (std::string const & n, std::list<std::string> const & e)
: name (n)
- , email (e)
+ , emails (e)
{}
Cinema (cxml::ConstNodePtr);
void remove_screen (boost::shared_ptr<Screen>);
std::string name;
- std::string email;
+ std::list<std::string> emails;
std::list<boost::shared_ptr<Screen> > screens () const {
return _screens;
}
}
boost::algorithm::replace_all (body, "$SCREENS", screens.str().substr (0, screens.str().length() - 2));
- Emailer email (config->kdm_from(), i.cinema->email, subject, body);
+ Emailer email (config->kdm_from(), i.cinema->emails, subject, body);
if (!config->kdm_cc().empty ()) {
email.add_cc (config->kdm_cc ());
using std::pair;
using boost::shared_ptr;
-Emailer::Emailer (string from, string to, string subject, string body)
+Emailer::Emailer (string from, list<string> to, string subject, string body)
: _from (from)
, _to (to)
, _subject (subject)
stringstream email;
email << "Date: " << date_buffer << "\r\n"
- << "To: " << _to << "\r\n"
+ << "To: " << address_list (_to) << "\r\n"
<< "From: " << _from << "\r\n";
if (!_cc.empty ()) {
curl_easy_setopt (curl, CURLOPT_MAIL_FROM, _from.c_str());
- struct curl_slist* recipients = curl_slist_append (0, _to.c_str());
+ struct curl_slist* recipients = 0;
+ BOOST_FOREACH (string i, _to) {
+ curl_slist_append (recipients, i.c_str());
+ }
BOOST_FOREACH (string i, _cc) {
recipients = curl_slist_append (recipients, i.c_str());
}
CURLMcode mc = curl_multi_fdset (mcurl, &fdread, &fdwrite, &fdexcep, &maxfd);
if (mc != CURLM_OK) {
- throw KDMError (String::compose ("Failed to send KDM email to %1", _to));
+ throw KDMError (String::compose ("Failed to send KDM email to %1", address_list (_to)));
}
int rc;
class Emailer
{
public:
- Emailer (std::string from, std::string to, std::string subject, std::string body);
+ Emailer (std::string from, std::list<std::string> to, std::string subject, std::string body);
void add_cc (std::string cc);
void add_bcc (std::string bcc);
size_t get_data (void* ptr, size_t size, size_t nmemb);
int debug (CURL* curl, curl_infotype type, char* data, size_t size);
-private:
static std::string address_list (std::list<std::string> addresses);
+private:
+
std::string _from;
- std::string _to;
+ std::list<std::string> _to;
std::string _subject;
std::string _body;
std::list<std::string> _cc;
add_file (body, "metadata.xml");
}
- Emailer emailer (_from, "carl@dcpomatic.com", "DCP-o-matic problem report", body);
+ list<string> to;
+ to.push_back ("carl@dcpomatic.com");
+
+ Emailer emailer (_from, to, "DCP-o-matic problem report", body);
emailer.send (shared_from_this ());
set_progress (1);
#include "lib/cinema_kdms.h"
#include "lib/config.h"
#include "lib/exceptions.h"
+#include "lib/emailer.h"
#include "lib/safe_stringstream.h"
#include <dcp/certificate.h>
#include <getopt.h>
if (cinemas) {
list<boost::shared_ptr<Cinema> > cinemas = Config::instance()->cinemas ();
for (list<boost::shared_ptr<Cinema> >::const_iterator i = cinemas.begin(); i != cinemas.end(); ++i) {
- cout << (*i)->name << " (" << (*i)->email << ")\n";
+ cout << (*i)->name << " (" << Emailer::address_list ((*i)->emails) << ")\n";
}
exit (EXIT_SUCCESS);
}
list<shared_ptr<Cinema> > cinemas = Config::instance()->cinemas ();
list<shared_ptr<Cinema> >::const_iterator i = cinemas.begin();
- while (i != cinemas.end() && (*i)->name != cinema_name && (*i)->email != cinema_name) {
+ while (
+ i != cinemas.end() &&
+ (*i)->name != cinema_name &&
+ find ((*i)->emails.begin(), (*i)->emails.end(), cinema_name) == (*i)->emails.end()) {
+
++i;
}
#include "cinema_dialog.h"
#include "wx_util.h"
+#include <boost/foreach.hpp>
using std::string;
+using std::vector;
+using std::copy;
+using std::back_inserter;
+using std::list;
+using std::cout;
+using boost::bind;
-CinemaDialog::CinemaDialog (wxWindow* parent, string title, string name, string email)
- : TableDialog (parent, std_to_wx (title), 2, 1, true)
+static string
+column (string s)
{
- add (_("Name"), true);
- _name = add (new wxTextCtrl (this, wxID_ANY, std_to_wx (name), wxDefaultPosition, wxSize (256, -1)));
+ return s;
+}
+
+CinemaDialog::CinemaDialog (wxWindow* parent, string title, string name, list<string> emails)
+ : wxDialog (parent, wxID_ANY, std_to_wx (title))
+{
+ wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL);
+ SetSizer (overall_sizer);
+
+ wxGridBagSizer* sizer = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
+ int r = 0;
+
+ add_label_to_sizer (sizer, this, _("Name"), true, wxGBPosition (r, 0));
+ _name = new wxTextCtrl (this, wxID_ANY, std_to_wx (name), wxDefaultPosition, wxSize (500, -1));
+ sizer->Add (_name, wxGBPosition (r, 1));
+ ++r;
+
+ add_label_to_sizer (sizer, this, _("Email addresses for KDM delivery"), true, wxGBPosition (r, 0), wxGBSpan (1, 2));
+ ++r;
+
+ copy (emails.begin(), emails.end(), back_inserter (_emails));
+
+ vector<string> columns;
+ columns.push_back (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)
+ );
+
+ sizer->Add (_email_list, wxGBPosition (r, 0), wxGBSpan (1, 2), wxEXPAND);
+ ++r;
- add (_("Email address for KDM delivery"), true);
- _email = add (new wxTextCtrl (this, wxID_ANY, std_to_wx (email), wxDefaultPosition, wxSize (256, -1)));
+ overall_sizer->Add (sizer, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER);
- layout ();
+ wxSizer* buttons = CreateSeparatedButtonSizer (wxOK | wxCANCEL);
+ if (buttons) {
+ overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
+ }
+
+ overall_sizer->Layout ();
+ overall_sizer->SetSizeHints (this);
}
string
return wx_to_std (_name->GetValue());
}
-string
-CinemaDialog::email () const
+void
+CinemaDialog::set_emails (vector<string> e)
+{
+ _emails = e;
+}
+
+vector<string>
+CinemaDialog::get_emails () const
+{
+ return _emails;
+}
+
+list<string>
+CinemaDialog::emails () const
{
- return wx_to_std (_email->GetValue());
+ list<string> e;
+ copy (_emails.begin(), _emails.end(), back_inserter (e));
+ return e;
}
*/
-#include <wx/wx.h>
#include "table_dialog.h"
+#include "editable_list.h"
+#include "email_dialog.h"
+#include <wx/wx.h>
+#include <list>
+#include <vector>
-class CinemaDialog : public TableDialog
+class CinemaDialog : public wxDialog
{
public:
- CinemaDialog (wxWindow *, std::string, std::string name = "", std::string email = "");
+ CinemaDialog (wxWindow *, std::string, std::string name = "", std::list<std::string> emails = std::list<std::string> ());
std::string name () const;
- std::string email () const;
+ std::list<std::string> emails () const;
private:
+ std::vector<std::string> get_emails () const;
+ void set_emails (std::vector<std::string>);
+
wxTextCtrl* _name;
- wxTextCtrl* _email;
+ EditableList<std::string, EmailDialog>* _email_list;
+ std::vector<std::string> _emails;
};
*/
+#include "wx_util.h"
#include <wx/wx.h>
#include <wx/listctrl.h>
+#include <boost/function.hpp>
+#include <vector>
+/** @param T type of things being edited.
+ * @param S dialog to edit a thing.
+ */
template<class T, class S>
class EditableList : public wxPanel
{
_list->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&EditableList::selection_changed, this));
_list->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&EditableList::selection_changed, this));
_list->Bind (wxEVT_SIZE, boost::bind (&EditableList::resized, this, _1));
- selection_changed ();
+ refresh ();
+ selection_changed ();
}
void refresh ()
--- /dev/null
+/*
+ Copyright (C) 2015 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "email_dialog.h"
+#include "wx_util.h"
+
+using std::string;
+using boost::shared_ptr;
+
+EmailDialog::EmailDialog (wxWindow* parent)
+ : TableDialog (parent, _("Email address"), 2, 1, true)
+{
+ add (_("Email address"), true);
+ _email = add (new wxTextCtrl (this, wxID_ANY, wxT (""), wxDefaultPosition, wxSize (400, -1)));
+
+ layout ();
+}
+
+void
+EmailDialog::set (string address)
+{
+ _email->SetValue (std_to_wx (address));
+}
+
+string
+EmailDialog::get () const
+{
+ return wx_to_std (_email->GetValue ());
+}
--- /dev/null
+/*
+ Copyright (C) 2015 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "table_dialog.h"
+
+class EmailDialog : public TableDialog
+{
+public:
+ EmailDialog (wxWindow *);
+
+ void set (std::string);
+ std::string get () const;
+
+private:
+ wxTextCtrl* _email;
+};
{
CinemaDialog* d = new CinemaDialog (this, "Add Cinema");
if (d->ShowModal () == wxID_OK) {
- shared_ptr<Cinema> c (new Cinema (d->name(), d->email()));
+ shared_ptr<Cinema> c (new Cinema (d->name(), d->emails()));
Config::instance()->add_cinema (c);
add_cinema (c);
}
pair<wxTreeItemId, shared_ptr<Cinema> > c = selected_cinemas().front();
- CinemaDialog* d = new CinemaDialog (this, "Edit cinema", c.second->name, c.second->email);
+ CinemaDialog* d = new CinemaDialog (this, "Edit cinema", c.second->name, c.second->emails);
if (d->ShowModal () == wxID_OK) {
c.second->name = d->name ();
- c.second->email = d->email ();
+ c.second->emails = d->emails ();
_targets->SetItemText (c.first, std_to_wx (d->name()));
Config::instance()->changed ();
}
content_properties_dialog.cc
content_sub_panel.cc
dcp_panel.cc
+ email_dialog.cc
image_sequence_dialog.cc
isdcf_metadata_dialog.cc
dir_picker_ctrl.cc