2 Copyright (C) 2008 Paul Davis
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.
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.
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.
21 #include <gtkmm/messagedialog.h>
22 #include <gtkmm/stock.h>
24 #include "pbd/failed_constructor.h"
26 #include "ardour/audio_region_importer.h"
27 #include "ardour/audio_playlist_importer.h"
28 #include "ardour/audio_track_importer.h"
29 #include "ardour/filename_extensions.h"
30 #include "ardour/location_importer.h"
31 #include "ardour/tempo_map_importer.h"
33 #include "gtkmm2ext/utils.h"
34 #include "widgets/prompter.h"
36 #include "gui_thread.h"
37 #include "session_import_dialog.h"
42 using namespace ARDOUR;
46 SessionImportDialog::SessionImportDialog (ARDOUR::Session* target) :
47 ArdourDialog (_("Import from Session")),
48 file_browse_button (_("Browse"))
53 file_entry.set_name ("ImportFileNameEntry");
54 file_entry.set_text ("/");
55 Gtkmm2ext::set_size_request_to_display_given_text (file_entry, X_("Kg/quite/a/reasonable/size/for/files/i/think"), 5, 8);
57 file_browse_button.set_name ("EditorGTKButton");
58 file_browse_button.signal_clicked().connect (sigc::mem_fun(*this, &SessionImportDialog::browse));
60 file_hbox.set_spacing (5);
61 file_hbox.set_border_width (5);
62 file_hbox.pack_start (file_entry, true, true);
63 file_hbox.pack_start (file_browse_button, false, false);
65 file_frame.add (file_hbox);
66 file_frame.set_border_width (5);
67 file_frame.set_name ("ImportFrom");
68 file_frame.set_label (_("Import from Session"));
70 get_vbox()->pack_start (file_frame, false, false);
73 session_tree = TreeStore::create (sb_cols);
74 session_browser.set_model (session_tree);
76 session_browser.set_name ("SessionBrowser");
77 session_browser.append_column (_("Elements"), sb_cols.name);
78 session_browser.append_column_editable (_("Import"), sb_cols.queued);
79 session_browser.set_tooltip_column (3);
80 session_browser.get_column(0)->set_min_width (180);
81 session_browser.get_column(1)->set_min_width (40);
82 session_browser.get_column(1)->set_sizing (TREE_VIEW_COLUMN_AUTOSIZE);
84 session_scroll.set_policy (POLICY_AUTOMATIC, POLICY_AUTOMATIC);
85 session_scroll.add (session_browser);
86 session_scroll.set_size_request (220, 400);
89 CellRendererToggle *toggle = dynamic_cast<CellRendererToggle *> (session_browser.get_column_cell_renderer (1));
90 toggle->signal_toggled().connect(sigc::mem_fun (*this, &SessionImportDialog::update));
91 session_browser.signal_row_activated().connect(sigc::mem_fun (*this, &SessionImportDialog::show_info));
93 get_vbox()->pack_start (session_scroll, false, false);
96 cancel_button = add_button (Stock::CANCEL, RESPONSE_CANCEL);
97 cancel_button->signal_clicked().connect (sigc::mem_fun (*this, &SessionImportDialog::end_dialog));
98 ok_button = add_button (_("Import"), RESPONSE_ACCEPT);
99 ok_button->signal_clicked().connect (sigc::mem_fun (*this, &SessionImportDialog::do_merge));
101 // prompt signals XXX: problem - handlers to be in the same thread since they return values
102 ElementImporter::Rename.connect_same_thread (connections, boost::bind (&SessionImportDialog::open_rename_dialog, this, _1, _2));
103 ElementImporter::Prompt.connect_same_thread (connections, boost::bind (&SessionImportDialog::open_prompt_dialog, this, _1));
110 SessionImportDialog::load_session (const string& filename)
113 if (tree.read (filename)) {
114 error << string_compose (_("Cannot load XML for session from %1"), filename) << endmsg;
117 boost::shared_ptr<AudioRegionImportHandler> region_handler (new AudioRegionImportHandler (tree, *_session));
118 boost::shared_ptr<AudioPlaylistImportHandler> pl_handler (new AudioPlaylistImportHandler (tree, *_session, *region_handler));
120 handlers.push_back (boost::static_pointer_cast<ElementImportHandler> (region_handler));
121 handlers.push_back (boost::static_pointer_cast<ElementImportHandler> (pl_handler));
122 handlers.push_back (HandlerPtr(new UnusedAudioPlaylistImportHandler (tree, *_session, *region_handler)));
123 handlers.push_back (HandlerPtr(new AudioTrackImportHandler (tree, *_session, *pl_handler)));
124 handlers.push_back (HandlerPtr(new LocationImportHandler (tree, *_session)));
125 handlers.push_back (HandlerPtr(new TempoMapImportHandler (tree, *_session)));
129 if (ElementImportHandler::dirty()) {
131 string txt = _("Some elements had errors in them. Please see the log for details");
132 MessageDialog msg (txt, false, MESSAGE_WARNING, BUTTONS_OK, true);
139 SessionImportDialog::fill_list ()
141 session_tree->clear();
143 // Loop through element types
144 for (HandlerList::iterator handler = handlers.begin(); handler != handlers.end(); ++handler) {
145 TreeModel::iterator iter = session_tree->append();
146 TreeModel::Row row = *iter;
147 row[sb_cols.name] = (*handler)->get_info();
148 row[sb_cols.queued] = false;
149 row[sb_cols.element] = ElementPtr(); // "Null" pointer
151 // Loop through elements
152 ElementList &elements = (*handler)->elements;
153 for (ElementList::iterator element = elements.begin(); element != elements.end(); ++element) {
154 iter = session_tree->append(row.children());
155 TreeModel::Row child = *iter;
156 child[sb_cols.name] = (*element)->get_name();
157 child[sb_cols.queued] = false;
158 child[sb_cols.element] = *element;
159 child[sb_cols.info] = (*element)->get_info();
165 SessionImportDialog::browse ()
167 FileChooserDialog dialog(_("Import from session"), browse_action());
168 dialog.set_transient_for(*this);
169 dialog.set_filename (file_entry.get_text());
171 FileFilter session_filter;
172 session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
173 session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
174 dialog.add_filter (session_filter);
175 dialog.set_filter (session_filter);
177 dialog.add_button(Stock::CANCEL, RESPONSE_CANCEL);
178 dialog.add_button(Stock::OK, RESPONSE_OK);
180 int result = dialog.run();
182 if (result == RESPONSE_OK) {
183 string filename = dialog.get_filename();
185 if (filename.length()) {
186 file_entry.set_text (filename);
187 load_session (filename);
193 SessionImportDialog::do_merge ()
197 TreeModel::Children types = session_browser.get_model()->children();
198 TreeModel::Children::iterator ti;
199 for (ti = types.begin(); ti != types.end(); ++ti) {
201 TreeModel::Children elements = ti->children();
202 TreeModel::Children::iterator ei;
203 for (ei = elements.begin(); ei != elements.end(); ++ei) {
204 if ((*ei)[sb_cols.queued]) {
205 ElementPtr element = (*ei)[sb_cols.element];
213 if (ElementImportHandler::errors()) {
215 string txt = _("Some elements had errors in them. Please see the log for details");
216 MessageDialog msg (txt, false, MESSAGE_WARNING, BUTTONS_OK, true);
223 SessionImportDialog::update (string path)
225 TreeModel::iterator cell = session_browser.get_model()->get_iter (path);
227 // Select all elements if element type is selected
228 if (path.size() == 1) {
230 // Prompt user for verification
231 string txt = _("This will select all elements of this type!");
232 MessageDialog msg (txt, false, MESSAGE_QUESTION, BUTTONS_OK_CANCEL, true);
233 if (msg.run() == RESPONSE_CANCEL) {
234 (*cell)[sb_cols.queued] = false;
239 TreeModel::Children elements = cell->children();
240 TreeModel::Children::iterator ei;
241 for (ei = elements.begin(); ei != elements.end(); ++ei) {
242 ElementPtr element = (*ei)[sb_cols.element];
243 if (element->prepare_move()) {
244 (*ei)[sb_cols.queued] = true;
246 (*cell)[sb_cols.queued] = false; // Not all are selected
252 ElementPtr element = (*cell)[sb_cols.element];
253 if ((*cell)[sb_cols.queued]) {
254 if (!element->prepare_move()) {
255 (*cell)[sb_cols.queued] = false;
258 element->cancel_move();
263 SessionImportDialog::show_info(const TreeModel::Path& path, TreeViewColumn*)
265 if (path.size() == 1) {
269 TreeModel::iterator cell = session_browser.get_model()->get_iter (path);
270 string info = (*cell)[sb_cols.info];
272 MessageDialog msg (info, false, MESSAGE_INFO, BUTTONS_OK, true);
277 SessionImportDialog::end_dialog ()
282 ok_button->set_sensitive(true);
285 std::pair<bool, string>
286 SessionImportDialog::open_rename_dialog (string text, string name)
288 ArdourWidgets::Prompter prompter(true);
291 prompter.set_name ("Prompter");
292 prompter.add_button (Stock::SAVE, RESPONSE_ACCEPT);
293 prompter.set_prompt (text);
294 prompter.set_initial_text (name);
296 if (prompter.run() == RESPONSE_ACCEPT) {
297 prompter.get_result (new_name);
298 if (new_name.length()) {
301 return std::make_pair (true, new_name);
303 return std::make_pair (false, new_name);
307 SessionImportDialog::open_prompt_dialog (string text)
309 MessageDialog msg (text, false, MESSAGE_QUESTION, BUTTONS_OK_CANCEL, true);
310 if (msg.run() == RESPONSE_OK) {