--- gigedit/trunk/src/gigedit/mainwindow.cpp 2019/02/16 19:56:56 3472
+++ gigedit/trunk/src/gigedit/mainwindow.cpp 2020/08/14 11:54:49 3811
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2019 Andreas Persson
+ * Copyright (C) 2006-2020 Andreas Persson
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -96,9 +96,9 @@
if (!Settings::singleton()->autoRestoreWindowDimension) {
#if GTKMM_MAJOR_VERSION >= 3
- set_default_size(895, 600);
+ set_default_size(1010, -1);
#else
- set_default_size(800, 600);
+ set_default_size(915, -1);
#endif
set_position(Gtk::WIN_POS_CENTER);
}
@@ -106,21 +106,21 @@
add(m_VBox);
// Handle selection
- m_TreeView.get_selection()->signal_changed().connect(
+ m_TreeViewInstruments.get_selection()->signal_changed().connect(
sigc::mem_fun(*this, &MainWindow::on_sel_change));
- // m_TreeView.set_reorderable();
+ // m_TreeViewInstruments.set_reorderable();
#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && (GTKMM_MINOR_VERSION > 91 || (GTKMM_MINOR_VERSION == 91 && GTKMM_MICRO_VERSION >= 2))) // GTKMM >= 3.91.2
- m_TreeView.signal_button_press_event().connect(
+ m_TreeViewInstruments.signal_button_press_event().connect(
sigc::mem_fun(*this, &MainWindow::on_button_release));
#else
- m_TreeView.signal_button_press_event().connect_notify(
+ m_TreeViewInstruments.signal_button_press_event().connect_notify(
sigc::mem_fun(*this, &MainWindow::on_button_release));
#endif
// Add the TreeView tab, inside a ScrolledWindow, with the button underneath:
- m_ScrolledWindow.add(m_TreeView);
+ m_ScrolledWindow.add(m_TreeViewInstruments);
// m_ScrolledWindow.set_size_request(200, 600);
m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
@@ -451,6 +451,12 @@
m_actionGroup->add_action_bool("Statusbar", sigc::mem_fun(*this, &MainWindow::on_action_view_status_bar), true);
m_actionToggleRestoreWinDim =
m_actionGroup->add_action_bool("AutoRestoreWinDim", sigc::mem_fun(*this, &MainWindow::on_auto_restore_win_dim), Settings::singleton()->autoRestoreWindowDimension);
+ m_actionInstrDoubleClickOpensProps =
+ m_actionGroup->add_action_bool(
+ "OpenInstrPropsByDoubleClick",
+ sigc::mem_fun(*this, &MainWindow::on_instr_double_click_opens_props),
+ Settings::singleton()->instrumentDoubleClickOpensProps
+ );
m_actionToggleShowTooltips = m_actionGroup->add_action_bool(
"ShowTooltips", sigc::mem_fun(*this, &MainWindow::on_action_show_tooltips),
Settings::singleton()->showTooltips
@@ -478,6 +484,13 @@
*this, &MainWindow::on_auto_restore_win_dim));
toggle_action =
+ Gtk::ToggleAction::create("OpenInstrPropsByDoubleClick", _("Instrument Properties by Double Click"));
+ toggle_action->set_active(Settings::singleton()->instrumentDoubleClickOpensProps);
+ actionGroup->add(toggle_action,
+ sigc::mem_fun(
+ *this, &MainWindow::on_instr_double_click_opens_props));
+
+ toggle_action =
Gtk::ToggleAction::create("ShowTooltips", _("Tooltips for Beginners"));
toggle_action->set_active(Settings::singleton()->showTooltips);
actionGroup->add(
@@ -509,6 +522,9 @@
"DupInstrument", sigc::mem_fun(*this, &MainWindow::on_action_duplicate_instrument)
);
m_actionGroup->add_action(
+ "MoveInstrument", sigc::mem_fun(*this, &MainWindow::on_action_move_instr)
+ );
+ m_actionGroup->add_action(
"CombInstruments", sigc::mem_fun(*this, &MainWindow::on_action_combine_instruments)
);
m_actionGroup->add_action(
@@ -530,6 +546,11 @@
sigc::mem_fun(*this, &MainWindow::on_action_duplicate_instrument)
);
actionGroup->add(
+ Gtk::Action::create("MoveInstrument", _("Move _Instrument To ...")),
+ Gtk::AccelKey(GDK_KEY_i, primaryModifierKey),
+ sigc::mem_fun(*this, &MainWindow::on_action_move_instr)
+ );
+ actionGroup->add(
Gtk::Action::create("CombInstruments", _("_Combine Instruments ...")),
Gtk::AccelKey(GDK_KEY_j, primaryModifierKey),
sigc::mem_fun(*this, &MainWindow::on_action_combine_instruments)
@@ -885,6 +906,10 @@
" Duplicate Instrument"
" AppMenu.DupInstrument"
" "
+ " - "
+ " Move Instrument To ..."
+ " AppMenu.MoveInstrument"
+ "
"
" - "
" Combine Instrument"
" AppMenu.CombInstruments"
@@ -935,6 +960,10 @@
" Auto restore Window Dimensions"
" AppMenu.AutoRestoreWinDim"
"
"
+ " - "
+ " Instrument Properties by Double Click"
+ " AppMenu.OpenInstrPropsByDoubleClick"
+ "
"
" "
" "
" - "
@@ -1010,6 +1039,10 @@
" Duplicate Instrument"
" AppMenu.DupInstrument"
"
"
+ " - "
+ " Move Instrument To ..."
+ " AppMenu.MoveInstrument"
+ "
"
" - "
" Combine Instruments"
" AppMenu.CombInstruments"
@@ -1148,6 +1181,7 @@
" "
" "
" "
+ " "
" "
" "
" "
@@ -1163,6 +1197,7 @@
" "
" "
" "
+ " "
" "
" "
" "
@@ -1186,6 +1221,7 @@
" "
" "
" "
+ " "
" "
" "
" "
@@ -1286,6 +1322,11 @@
}
{
Gtk::MenuItem* item = dynamic_cast(
+ uiManager->get_widget("/MenuBar/MenuView/OpenInstrPropsByDoubleClick"));
+ item->set_tooltip_text(_("If checked, double clicking an instrument opens its properties dialog."));
+ }
+ {
+ Gtk::MenuItem* item = dynamic_cast(
uiManager->get_widget("/MenuBar/MenuTools/CombineInstruments"));
item->set_tooltip_text(_("Create combi sounds out of individual sounds of this .gig file."));
}
@@ -1342,42 +1383,42 @@
// Create the Tree model:
- m_refTreeModel = Gtk::ListStore::create(m_Columns);
- m_refTreeModelFilter = Gtk::TreeModelFilter::create(m_refTreeModel);
- m_refTreeModelFilter->set_visible_func(
+ m_refInstrumentsTreeModel = Gtk::ListStore::create(m_InstrumentsModel);
+ m_refInstrumentsModelFilter = Gtk::TreeModelFilter::create(m_refInstrumentsTreeModel);
+ m_refInstrumentsModelFilter->set_visible_func(
sigc::mem_fun(*this, &MainWindow::instrument_row_visible)
);
- m_TreeView.set_model(m_refTreeModelFilter);
+ m_TreeViewInstruments.set_model(m_refInstrumentsModelFilter);
- m_TreeView.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);
- m_TreeView.set_has_tooltip(true);
- m_TreeView.signal_query_tooltip().connect(
+ m_TreeViewInstruments.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);
+ m_TreeViewInstruments.set_has_tooltip(true);
+ m_TreeViewInstruments.signal_query_tooltip().connect(
sigc::mem_fun(*this, &MainWindow::onQueryTreeViewTooltip)
);
- instrument_name_connection = m_refTreeModel->signal_row_changed().connect(
+ instrument_name_connection = m_refInstrumentsTreeModel->signal_row_changed().connect(
sigc::mem_fun(*this, &MainWindow::instrument_name_changed)
);
// Add the TreeView's view columns:
- m_TreeView.append_column(_("Nr"), m_Columns.m_col_nr);
- m_TreeView.append_column_editable(_("Instrument"), m_Columns.m_col_name);
- m_TreeView.append_column(_("Scripts"), m_Columns.m_col_scripts);
- m_TreeView.set_headers_visible(true);
+ m_TreeViewInstruments.append_column(_("Nr"), m_InstrumentsModel.m_col_nr);
+ m_TreeViewInstruments.append_column_editable(_("Instrument"), m_InstrumentsModel.m_col_name);
+ m_TreeViewInstruments.append_column(_("Scripts"), m_InstrumentsModel.m_col_scripts);
+ m_TreeViewInstruments.set_headers_visible(true);
// establish drag&drop within the instrument tree view, allowing to reorder
// the sequence of instruments within the gig file
{
std::vector drag_target_instrument;
drag_target_instrument.push_back(Gtk::TargetEntry("gig::Instrument"));
- m_TreeView.drag_source_set(drag_target_instrument);
- m_TreeView.drag_dest_set(drag_target_instrument);
- m_TreeView.signal_drag_begin().connect(
+ m_TreeViewInstruments.drag_source_set(drag_target_instrument);
+ m_TreeViewInstruments.drag_dest_set(drag_target_instrument);
+ m_TreeViewInstruments.signal_drag_begin().connect(
sigc::mem_fun(*this, &MainWindow::on_instruments_treeview_drag_begin)
);
- m_TreeView.signal_drag_data_get().connect(
+ m_TreeViewInstruments.signal_drag_data_get().connect(
sigc::mem_fun(*this, &MainWindow::on_instruments_treeview_drag_data_get)
);
- m_TreeView.signal_drag_data_received().connect(
+ m_TreeViewInstruments.signal_drag_data_received().connect(
sigc::mem_fun(*this, &MainWindow::on_instruments_treeview_drop_drag_data_received)
);
}
@@ -1484,7 +1525,9 @@
sigc::mem_fun(*this, &MainWindow::file_changed));
instrumentProps.signal_changed().connect(
sigc::mem_fun(*this, &MainWindow::file_changed));
- propDialog.signal_changed().connect(
+ sampleProps.signal_changed().connect(
+ sigc::mem_fun(*this, &MainWindow::file_changed));
+ fileProps.signal_changed().connect(
sigc::mem_fun(*this, &MainWindow::file_changed));
midiRules.signal_changed().connect(
sigc::mem_fun(*this, &MainWindow::file_changed));
@@ -1506,6 +1549,35 @@
sigc::mem_fun(*this, &MainWindow::select_sample)
);
+ dimreg_edit.editScriptSlotsButton.signal_clicked().connect(
+ sigc::mem_fun(*this, &MainWindow::show_script_slots)
+ );
+ // simply sending the same signal (pair) to the sampler on 'patch' variable
+ // changes as the already existing signal (pair) when the user edits the
+ // script's source code, because the sampler would reload the source code
+ // and the 'patch' variables from the instrument on this signal anyway
+ dimreg_edit.scriptVars.signal_vars_to_be_changed.connect(
+ [this](gig::Instrument* instr) {
+ for (int i = 0; i < instr->ScriptSlotCount(); ++i) {
+ gig::Script* script = instr->GetScriptOfSlot(i);
+ signal_script_to_be_changed.emit(script);
+ }
+ }
+ );
+ dimreg_edit.scriptVars.signal_vars_changed.connect(
+ [this](gig::Instrument* instr) {
+ for (int i = 0; i < instr->ScriptSlotCount(); ++i) {
+ gig::Script* script = instr->GetScriptOfSlot(i);
+ signal_script_changed.emit(script);
+ }
+ }
+ );
+ dimreg_edit.scriptVars.signal_edit_script.connect(
+ [this](gig::Script* script) {
+ editScript(script);
+ }
+ );
+
m_RegionChooser.signal_instrument_struct_to_be_changed().connect(
sigc::hide(
sigc::bind(
@@ -1548,7 +1620,7 @@
sigc::mem_fun(*this, &MainWindow::update_dimregs));
m_searchText.signal_changed().connect(
- sigc::mem_fun(*m_refTreeModelFilter.operator->(), &Gtk::TreeModelFilter::refilter)
+ sigc::mem_fun(*m_refInstrumentsModelFilter.operator->(), &Gtk::TreeModelFilter::refilter)
);
file = 0;
@@ -1792,14 +1864,21 @@
gig::Instrument* MainWindow::get_instrument()
{
- gig::Instrument* instrument = 0;
- std::vector rows = m_TreeView.get_selection()->get_selected_rows();
+ gig::Instrument* instrument = NULL;
+
+ // get indeces of visual selection
+ std::vector rows = m_TreeViewInstruments.get_selection()->get_selected_rows();
if (rows.empty()) return NULL;
+
+ // convert index of visual selection (i.e. if filtered) to index of model
+ Gtk::TreeModel::Path path = m_refInstrumentsModelFilter->convert_path_to_child_path(rows[0]);
+ if (!path) return NULL;
+
//NOTE: was const_iterator before, which did not compile with GTKMM4 development branch, probably going to be fixed before final GTKMM4 release though.
- Gtk::TreeModel::iterator it = m_refTreeModel->get_iter(rows[0]);
+ Gtk::TreeModel::iterator it = m_refInstrumentsTreeModel->get_iter(path);
if (it) {
Gtk::TreeModel::Row row = *it;
- instrument = row[m_Columns.m_col_instr];
+ instrument = row[m_InstrumentsModel.m_col_instr];
}
return instrument;
}
@@ -1864,9 +1943,11 @@
{
#if !USE_GTKMM_BUILDER
// select item in instrument menu
- std::vector rows = m_TreeView.get_selection()->get_selected_rows();
+ std::vector rows = m_TreeViewInstruments.get_selection()->get_selected_rows();
if (!rows.empty()) {
- Gtk::TreeModel::iterator it = m_refTreeModel->get_iter(rows[0]);
+ // convert index of visual selection (i.e. if filtered) to index of model
+ Gtk::TreeModel::Path row = m_refInstrumentsModelFilter->convert_path_to_child_path(rows[0]);
+ Gtk::TreeModel::iterator it = m_refInstrumentsTreeModel->get_iter(row);
if (it) {
Gtk::TreePath path(it);
int index = path[0];
@@ -1879,7 +1960,10 @@
updateScriptListOfMenu();
- m_RegionChooser.set_instrument(get_instrument());
+ gig::Instrument* instr = get_instrument();
+
+ m_RegionChooser.set_instrument(instr);
+ dimreg_edit.scriptVars.setInstrument(instr, true/*force update*/);
if (Settings::singleton()->syncSamplerInstrumentSelection) {
switch_sampler_instrument_signal.emit(get_instrument());
@@ -2071,7 +2155,7 @@
// forget all samples that ought to be imported
m_SampleImportQueue.clear();
// clear the samples and instruments tree views
- m_refTreeModel->clear();
+ m_refInstrumentsTreeModel->clear();
m_refSamplesTreeModel->clear();
m_refScriptsTreeModel->clear();
#if !USE_GTKMM_BUILDER
@@ -2088,7 +2172,7 @@
void MainWindow::__refreshEntireGUI() {
// clear the samples and instruments tree views
- m_refTreeModel->clear();
+ m_refInstrumentsTreeModel->clear();
m_refSamplesTreeModel->clear();
m_refScriptsTreeModel->clear();
#if !USE_GTKMM_BUILDER
@@ -2205,6 +2289,7 @@
dialog.set_current_folder(current_gig_dir);
}
if (dialog.run() == Gtk::RESPONSE_OK) {
+ dialog.hide();
std::string filename = dialog.get_filename();
printf("filename=%s\n", filename.c_str());
#ifdef GLIB_THREADS
@@ -2260,10 +2345,10 @@
{
if (instrument == instr) {
// select item in "instruments" tree view
- m_TreeView.get_selection()->select(Gtk::TreePath(ToString(i)));
+ m_TreeViewInstruments.get_selection()->select(Gtk::TreePath(ToString(i)));
// make sure the selected item in the "instruments" tree view is
// visible (scroll to it)
- m_TreeView.scroll_to_row(Gtk::TreePath(ToString(i)));
+ m_TreeViewInstruments.scroll_to_row(Gtk::TreePath(ToString(i)));
#if !USE_GTKMM_BUILDER
// select item in instrument menu
{
@@ -2473,6 +2558,7 @@
#endif
if (dialog.run() == Gtk::RESPONSE_OK) {
+ dialog.hide();
std::string filename = dialog.get_filename();
if (!Glib::str_has_suffix(filename, ".gig")) {
filename += ".gig";
@@ -2601,8 +2687,8 @@
void MainWindow::on_action_file_properties()
{
- propDialog.show();
- propDialog.deiconify();
+ fileProps.show();
+ fileProps.deiconify();
}
void MainWindow::on_action_warn_user_on_extensions() {
@@ -2626,7 +2712,7 @@
dimreg_stereo.set_has_tooltip(b);
// Not doing this here, we let onQueryTreeViewTooltip() handle this per cell
- //m_TreeView.set_has_tooltip(b);
+ //m_TreeViewInstruments.set_has_tooltip(b);
m_TreeViewSamples.set_has_tooltip(b);
m_TreeViewScripts.set_has_tooltip(b);
@@ -2664,16 +2750,16 @@
"backup your Gigasampler/GigaStudio files before editing them with "
"this application.\n"
"\n"
- "Please report bugs to: http://bugs.linuxsampler.org"
+ "Please report bugs to: https://bugs.linuxsampler.org"
);
dialog.set_comments(sComment.c_str());
- dialog.set_website("http://www.linuxsampler.org");
- dialog.set_website_label("http://www.linuxsampler.org");
+ dialog.set_website("https://www.linuxsampler.org");
+ dialog.set_website_label("https://www.linuxsampler.org");
dialog.set_position(Gtk::WIN_POS_CENTER);
dialog.run();
}
-PropDialog::PropDialog()
+FilePropDialog::FilePropDialog()
: eFileFormat(_("File Format")),
eName(_("Name")),
eCreationDate(_("Creation date")),
@@ -2707,7 +2793,7 @@
set_title(_("File Properties"));
eName.set_width_chars(50);
- connect(eFileFormat, &PropDialog::set_FileFormat);
+ connect(eFileFormat, &FilePropDialog::set_FileFormat);
connect(eName, &DLS::Info::Name);
connect(eCreationDate, &DLS::Info::CreationDate);
connect(eComments, &DLS::Info::Comments);
@@ -2768,7 +2854,7 @@
quitButton.set_can_default();
quitButton.grab_focus();
quitButton.signal_clicked().connect(
- sigc::mem_fun(*this, &PropDialog::hide));
+ sigc::mem_fun(*this, &FilePropDialog::hide));
quitButton.show();
vbox.show();
@@ -2777,7 +2863,7 @@
#endif
}
-void PropDialog::set_file(gig::File* file)
+void FilePropDialog::set_file(gig::File* file)
{
m_file = file;
update(file->pInfo);
@@ -2803,7 +2889,7 @@
update_model--;
}
-void PropDialog::set_FileFormat(int value)
+void FilePropDialog::set_FileFormat(int value)
{
m_file->pVersion->major = value;
}
@@ -2847,14 +2933,30 @@
eIsDrum(_("Is drum")),
eMIDIBank(_("MIDI bank"), 0, 16383),
eMIDIProgram(_("MIDI program")),
- eAttenuation(_("Attenuation"), 0, 96, 0, 1),
- eGainPlus6(_("Gain +6dB"), eAttenuation, -6),
+ eAttenuation(_("Attenuation (dB)"), -96, +96, 0, 1),
eEffectSend(_("Effect send"), 0, 65535),
eFineTune(_("Fine tune"), -8400, 8400),
- ePitchbendRange(_("Pitchbend range"), 0, 48),
+ ePitchbendRange(_("Pitchbend range (halftones)"), 0, 48),
ePianoReleaseMode(_("Piano release mode")),
eDimensionKeyRangeLow(_("Keyswitching range low")),
- eDimensionKeyRangeHigh(_("Keyswitching range high"))
+ eDimensionKeyRangeHigh(_("Keyswitching range high")),
+ table2(2,1),
+ eName2(_("Name")),
+ eCreationDate(_("Creation date")),
+ eComments(_("Comments")),
+ eProduct(_("Product")),
+ eCopyright(_("Copyright")),
+ eArtists(_("Artists")),
+ eGenre(_("Genre")),
+ eKeywords(_("Keywords")),
+ eEngineer(_("Engineer")),
+ eTechnician(_("Technician")),
+ eSoftware(_("Software")),
+ eMedium(_("Medium")),
+ eSource(_("Source")),
+ eSourceForm(_("Source form")),
+ eCommissioned(_("Commissioned")),
+ eSubject(_("Subject"))
{
if (!Settings::singleton()->autoRestoreWindowDimension) {
//set_default_size(470, 390);
@@ -2863,6 +2965,9 @@
set_title(_("Instrument Properties"));
+ tabs.append_page(vbox[1], _("Settings"));
+ tabs.append_page(vbox[2], _("Info"));
+
eDimensionKeyRangeLow.set_tip(
_("start of the keyboard area which should switch the "
"\"keyswitching\" dimension")
@@ -2877,7 +2982,6 @@
connect(eMIDIBank, &InstrumentProps::set_MIDIBank);
connect(eMIDIProgram, &InstrumentProps::set_MIDIProgram);
connect(eAttenuation, &gig::Instrument::Attenuation);
- connect(eGainPlus6, &gig::Instrument::Attenuation);
connect(eEffectSend, &gig::Instrument::EffectSend);
connect(eFineTune, &gig::Instrument::FineTune);
connect(ePitchbendRange, &gig::Instrument::PitchbendRange);
@@ -2887,18 +2991,64 @@
eName.signal_value_changed().connect(sig_name_changed.make_slot());
+ connect(eName2, &InstrumentProps::set_Name);
+ connectLambda(eCreationDate, [this](gig::String s) {
+ m->pInfo->CreationDate = s;
+ });
+ connectLambda(eComments, [this](gig::String s) {
+ m->pInfo->Comments = s;
+ });
+ connectLambda(eProduct, [this](gig::String s) {
+ m->pInfo->Product = s;
+ });
+ connectLambda(eCopyright, [this](gig::String s) {
+ m->pInfo->Copyright = s;
+ });
+ connectLambda(eArtists, [this](gig::String s) {
+ m->pInfo->Artists = s;
+ });
+ connectLambda(eGenre, [this](gig::String s) {
+ m->pInfo->Genre = s;
+ });
+ connectLambda(eKeywords, [this](gig::String s) {
+ m->pInfo->Keywords = s;
+ });
+ connectLambda(eEngineer, [this](gig::String s) {
+ m->pInfo->Engineer = s;
+ });
+ connectLambda(eTechnician, [this](gig::String s) {
+ m->pInfo->Technician = s;
+ });
+ connectLambda(eSoftware, [this](gig::String s) {
+ m->pInfo->Software = s;
+ });
+ connectLambda(eMedium, [this](gig::String s) {
+ m->pInfo->Medium = s;
+ });
+ connectLambda(eSource, [this](gig::String s) {
+ m->pInfo->Source = s;
+ });
+ connectLambda(eSourceForm, [this](gig::String s) {
+ m->pInfo->SourceForm = s;
+ });
+ connectLambda(eCommissioned, [this](gig::String s) {
+ m->pInfo->Commissioned = s;
+ });
+ connectLambda(eSubject, [this](gig::String s) {
+ m->pInfo->Subject = s;
+ });
+
+ // tab 1
#if USE_GTKMM_GRID
table.set_column_spacing(5);
#else
table.set_col_spacings(5);
#endif
-
table.add(eName);
table.add(eIsDrum);
table.add(eMIDIBank);
table.add(eMIDIProgram);
table.add(eAttenuation);
- table.add(eGainPlus6);
table.add(eEffectSend);
table.add(eFineTune);
table.add(ePitchbendRange);
@@ -2906,15 +3056,41 @@
table.add(eDimensionKeyRangeLow);
table.add(eDimensionKeyRangeHigh);
- add(vbox);
+ // tab 2
+#if USE_GTKMM_GRID
+ table2.set_column_spacing(5);
+#else
+ table2.set_col_spacings(5);
+#endif
+ table2.add(eName2);
+ table2.add(eCreationDate);
+ table2.add(eComments);
+ table2.add(eProduct);
+ table2.add(eCopyright);
+ table2.add(eArtists);
+ table2.add(eGenre);
+ table2.add(eKeywords);
+ table2.add(eEngineer);
+ table2.add(eTechnician);
+ table2.add(eSoftware);
+ table2.add(eMedium);
+ table2.add(eSource);
+ table2.add(eSourceForm);
+ table2.add(eCommissioned);
+ table2.add(eSubject);
+
+ add(vbox[0]);
#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24)
table.set_margin(5);
#else
table.set_border_width(5);
#endif
- vbox.pack_start(table);
+ vbox[1].pack_start(table);
+ vbox[2].pack_start(table2);
table.show();
- vbox.pack_start(buttonBox, Gtk::PACK_SHRINK);
+ table2.show();
+ vbox[0].pack_start(tabs);
+ vbox[0].pack_start(buttonBox, Gtk::PACK_SHRINK);
buttonBox.set_layout(Gtk::BUTTONBOX_END);
#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24)
buttonBox.set_margin(5);
@@ -2930,7 +3106,7 @@
sigc::mem_fun(*this, &InstrumentProps::hide));
quitButton.show();
- vbox.show();
+ vbox[0].show();
#if HAS_GTKMM_SHOW_ALL_CHILDREN
show_all_children();
#endif
@@ -2941,10 +3117,318 @@
update(instrument);
update_model++;
+
+ // tab 1
eName.set_value(instrument->pInfo->Name);
eIsDrum.set_value(instrument->IsDrum);
eMIDIBank.set_value(instrument->MIDIBank);
eMIDIProgram.set_value(instrument->MIDIProgram);
+ // tab 2
+ eName2.set_value(instrument->pInfo->Name);
+ eCreationDate.set_value(instrument->pInfo->CreationDate);
+ eComments.set_value(instrument->pInfo->Comments);
+ eProduct.set_value(instrument->pInfo->Product);
+ eCopyright.set_value(instrument->pInfo->Copyright);
+ eArtists.set_value(instrument->pInfo->Artists);
+ eGenre.set_value(instrument->pInfo->Genre);
+ eKeywords.set_value(instrument->pInfo->Keywords);
+ eEngineer.set_value(instrument->pInfo->Engineer);
+ eTechnician.set_value(instrument->pInfo->Technician);
+ eSoftware.set_value(instrument->pInfo->Software);
+ eMedium.set_value(instrument->pInfo->Medium);
+ eSource.set_value(instrument->pInfo->Source);
+ eSourceForm.set_value(instrument->pInfo->SourceForm);
+ eCommissioned.set_value(instrument->pInfo->Commissioned);
+ eSubject.set_value(instrument->pInfo->Subject);
+
+ update_model--;
+}
+
+
+SampleProps::SampleProps() :
+#if HAS_GTKMM_STOCK
+ quitButton(Gtk::Stock::CLOSE),
+#else
+ quitButton(_("_Close")),
+#endif
+ table(2,1),
+ eName(_("Name")),
+ eUnityNote(_("Unity Note")),
+ eSampleGroup(_("Sample Group")),
+ eSampleFormatInfo(_("Sample Format")),
+ eSampleID("Sample ID"),
+ eChecksum("Wave Data CRC-32"),
+ eLoopsCount(_("Loops"), 0, 1), // we might support more than 1 loop in future
+ eLoopStart(_("Loop start position"), 0, 9999999),
+ eLoopLength(_("Loop size"), 0, 9999999),
+ eLoopType(_("Loop type")),
+ eLoopPlayCount(_("Playback count")),
+ table2(2,1),
+ eName2(_("Name")),
+ eCreationDate(_("Creation date")),
+ eComments(_("Comments")),
+ eProduct(_("Product")),
+ eCopyright(_("Copyright")),
+ eArtists(_("Artists")),
+ eGenre(_("Genre")),
+ eKeywords(_("Keywords")),
+ eEngineer(_("Engineer")),
+ eTechnician(_("Technician")),
+ eSoftware(_("Software")),
+ eMedium(_("Medium")),
+ eSource(_("Source")),
+ eSourceForm(_("Source form")),
+ eCommissioned(_("Commissioned")),
+ eSubject(_("Subject"))
+{
+ if (!Settings::singleton()->autoRestoreWindowDimension) {
+ //set_default_size(470, 390);
+ set_position(Gtk::WIN_POS_MOUSE);
+ }
+
+ set_title(_("Sample Properties"));
+
+ tabs.append_page(vbox[1], _("Settings"));
+ tabs.append_page(vbox[2], _("Info"));
+
+ connect(eName, &SampleProps::set_Name);
+ connect(eUnityNote, &gig::Sample::MIDIUnityNote);
+ connect(eLoopsCount, &gig::Sample::Loops);
+ connectLambda(eLoopStart, [this](uint32_t start){
+ m->LoopStart = start;
+ m->LoopEnd = start + m->LoopSize;
+ });
+ connectLambda(eLoopLength, [this](uint32_t length){
+ m->LoopSize = length;
+ m->LoopEnd = m->LoopStart + length;
+ });
+ {
+ const char* choices[] = { _("normal"), _("bidirectional"), _("backward"), 0 };
+ static const gig::loop_type_t values[] = {
+ gig::loop_type_normal,
+ gig::loop_type_bidirectional,
+ gig::loop_type_backward
+ };
+ eLoopType.set_choices(choices, values);
+ }
+ connect(eLoopType, &gig::Sample::LoopType);
+ connect(eLoopPlayCount, &gig::Sample::LoopPlayCount);
+
+ eName.signal_value_changed().connect(sig_name_changed.make_slot());
+
+ connect(eName2, &SampleProps::set_Name);
+ connectLambda(eCreationDate, [this](gig::String s) {
+ m->pInfo->CreationDate = s;
+ });
+ connectLambda(eComments, [this](gig::String s) {
+ m->pInfo->Comments = s;
+ });
+ connectLambda(eProduct, [this](gig::String s) {
+ m->pInfo->Product = s;
+ });
+ connectLambda(eCopyright, [this](gig::String s) {
+ m->pInfo->Copyright = s;
+ });
+ connectLambda(eArtists, [this](gig::String s) {
+ m->pInfo->Artists = s;
+ });
+ connectLambda(eGenre, [this](gig::String s) {
+ m->pInfo->Genre = s;
+ });
+ connectLambda(eKeywords, [this](gig::String s) {
+ m->pInfo->Keywords = s;
+ });
+ connectLambda(eEngineer, [this](gig::String s) {
+ m->pInfo->Engineer = s;
+ });
+ connectLambda(eTechnician, [this](gig::String s) {
+ m->pInfo->Technician = s;
+ });
+ connectLambda(eSoftware, [this](gig::String s) {
+ m->pInfo->Software = s;
+ });
+ connectLambda(eMedium, [this](gig::String s) {
+ m->pInfo->Medium = s;
+ });
+ connectLambda(eSource, [this](gig::String s) {
+ m->pInfo->Source = s;
+ });
+ connectLambda(eSourceForm, [this](gig::String s) {
+ m->pInfo->SourceForm = s;
+ });
+ connectLambda(eCommissioned, [this](gig::String s) {
+ m->pInfo->Commissioned = s;
+ });
+ connectLambda(eSubject, [this](gig::String s) {
+ m->pInfo->Subject = s;
+ });
+
+ // tab 1
+#if USE_GTKMM_GRID
+ table.set_column_spacing(5);
+#else
+ table.set_col_spacings(5);
+#endif
+ table.add(eName);
+ table.add(eUnityNote);
+ table.add(eSampleGroup);
+ table.add(eSampleFormatInfo);
+ table.add(eSampleID);
+ table.add(eChecksum);
+ table.add(eLoopsCount);
+ table.add(eLoopStart);
+ table.add(eLoopLength);
+ table.add(eLoopType);
+ table.add(eLoopPlayCount);
+
+ // tab 2
+#if USE_GTKMM_GRID
+ table2.set_column_spacing(5);
+#else
+ table2.set_col_spacings(5);
+#endif
+ table2.add(eName2);
+ table2.add(eCreationDate);
+ table2.add(eComments);
+ table2.add(eProduct);
+ table2.add(eCopyright);
+ table2.add(eArtists);
+ table2.add(eGenre);
+ table2.add(eKeywords);
+ table2.add(eEngineer);
+ table2.add(eTechnician);
+ table2.add(eSoftware);
+ table2.add(eMedium);
+ table2.add(eSource);
+ table2.add(eSourceForm);
+ table2.add(eCommissioned);
+ table2.add(eSubject);
+
+ add(vbox[0]);
+#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24)
+ table.set_margin(5);
+#else
+ table.set_border_width(5);
+#endif
+ vbox[1].pack_start(table);
+ vbox[2].pack_start(table2);
+ table.show();
+ table2.show();
+ vbox[0].pack_start(tabs);
+ vbox[0].pack_start(buttonBox, Gtk::PACK_SHRINK);
+ buttonBox.set_layout(Gtk::BUTTONBOX_END);
+#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24)
+ buttonBox.set_margin(5);
+#else
+ buttonBox.set_border_width(5);
+#endif
+ buttonBox.show();
+ buttonBox.pack_start(quitButton);
+ quitButton.set_can_default();
+ quitButton.grab_focus();
+
+ quitButton.signal_clicked().connect(
+ sigc::mem_fun(*this, &SampleProps::hide));
+
+ quitButton.show();
+ vbox[0].show();
+#if HAS_GTKMM_SHOW_ALL_CHILDREN
+ show_all_children();
+#endif
+}
+
+void SampleProps::set_sample(gig::Sample* sample)
+{
+ update(sample);
+
+ update_model++;
+
+ // tab 1
+ eName.set_value(sample->pInfo->Name);
+ eUnityNote.set_value(sample->MIDIUnityNote);
+ // show sample group name
+ {
+ Glib::ustring s = "---";
+ if (sample && sample->GetGroup())
+ s = sample->GetGroup()->Name;
+ eSampleGroup.text.set_text(s);
+ }
+ // assemble sample format info string
+ {
+ Glib::ustring s;
+ if (sample) {
+ switch (sample->Channels) {
+ case 1: s = _("Mono"); break;
+ case 2: s = _("Stereo"); break;
+ default:
+ s = ToString(sample->Channels) + _(" audio channels");
+ break;
+ }
+ s += " " + ToString(sample->BitDepth) + " Bits";
+ s += " " + ToString(sample->SamplesPerSecond/1000) + "."
+ + ToString((sample->SamplesPerSecond%1000)/100) + " kHz";
+ } else {
+ s = _("No sample assigned to this dimension region.");
+ }
+ eSampleFormatInfo.text.set_text(s);
+ }
+ // generate sample's memory address pointer string
+ {
+ Glib::ustring s;
+ if (sample) {
+ char buf[64] = {};
+ snprintf(buf, sizeof(buf), "%p", sample);
+ s = buf;
+ } else {
+ s = "---";
+ }
+ eSampleID.text.set_text(s);
+ }
+ // generate raw wave form data CRC-32 checksum string
+ {
+ Glib::ustring s = "---";
+ if (sample) {
+ char buf[64] = {};
+ snprintf(buf, sizeof(buf), "%x", sample->GetWaveDataCRC32Checksum());
+ s = buf;
+ }
+ eChecksum.text.set_text(s);
+ }
+ eLoopsCount.set_value(sample->Loops);
+ eLoopStart.set_value(sample->LoopStart);
+ eLoopLength.set_value(sample->LoopSize);
+ eLoopType.set_value(sample->LoopType);
+ eLoopPlayCount.set_value(sample->LoopPlayCount);
+ // tab 2
+ eName2.set_value(sample->pInfo->Name);
+ eCreationDate.set_value(sample->pInfo->CreationDate);
+ eComments.set_value(sample->pInfo->Comments);
+ eProduct.set_value(sample->pInfo->Product);
+ eCopyright.set_value(sample->pInfo->Copyright);
+ eArtists.set_value(sample->pInfo->Artists);
+ eGenre.set_value(sample->pInfo->Genre);
+ eKeywords.set_value(sample->pInfo->Keywords);
+ eEngineer.set_value(sample->pInfo->Engineer);
+ eTechnician.set_value(sample->pInfo->Technician);
+ eSoftware.set_value(sample->pInfo->Software);
+ eMedium.set_value(sample->pInfo->Medium);
+ eSource.set_value(sample->pInfo->Source);
+ eSourceForm.set_value(sample->pInfo->SourceForm);
+ eCommissioned.set_value(sample->pInfo->Commissioned);
+ eSubject.set_value(sample->pInfo->Subject);
+
+ update_model--;
+}
+
+void SampleProps::set_Name(const gig::String& name)
+{
+ m->pInfo->Name = name;
+}
+
+void SampleProps::update_name()
+{
+ update_model++;
+ eName.set_value(m->pInfo->Name);
update_model--;
}
@@ -2980,7 +3464,7 @@
bool MainWindow::onQueryTreeViewTooltip(int x, int y, bool keyboardTip, const Glib::RefPtr& tooltip) {
Gtk::TreeModel::iterator iter;
- if (!m_TreeView.get_tooltip_context_iter(x, y, keyboardTip, iter)) {
+ if (!m_TreeViewInstruments.get_tooltip_context_iter(x, y, keyboardTip, iter)) {
return false;
}
Gtk::TreeModel::Path path(iter);
@@ -2990,13 +3474,13 @@
{
Gtk::TreeModel::Path path; // unused
int cellX, cellY; // unused
- m_TreeView.get_path_at_pos(x, y, path, pointedColumn, cellX, cellY);
+ m_TreeViewInstruments.get_path_at_pos(x, y, path, pointedColumn, cellX, cellY);
}
- Gtk::TreeViewColumn* scriptsColumn = m_TreeView.get_column(2);
+ Gtk::TreeViewColumn* scriptsColumn = m_TreeViewInstruments.get_column(2);
if (pointedColumn == scriptsColumn) { // mouse hovers scripts column ...
// show the script(s) assigned to the hovered instrument as tooltip
- tooltip->set_markup( row[m_Columns.m_col_tooltip] );
- m_TreeView.set_tooltip_cell(tooltip, &path, scriptsColumn, NULL);
+ tooltip->set_markup( row[m_InstrumentsModel.m_col_tooltip] );
+ m_TreeViewInstruments.set_tooltip_cell(tooltip, &path, scriptsColumn, NULL);
} else {
// if beginners' tooltips is disabled then don't show the following one
if (!Settings::singleton()->showTooltips)
@@ -3006,7 +3490,7 @@
"Right click here for actions on instruments & MIDI Rules. "
"Drag & drop to change the order of instruments."
));
- m_TreeView.set_tooltip_cell(tooltip, &path, pointedColumn, NULL);
+ m_TreeViewInstruments.set_tooltip_cell(tooltip, &path, pointedColumn, NULL);
}
return true;
}
@@ -3040,7 +3524,7 @@
file_has_name = filename;
file_is_changed = false;
- propDialog.set_file(gig);
+ fileProps.set_file(gig);
instrument_name_connection.block();
int index = 0;
@@ -3049,13 +3533,13 @@
Glib::ustring name(gig_to_utf8(instrument->pInfo->Name));
const int iScriptSlots = instrument->ScriptSlotCount();
- Gtk::TreeModel::iterator iter = m_refTreeModel->append();
+ Gtk::TreeModel::iterator iter = m_refInstrumentsTreeModel->append();
Gtk::TreeModel::Row row = *iter;
- row[m_Columns.m_col_nr] = index;
- row[m_Columns.m_col_name] = name;
- row[m_Columns.m_col_instr] = instrument;
- row[m_Columns.m_col_scripts] = iScriptSlots ? ToString(iScriptSlots) : "";
- row[m_Columns.m_col_tooltip] = scriptTooltipFor(instrument, index);
+ row[m_InstrumentsModel.m_col_nr] = index;
+ row[m_InstrumentsModel.m_col_name] = name;
+ row[m_InstrumentsModel.m_col_instr] = instrument;
+ row[m_InstrumentsModel.m_col_scripts] = iScriptSlots ? ToString(iScriptSlots) : "";
+ row[m_InstrumentsModel.m_col_tooltip] = scriptTooltipFor(instrument, index);
#if !USE_GTKMM_BUILDER
add_instrument_to_menu(name);
@@ -3117,7 +3601,7 @@
file = gig;
// select the first instrument
- m_TreeView.get_selection()->select(Gtk::TreePath("0"));
+ m_TreeViewInstruments.get_selection()->select(Gtk::TreePath("0"));
instr_props_set_instrument();
gig::Instrument* instrument = get_instrument();
@@ -3130,16 +3614,21 @@
{
instrumentProps.signal_name_changed().clear();
- std::vector rows = m_TreeView.get_selection()->get_selected_rows();
+ // get visual selection
+ std::vector rows = m_TreeViewInstruments.get_selection()->get_selected_rows();
if (rows.empty()) {
instrumentProps.hide();
return false;
}
+
+ // convert index of visual selection (i.e. if filtered) to index of model
+ Gtk::TreeModel::Path path = m_refInstrumentsModelFilter->convert_path_to_child_path(rows[0]);
+
//NOTE: was const_iterator before, which did not compile with GTKMM4 development branch, probably going to be fixed before final GTKMM4 release though.
- Gtk::TreeModel::iterator it = m_refTreeModel->get_iter(rows[0]);
+ Gtk::TreeModel::iterator it = m_refInstrumentsTreeModel->get_iter(path);
if (it) {
Gtk::TreeModel::Row row = *it;
- gig::Instrument* instrument = row[m_Columns.m_col_instr];
+ gig::Instrument* instrument = row[m_InstrumentsModel.m_col_instr];
instrumentProps.set_instrument(instrument);
@@ -3168,15 +3657,69 @@
void MainWindow::instr_name_changed_by_instr_props(Gtk::TreeModel::iterator& it)
{
Gtk::TreeModel::Row row = *it;
- Glib::ustring name = row[m_Columns.m_col_name];
+ Glib::ustring name = row[m_InstrumentsModel.m_col_name];
- gig::Instrument* instrument = row[m_Columns.m_col_instr];
+ gig::Instrument* instrument = row[m_InstrumentsModel.m_col_instr];
Glib::ustring gigname(gig_to_utf8(instrument->pInfo->Name));
if (gigname != name) {
Gtk::TreeModel::Path path(*it);
const int index = path[0];
- row[m_Columns.m_col_name] = gigname;
- row[m_Columns.m_col_tooltip] = scriptTooltipFor(instrument, index);
+ row[m_InstrumentsModel.m_col_name] = gigname;
+ row[m_InstrumentsModel.m_col_tooltip] = scriptTooltipFor(instrument, index);
+ }
+}
+
+bool MainWindow::sample_props_set_sample()
+{
+ sampleProps.signal_name_changed().clear();
+
+ std::vector rows = m_TreeViewSamples.get_selection()->get_selected_rows();
+ if (rows.empty()) {
+ sampleProps.hide();
+ return false;
+ }
+ //NOTE: was const_iterator before, which did not compile with GTKMM4 development branch, probably going to be fixed before final GTKMM4 release though.
+ Gtk::TreeModel::iterator it = m_refSamplesTreeModel->get_iter(rows[0]);
+ if (it) {
+ Gtk::TreeModel::Row row = *it;
+ gig::Sample* sample = row[m_SamplesModel.m_col_sample];
+
+ sampleProps.set_sample(sample);
+
+ // make sure sample tree is updated when user changes the
+ // sample name in sample properties window
+ sampleProps.signal_name_changed().connect(
+ sigc::bind(
+ sigc::mem_fun(*this,
+ &MainWindow::sample_name_changed_by_sample_props
+ ), it
+ )
+ );
+ } else {
+ sampleProps.hide();
+ }
+ //NOTE: explicit boolean cast required for GTKMM4 development branch here
+ return it ? true : false;
+}
+
+void MainWindow::show_sample_props()
+{
+ if (sample_props_set_sample()) {
+ sampleProps.show();
+ sampleProps.deiconify();
+ }
+}
+
+void MainWindow::sample_name_changed_by_sample_props(Gtk::TreeModel::iterator& it)
+{
+ Gtk::TreeModel::Row row = *it;
+ Glib::ustring name = row[m_SamplesModel.m_col_name];
+
+ gig::Sample* sample = row[m_SamplesModel.m_col_sample];
+ Glib::ustring gigname(gig_to_utf8(sample->pInfo->Name));
+ if (gigname != name) {
+ Gtk::TreeModel::Path path(*it);
+ row[m_SamplesModel.m_col_name] = gigname;
}
}
@@ -3192,13 +3735,9 @@
void MainWindow::show_script_slots() {
if (!file) return;
+
// get selected instrument
- std::vector rows = m_TreeView.get_selection()->get_selected_rows();
- if (rows.empty()) return;
- Gtk::TreeModel::iterator it = m_refTreeModel->get_iter(rows[0]);
- if (!it) return;
- Gtk::TreeModel::Row row = *it;
- gig::Instrument* instrument = row[m_Columns.m_col_instr];
+ gig::Instrument* instrument = get_instrument();
if (!instrument) return;
ScriptSlots* window = new ScriptSlots;
@@ -3214,20 +3753,23 @@
if (!pInstrument) return;
const int iScriptSlots = pInstrument->ScriptSlotCount();
- //NOTE: This is a big mess! Sometimes GTK requires m_TreeView.get_model(), here we need m_refTreeModelFilter->get_model(), otherwise accessing children below causes an error!
- //Glib::RefPtr model = m_TreeView.get_model();
- Glib::RefPtr model = m_refTreeModelFilter->get_model();
+ //NOTE: This is a big mess! Sometimes GTK requires m_TreeViewInstruments.get_model(), here we need m_refInstrumentsModelFilter->get_model(), otherwise accessing children below causes an error!
+ //Glib::RefPtr model = m_TreeViewInstruments.get_model();
+ Glib::RefPtr model = m_refInstrumentsModelFilter->get_model();
for (int i = 0; i < model->children().size(); ++i) {
Gtk::TreeModel::Row row = model->children()[i];
- if (row[m_Columns.m_col_instr] != pInstrument) continue;
- row[m_Columns.m_col_scripts] = iScriptSlots ? ToString(iScriptSlots) : "";
- row[m_Columns.m_col_tooltip] = scriptTooltipFor(pInstrument, i);
+ if (row[m_InstrumentsModel.m_col_instr] != pInstrument) continue;
+ row[m_InstrumentsModel.m_col_scripts] = iScriptSlots ? ToString(iScriptSlots) : "";
+ row[m_InstrumentsModel.m_col_tooltip] = scriptTooltipFor(pInstrument, i);
break;
}
// causes the sampler to reload the instrument with the new script
on_sel_change();
+
+ // force script 'patch' variables editor ("Script" tab) to be refreshed
+ dimreg_edit.scriptVars.setInstrument(pInstrument, true/*force update*/);
}
void MainWindow::assignScript(gig::Script* pScript) {
@@ -3308,6 +3850,25 @@
#endif
}
+void MainWindow::on_instr_double_click_opens_props() {
+#if USE_GLIB_ACTION
+ bool active = false;
+ m_actionInstrDoubleClickOpensProps->get_state(active);
+ // for some reason toggle state does not change automatically
+ active = !active;
+ m_actionInstrDoubleClickOpensProps->change_state(active);
+ Settings::singleton()->instrumentDoubleClickOpensProps = active;
+#else
+ Gtk::CheckMenuItem* item =
+ dynamic_cast(uiManager->get_widget("/MenuBar/MenuView/OpenInstrPropsByDoubleClick"));
+ if (!item) {
+ std::cerr << "/MenuBar/MenuView/OpenInstrPropsByDoubleClick == NULL\n";
+ return;
+ }
+ Settings::singleton()->instrumentDoubleClickOpensProps = item->get_active();
+#endif
+}
+
void MainWindow::on_save_with_temporary_file() {
#if USE_GLIB_ACTION
bool active = false;
@@ -3382,7 +3943,8 @@
void MainWindow::on_button_release(GdkEventButton* button) {
#endif
if (button->type == GDK_2BUTTON_PRESS) {
- show_instr_props();
+ if (Settings::singleton()->instrumentDoubleClickOpensProps)
+ show_instr_props();
} else if (button->type == GDK_BUTTON_PRESS && button->button == 3) {
// gig v2 files have no midi rules
const bool bEnabled = !(file->pVersion && file->pVersion->major == 2);
@@ -3414,7 +3976,7 @@
find(children.begin(), children.end(), item);
if (it != children.end()) {
int index = it - children.begin();
- m_TreeView.get_selection()->select(Gtk::TreePath(ToString(index)));
+ m_TreeViewInstruments.get_selection()->select(Gtk::TreePath(ToString(index)));
m_RegionChooser.set_instrument(file->GetInstrument(index));
}
@@ -3422,30 +3984,90 @@
}
#endif
+void MainWindow::on_action_move_instr() {
+ gig::Instrument* instr = get_instrument();
+ if (!instr) return;
+
+ int currentIndex = getIndexOf(instr);
+
+ Gtk::Dialog dialog(_("Move Instrument"), true /*modal*/);
+#if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
+ Gtk::Adjustment adjustment(
+ currentIndex,
+ 0 /*min*/, file->CountInstruments() - 1 /*max*/
+ );
+ Gtk::SpinButton spinBox(adjustment);
+#else
+ Gtk::SpinButton spinBox(
+ Gtk::Adjustment::create(
+ currentIndex,
+ 0 /*min*/, file->CountInstruments() - 1 /*max*/
+ )
+ );
+#endif
+#if USE_GTKMM_BOX
+ dialog.get_content_area()->pack_start(spinBox);
+#else
+ dialog.get_vbox()->pack_start(spinBox);
+#endif
+#if HAS_GTKMM_STOCK
+ Gtk::Button* okButton = dialog.add_button(Gtk::Stock::OK, 0);
+ dialog.add_button(Gtk::Stock::CANCEL, 1);
+#else
+ Gtk::Button* okButton = dialog.add_button(_("_OK"), 0);
+ dialog.add_button(_("_Cancel"), 1);
+#endif
+ okButton->set_sensitive(false);
+ // show the dialog at a reasonable screen position
+ dialog.set_position(Gtk::WIN_POS_MOUSE);
+ // only enable the 'OK' button if entered new index is not instrument's
+ // current index already
+ spinBox.signal_value_changed().connect([&]{
+ okButton->set_sensitive( spinBox.get_value_as_int() != currentIndex );
+ });
+ // usability acceleration: if user hits enter key on the text entry field
+ // then auto trigger the 'OK' button
+ spinBox.signal_activate().connect([&]{
+ if (okButton->get_sensitive())
+ okButton->clicked();
+ });
+#if HAS_GTKMM_SHOW_ALL_CHILDREN
+ dialog.show_all_children();
+#endif
+ if (!dialog.run()) { // 'OK' selected ...
+ int newIndex = spinBox.get_value_as_int();
+ printf("MOVE TO %d\n", newIndex);
+ gig::Instrument* dst = file->GetInstrument(newIndex);
+ instr->MoveTo(dst);
+ __refreshEntireGUI();
+ select_instrument(instr);
+ }
+}
+
void MainWindow::select_instrument(gig::Instrument* instrument) {
if (!instrument) return;
- //NOTE: This is a big mess! Sometimes GTK requires m_refTreeModelFilter->get_model(), here we need m_TreeView.get_model(), otherwise treeview selection below causes an error!
- Glib::RefPtr model = m_TreeView.get_model();
- //Glib::RefPtr model = m_refTreeModelFilter->get_model();
+ //NOTE: This is a big mess! Sometimes GTK requires m_refInstrumentsModelFilter->get_model(), here we need m_TreeViewInstruments.get_model(), otherwise treeview selection below causes an error!
+ Glib::RefPtr model = m_TreeViewInstruments.get_model();
+ //Glib::RefPtr model = m_refInstrumentsModelFilter->get_model();
for (int i = 0; i < model->children().size(); ++i) {
Gtk::TreeModel::Row row = model->children()[i];
- if (row[m_Columns.m_col_instr] == instrument) {
+ if (row[m_InstrumentsModel.m_col_instr] == instrument) {
// select and show the respective instrument in the list view
show_intruments_tab();
- m_TreeView.get_selection()->unselect_all();
+ m_TreeViewInstruments.get_selection()->unselect_all();
#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24)
auto iterSel = model->children()[i].get_iter();
- m_TreeView.get_selection()->select(iterSel);
+ m_TreeViewInstruments.get_selection()->select(iterSel);
#else
- m_TreeView.get_selection()->select(model->children()[i]);
+ m_TreeViewInstruments.get_selection()->select(model->children()[i]);
#endif
std::vector rows =
- m_TreeView.get_selection()->get_selected_rows();
+ m_TreeViewInstruments.get_selection()->get_selected_rows();
if (!rows.empty())
- m_TreeView.scroll_to_row(rows[0]);
+ m_TreeViewInstruments.scroll_to_row(rows[0]);
on_sel_change(); // the regular instrument selection change callback
}
}
@@ -3456,26 +4078,26 @@
gig::Region* pRegion = (gig::Region*) dimRgn->GetParent();
gig::Instrument* pInstrument = (gig::Instrument*) pRegion->GetParent();
- //NOTE: This is a big mess! Sometimes GTK requires m_refTreeModelFilter->get_model(), here we need m_TreeView.get_model(), otherwise treeview selection below causes an error!
- Glib::RefPtr model = m_TreeView.get_model();
- //Glib::RefPtr model = m_refTreeModelFilter->get_model();
+ //NOTE: This is a big mess! Sometimes GTK requires m_refInstrumentsModelFilter->get_model(), here we need m_TreeViewInstruments.get_model(), otherwise treeview selection below causes an error!
+ Glib::RefPtr model = m_TreeViewInstruments.get_model();
+ //Glib::RefPtr model = m_refInstrumentsModelFilter->get_model();
for (int i = 0; i < model->children().size(); ++i) {
Gtk::TreeModel::Row row = model->children()[i];
- if (row[m_Columns.m_col_instr] == pInstrument) {
+ if (row[m_InstrumentsModel.m_col_instr] == pInstrument) {
// select and show the respective instrument in the list view
show_intruments_tab();
- m_TreeView.get_selection()->unselect_all();
+ m_TreeViewInstruments.get_selection()->unselect_all();
#if GTKMM_MAJOR_VERSION > 3 || (GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION > 24)
auto iterSel = model->children()[i].get_iter();
- m_TreeView.get_selection()->select(iterSel);
+ m_TreeViewInstruments.get_selection()->select(iterSel);
#else
- m_TreeView.get_selection()->select(model->children()[i]);
+ m_TreeViewInstruments.get_selection()->select(model->children()[i]);
#endif
std::vector rows =
- m_TreeView.get_selection()->get_selected_rows();
+ m_TreeViewInstruments.get_selection()->get_selected_rows();
if (!rows.empty())
- m_TreeView.scroll_to_row(rows[0]);
+ m_TreeViewInstruments.scroll_to_row(rows[0]);
on_sel_change(); // the regular instrument selection change callback
// select respective region in the region selector
@@ -3760,14 +4382,15 @@
// update instrument tree view
instrument_name_connection.block();
- Gtk::TreeModel::iterator iterInstr = m_refTreeModel->append();
+ Gtk::TreeModel::iterator iterInstr = m_refInstrumentsTreeModel->append();
Gtk::TreeModel::Row rowInstr = *iterInstr;
- const int index = m_refTreeModel->children().size() - 1;
- rowInstr[m_Columns.m_col_nr] = index;
- rowInstr[m_Columns.m_col_name] = name;
- rowInstr[m_Columns.m_col_instr] = instrument;
- rowInstr[m_Columns.m_col_scripts] = "";
- rowInstr[m_Columns.m_col_tooltip] = scriptTooltipFor(instrument, index);
+ const int index = m_refInstrumentsTreeModel->children().size() - 1;
+ const int iScriptSlots = instrument->ScriptSlotCount();
+ rowInstr[m_InstrumentsModel.m_col_nr] = index;
+ rowInstr[m_InstrumentsModel.m_col_name] = name;
+ rowInstr[m_InstrumentsModel.m_col_instr] = instrument;
+ rowInstr[m_InstrumentsModel.m_col_scripts] = iScriptSlots ? ToString(iScriptSlots) : "";
+ rowInstr[m_InstrumentsModel.m_col_tooltip] = scriptTooltipFor(instrument, index);
instrument_name_connection.unblock();
#if !USE_GTKMM_BUILDER
@@ -3793,13 +4416,15 @@
// retrieve the currently selected instrument
// (being the original instrument to be duplicated)
- Glib::RefPtr sel = m_TreeView.get_selection();
+ Glib::RefPtr sel = m_TreeViewInstruments.get_selection();
std::vector rows = sel->get_selected_rows();
for (int r = 0; r < rows.size(); ++r) {
- Gtk::TreeModel::iterator it = m_refTreeModel->get_iter(rows[r]);
+ // convert index of visual selection (i.e. if filtered) to index of model
+ Gtk::TreeModel::Path path = m_refInstrumentsModelFilter->convert_path_to_child_path(rows[r]);
+ Gtk::TreeModel::iterator it = m_refInstrumentsTreeModel->get_iter(path);
if (it) {
Gtk::TreeModel::Row row = *it;
- gig::Instrument* instrOrig = row[m_Columns.m_col_instr];
+ gig::Instrument* instrOrig = row[m_InstrumentsModel.m_col_instr];
if (instrOrig) {
// duplicate the orginal instrument
gig::Instrument* instrNew = file->AddDuplicateInstrument(instrOrig);
@@ -3826,13 +4451,13 @@
return;
}
- Glib::RefPtr sel = m_TreeView.get_selection();
+ Glib::RefPtr sel = m_TreeViewInstruments.get_selection();
std::vector rows = sel->get_selected_rows();
for (int r = rows.size() - 1; r >= 0; --r) {
- Gtk::TreeModel::iterator it = m_refTreeModel->get_iter(rows[r]);
+ Gtk::TreeModel::iterator it = m_refInstrumentsTreeModel->get_iter(rows[r]);
if (!it) continue;
Gtk::TreeModel::Row row = *it;
- gig::Instrument* instr = row[m_Columns.m_col_instr];
+ gig::Instrument* instr = row[m_InstrumentsModel.m_col_instr];
try {
Gtk::TreePath path(it);
int index = path[0];
@@ -3846,28 +4471,28 @@
#endif
// remove row from instruments tree view
- m_refTreeModel->erase(it);
+ m_refInstrumentsTreeModel->erase(it);
// update "Nr" column of all instrument rows
{
int index = 0;
- for (Gtk::TreeModel::iterator it = m_refTreeModel->children().begin();
- it != m_refTreeModel->children().end(); ++it, ++index)
+ for (Gtk::TreeModel::iterator it = m_refInstrumentsTreeModel->children().begin();
+ it != m_refInstrumentsTreeModel->children().end(); ++it, ++index)
{
Gtk::TreeModel::Row row = *it;
- gig::Instrument* instrument = row[m_Columns.m_col_instr];
- row[m_Columns.m_col_nr] = index;
- row[m_Columns.m_col_tooltip] = scriptTooltipFor(instrument, index);
+ gig::Instrument* instrument = row[m_InstrumentsModel.m_col_instr];
+ row[m_InstrumentsModel.m_col_nr] = index;
+ row[m_InstrumentsModel.m_col_tooltip] = scriptTooltipFor(instrument, index);
}
}
#if GTKMM_MAJOR_VERSION < 3
// select another instrument (in gtk3 this is done
// automatically)
- if (!m_refTreeModel->children().empty()) {
- if (index == m_refTreeModel->children().size()) {
+ if (!m_refInstrumentsTreeModel->children().empty()) {
+ if (index == m_refInstrumentsTreeModel->children().size()) {
index--;
}
- m_TreeView.get_selection()->select(
+ m_TreeViewInstruments.get_selection()->select(
Gtk::TreePath(ToString(index)));
}
#endif
@@ -3886,11 +4511,7 @@
}
void MainWindow::on_action_sample_properties() {
- //TODO: show a dialog where the selected sample's properties can be edited
- Gtk::MessageDialog msg(
- *this, _("Sorry, yet to be implemented!"), false, Gtk::MESSAGE_INFO
- );
- msg.run();
+ show_sample_props();
}
void MainWindow::on_action_add_script_group() {
@@ -3953,15 +4574,22 @@
if (!it) return;
Gtk::TreeModel::Row row = *it;
gig::Script* script = row[m_ScriptsModel.m_col_script];
- if (!script) return;
+ editScript(script);
+}
+void MainWindow::editScript(gig::Script* script) {
+ if (!script) return;
ScriptEditor* editor = new ScriptEditor;
editor->signal_script_to_be_changed.connect(
signal_script_to_be_changed.make_slot()
);
- editor->signal_script_changed.connect(
- signal_script_changed.make_slot()
- );
+ editor->signal_script_changed.connect([this](gig::Script* script) {
+ // signal to sampler (which will reload the script due to this)
+ signal_script_changed.emit(script);
+ // force script 'patch' variables editor ("Script" tab) to be refreshed
+ gig::Instrument* instr = get_instrument();
+ dimreg_edit.scriptVars.setInstrument(instr, true/*force update*/);
+ });
editor->setScript(script);
//editor->reparent(*this);
editor->show();
@@ -4109,6 +4737,7 @@
dialog.set_current_folder(current_sample_dir);
}
if (dialog.run() == Gtk::RESPONSE_OK) {
+ dialog.hide();
current_sample_dir = dialog.get_current_folder();
Glib::ustring error_files;
std::vector filenames = dialog.get_filenames();
@@ -4289,6 +4918,7 @@
}
if (dialog.run() == Gtk::RESPONSE_OK)
{
+ dialog.hide();
current_sample_dir = dialog.get_current_folder();
Glib::ustring error_files;
std::string folder = dialog.get_filename();
@@ -4514,13 +5144,13 @@
// get selected source instrument
gig::Instrument* src = NULL;
{
- Glib::RefPtr sel = m_TreeView.get_selection();
+ Glib::RefPtr sel = m_TreeViewInstruments.get_selection();
std::vector rows = sel->get_selected_rows();
if (!rows.empty()) {
- Gtk::TreeModel::iterator it = m_refTreeModel->get_iter(rows[0]);
+ Gtk::TreeModel::iterator it = m_refInstrumentsTreeModel->get_iter(rows[0]);
if (it) {
Gtk::TreeModel::Row row = *it;
- src = row[m_Columns.m_col_instr];
+ src = row[m_InstrumentsModel.m_col_instr];
}
}
}
@@ -4542,13 +5172,13 @@
gig::Instrument* dst = NULL;
{
Gtk::TreeModel::Path path;
- const bool found = m_TreeView.get_path_at_pos(x, y, path);
+ const bool found = m_TreeViewInstruments.get_path_at_pos(x, y, path);
if (!found) return;
- Gtk::TreeModel::iterator iter = m_refTreeModel->get_iter(path);
+ Gtk::TreeModel::iterator iter = m_refInstrumentsTreeModel->get_iter(path);
if (!iter) return;
Gtk::TreeModel::Row row = *iter;
- dst = row[m_Columns.m_col_instr];
+ dst = row[m_InstrumentsModel.m_col_instr];
}
if (!dst) return;
@@ -4687,6 +5317,10 @@
file_changed();
}
}
+ // change name in the sample properties window
+ if (sampleProps.get_sample() == sample && sample) {
+ sampleProps.set_sample(sample);
+ }
}
void MainWindow::script_name_changed(const Gtk::TreeModel::Path& path,
@@ -4719,25 +5353,14 @@
if (!iter) return;
Gtk::TreeModel::Row row = *iter;
gig::Script* script = row[m_ScriptsModel.m_col_script];
- if (!script) return;
-
- ScriptEditor* editor = new ScriptEditor;
- editor->signal_script_to_be_changed.connect(
- signal_script_to_be_changed.make_slot()
- );
- editor->signal_script_changed.connect(
- signal_script_changed.make_slot()
- );
- editor->setScript(script);
- //editor->reparent(*this);
- editor->show();
+ editScript(script);
}
void MainWindow::instrument_name_changed(const Gtk::TreeModel::Path& path,
const Gtk::TreeModel::iterator& iter) {
if (!iter) return;
Gtk::TreeModel::Row row = *iter;
- Glib::ustring name = row[m_Columns.m_col_name];
+ Glib::ustring name = row[m_InstrumentsModel.m_col_name];
#if !USE_GTKMM_BUILDER
// change name in instrument menu
@@ -4755,7 +5378,7 @@
#endif
// change name in gig
- gig::Instrument* instrument = row[m_Columns.m_col_instr];
+ gig::Instrument* instrument = row[m_InstrumentsModel.m_col_instr];
gig::String gigname(gig_from_utf8(name));
if (instrument && instrument->pInfo->Name != gigname) {
instrument->pInfo->Name = gigname;
@@ -4783,7 +5406,7 @@
#else
Gtk::TreeModel::Row row = *iter;
#endif
- Glib::ustring name = row[m_Columns.m_col_name];
+ Glib::ustring name = row[m_InstrumentsModel.m_col_name];
name = name.lowercase();
std::vector tokens = Glib::Regex::split_simple(" ", pattern);
@@ -4801,13 +5424,13 @@
// list view as pre-selection
std::set indeces;
{
- Glib::RefPtr sel = m_TreeView.get_selection();
+ Glib::RefPtr sel = m_TreeViewInstruments.get_selection();
std::vector rows = sel->get_selected_rows();
for (int r = 0; r < rows.size(); ++r) {
- Gtk::TreeModel::iterator it = m_refTreeModel->get_iter(rows[r]);
+ Gtk::TreeModel::iterator it = m_refInstrumentsTreeModel->get_iter(rows[r]);
if (it) {
Gtk::TreeModel::Row row = *it;
- int index = row[m_Columns.m_col_nr];
+ int index = row[m_InstrumentsModel.m_col_nr];
indeces.insert(index);
}
}
@@ -5017,6 +5640,7 @@
#endif
if (dialog.run() == Gtk::RESPONSE_OK) {
+ dialog.hide();
#ifdef GLIB_THREADS
printf("on_action_merge_files self=%p\n",
static_cast(Glib::Threads::Thread::self()));