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 "session_import_dialog.h"
23 #include "pbd/failed_constructor.h"
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"
31 #include <gtkmm2ext/utils.h>
33 #include "gui_thread.h"
38 using namespace ARDOUR
;
40 SessionImportDialog::SessionImportDialog (ARDOUR::Session
* target
) :
41 ArdourDialog (_("Import From Session")),
42 file_browse_button (_("Browse"))
47 file_entry
.set_name ("ImportFileNameEntry");
48 file_entry
.set_text ("/");
49 Gtkmm2ext::set_size_request_to_display_given_text (file_entry
, X_("Kg/quite/a/reasonable/size/for/files/i/think"), 5, 8);
51 file_browse_button
.set_name ("EditorGTKButton");
52 file_browse_button
.signal_clicked().connect (sigc::mem_fun(*this, &SessionImportDialog::browse
));
54 file_hbox
.set_spacing (5);
55 file_hbox
.set_border_width (5);
56 file_hbox
.pack_start (file_entry
, true, true);
57 file_hbox
.pack_start (file_browse_button
, false, false);
59 file_frame
.add (file_hbox
);
60 file_frame
.set_border_width (5);
61 file_frame
.set_name ("ImportFrom");
62 file_frame
.set_label (_("Import from Session"));
64 get_vbox()->pack_start (file_frame
, false, false);
67 session_tree
= Gtk::TreeStore::create (sb_cols
);
68 session_browser
.set_model (session_tree
);
70 session_browser
.set_name ("SessionBrowser");
71 session_browser
.append_column (_("Elements"), sb_cols
.name
);
72 session_browser
.append_column_editable (_("Import"), sb_cols
.queued
);
73 session_browser
.set_tooltip_column (3);
74 session_browser
.get_column(0)->set_min_width (180);
75 session_browser
.get_column(1)->set_min_width (40);
76 session_browser
.get_column(1)->set_sizing (Gtk::TREE_VIEW_COLUMN_AUTOSIZE
);
78 session_scroll
.set_policy (Gtk::POLICY_AUTOMATIC
, Gtk::POLICY_AUTOMATIC
);
79 session_scroll
.add (session_browser
);
80 session_scroll
.set_size_request (220, 400);
83 Gtk::CellRendererToggle
*toggle
= dynamic_cast<Gtk::CellRendererToggle
*> (session_browser
.get_column_cell_renderer (1));
84 toggle
->signal_toggled().connect(sigc::mem_fun (*this, &SessionImportDialog::update
));
85 session_browser
.signal_row_activated().connect(sigc::mem_fun (*this, &SessionImportDialog::show_info
));
87 get_vbox()->pack_start (session_scroll
, false, false);
90 cancel_button
= add_button (Gtk::Stock::CANCEL
, Gtk::RESPONSE_CANCEL
);
91 cancel_button
->signal_clicked().connect (sigc::mem_fun (*this, &SessionImportDialog::end_dialog
));
92 ok_button
= add_button (_("Import"), Gtk::RESPONSE_ACCEPT
);
93 ok_button
->signal_clicked().connect (sigc::mem_fun (*this, &SessionImportDialog::do_merge
));
95 // prompt signals XXX: problem - handlers to be in the same thread since they return values
96 ElementImporter::Rename
.connect_same_thread (connections
, boost::bind (&SessionImportDialog::open_rename_dialog
, this, _1
, _2
));
97 ElementImporter::Prompt
.connect_same_thread (connections
, boost::bind (&SessionImportDialog::open_prompt_dialog
, this, _1
));
104 SessionImportDialog::load_session (const string
& filename
)
107 tree
.read (filename
);
108 boost::shared_ptr
<AudioRegionImportHandler
> region_handler (new AudioRegionImportHandler (tree
, *_session
));
109 boost::shared_ptr
<AudioPlaylistImportHandler
> pl_handler (new AudioPlaylistImportHandler (tree
, *_session
, *region_handler
));
111 handlers
.push_back (boost::static_pointer_cast
<ElementImportHandler
> (region_handler
));
112 handlers
.push_back (boost::static_pointer_cast
<ElementImportHandler
> (pl_handler
));
113 handlers
.push_back (HandlerPtr(new UnusedAudioPlaylistImportHandler (tree
, *_session
, *region_handler
)));
114 handlers
.push_back (HandlerPtr(new AudioTrackImportHandler (tree
, *_session
, *pl_handler
)));
115 handlers
.push_back (HandlerPtr(new LocationImportHandler (tree
, *_session
)));
116 handlers
.push_back (HandlerPtr(new TempoMapImportHandler (tree
, *_session
)));
120 if (ElementImportHandler::dirty()) {
122 string txt
= _("Some elements had errors in them. Please see the log for details");
123 Gtk::MessageDialog
msg (txt
, false, Gtk::MESSAGE_WARNING
, Gtk::BUTTONS_OK
, true);
130 SessionImportDialog::fill_list ()
132 session_tree
->clear();
134 // Loop through element types
135 for (HandlerList::iterator handler
= handlers
.begin(); handler
!= handlers
.end(); ++handler
) {
136 Gtk::TreeModel::iterator iter
= session_tree
->append();
137 Gtk::TreeModel::Row row
= *iter
;
138 row
[sb_cols
.name
] = (*handler
)->get_info();
139 row
[sb_cols
.queued
] = false;
140 row
[sb_cols
.element
] = ElementPtr(); // "Null" pointer
142 // Loop through elements
143 ElementList
&elements
= (*handler
)->elements
;
144 for (ElementList::iterator element
= elements
.begin(); element
!= elements
.end(); ++element
) {
145 iter
= session_tree
->append(row
.children());
146 Gtk::TreeModel::Row child
= *iter
;
147 child
[sb_cols
.name
] = (*element
)->get_name();
148 child
[sb_cols
.queued
] = false;
149 child
[sb_cols
.element
] = *element
;
150 child
[sb_cols
.info
] = (*element
)->get_info();
156 SessionImportDialog::browse ()
158 Gtk::FileChooserDialog
dialog(_("Import from session"), browse_action());
159 dialog
.set_transient_for(*this);
160 dialog
.set_filename (file_entry
.get_text());
162 dialog
.add_button(Gtk::Stock::CANCEL
, Gtk::RESPONSE_CANCEL
);
163 dialog
.add_button(Gtk::Stock::OK
, Gtk::RESPONSE_OK
);
165 int result
= dialog
.run();
167 if (result
== Gtk::RESPONSE_OK
) {
168 string filename
= dialog
.get_filename();
170 if (filename
.length()) {
171 file_entry
.set_text (filename
);
172 load_session (filename
);
178 SessionImportDialog::do_merge ()
182 Gtk::TreeModel::Children types
= session_browser
.get_model()->children();
183 Gtk::TreeModel::Children::iterator ti
;
184 for (ti
= types
.begin(); ti
!= types
.end(); ++ti
) {
186 Gtk::TreeModel::Children elements
= ti
->children();
187 Gtk::TreeModel::Children::iterator ei
;
188 for (ei
= elements
.begin(); ei
!= elements
.end(); ++ei
) {
189 if ((*ei
)[sb_cols
.queued
]) {
190 ElementPtr element
= (*ei
)[sb_cols
.element
];
198 if (ElementImportHandler::errors()) {
200 string txt
= _("Some elements had errors in them. Please see the log for details");
201 Gtk::MessageDialog
msg (txt
, false, Gtk::MESSAGE_WARNING
, Gtk::BUTTONS_OK
, true);
208 SessionImportDialog::update (string path
)
210 Gtk::TreeModel::iterator cell
= session_browser
.get_model()->get_iter (path
);
212 // Select all elements if element type is selected
213 if (path
.size() == 1) {
215 // Prompt user for verification
216 string txt
= _("This will select all elements of this type!");
217 Gtk::MessageDialog
msg (txt
, false, Gtk::MESSAGE_QUESTION
, Gtk::BUTTONS_OK_CANCEL
, true);
218 if (msg
.run() == Gtk::RESPONSE_CANCEL
) {
219 (*cell
)[sb_cols
.queued
] = false;
224 Gtk::TreeModel::Children elements
= cell
->children();
225 Gtk::TreeModel::Children::iterator ei
;
226 for (ei
= elements
.begin(); ei
!= elements
.end(); ++ei
) {
227 ElementPtr element
= (*ei
)[sb_cols
.element
];
228 if (element
->prepare_move()) {
229 (*ei
)[sb_cols
.queued
] = true;
231 (*cell
)[sb_cols
.queued
] = false; // Not all are selected
237 ElementPtr element
= (*cell
)[sb_cols
.element
];
238 if ((*cell
)[sb_cols
.queued
]) {
239 if (!element
->prepare_move()) {
240 (*cell
)[sb_cols
.queued
] = false;
243 element
->cancel_move();
248 SessionImportDialog::show_info(const Gtk::TreeModel::Path
& path
, Gtk::TreeViewColumn
*)
250 if (path
.size() == 1) {
254 Gtk::TreeModel::iterator cell
= session_browser
.get_model()->get_iter (path
);
255 string info
= (*cell
)[sb_cols
.info
];
257 Gtk::MessageDialog
msg (info
, false, Gtk::MESSAGE_INFO
, Gtk::BUTTONS_OK
, true);
262 SessionImportDialog::end_dialog ()
267 ok_button
->set_sensitive(true);
270 std::pair
<bool, string
>
271 SessionImportDialog::open_rename_dialog (string text
, string name
)
273 ArdourPrompter
prompter(true);
276 prompter
.set_name ("Prompter");
277 prompter
.add_button (Gtk::Stock::SAVE
, Gtk::RESPONSE_ACCEPT
);
278 prompter
.set_prompt (text
);
279 prompter
.set_initial_text (name
);
281 if (prompter
.run() == Gtk::RESPONSE_ACCEPT
) {
282 prompter
.get_result (new_name
);
283 if (new_name
.length()) {
286 return std::make_pair (true, new_name
);
288 return std::make_pair (false, new_name
);
292 SessionImportDialog::open_prompt_dialog (string text
)
294 Gtk::MessageDialog
msg (text
, false, Gtk::MESSAGE_QUESTION
, Gtk::BUTTONS_OK_CANCEL
, true);
295 if (msg
.run() == Gtk::RESPONSE_OK
) {