wip: stuff.
[dcpomatic.git] / src / wx / recipients_panel.cc
1 /*
2     Copyright (C) 2015-2020 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     DCP-o-matic is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21 #include "recipients_panel.h"
22 #include "recipient_dialog.h"
23 #include "wx_util.h"
24 #include "dcpomatic_button.h"
25 #include "lib/config.h"
26 #include "lib/dkdm_recipient.h"
27 #include <boost/foreach.hpp>
28
29 using std::list;
30 using std::pair;
31 using std::cout;
32 using std::map;
33 using std::string;
34 using std::make_pair;
35 using boost::shared_ptr;
36 using boost::optional;
37 using namespace dcpomatic;
38
39 RecipientsPanel::RecipientsPanel (wxWindow* parent)
40         : wxPanel (parent, wxID_ANY)
41         , _ignore_selection_change (false)
42 {
43         wxBoxSizer* sizer = new wxBoxSizer (wxVERTICAL);
44
45         _search = new wxSearchCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (200, -1));
46         _search->ShowCancelButton (true);
47         sizer->Add (_search, 0, wxBOTTOM, DCPOMATIC_SIZER_GAP);
48
49         wxBoxSizer* targets = new wxBoxSizer (wxHORIZONTAL);
50         _targets = new wxTreeCtrl (this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTR_HIDE_ROOT | wxTR_MULTIPLE | wxTR_HAS_BUTTONS | wxTR_LINES_AT_ROOT);
51         targets->Add (_targets, 1, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_GAP);
52
53         add_recipients_from_config ();
54
55         wxBoxSizer* target_buttons = new wxBoxSizer (wxVERTICAL);
56
57         _add_recipient = new Button (this, _("Add Recipient..."));
58         target_buttons->Add (_add_recipient, 1, wxEXPAND | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
59         _edit_recipient = new Button (this, _("Edit Recipient..."));
60         target_buttons->Add (_edit_recipient, 1, wxEXPAND | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
61         _remove_recipient = new Button (this, _("Remove Recipient"));
62         target_buttons->Add (_remove_recipient, 1, wxEXPAND | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
63
64         targets->Add (target_buttons, 0, 0);
65
66         sizer->Add (targets, 1, wxEXPAND);
67
68         _search->Bind        (wxEVT_TEXT, boost::bind (&RecipientsPanel::search_changed, this));
69         _targets->Bind       (wxEVT_TREE_SEL_CHANGED, &RecipientsPanel::selection_changed_shim, this);
70
71         _add_recipient->Bind    (wxEVT_BUTTON, boost::bind (&RecipientsPanel::add_recipient_clicked, this));
72         _edit_recipient->Bind   (wxEVT_BUTTON, boost::bind (&RecipientsPanel::edit_recipient_clicked, this));
73         _remove_recipient->Bind (wxEVT_BUTTON, boost::bind (&RecipientsPanel::remove_recipient_clicked, this));
74
75         SetSizer (sizer);
76 }
77
78
79 RecipientsPanel::~RecipientsPanel ()
80 {
81         _targets->Unbind (wxEVT_TREE_SEL_CHANGED, &RecipientsPanel::selection_changed_shim, this);
82 }
83
84
85 void
86 RecipientsPanel::setup_sensitivity ()
87 {
88         bool const s = _selected.size() == 1;
89
90         _edit_recipient->Enable (s);
91         _remove_recipient->Enable (_selected.size() >= 1);
92 }
93
94
95 void
96 RecipientsPanel::add_recipient (shared_ptr<DKDMRecipient> r)
97 {
98         string search = wx_to_std (_search->GetValue());
99         transform (search.begin(), search.end(), search.begin(), ::tolower);
100
101         if (!search.empty()) {
102                 string name = r->name;
103                 transform (name.begin(), name.end(), name.begin(), ::tolower);
104                 if (name.find(search) == string::npos) {
105                         return;
106                 }
107         }
108
109         _recipients[_targets->AppendItem(_root, std_to_wx(r->name))] = r;
110
111         _targets->SortChildren (_root);
112 }
113
114
115 void
116 RecipientsPanel::add_recipient_clicked ()
117 {
118         RecipientDialog* d = new RecipientDialog (GetParent(), _("Add Recipient"));
119         if (d->ShowModal() == wxID_OK) {
120                 shared_ptr<DKDMRecipient> r (new DKDMRecipient(d->name(), d->notes(), d->recipient(), d->emails(), d->utc_offset_hour(), d->utc_offset_minute()));
121                 Config::instance()->add_dkdm_recipient (r);
122                 add_recipient (r);
123         }
124
125         d->Destroy ();
126 }
127
128
129 void
130 RecipientsPanel::edit_recipient_clicked ()
131 {
132         if (_selected.size() != 1) {
133                 return;
134         }
135
136         pair<wxTreeItemId, shared_ptr<DKDMRecipient> > r = *_selected.begin();
137
138         RecipientDialog* d = new RecipientDialog (
139                 GetParent(), _("Edit recipient"), r.second->name, r.second->emails, r.second->notes, r.second->utc_offset_hour(), r.second->utc_offset_minute(), r.second->recipient
140                 );
141
142         if (d->ShowModal() == wxID_OK) {
143                 r.second->name = d->name ();
144                 r.second->emails = d->emails ();
145                 r.second->notes = d->notes ();
146                 r.second->set_utc_offset_hour (d->utc_offset_hour());
147                 r.second->set_utc_offset_minute (d->utc_offset_minute());
148                 r.second->recipient = d->recipient ();
149                 _targets->SetItemText (r.first, std_to_wx(d->name()));
150                 Config::instance()->changed (Config::DKDM_RECIPIENTS);
151         }
152
153         d->Destroy ();
154 }
155
156
157 void
158 RecipientsPanel::remove_recipient_clicked ()
159 {
160         for (RecipientMap::iterator i = _selected.begin(); i != _selected.end(); ++i) {
161                 Config::instance()->remove_dkdm_recipient (i->second);
162                 _targets->Delete (i->first);
163         }
164
165         selection_changed ();
166 }
167
168
169 list<shared_ptr<DKDMRecipient> >
170 RecipientsPanel::recipients () const
171 {
172         list<shared_ptr<DKDMRecipient> > s;
173
174         for (RecipientMap::const_iterator i = _selected.begin(); i != _selected.end(); ++i) {
175                 s.push_back (i->second);
176         }
177
178         s.sort ();
179         s.unique ();
180
181         return s;
182 }
183
184
185 void
186 RecipientsPanel::selection_changed_shim (wxTreeEvent &)
187 {
188         selection_changed ();
189 }
190
191
192 void
193 RecipientsPanel::selection_changed ()
194 {
195         if (_ignore_selection_change) {
196                 return;
197         }
198
199         wxArrayTreeItemIds s;
200         _targets->GetSelections (s);
201
202         _selected.clear ();
203
204         for (size_t i = 0; i < s.GetCount(); ++i) {
205                 RecipientMap::const_iterator j = _recipients.find (s[i]);
206                 if (j != _recipients.end()) {
207                         _selected[j->first] = j->second;
208                 }
209         }
210
211         setup_sensitivity ();
212         RecipientsChanged ();
213 }
214
215
216 void
217 RecipientsPanel::add_recipients_from_config ()
218 {
219         _root = _targets->AddRoot ("Foo");
220
221         BOOST_FOREACH (shared_ptr<DKDMRecipient> i, Config::instance()->dkdm_recipients()) {
222                 add_recipient (i);
223         }
224 }
225
226
227 void
228 RecipientsPanel::search_changed ()
229 {
230         _targets->DeleteAllItems ();
231         _recipients.clear ();
232
233         add_recipients_from_config ();
234
235         _ignore_selection_change = true;
236
237         for (RecipientMap::const_iterator i = _selected.begin(); i != _selected.end(); ++i) {
238                 RecipientMap::const_iterator j = _recipients.begin ();
239                 while (j != _recipients.end() && j->second != i->second) {
240                         ++j;
241                 }
242
243                 if (j != _recipients.end()) {
244                         _targets->SelectItem (j->first);
245                 }
246         }
247
248         _ignore_selection_change = false;
249 }