500ca3ea094f9a0fe51a8901de1d9d1385956522
[ardour.git] / gtk2_ardour / session_import_dialog.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 "session_import_dialog.h"
22
23 #include "pbd/failed_constructor.h"
24
25 #include "ardour/audio_region_importer.h"
26 #include "ardour/audio_playlist_importer.h"
27 #include "ardour/audio_track_importer.h"
28 #include "ardour/location_importer.h"
29 #include "ardour/tempo_map_importer.h"
30
31 #include <gtkmm2ext/utils.h>
32 #include <gtkmm2ext/window_title.h>
33
34 #include "prompter.h"
35 #include "i18n.h"
36
37 using namespace std;
38 using namespace ARDOUR;
39
40 SessionImportDialog::SessionImportDialog (ARDOUR::Session & target) :
41   ArdourDialog (_("Import from session")),
42   target (target),
43   file_browse_button (_("Browse"))
44 {
45         // File entry
46         file_entry.set_name ("ImportFileNameEntry");
47         file_entry.set_text ("/");
48         Gtkmm2ext::set_size_request_to_display_given_text (file_entry, X_("Kg/quite/a/reasonable/size/for/files/i/think"), 5, 8);
49
50         file_browse_button.set_name ("EditorGTKButton");
51         file_browse_button.signal_clicked().connect (mem_fun(*this, &SessionImportDialog::browse));
52
53         file_hbox.set_spacing (5);
54         file_hbox.set_border_width (5);
55         file_hbox.pack_start (file_entry, true, true);
56         file_hbox.pack_start (file_browse_button, false, false);
57
58         file_frame.add (file_hbox);
59         file_frame.set_border_width (5);
60         file_frame.set_name ("ImportFrom");
61         file_frame.set_label (_("Import from Session"));
62
63         get_vbox()->pack_start (file_frame, false, false);
64
65         // Session browser
66         session_tree = Gtk::TreeStore::create (sb_cols);
67         session_browser.set_model (session_tree);
68
69         session_browser.set_name ("SessionBrowser");
70         session_browser.append_column (_("Elements"), sb_cols.name);
71         session_browser.append_column_editable (_("Import"), sb_cols.queued);
72         session_browser.set_tooltip_column (3);
73         session_browser.get_column(0)->set_min_width (180);
74         session_browser.get_column(1)->set_min_width (40);
75         session_browser.get_column(1)->set_sizing (Gtk::TREE_VIEW_COLUMN_AUTOSIZE);
76
77         session_scroll.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
78         session_scroll.add (session_browser);
79         session_scroll.set_size_request (220, 400);
80
81         // Connect signals
82         Gtk::CellRendererToggle *toggle = dynamic_cast<Gtk::CellRendererToggle *> (session_browser.get_column_cell_renderer (1));
83         toggle->signal_toggled().connect(mem_fun (*this, &SessionImportDialog::update));
84         session_browser.signal_row_activated().connect(mem_fun (*this, &SessionImportDialog::show_info));
85
86         get_vbox()->pack_start (session_scroll, false, false);
87
88         // Buttons
89         cancel_button = add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
90         cancel_button->signal_clicked().connect (mem_fun (*this, &SessionImportDialog::end_dialog));
91         ok_button = add_button (_("Import"), Gtk::RESPONSE_ACCEPT);
92         ok_button->signal_clicked().connect (mem_fun (*this, &SessionImportDialog::do_merge));
93
94         // prompt signals
95         ElementImporter::Rename.connect (mem_fun (*this, &SessionImportDialog::open_rename_dialog));
96         ElementImporter::Prompt.connect (mem_fun (*this, &SessionImportDialog::open_prompt_dialog));
97
98         // Finalize
99         show_all();
100 }
101
102 void
103 SessionImportDialog::load_session (const string& filename)
104 {
105         tree.read (filename);
106         boost::shared_ptr<AudioRegionImportHandler> region_handler (new AudioRegionImportHandler (tree, target));
107         boost::shared_ptr<AudioPlaylistImportHandler> pl_handler (new AudioPlaylistImportHandler (tree, target, *region_handler));
108
109         handlers.push_back (boost::static_pointer_cast<ElementImportHandler> (region_handler));
110         handlers.push_back (boost::static_pointer_cast<ElementImportHandler> (pl_handler));
111         handlers.push_back (HandlerPtr(new UnusedAudioPlaylistImportHandler (tree, target, *region_handler)));
112         handlers.push_back (HandlerPtr(new AudioTrackImportHandler (tree, target, *pl_handler)));
113         handlers.push_back (HandlerPtr(new LocationImportHandler (tree, target)));
114         handlers.push_back (HandlerPtr(new TempoMapImportHandler (tree, target)));
115
116         fill_list();
117
118         if (ElementImportHandler::dirty()) {
119                 // Warn user
120                 string txt = _("Some elements had errors in them. Please see the log for details");
121                 Gtk::MessageDialog msg (txt, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true);
122                 msg.run();
123         }
124 }
125
126 void
127 SessionImportDialog::fill_list ()
128 {
129         session_tree->clear();
130
131         // Loop through element types
132         for (HandlerList::iterator handler = handlers.begin(); handler != handlers.end(); ++handler) {
133                 Gtk::TreeModel::iterator iter = session_tree->append();
134                 Gtk::TreeModel::Row row = *iter;
135                 row[sb_cols.name] = (*handler)->get_info();
136                 row[sb_cols.queued] = false;
137                 row[sb_cols.element] = ElementPtr(); // "Null" pointer
138
139                 // Loop through elements
140                 ElementList &elements = (*handler)->elements;
141                 for (ElementList::iterator element = elements.begin(); element != elements.end(); ++element) {
142                         iter = session_tree->append(row.children());
143                         Gtk::TreeModel::Row child = *iter;
144                         child[sb_cols.name] = (*element)->get_name();
145                         child[sb_cols.queued] = false;
146                         child[sb_cols.element] = *element;
147                         child[sb_cols.info] = (*element)->get_info();
148                 }
149         }
150 }
151
152 void
153 SessionImportDialog::browse ()
154 {
155         Gtk::FileChooserDialog dialog(_("Import from session"), browse_action());
156         dialog.set_transient_for(*this);
157         dialog.set_filename (file_entry.get_text());
158
159         dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
160         dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
161
162         int result = dialog.run();
163
164         if (result == Gtk::RESPONSE_OK) {
165                 string filename = dialog.get_filename();
166
167                 if (filename.length()) {
168                         file_entry.set_text (filename);
169                         load_session (filename);
170                 }
171         }
172 }
173
174 void
175 SessionImportDialog::do_merge ()
176 {
177
178         // element types
179         Gtk::TreeModel::Children types = session_browser.get_model()->children();
180         Gtk::TreeModel::Children::iterator ti;
181         for (ti = types.begin(); ti != types.end(); ++ti) {
182                 // elements
183                 Gtk::TreeModel::Children elements = ti->children();
184                 Gtk::TreeModel::Children::iterator ei;
185                 for (ei = elements.begin(); ei != elements.end(); ++ei) {
186                         if ((*ei)[sb_cols.queued]) {
187                                 ElementPtr element = (*ei)[sb_cols.element];
188                                 element->move();
189                         }
190                 }
191         }
192
193         end_dialog();
194
195         if (ElementImportHandler::errors()) {
196                 // Warn user
197                 string txt = _("Some elements had errors in them. Please see the log for details");
198                 Gtk::MessageDialog msg (txt, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true);
199                 msg.run();
200         }
201 }
202
203
204 void
205 SessionImportDialog::update (string path)
206 {
207         Gtk::TreeModel::iterator cell = session_browser.get_model()->get_iter (path);
208
209         // Select all elements if element type is selected
210         if (path.size() == 1) {
211                 {
212                         // Prompt user for verification
213                         string txt = _("This will select all elements of this type!");
214                         Gtk::MessageDialog msg (txt, false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL, true);
215                         if (msg.run() == Gtk::RESPONSE_CANCEL) {
216                                 (*cell)[sb_cols.queued] = false;
217                                 return;
218                         }
219                 }
220
221                 Gtk::TreeModel::Children elements = cell->children();
222                 Gtk::TreeModel::Children::iterator ei;
223                 for (ei = elements.begin(); ei != elements.end(); ++ei) {
224                         ElementPtr element = (*ei)[sb_cols.element];
225                         if (element->prepare_move()) {
226                                 (*ei)[sb_cols.queued] = true;
227                         } else {
228                                 (*cell)[sb_cols.queued] = false; // Not all are selected
229                         }
230                 }
231                 return;
232         }
233
234         ElementPtr element = (*cell)[sb_cols.element];
235         if ((*cell)[sb_cols.queued]) {
236                 if (!element->prepare_move()) {
237                         (*cell)[sb_cols.queued] = false;
238                 }
239         } else {
240                 element->cancel_move();
241         }
242 }
243
244 void
245 SessionImportDialog::show_info(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*)
246 {
247         if (path.size() == 1) {
248                 return;
249         }
250
251         Gtk::TreeModel::iterator cell = session_browser.get_model()->get_iter (path);
252         string info = (*cell)[sb_cols.info];
253
254         Gtk::MessageDialog msg (info, false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK, true);
255         msg.run();
256 }
257
258 void
259 SessionImportDialog::end_dialog ()
260 {
261         hide_all();
262
263         set_modal (false);
264         ok_button->set_sensitive(true);
265 }
266
267 std::pair<bool, string>
268 SessionImportDialog::open_rename_dialog (string text, string name)
269 {
270         ArdourPrompter prompter(true);
271         string new_name;
272
273         prompter.set_name ("Prompter");
274         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
275         prompter.set_prompt (text);
276         prompter.set_initial_text (name);
277
278         if (prompter.run() == Gtk::RESPONSE_ACCEPT) {
279                 prompter.get_result (new_name);
280                 if (new_name.length()) {
281                         name = new_name;
282                 }
283                 return std::make_pair (true, new_name);
284         }
285         return std::make_pair (false, new_name);
286 }
287
288 bool
289 SessionImportDialog::open_prompt_dialog (string text)
290 {
291         Gtk::MessageDialog msg (text, false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL, true);
292         if (msg.run() == Gtk::RESPONSE_OK) {
293                 return true;
294         }
295         return false;
296 }