GUI layout tweaks.
[dcpomatic.git] / src / wx / config_dialog.cc
1 /*
2     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 /** @file src/config_dialog.cc
21  *  @brief A dialogue to edit DCP-o-matic configuration.
22  */
23
24 #include <iostream>
25 #include <boost/lexical_cast.hpp>
26 #include <boost/filesystem.hpp>
27 #include <wx/stdpaths.h>
28 #include <wx/notebook.h>
29 #include <libdcp/colour_matrix.h>
30 #include "lib/config.h"
31 #include "lib/ratio.h"
32 #include "lib/scaler.h"
33 #include "lib/filter.h"
34 #include "lib/dcp_content_type.h"
35 #include "lib/colour_conversion.h"
36 #include "config_dialog.h"
37 #include "wx_util.h"
38 #include "filter_dialog.h"
39 #include "dir_picker_ctrl.h"
40 #include "dci_metadata_dialog.h"
41 #include "preset_colour_conversion_dialog.h"
42
43 using std::vector;
44 using std::string;
45 using std::list;
46 using boost::bind;
47 using boost::shared_ptr;
48 using boost::lexical_cast;
49
50 ConfigDialog::ConfigDialog (wxWindow* parent)
51         : wxDialog (parent, wxID_ANY, _("DCP-o-matic Preferences"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
52 {
53         wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
54         _notebook = new wxNotebook (this, wxID_ANY);
55         s->Add (_notebook, 1);
56
57         make_misc_panel ();
58         _notebook->AddPage (_misc_panel, _("Miscellaneous"), true);
59         make_colour_conversions_panel ();
60         _notebook->AddPage (_colour_conversions_panel, _("Colour conversions"), false);
61         make_metadata_panel ();
62         _notebook->AddPage (_metadata_panel, _("Metadata"), false);
63         make_tms_panel ();
64         _notebook->AddPage (_tms_panel, _("TMS"), false);
65         make_kdm_email_panel ();
66         _notebook->AddPage (_kdm_email_panel, _("KDM email"), false);
67
68         wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL);
69         overall_sizer->Add (s, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER);
70
71         wxSizer* buttons = CreateSeparatedButtonSizer (wxOK);
72         if (buttons) {
73                 overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
74         }
75
76         SetSizer (overall_sizer);
77         overall_sizer->Layout ();
78         overall_sizer->SetSizeHints (this);
79 }
80
81 void
82 ConfigDialog::make_misc_panel ()
83 {
84         _misc_panel = new wxPanel (_notebook);
85         wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
86         _misc_panel->SetSizer (s);
87
88         wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
89         table->AddGrowableCol (1, 1);
90         s->Add (table, 1, wxALL | wxEXPAND, 8);
91
92         _set_language = new wxCheckBox (_misc_panel, wxID_ANY, _("Set language"));
93         table->Add (_set_language, 1);
94         _language = new wxChoice (_misc_panel, wxID_ANY);
95         _language->Append (wxT ("English"));
96         _language->Append (wxT ("Français"));
97         _language->Append (wxT ("Italiano"));
98         _language->Append (wxT ("Español"));
99         _language->Append (wxT ("Svenska"));
100         table->Add (_language);
101
102         wxStaticText* restart = add_label_to_sizer (table, _misc_panel, _("(restart DCP-o-matic to see language changes)"), false);
103         wxFont font = restart->GetFont();
104         font.SetStyle (wxFONTSTYLE_ITALIC);
105         font.SetPointSize (font.GetPointSize() - 1);
106         restart->SetFont (font);
107         table->AddSpacer (0);
108
109         add_label_to_sizer (table, _misc_panel, _("Threads to use for encoding on this host"), true);
110         _num_local_encoding_threads = new wxSpinCtrl (_misc_panel);
111         table->Add (_num_local_encoding_threads, 1);
112
113         add_label_to_sizer (table, _misc_panel, _("Outgoing mail server"), true);
114         _mail_server = new wxTextCtrl (_misc_panel, wxID_ANY);
115         table->Add (_mail_server, 1, wxEXPAND | wxALL);
116
117         add_label_to_sizer (table, _misc_panel, _("From address for KDM emails"), true);
118         _kdm_from = new wxTextCtrl (_misc_panel, wxID_ANY);
119         table->Add (_kdm_from, 1, wxEXPAND | wxALL);
120         
121         {
122                 add_label_to_sizer (table, _misc_panel, _("Default duration of still images"), true);
123                 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
124                 _default_still_length = new wxSpinCtrl (_misc_panel);
125                 s->Add (_default_still_length);
126                 add_label_to_sizer (s, _misc_panel, _("s"), false);
127                 table->Add (s, 1);
128         }
129
130         add_label_to_sizer (table, _misc_panel, _("Default directory for new films"), true);
131 #ifdef DCPOMATIC_USE_OWN_DIR_PICKER
132         _default_directory = new DirPickerCtrl (_misc_panel);
133 #else   
134         _default_directory = new wxDirPickerCtrl (_misc_panel, wxDD_DIR_MUST_EXIST);
135 #endif
136         table->Add (_default_directory, 1, wxEXPAND);
137
138         add_label_to_sizer (table, _misc_panel, _("Default DCI name details"), true);
139         _default_dci_metadata_button = new wxButton (_misc_panel, wxID_ANY, _("Edit..."));
140         table->Add (_default_dci_metadata_button);
141
142         add_label_to_sizer (table, _misc_panel, _("Default container"), true);
143         _default_container = new wxChoice (_misc_panel, wxID_ANY);
144         table->Add (_default_container);
145
146         add_label_to_sizer (table, _misc_panel, _("Default content type"), true);
147         _default_dcp_content_type = new wxChoice (_misc_panel, wxID_ANY);
148         table->Add (_default_dcp_content_type);
149
150         {
151                 add_label_to_sizer (table, _misc_panel, _("Default JPEG2000 bandwidth"), true);
152                 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
153                 _default_j2k_bandwidth = new wxSpinCtrl (_misc_panel);
154                 s->Add (_default_j2k_bandwidth);
155                 add_label_to_sizer (s, _misc_panel, _("MBps"), false);
156                 table->Add (s, 1);
157         }
158         
159         Config* config = Config::instance ();
160
161         _set_language->SetValue (config->language ());
162
163         if (config->language().get_value_or ("") == "fr") {
164                 _language->SetSelection (1);
165         } else if (config->language().get_value_or ("") == "it") {
166                 _language->SetSelection (2);
167         } else if (config->language().get_value_or ("") == "es") {
168                 _language->SetSelection (3);
169         } else if (config->language().get_value_or ("") == "sv") {
170                 _language->SetSelection (4);
171         } else {
172                 _language->SetSelection (0);
173         }
174
175         setup_language_sensitivity ();
176
177         _set_language->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&ConfigDialog::set_language_changed, this));
178         _language->Bind     (wxEVT_COMMAND_CHOICE_SELECTED,  boost::bind (&ConfigDialog::language_changed,     this));
179
180         _num_local_encoding_threads->SetRange (1, 128);
181         _num_local_encoding_threads->SetValue (config->num_local_encoding_threads ());
182         _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&ConfigDialog::num_local_encoding_threads_changed, this));
183
184         _mail_server->SetValue (std_to_wx (config->mail_server ()));
185         _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&ConfigDialog::mail_server_changed, this));
186         _kdm_from->SetValue (std_to_wx (config->kdm_from ()));
187         _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&ConfigDialog::kdm_from_changed, this));
188
189         _default_still_length->SetRange (1, 3600);
190         _default_still_length->SetValue (config->default_still_length ());
191         _default_still_length->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&ConfigDialog::default_still_length_changed, this));
192
193         _default_directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
194         _default_directory->Bind (wxEVT_COMMAND_DIRPICKER_CHANGED, boost::bind (&ConfigDialog::default_directory_changed, this));
195
196         _default_dci_metadata_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&ConfigDialog::edit_default_dci_metadata_clicked, this));
197
198         vector<Ratio const *> ratio = Ratio::all ();
199         int n = 0;
200         for (vector<Ratio const *>::iterator i = ratio.begin(); i != ratio.end(); ++i) {
201                 _default_container->Append (std_to_wx ((*i)->nickname ()));
202                 if (*i == config->default_container ()) {
203                         _default_container->SetSelection (n);
204                 }
205                 ++n;
206         }
207
208         _default_container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&ConfigDialog::default_container_changed, this));
209         
210         vector<DCPContentType const *> const ct = DCPContentType::all ();
211         n = 0;
212         for (vector<DCPContentType const *>::const_iterator i = ct.begin(); i != ct.end(); ++i) {
213                 _default_dcp_content_type->Append (std_to_wx ((*i)->pretty_name ()));
214                 if (*i == config->default_dcp_content_type ()) {
215                         _default_dcp_content_type->SetSelection (n);
216                 }
217                 ++n;
218         }
219
220         _default_dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&ConfigDialog::default_dcp_content_type_changed, this));
221
222         _default_j2k_bandwidth->SetRange (50, 250);
223         _default_j2k_bandwidth->SetValue (config->default_j2k_bandwidth() / 1000000);
224         _default_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&ConfigDialog::default_j2k_bandwidth_changed, this));
225 }
226
227 void
228 ConfigDialog::make_tms_panel ()
229 {
230         _tms_panel = new wxPanel (_notebook);
231         wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
232         _tms_panel->SetSizer (s);
233
234         wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
235         table->AddGrowableCol (1, 1);
236         s->Add (table, 1, wxALL | wxEXPAND, 8);
237
238         add_label_to_sizer (table, _tms_panel, _("IP address"), true);
239         _tms_ip = new wxTextCtrl (_tms_panel, wxID_ANY);
240         table->Add (_tms_ip, 1, wxEXPAND);
241
242         add_label_to_sizer (table, _tms_panel, _("Target path"), true);
243         _tms_path = new wxTextCtrl (_tms_panel, wxID_ANY);
244         table->Add (_tms_path, 1, wxEXPAND);
245
246         add_label_to_sizer (table, _tms_panel, _("User name"), true);
247         _tms_user = new wxTextCtrl (_tms_panel, wxID_ANY);
248         table->Add (_tms_user, 1, wxEXPAND);
249
250         add_label_to_sizer (table, _tms_panel, _("Password"), true);
251         _tms_password = new wxTextCtrl (_tms_panel, wxID_ANY);
252         table->Add (_tms_password, 1, wxEXPAND);
253
254         Config* config = Config::instance ();
255         
256         _tms_ip->SetValue (std_to_wx (config->tms_ip ()));
257         _tms_ip->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&ConfigDialog::tms_ip_changed, this));
258         _tms_path->SetValue (std_to_wx (config->tms_path ()));
259         _tms_path->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&ConfigDialog::tms_path_changed, this));
260         _tms_user->SetValue (std_to_wx (config->tms_user ()));
261         _tms_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&ConfigDialog::tms_user_changed, this));
262         _tms_password->SetValue (std_to_wx (config->tms_password ()));
263         _tms_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&ConfigDialog::tms_password_changed, this));
264 }
265
266 void
267 ConfigDialog::make_metadata_panel ()
268 {
269         _metadata_panel = new wxPanel (_notebook);
270         wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
271         _metadata_panel->SetSizer (s);
272
273         wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
274         table->AddGrowableCol (1, 1);
275         s->Add (table, 1, wxALL | wxEXPAND, 8);
276
277         add_label_to_sizer (table, _metadata_panel, _("Issuer"), true);
278         _issuer = new wxTextCtrl (_metadata_panel, wxID_ANY);
279         table->Add (_issuer, 1, wxEXPAND);
280
281         add_label_to_sizer (table, _metadata_panel, _("Creator"), true);
282         _creator = new wxTextCtrl (_metadata_panel, wxID_ANY);
283         table->Add (_creator, 1, wxEXPAND);
284
285         Config* config = Config::instance ();
286
287         _issuer->SetValue (std_to_wx (config->dcp_metadata().issuer));
288         _issuer->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&ConfigDialog::issuer_changed, this));
289         _creator->SetValue (std_to_wx (config->dcp_metadata().creator));
290         _creator->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&ConfigDialog::creator_changed, this));
291 }
292
293 void
294 ConfigDialog::language_changed ()
295 {
296         switch (_language->GetSelection ()) {
297         case 0:
298                 Config::instance()->set_language ("en");
299                 break;
300         case 1:
301                 Config::instance()->set_language ("fr");
302                 break;
303         case 2:
304                 Config::instance()->set_language ("it");
305                 break;
306         case 3:
307                 Config::instance()->set_language ("es");
308                 break;
309         case 4:
310                 Config::instance()->set_language ("sv");
311                 break;
312         }
313 }
314
315 void
316 ConfigDialog::tms_ip_changed ()
317 {
318         Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
319 }
320
321 void
322 ConfigDialog::tms_path_changed ()
323 {
324         Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
325 }
326
327 void
328 ConfigDialog::tms_user_changed ()
329 {
330         Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
331 }
332
333 void
334 ConfigDialog::tms_password_changed ()
335 {
336         Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
337 }
338
339 void
340 ConfigDialog::num_local_encoding_threads_changed ()
341 {
342         Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ());
343 }
344
345 void
346 ConfigDialog::default_directory_changed ()
347 {
348         Config::instance()->set_default_directory (wx_to_std (_default_directory->GetPath ()));
349 }
350
351 void
352 ConfigDialog::edit_default_dci_metadata_clicked ()
353 {
354         DCIMetadataDialog* d = new DCIMetadataDialog (this, Config::instance()->default_dci_metadata ());
355         d->ShowModal ();
356         Config::instance()->set_default_dci_metadata (d->dci_metadata ());
357         d->Destroy ();
358 }
359
360 void
361 ConfigDialog::set_language_changed ()
362 {
363         setup_language_sensitivity ();
364         if (_set_language->GetValue ()) {
365                 language_changed ();
366         } else {
367                 Config::instance()->unset_language ();
368         }
369 }
370
371 void
372 ConfigDialog::setup_language_sensitivity ()
373 {
374         _language->Enable (_set_language->GetValue ());
375 }
376
377 void
378 ConfigDialog::default_still_length_changed ()
379 {
380         Config::instance()->set_default_still_length (_default_still_length->GetValue ());
381 }
382
383 void
384 ConfigDialog::default_container_changed ()
385 {
386         vector<Ratio const *> ratio = Ratio::all ();
387         Config::instance()->set_default_container (ratio[_default_container->GetSelection()]);
388 }
389
390 void
391 ConfigDialog::default_dcp_content_type_changed ()
392 {
393         vector<DCPContentType const *> ct = DCPContentType::all ();
394         Config::instance()->set_default_dcp_content_type (ct[_default_dcp_content_type->GetSelection()]);
395 }
396
397 void
398 ConfigDialog::issuer_changed ()
399 {
400         libdcp::XMLMetadata m = Config::instance()->dcp_metadata ();
401         m.issuer = wx_to_std (_issuer->GetValue ());
402         Config::instance()->set_dcp_metadata (m);
403 }
404
405 void
406 ConfigDialog::creator_changed ()
407 {
408         libdcp::XMLMetadata m = Config::instance()->dcp_metadata ();
409         m.creator = wx_to_std (_creator->GetValue ());
410         Config::instance()->set_dcp_metadata (m);
411 }
412
413 void
414 ConfigDialog::default_j2k_bandwidth_changed ()
415 {
416         Config::instance()->set_default_j2k_bandwidth (_default_j2k_bandwidth->GetValue() * 1000000);
417 }
418
419 static std::string
420 colour_conversion_column (PresetColourConversion c)
421 {
422         return c.name;
423 }
424
425 void
426 ConfigDialog::make_colour_conversions_panel ()
427 {
428         vector<string> columns;
429         columns.push_back (wx_to_std (_("Name")));
430         _colour_conversions_panel = new EditableList<PresetColourConversion, PresetColourConversionDialog> (
431                 _notebook,
432                 columns,
433                 boost::bind (&Config::colour_conversions, Config::instance()),
434                 boost::bind (&Config::set_colour_conversions, Config::instance(), _1),
435                 boost::bind (&colour_conversion_column, _1),
436                 300
437                 );
438 }
439
440 void
441 ConfigDialog::mail_server_changed ()
442 {
443         Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
444 }
445
446
447 void
448 ConfigDialog::kdm_from_changed ()
449 {
450         Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
451 }
452
453 void
454 ConfigDialog::make_kdm_email_panel ()
455 {
456         _kdm_email_panel = new wxPanel (_notebook);
457         wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
458         _kdm_email_panel->SetSizer (s);
459
460         _kdm_email = new wxTextCtrl (_kdm_email_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);
461         s->Add (_kdm_email, 1, wxEXPAND | wxALL, 12);
462
463         _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&ConfigDialog::kdm_email_changed, this));
464         _kdm_email->SetValue (wx_to_std (Config::instance()->kdm_email ()));
465 }
466
467 void
468 ConfigDialog::kdm_email_changed ()
469 {
470         Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
471 }