Guitarix
gx_preset_window.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert
3  * Copyright (C) 2011 Pete Shorthose
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  * ---------------------------------------------------------------------------
19  *
20  *
21  * ----------------------------------------------------------------------------
22  */
23 
24 #include <guitarix.h>
25 
26 /****************************************************************
27  ** class PresetWindow
28  */
29 
30 PresetStore::PresetStore(): Gtk::ListStore(), col() {
31  set_column_types(col);
32 }
33 
34 bool PresetStore::row_draggable_vfunc(const TreeModel::Path& path) const {
35  Gtk::TreeModel::const_iterator i = const_cast<PresetStore*>(this)->get_iter(path); // Bug in Gtkmm: no get_iter() const
36  Glib::ustring s(i->get_value(col.name));
37  if (s.empty()) {
38  return false;
39  } else {
40  return true;
41  }
42 }
43 
44 
45 PresetWindow::PresetWindow(Glib::RefPtr<gx_gui::GxBuilder> bld, gx_engine::GxMachineBase& machine_,
46  const gx_system::CmdlineOptions& options_, GxActions& actions_, GtkSizeGroup *lc)
47  : sigc::trackable(),
48  machine(machine_),
49  actions(actions_),
50  in_edit(false),
51  edit_iter(),
52  pb_edit(),
53  pb_del(),
54  pb_scratch(),
55  pb_versiondiff(),
56  pb_readonly(),
57  pb_factory(),
58  pstore(new PresetStore),
59  target_col(),
60  bank_col(),
61  bank_row_del_conn(),
62  preset_row_del_conn(),
63  vpaned_pos(),
64  vpaned_step(),
65  vpaned_target(),
66  options(options_),
67  in_current_preset(false),
68  on_map_conn()
69  /* widget pointers not initialized */ {
70  load_widget_pointers(bld);
71  actions.new_bank = Gtk::Action::create("NewBank");
72  actions.group->add(actions.new_bank, sigc::mem_fun(*this, &PresetWindow::on_new_bank));
73  gtk_activatable_set_related_action(GTK_ACTIVATABLE(new_preset_bank->gobj()), actions.new_bank->gobj());
74  actions.save_changes = Gtk::Action::create("Save", _("_Save changes"));
75  actions.group->add(actions.save_changes, sigc::mem_fun(*this, &PresetWindow::on_preset_save));
76  gtk_activatable_set_related_action(GTK_ACTIVATABLE(save_preset->gobj()), actions.save_changes->gobj());
77  actions.organize = Gtk::ToggleAction::create("Organize", _("_Organize"));
78  actions.group->add(actions.organize, sigc::mem_fun(*this, &PresetWindow::on_organize));
79  gtk_activatable_set_related_action(GTK_ACTIVATABLE(organize_presets->gobj()), GTK_ACTION(actions.organize->gobj()));
80  //act = Gtk::Action::create("ClosePresetsAction");
81  //actiongroup->add(act, sigc::mem_fun(*this, &PresetWindow::on_presets_close));
82  //gtk_activatable_set_related_action(GTK_ACTIVATABLE(close_preset->gobj()), act->gobj());
83  close_preset->hide(); // disable (maybe remove later)
84  actions.online_preset_bank = Gtk::Action::create("OnlineBank");
85  actions.group->add(actions.online_preset_bank, sigc::mem_fun(*this, &PresetWindow::on_online_preset));
86  gtk_activatable_set_related_action(GTK_ACTIVATABLE(online_preset->gobj()), actions.online_preset_bank->gobj());
87  if (!machine.get_jack()) online_preset->set_sensitive(false);
88  bank_treeview->set_model(Gtk::ListStore::create(bank_col));
89  bank_treeview->set_name("PresetView");
90  bank_treeview->get_selection()->set_select_function(
91  sigc::mem_fun(*this, &PresetWindow::select_func));
92  bank_treeview->set_has_tooltip(true);
93  bank_treeview->signal_query_tooltip().connect(
94  sigc::mem_fun(*this, &PresetWindow::on_bank_query_tooltip));
95  pb_edit = bank_treeview->render_icon(Gtk::Stock::EDIT, Gtk::ICON_SIZE_MENU);
96  pb_del = bank_treeview->render_icon(Gtk::Stock::DELETE, Gtk::ICON_SIZE_MENU);
97  pb_scratch = Gdk::Pixbuf::create_from_file(options.get_style_filepath("scratch.png"));
98  pb_versiondiff = Gdk::Pixbuf::create_from_file(options.get_style_filepath("versiondiff.png"));
99  pb_readonly = Gdk::Pixbuf::create_from_file(options.get_style_filepath("readonly.png"));
100  pb_factory = Gdk::Pixbuf::create_from_file(options.get_style_filepath("factory.png"));
101  bank_treeview->set_row_separator_func(sigc::mem_fun(*this, &PresetWindow::is_row_separator));
102  bank_cellrenderer->signal_edited().connect(
103  sigc::bind(sigc::mem_fun(*this, &PresetWindow::on_bank_edited), bank_treeview));
104  bank_cellrenderer->signal_editing_canceled().connect(
105  sigc::bind(sigc::mem_fun(*this, &PresetWindow::on_edit_canceled), bank_treeview->get_column(1)));
106  bank_cellrenderer->signal_editing_started().connect(
107  sigc::bind(sigc::mem_fun(*this, &PresetWindow::on_editing_started), bank_treeview->get_model()));
108  Gtk::TreeViewColumn *col = bank_treeview->get_column(1);
109  col->set_cell_data_func(**col->get_cell_renderers().begin(), sigc::mem_fun(*this, &PresetWindow::highlight_current_bank));
110 
111  std::vector<Gtk::TargetEntry> listTargets;
112  listTargets.push_back(Gtk::TargetEntry("GTK_TREE_MODEL_ROW", Gtk::TARGET_SAME_WIDGET, MODELROW_TARGET));
113  listTargets.push_back(Gtk::TargetEntry("text/uri-list", Gtk::TARGET_OTHER_APP, URILIST_TARGET));
114  bank_treeview->enable_model_drag_source(listTargets, Gdk::BUTTON1_MASK, Gdk::ACTION_COPY);
115  bank_treeview->drag_source_add_text_targets(); // sets info == 0 (TEXT_TARGETS)
116  bank_treeview->signal_drag_motion().connect(sigc::mem_fun(*this, &PresetWindow::on_bank_drag_motion), false);
117  bank_treeview->enable_model_drag_dest(listTargets, Gdk::ACTION_COPY);
118  bank_treeview->signal_drag_data_received().connect(
119  sigc::mem_fun(*this, &PresetWindow::on_bank_drag_data_received));
120  bank_treeview->signal_drag_data_get().connect(
121  sigc::mem_fun(*this, &PresetWindow::on_bank_drag_data_get));
122  bank_treeview->signal_drag_begin().connect(
123  sigc::hide(sigc::mem_fun(machine, &gx_engine::GxMachineBase::bank_drag_begin)));
124  Glib::RefPtr<Gtk::TreeSelection> sel = bank_treeview->get_selection();
125  sel->set_mode(Gtk::SELECTION_BROWSE);
126  sel->signal_changed().connect(sigc::mem_fun(*this, &PresetWindow::on_bank_changed));
127  bank_treeview->signal_button_release_event().connect(sigc::mem_fun(*this, &PresetWindow::on_bank_button_release), true);
128  Glib::RefPtr<Gtk::TreeModel> ls = bank_treeview->get_model();
129  bank_row_del_conn = ls->signal_row_deleted().connect(sigc::mem_fun(*this, &PresetWindow::on_bank_reordered));
130 
131  preset_treeview->set_model(pstore);
132  preset_treeview->set_name("PresetView");
133  preset_treeview->signal_drag_motion().connect(sigc::mem_fun(*this, &PresetWindow::on_preset_drag_motion), false);
134  preset_treeview->signal_drag_data_get().connect(sigc::mem_fun(*this, &PresetWindow::on_preset_drag_data_get));
135  preset_treeview->signal_row_activated().connect(sigc::mem_fun(*this, &PresetWindow::on_preset_row_activated));
136  preset_treeview->signal_button_press_event().connect(sigc::mem_fun(*this, &PresetWindow::on_preset_button_press));
137  preset_treeview->signal_button_release_event().connect(sigc::mem_fun(*this, &PresetWindow::on_preset_button_release), true);
138  preset_row_del_conn = pstore->signal_row_deleted().connect(sigc::mem_fun(*this, &PresetWindow::on_preset_reordered));
139  preset_treeview->get_selection()->set_mode(Gtk::SELECTION_BROWSE);
140  preset_treeview->get_selection()->set_select_function(
141  sigc::mem_fun(*this, &PresetWindow::select_func));
142  preset_treeview->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &PresetWindow::on_preset_changed));
143  preset_treeview->signal_cursor_changed().connect(sigc::mem_fun(*this, &PresetWindow::on_cursor_changed));
144  preset_cellrenderer->signal_edited().connect(sigc::mem_fun(*this, &PresetWindow::on_preset_edited));
145  preset_cellrenderer->signal_editing_canceled().connect(
146  sigc::bind(sigc::mem_fun(*this, &PresetWindow::on_edit_canceled), preset_treeview->get_column(0)));
147  preset_cellrenderer->signal_editing_started().connect(
148  sigc::bind(
149  sigc::mem_fun(*this, &PresetWindow::on_editing_started),
150  Glib::RefPtr<Gtk::TreeModel>::cast_static(pstore)));
151  preset_treeview->get_column(0)->set_cell_data_func(
152  *preset_cellrenderer, sigc::mem_fun(*this, &PresetWindow::text_func));
153  banks_combobox->signal_changed().connect(
154  sigc::mem_fun(*this, &PresetWindow::on_preset_combo_changed));
155  presets_target_treeview->get_selection()->set_mode(Gtk::SELECTION_NONE);
156  std::vector<Gtk::TargetEntry> listTargets3;
157  listTargets3.push_back(
158  Gtk::TargetEntry("application/x-guitarix-preset", Gtk::TARGET_SAME_APP, 0));
159  presets_target_treeview->enable_model_drag_dest(listTargets3, Gdk::ACTION_COPY);
160  presets_target_treeview->signal_drag_motion().connect(
161  sigc::mem_fun(*this, &PresetWindow::on_target_drag_motion), false);
162  presets_target_treeview->signal_drag_data_received().connect_notify(
163  sigc::mem_fun(*this, &PresetWindow::target_drag_data_received));
164  machine.signal_selection_changed().connect(
165  sigc::mem_fun(*this, &PresetWindow::on_selection_changed));
166 
167  left_column = lc;
168  gtk_size_group_add_widget(lc, GTK_WIDGET(close_preset->gobj()));
169  gtk_size_group_add_widget(lc, GTK_WIDGET(save_preset->gobj()));
170  gtk_size_group_add_widget(lc, GTK_WIDGET(new_preset_bank->gobj()));
171  gtk_size_group_add_widget(lc, GTK_WIDGET(organize_presets->gobj()));
172  gtk_size_group_add_widget(lc, GTK_WIDGET(online_preset->gobj()));
173  curl_global_init(CURL_GLOBAL_DEFAULT);
174  curl = curl_easy_init();
175 }
176 
178  curl_easy_cleanup(curl);
179  curl_global_cleanup();
180 }
181 
182 void PresetWindow::on_selection_changed() {
183  Gtk::TreeIter it = bank_treeview->get_selection()->get_selected();
184  if (it && it->get_value(bank_col.name) == machine.get_current_bank()) {
185  it = preset_treeview->get_selection()->get_selected();
186  if (it && it->get_value(pstore->col.name) == machine.get_current_name()) {
187  Glib::RefPtr<Gdk::Window> w = bank_treeview->get_window();
188  if (w) { // might not yet be initialized
189  gdk_window_invalidate_rect(w->gobj(), 0, true);
190  gdk_window_invalidate_rect(preset_treeview->get_window()->gobj(), 0, true);
191  }
192  return;
193  }
194  }
195  set_presets();
196  bool s = false;
197  if (machine.setting_is_preset()) {
199  if (pf && pf->is_mutable()) {
200  s = true;
201  }
202  }
203  actions.save_changes->set_sensitive(s);
204 }
205 
206 void PresetWindow::load_widget_pointers(Glib::RefPtr<gx_gui::GxBuilder> bld) {
207  bld->find_widget("close_preset", close_preset);
208  bld->find_widget("save_preset", save_preset);
209  bld->find_widget("new_preset_bank", new_preset_bank);
210  bld->find_widget("organize_presets", organize_presets);
211  bld->find_widget("online_preset", online_preset);
212  bld->find_widget_derived("bank_treeview", bank_treeview, sigc::ptr_fun(MyTreeView::create_from_builder));
213  bld->find_widget("bank_cellrenderer", bank_cellrenderer);
214  bld->find_widget_derived("preset_treeview", preset_treeview, sigc::ptr_fun(MyTreeView::create_from_builder));
215  bld->find_widget("preset_cellrenderer", preset_cellrenderer);
216  bld->find_widget("banks_combobox", banks_combobox);
217  bld->find_widget_derived("presets_target_treeview", presets_target_treeview, sigc::ptr_fun(MyTreeView::create_from_builder));
218  bld->find_widget("preset_title", preset_title);
219  bld->find_widget("presets_target_scrolledbox", presets_target_scrolledbox);
220  bld->find_widget("bank_column_edit", bank_column_edit);
221  bld->find_widget("bank_column_delete", bank_column_delete);
222  bld->find_widget("preset_column_edit", preset_column_edit);
223  bld->find_widget("preset_column_delete", preset_column_delete);
224  bld->find_widget("main_vpaned", main_vpaned);
225  bld->find_widget("preset_scrolledbox", preset_scrolledbox);
226 }
227 
228 static bool preset_button_press_idle(Gtk::Widget& w) {
229  w.grab_focus();
230  return false;
231 }
232 
233 bool PresetWindow::on_bank_query_tooltip(int x, int y, bool kb_tooltip, Glib::RefPtr<Gtk::Tooltip> tooltip) {
234  Gtk::TreeIter it;
235  if (!bank_treeview->get_tooltip_context_iter(x, y, kb_tooltip, it)) {
236  return false;
237  }
238  int tp = it->get_value(bank_col.tp);
240  return false;
241  }
242  Gtk::TreeModel::Path pt;
243  Gtk::TreeViewColumn *col;
244  int dx, dy;
245  if (!bank_treeview->get_path_at_pos(x, y, pt, col, dx, dy)) {
246  col = 0;
247  }
248  Glib::ustring nm = it->get_value(bank_col.name);
249  if (nm.empty()) {
250  return false;
251  }
252  gx_system::PresetFileGui *f = machine.get_bank_file(nm);
253  if (col == bank_treeview->get_column(0) || col == bank_treeview->get_column(1)) {
256  tooltip->set_text(_("damaged bank file; click to delete"));
257  } else if (f->get_flags() & gx_system::PRESET_FLAG_VERSIONDIFF) {
258  tooltip->set_text(
259  Glib::ustring::compose(_("wrong format version (is %1, need %2)\nclick to convert"),
260  f->get_header().version_string(),
262  } else if (f->get_flags() & gx_system::PRESET_FLAG_READONLY) {
263  tooltip->set_text(_("readonly bank, click to change to read-write"));
264  } else if (col == bank_treeview->get_column(0)){
265  tooltip->set_text(_("click to set to readonly"));
266  } else {
267  return false;
268  }
269  } else if (tp == gx_system::PresetFile::PRESET_FACTORY) {
270  tooltip->set_text(_("predefined factory preset bank"));
271  } else if (tp == gx_system::PresetFile::PRESET_SCRATCH) {
272  tooltip->set_text(_("scratch preset bank: changes will be persistent (without explicit saving)"));
273  } else {
274  return false;
275  }
276  } else if (col == bank_treeview->get_column(2)) {
277  if (f->get_flags()) {
278  return false;
279  }
280  tooltip->set_text(_("click to edit the bank name"));
281  } else if (col == bank_treeview->get_column(3)) {
282  if (f->get_flags()) {
283  return false;
284  }
285  tooltip->set_text(_("click to delete the bank"));
286  } else {
287  return false;
288  }
289  bank_treeview->set_tooltip_cell(tooltip, &pt, col, 0);
290  return true;
291 }
292 
293 void PresetWindow::on_preset_row_activated(const Gtk::TreePath& path, Gtk::TreeViewColumn* column) {
294  bool in_organize = actions.organize->get_active();
295  on_presets_close();
296  if (in_organize) {
297  preset_treeview->get_selection()->select(path);
298  }
299 }
300 
301 bool PresetWindow::on_preset_button_press(GdkEventButton *ev) {
302  if (ev->type == GDK_BUTTON_PRESS) {
303  Glib::signal_idle().connect(sigc::bind(sigc::ptr_fun(preset_button_press_idle), sigc::ref(*preset_treeview)));
304  }
305  return false;
306 }
307 
308 
309 void PresetWindow::on_preset_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& context, Gtk::SelectionData& selection, int info, int timestamp) {
310  if (selection.get_target() == "application/x-guitarix-preset") {
311  Gtk::TreeModel::Path path;
312  Gtk::TreeViewColumn *focus_column;
313  preset_treeview->get_cursor(path, focus_column);
314  Glib::ustring data = pstore->get_iter(path)->get_value(pstore->col.name);
315  selection.set("application/x-guitarix-preset", data);
316  }
317 }
318 
319 void PresetWindow::on_bank_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& context, Gtk::SelectionData& selection, int info, int timestamp) {
320  if (info != URILIST_TARGET && info != TEXT_TARGETS) {
321  return;
322  }
323  Gtk::TreeModel::Path path;
324  Gtk::TreeViewColumn *focus_column;
325  bank_treeview->get_cursor(path, focus_column);
326  Glib::RefPtr<Gio::File> f =
327  Gio::File::create_for_path(
328  machine.bank_get_filename(
329  bank_treeview->get_model()->get_iter(path)->get_value(bank_col.name)));
330  if (info == TEXT_TARGETS) {
331  selection.set_text(f->get_path());
332  } else {
333  std::vector<std::string> uris;
334  uris.push_back(f->get_uri());
335  selection.set_uris(uris);
336  }
337 }
338 
339 void PresetWindow::on_bank_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, const Gtk::SelectionData& data, guint info, guint timestamp) {
340  if (info != URILIST_TARGET) {
341  return;
342  }
343 #if false //gtk 2.22
344  bool is_move = context->get_selected_action() == Gdk::ACTION_MOVE;
345 #else
346  bool is_move = gdk_drag_context_get_selected_action(context->gobj()) == GDK_ACTION_MOVE;
347 #endif
348  bool success = false;
349  std::vector<Glib::ustring> uris = data.get_uris();
350  Glib::RefPtr<Gtk::ListStore> ls = Glib::RefPtr<Gtk::ListStore>::cast_dynamic(bank_treeview->get_model());
351  for (std::vector<Glib::ustring>::iterator i = uris.begin(); i != uris.end(); ++i) {
352  gx_system::PresetFileGui *f = machine.bank_insert_uri(*i, is_move);
353  if (f) {
354  Gtk::TreeIter i = ls->prepend();
355  set_row_for_presetfile(i,f);
356  bank_treeview->set_cursor(ls->get_path(i));
357  bank_treeview->get_selection()->select(i);
358  success = true;
359  }
360  }
361  context->drag_finish(success, false, timestamp);
362 }
363 
364 Glib::ustring PresetWindow::get_combo_selection() {
365  Gtk::TreeIter idx = banks_combobox->get_active();
366  if (!idx) {
367  return "";
368  }
369  return idx->get_value(target_col.name);
370 }
371 
372 /*
373  ** dnd target
374  */
375 
376 void PresetWindow::target_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, const Gtk::SelectionData& data, guint info, guint timestamp) {
377  Glib::ustring bank = get_combo_selection();
378  if (bank.empty()) {
379  presets_target_treeview->signal_drag_data_received().emission_stop();
380  return;
381  }
382  gx_system::PresetFileGui& fl = *machine.get_bank_file(bank);
383  Glib::RefPtr<Gtk::ListStore> ls = Glib::RefPtr<Gtk::ListStore>::cast_dynamic(presets_target_treeview->get_model());
384  Glib::ustring srcnm = data.get_data_as_string();
385  Glib::ustring dstnm = srcnm;
386  int n = 1;
387  while (fl.has_entry(dstnm)) {
388  dstnm = srcnm + "-" + gx_system::to_string(n);
389  n += 1;
390  }
391  Glib::ustring src_bank = get_current_bank();
392  gx_system::PresetFileGui& pf = *machine.bank_get_file(src_bank);
393  if (src_bank == bank) {
394  gx_print_error("preset", "can't copy inside the same bank");
395  return;
396  }
397  Gtk::TreeModel::Path pt;
398  Gtk::TreeViewDropPosition dst;
399  if (!presets_target_treeview->get_dest_row_at_pos(x, y, pt, dst)) {
400  ls->append()->set_value(target_col.name, dstnm);
401  machine.pf_append(pf, srcnm, fl, dstnm);
402  } else {
403  Gtk::TreeIter it = ls->get_iter(pt);
404  if (dst == Gtk::TREE_VIEW_DROP_BEFORE || dst == Gtk::TREE_VIEW_DROP_INTO_OR_BEFORE) {
405  ls->insert(it)->set_value(target_col.name, dstnm);
406  machine.pf_insert_before(pf, srcnm, fl, it->get_value(target_col.name), dstnm);
407  } else { // gtk.TREE_VIEW_DROP_INTO_OR_AFTER, gtk.TREE_VIEW_DROP_AFTER
408  ls->insert_after(it)->set_value(target_col.name, dstnm);
409  machine.pf_insert_after(pf, srcnm, fl, it->get_value(target_col.name), dstnm);
410  }
411  }
412  if (context->get_action() == Gdk::ACTION_MOVE) {
413  Gtk::TreeModel::Path pt;
414  Gtk::TreeViewColumn *col;
415  preset_treeview->get_cursor(pt, col);
416  preset_row_del_conn.block();
417  pstore->erase(pstore->get_iter(pt));
418  preset_row_del_conn.unblock();
419  machine.erase_preset(pf, srcnm);
420  }
421  if (src_bank == bank) {
422  on_bank_changed();
423  }
424 }
425 
426 bool PresetWindow::on_target_drag_motion(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint timestamp) {
427  Gtk::Widget *source_widget = Gtk::Widget::drag_get_source_widget(context);
428  if (source_widget != preset_treeview || get_combo_selection().empty()) {
429  context->drag_status((Gdk::DragAction)0, timestamp);
430  return true;
431  }
432  presets_target_treeview->on_drag_motion(context, x, y, timestamp);
433  Gtk::TreeIter it = bank_treeview->get_selection()->get_selected();
434  int tp = it->get_value(bank_col.tp);
435  Glib::ustring nm = it->get_value(bank_col.name);
437  get_combo_selection() == nm) {
438  context->drag_status(Gdk::ACTION_COPY, timestamp);
439  }
440  return true;
441 }
442 
443 void PresetWindow::reload_combo() {
444  Glib::ustring old = get_combo_selection();
445  Glib::RefPtr<Gtk::ListStore> ls = Glib::RefPtr<Gtk::ListStore>::cast_dynamic(banks_combobox->get_model());
446  ls->clear();
447  int n = 0;
448  int nn = -1;
449  for (gx_engine::bank_iterator i = machine.bank_begin(); i != machine.bank_end(); ++i) {
450  int tp = i->get_type();
452  continue;
453  }
454  if (i->get_flags()) {
455  continue;
456  }
457  Glib::ustring s = i->get_name();
458  ls->append()->set_value(bank_col.name, s);
459  if (s == old) {
460  nn = n;
461  }
462  n += 1;
463  }
464  banks_combobox->set_active(nn);
465 }
466 
467 void PresetWindow::on_preset_combo_changed() {
468  Glib::RefPtr<Gtk::ListStore> ls = Glib::RefPtr<Gtk::ListStore>::cast_dynamic(presets_target_treeview->get_model());
469  ls->clear();
470  Glib::ustring nm = get_combo_selection();
471  if (nm.empty()) {
472  return;
473  }
474  gx_system::PresetFileGui& f = *machine.get_bank_file(nm);
475  for (gx_system::PresetFile::iterator i = f.begin(); i != f.end(); ++i) {
476  ls->append()->set_value(bank_col.name, i->name);
477  }
478 }
479 
480 void PresetWindow::reload_target() {
481  on_preset_combo_changed();
482 }
483 
484 /*
485  ** name edit
486  */
487 
488 bool PresetWindow::select_func(const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreePath& path, bool path_currently_selected) {
489  Glib::ustring s = model->get_iter(path)->get_value(bank_col.name);
490  if (s.empty()) {
491  return false;
492  }
493  return true;
494 }
495 
496 void PresetWindow::on_editing_started(const Gtk::CellEditable* edit, const Glib::ustring& path, Glib::RefPtr<Gtk::TreeModel>& model) {
497  Glib::ustring s = model->get_iter(path)->get_value(bank_col.name);
498  if (s.empty()) {
499  dynamic_cast<Gtk::Entry*>(const_cast<Gtk::CellEditable*>(edit))->set_text("");
500  } else {
501  dynamic_cast<Gtk::Entry*>(const_cast<Gtk::CellEditable*>(edit))->set_text(s);
502  }
503  dynamic_cast<Gtk::Window*>(main_vpaned->get_toplevel())->remove_accel_group(actions.accels);
504 }
505 
506 bool PresetWindow::edit_cell(const Gtk::TreeModel::Path pt, Gtk::TreeViewColumn& col, Gtk::CellRenderer& cell) {
507  dynamic_cast<Gtk::CellRendererText*>(&cell)->property_editable().set_value(true);
508  col.get_tree_view()->set_cursor(pt, col, true);
509  return false;
510 }
511 
512 void PresetWindow::reset_edit(Gtk::TreeViewColumn& col) {
513  if (edit_iter) {
514  Glib::RefPtr<Gtk::ListStore> ls = Glib::RefPtr<Gtk::ListStore>::cast_dynamic(col.get_tree_view()->get_model());
515  ls->erase(edit_iter);
516  edit_iter = ls->children().end();
517  }
518  Gtk::CellRendererText& cell = *dynamic_cast<Gtk::CellRendererText*>(col.get_first_cell_renderer());
519  cell.property_editable().set_value(false);
520  col.set_min_width(0);
521  col.queue_resize();
522  in_edit = false;
523  dynamic_cast<Gtk::Window*>(main_vpaned->get_toplevel())->add_accel_group(actions.accels);
524 }
525 
526 void PresetWindow::on_edit_canceled(Gtk::TreeViewColumn *col) {
527  reset_edit(*col);
528 }
529 
530 void PresetWindow::start_edit(const Gtk::TreeModel::Path& pt, Gtk::TreeViewColumn& col, Gtk::CellRenderer& cell) {
531  col.set_min_width(100);
532  Glib::signal_idle().connect(
533  sigc::bind(sigc::mem_fun(*this, &PresetWindow::edit_cell),
534  pt, sigc::ref(col), sigc::ref(cell)));
535 }
536 
537 /*
538  ** list of banks
539  */
540 
541 void PresetWindow::highlight_current_bank(Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator& iter) {
542  Glib::ustring t = iter->get_value(bank_col.name);
543  if (t.empty()) {
544  return;
545  }
546  Gtk::CellRendererText *tc = dynamic_cast<Gtk::CellRendererText*>(cell);
547  if (machine.setting_is_preset() && t == machine.get_current_bank()) {
548  tc->property_foreground().set_value("#f00");
549  } else{
550  tc->property_foreground_set().set_value(false);
551  }
552  int n = machine.bank_size() - *bank_treeview->get_model()->get_path(iter).begin();
554  n -= 1;
555  }
556  if (n > 26) {
557  t = " " + t;
558  } else {
559  t = Glib::ustring::compose("%1: %2", char('A'+n), t);
560  }
561  cell->set_property("text", t);
562 }
563 
564 Glib::ustring PresetWindow::get_current_bank() {
565  Gtk::TreeIter it = get_current_bank_iter();
566  if (!it) {
567  return "";
568  }
569  return it->get_value(bank_col.name);
570 }
571 
572 bool PresetWindow::run_message_dialog(Gtk::Widget& w, const Glib::ustring& msg) {
573  Gtk::MessageDialog d(*dynamic_cast<Gtk::Window*>(w.get_toplevel()), msg, false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL, true);
574  d.set_position(Gtk::WIN_POS_MOUSE);
575  return d.run() == Gtk::RESPONSE_OK;
576 }
577 
578 bool PresetWindow::on_bank_button_release(GdkEventButton *ev) {
579  // edit bank name / delete bank
580  Gtk::TreeModel::Path pt;
581  Gtk::TreeViewColumn *col;
582  int dx, dy;
583  if (!bank_treeview->get_path_at_pos(ev->x, ev->y, pt, col, dx, dy)) {
584  return false;
585  }
586  Gtk::TreeModel::Path path;
587  Gtk::TreeViewColumn *focus_column;
588  bank_treeview->get_cursor(path, focus_column);
589  if (col != focus_column || pt != path) {
590  return false;
591  }
592  Glib::RefPtr<Gtk::ListStore> ls = Glib::RefPtr<Gtk::ListStore>::cast_dynamic(bank_treeview->get_model());
593  Gtk::TreeModel::iterator it = ls->get_iter(pt);
594  Glib::ustring nm = it->get_value(bank_col.name);
595  int tp = it->get_value(bank_col.tp);
596  if (col == bank_treeview->get_column(0)) {
598  int flags = machine.get_bank_file(nm)->get_flags();
599  gx_system::PresetFileGui *f = machine.get_bank_file(nm);
600  if (flags == 0 && tp == gx_system::PresetFile::PRESET_FILE) {
601  /*if (run_message_dialog(*bank_treeview, "set bank " + nm + " to readonly?")) {*/
603  reload_banks(nm);
604  } else if (flags == gx_system::PRESET_FLAG_VERSIONDIFF) {
605  if (run_message_dialog(*bank_treeview, "convert bank " + nm + " to new version?")) {
606  if (machine.convert_preset(*f)) {
607  reload_banks(nm);
608  }
609  }
610  } else if (flags == gx_system::PRESET_FLAG_READONLY) {
611  /*if (run_message_dialog(*bank_treeview, "set bank " + nm + " to read/write?")) {*/
613  reload_banks(nm);
615  if (run_message_dialog(*bank_treeview, "convert readonly bank " + nm + " to new version?")) {
616  if (machine.convert_preset(*f)) {
617  reload_banks(nm);
618  }
619  }
620  } else if (flags & gx_system::PRESET_FLAG_INVALID) {
621  if (run_message_dialog(
622  *bank_treeview, "delete damaged bank " + nm + "?"
623  " Export it before deleting and ask in the"
624  " guitarix online forum if you want to try to repair it!")) {
625  machine.bank_remove(nm);
626  reload_banks(nm);
627  }
628  }
629  }
630  return false;
631  }
632  if (tp != gx_system::PresetFile::PRESET_FILE || machine.get_bank_file(nm)->get_flags()) {
633  return false;
634  }
635  if (col == bank_treeview->get_column(2)) {
636  col = bank_treeview->get_column(1);
637  start_edit(pt, *col, *col->get_first_cell_renderer());
638  } else if (col == bank_treeview->get_column(3)) {
639  Gtk::MessageDialog d(*dynamic_cast<Gtk::Window*>(bank_treeview->get_toplevel()), "delete bank " + nm + "?", false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL, true);
640  d.set_position(Gtk::WIN_POS_MOUSE);
641  if (d.run() == Gtk::RESPONSE_OK) {
642  bank_row_del_conn.block();
643  ls->erase(it);
644  bank_row_del_conn.unblock();
645  machine.bank_remove(nm);
646  reload_combo();
647  if (!machine.setting_is_preset()) { // if current bank was removed
648  actions.save_changes->set_sensitive(false);
649  }
650  }
651  }
652  return false;
653 }
654 
655 void PresetWindow::on_bank_edited(const Glib::ustring& path, const Glib::ustring& newtext, Gtk::TreeView* w) {
656  Gtk::TreeIter sel = w->get_model()->get_iter(path);
657  Glib::ustring oldname = sel->get_value(bank_col.name);
658  Glib::ustring newname = newtext;
659  gx_system::strip(newname);
660  if (newname.empty() || newname == oldname) {
661  Gtk::TreeViewColumn *p = w->get_column(1);
662  reset_edit(*p);
663  return;
664  }
665  Glib::RefPtr<Gtk::ListStore> ls = Glib::RefPtr<Gtk::ListStore>::cast_dynamic(banks_combobox->get_model());
666  if (edit_iter) {
667  gx_system::PresetFileGui *f = machine.bank_insert_new(newname);
668  if (f) {
669  ls->prepend()->set_value(target_col.name, f->get_name());
670  edit_iter = ls->children().end();
671  set_row_for_presetfile(sel, f);
672  w->get_selection()->select(sel);
673  }
674  } else {
675  machine.rename_bank(oldname, newname);
676  Gtk::TreeNodeChildren ch = ls->children();
677  for (Gtk::TreeIter it = ch.begin(); it != ch.end(); ++it) {
678  if (it->get_value(bank_col.name) == oldname) {
679  it->set_value(bank_col.name, newname);
680  }
681  }
682  w->get_model()->get_iter(path)->set_value(bank_col.name, newname);
683  }
684  Gtk::TreeViewColumn *p = w->get_column(1);
685  reset_edit(*p);
686 }
687 
688 bool PresetWindow::is_row_separator(const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::iterator& iter) {
689  return iter->get_value(bank_col.tp) == gx_system::PresetFile::PRESET_SEP;
690 }
691 
692 void PresetWindow::on_new_bank() {
693  Glib::RefPtr<Gtk::ListStore> m = Glib::RefPtr<Gtk::ListStore>::cast_dynamic(bank_treeview->get_model());
694  edit_iter = m->prepend();
695  edit_iter->set_value(bank_col.tp, static_cast<int>(gx_system::PresetFile::PRESET_FILE));
696  in_edit = true;
697  start_edit(m->get_path(edit_iter), *bank_treeview->get_column(1), *bank_cellrenderer);
698 }
699 
700 // Online Preset Downloader
701 
702 Glib::ustring PresetWindow::resolve_hostname() {
703  static Glib::ustring hostname = "localhost";
704  if (! machine.get_jack()) {
705  hostname = Gio::Resolver::get_default()->lookup_by_address
706  (Gio::InetAddress::create( machine.get_options().get_rpcaddress()));
707  }
708  return hostname;
709 }
710 
711 bool PresetWindow::download_file(Glib::ustring from_uri, Glib::ustring to_path) {
712 
713  CURLcode res;
714  FILE *out;
715  out = fopen(to_path.c_str(), "wb");
716 
717  curl_easy_setopt(curl, CURLOPT_WRITEDATA, out);
718  curl_easy_setopt(curl, CURLOPT_URL, from_uri.c_str());
719  res = curl_easy_perform(curl);
720  if(CURLE_OK == res) {
721  char *ct = NULL;
722  res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
723  if (strstr(ct, "application/json")!= NULL ) {
724  gx_print_info( "download_file", from_uri);
725  } else if (strstr(ct, "application/octet-stream")!= NULL) {
726  gx_print_info( "download_preset", from_uri);
727  } else {
728  res = CURLE_CONV_FAILED;
729  }
730  }
731  curl_easy_reset(curl);
732  fclose(out);
733  if(res != CURLE_OK) {
734  remove(to_path.c_str());
735  gx_print_error( "download_file", Glib::ustring::compose("curl_easy_perform() failed: %1", curl_easy_strerror(res)));
736  return false;
737  }
738  return true;
739 }
740 
741 void PresetWindow::downloadPreset(Gtk::Menu *presetMenu,std::string uri) {
742 
743  std::string::size_type n = uri.find_last_of('/');
744  if (n != std::string::npos) {
745  std::string fn = uri.substr(n);
746  std::string ff = "/tmp"+fn;
747 
748  if (download_file(uri, ff)) {
749  Glib::RefPtr<Gtk::ListStore> ls = Glib::RefPtr<Gtk::ListStore>::cast_dynamic(bank_treeview->get_model());
750  gx_system::PresetFileGui *f = machine.bank_insert_uri(Glib::filename_to_uri(ff, resolve_hostname()), false);
751  if (f) {
752  Gtk::TreeIter i = ls->prepend();
753  set_row_for_presetfile(i,f);
754  bank_treeview->set_cursor(ls->get_path(i));
755  bank_treeview->get_selection()->select(i);
756  }
757  }
758  } else {
759  gx_print_error("downloadPreset", _("can't download preset from https://musical-artifacts.com/"));
760  }
761 }
762 
763 void PresetWindow::read_preset_menu() {
764  if (! machine.get_jack()) usleep(5000);
765  Glib::RefPtr<Gio::File> dest = Gio::File::create_for_uri(Glib::filename_to_uri(options.get_online_config_filename(), resolve_hostname()));
766  Glib::RefPtr<Gio::DataInputStream> in = Gio::DataInputStream::create(dest->read());
767  std::string NAME_;
768  std::string FILE_;
769  std::string INFO_;
770  std::string AUTHOR_;
771  std::string line;
772  while ( in->read_line(line) )
773  {
774  std::istringstream is(line);
775  gx_system::JsonParser jp(&is);
776  try {
778  do {
780  do {
782  if (jp.current_value() == "name") {
783  jp.read_kv("name", NAME_);
784  } else if (jp.current_value() == "description") {
785  jp.read_kv("description", INFO_);
786  } else if (jp.current_value() == "author") {
787  jp.read_kv("author", AUTHOR_);
788  } else if (jp.current_value() == "file") {
789  jp.read_kv("file", FILE_);
790  INFO_ += "Author : " + AUTHOR_;
791  olp.push_back(std::tuple<std::string,std::string,std::string>(NAME_,FILE_,INFO_));
792  } else {
793  jp.skip_object();
794  }
795  } while (jp.peek() == gx_system::JsonParser::value_key);
797  } while (jp.peek() == gx_system::JsonParser::begin_object);
798  } catch (gx_system::JsonException& e) {
799  cerr << "JsonException: " << e.what() << ": '" << jp.current_value() << "'" << endl;
800  assert(false);
801  }
802  }
803  in->close ();
804 }
805 
806 void PresetWindow::popup_pos( int& x, int& y, bool& push_in ){
807  online_preset->get_window()->get_origin( x, y );
808  x +=150;
809  y -= 450;
810  push_in = false;
811 }
812 
813 void PresetWindow::create_preset_menu(bool is_new) {
814 
815  static bool read_new = true;
816  if (read_new || is_new) {
817  read_preset_menu();
818  read_new = false;
819  }
820 
821  Gtk::MenuItem* item;
822  Gtk::Menu *presetMenu = Gtk::manage(new Gtk::Menu());
823  presetMenu->set_size_request (-1, 600);
824  for(std::vector<std::tuple<std::string,std::string,std::string> >::iterator it = olp.begin(); it != olp.end(); it++) {
825  item = Gtk::manage(new Gtk::MenuItem(get<0>(*it), true));
826  item->set_tooltip_text(get<2>(*it));
827  std::string f = get<1>(*it);
828  item->signal_activate().connect(sigc::bind(sigc::bind(sigc::mem_fun(
829  *this, &PresetWindow::downloadPreset),f),presetMenu));
830  presetMenu->append(*item);
831 
832  }
833  presetMenu->show_all();
834  presetMenu->popup(Gtk::Menu::SlotPositionCalc(sigc::mem_fun(
835  *this, &PresetWindow::popup_pos ) ),0,gtk_get_current_event_time());
836 }
837 
838 void PresetWindow::replace_inline(std::string& subject, const std::string& search,
839  const std::string& replace) {
840  size_t pos = 0;
841  while ((pos = subject.find(search, pos)) != std::string::npos) {
842  subject.replace(pos, search.length(), replace);
843  pos += replace.length();
844  }
845 }
846 
847 void PresetWindow::show_online_preset() {
848 
849  Glib::RefPtr<Gio::File> dest = Gio::File::create_for_uri(Glib::filename_to_uri(options.get_online_config_filename(), resolve_hostname()));
850  static bool load_new = true;
851  static bool load = false;
852  Glib::RefPtr<Gdk::Window> window = preset_scrolledbox->get_toplevel()->get_window();
853  if (load_new || ! dest->query_exists()) {
854  Gdk::Cursor cursor(Gdk::WATCH);
855  window->set_cursor(cursor);
856  if (dest->query_exists()) {
857  Gtk::MessageDialog *d = new Gtk::MessageDialog(*dynamic_cast<Gtk::Window*>(online_preset->get_toplevel()),
858  "Do you want to check for new presets from\n https://musical-artifacts.com ? \n Note, that may take a while",
859  false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true);
860  d->set_position(Gtk::WIN_POS_MOUSE);
861  if (d->run() == Gtk::RESPONSE_YES) load = true;
862  delete d;
863  }
864  if (load || ! dest->query_exists()) {
865  if (!download_file("https://musical-artifacts.com/artifacts.json?apps=guitarix", options.get_online_config_filename())) {
866  window->set_cursor();
867  return;
868  }
869  }
870  window->set_cursor();
871  }
872  load_new = false;
873  create_preset_menu(load_new);
874 }
875 
876 void PresetWindow::on_online_preset() {
877  Glib::signal_idle().connect_once(sigc::mem_fun(*this, &PresetWindow::show_online_preset));
878 }
879 
880 bool PresetWindow::on_bank_drag_motion(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint timestamp) {
881  Gtk::Widget *source_widget = Gtk::Widget::drag_get_source_widget(context);
882  if (!source_widget) {
883  // URI from other application
884  Gdk::DragAction a;
885  if (context->get_suggested_action() == Gdk::ACTION_MOVE) {
886  a = context->get_suggested_action();
887  } else {
888  a = Gdk::ACTION_COPY;
889  }
890  context->drag_status(a, timestamp);
891  } else if (source_widget != bank_treeview) {
892  // other window
893  context->drag_status((Gdk::DragAction)0, timestamp);
894  } else {
895  // reorder
896  Gtk::TreeIter it = bank_treeview->get_selection()->get_selected();
897  if (!it) {
898  return true;
899  }
900  int tp = it->get_value(bank_col.tp);
902  context->drag_status((Gdk::DragAction)0, timestamp);
903  return true;
904  }
905  Gtk::TreeModel::Path pt;
906  Gtk::TreeViewDropPosition dst;
907  if (bank_treeview->get_dest_row_at_pos(x, y, pt, dst)) {
908  tp = bank_treeview->get_model()->get_iter(pt)->get_value(bank_col.tp);
910  context->drag_status((Gdk::DragAction)0, timestamp);
911  return true;
912  }
913  }
914  bank_treeview->on_drag_motion(context, x, y, timestamp);
915  context->drag_status(Gdk::ACTION_MOVE, timestamp);
916  }
917  return true;
918 }
919 
920 void PresetWindow::on_bank_changed() {
921  preset_row_del_conn.block();
922  if (in_edit) {
923  pstore->prepend();
924  }
925  pstore->clear();
926  preset_row_del_conn.unblock();
927  Gtk::TreeIter it = bank_treeview->get_selection()->get_selected();
928  if (!it) {
929  in_current_preset = false;
930  return;
931  }
932  Glib::ustring nm = it->get_value(bank_col.name);
933  preset_title->set_text(nm);
934  in_current_preset = (nm == machine.get_current_bank());
935  Gtk::TreeIter i;
936  gx_system::PresetFileGui& ll = *machine.get_bank_file(nm);
938  ((ll.get_flags() & gx_system::PRESET_FLAG_READONLY) && !actions.organize->get_active())) {
939  preset_treeview->unset_rows_drag_source();
940  } else {
941  preset_treeview->unset_rows_drag_source(); //FIXME: needed?
942  preset_treeview->set_reorderable(true);
943  std::vector<Gtk::TargetEntry> listTargets2;
944  listTargets2.push_back(Gtk::TargetEntry("GTK_TREE_MODEL_ROW", Gtk::TARGET_SAME_WIDGET, 0));
945  listTargets2.push_back(Gtk::TargetEntry("application/x-guitarix-preset", Gtk::TARGET_SAME_APP, 1));
946  preset_treeview->enable_model_drag_source(listTargets2, Gdk::BUTTON1_MASK, Gdk::ACTION_COPY|Gdk::ACTION_MOVE);
947  }
948  bool modifiable = ll.is_mutable();
949  for (gx_system::PresetFile::iterator s = ll.begin(); s != ll.end(); ++s) {
950  i = pstore->append();
951  i->set_value(pstore->col.name, s->name);
952  if (modifiable) {
953  i->set_value(pstore->col.edit_pb, pb_edit);
954  i->set_value(pstore->col.del_pb, pb_del);
955  }
956  if (in_current_preset && s->name == machine.get_current_name()) {
957  if (preset_treeview->get_mapped()) {
958  preset_treeview->scroll_to_row(pstore->get_path(i));
959  }
960  }
961  }
962  if (modifiable) {
963  i = pstore->append();
964  }
965 }
966 
967 void PresetWindow::set_row_for_presetfile(Gtk::TreeIter i, gx_system::PresetFileGui *f) {
968  i->set_value(bank_col.name, f->get_name());
970  i->set_value(bank_col.type_pb, pb_del);
971  } else if (f->get_flags() & gx_system::PRESET_FLAG_VERSIONDIFF) {
972  i->set_value(bank_col.type_pb, pb_versiondiff);
973  } else if (f->get_flags() & gx_system::PRESET_FLAG_READONLY) {
974  i->set_value(bank_col.type_pb, pb_readonly);
975  }
976  int tp = f->get_type();
977  i->set_value(bank_col.tp, tp);
979  i->set_value(bank_col.type_pb, pb_scratch);
980  } else if (tp == gx_system::PresetFile::PRESET_FACTORY) {
981  i->set_value(bank_col.type_pb, pb_factory);
982  } else if (f->is_mutable() || f->get_flags() & gx_system::PRESET_FLAG_VERSIONDIFF) {
983  i->set_value(bank_col.edit_pb, pb_edit);
984  i->set_value(bank_col.del_pb, pb_del);
985  }
986 }
987 
988 void PresetWindow::reload_banks(const Glib::ustring& sel_bank) {
989  preset_row_del_conn.block();
990  pstore->clear();
991  preset_row_del_conn.unblock();
992  Glib::RefPtr<Gtk::ListStore> ls = Glib::RefPtr<Gtk::ListStore>::cast_dynamic(bank_treeview->get_model());
993  bank_row_del_conn.block();
994  ls->clear();
995  bank_row_del_conn.unblock();
996  Gtk::TreeIter i;
997  int in_factory = false;
998  for (gx_engine::bank_iterator v = machine.bank_begin(); v != machine.bank_end(); ++v) {
999  if (!in_factory && v->get_type() == gx_system::PresetFile::PRESET_FACTORY) {
1000  i = ls->append();
1001  i->set_value(bank_col.tp, static_cast<int>(gx_system::PresetFile::PRESET_SEP));
1002  in_factory = true;
1003  }
1004  i = ls->append();
1005  set_row_for_presetfile(i, *v);
1006  if (v->get_name() == sel_bank) {
1007  bank_treeview->get_selection()->select(i);
1008  }
1009  }
1010  reload_combo();
1011 }
1012 
1013 void PresetWindow::set_presets() {
1014  reload_banks(machine.get_current_bank());
1015 }
1016 
1017 void PresetWindow::on_bank_reordered(const Gtk::TreeModel::Path& path) {
1018  Glib::RefPtr<Gtk::TreeModel> ls = bank_treeview->get_model();
1019  Gtk::TreeModel::Children ch = ls->children();
1020  std::vector<Glib::ustring> l;
1021  for (Gtk::TreeIter i = ch.begin(); i != ch.end(); ++i) {
1022  int tp = i->get_value(bank_col.tp);
1023  Glib::ustring nm = i->get_value(bank_col.name);
1024  if (!nm.empty() && (tp == gx_system::PresetFile::PRESET_SCRATCH || tp == gx_system::PresetFile::PRESET_FILE)) {
1025  l.push_back(nm);
1026  }
1027  }
1028  machine.bank_reorder(l);
1029 }
1030 
1031 /*
1032  ** list of presets
1033  */
1034 
1035 void PresetWindow::text_func(Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator& iter) {
1036  Glib::ustring val = iter->get_value(pstore->col.name);
1037  Glib::ustring t = val;
1038 #if false // gtk 2.24
1039  if (t.empty() && !cell->property_editing().get_value()) {
1040  } //to make indent happy (remove)
1041 #else
1042  gboolean editing;
1043  g_object_get(cell->gobj(), "editing", &editing, NULL);
1044  if (t.empty() && !editing) {
1045 #endif
1046  t = "<new>";
1047  } else if (in_current_preset) {
1048  int n = *pstore->get_path(iter).begin();
1049  if (n > 9) {
1050  t = " " + t;
1051  } else {
1052  t = Glib::ustring::compose("%1: %2", n, t);
1053  }
1054  }
1055  cell->set_property("text", t);
1056  Gtk::CellRendererText *tc = dynamic_cast<Gtk::CellRendererText*>(cell);
1057  if (in_current_preset && machine.setting_is_preset() && val == machine.get_current_name()) {
1058  tc->property_foreground().set_value("#f00");
1059  } else{
1060  tc->property_foreground_set().set_value(false);
1061  }
1062 }
1063 
1064 bool PresetWindow::on_preset_button_release(GdkEventButton *ev) {
1065  Gtk::TreeModel::Path pt;
1066  Gtk::TreeViewColumn *col;
1067  int dx, dy;
1068  if (!preset_treeview->get_path_at_pos(ev->x, ev->y, pt, col, dx, dy)) {
1069  return false;
1070  }
1071  Gtk::TreeModel::Path path;
1072  Gtk::TreeViewColumn *focus_column;
1073  preset_treeview->get_cursor(path, focus_column);
1074  if (col != focus_column || !path || pt != path) {
1075  return false;
1076  }
1077  Gtk::TreeIter bank_iter = get_current_bank_iter();
1078  int tp = bank_iter->get_value(bank_col.tp);
1079  if ((tp != gx_system::PresetFile::PRESET_SCRATCH && tp != gx_system::PresetFile::PRESET_FILE) || machine.get_bank_file(bank_iter->get_value(bank_col.name))->get_flags()) {
1080  return false;
1081  }
1082  if (col == preset_treeview->get_column(1)) {
1083  col = preset_treeview->get_column(0);
1084  start_edit(pt, *col, *col->get_first_cell_renderer());
1085  } else if (col == preset_treeview->get_column(2)) {
1086  Glib::ustring nm = pstore->get_iter(pt)->get_value(pstore->col.name);
1087  Gtk::MessageDialog d(*dynamic_cast<Gtk::Window*>(preset_treeview->get_toplevel()), Glib::ustring::compose("delete preset %1?", nm), false,
1088  Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL, true);
1089  d.set_position(Gtk::WIN_POS_MOUSE);
1090  if (d.run() == Gtk::RESPONSE_OK) {
1091  preset_row_del_conn.block();
1092  pstore->erase(pstore->get_iter(pt));
1093  preset_row_del_conn.unblock();
1094  machine.erase_preset(*machine.get_bank_file(bank_iter->get_value(bank_col.name)), nm);
1095  reload_target();
1096  }
1097  }
1098  return false;
1099 }
1100 
1101 void PresetWindow::on_preset_edited(const Glib::ustring& path, const Glib::ustring& newtext) {
1102  Gtk::TreeIter it = pstore->get_iter(path);
1103  Glib::ustring oldname = it->get_value(pstore->col.name);
1104  Glib::ustring newname = newtext;
1105  gx_system::strip(newname);
1106  if (newname.empty() || newname == oldname) {
1107  reset_edit(*preset_treeview->get_column(0));
1108  return;
1109  }
1110  // vowel mutation lead to a Glib::markup error when building the menu action,
1111  // so check for it and avoid them
1112  if (newname.find_first_of("ÜüūûúùÖöøøōôóòǫ°Ääæǣāàáâąþćēêèéīîíìȳŷýỳźżłśñ&%$§!?*#|<>/~_") != Glib::ustring::npos) {
1113  gx_print_error("PresetWindow", "Vowel mutation isn't allowed in preset names, please choose a name without \n(ÜüūûúùÖöøøōôóòǫ°Ääæǣāàáâąþēêèéīîíìȳŷýỳñ&%$§!?*#|<>/~_)");
1114  reset_edit(*preset_treeview->get_column(0));
1115  return;
1116  }
1117  gx_system::PresetFileGui& fl = *machine.get_bank_file(get_current_bank());
1118  Glib::ustring t = newname;
1119  int n = 1;
1120  while (fl.has_entry(newname)) {
1121  newname = Glib::ustring::compose("%1-%2", t, n);
1122  n += 1;
1123  }
1124  it->set_value(pstore->col.name, newname);
1125  it->set_value(pstore->col.edit_pb, pb_edit);
1126  it->set_value(pstore->col.del_pb, pb_del);
1127  if (oldname.empty()) {
1128  // check if current preset is scratch and needs to be saved
1129  if (!machine.get_current_bank().empty()) {
1130  gx_system::PresetFileGui *cpf = machine.get_bank_file(machine.get_current_bank());
1131  if (cpf && cpf->has_entry(machine.get_current_name())) {
1132  if (cpf->get_type() == gx_system::PresetFile::PRESET_SCRATCH && cpf->is_mutable()) {
1133  machine.pf_save(*cpf, machine.get_current_name());
1134  }
1135  }
1136  }
1137  pstore->append();
1138  machine.pf_save(fl, newname);
1139  } else {
1140  machine.rename_preset(fl, oldname, newname);
1141  }
1142  reload_target();
1143  reset_edit(*preset_treeview->get_column(0));
1144 }
1145 
1146 void PresetWindow::on_cursor_changed() {
1147  if (in_edit) {
1148  return;
1149  }
1150  Gtk::TreeModel::Path path;
1151  Gtk::TreeViewColumn *focus_column;
1152  preset_treeview->get_cursor(path, focus_column);
1153  if (!pstore->get_iter(path)->get_value(pstore->col.name).empty()) {
1154  return;
1155  }
1156  in_edit = true;
1157  start_edit(path, *preset_treeview->get_column(0), *preset_cellrenderer);
1158 }
1159 
1160 bool PresetWindow::on_preset_drag_motion(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint timestamp) {
1161  if (Gtk::Widget::drag_get_source_widget(context) == preset_treeview) {
1162  Gtk::TreeIter it = bank_treeview->get_selection()->get_selected();
1163  bool ro = it && (machine.get_bank_file(it->get_value(bank_col.name))->get_flags() & gx_system::PRESET_FLAG_READONLY);
1164  if (!ro) {
1165  preset_treeview->on_drag_motion(context, x, y, timestamp);
1166  Gtk::TreeModel::Path pt;
1167  Gtk::TreeViewDropPosition dst;
1168  if (preset_treeview->get_dest_row_at_pos(x, y, pt, dst)) {
1169  if (dst == Gtk::TREE_VIEW_DROP_BEFORE ||
1170  (dst == Gtk::TREE_VIEW_DROP_AFTER &&
1171  !pstore->get_iter(pt)->get_value(pstore->col.name).empty())) {
1172  context->drag_status(Gdk::ACTION_MOVE, timestamp);
1173  return true;
1174  }
1175  }
1176  }
1177  }
1178  context->drag_status((Gdk::DragAction)0, timestamp);
1179  return true;
1180 }
1181 
1182 void PresetWindow::on_preset_reordered(const Gtk::TreeModel::Path& path) {
1183  // save changed order to file
1184  Gtk::TreeModel::Children ch = pstore->children();
1185  std::vector<Glib::ustring> l;
1186  for (Gtk::TreeIter i = ch.begin(); i != ch.end(); ++i) {
1187  Glib::ustring s = i->get_value(pstore->col.name);
1188  if (!s.empty()) {
1189  l.push_back(s);
1190  }
1191  }
1192  machine.reorder_preset(*machine.get_bank_file(get_current_bank()), l);
1193  reload_target();
1194 }
1195 
1196 void PresetWindow::autosize() {
1197  if (bank_treeview->get_mapped()) {
1198  bank_treeview->columns_autosize();
1199  preset_treeview->columns_autosize();
1200  }
1201 }
1202 
1203 void PresetWindow::on_organize() {
1204  bool v = organize_presets->get_active();
1205  bank_column_edit->set_visible(v);
1206  bank_column_delete->set_visible(v);
1207  preset_column_edit->set_visible(v);
1208  preset_column_delete->set_visible(v);
1209  Glib::RefPtr<Gtk::TreeSelection> sel = preset_treeview->get_selection();
1210  if (v) {
1211  actions.presets->set_active(true);
1212  sel->set_mode(Gtk::SELECTION_NONE);
1213  banks_combobox->set_active(-1);
1214  banks_combobox->show();
1215  presets_target_scrolledbox->show();
1216  actions.save_changes->set_sensitive(false);
1217  } else {
1218  sel->set_mode(Gtk::SELECTION_BROWSE);
1219  banks_combobox->hide();
1220  presets_target_scrolledbox->hide();
1221  if (machine.setting_is_preset()) {
1222  if (machine.get_bank_file(machine.get_current_bank())->is_mutable()) {
1223  actions.save_changes->set_sensitive(true);
1224  }
1225  }
1226  }
1227  on_bank_changed(); // reload for DnD adjustment of readonly banks
1228  autosize();
1229 }
1230 
1231 void PresetWindow::on_presets_close() {
1232  actions.presets->set_active(false); // FIXME
1233 }
1234 
1235 /*
1236  ** preset window
1237  */
1238 
1239 bool PresetWindow::animate_preset_show() {
1240  vpaned_pos -= vpaned_step;
1241  if (vpaned_pos <= vpaned_target) {
1242  main_vpaned->set_position(vpaned_target);
1243  gx_gui::child_set_property(*main_vpaned, *preset_scrolledbox, "shrink", false);
1244  Gtk::TreeIter it = get_current_bank_iter();
1245  if (it) {
1246  bank_treeview->scroll_to_row(bank_treeview->get_model()->get_path(it));
1247  }
1248  return false;
1249  }
1250  main_vpaned->set_position(vpaned_pos);
1251  return true;
1252 }
1253 
1254 bool PresetWindow::animate_preset_hide() {
1255  vpaned_pos += vpaned_step;
1256  if (vpaned_pos >= vpaned_target) {
1257  preset_scrolledbox->hide();
1258  return false;
1259  }
1260  main_vpaned->set_position(vpaned_pos);
1261  return true;
1262 }
1263 
1264 void PresetWindow::on_preset_changed() {
1265  if (actions.organize->get_active()) {
1266  return;
1267  }
1268  Glib::ustring bank;
1269  Glib::ustring name;
1270  Gtk::TreeIter it = bank_treeview->get_selection()->get_selected();
1271  if (!it) {
1272  return;
1273  }
1274  bank = it->get_value(bank_col.name);
1275  it = preset_treeview->get_selection()->get_selected();
1276  if (!it) {
1277  return;
1278  }
1279  name = it->get_value(pstore->col.name);
1280  bool is_scratch = false;
1281  gx_system::PresetFileGui *cpf = 0;
1282  if (!machine.get_current_bank().empty()) {
1283  cpf = machine.get_bank_file(machine.get_current_bank());
1284  if (cpf && cpf->has_entry(machine.get_current_name())) {
1285  is_scratch = (cpf->get_type() == gx_system::PresetFile::PRESET_SCRATCH);
1286  }
1287  }
1288  if (is_scratch) {
1289  if (bank == machine.get_current_bank() && name == machine.get_current_name()) {
1290  machine.pf_save(*cpf, machine.get_current_name());
1291  // no reload necessary
1292  return;
1293  }
1294  }
1295  in_current_preset = true;
1296  cpf = machine.get_bank_file(bank);
1297  machine.load_preset(cpf, name);
1298  actions.save_changes->set_sensitive(cpf && cpf->is_mutable());
1299 }
1300 
1301 void PresetWindow::on_preset_save() {
1302  if (!machine.setting_is_preset()) {
1303  return;
1304  }
1305  gx_system::PresetFileGui *pf = machine.get_bank_file(machine.get_current_bank());
1306  if (!pf->is_mutable()) {
1307  return;
1308  }
1309  machine.pf_save(*pf, machine.get_current_name());
1310 }
1311 
1312 void PresetWindow::display_paned(bool show_preset, int paned_child_height) {
1313  if (preset_scrolledbox->get_parent() == main_vpaned) {
1314  vpaned_pos = main_vpaned->get_allocation().get_height();
1315  int w, h;
1316  main_vpaned->get_handle_window()->get_size(w, h);
1317  vpaned_target = vpaned_pos - paned_child_height - h;
1318  main_vpaned->set_position(vpaned_target);
1319  gx_gui::child_set_property(*main_vpaned, *preset_scrolledbox, "shrink", false);
1320  }
1321  preset_scrolledbox->show();
1322  if (!show_preset || !in_current_preset) {
1323  return;
1324  }
1325  on_map_conn.disconnect();
1326  // make the current entry in the preset list window
1327  // visible (in case it's outside the displayed range).
1328  // apparently only works after the window is mapped
1329  // and some size calculations are done, so put it into
1330  // an idle handler.
1331  Gtk::TreeIter it = get_current_bank_iter();
1332  if (it) {
1333  Glib::signal_idle().connect_once(
1334  sigc::bind(
1335  sigc::mem_fun1(bank_treeview, &MyTreeView::scroll_to_row),
1336  bank_treeview->get_model()->get_path(it)));
1337  }
1338  Gtk::TreeNodeChildren ch = pstore->children();
1339  for (it = ch.begin(); it != ch.end(); ++it) {
1340  if (it->get_value(pstore->col.name) == machine.get_current_name()) {
1341  Glib::signal_idle().connect_once(
1342  sigc::bind(
1343  sigc::mem_fun1(*preset_treeview, &MyTreeView::scroll_to_row),
1344  pstore->get_path(it)));
1345  break;
1346  }
1347  }
1348 }
1349 
1350 void PresetWindow::on_preset_select(bool v, bool animated, int paned_child_height) {
1351  static bool first_time = true;
1352  if (first_time) {
1353  //FIXME needed to fix first time display height, not clear why
1354  paned_child_height += 1;
1355  first_time = false;
1356  }
1357  on_map_conn.disconnect();
1358  bool is_mapped = main_vpaned->get_toplevel()->get_mapped();
1359  bool rack_visible = actions.show_rack->get_active();
1360  if (v) {
1361  if (machine.bank_check_reparse()) {
1362  set_presets();
1363  } else if (!get_current_bank_iter()) {
1364  Glib::ustring bank = machine.get_current_bank();
1365  if (!bank.empty()) {
1366  reload_banks(bank);
1367  }
1368  }
1369  autosize();
1370  Gtk::TreeIter it = get_current_bank_iter();
1371  if (it && animated && is_mapped) {
1372  bank_treeview->scroll_to_row(bank_treeview->get_model()->get_path(it));
1373  }
1374  if (!is_mapped) {
1375  // don't have widget height to calculate paned separator
1376  // position before window is mapped
1377  on_map_conn = main_vpaned->get_toplevel()->signal_map().connect(
1378  sigc::bind(
1379  sigc::mem_fun(*this, &PresetWindow::display_paned),
1380  true, paned_child_height));
1381  } else if (animated && rack_visible) {
1382  gx_gui::child_set_property(*main_vpaned, *preset_scrolledbox, "shrink", true);
1383  vpaned_pos = main_vpaned->get_allocation().get_height();
1384  int w, h;
1385  main_vpaned->get_handle_window()->get_size(w, h);
1386  vpaned_target = vpaned_pos - paned_child_height - h;
1387  main_vpaned->set_position(vpaned_pos);
1388  vpaned_step = paned_child_height / 5;
1389  preset_scrolledbox->show();
1390  animate_preset_show();
1391  Glib::signal_timeout().connect(sigc::mem_fun(*this, &PresetWindow::animate_preset_show), 20);
1392  } else {
1393  display_paned(false, paned_child_height);
1394  }
1395  } else {
1396  vpaned_target = main_vpaned->get_allocation().get_height();
1397  vpaned_pos = main_vpaned->get_position();
1398  if (animated && is_mapped && rack_visible) {
1399  vpaned_step = paned_child_height / 5;
1400  gx_gui::child_set_property(*main_vpaned, *preset_scrolledbox, "shrink", true);
1401  Glib::signal_timeout().connect(sigc::mem_fun(*this, &PresetWindow::animate_preset_hide), 20);
1402  } else {
1403  preset_scrolledbox->hide();
1404  }
1405  actions.organize->set_active(false);
1406  }
1407 }
gx_system::JsonParser::value_key
@ value_key
Definition: gx_json.h:130
gx_engine::GxMachineBase::load_preset
virtual void load_preset(gx_system::PresetFileGui *pf, const Glib::ustring &name)=0
gx_system::JsonParser::begin_object
@ begin_object
Definition: gx_json.h:124
BankModelColumns::name
Gtk::TreeModelColumn< Glib::ustring > name
Definition: gx_preset_window.h:52
gx_engine::GxMachineBase::get_options
virtual gx_system::CmdlineOptions & get_options() const =0
gx_print_info
void gx_print_info(const char *, const std::string &)
Definition: gx_logging.cpp:183
MyTreeView::create_from_builder
static MyTreeView * create_from_builder(BaseObjectType *cobject)
Definition: gx_preset_window.h:64
gx_system::PresetFileGui::get_header
const SettingsFileHeader & get_header()
Definition: gx_json.cpp:1117
gx_engine::GxMachineBase::bank_drag_begin
virtual void bank_drag_begin()=0
gx_engine::GxMachineBase
Definition: machine.h:53
gx_engine::GxMachineBase::get_current_name
virtual const Glib::ustring & get_current_name()=0
gx_system::PresetFileGui::is_mutable
bool is_mutable() const
Definition: gx_json.h:367
gx_engine::GxMachineBase::erase_preset
virtual void erase_preset(gx_system::PresetFileGui &pf, const Glib::ustring &name)=0
gx_engine::GxMachineBase::bank_begin
virtual bank_iterator bank_begin()=0
PresetStore
Definition: gx_preset_window.h:29
GxActions::group
Glib::RefPtr< Gtk::ActionGroup > group
Definition: gx_main_window.h:513
gx_system::PresetFileGui::has_entry
bool has_entry(const Glib::ustring &name)
Definition: gx_json.h:354
GxActions::save_changes
Glib::RefPtr< Gtk::Action > save_changes
Definition: gx_main_window.h:556
gx_engine::GxMachineBase::bank_insert_uri
virtual gx_system::PresetFileGui * bank_insert_uri(const Glib::ustring &uri, bool move)=0
gx_system::JsonException::what
virtual const char * what() const
Definition: gx_json.h:49
gx_engine::GxMachineBase::bank_set_flag
virtual void bank_set_flag(gx_system::PresetFileGui *pf, int flag, bool v)=0
gx_system::PresetFileGui::get_name
const Glib::ustring & get_name(int n)
Definition: gx_json.cpp:1129
gx_system::PresetFile::iterator
std::vector< Position >::iterator iterator
Definition: gx_json.h:321
GxActions::accels
Glib::RefPtr< Gtk::AccelGroup > accels
Definition: gx_main_window.h:514
gx_system::PresetFile::PRESET_FACTORY
@ PRESET_FACTORY
Definition: gx_json.h:301
GxActions::new_bank
Glib::RefPtr< Gtk::Action > new_bank
Definition: gx_main_window.h:555
gx_engine::GxMachineBase::get_current_bank_file
virtual gx_system::PresetFileGui * get_current_bank_file()=0
gx_system::JsonException
Definition: gx_json.h:40
gx_system::PresetFileGui::get_flags
int get_flags() const
Definition: gx_json.h:358
gx_engine::GxMachineBase::pf_append
virtual void pf_append(gx_system::PresetFileGui &pf, const Glib::ustring &src, gx_system::PresetFileGui &pftgt, const Glib::ustring &name)=0
gx_engine::bank_iterator
Definition: machine.h:41
gx_system::to_string
std::string to_string(const T &t)
Definition: gx_system.h:529
GxActions::online_preset_bank
Glib::RefPtr< Gtk::Action > online_preset_bank
Definition: gx_main_window.h:558
PresetStore::PresetStore
PresetStore()
Definition: gx_preset_window.cpp:30
gx_engine::GxMachineBase::reorder_preset
virtual void reorder_preset(gx_system::PresetFileGui &pf, const std::vector< Glib::ustring > &neworder)=0
GxActions
Definition: gx_main_window.h:511
gx_system::CmdlineOptions::get_style_filepath
std::string get_style_filepath(const std::string &basename) const
Definition: gx_system.h:463
gx_engine::GxMachineBase::bank_reorder
virtual void bank_reorder(const std::vector< Glib::ustring > &neworder)=0
gx_system::PresetFileGui::get_type
int get_type() const
Definition: gx_json.h:361
gx_system::PresetFile::PRESET_SEP
@ PRESET_SEP
Definition: gx_json.h:301
gx_system::CmdlineOptions::get_rpcaddress
const Glib::ustring & get_rpcaddress()
Definition: gx_system.h:495
gx_system::CmdlineOptions::get_online_config_filename
std::string get_online_config_filename() const
Definition: gx_system.h:482
gx_engine::GxMachineBase::get_current_bank
virtual const Glib::ustring & get_current_bank()=0
gx_system::PresetFile::PRESET_FILE
@ PRESET_FILE
Definition: gx_json.h:301
GxActions::organize
Glib::RefPtr< Gtk::ToggleAction > organize
Definition: gx_main_window.h:557
gx_system::JsonParser
Definition: gx_json.h:112
gx_system::PresetFileGui
Definition: gx_json.h:371
gx_engine::GxMachineBase::bank_get_filename
virtual std::string bank_get_filename(const Glib::ustring &bank)=0
PresetWindow::PresetWindow
PresetWindow(Glib::RefPtr< gx_gui::GxBuilder > bld, gx_engine::GxMachineBase &machine, const gx_system::CmdlineOptions &options, GxActions &actions, GtkSizeGroup *lc)
Definition: gx_preset_window.cpp:45
gx_print_error
void gx_print_error(const char *, const std::string &)
Definition: gx_logging.cpp:166
gx_system::JsonParser::begin_array
@ begin_array
Definition: gx_json.h:126
gx_engine::GxMachineBase::rename_preset
virtual bool rename_preset(gx_system::PresetFileGui &pf, const Glib::ustring &oldname, const Glib::ustring &newname)=0
BankModelColumns::type_pb
Gtk::TreeModelColumn< Glib::RefPtr< Gdk::Pixbuf > > type_pb
Definition: gx_preset_window.h:53
gx_system::PresetFileGui::end
iterator end()
Definition: gx_json.h:366
gx_engine::GxMachineBase::get_bank_file
virtual gx_system::PresetFileGui * get_bank_file(const Glib::ustring &bank) const =0
gx_system::PRESET_FLAG_INVALID
@ PRESET_FLAG_INVALID
Definition: gx_json.h:294
PresetStore::row_draggable_vfunc
virtual bool row_draggable_vfunc(const TreeModel::Path &path) const
Definition: gx_preset_window.cpp:34
gx_engine::GxMachineBase::bank_get_file
virtual gx_system::PresetFileGui * bank_get_file(const Glib::ustring &bank) const =0
gx_system::PRESET_FLAG_READONLY
@ PRESET_FLAG_READONLY
Definition: gx_json.h:293
gx_engine::GxMachineBase::convert_preset
virtual bool convert_preset(gx_system::PresetFileGui &pf)=0
gx_system::PresetFileGui::begin
iterator begin()
Definition: gx_json.cpp:1345
BankModelColumns::del_pb
Gtk::TreeModelColumn< Glib::RefPtr< Gdk::Pixbuf > > del_pb
Definition: gx_preset_window.h:55
gx_system::JsonParser::end_object
@ end_object
Definition: gx_json.h:125
gx_engine::GxMachineBase::bank_end
virtual bank_iterator bank_end()=0
gx_engine::GxMachineBase::pf_save
virtual void pf_save(gx_system::PresetFileGui &pf, const Glib::ustring &name)=0
GxActions::show_rack
Glib::RefPtr< Gtk::ToggleAction > show_rack
Definition: gx_main_window.h:539
TargetModelColumns::name
Gtk::TreeModelColumn< Glib::ustring > name
Definition: gx_preset_window.h:46
BankModelColumns::edit_pb
Gtk::TreeModelColumn< Glib::RefPtr< Gdk::Pixbuf > > edit_pb
Definition: gx_preset_window.h:54
BankModelColumns::tp
Gtk::TreeModelColumn< int > tp
Definition: gx_preset_window.h:56
PresetWindow::~PresetWindow
~PresetWindow()
Definition: gx_preset_window.cpp:177
gx_system::CmdlineOptions
Definition: gx_system.h:381
gx_engine::GxMachineBase::setting_is_preset
virtual bool setting_is_preset()=0
gx_engine::GxMachineBase::pf_insert_before
virtual void pf_insert_before(gx_system::PresetFileGui &pf, const Glib::ustring &src, gx_system::PresetFileGui &pftgt, const Glib::ustring &pos, const Glib::ustring &name)=0
PresetWindow::on_preset_select
void on_preset_select(bool v, bool animated, int preset_window_height)
Definition: gx_preset_window.cpp:1350
PresetStore::PresetModelColumns::name
Gtk::TreeModelColumn< Glib::ustring > name
Definition: gx_preset_window.h:37
gx_engine::GxMachineBase::get_jack
virtual gx_jack::GxJack * get_jack()=0
gx_engine::GxMachineBase::bank_size
virtual int bank_size()=0
gx_system::PresetFile::PRESET_SCRATCH
@ PRESET_SCRATCH
Definition: gx_json.h:301
GxActions::presets
Glib::RefPtr< Gtk::ToggleAction > presets
Definition: gx_main_window.h:538
gx_engine::GxMachineBase::bank_insert_new
virtual gx_system::PresetFileGui * bank_insert_new(const Glib::ustring &newname)=0
gx_system::SettingsFileHeader::current_version_string
Glib::ustring current_version_string() const
Definition: gx_json.h:254
gx_system::strip
void strip(Glib::ustring &s)
Definition: gx_system.cpp:984
gx_gui::child_set_property
void child_set_property(Gtk::Container &container, Gtk::Widget &child, const char *property_name, bool value)
Definition: gx_gui_helpers.cpp:39
gx_engine::GxMachineBase::signal_selection_changed
virtual sigc::signal< void > & signal_selection_changed()=0
gx_engine::GxMachineBase::bank_remove
virtual bool bank_remove(const Glib::ustring &bank)=0
gx_system::SettingsFileHeader::version_string
Glib::ustring version_string() const
Definition: gx_json.h:253
gx_engine::GxMachineBase::bank_check_reparse
virtual bool bank_check_reparse()=0
guitarix.h
gx_engine::GxMachineBase::rename_bank
virtual bool rename_bank(const Glib::ustring &oldname, Glib::ustring &newname)=0
PresetStore::col
PresetStore::PresetModelColumns col
gx_engine::GxMachineBase::pf_insert_after
virtual void pf_insert_after(gx_system::PresetFileGui &pf, const Glib::ustring &src, gx_system::PresetFileGui &pftgt, const Glib::ustring &pos, const Glib::ustring &name)=0
gx_system::PRESET_FLAG_VERSIONDIFF
@ PRESET_FLAG_VERSIONDIFF
Definition: gx_json.h:292