--- qsampler/trunk/src/qsamplerInstrumentList.cpp 2007/06/13 21:54:07 1234 +++ qsampler/trunk/src/qsamplerInstrumentList.cpp 2010/03/15 10:45:35 2069 @@ -1,7 +1,8 @@ // qsamplerInstrumentList.cpp // /**************************************************************************** - Copyright (C) 2003-2007, rncbc aka Rui Nuno Capela. All rights reserved. + Copyright (C) 2003-2010, rncbc aka Rui Nuno Capela. All rights reserved. + Copyright (C) 2007, Christian Schoenebeck This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -23,704 +24,394 @@ #include "qsamplerInstrumentList.h" #include "qsamplerInstrument.h" -#include "qsamplerInstrumentForm.h" #include "qsamplerOptions.h" #include "qsamplerMainForm.h" -#include -#include -#include -#include -#include -#include -#include +#include +#include -// Needed for lroundf() -#include - -#ifndef CONFIG_ROUND -static inline long lroundf ( float x ) -{ - if (x >= 0.0f) - return long(x + 0.5f); - else - return long(x - 0.5f); -} -#endif +namespace QSampler { -//---------------------------------------------------------------------- -// class qsamplerInstrumentGroup -- custom group list view item. +//------------------------------------------------------------------------- +// QSampler::InstrumentListModel - data model for MIDI prog mappings // -// Constructors. -qsamplerInstrumentGroup::qsamplerInstrumentGroup ( - qsamplerInstrumentList *pListView, const QString& sName, - QListViewItem *pItemAfter ) - : QListViewItem(pListView, pItemAfter ? pItemAfter : pListView->lastItem()) +InstrumentListModel::InstrumentListModel ( QObject *pParent ) + : QAbstractItemModel(pParent), m_iMidiMap(LSCP_MIDI_MAP_ALL) { - QListViewItem::setRenameEnabled(0, true); - - QListViewItem::setPixmap(0, QPixmap::fromMimeSource("itemGroup.png")); - QListViewItem::setText(0, sName); +// QAbstractItemModel::reset(); } - -qsamplerInstrumentGroup::qsamplerInstrumentGroup ( - qsamplerInstrumentGroup *pGroupItem, const QString& sName ) - : QListViewItem(pGroupItem, sName) +InstrumentListModel::~InstrumentListModel (void) { - QListViewItem::setRenameEnabled(0, true); - - QListViewItem::setPixmap(0, QPixmap::fromMimeSource("itemGroup.png")); + clear(); } -// Default destructor. -qsamplerInstrumentGroup::~qsamplerInstrumentGroup (void) +int InstrumentListModel::rowCount ( const QModelIndex& /*parent*/) const { -} + int nrows = 0; + if (m_iMidiMap == LSCP_MIDI_MAP_ALL) { + InstrumentMap::const_iterator itMap = m_instruments.constBegin(); + for ( ; itMap != m_instruments.constEnd(); ++itMap) + nrows += (*itMap).size(); + } else { + InstrumentMap::const_iterator itMap = m_instruments.find(m_iMidiMap); + if (itMap != m_instruments.constEnd()) + nrows += (*itMap).size(); + } -// Instance accessors. -void qsamplerInstrumentGroup::setName ( const QString& sName ) -{ - QListViewItem::setText(0, sName); + return nrows; } -QString qsamplerInstrumentGroup::name (void) const +int InstrumentListModel::columnCount ( const QModelIndex& /*parent*/) const { - return QListViewItem::text(0); + return 9; } -qsamplerInstrumentGroup *qsamplerInstrumentGroup::groupItem (void) const +QVariant InstrumentListModel::data ( + const QModelIndex &index, int role ) const { - QListViewItem *pParent = QListViewItem::parent(); - while (pParent && pParent->rtti() != qsamplerInstrumentList::Group) - pParent = pParent->parent(); - return static_cast (pParent); -} + if (!index.isValid()) + return QVariant(); + const Instrument *pInstr + = static_cast (index.internalPointer()); + if (pInstr && role == Qt::DisplayRole) { + switch (index.column()) { + case 0: return pInstr->name(); + case 1: return QVariant::fromValue(pInstr->map()); + case 2: return QVariant::fromValue(pInstr->bank()); + case 3: return QVariant::fromValue(pInstr->prog() + 1); + case 4: return pInstr->engineName(); + case 5: return pInstr->instrumentFile(); + case 6: return QVariant::fromValue(pInstr->instrumentNr()); + case 7: return QString::number(pInstr->volume() * 100.0) + " %"; + case 8: { + switch (pInstr->loadMode()) { + case 3: return tr("Persistent"); + case 2: return tr("On Demand Hold"); + case 1: return tr("On Demand"); + } + } + default: + break; + } + } -qsamplerInstrumentList *qsamplerInstrumentGroup::listView (void) const -{ - return static_cast (QListViewItem::listView()); + return QVariant(); } -// To show up whether its open or not. -void qsamplerInstrumentGroup::setOpen ( bool bOpen ) +QModelIndex InstrumentListModel::index ( + int row, int col, const QModelIndex& /*parent*/ ) const { - // Set the proper pixmap of this... - if (rtti() == qsamplerInstrumentList::Group) { - QListViewItem::setPixmap(0, QPixmap::fromMimeSource( - bOpen ? "itemGroupOpen.png" : "itemGroup.png")); + const Instrument *pInstr = NULL; + + if (m_iMidiMap == LSCP_MIDI_MAP_ALL) { + int nrows = 0; + InstrumentMap::const_iterator itMap = m_instruments.constBegin(); + for ( ; itMap != m_instruments.constEnd(); ++itMap) { + const InstrumentList& list = *itMap; + nrows += list.size(); + if (row < nrows) { + pInstr = list.at(row + list.size() - nrows); + break; + } + } + } else { + // Resolve MIDI instrument map... + InstrumentMap::const_iterator itMap = m_instruments.find(m_iMidiMap); + if (itMap != m_instruments.constEnd()) { + const InstrumentList& list = *itMap; + if (row < list.size()) + pInstr = list.at(row); + } } - // Open it up... - QListViewItem::setOpen(bOpen); - // All ancestors should be also visible. - if (bOpen && QListViewItem::parent()) - QListViewItem::parent()->setOpen(true); + if (pInstr) + return createIndex(row, col, (void *) pInstr); + else + return QModelIndex(); } -// To virtually distinguish between list view items. -int qsamplerInstrumentGroup::rtti (void) const +QModelIndex InstrumentListModel::parent ( const QModelIndex& /*child*/ ) const { - return qsamplerInstrumentList::Group; + return QModelIndex(); } -//---------------------------------------------------------------------- -// class qsamplerInstrumentItem -- custom file list view item. -// - -// Constructors. -qsamplerInstrumentItem::qsamplerInstrumentItem ( - qsamplerInstrumentList *pListView, - qsamplerInstrument *pInstrument, - QListViewItem *pItemAfter ) - : qsamplerInstrumentGroup(pListView, pInstrument->name(), pItemAfter) +QVariant InstrumentListModel::headerData ( + int section, Qt::Orientation orientation, int role ) const { - m_pInstrument = pInstrument; - - update(); -} - -qsamplerInstrumentItem::qsamplerInstrumentItem ( - qsamplerInstrumentGroup *pGroupItem, - qsamplerInstrument *pInstrument ) - : qsamplerInstrumentGroup(pGroupItem, pInstrument->name()) -{ - m_pInstrument = pInstrument; + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { + switch (section) { + case 0: return tr("Name"); + case 1: return tr("Map"); + case 2: return tr("Bank"); + case 3: return tr("Prog"); + case 4: return tr("Engine"); + case 5: return tr("File"); + case 6: return tr("Nr"); + case 7: return tr("Vol"); + case 8: return tr("Mode"); + } + } - update(); + return QAbstractItemModel::headerData(section, orientation, role); } -// Default destructor. -qsamplerInstrumentItem::~qsamplerInstrumentItem (void) +void InstrumentListModel::setMidiMap ( int iMidiMap ) { - if (m_pInstrument) - delete m_pInstrument; -} - + if (iMidiMap < 0) + iMidiMap = LSCP_MIDI_MAP_ALL; -// To virtually distinguish between list view items. -int qsamplerInstrumentItem::rtti (void) const -{ - return qsamplerInstrumentList::Item; + m_iMidiMap = iMidiMap; } -// Payload accessor. -qsamplerInstrument *qsamplerInstrumentItem::instrument (void) const +int InstrumentListModel::midiMap (void) const { - return m_pInstrument; + return m_iMidiMap; } -// Item refreshment. -void qsamplerInstrumentItem::update (void) +const Instrument *InstrumentListModel::addInstrument ( + int iMap, int iBank, int iProg ) { - QListViewItem::setPixmap(0, QPixmap::fromMimeSource("itemFile.png")); - - const QString s = "-"; - if (m_pInstrument) { - setText(0, m_pInstrument->name()); - setText(1, QString::number(m_pInstrument->map())); - setText(2, QString::number(m_pInstrument->bank())); - setText(3, QString::number(m_pInstrument->prog() + 1)); - setText(4, m_pInstrument->engineName()); - setText(5, QFileInfo(m_pInstrument->instrumentFile()).fileName()); - setText(6, QString::number(m_pInstrument->instrumentNr())); - setText(7, QString::number(::lroundf(100.0f * m_pInstrument->volume()))); - QString sLoadMode = s; - switch (m_pInstrument->loadMode()) { - case 3: - sLoadMode = QObject::tr("Persistent"); - break; - case 2: - sLoadMode = QObject::tr("On Demand Hold"); - break; - case 1: - sLoadMode = QObject::tr("On Demand"); + // Check it there's already one instrument item + // with the very same key (bank, program); + // if yes, just remove it without prejudice... + InstrumentList& list = m_instruments[iMap]; + for (int i = 0; i < list.size(); ++i) { + const Instrument *pInstr = list.at(i); + if (pInstr->bank() == iBank && pInstr->prog() == iProg) { + delete pInstr; + list.removeAt(i); break; } - setText(8, sLoadMode); - } else { - for (int i = 0; i < listView()->columns(); i++) - setText(i, s); } -} - -//---------------------------------------------------------------------------- -// qsamplerInstrumentList -- MIDI instrument list view. -// - -// Constructor. -qsamplerInstrumentList::qsamplerInstrumentList ( - QWidget *pParent, const char *pszName ) - : QListView(pParent, pszName) -{ - m_iMidiMap = LSCP_MIDI_MAP_ALL; - -// QListView::setRootIsDecorated(true); - QListView::setAllColumnsShowFocus(true); - QListView::setResizeMode(QListView::NoColumn); -// QListView::setAcceptDrops(true); - QListView::setDragAutoScroll(true); - QListView::setSizePolicy( - QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); -// QListView::setShowToolTips(false); - QListView::setSortColumn(-1); - - QListView::addColumn(tr("Name")); - QListView::addColumn(tr("Map")); - QListView::addColumn(tr("Bank")); - QListView::addColumn(tr("Prog")); - QListView::addColumn(tr("Engine")); - QListView::addColumn(tr("File")); - QListView::addColumn(tr("Nr")); - QListView::addColumn(tr("Vol")); - QListView::addColumn(tr("Mode")); - - QListView::setColumnAlignment(1, Qt::AlignHCenter); // Map - QListView::setColumnAlignment(2, Qt::AlignHCenter); // Bank - QListView::setColumnAlignment(3, Qt::AlignHCenter); // Prog - QListView::setColumnAlignment(6, Qt::AlignHCenter); // Nr - QListView::setColumnAlignment(7, Qt::AlignHCenter); // Vol - - QListView::setColumnWidth(0, 120); // Name - QListView::setColumnWidth(5, 240); // File - - m_pNewGroupAction = new QAction( - QIconSet(QPixmap::fromMimeSource("itemGroupNew.png")), - tr("New &Group"), tr("Ctrl+G"), this); - m_pNewItemAction = new QAction( - QIconSet(QPixmap::fromMimeSource("itemNew.png")), - tr("New &Instrument..."), tr("Ins"), this); - m_pEditItemAction = new QAction( - QIconSet(QPixmap::fromMimeSource("formEdit.png")), - tr("&Edit..."), tr("Enter"), this); - m_pRenameAction = new QAction(tr("&Rename"), tr("F2"), this); - m_pDeleteAction = new QAction( - QIconSet(QPixmap::fromMimeSource("formRemove.png")), - tr("&Delete"), tr("Del"), this); - m_pRefreshAction = new QAction( - QIconSet(QPixmap::fromMimeSource("formRefresh.png")), - tr("Re&fresh"), tr("F5"), this); - - m_pNewGroupAction->setToolTip(tr("New Group")); - m_pNewItemAction->setToolTip(tr("New Instrument")); - m_pEditItemAction->setToolTip(tr("Edit")); - m_pRenameAction->setToolTip(tr("Rename")); - m_pDeleteAction->setToolTip(tr("Delete")); - m_pRefreshAction->setToolTip(tr("Refresh")); - - QObject::connect(m_pNewGroupAction, - SIGNAL(activated()), - SLOT(newGroupSlot())); - QObject::connect(m_pNewItemAction, - SIGNAL(activated()), - SLOT(newItemSlot())); - QObject::connect(m_pEditItemAction, - SIGNAL(activated()), - SLOT(editItemSlot())); - QObject::connect(m_pRenameAction, - SIGNAL(activated()), - SLOT(renameSlot())); - QObject::connect(m_pDeleteAction, - SIGNAL(activated()), - SLOT(deleteSlot())); - QObject::connect(m_pRefreshAction, - SIGNAL(activated()), - SLOT(refresh())); - - QObject::connect(this, - SIGNAL(selectionChanged()), - SLOT(selectionChangedSlot())); - QObject::connect(this, - SIGNAL(doubleClicked(QListViewItem*, const QPoint&, int)), - SLOT(activatedSlot(QListViewItem*))); - QObject::connect(this, - SIGNAL(returnPressed(QListViewItem*)), - SLOT(activatedSlot(QListViewItem*))); - QObject::connect(this, - SIGNAL(itemRenamed(QListViewItem*,int)), - SLOT(renamedSlot(QListViewItem*))); - - selectionChangedSlot(); -} - - -// Default destructor. -qsamplerInstrumentList::~qsamplerInstrumentList (void) -{ - delete m_pNewGroupAction; - delete m_pNewItemAction; - delete m_pEditItemAction; - delete m_pRenameAction; - delete m_pDeleteAction; -} - - -// Add a new instrument item, optionally under a given group. -qsamplerInstrumentItem *qsamplerInstrumentList::addItem ( - qsamplerInstrument *pInstrument, - qsamplerInstrumentGroup *pParentGroup ) -{ - // Check it there's already one instrument item - // with the very same key (bank, program); - // if yes, just remove it without prejudice... - qsamplerInstrumentItem *pItem = findItem(pInstrument); - if (pItem) { - // If exactly the same, just update view and bail out... - if (pItem->instrument() == pInstrument) { - pItem->update(); - return pItem; + // Resolve the appropriate place, we keep the list sorted that way... + int i = 0; + for ( ; i < list.size(); ++i) { + const Instrument *pInstr = list.at(i); + if (iBank < pInstr->bank() + || (iBank == pInstr->bank() && iProg < pInstr->prog())) { + break; } - // Remove it, as instrument keys must be unique. - delete pItem; } - // Add the new item under proper group one, if any... - if (pParentGroup) { - pParentGroup->setOpen(true); - pItem = new qsamplerInstrumentItem(pParentGroup, pInstrument); + Instrument *pInstr = new Instrument(iMap, iBank, iProg); + if (pInstr->getInstrument()) { + list.insert(i, pInstr); } else { - pItem = new qsamplerInstrumentItem(this, pInstrument); + delete pInstr; + pInstr = NULL; } - // Set it as current selection... - QListView::setSelected(pItem, true); - - return pItem; + return pInstr; } -// Add a new instrument group, optionally under another group. -qsamplerInstrumentGroup *qsamplerInstrumentList::addGroup ( - const QString& sName, qsamplerInstrumentGroup *pParentGroup ) +void InstrumentListModel::removeInstrument ( const Instrument *pInstrument ) { - qsamplerInstrumentGroup *pGroup = findGroup(sName); - if (pGroup == NULL) { - if (pParentGroup) { - pParentGroup->setOpen(true); - pGroup = new qsamplerInstrumentGroup(pParentGroup, sName); - } else { - pGroup = new qsamplerInstrumentGroup(this, sName); - } - } - QListView::setSelected(pGroup, true); - return pGroup; -} - - -// Find a group item, given its name. -qsamplerInstrumentGroup *qsamplerInstrumentList::findGroup ( - const QString& sName ) const -{ - // Iterate all over the place to search for the group. - QListViewItemIterator iter((QListView *) this); - while (iter.current()) { - QListViewItem *pItem = iter.current(); - if (pItem->rtti() == Group && pItem->text(0) == sName) - return static_cast (pItem); - ++iter; - } - // Not found. - return NULL; -} - + const int iMap = pInstrument->map(); + const int iBank = pInstrument->bank(); + const int iProg = pInstrument->prog(); -// Find a file item, given its name. -qsamplerInstrumentItem *qsamplerInstrumentList::findItem ( - qsamplerInstrument *pInstrument ) const -{ - if (pInstrument == NULL) - return NULL; - - // Iterate all over the place to search for the group. - QListViewItemIterator iter((QListView *) this); - while (iter.current()) { - QListViewItem *pListItem = iter.current(); - if (pListItem->rtti() == Item) { - qsamplerInstrumentItem *pItem - = static_cast (pListItem); - if (pItem && pItem->instrument() - && pItem->instrument()->map() == pInstrument->map() - && pItem->instrument()->bank() == pInstrument->bank() - && pItem->instrument()->prog() == pInstrument->prog()) - return pItem; + if (m_instruments.contains(iMap)) { + InstrumentList& list = m_instruments[iMap]; + for (int i = 0; i < list.size(); ++i) { + const Instrument *pInstr = list.at(i); + if (pInstr->bank() == iBank && pInstr->prog() == iProg) { + delete pInstr; + list.removeAt(i); + break; + } } - ++iter; } - // Not found. - return NULL; } -// Find and return the nearest group item... -qsamplerInstrumentGroup *qsamplerInstrumentList::groupItem ( - QListViewItem *pItem ) const +// Reposition the instrument in the model (called when map/bank/prg changed) +void InstrumentListModel::updateInstrument ( const Instrument *pInstrument ) { - while (pItem && pItem->rtti() != Group) - pItem = pItem->parent(); - return static_cast (pItem); -} + const int iMap = pInstrument->map(); + const int iBank = pInstrument->bank(); + const int iProg = pInstrument->prog(); + // Remove given instrument from its current list... + removeInstrument(pInstrument); -// Add a new group item below the current one. -void qsamplerInstrumentList::newGroupSlot (void) -{ - qsamplerInstrumentGroup *pNewGroup - = addGroup(tr("New Group"), groupItem(QListView::selectedItem())); - if (pNewGroup) - pNewGroup->startRename(0); - - selectionChangedSlot(); + // Re-add the instrument... + addInstrument(iMap, iBank, iProg); } -// Map selector. -void qsamplerInstrumentList::setMidiMap ( int iMidiMap ) +void InstrumentListModel::refresh (void) { - if (iMidiMap < 0) - iMidiMap = LSCP_MIDI_MAP_ALL; + MainForm *pMainForm = MainForm::getInstance(); + if (pMainForm == NULL) + return; + if (pMainForm->client() == NULL) + return; - m_iMidiMap = iMidiMap; -} + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); -int qsamplerInstrumentList::midiMap (void) const -{ - return m_iMidiMap; -} + clear(); + // Load the whole bunch of instrument items... + lscp_midi_instrument_t *pInstrs + = ::lscp_list_midi_instruments(pMainForm->client(), m_iMidiMap); + for (int iInstr = 0; pInstrs && pInstrs[iInstr].map >= 0; ++iInstr) { + const int iMap = pInstrs[iInstr].map; + const int iBank = pInstrs[iInstr].bank; + const int iProg = pInstrs[iInstr].prog; + addInstrument(iMap, iBank, iProg); + // Try to keep it snappy :) + QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); + } -// List actions accessors. -QAction *qsamplerInstrumentList::newGroupAction (void) const -{ - return m_pNewGroupAction; -} + QApplication::restoreOverrideCursor(); -QAction *qsamplerInstrumentList::newItemAction (void) const -{ - return m_pNewItemAction; + if (pInstrs == NULL && ::lscp_client_get_errno(pMainForm->client())) { + pMainForm->appendMessagesClient("lscp_list_midi_instruments"); + pMainForm->appendMessagesError( + tr("Could not get current list of MIDI instrument mappings.\n\nSorry.")); + } } -QAction *qsamplerInstrumentList::editItemAction (void) const +void InstrumentListModel::beginReset (void) { - return m_pEditItemAction; +#if QT_VERSION >= 0x040600 + QAbstractItemModel::beginResetModel(); +#endif } -QAction *qsamplerInstrumentList::renameAction (void) const +void InstrumentListModel::endReset (void) { - return m_pRenameAction; +#if QT_VERSION >= 0x040600 + QAbstractItemModel::endResetModel(); +#else + QAbstractItemModel::reset(); +#endif } -QAction *qsamplerInstrumentList::deleteAction (void) const -{ - return m_pDeleteAction; -} -QAction *qsamplerInstrumentList::refreshAction (void) const +// Map clear. +void InstrumentListModel::clear (void) { - return m_pRefreshAction; + InstrumentMap::iterator itMap = m_instruments.begin(); + for ( ; itMap != m_instruments.end(); ++itMap) { + InstrumentList& list = itMap.value(); + qDeleteAll(list); + list.clear(); + } + + m_instruments.clear(); } -// Add a new instrument item below the current one. -void qsamplerInstrumentList::newItemSlot (void) +//------------------------------------------------------------------------- +// QSampler::InstrumentListView - list view for MIDI prog mappings +// + +// Constructor. +InstrumentListView::InstrumentListView ( QWidget *pParent ) + : QTreeView(pParent) { - qsamplerInstrument *pInstrument = new qsamplerInstrument(); + m_pListModel = new InstrumentListModel(this); - qsamplerInstrumentForm form(this); - form.setup(pInstrument); - if (!form.exec()) { - delete pInstrument; - return; - } + QTreeView::setModel(m_pListModel); - // Commit... - pInstrument->mapInstrument(); - // add new item to the tree... - addItem(pInstrument, groupItem(QListView::selectedItem())); - // Notify we've changes... - emit instrumentsChanged(); + QTreeView::setRootIsDecorated(false); + QTreeView::setUniformRowHeights(true); + QTreeView::setAlternatingRowColors(true); + QTreeView::setSelectionBehavior(QAbstractItemView::SelectRows); + QTreeView::setSelectionMode(QAbstractItemView::SingleSelection); + QTreeView::setItemsExpandable(false); - selectionChangedSlot(); + QHeaderView *pHeader = QTreeView::header(); + pHeader->setDefaultAlignment(Qt::AlignLeft); + pHeader->setMovable(false); + pHeader->setStretchLastSection(true); + pHeader->resizeSection(0, 120); // Name + QTreeView::resizeColumnToContents(1); // Map + QTreeView::resizeColumnToContents(2); // Bank + QTreeView::resizeColumnToContents(3); // Prog + QTreeView::resizeColumnToContents(4); // Engine + pHeader->resizeSection(5, 240); // File + QTreeView::resizeColumnToContents(6); // Nr + pHeader->resizeSection(7, 60); // Vol } -// Edit current item below the current one. -void qsamplerInstrumentList::editItemSlot (void) +// Destructor. +InstrumentListView::~InstrumentListView (void) { - QListViewItem *pListItem = QListView::selectedItem(); - if (pListItem == NULL) - return; - if (pListItem->rtti() == Item) { - qsamplerInstrument *pInstrument = NULL; - qsamplerInstrumentItem *pItem - = static_cast (pListItem); - if (pItem) - pInstrument = pItem->instrument(); - if (pInstrument) { - // Save current key values... - qsamplerInstrument oldInstrument(*pInstrument); - // Do the edit dance... - qsamplerInstrumentForm form(this); - form.setup(pInstrument); - if (form.exec()) { - // Commit... - pInstrument->mapInstrument(); - // Check whether we changed instrument key... - if (oldInstrument.map() == pInstrument->map() && - oldInstrument.bank() == pInstrument->bank() && - oldInstrument.prog() == pInstrument->prog()) { - // just update tree item... - pItem->update(); - } else { - // Unmap old instance... - oldInstrument.unmapInstrument(); - // Change item tree, whether applicable... - if (m_iMidiMap < 0 || m_iMidiMap == pInstrument->map()) { - // Add new brand item into view... - addItem(pInstrument, groupItem(pListItem)); - } else { - // Just remove/hide old one. - delete pItem; - } - } - // Notify we've changes... - emit instrumentsChanged(); - } - } - } - - selectionChangedSlot(); + delete m_pListModel; } -// Rename current group/item. -void qsamplerInstrumentList::renameSlot (void) +void InstrumentListView::setMidiMap ( int iMidiMap ) { - QListViewItem *pListItem = QListView::selectedItem(); - if (pListItem) - pListItem->startRename(0); - - selectionChangedSlot(); + m_pListModel->setMidiMap(iMidiMap); } -// Remove current group/item. -void qsamplerInstrumentList::deleteSlot (void) +int InstrumentListView::midiMap (void) const { - QListViewItem *pListItem = QListView::selectedItem(); - if (pListItem == NULL) - return; - - qsamplerMainForm *pMainForm = qsamplerMainForm::getInstance(); - if (pMainForm == NULL) - return; - - // Prompt user if this is for real... - qsamplerOptions *pOptions = pMainForm->options(); - if (pOptions && pOptions->bConfirmRemove) { - if (QMessageBox::warning(this, - QSAMPLER_TITLE ": " + tr("Warning"), - tr("Delete %1:\n\n" - "%2\n\n" - "Are you sure?") - .arg(pListItem->rtti() == Item ? tr("instrument") : tr("group")) - .arg(pListItem->text(0)), - tr("OK"), tr("Cancel")) > 0) - return; - } - - // Unmap instrument entry... - if (pListItem->rtti() == Item) { - qsamplerInstrumentItem *pItem - = static_cast (pListItem); - if (pItem && pItem->instrument()) { - pItem->instrument()->unmapInstrument(); - emit instrumentsChanged(); - } - } - - // Do it for real... - delete pListItem; - - selectionChangedSlot(); + return m_pListModel->midiMap(); } -// In-place selection slot. -void qsamplerInstrumentList::selectionChangedSlot (void) +const Instrument *InstrumentListView::addInstrument ( + int iMap, int iBank, int iProg ) { - qsamplerMainForm *pMainForm = qsamplerMainForm::getInstance(); - QListViewItem *pListItem = QListView::selectedItem(); - bool bEnabled = (pMainForm && pMainForm->client()); - m_pNewItemAction->setEnabled(bEnabled); - bEnabled = (bEnabled && pListItem != NULL); - m_pEditItemAction->setEnabled(bEnabled && pListItem->rtti() == Item); - m_pRenameAction->setEnabled(bEnabled); - m_pDeleteAction->setEnabled(bEnabled); -} - + m_pListModel->beginReset(); + const Instrument *pInstrument + = m_pListModel->addInstrument(iMap, iBank, iProg); + m_pListModel->endReset(); -// In-place activation slot. -void qsamplerInstrumentList::activatedSlot ( QListViewItem *pListItem ) -{ - // FIXME: Hope the list view item is the one selected. - if (pListItem && pListItem->rtti() == Item) - editItemSlot(); + return pInstrument; } -// In-place aliasing slot. -void qsamplerInstrumentList::renamedSlot ( QListViewItem *pListItem ) +void InstrumentListView::removeInstrument ( const Instrument *pInstrument ) { - if (pListItem->rtti() == Item) { - qsamplerInstrumentItem *pItem - = static_cast (pListItem); - if (pItem && pItem->instrument()) { - pItem->instrument()->setName(pListItem->text(0)); - pItem->instrument()->mapInstrument(); - emit instrumentsChanged(); - pItem->update(); - } - } + m_pListModel->beginReset(); + m_pListModel->removeInstrument(pInstrument); + m_pListModel->endReset(); } -// Context menu request event handler. -void qsamplerInstrumentList::contextMenuEvent ( - QContextMenuEvent *pContextMenuEvent ) +// Reposition the instrument in the model (called when map/bank/prg changed) +void InstrumentListView::updateInstrument ( const Instrument *pInstrument ) { - if (!m_pNewItemAction->isEnabled()) - return; - - QPopupMenu menu(this); - - // Construct context menu. - m_pNewItemAction->addTo(&menu); -// m_pNewGroupAction->addTo(&menu); - menu.insertSeparator(); - m_pEditItemAction->addTo(&menu); - m_pRenameAction->addTo(&menu); - m_pDeleteAction->addTo(&menu); - menu.insertSeparator(); - m_pRefreshAction->addTo(&menu); - - menu.exec(pContextMenuEvent->globalPos()); + m_pListModel->beginReset(); + m_pListModel->updateInstrument(pInstrument); + m_pListModel->endReset(); } -// General reloader. -void qsamplerInstrumentList::refresh (void) +// Refreshener. +void InstrumentListView::refresh (void) { - clear(); - - qsamplerMainForm *pMainForm = qsamplerMainForm::getInstance(); - if (pMainForm == NULL) - return; - if (pMainForm->client() == NULL) - return; - - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - - // Load the whole bunch of instrument items... - qsamplerInstrumentItem *pItem = NULL; - lscp_midi_instrument_t *pInstrs - = ::lscp_list_midi_instruments(pMainForm->client(), m_iMidiMap); - for (int iInstr = 0; pInstrs && pInstrs[iInstr].map >= 0; ++iInstr) { - int iMap = pInstrs[iInstr].map; - int iBank = pInstrs[iInstr].bank; - int iProg = pInstrs[iInstr].prog; - qsamplerInstrument *pInstrument - = new qsamplerInstrument(iMap, iBank, iProg); - if (pInstrument->getInstrument()) - pItem = new qsamplerInstrumentItem(this, pInstrument, pItem); - // Try to keep it snappy :) - QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput); - } + m_pListModel->beginReset(); + m_pListModel->refresh(); + m_pListModel->endReset(); +} - QApplication::restoreOverrideCursor(); - if (pInstrs == NULL && ::lscp_client_get_errno(pMainForm->client())) { - pMainForm->appendMessagesClient("lscp_list_midi_instruments"); - pMainForm->appendMessagesError(tr("Could not get current list of MIDI instrument mappings.\n\nSorry.")); - } - - selectionChangedSlot(); -} +} // namespace QSampler // end of qsamplerInstrumentList.cpp -