31 set_column_types(
col);
35 Gtk::TreeModel::const_iterator i = const_cast<PresetStore*>(
this)->get_iter(path);
36 Glib::ustring s(i->get_value(
col.
name));
62 preset_row_del_conn(),
67 in_current_preset(false),
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()));
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);
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));
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();
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(
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));
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(
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));
165 sigc::mem_fun(*
this, &PresetWindow::on_selection_changed));
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();
178 curl_easy_cleanup(curl);
179 curl_global_cleanup();
182 void PresetWindow::on_selection_changed() {
183 Gtk::TreeIter it = bank_treeview->get_selection()->get_selected();
185 it = preset_treeview->get_selection()->get_selected();
187 Glib::RefPtr<Gdk::Window> w = bank_treeview->get_window();
189 gdk_window_invalidate_rect(w->gobj(), 0,
true);
190 gdk_window_invalidate_rect(preset_treeview->get_window()->gobj(), 0,
true);
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);
213 bld->find_widget(
"bank_cellrenderer", bank_cellrenderer);
215 bld->find_widget(
"preset_cellrenderer", preset_cellrenderer);
216 bld->find_widget(
"banks_combobox", banks_combobox);
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);
228 static bool preset_button_press_idle(Gtk::Widget& w) {
233 bool PresetWindow::on_bank_query_tooltip(
int x,
int y,
bool kb_tooltip, Glib::RefPtr<Gtk::Tooltip> tooltip) {
235 if (!bank_treeview->get_tooltip_context_iter(x, y, kb_tooltip, it)) {
238 int tp = it->get_value(bank_col.
tp);
242 Gtk::TreeModel::Path pt;
243 Gtk::TreeViewColumn *col;
245 if (!bank_treeview->get_path_at_pos(x, y, pt, col, dx, dy)) {
248 Glib::ustring nm = it->get_value(bank_col.
name);
253 if (col == bank_treeview->get_column(0) || col == bank_treeview->get_column(1)) {
256 tooltip->set_text(_(
"damaged bank file; click to delete"));
259 Glib::ustring::compose(_(
"wrong format version (is %1, need %2)\nclick to convert"),
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"));
270 tooltip->set_text(_(
"predefined factory preset bank"));
272 tooltip->set_text(_(
"scratch preset bank: changes will be persistent (without explicit saving)"));
276 }
else if (col == bank_treeview->get_column(2)) {
280 tooltip->set_text(_(
"click to edit the bank name"));
281 }
else if (col == bank_treeview->get_column(3)) {
285 tooltip->set_text(_(
"click to delete the bank"));
289 bank_treeview->set_tooltip_cell(tooltip, &pt, col, 0);
293 void PresetWindow::on_preset_row_activated(
const Gtk::TreePath& path, Gtk::TreeViewColumn* column) {
294 bool in_organize = actions.
organize->get_active();
297 preset_treeview->get_selection()->select(path);
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)));
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);
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) {
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(
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());
333 std::vector<std::string> uris;
334 uris.push_back(f->get_uri());
335 selection.set_uris(uris);
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) {
344 bool is_move = context->get_selected_action() == Gdk::ACTION_MOVE;
346 bool is_move = gdk_drag_context_get_selected_action(context->gobj()) == GDK_ACTION_MOVE;
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) {
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);
361 context->drag_finish(success,
false, timestamp);
364 Glib::ustring PresetWindow::get_combo_selection() {
365 Gtk::TreeIter idx = banks_combobox->get_active();
369 return idx->get_value(target_col.
name);
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();
379 presets_target_treeview->signal_drag_data_received().emission_stop();
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;
391 Glib::ustring src_bank = get_current_bank();
393 if (src_bank == bank) {
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);
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);
408 ls->insert_after(it)->set_value(target_col.
name, dstnm);
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();
421 if (src_bank == bank) {
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);
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);
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());
450 int tp = i->get_type();
454 if (i->get_flags()) {
457 Glib::ustring s = i->get_name();
458 ls->append()->set_value(bank_col.
name, s);
464 banks_combobox->set_active(nn);
467 void PresetWindow::on_preset_combo_changed() {
468 Glib::RefPtr<Gtk::ListStore> ls = Glib::RefPtr<Gtk::ListStore>::cast_dynamic(presets_target_treeview->get_model());
470 Glib::ustring nm = get_combo_selection();
476 ls->append()->set_value(bank_col.
name, i->name);
480 void PresetWindow::reload_target() {
481 on_preset_combo_changed();
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);
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);
499 dynamic_cast<Gtk::Entry*>(const_cast<Gtk::CellEditable*>(edit))->set_text(
"");
501 dynamic_cast<Gtk::Entry*>(const_cast<Gtk::CellEditable*>(edit))->set_text(s);
503 dynamic_cast<Gtk::Window*>(main_vpaned->get_toplevel())->remove_accel_group(actions.
accels);
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);
512 void PresetWindow::reset_edit(Gtk::TreeViewColumn& col) {
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();
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);
523 dynamic_cast<Gtk::Window*>(main_vpaned->get_toplevel())->add_accel_group(actions.
accels);
526 void PresetWindow::on_edit_canceled(Gtk::TreeViewColumn *col) {
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)));
541 void PresetWindow::highlight_current_bank(Gtk::CellRenderer *cell,
const Gtk::TreeModel::iterator& iter) {
542 Glib::ustring t = iter->get_value(bank_col.
name);
546 Gtk::CellRendererText *tc = dynamic_cast<Gtk::CellRendererText*>(cell);
548 tc->property_foreground().set_value(
"#f00");
550 tc->property_foreground_set().set_value(
false);
552 int n = machine.
bank_size() - *bank_treeview->get_model()->get_path(iter).begin();
559 t = Glib::ustring::compose(
"%1: %2",
char(
'A'+n), t);
561 cell->set_property(
"text", t);
564 Glib::ustring PresetWindow::get_current_bank() {
565 Gtk::TreeIter it = get_current_bank_iter();
569 return it->get_value(bank_col.
name);
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;
578 bool PresetWindow::on_bank_button_release(GdkEventButton *ev) {
580 Gtk::TreeModel::Path pt;
581 Gtk::TreeViewColumn *col;
583 if (!bank_treeview->get_path_at_pos(ev->x, ev->y, pt, col, dx, dy)) {
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) {
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)) {
605 if (run_message_dialog(*bank_treeview,
"convert bank " + nm +
" to new version?")) {
615 if (run_message_dialog(*bank_treeview,
"convert readonly bank " + nm +
" to new version?")) {
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!")) {
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();
644 bank_row_del_conn.unblock();
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;
660 if (newname.empty() || newname == oldname) {
661 Gtk::TreeViewColumn *p = w->get_column(1);
665 Glib::RefPtr<Gtk::ListStore> ls = Glib::RefPtr<Gtk::ListStore>::cast_dynamic(banks_combobox->get_model());
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);
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);
682 w->get_model()->get_iter(path)->set_value(bank_col.
name, newname);
684 Gtk::TreeViewColumn *p = w->get_column(1);
688 bool PresetWindow::is_row_separator(
const Glib::RefPtr<Gtk::TreeModel>& model,
const Gtk::TreeModel::iterator& iter) {
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();
697 start_edit(m->get_path(edit_iter), *bank_treeview->get_column(1), *bank_cellrenderer);
702 Glib::ustring PresetWindow::resolve_hostname() {
703 static Glib::ustring hostname =
"localhost";
705 hostname = Gio::Resolver::get_default()->lookup_by_address
711 bool PresetWindow::download_file(Glib::ustring from_uri, Glib::ustring to_path) {
715 out = fopen(to_path.c_str(),
"wb");
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) {
722 res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
723 if (strstr(ct,
"application/json")!= NULL ) {
725 }
else if (strstr(ct,
"application/octet-stream")!= NULL) {
728 res = CURLE_CONV_FAILED;
731 curl_easy_reset(curl);
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)));
741 void PresetWindow::downloadPreset(Gtk::Menu *presetMenu,std::string uri) {
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;
748 if (download_file(uri, ff)) {
749 Glib::RefPtr<Gtk::ListStore> ls = Glib::RefPtr<Gtk::ListStore>::cast_dynamic(bank_treeview->get_model());
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);
759 gx_print_error(
"downloadPreset", _(
"can't download preset from https://musical-artifacts.com/"));
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());
772 while ( in->read_line(line) )
774 std::istringstream is(line);
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_));
799 cerr <<
"JsonException: " << e.
what() <<
": '" << jp.current_value() <<
"'" << endl;
806 void PresetWindow::popup_pos(
int& x,
int& y,
bool& push_in ){
807 online_preset->get_window()->get_origin( x, y );
813 void PresetWindow::create_preset_menu(
bool is_new) {
815 static bool read_new =
true;
816 if (read_new || is_new) {
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);
833 presetMenu->show_all();
834 presetMenu->popup(Gtk::Menu::SlotPositionCalc(sigc::mem_fun(
835 *
this, &PresetWindow::popup_pos ) ),0,gtk_get_current_event_time());
838 void PresetWindow::replace_inline(std::string& subject,
const std::string& search,
839 const std::string& replace) {
841 while ((pos = subject.find(search, pos)) != std::string::npos) {
842 subject.replace(pos, search.length(), replace);
843 pos += replace.length();
847 void PresetWindow::show_online_preset() {
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;
864 if (load || ! dest->query_exists()) {
866 window->set_cursor();
870 window->set_cursor();
873 create_preset_menu(load_new);
876 void PresetWindow::on_online_preset() {
877 Glib::signal_idle().connect_once(sigc::mem_fun(*
this, &PresetWindow::show_online_preset));
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) {
885 if (context->get_suggested_action() == Gdk::ACTION_MOVE) {
886 a = context->get_suggested_action();
888 a = Gdk::ACTION_COPY;
890 context->drag_status(a, timestamp);
891 }
else if (source_widget != bank_treeview) {
893 context->drag_status((Gdk::DragAction)0, timestamp);
896 Gtk::TreeIter it = bank_treeview->get_selection()->get_selected();
900 int tp = it->get_value(bank_col.
tp);
902 context->drag_status((Gdk::DragAction)0, timestamp);
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);
914 bank_treeview->on_drag_motion(context, x, y, timestamp);
915 context->drag_status(Gdk::ACTION_MOVE, timestamp);
920 void PresetWindow::on_bank_changed() {
921 preset_row_del_conn.block();
926 preset_row_del_conn.unblock();
927 Gtk::TreeIter it = bank_treeview->get_selection()->get_selected();
929 in_current_preset =
false;
932 Glib::ustring nm = it->get_value(bank_col.
name);
933 preset_title->set_text(nm);
939 preset_treeview->unset_rows_drag_source();
941 preset_treeview->unset_rows_drag_source();
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);
950 i = pstore->append();
951 i->set_value(pstore->col.name, s->name);
953 i->set_value(pstore->col.edit_pb, pb_edit);
954 i->set_value(pstore->col.del_pb, pb_del);
957 if (preset_treeview->get_mapped()) {
958 preset_treeview->scroll_to_row(pstore->get_path(i));
963 i = pstore->append();
970 i->set_value(bank_col.
type_pb, pb_del);
972 i->set_value(bank_col.
type_pb, pb_versiondiff);
974 i->set_value(bank_col.
type_pb, pb_readonly);
977 i->set_value(bank_col.
tp, tp);
979 i->set_value(bank_col.
type_pb, pb_scratch);
981 i->set_value(bank_col.
type_pb, pb_factory);
983 i->set_value(bank_col.
edit_pb, pb_edit);
984 i->set_value(bank_col.
del_pb, pb_del);
988 void PresetWindow::reload_banks(
const Glib::ustring& sel_bank) {
989 preset_row_del_conn.block();
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();
995 bank_row_del_conn.unblock();
997 int in_factory =
false;
1005 set_row_for_presetfile(i, *v);
1006 if (v->get_name() == sel_bank) {
1007 bank_treeview->get_selection()->select(i);
1013 void PresetWindow::set_presets() {
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);
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()) {
1043 g_object_get(cell->gobj(),
"editing", &editing, NULL);
1044 if (t.empty() && !editing) {
1047 }
else if (in_current_preset) {
1048 int n = *pstore->get_path(iter).begin();
1052 t = Glib::ustring::compose(
"%1: %2", n, t);
1055 cell->set_property(
"text", t);
1056 Gtk::CellRendererText *tc = dynamic_cast<Gtk::CellRendererText*>(cell);
1058 tc->property_foreground().set_value(
"#f00");
1060 tc->property_foreground_set().set_value(
false);
1064 bool PresetWindow::on_preset_button_release(GdkEventButton *ev) {
1065 Gtk::TreeModel::Path pt;
1066 Gtk::TreeViewColumn *col;
1068 if (!preset_treeview->get_path_at_pos(ev->x, ev->y, pt, col, dx, dy)) {
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) {
1077 Gtk::TreeIter bank_iter = get_current_bank_iter();
1078 int tp = bank_iter->get_value(bank_col.
tp);
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();
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;
1106 if (newname.empty() || newname == oldname) {
1107 reset_edit(*preset_treeview->get_column(0));
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));
1118 Glib::ustring t = newname;
1121 newname = Glib::ustring::compose(
"%1-%2", t, n);
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()) {
1143 reset_edit(*preset_treeview->get_column(0));
1146 void PresetWindow::on_cursor_changed() {
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()) {
1157 start_edit(path, *preset_treeview->get_column(0), *preset_cellrenderer);
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();
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);
1178 context->drag_status((Gdk::DragAction)0, timestamp);
1182 void PresetWindow::on_preset_reordered(
const Gtk::TreeModel::Path& path) {
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);
1196 void PresetWindow::autosize() {
1197 if (bank_treeview->get_mapped()) {
1198 bank_treeview->columns_autosize();
1199 preset_treeview->columns_autosize();
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();
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();
1218 sel->set_mode(Gtk::SELECTION_BROWSE);
1219 banks_combobox->hide();
1220 presets_target_scrolledbox->hide();
1231 void PresetWindow::on_presets_close() {
1232 actions.
presets->set_active(
false);
1239 bool PresetWindow::animate_preset_show() {
1240 vpaned_pos -= vpaned_step;
1241 if (vpaned_pos <= vpaned_target) {
1242 main_vpaned->set_position(vpaned_target);
1244 Gtk::TreeIter it = get_current_bank_iter();
1246 bank_treeview->scroll_to_row(bank_treeview->get_model()->get_path(it));
1250 main_vpaned->set_position(vpaned_pos);
1254 bool PresetWindow::animate_preset_hide() {
1255 vpaned_pos += vpaned_step;
1256 if (vpaned_pos >= vpaned_target) {
1257 preset_scrolledbox->hide();
1260 main_vpaned->set_position(vpaned_pos);
1264 void PresetWindow::on_preset_changed() {
1265 if (actions.
organize->get_active()) {
1270 Gtk::TreeIter it = bank_treeview->get_selection()->get_selected();
1274 bank = it->get_value(bank_col.
name);
1275 it = preset_treeview->get_selection()->get_selected();
1279 name = it->get_value(pstore->col.name);
1280 bool is_scratch =
false;
1295 in_current_preset =
true;
1301 void PresetWindow::on_preset_save() {
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();
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);
1321 preset_scrolledbox->show();
1322 if (!show_preset || !in_current_preset) {
1325 on_map_conn.disconnect();
1331 Gtk::TreeIter it = get_current_bank_iter();
1333 Glib::signal_idle().connect_once(
1335 sigc::mem_fun1(bank_treeview, &MyTreeView::scroll_to_row),
1336 bank_treeview->get_model()->get_path(it)));
1338 Gtk::TreeNodeChildren ch = pstore->children();
1339 for (it = ch.begin(); it != ch.end(); ++it) {
1341 Glib::signal_idle().connect_once(
1343 sigc::mem_fun1(*preset_treeview, &MyTreeView::scroll_to_row),
1344 pstore->get_path(it)));
1351 static bool first_time =
true;
1354 paned_child_height += 1;
1357 on_map_conn.disconnect();
1358 bool is_mapped = main_vpaned->get_toplevel()->get_mapped();
1359 bool rack_visible = actions.
show_rack->get_active();
1363 }
else if (!get_current_bank_iter()) {
1365 if (!bank.empty()) {
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));
1377 on_map_conn = main_vpaned->get_toplevel()->signal_map().connect(
1379 sigc::mem_fun(*
this, &PresetWindow::display_paned),
1380 true, paned_child_height));
1381 }
else if (animated && rack_visible) {
1383 vpaned_pos = main_vpaned->get_allocation().get_height();
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);
1393 display_paned(
false, paned_child_height);
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;
1401 Glib::signal_timeout().connect(sigc::mem_fun(*
this, &PresetWindow::animate_preset_hide), 20);
1403 preset_scrolledbox->hide();
1405 actions.
organize->set_active(
false);