Fix hidden advanced preferences button in some locales (e.g. de_DE).
[dcpomatic.git] / src / wx / config_dialog.cc
1 /*
2     Copyright (C) 2012-2014 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/preferences.h>
29 #include <wx/filepicker.h>
30 #include <wx/spinctrl.h>
31 #include <libdcp/colour_matrix.h>
32 #include "lib/config.h"
33 #include "lib/ratio.h"
34 #include "lib/scaler.h"
35 #include "lib/filter.h"
36 #include "lib/dcp_content_type.h"
37 #include "lib/colour_conversion.h"
38 #include "config_dialog.h"
39 #include "wx_util.h"
40 #include "editable_list.h"
41 #include "filter_dialog.h"
42 #include "dir_picker_ctrl.h"
43 #include "isdcf_metadata_dialog.h"
44 #include "preset_colour_conversion_dialog.h"
45 #include "server_dialog.h"
46
47 using std::vector;
48 using std::string;
49 using std::list;
50 using std::cout;
51 using boost::bind;
52 using boost::shared_ptr;
53 using boost::lexical_cast;
54
55 class Page
56 {
57 public:
58         Page (wxSize panel_size, int border)
59                 : _panel_size (panel_size)
60                 , _border (border)
61         {}
62
63 protected:
64         wxPanel* make_panel (wxWindow* parent)
65         {
66                 wxPanel* panel = new wxPanel (parent, wxID_ANY, wxDefaultPosition, _panel_size);
67                 wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
68                 panel->SetSizer (s);
69                 return panel;
70         }
71         
72         wxSize _panel_size;
73         int _border;
74 };
75
76 class GeneralPage : public wxStockPreferencesPage, public Page
77 {
78 public:
79         GeneralPage (wxSize panel_size, int border)
80                 : wxStockPreferencesPage (Kind_General)
81                 , Page (panel_size, border)
82         {}
83
84         wxWindow* CreateWindow (wxWindow* parent)
85         {
86                 wxPanel* panel = make_panel (parent);
87
88                 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
89                 table->AddGrowableCol (1, 1);
90                 panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
91                 
92                 _set_language = new wxCheckBox (panel, wxID_ANY, _("Set language"));
93                 table->Add (_set_language, 1);
94                 _language = new wxChoice (panel, wxID_ANY);
95                 _language->Append (wxT ("Deutsch"));
96                 _language->Append (wxT ("English"));
97                 _language->Append (wxT ("Español"));
98                 _language->Append (wxT ("Français"));
99                 _language->Append (wxT ("Italiano"));
100                 _language->Append (wxT ("Nederlands"));
101                 _language->Append (wxT ("Svenska"));
102                 table->Add (_language);
103                 
104                 wxStaticText* restart = add_label_to_sizer (table, panel, _("(restart DCP-o-matic to see language changes)"), false);
105                 wxFont font = restart->GetFont();
106                 font.SetStyle (wxFONTSTYLE_ITALIC);
107                 font.SetPointSize (font.GetPointSize() - 1);
108                 restart->SetFont (font);
109                 table->AddSpacer (0);
110                 
111                 add_label_to_sizer (table, panel, _("Threads to use for encoding on this host"), true);
112                 _num_local_encoding_threads = new wxSpinCtrl (panel);
113                 table->Add (_num_local_encoding_threads, 1);
114
115                 
116                 _check_for_updates = new wxCheckBox (panel, wxID_ANY, _("Check for updates on startup"));
117                 table->Add (_check_for_updates, 1, wxEXPAND | wxALL);
118                 table->AddSpacer (0);
119                 
120                 _check_for_test_updates = new wxCheckBox (panel, wxID_ANY, _("Check for testing updates as well as stable ones"));
121                 table->Add (_check_for_test_updates, 1, wxEXPAND | wxALL);
122                 table->AddSpacer (0);
123                 
124                 Config* config = Config::instance ();
125                 
126                 _set_language->SetValue (config->language ());
127                 
128                 if (config->language().get_value_or ("") == "fr") {
129                         _language->SetSelection (3);
130                 } else if (config->language().get_value_or ("") == "it") {
131                         _language->SetSelection (4);
132                 } else if (config->language().get_value_or ("") == "es") {
133                         _language->SetSelection (2);
134                 } else if (config->language().get_value_or ("") == "sv") {
135                         _language->SetSelection (6);
136                 } else if (config->language().get_value_or ("") == "de") {
137                         _language->SetSelection (0);
138                 } else if (config->language().get_value_or ("") == "nl") {
139                         _language->SetSelection (5);
140                 } else {
141                         _language->SetSelection (1);
142                 }
143                 
144                 setup_language_sensitivity ();
145                 
146                 _set_language->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::set_language_changed, this));
147                 _language->Bind     (wxEVT_COMMAND_CHOICE_SELECTED,  boost::bind (&GeneralPage::language_changed,     this));
148                 
149                 _num_local_encoding_threads->SetRange (1, 128);
150                 _num_local_encoding_threads->SetValue (config->num_local_encoding_threads ());
151                 _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this));
152
153                 _check_for_updates->SetValue (config->check_for_updates ());
154                 _check_for_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_updates_changed, this));
155                 _check_for_test_updates->SetValue (config->check_for_test_updates ());
156                 _check_for_test_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
157                 
158                 return panel;
159         }
160
161 private:        
162         void setup_language_sensitivity ()
163         {
164                 _language->Enable (_set_language->GetValue ());
165         }
166
167         void set_language_changed ()
168         {
169                 setup_language_sensitivity ();
170                 if (_set_language->GetValue ()) {
171                         language_changed ();
172                 } else {
173                         Config::instance()->unset_language ();
174                 }
175         }
176
177         void language_changed ()
178         {
179                 switch (_language->GetSelection ()) {
180                 case 0:
181                         Config::instance()->set_language ("de");
182                         break;
183                 case 1:
184                         Config::instance()->set_language ("en");
185                         break;
186                 case 2:
187                         Config::instance()->set_language ("es");
188                         break;
189                 case 3:
190                         Config::instance()->set_language ("fr");
191                         break;
192                 case 4:
193                         Config::instance()->set_language ("it");
194                         break;
195                 case 5:
196                         Config::instance()->set_language ("nl");
197                         break;
198                 case 6:
199                         Config::instance()->set_language ("sv");
200                         break;
201                 }
202         }
203         
204         void check_for_updates_changed ()
205         {
206                 Config::instance()->set_check_for_updates (_check_for_updates->GetValue ());
207         }
208         
209         void check_for_test_updates_changed ()
210         {
211                 Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ());
212         }
213
214         void num_local_encoding_threads_changed ()
215         {
216                 Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ());
217         }
218
219         wxCheckBox* _set_language;
220         wxChoice* _language;
221         wxSpinCtrl* _num_local_encoding_threads;
222         wxCheckBox* _check_for_updates;
223         wxCheckBox* _check_for_test_updates;
224 };
225
226 class DefaultsPage : public wxPreferencesPage, public Page
227 {
228 public:
229         DefaultsPage (wxSize panel_size, int border)
230                 : Page (panel_size, border)
231         {}
232         
233         wxString GetName () const
234         {
235                 return _("Defaults");
236         }
237
238 #ifdef DCPOMATIC_OSX    
239         wxBitmap GetLargeIcon () const
240         {
241                 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
242         }
243 #endif  
244
245         wxWindow* CreateWindow (wxWindow* parent)
246         {
247                 wxPanel* panel = make_panel (parent);
248
249                 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
250                 table->AddGrowableCol (1, 1);
251                 panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
252                 
253                 {
254                         add_label_to_sizer (table, panel, _("Default duration of still images"), true);
255                         wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
256                         _still_length = new wxSpinCtrl (panel);
257                         s->Add (_still_length);
258                         add_label_to_sizer (s, panel, _("s"), false);
259                         table->Add (s, 1);
260                 }
261                 
262                 add_label_to_sizer (table, panel, _("Default directory for new films"), true);
263 #ifdef DCPOMATIC_USE_OWN_DIR_PICKER
264                 _directory = new DirPickerCtrl (panel);
265 #else   
266                 _directory = new wxDirPickerCtrl (panel, wxDD_DIR_MUST_EXIST);
267 #endif
268                 table->Add (_directory, 1, wxEXPAND);
269                 
270                 add_label_to_sizer (table, panel, _("Default ISDCF name details"), true);
271                 _isdcf_metadata_button = new wxButton (panel, wxID_ANY, _("Edit..."));
272                 table->Add (_isdcf_metadata_button);
273
274                 add_label_to_sizer (table, panel, _("Default scale to"), true);
275                 _scale = new wxChoice (panel, wxID_ANY);
276                 table->Add (_scale);
277                 
278                 add_label_to_sizer (table, panel, _("Default container"), true);
279                 _container = new wxChoice (panel, wxID_ANY);
280                 table->Add (_container);
281                 
282                 add_label_to_sizer (table, panel, _("Default content type"), true);
283                 _dcp_content_type = new wxChoice (panel, wxID_ANY);
284                 table->Add (_dcp_content_type);
285                 
286                 {
287                         add_label_to_sizer (table, panel, _("Default JPEG2000 bandwidth"), true);
288                         wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
289                         _j2k_bandwidth = new wxSpinCtrl (panel);
290                         s->Add (_j2k_bandwidth);
291                         add_label_to_sizer (s, panel, _("Mbit/s"), false);
292                         table->Add (s, 1);
293                 }
294                 
295                 {
296                         add_label_to_sizer (table, panel, _("Default audio delay"), true);
297                         wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
298                         _audio_delay = new wxSpinCtrl (panel);
299                         s->Add (_audio_delay);
300                         add_label_to_sizer (s, panel, _("ms"), false);
301                         table->Add (s, 1);
302                 }
303
304                 add_label_to_sizer (table, panel, _("Default issuer"), true);
305                 _issuer = new wxTextCtrl (panel, wxID_ANY);
306                 table->Add (_issuer, 1, wxEXPAND);
307
308                 Config* config = Config::instance ();
309                 
310                 _still_length->SetRange (1, 3600);
311                 _still_length->SetValue (config->default_still_length ());
312                 _still_length->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::still_length_changed, this));
313                 
314                 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
315                 _directory->Bind (wxEVT_COMMAND_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
316                 
317                 _isdcf_metadata_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this, parent));
318                 
319                 vector<VideoContentScale> scales = VideoContentScale::all ();
320                 for (size_t i = 0; i < scales.size(); ++i) {
321                         _scale->Append (std_to_wx (scales[i].name ()));
322                         if (scales[i] == config->default_scale ()) {
323                                 _scale->SetSelection (i);
324                         }
325                 }
326
327                 vector<Ratio const *> ratios = Ratio::all ();
328                 for (size_t i = 0; i < ratios.size(); ++i) {
329                         _container->Append (std_to_wx (ratios[i]->nickname ()));
330                         if (ratios[i] == config->default_container ()) {
331                                 _container->SetSelection (i);
332                         }
333                 }
334                 
335                 _scale->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::scale_changed, this));
336                 _container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::container_changed, this));
337                 
338                 vector<DCPContentType const *> const ct = DCPContentType::all ();
339                 for (size_t i = 0; i < ct.size(); ++i) {
340                         _dcp_content_type->Append (std_to_wx (ct[i]->pretty_name ()));
341                         if (ct[i] == config->default_dcp_content_type ()) {
342                                 _dcp_content_type->SetSelection (i);
343                         }
344                 }
345                 
346                 _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
347                 
348                 _j2k_bandwidth->SetRange (50, 250);
349                 _j2k_bandwidth->SetValue (config->default_j2k_bandwidth() / 1000000);
350                 _j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
351                 
352                 _audio_delay->SetRange (-1000, 1000);
353                 _audio_delay->SetValue (config->default_audio_delay ());
354                 _audio_delay->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::audio_delay_changed, this));
355
356                 _issuer->SetValue (std_to_wx (config->dcp_issuer ()));
357                 _issuer->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&DefaultsPage::issuer_changed, this));
358
359                 return panel;
360         }
361
362 private:
363         void j2k_bandwidth_changed ()
364         {
365                 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
366         }
367         
368         void audio_delay_changed ()
369         {
370                 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
371         }
372
373         void directory_changed ()
374         {
375                 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
376         }
377
378         void edit_isdcf_metadata_clicked (wxWindow* parent)
379         {
380                 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (parent, Config::instance()->default_isdcf_metadata ());
381                 d->ShowModal ();
382                 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
383                 d->Destroy ();
384         }
385
386         void still_length_changed ()
387         {
388                 Config::instance()->set_default_still_length (_still_length->GetValue ());
389         }
390
391         void scale_changed ()
392         {
393                 vector<VideoContentScale> scale = VideoContentScale::all ();
394                 Config::instance()->set_default_scale (scale[_scale->GetSelection()]);
395         }
396         
397         void container_changed ()
398         {
399                 vector<Ratio const *> ratio = Ratio::all ();
400                 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
401         }
402         
403         void dcp_content_type_changed ()
404         {
405                 vector<DCPContentType const *> ct = DCPContentType::all ();
406                 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
407         }
408
409         void issuer_changed ()
410         {
411                 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
412         }
413         
414         wxSpinCtrl* _j2k_bandwidth;
415         wxSpinCtrl* _audio_delay;
416         wxButton* _isdcf_metadata_button;
417         wxSpinCtrl* _still_length;
418 #ifdef DCPOMATIC_USE_OWN_DIR_PICKER
419         DirPickerCtrl* _directory;
420 #else
421         wxDirPickerCtrl* _directory;
422 #endif
423         wxChoice* _scale;
424         wxChoice* _container;
425         wxChoice* _dcp_content_type;
426         wxTextCtrl* _issuer;
427 };
428
429 class EncodingServersPage : public wxPreferencesPage, public Page
430 {
431 public:
432         EncodingServersPage (wxSize panel_size, int border)
433                 : Page (panel_size, border)
434         {}
435         
436         wxString GetName () const
437         {
438                 return _("Servers");
439         }
440
441 #ifdef DCPOMATIC_OSX    
442         wxBitmap GetLargeIcon () const
443         {
444                 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
445         }
446 #endif  
447
448         wxWindow* CreateWindow (wxWindow* parent)
449         {
450                 wxPanel* panel = make_panel (parent);
451                 
452                 _use_any_servers = new wxCheckBox (panel, wxID_ANY, _("Use all servers"));
453                 panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
454                 
455                 vector<string> columns;
456                 columns.push_back (wx_to_std (_("IP address / host name")));
457                 _servers_list = new EditableList<string, ServerDialog> (
458                         panel,
459                         columns,
460                         boost::bind (&Config::servers, Config::instance()),
461                         boost::bind (&Config::set_servers, Config::instance(), _1),
462                         boost::bind (&EncodingServersPage::server_column, this, _1)
463                         );
464                 
465                 panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
466                 
467                 _use_any_servers->SetValue (Config::instance()->use_any_servers ());
468                 _use_any_servers->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
469
470                 return panel;
471         }
472
473 private:        
474
475         void use_any_servers_changed ()
476         {
477                 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
478         }
479
480         string server_column (string s)
481         {
482                 return s;
483         }
484
485         wxCheckBox* _use_any_servers;
486         EditableList<string, ServerDialog>* _servers_list;
487 };
488
489 class ColourConversionsPage : public wxPreferencesPage, public Page
490 {
491 public:
492         ColourConversionsPage (wxSize panel_size, int border)
493                 : Page (panel_size, border)
494         {}
495         
496         wxString GetName () const
497         {
498                 return _("Colour Conversions");
499         }
500
501 #ifdef DCPOMATIC_OSX    
502         wxBitmap GetLargeIcon () const
503         {
504                 return wxBitmap ("colour_conversions", wxBITMAP_TYPE_PNG_RESOURCE);
505         }
506 #endif  
507         wxWindow* CreateWindow (wxWindow* parent)
508         {
509                 wxPanel* panel = make_panel (parent);
510
511                 vector<string> columns;
512                 columns.push_back (wx_to_std (_("Name")));
513                 wxPanel* list = new EditableList<PresetColourConversion, PresetColourConversionDialog> (
514                         panel,
515                         columns,
516                         boost::bind (&Config::colour_conversions, Config::instance()),
517                         boost::bind (&Config::set_colour_conversions, Config::instance(), _1),
518                         boost::bind (&ColourConversionsPage::colour_conversion_column, this, _1),
519                         300
520                         );
521
522                 panel->GetSizer()->Add (list, 1, wxEXPAND | wxALL, _border);
523                 return panel;
524         }
525
526 private:
527         string colour_conversion_column (PresetColourConversion c)
528         {
529                 return c.name;
530         }
531 };
532
533 class TMSPage : public wxPreferencesPage, public Page
534 {
535 public:
536         TMSPage (wxSize panel_size, int border)
537                 : Page (panel_size, border)
538         {}
539
540         wxString GetName () const
541         {
542                 return _("TMS");
543         }
544
545 #ifdef DCPOMATIC_OSX    
546         wxBitmap GetLargeIcon () const
547         {
548                 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
549         }
550 #endif  
551
552         wxWindow* CreateWindow (wxWindow* parent)
553         {
554                 wxPanel* panel = make_panel (parent);
555
556                 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
557                 table->AddGrowableCol (1, 1);
558                 panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
559                 
560                 add_label_to_sizer (table, panel, _("IP address"), true);
561                 _tms_ip = new wxTextCtrl (panel, wxID_ANY);
562                 table->Add (_tms_ip, 1, wxEXPAND);
563                 
564                 add_label_to_sizer (table, panel, _("Target path"), true);
565                 _tms_path = new wxTextCtrl (panel, wxID_ANY);
566                 table->Add (_tms_path, 1, wxEXPAND);
567                 
568                 add_label_to_sizer (table, panel, _("User name"), true);
569                 _tms_user = new wxTextCtrl (panel, wxID_ANY);
570                 table->Add (_tms_user, 1, wxEXPAND);
571                 
572                 add_label_to_sizer (table, panel, _("Password"), true);
573                 _tms_password = new wxTextCtrl (panel, wxID_ANY);
574                 table->Add (_tms_password, 1, wxEXPAND);
575                 
576                 Config* config = Config::instance ();
577                 
578                 _tms_ip->SetValue (std_to_wx (config->tms_ip ()));
579                 _tms_ip->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_ip_changed, this));
580                 _tms_path->SetValue (std_to_wx (config->tms_path ()));
581                 _tms_path->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_path_changed, this));
582                 _tms_user->SetValue (std_to_wx (config->tms_user ()));
583                 _tms_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_user_changed, this));
584                 _tms_password->SetValue (std_to_wx (config->tms_password ()));
585                 _tms_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_password_changed, this));
586
587                 return panel;
588         }
589
590 private:
591         void tms_ip_changed ()
592         {
593                 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
594         }
595         
596         void tms_path_changed ()
597         {
598                 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
599         }
600         
601         void tms_user_changed ()
602         {
603                 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
604         }
605         
606         void tms_password_changed ()
607         {
608                 Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
609         }
610
611         wxTextCtrl* _tms_ip;
612         wxTextCtrl* _tms_path;
613         wxTextCtrl* _tms_user;
614         wxTextCtrl* _tms_password;
615 };
616
617 class KDMEmailPage : public wxPreferencesPage, public Page
618 {
619 public:
620
621         KDMEmailPage (wxSize panel_size, int border)
622                 : Page (panel_size, border)
623         {}
624         
625         wxString GetName () const
626         {
627                 return _("KDM Email");
628         }
629
630 #ifdef DCPOMATIC_OSX    
631         wxBitmap GetLargeIcon () const
632         {
633                 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
634         }
635 #endif  
636
637         wxWindow* CreateWindow (wxWindow* parent)
638         {
639 #ifdef DCPOMATIC_OSX            
640                 /* We have to force both width and height of this one */
641                 wxPanel* panel = new wxPanel (parent, wxID_ANY, wxDefaultPosition, wxSize (480, 128));
642 #else
643                 wxPanel* panel = new wxPanel (parent);
644 #endif
645                 wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
646                 panel->SetSizer (s);
647
648                 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
649                 table->AddGrowableCol (1, 1);
650                 panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
651
652                 add_label_to_sizer (table, panel, _("Outgoing mail server"), true);
653                 _mail_server = new wxTextCtrl (panel, wxID_ANY);
654                 table->Add (_mail_server, 1, wxEXPAND | wxALL);
655                 
656                 add_label_to_sizer (table, panel, _("Mail user name"), true);
657                 _mail_user = new wxTextCtrl (panel, wxID_ANY);
658                 table->Add (_mail_user, 1, wxEXPAND | wxALL);
659                 
660                 add_label_to_sizer (table, panel, _("Mail password"), true);
661                 _mail_password = new wxTextCtrl (panel, wxID_ANY);
662                 table->Add (_mail_password, 1, wxEXPAND | wxALL);
663                 
664                 wxStaticText* plain = add_label_to_sizer (table, panel, _("(password will be stored on disk in plaintext)"), false);
665                 wxFont font = plain->GetFont();
666                 font.SetStyle (wxFONTSTYLE_ITALIC);
667                 font.SetPointSize (font.GetPointSize() - 1);
668                 plain->SetFont (font);
669                 table->AddSpacer (0);
670
671                 add_label_to_sizer (table, panel, _("Subject"), true);
672                 _kdm_subject = new wxTextCtrl (panel, wxID_ANY);
673                 table->Add (_kdm_subject, 1, wxEXPAND | wxALL);
674                 
675                 add_label_to_sizer (table, panel, _("From address"), true);
676                 _kdm_from = new wxTextCtrl (panel, wxID_ANY);
677                 table->Add (_kdm_from, 1, wxEXPAND | wxALL);
678
679                 add_label_to_sizer (table, panel, _("CC address"), true);
680                 _kdm_cc = new wxTextCtrl (panel, wxID_ANY);
681                 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
682
683                 add_label_to_sizer (table, panel, _("BCC address"), true);
684                 _kdm_bcc = new wxTextCtrl (panel, wxID_ANY);
685                 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
686                 
687                 _kdm_email = new wxTextCtrl (panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (480, 128), wxTE_MULTILINE);
688                 panel->GetSizer()->Add (_kdm_email, 1, wxEXPAND | wxALL, _border);
689
690                 _reset_kdm_email = new wxButton (panel, wxID_ANY, _("Reset to default text"));
691                 panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
692
693                 Config* config = Config::instance ();
694                 _mail_server->SetValue (std_to_wx (config->mail_server ()));
695                 _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_server_changed, this));
696                 _mail_user->SetValue (std_to_wx (config->mail_user ()));
697                 _mail_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_user_changed, this));
698                 _mail_password->SetValue (std_to_wx (config->mail_password ()));
699                 _mail_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_password_changed, this));
700                 _kdm_subject->SetValue (std_to_wx (config->kdm_subject ()));
701                 _kdm_subject->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
702                 _kdm_from->SetValue (std_to_wx (config->kdm_from ()));
703                 _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_from_changed, this));
704                 _kdm_cc->SetValue (std_to_wx (config->kdm_cc ()));
705                 _kdm_cc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_cc_changed, this));
706                 _kdm_bcc->SetValue (std_to_wx (config->kdm_bcc ()));
707                 _kdm_bcc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
708                 _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_email_changed, this));
709                 _kdm_email->SetValue (std_to_wx (Config::instance()->kdm_email ()));
710                 _reset_kdm_email->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMEmailPage::reset_kdm_email, this));
711
712                 return panel;
713         }
714
715 private:
716         void mail_server_changed ()
717         {
718                 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
719         }
720         
721         void mail_user_changed ()
722         {
723                 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
724         }
725         
726         void mail_password_changed ()
727         {
728                 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
729         }
730
731         void kdm_subject_changed ()
732         {
733                 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
734         }
735         
736         void kdm_from_changed ()
737         {
738                 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
739         }
740
741         void kdm_cc_changed ()
742         {
743                 Config::instance()->set_kdm_cc (wx_to_std (_kdm_cc->GetValue ()));
744         }
745
746         void kdm_bcc_changed ()
747         {
748                 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
749         }
750         
751         void kdm_email_changed ()
752         {
753                 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
754         }
755
756         void reset_kdm_email ()
757         {
758                 Config::instance()->reset_kdm_email ();
759                 _kdm_email->SetValue (wx_to_std (Config::instance()->kdm_email ()));
760         }
761
762         wxTextCtrl* _mail_server;
763         wxTextCtrl* _mail_user;
764         wxTextCtrl* _mail_password;
765         wxTextCtrl* _kdm_subject;
766         wxTextCtrl* _kdm_from;
767         wxTextCtrl* _kdm_cc;
768         wxTextCtrl* _kdm_bcc;
769         wxTextCtrl* _kdm_email;
770         wxButton* _reset_kdm_email;
771 };
772
773 class AdvancedPage : public wxStockPreferencesPage, public Page
774 {
775 public:
776
777         AdvancedPage (wxSize panel_size, int border)
778                 : wxStockPreferencesPage (Kind_Advanced)
779                 , Page (panel_size, border)
780         {}
781         
782         wxWindow* CreateWindow (wxWindow* parent)
783         {
784                 wxPanel* panel = make_panel (parent);
785
786                 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
787                 table->AddGrowableCol (1, 1);
788                 panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
789
790                 {
791                         add_label_to_sizer (table, panel, _("Maximum JPEG2000 bandwidth"), true);
792                         wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
793                         _maximum_j2k_bandwidth = new wxSpinCtrl (panel);
794                         s->Add (_maximum_j2k_bandwidth, 1);
795                         add_label_to_sizer (s, panel, _("Mbit/s"), false);
796                         table->Add (s, 1);
797                 }
798
799                 _allow_any_dcp_frame_rate = new wxCheckBox (panel, wxID_ANY, _("Allow any DCP frame rate"));
800                 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
801                 table->AddSpacer (0);
802
803 #ifdef __WXOSX__
804                 wxStaticText* m = new wxStaticText (panel, wxID_ANY, _("Log:"));
805                 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL | wxALIGN_RIGHT, 6);
806 #else           
807                 wxStaticText* m = new wxStaticText (panel, wxID_ANY, _("Log"));
808                 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL, 6);
809 #endif          
810                 
811                 {
812                         wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
813                         _log_general = new wxCheckBox (panel, wxID_ANY, _("General"));
814                         t->Add (_log_general, 1, wxEXPAND | wxALL);
815                         _log_warning = new wxCheckBox (panel, wxID_ANY, _("Warnings"));
816                         t->Add (_log_warning, 1, wxEXPAND | wxALL);
817                         _log_error = new wxCheckBox (panel, wxID_ANY, _("Errors"));
818                         t->Add (_log_error, 1, wxEXPAND | wxALL);
819                         _log_timing = new wxCheckBox (panel, wxID_ANY, S_("Config|Timing"));
820                         t->Add (_log_timing, 1, wxEXPAND | wxALL);
821                         table->Add (t, 0, wxALL, 6);
822                 }
823
824                 Config* config = Config::instance ();
825                 
826                 _maximum_j2k_bandwidth->SetRange (1, 500);
827                 _maximum_j2k_bandwidth->SetValue (config->maximum_j2k_bandwidth() / 1000000);
828                 _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
829                 _allow_any_dcp_frame_rate->SetValue (config->allow_any_dcp_frame_rate ());
830                 _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
831                 _log_general->SetValue (config->log_types() & Log::TYPE_GENERAL);
832                 _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
833                 _log_warning->SetValue (config->log_types() & Log::TYPE_WARNING);
834                 _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
835                 _log_error->SetValue (config->log_types() & Log::TYPE_ERROR);
836                 _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
837                 _log_timing->SetValue (config->log_types() & Log::TYPE_TIMING);
838                 _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
839                 
840                 return panel;
841         }
842
843 private:
844
845         void maximum_j2k_bandwidth_changed ()
846         {
847                 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
848         }
849
850         void allow_any_dcp_frame_rate_changed ()
851         {
852                 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
853         }
854
855         void log_changed ()
856         {
857                 int types = 0;
858                 if (_log_general->GetValue ()) {
859                         types |= Log::TYPE_GENERAL;
860                 }
861                 if (_log_warning->GetValue ()) {
862                         types |= Log::TYPE_WARNING;
863                 }
864                 if (_log_error->GetValue ())  {
865                         types |= Log::TYPE_ERROR;
866                 }
867                 if (_log_timing->GetValue ()) {
868                         types |= Log::TYPE_TIMING;
869                 }
870                 Config::instance()->set_log_types (types);
871         }
872         
873         wxSpinCtrl* _maximum_j2k_bandwidth;
874         wxCheckBox* _allow_any_dcp_frame_rate;
875         wxCheckBox* _log_general;
876         wxCheckBox* _log_warning;
877         wxCheckBox* _log_error;
878         wxCheckBox* _log_timing;
879 };
880         
881 wxPreferencesEditor*
882 create_config_dialog ()
883 {
884         wxPreferencesEditor* e = new wxPreferencesEditor ();
885
886 #ifdef DCPOMATIC_OSX
887         /* Width that we force some of the config panels to be on OSX so that
888            the containing window doesn't shrink too much when we select those panels.
889            This is obviously an unpleasant hack.
890         */
891         wxSize ps = wxSize (520, -1);
892         int const border = 16;
893 #else
894         wxSize ps = wxSize (-1, -1);
895         int const border = 8;
896 #endif
897         
898         e->AddPage (new GeneralPage (ps, border));
899         e->AddPage (new DefaultsPage (ps, border));
900         e->AddPage (new EncodingServersPage (ps, border));
901         e->AddPage (new ColourConversionsPage (ps, border));
902         e->AddPage (new TMSPage (ps, border));
903         e->AddPage (new KDMEmailPage (ps, border));
904         e->AddPage (new AdvancedPage (ps, border));
905         return e;
906 }