Mixxx

/home/maxime/Projets/Mixxx/1.10/mixxx/src/dlgprefmidibindings.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           dlgprefmidibindings.cpp  -  description
00003                              -------------------
00004     begin                : Sat Jun 21 2008
00005     copyright            : (C) 2008 by Tom Care
00006     email                : psyc0de@gmail.com
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 #include <QtGui>
00018 #include <QDebug>
00019 #include "midi/midiinputmappingtablemodel.h"
00020 #include "midi/midioutputmappingtablemodel.h"
00021 #include "midi/midichanneldelegate.h"
00022 #include "midi/midistatusdelegate.h"
00023 #include "midi/midinodelegate.h"
00024 #include "midi/midioptiondelegate.h"
00025 #include "controlgroupdelegate.h"
00026 #include "controlvaluedelegate.h"
00027 #include "dlgprefmidibindings.h"
00028 #include "midi/mididevice.h"
00029 #include "midi/mididevicemanager.h"
00030 #include "configobject.h"
00031 #include "midi/midimapping.h"
00032 
00033 #ifdef __MIDISCRIPT__
00034 #include "midi/midiscriptengine.h"
00035 #endif
00036 
00037 
00038 DlgPrefMidiBindings::DlgPrefMidiBindings(QWidget *parent, MidiDevice* midiDevice,
00039                                          MidiDeviceManager* midiDeviceManager,
00040                                          ConfigObject<ConfigValue> *pConfig)
00041     : QWidget(parent), Ui::DlgPrefMidiBindingsDlg()
00042 {
00043     setupUi(this);
00044     m_pConfig = pConfig;
00045     m_pMidiDevice = midiDevice;
00046     m_pMidiDeviceManager = midiDeviceManager;
00047 
00048     m_pDlgMidiLearning = NULL;
00049 
00050     m_bDirty = false;
00051 
00052     labelDeviceName->setText(m_pMidiDevice->getName());
00053 
00054     //Tell the input mapping table widget which data model it should be viewing
00055     //(note that m_pInputMappingTableView is defined in the .ui file!)
00056     m_pInputMappingTableView->setModel((QAbstractItemModel*)m_pMidiDevice->getMidiMapping()->getMidiInputMappingTableModel());
00057 
00058     m_pInputMappingTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
00059     m_pInputMappingTableView->setSelectionMode(QAbstractItemView::ContiguousSelection); //The model won't like ExtendedSelection, probably.
00060     m_pInputMappingTableView->verticalHeader()->hide();
00061 
00062     //Set up "delete" as a shortcut key to remove a row for the MIDI input table.
00063     m_deleteMIDIInputRowAction = new QAction(m_pInputMappingTableView);
00064     /*m_deleteMIDIInputRowAction->setShortcut(QKeySequence::Delete);
00065     m_deleteMIDIInputRowAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
00066     connect(m_deleteMIDIInputRowAction, SIGNAL(triggered()), this, SLOT(slotRemoveInputBinding()));
00067     */
00068     //The above shortcut doesn't work yet, not quite sure why. -- Albert Feb 1 / 2009
00069 
00070     //Set up the cool item delegates for the input mapping table
00071     m_pMidiChannelDelegate = new MidiChannelDelegate(m_pInputMappingTableView);
00072     m_pMidiStatusDelegate = new MidiStatusDelegate(m_pInputMappingTableView);
00073     m_pMidiNoDelegate = new MidiNoDelegate(m_pInputMappingTableView);
00074     m_pMidiOptionDelegate = new MidiOptionDelegate(m_pInputMappingTableView);
00075     m_pControlGroupDelegate = new ControlGroupDelegate(m_pInputMappingTableView);
00076     m_pControlValueDelegate = new ControlValueDelegate(m_pInputMappingTableView);
00077     m_pInputMappingTableView->setItemDelegateForColumn(MIDIINPUTTABLEINDEX_MIDISTATUS, m_pMidiStatusDelegate);
00078     m_pInputMappingTableView->setItemDelegateForColumn(MIDIINPUTTABLEINDEX_MIDICHANNEL, m_pMidiChannelDelegate);
00079     m_pInputMappingTableView->setItemDelegateForColumn(MIDIINPUTTABLEINDEX_MIDINO, m_pMidiNoDelegate);
00080     m_pInputMappingTableView->setItemDelegateForColumn(MIDIINPUTTABLEINDEX_CONTROLOBJECTGROUP, m_pControlGroupDelegate);
00081     m_pInputMappingTableView->setItemDelegateForColumn(MIDIINPUTTABLEINDEX_CONTROLOBJECTVALUE, m_pControlValueDelegate);
00082     m_pInputMappingTableView->setItemDelegateForColumn(MIDIINPUTTABLEINDEX_MIDIOPTION, m_pMidiOptionDelegate);
00083 
00084     //Tell the output mapping table widget which data model it should be viewing
00085     //(note that m_pOutputMappingTableView is defined in the .ui file!)
00086     m_pOutputMappingTableView->setModel((QAbstractItemModel*)m_pMidiDevice->getMidiMapping()->getMidiOutputMappingTableModel());
00087     m_pOutputMappingTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
00088     m_pOutputMappingTableView->setSelectionMode(QAbstractItemView::ContiguousSelection);
00089     m_pOutputMappingTableView->verticalHeader()->hide();
00090 
00091     //Set up the cool item delegates for the output mapping table
00092     m_pOutputMappingTableView->setItemDelegateForColumn(MIDIOUTPUTTABLEINDEX_MIDISTATUS, m_pMidiStatusDelegate);
00093     m_pOutputMappingTableView->setItemDelegateForColumn(MIDIOUTPUTTABLEINDEX_MIDICHANNEL, m_pMidiChannelDelegate);
00094     m_pOutputMappingTableView->setItemDelegateForColumn(MIDIOUTPUTTABLEINDEX_MIDINO, m_pMidiNoDelegate);
00095     //TODO: We need different delegates for the output table's CO group/value columns because we only list real input
00096     //      controls, and for output we'd want to list a different set with stuff like "VUMeter" and other output controls.
00097     //m_pOutputMappingTableView->setItemDelegateForColumn(MIDIOUTPUTTABLEINDEX_CONTROLOBJECTGROUP, m_pControlGroupDelegate);
00098     //m_pOutputMappingTableView->setItemDelegateForColumn(MIDIOUTPUTTABLEINDEX_CONTROLOBJECTVALUE, m_pControlValueDelegate);
00099 
00100     // Connect buttons to slots
00101     connect(btnExportXML, SIGNAL(clicked()), this, SLOT(slotExportXML()));
00102 
00103     //Input bindings
00104     connect(btnMidiLearnWizard, SIGNAL(clicked()), this, SLOT(slotShowMidiLearnDialog()));
00105     connect(btnMidiLearnWizard, SIGNAL(clicked()), this, SLOT(slotDirty()));
00106     connect(btnClearAllInputBindings, SIGNAL(clicked()), this, SLOT(slotClearAllInputBindings()));
00107     connect(btnClearAllInputBindings, SIGNAL(clicked()), this, SLOT(slotDirty()));
00108     connect(btnRemoveInputBinding, SIGNAL(clicked()), this, SLOT(slotRemoveInputBinding()));
00109     connect(btnRemoveInputBinding, SIGNAL(clicked()), this, SLOT(slotDirty()));
00110     connect(btnAddInputBinding, SIGNAL(clicked()), this, SLOT(slotAddInputBinding()));
00111     connect(btnAddInputBinding, SIGNAL(clicked()), this, SLOT(slotDirty()));
00112 
00113     //Output bindings
00114     connect(btnClearAllOutputBindings, SIGNAL(clicked()), this, SLOT(slotClearAllOutputBindings()));
00115     connect(btnClearAllOutputBindings, SIGNAL(clicked()), this, SLOT(slotDirty()));
00116     connect(btnRemoveOutputBinding, SIGNAL(clicked()), this, SLOT(slotRemoveOutputBinding()));
00117     connect(btnRemoveOutputBinding, SIGNAL(clicked()), this, SLOT(slotDirty()));
00118     connect(btnAddOutputBinding, SIGNAL(clicked()), this, SLOT(slotAddOutputBinding()));
00119     connect(btnAddOutputBinding, SIGNAL(clicked()), this, SLOT(slotDirty()));
00120 
00121     connect(comboBoxPreset, SIGNAL(activated(const QString&)), this, SLOT(slotLoadMidiMapping(const QString&)));
00122     connect(comboBoxPreset, SIGNAL(activated(const QString&)), this, SLOT(slotDirty()));
00123 
00124     connect(m_pInputMappingTableView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(slotDirty()));
00125     connect(m_pOutputMappingTableView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(slotDirty()));
00126 
00127     //Load the list of presets into the presets combobox.
00128     enumeratePresets();
00129 
00130     //Initialize the output device combobox
00131     enumerateOutputDevices();
00132 
00133 }
00134 
00135 DlgPrefMidiBindings::~DlgPrefMidiBindings() {
00136     delete m_deleteMIDIInputRowAction;
00137 }
00138 
00139 void DlgPrefMidiBindings::slotDirty ()
00140 {
00141     m_bDirty = true;
00142 }
00143 
00144 void DlgPrefMidiBindings::enumerateOutputDevices()
00145 {
00146     comboBoxOutputDevice->clear();
00147 
00148     comboBoxOutputDevice->addItem(tr("None"));
00149 
00150     //For each MIDI output device, insert an item into the output device combobox.
00151     QList<MidiDevice*> deviceList = m_pMidiDeviceManager->getDeviceList(true, false);
00152     QListIterator<MidiDevice*> it(deviceList);
00153 
00154     while (it.hasNext())
00155       {
00156         MidiDevice* currentDevice = it.next();
00157         QString curDeviceName = currentDevice->getName();
00158         //qDebug() << "curDeviceName: " << curDeviceName;
00159         comboBoxOutputDevice->addItem(curDeviceName);
00160       }
00161 
00162     //Assume autopairing was done and let's just show the output device combobox with the name
00163     //of the input device selected for now...
00164     QString currentOutputMidiDeviceName = m_pMidiDevice->getName();
00165     comboBoxOutputDevice->setCurrentIndex(comboBoxOutputDevice->findText(currentOutputMidiDeviceName));
00166 
00167 }
00168 
00169 void DlgPrefMidiBindings::enumeratePresets()
00170 {
00171     QList<QString> presetsList;
00172     comboBoxPreset->clear();
00173 
00174     //Insert a dummy "..." item at the top to try to make it less confusing.
00175     //(For example, we don't want "Akai MPD24" showing up as the default item
00176     // when a user has their controller plugged in)
00177     comboBoxPreset->addItem("...");
00178 
00179     // paths to search for midi presets
00180     QList<QString> midiDirPaths;
00181     midiDirPaths.append(LPRESETS_PATH);
00182     midiDirPaths.append(m_pConfig->getConfigPath().append("midi/"));
00183 
00184     QListIterator<QString> itpth(midiDirPaths);
00185     while (itpth.hasNext()) {
00186         QDirIterator it(itpth.next());
00187         while (it.hasNext())
00188         {
00189             it.next(); //Advance iterator. We get the filename from the next line. (It's a bit weird.)
00190             QString curMapping = it.fileName();
00191             if (curMapping.endsWith(MIDI_MAPPING_EXTENSION)) //blah, thanks for nothing Qt
00192             {
00193                 curMapping.chop(QString(MIDI_MAPPING_EXTENSION).length()); //chop off the .midi.xml
00194                 presetsList.append(curMapping);
00195             }
00196         }
00197     }
00198     //Sort in alphabetical order
00199     qSort(presetsList);
00200     comboBoxPreset->addItems(presetsList);
00201 }
00202 
00203 
00204 
00205 /* slotUpdate()
00206  * Called when the dialog is displayed.
00207  */
00208 void DlgPrefMidiBindings::slotUpdate() {
00209 
00210     //Check if the device that this dialog is for is already enabled...
00211     if (m_pMidiDevice->isOpen())
00212     {
00213         chkEnabledDevice->setCheckState(Qt::Checked); //Check the "Enabled" box
00214         toolBox->setEnabled(true); //Enable MIDI in/out toolbox.
00215         groupBoxPresets->setEnabled(true); //Enable presets group box.
00216     }
00217     else {
00218         chkEnabledDevice->setCheckState(Qt::Unchecked); //Uncheck the "Enabled" box
00219         toolBox->setEnabled(false); //Disable MIDI in/out toolbox.
00220         groupBoxPresets->setEnabled(false); //Disable presets group box.
00221     }
00222 
00223     //Connect the "Enabled" checkbox after the checkbox state is set
00224     connect(chkEnabledDevice, SIGNAL(stateChanged(int)), this, SLOT(slotDeviceState(int)));
00225     connect(chkEnabledDevice, SIGNAL(stateChanged(int)), this, SLOT(slotDirty()));
00226 }
00227 
00228 /* slotApply()
00229  * Called when the OK button is pressed.
00230  */
00231 void DlgPrefMidiBindings::slotApply() {
00232     /* User has pressed OK, so enable or disable the device, write the
00233      * controls to the DOM, and reload the MIDI bindings.  FIXED: only
00234      * do this if the user has changed the preferences.
00235      */
00236     if (m_bDirty)
00237     {
00238         m_pMidiDevice->disableMidiLearn();
00239         if (chkEnabledDevice->isChecked()) {
00240             //Enable the device.
00241             enableDevice();
00242 
00243             //Disable processing of MIDI messages received from the device in order to
00244             //prevent a race condition while we modify the MIDI mapping.
00245             m_pMidiDevice->setReceiveInhibit(true);
00246             m_pMidiDevice->getMidiMapping()->applyPreset();
00247             m_pMidiDevice->setReceiveInhibit(false);
00248 
00249             //FIXME: We need some logic like this to make changing the output device work.
00250             //       See MidiDeviceManager::associateInputAndOutputDevices() for more info...
00251             /*
00252               if (comboBoxOutputDevice->currentText() != tr("None"))
00253               m_pMidiDeviceManager->associateInputAndOutputDevices(m_pMidiDevice, comboBoxOutputDevice->currentText());
00254             */
00255         }
00256         else disableDevice();
00257     }
00258     m_bDirty = false;
00259 }
00260 
00261 void DlgPrefMidiBindings::slotShowMidiLearnDialog() {
00262     // If the user has checked the "Enabled" checkbox but they haven't hit OK to
00263     // apply it yet, prompt them to apply the settings before we open the MIDI
00264     // learning dialog. If we don't apply the settings first and open the
00265     // device, MIDI learn won't react to MIDI messages.
00266     if (chkEnabledDevice->isChecked() && !m_pMidiDevice->isOpen()) {
00267         QMessageBox::StandardButton result = QMessageBox::question(
00268             this,
00269             tr("Apply MIDI device settings?"),
00270             tr("Your settings must be applied before starting the MIDI learning wizard.\n"
00271                "Apply settings and continue?"),
00272             QMessageBox::Ok | QMessageBox::Cancel,  // Buttons to be displayed
00273             QMessageBox::Ok);  // Default button
00274         // Stop if the user has not pressed the Ok button,
00275         // which could be the Cancel or the Close Button.
00276         if (result != QMessageBox::Ok) return;
00277     }
00278     slotApply();
00279 
00280     // Note that DlgMidiLearning is set to delete itself on close using the
00281     // Qt::WA_DeleteOnClose attribute (so this "new" doesn't leak memory)
00282     m_pDlgMidiLearning = new DlgMidiLearning(
00283         this, m_pMidiDevice->getMidiMapping());
00284     m_pDlgMidiLearning->show();
00285 }
00286 
00287 /* slotImportXML()
00288  * Prompts the user for an XML preset and loads it.
00289  */
00290 void DlgPrefMidiBindings::slotLoadMidiMapping(const QString &name) {
00291 
00292     if (name == "...")
00293         return;
00294 
00295     //Ask for confirmation if the MIDI tables aren't empty...
00296     MidiMapping* mapping = m_pMidiDevice->getMidiMapping();
00297     if (mapping->numInputMidiMessages() > 0 ||
00298         mapping->numOutputMixxxControls() > 0)
00299     {
00300          QMessageBox::StandardButton result = QMessageBox::question(
00301              this,
00302              tr("Overwrite existing mapping?"),
00303              tr("Are you sure you'd like to load the %1 mapping?\n"
00304                 "This will overwrite your existing MIDI mapping.").arg(name),
00305                    QMessageBox::Yes | QMessageBox::No);
00306 
00307          if (result == QMessageBox::No) {
00308             //Select the "..." item again in the combobox.
00309             comboBoxPreset->setCurrentIndex(0);
00310             return;
00311          }
00312     }
00313 
00314     QString filename = LPRESETS_PATH + name + MIDI_MAPPING_EXTENSION;
00315     QFile ftest(filename);
00316     if ( !ftest.exists() ) filename = m_pConfig->getConfigPath().append("midi/") + name + MIDI_MAPPING_EXTENSION;
00317 
00318     if (!filename.isNull()) m_pMidiDevice->getMidiMapping()->loadPreset(filename, true);    // It's applied on prefs close
00319     m_pInputMappingTableView->update();
00320 
00321     //Select the "..." item again in the combobox.
00322     comboBoxPreset->setCurrentIndex(0);
00323 }
00324 
00325 /* slotExportXML()
00326  * Prompts the user for an XML preset and saves it.
00327  */
00328 void DlgPrefMidiBindings::slotExportXML() {
00329     QString fileName = QFileDialog::getSaveFileName(this,
00330             tr("Export Mixxx MIDI Bindings"), m_pConfig->getConfigPath().append("midi/"),
00331             tr("Preset Files (*.midi.xml)"));
00332     if (!fileName.isNull()) m_pMidiDevice->getMidiMapping()->savePreset(fileName);
00333 }
00334 
00335 void DlgPrefMidiBindings::slotDeviceState(int state) {
00336   if (state == Qt::Checked) {
00337       toolBox->setEnabled(true);    //Enable MIDI in/out toolbox.
00338       groupBoxPresets->setEnabled(true);    //Enable presets group box.
00339       emit deviceStateChanged(this,true);  // Set tree item text to bold
00340   }
00341   else {
00342       toolBox->setEnabled(false);   //Disable MIDI in/out toolbox.
00343       groupBoxPresets->setEnabled(false);   //Disable presets group box.
00344       emit deviceStateChanged(this,false);  // Set tree item text to not bold
00345   }
00346 }
00347 
00348 void DlgPrefMidiBindings::enableDevice()
00349 {
00350     if (m_pMidiDevice->isOpen()) {
00351         m_pMidiDevice->close();
00352     }
00353     m_pMidiDevice->open();
00354     m_pConfig->set(ConfigKey("[Midi]", m_pMidiDevice->getName().replace(" ", "_")), 1);
00355 
00356     //TODO: Should probably check if open() actually succeeded.
00357 }
00358 
00359 void DlgPrefMidiBindings::disableDevice()
00360 {
00361     m_pMidiDevice->close();
00362     m_pConfig->set(ConfigKey("[Midi]", m_pMidiDevice->getName().replace(" ", "_")), 0);
00363 
00364     //TODO: Should probably check if close() actually succeeded.
00365 }
00366 
00367 void DlgPrefMidiBindings::slotAddInputBinding()
00368 {
00369     bool ok = true;
00370     QString controlGroup = QInputDialog::getItem(this, tr("Select Control Group"), tr("Select Control Group"),
00371                                                 ControlGroupDelegate::getControlGroups(), 0, false,  &ok);
00372     if (!ok) return;
00373 
00374     QStringList controlValues;
00375     if (controlGroup == CONTROLGROUP_CHANNEL1_STRING ||
00376         controlGroup == CONTROLGROUP_CHANNEL2_STRING ||
00377         controlGroup == CONTROLGROUP_SAMPLER1_STRING ||
00378         controlGroup == CONTROLGROUP_SAMPLER2_STRING ||
00379         controlGroup == CONTROLGROUP_SAMPLER3_STRING ||
00380         controlGroup == CONTROLGROUP_SAMPLER4_STRING) {
00381         controlValues = ControlValueDelegate::getChannelControlValues();
00382     }
00383     else if (controlGroup == CONTROLGROUP_MASTER_STRING)
00384     {
00385         controlValues = ControlValueDelegate::getMasterControlValues();
00386     }
00387     else if (controlGroup == CONTROLGROUP_PLAYLIST_STRING)
00388     {
00389         controlValues = ControlValueDelegate::getPlaylistControlValues();
00390     }
00391     else if (controlGroup == CONTROLGROUP_FLANGER_STRING)
00392     {
00393         controlValues = ControlValueDelegate::getFlangerControlValues();
00394     }
00395     else if (controlGroup == CONTROLGROUP_MICROPHONE_STRING)
00396     {
00397         controlValues = ControlValueDelegate::getMicrophoneControlValues();
00398     }
00399     else
00400     {
00401         qDebug() << "Unhandled ControlGroup in " << __FILE__;
00402     }
00403 
00404 
00405     QString controlValue = QInputDialog::getItem(this, tr("Select Control"), tr("Select Control"),
00406                                                  controlValues, 0, false,  &ok);
00407     if (!ok) return;
00408 
00409 
00410     MixxxControl mixxxControl(controlGroup, controlValue);
00411     MidiMessage message;
00412 
00413     while (m_pMidiDevice->getMidiMapping()->isMidiMessageMapped(message))
00414     {
00415         message.setMidiNo(message.getMidiNo() + 1);
00416         if (message.getMidiNo() >= 127) //If the table is full, then overwrite something...
00417             break;
00418     }
00419     m_pMidiDevice->getMidiMapping()->setInputMidiMapping(message, mixxxControl);
00420 }
00421 
00422 void DlgPrefMidiBindings::slotRemoveInputBinding()
00423 {
00424     QModelIndexList selectedIndices = m_pInputMappingTableView->selectionModel()->selectedRows();
00425     if (selectedIndices.size() > 0)
00426     {
00427         MidiInputMappingTableModel* tableModel = dynamic_cast<MidiInputMappingTableModel*>(m_pInputMappingTableView->model());
00428         if (tableModel) {
00429 
00430             QModelIndex curIndex;
00431             //The model indices are sorted so that we remove the rows from the table
00432             //in ascending order. This is necessary because if row A is above row B in
00433             //the table, and you remove row A, the model index for row B will change.
00434             //Sorting the indices first means we don't have to worry about this.
00435             qSort(selectedIndices);
00436 
00437             //Going through the model indices in descending order (see above comment for explanation).
00438             QListIterator<QModelIndex> it(selectedIndices);
00439             it.toBack();
00440             while (it.hasPrevious())
00441             {
00442                 curIndex = it.previous();
00443                 tableModel->removeRow(curIndex.row());
00444             }
00445         }
00446     }
00447 }
00448 
00449 void DlgPrefMidiBindings::slotClearAllInputBindings() {
00450     if (QMessageBox::warning(this, tr("Clear Input Bindings"),
00451             tr("Are you sure you want to clear all bindings?"),
00452             QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel) != QMessageBox::Ok)
00453         return;
00454 
00455     //Remove all the rows from the data model (ie. the MIDI mapping).
00456     MidiInputMappingTableModel* tableModel = dynamic_cast<MidiInputMappingTableModel*>(m_pInputMappingTableView->model());
00457     if (tableModel) {
00458         tableModel->removeRows(0, tableModel->rowCount());
00459     }
00460 }
00461 
00462 
00463 void DlgPrefMidiBindings::slotAddOutputBinding() {
00464     qDebug() << "STUB: DlgPrefMidiBindings::slotAddOutputBinding()";
00465 
00466     m_pMidiDevice->getMidiMapping()->setOutputMidiMapping(MixxxControl(), MidiMessage());
00467 }
00468 
00469 void DlgPrefMidiBindings::slotRemoveOutputBinding()
00470 {
00471     QModelIndexList selectedIndices = m_pOutputMappingTableView->selectionModel()->selectedRows();
00472     if (selectedIndices.size() > 0)
00473     {
00474         MidiOutputMappingTableModel* tableModel =
00475                             dynamic_cast<MidiOutputMappingTableModel*>(m_pOutputMappingTableView->model());
00476         if (tableModel) {
00477             QModelIndex curIndex;
00478             //The model indices are sorted so that we remove the rows from the table
00479             //in ascending order. This is necessary because if row A is above row B in
00480             //the table, and you remove row A, the model index for row B will change.
00481             //Sorting the indices first means we don't have to worry about this.
00482             //qSort(selectedIndices);
00483 
00484             //Going through the model indices in descending order (see above comment for explanation).
00485             QListIterator<QModelIndex> it(selectedIndices);
00486             it.toBack();
00487             while (it.hasPrevious())
00488             {
00489                 curIndex = it.previous();
00490                 qDebug() << "Dlg: removing row" << curIndex.row();
00491                 tableModel->removeRow(curIndex.row());
00492             }
00493         }
00494     }
00495 }
00496 
00497 void DlgPrefMidiBindings::slotClearAllOutputBindings() {
00498     if (QMessageBox::warning(this, tr("Clear Output Bindings"),
00499             tr("Are you sure you want to clear all output bindings?"),
00500             QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel) != QMessageBox::Ok)
00501         return;
00502 
00503     //Remove all the rows from the data model (ie. the MIDI mapping).
00504     MidiOutputMappingTableModel* tableModel = dynamic_cast<MidiOutputMappingTableModel*>(m_pOutputMappingTableView->model());
00505     if (tableModel) {
00506         tableModel->removeRows(0, tableModel->rowCount());
00507     }
00508 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines