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