Optimize automation-event process splitting
[ardour.git] / gtk2_ardour / export_filename_selector.cc
1 /*
2     Copyright (C) 2008 Paul Davis
3     Author: Sakari Bergen
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 */
20
21 #include <gtkmm/filechooserdialog.h>
22 #include <gtkmm/messagedialog.h>
23 #include <gtkmm/stock.h>
24
25 #include "pbd/openuri.h"
26 #include "export_filename_selector.h"
27
28 #include "pbd/i18n.h"
29
30 using namespace ARDOUR;
31
32 ExportFilenameSelector::ExportFilenameSelector () :
33         include_label ("", Gtk::ALIGN_LEFT),
34
35         label_label (_("Label:"), Gtk::ALIGN_LEFT),
36         timespan_checkbox (_("Timespan Name")),
37         revision_checkbox (_("Revision:")),
38
39         path_label (_("Folder:"), Gtk::ALIGN_LEFT),
40         browse_button (_("Browse")),
41         open_button (_("Open Folder")),
42
43         example_filename_label ("", Gtk::ALIGN_LEFT),
44         _require_timespan (false)
45 {
46         include_label.set_markup (_("Build filename(s) from these components:"));
47
48         session_snap_name.append_text (_("No Name"));
49         session_snap_name.append_text (_("Session Name"));
50         session_snap_name.append_text (_("Snapshot Name"));
51         session_snap_name.set_active (0);
52
53         pack_start (path_hbox, false, false, 12);
54         pack_start (include_label, false, false, 6);
55         pack_start (include_hbox, false, false, 0);
56         pack_start (example_filename_label, false, false, 12);
57
58         include_hbox.pack_start (session_snap_name, false, false, 3);
59         include_hbox.pack_start (label_label, false, false, 3);
60         include_hbox.pack_start (label_entry, false, false, 3);
61         include_hbox.pack_start (revision_checkbox, false, false, 3);
62         include_hbox.pack_start (revision_spinbutton, false, false, 3);
63         include_hbox.pack_start (timespan_checkbox, false, false, 3);
64         include_hbox.pack_start (date_format_combo, false, false, 3);
65         include_hbox.pack_start (time_format_combo, false, false, 3);
66
67         label_entry.set_activates_default ();
68
69         path_hbox.pack_start (path_label, false, false, 3);
70         path_hbox.pack_start (path_entry, true, true, 3);
71         path_hbox.pack_start (browse_button, false, false, 3);
72         path_hbox.pack_start (open_button, false, false, 3); // maybe Mixbus only ?
73
74         path_entry.set_activates_default ();
75
76         label_sizegroup = Gtk::SizeGroup::create (Gtk::SIZE_GROUP_HORIZONTAL);
77         label_sizegroup->add_widget (label_label);
78         label_sizegroup->add_widget (path_label);
79
80         /* Date */
81
82         date_format_list = Gtk::ListStore::create (date_format_cols);
83         date_format_combo.set_model (date_format_list);
84         date_format_combo.pack_start (date_format_cols.label);
85
86         date_format_combo.signal_changed().connect (sigc::mem_fun (*this, &ExportFilenameSelector::change_date_format));
87
88         /* Time */
89
90         time_format_list = Gtk::ListStore::create (time_format_cols);
91         time_format_combo.set_model (time_format_list);
92         time_format_combo.pack_start (time_format_cols.label);
93
94         time_format_combo.signal_changed().connect (sigc::mem_fun (*this, &ExportFilenameSelector::change_time_format));
95
96         /* Revision */
97
98         revision_spinbutton.set_digits (0);
99         revision_spinbutton.set_increments (1, 10);
100         revision_spinbutton.set_range (1, 1000);
101         revision_spinbutton.set_sensitive (false);
102
103         /* Signals */
104
105         label_entry.signal_changed().connect (sigc::mem_fun (*this, &ExportFilenameSelector::update_label));
106         path_entry.signal_changed().connect (sigc::mem_fun (*this, &ExportFilenameSelector::update_folder));
107         path_entry.signal_activate().connect (sigc::mem_fun (*this, &ExportFilenameSelector::check_folder), false);
108
109         session_snap_name.signal_changed().connect (sigc::mem_fun (*this, &ExportFilenameSelector::change_session_selection));
110         timespan_checkbox.signal_toggled().connect (sigc::mem_fun (*this, &ExportFilenameSelector::change_timespan_selection));
111
112         revision_checkbox.signal_toggled().connect (sigc::mem_fun (*this, &ExportFilenameSelector::change_revision_selection));
113         revision_spinbutton.signal_value_changed().connect (sigc::mem_fun (*this, &ExportFilenameSelector::change_revision_value));
114
115         browse_button.signal_clicked().connect (sigc::mem_fun (*this, &ExportFilenameSelector::open_browse_dialog));
116         open_button.signal_clicked().connect (sigc::mem_fun (*this, &ExportFilenameSelector::open_folder));
117 }
118
119 ExportFilenameSelector::~ExportFilenameSelector ()
120 {
121
122 }
123
124 void
125 ExportFilenameSelector::load_state ()
126 {
127         if (!filename) {
128                 return;
129         }
130
131         label_entry.set_text (filename->include_label ? filename->get_label() : "");
132         if (filename->include_session) {
133                 if (filename->use_session_snapshot_name) {
134                         session_snap_name.set_active (2);
135                 } else {
136                         session_snap_name.set_active (1);
137                 }
138         } else {
139                 session_snap_name.set_active (0);
140         }
141         timespan_checkbox.set_active (filename->include_timespan);
142         revision_checkbox.set_active (filename->include_revision);
143         revision_spinbutton.set_value (filename->get_revision());
144         path_entry.set_text (filename->get_folder());
145
146         Gtk::TreeModel::Children::iterator it;
147
148         for (it = date_format_list->children().begin(); it != date_format_list->children().end(); ++it) {
149                 if (it->get_value (date_format_cols.format) == filename->get_date_format()) {
150                         date_format_combo.set_active (it);
151                 }
152         }
153
154         for (it = time_format_list->children().begin(); it != time_format_list->children().end(); ++it) {
155                 if (it->get_value (time_format_cols.format) == filename->get_time_format()) {
156                         time_format_combo.set_active (it);
157                 }
158         }
159 }
160
161 void
162 ExportFilenameSelector::set_state (ARDOUR::ExportProfileManager::FilenameStatePtr state_, ARDOUR::Session * session_)
163 {
164         SessionHandlePtr::set_session (session_);
165
166         filename = state_->filename;
167
168         /* Fill combo boxes */
169
170         Gtk::TreeModel::iterator iter;
171         Gtk::TreeModel::Row row;
172
173         /* Dates */
174
175         date_format_list->clear();
176
177         iter = date_format_list->append();
178         row = *iter;
179         row[date_format_cols.format] = ExportFilename::D_None;
180         row[date_format_cols.label] = filename->get_date_format_str (ExportFilename::D_None);
181
182         iter = date_format_list->append();
183         row = *iter;
184         row[date_format_cols.format] = ExportFilename::D_ISO;
185         row[date_format_cols.label] = filename->get_date_format_str (ExportFilename::D_ISO);
186
187         iter = date_format_list->append();
188         row = *iter;
189         row[date_format_cols.format] = ExportFilename::D_ISOShortY;
190         row[date_format_cols.label] = filename->get_date_format_str (ExportFilename::D_ISOShortY);
191
192         iter = date_format_list->append();
193         row = *iter;
194         row[date_format_cols.format] = ExportFilename::D_BE;
195         row[date_format_cols.label] = filename->get_date_format_str (ExportFilename::D_BE);
196
197         iter = date_format_list->append();
198         row = *iter;
199         row[date_format_cols.format] = ExportFilename::D_BEShortY;
200         row[date_format_cols.label] = filename->get_date_format_str (ExportFilename::D_BEShortY);
201
202         /* Times */
203
204         time_format_list->clear();
205
206         iter = time_format_list->append();
207         row = *iter;
208         row[time_format_cols.format] = ExportFilename::T_None;
209         row[time_format_cols.label] = filename->get_time_format_str (ExportFilename::T_None);
210
211         iter = time_format_list->append();
212         row = *iter;
213         row[time_format_cols.format] = ExportFilename::T_NoDelim;
214         row[time_format_cols.label] = filename->get_time_format_str (ExportFilename::T_NoDelim);
215
216         iter = time_format_list->append();
217         row = *iter;
218         row[time_format_cols.format] = ExportFilename::T_Delim;
219         row[time_format_cols.label] = filename->get_time_format_str (ExportFilename::T_Delim);
220
221         /* Load state */
222
223         load_state();
224
225 }
226
227 void
228 ExportFilenameSelector::set_example_filename (std::string filename)
229 {
230         if (filename == "") {
231                 example_filename_label.set_markup (_("<small><i>Sorry, no example filename can be shown at the moment</i></small>"));
232         } else {
233                 example_filename_label.set_markup (string_compose(_("<i>Current (approximate) filename</i>: \"%1\""), filename));
234         }
235 }
236
237 void
238 ExportFilenameSelector::update_label ()
239 {
240         if (!filename) {
241                 return;
242         }
243
244         filename->set_label (label_entry.get_text());
245
246         filename->include_label = !label_entry.get_text().empty();
247         CriticalSelectionChanged();
248 }
249
250 void
251 ExportFilenameSelector::update_folder ()
252 {
253         if (!filename) {
254                 return;
255         }
256
257         filename->set_folder (path_entry.get_text());
258         CriticalSelectionChanged();
259 }
260
261 void
262 ExportFilenameSelector::check_folder ()
263 {
264         if (!filename) {
265                 return;
266         }
267
268         if (!Glib::file_test (path_entry.get_text(), Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
269                 Gtk::MessageDialog msg (string_compose (_("%1: this is only the directory/folder name, not the filename.\n\
270 The filename will be chosen from the information just above the folder selector."), path_entry.get_text()));
271                 msg.run ();
272                 path_entry.set_text (Glib::path_get_dirname (path_entry.get_text()));
273                 filename->set_folder (path_entry.get_text());
274                 CriticalSelectionChanged();
275         }
276 }
277
278 void
279 ExportFilenameSelector::change_date_format ()
280 {
281         if (!filename) {
282                 return;
283         }
284
285         DateFormat format = date_format_combo.get_active()->get_value (date_format_cols.format);
286         filename->set_date_format (format);
287         CriticalSelectionChanged();
288 }
289
290 void
291 ExportFilenameSelector::change_time_format ()
292 {
293         if (!filename) {
294                 return;
295         }
296
297         TimeFormat format = time_format_combo.get_active()->get_value (time_format_cols.format);
298         filename->set_time_format (format);
299         CriticalSelectionChanged();
300 }
301
302 void
303 ExportFilenameSelector::require_timespan (bool r)
304 {
305         _require_timespan = r;
306         update_timespan_sensitivity ();
307 }
308
309 void
310 ExportFilenameSelector::update_timespan_sensitivity ()
311 {
312         bool implicit = _require_timespan;
313
314         if (!implicit
315                         && !filename->include_session
316                         && !filename->include_label
317                         && !filename->include_revision
318                         && !filename->include_channel_config
319                         && !filename->include_channel
320                         && !filename->include_date
321                         && !filename->include_format_name) {
322                 implicit = true;
323         }
324
325         // remember prev state, force enable if implicit active.
326         if (implicit && !timespan_checkbox.get_inconsistent()) {
327                 timespan_checkbox.set_inconsistent (true);
328                 filename->include_timespan = true;
329         }
330         else if (!implicit && timespan_checkbox.get_inconsistent()) {
331                 filename->include_timespan = timespan_checkbox.get_active();
332                 timespan_checkbox.set_inconsistent (false);
333         }
334
335 }
336
337 void
338 ExportFilenameSelector::change_timespan_selection ()
339 {
340         if (!filename) {
341                 return;
342         }
343         if (timespan_checkbox.get_inconsistent()) {
344                 return;
345         }
346
347         filename->include_timespan = timespan_checkbox.get_active();
348         CriticalSelectionChanged();
349 }
350
351 void
352 ExportFilenameSelector::change_session_selection ()
353 {
354         if (!filename) {
355                 return;
356         }
357
358         switch (session_snap_name.get_active_row_number ()) {
359                 case 1:
360                         filename->include_session = true;
361                         filename->use_session_snapshot_name = false;
362                         break;
363                 case 2:
364                         filename->include_session = true;
365                         filename->use_session_snapshot_name = true;
366                         break;
367                 default:
368                         filename->include_session = false;
369                         filename->use_session_snapshot_name = false;
370                         break;
371         }
372         CriticalSelectionChanged();
373 }
374
375 void
376 ExportFilenameSelector::change_revision_selection ()
377 {
378         if (!filename) {
379                 return;
380         }
381
382         bool selected = revision_checkbox.get_active();
383         filename->include_revision = selected;
384
385         revision_spinbutton.set_sensitive (selected);
386         CriticalSelectionChanged();
387 }
388
389 void
390 ExportFilenameSelector::change_revision_value ()
391 {
392         if (!filename) {
393                 return;
394         }
395
396         filename->set_revision ((uint32_t) revision_spinbutton.get_value_as_int());
397         CriticalSelectionChanged();
398 }
399
400 void
401 ExportFilenameSelector::open_folder ()
402 {
403         const std::string& dir (path_entry.get_text());
404         if (!Glib::file_test (dir, Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
405                 Gtk::MessageDialog msg (string_compose (_("%1: this is not a valid directory/folder."), dir));
406                 msg.run ();
407                 return;
408         }
409         PBD::open_folder (dir);
410 }
411
412 void
413 ExportFilenameSelector::open_browse_dialog ()
414 {
415         Gtk::FileChooserDialog dialog(_("Choose export folder"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
416         //dialog.set_transient_for(*this);
417         dialog.set_filename (path_entry.get_text());
418
419         dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
420         dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
421
422         while (true) {
423                 int result = dialog.run();
424
425                 if (result == Gtk::RESPONSE_OK) {
426                         std::string filename = dialog.get_filename();
427
428                         if (!Glib::file_test (filename, Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
429                                 Gtk::MessageDialog msg (string_compose (_("%1: this is only the directory/folder name, not the filename.\n\
430 The filename will be chosen from the information just above the folder selector."), filename));
431                                 msg.run ();
432                                 continue;
433                         }
434
435                         if (filename.length()) {
436                                 path_entry.set_text (filename);
437                                 break;
438                         }
439                 }
440                 break;
441         }
442
443         CriticalSelectionChanged();
444 }