/[svn]/qsampler/trunk/src/qsamplerInstrumentList.cpp
ViewVC logotype

Diff of /qsampler/trunk/src/qsamplerInstrumentList.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1492 by schoenebeck, Mon Nov 19 21:08:18 2007 UTC revision 2069 by capela, Mon Mar 15 10:45:35 2010 UTC
# Line 1  Line 1 
1  // qsamplerInstrumentList.cpp  // qsamplerInstrumentList.cpp
2  //  //
3  /****************************************************************************  /****************************************************************************
4     Copyright (C) 2003-2007, rncbc aka Rui Nuno Capela. All rights reserved.     Copyright (C) 2003-2010, rncbc aka Rui Nuno Capela. All rights reserved.
5     Copyright (C) 2007, Christian Schoenebeck     Copyright (C) 2007, Christian Schoenebeck
6    
7     This program is free software; you can redistribute it and/or     This program is free software; you can redistribute it and/or
# Line 24  Line 24 
24  #include "qsamplerInstrumentList.h"  #include "qsamplerInstrumentList.h"
25    
26  #include "qsamplerInstrument.h"  #include "qsamplerInstrument.h"
 #include "qsamplerInstrumentForm.h"  
27    
28  #include "qsamplerOptions.h"  #include "qsamplerOptions.h"
29  #include "qsamplerMainForm.h"  #include "qsamplerMainForm.h"
30    
31  #include <qapplication.h>  #include <QApplication>
32  #include <qmessagebox.h>  #include <QCursor>
 #include <qeventloop.h>  
 #include <qaction.h>  
 #include <qcursor.h>  
 #include <qfileinfo.h>  
   
 #include <QMenu>  
33    
 // Needed for lroundf()  
 #include <math.h>  
34    
35  #ifndef CONFIG_ROUND  namespace QSampler {
36  static inline long lroundf ( float x )  
37    //-------------------------------------------------------------------------
38    // QSampler::InstrumentListModel - data model for MIDI prog mappings
39    //
40    
41    InstrumentListModel::InstrumentListModel ( QObject *pParent )
42            : QAbstractItemModel(pParent), m_iMidiMap(LSCP_MIDI_MAP_ALL)
43    {
44    //      QAbstractItemModel::reset();
45    }
46    
47    InstrumentListModel::~InstrumentListModel (void)
48    {
49            clear();
50    }
51    
52    
53    int InstrumentListModel::rowCount ( const QModelIndex& /*parent*/) const
54    {
55            int nrows = 0;
56    
57            if (m_iMidiMap == LSCP_MIDI_MAP_ALL) {
58                    InstrumentMap::const_iterator itMap = m_instruments.constBegin();
59                    for ( ; itMap != m_instruments.constEnd(); ++itMap)
60                            nrows += (*itMap).size();
61            } else {
62                    InstrumentMap::const_iterator itMap = m_instruments.find(m_iMidiMap);
63                    if (itMap != m_instruments.constEnd())
64                            nrows += (*itMap).size();
65            }
66    
67            return nrows;
68    }
69    
70    
71    int InstrumentListModel::columnCount ( const QModelIndex& /*parent*/) const
72    {
73            return 9;
74    }
75    
76    
77    QVariant InstrumentListModel::data (
78            const QModelIndex &index, int role ) const
79    {
80            if (!index.isValid())
81                    return QVariant();
82            const Instrument *pInstr
83                    = static_cast<Instrument *> (index.internalPointer());
84    
85            if (pInstr && role == Qt::DisplayRole) {
86                    switch (index.column()) {
87                            case 0: return pInstr->name();
88                            case 1: return QVariant::fromValue(pInstr->map());
89                            case 2: return QVariant::fromValue(pInstr->bank());
90                            case 3: return QVariant::fromValue(pInstr->prog() + 1);
91                            case 4: return pInstr->engineName();
92                            case 5: return pInstr->instrumentFile();
93                            case 6: return QVariant::fromValue(pInstr->instrumentNr());
94                            case 7: return QString::number(pInstr->volume() * 100.0) + " %";
95                            case 8: {
96                                    switch (pInstr->loadMode()) {
97                                            case 3: return tr("Persistent");
98                                            case 2: return tr("On Demand Hold");
99                                            case 1: return tr("On Demand");
100                                    }
101                            }
102                            default:
103                                    break;
104                    }
105            }
106    
107            return QVariant();
108    }
109    
110    
111    QModelIndex InstrumentListModel::index (
112            int row, int col, const QModelIndex& /*parent*/ ) const
113  {  {
114          if (x >= 0.0f)          const Instrument *pInstr = NULL;
115                  return long(x + 0.5f);  
116            if (m_iMidiMap == LSCP_MIDI_MAP_ALL) {
117                    int nrows = 0;
118                    InstrumentMap::const_iterator itMap = m_instruments.constBegin();
119                    for ( ; itMap != m_instruments.constEnd(); ++itMap) {
120                            const InstrumentList& list = *itMap;
121                            nrows += list.size();
122                            if (row < nrows) {
123                                    pInstr = list.at(row + list.size() - nrows);
124                                    break;
125                            }
126                    }
127            } else {
128                    // Resolve MIDI instrument map...
129                    InstrumentMap::const_iterator itMap     = m_instruments.find(m_iMidiMap);
130                    if (itMap != m_instruments.constEnd()) {
131                            const InstrumentList& list = *itMap;
132                            if (row < list.size())
133                                    pInstr = list.at(row);
134                    }
135            }
136    
137            if (pInstr)
138                    return createIndex(row, col, (void *) pInstr);
139          else          else
140                  return long(x - 0.5f);                  return QModelIndex();
141  }  }
 #endif  
142    
143  using namespace QSampler;  
144    QModelIndex InstrumentListModel::parent ( const QModelIndex& /*child*/ ) const
145    {
146            return QModelIndex();
147    }
148    
149    
150  //-------------------------------------------------------------------------  QVariant InstrumentListModel::headerData (
151  // MidiInstrumentsModel - data model for MIDI prog mappings (used for QTableView)          int section, Qt::Orientation orientation, int role ) const
152  //  {
153            if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
154                    switch (section) {
155                            case 0: return tr("Name");
156                            case 1: return tr("Map");
157                            case 2: return tr("Bank");
158                            case 3: return tr("Prog");
159                            case 4: return tr("Engine");
160                            case 5: return tr("File");
161                            case 6: return tr("Nr");
162                            case 7: return tr("Vol");
163                            case 8: return tr("Mode");
164                    }
165            }
166    
167  MidiInstrumentsModel::MidiInstrumentsModel(QObject* parent) : QAbstractTableModel(parent) {          return QAbstractItemModel::headerData(section, orientation, role);
     m_iMidiMap = LSCP_MIDI_MAP_ALL;  
168  }  }
169    
170  int MidiInstrumentsModel::rowCount(const QModelIndex& /*parent*/) const {  
171      if (m_iMidiMap == LSCP_MIDI_MAP_ALL) {  void InstrumentListModel::setMidiMap ( int iMidiMap )
172          int n = 0;  {
173          for (InstrumentsMap::const_iterator itMap = instruments.begin(); itMap != instruments.end(); ++itMap)          if (iMidiMap < 0)
174              n += (*itMap).size();                  iMidiMap = LSCP_MIDI_MAP_ALL;
175          return n;  
176      }          m_iMidiMap = iMidiMap;
     InstrumentsMap::const_iterator itMap = instruments.find(m_iMidiMap);  
     if (itMap == instruments.end()) return 0;  
     return (*itMap).size();  
 }  
   
 int MidiInstrumentsModel::columnCount(const QModelIndex& /*parent*/) const {  
     return 9;  
 }  
   
 QVariant MidiInstrumentsModel::data(const QModelIndex &index, int role) const {  
     if (!index.isValid()) return QVariant();  
   
     const qsamplerInstrument* pInstr = NULL;  
   
     if (m_iMidiMap == LSCP_MIDI_MAP_ALL) {  
         int n = 0;  
         for (InstrumentsMap::const_iterator itMap = instruments.begin(); itMap != instruments.end(); ++itMap) {  
             n += (*itMap).size();  
             if (index.row() < n)  
                 pInstr = &(*itMap)[index.row() + (*itMap).size() - n];  
         }  
     } else {  
         // resolve MIDI instrument map  
         InstrumentsMap::const_iterator itMap = instruments.find(m_iMidiMap);  
         if (itMap == instruments.end()) return QVariant();  
         // resolve instrument in that map  
         if (index.row() >= (*itMap).size()) return QVariant();  
         pInstr = &(*itMap)[index.row()];  
     }  
   
     if (!pInstr) return QVariant();  
   
     if (role == Qt::UserRole) {  
         return QVariant::fromValue((void*)pInstr);  
     }  
   
     if (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());  
             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 QObject::tr("Persistent");  
                     case 2: return QObject::tr("On Demand Hold");  
                     case 1: return QObject::tr("On Demand");  
                     default: return QVariant();  
                 }  
             }  
             default: return QVariant();  
         }  
     }  
   
     return QVariant();  
 }  
   
 QVariant MidiInstrumentsModel::headerData(int section, Qt::Orientation orientation, int role) const {  
     if (orientation != Qt::Horizontal || role != Qt::DisplayRole)  
         return QVariant();  
   
     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");  
         default: return QVariant();  
     }  
 }  
   
 qsamplerInstrument* MidiInstrumentsModel::addInstrument(int iMap, int iBank, int iProg) {  
     // Check it there's already one instrument item  
     // with the very same key (bank, program);  
     // if yes, just remove it without prejudice...  
     for (int i = 0; i < instruments[iMap].size(); i++) {  
         if (  
             instruments[iMap][i].bank() == iBank &&  
             instruments[iMap][i].prog() == iProg  
         ) {  
             instruments[iMap].removeAt(i);  
             break;  
         }  
     }  
   
     // resolve the appropriate place, we keep the list sorted that way ...  
     int i = 0;  
     for (; i < instruments[iMap].size(); i++)  
         if (  
             iBank > instruments[iMap][i].bank() ||  
             ( iBank == instruments[iMap][i].bank() &&  
               iProg > instruments[iMap][i].prog() )  
         ) break;  
   
     instruments[iMap].insert(i, qsamplerInstrument(iMap, iBank, iProg));  
     qsamplerInstrument& instr = instruments[iMap][i];  
     if (!instr.getInstrument())  
         instruments[iMap].removeAt(i);  
   
     return &instr;  
 }  
   
 void MidiInstrumentsModel::removeInstrument(const qsamplerInstrument& instrument) {  
     const int iMap  = instrument.map();  
     const int iBank = instrument.bank();  
     const int iProg = instrument.prog();  
     for (int i = 0; i < instruments[iMap].size(); i++) {  
         if (  
             instruments[iMap][i].bank() == iBank &&  
             instruments[iMap][i].prog() == iProg  
         ) {  
             instruments[iMap].removeAt(i);  
             break;  
         }  
     }  
 }  
   
 // reposition the instrument in the model (called when map/bank/prg changed)  
 void MidiInstrumentsModel::resort(const qsamplerInstrument instrument) {  
     const int iMap  = instrument.map();  
     const int iBank = instrument.bank();  
     const int iProg = instrument.prog();  
     // remove given instrument from its current list  
     removeInstrument(instrument);  
     // re-add the instrument  
     addInstrument(iMap, iBank, iProg);  
 }  
   
 void MidiInstrumentsModel::setMidiMap(int iMidiMap) {  
     if (iMidiMap < 0)  
         iMidiMap = LSCP_MIDI_MAP_ALL;  
   
     m_iMidiMap = iMidiMap;  
177  }  }
178    
179  int MidiInstrumentsModel::midiMap() const {  
180      return m_iMidiMap;  int InstrumentListModel::midiMap (void) const
181    {
182            return m_iMidiMap;
183    }
184    
185    
186    const Instrument *InstrumentListModel::addInstrument (
187            int iMap, int iBank, int iProg )
188    {
189            // Check it there's already one instrument item
190            // with the very same key (bank, program);
191            // if yes, just remove it without prejudice...
192            InstrumentList& list = m_instruments[iMap];
193            for (int i = 0; i < list.size(); ++i) {
194                    const Instrument *pInstr = list.at(i);
195                    if (pInstr->bank() == iBank && pInstr->prog() == iProg) {
196                            delete pInstr;
197                            list.removeAt(i);
198                            break;
199                    }
200            }
201    
202            // Resolve the appropriate place, we keep the list sorted that way...
203            int i = 0;
204            for ( ; i < list.size(); ++i) {
205                    const Instrument *pInstr = list.at(i);
206                    if (iBank < pInstr->bank()
207                            || (iBank == pInstr->bank() && iProg < pInstr->prog())) {
208                            break;
209                    }
210            }
211    
212            Instrument *pInstr = new Instrument(iMap, iBank, iProg);
213            if (pInstr->getInstrument()) {
214                    list.insert(i, pInstr);
215            } else {
216                    delete pInstr;
217                    pInstr = NULL;
218            }
219    
220            return pInstr;
221  }  }
222    
 void MidiInstrumentsModel::refresh() {  
         instruments.clear();  
223    
224          MainForm* pMainForm = MainForm::getInstance();  void InstrumentListModel::removeInstrument ( const Instrument *pInstrument )
225    {
226            const int iMap  = pInstrument->map();
227            const int iBank = pInstrument->bank();
228            const int iProg = pInstrument->prog();
229    
230            if (m_instruments.contains(iMap)) {
231                    InstrumentList& list = m_instruments[iMap];
232                    for (int i = 0; i < list.size(); ++i) {
233                            const Instrument *pInstr = list.at(i);
234                            if (pInstr->bank() == iBank && pInstr->prog() == iProg) {
235                                    delete pInstr;
236                                    list.removeAt(i);
237                                    break;
238                            }
239                    }
240            }
241    }
242    
243    
244    // Reposition the instrument in the model (called when map/bank/prg changed)
245    void InstrumentListModel::updateInstrument ( const Instrument *pInstrument )
246    {
247            const int iMap  = pInstrument->map();
248            const int iBank = pInstrument->bank();
249            const int iProg = pInstrument->prog();
250    
251            // Remove given instrument from its current list...
252            removeInstrument(pInstrument);
253    
254            // Re-add the instrument...
255            addInstrument(iMap, iBank, iProg);
256    }
257    
258    
259    void InstrumentListModel::refresh (void)
260    {
261            MainForm *pMainForm = MainForm::getInstance();
262          if (pMainForm == NULL)          if (pMainForm == NULL)
263                  return;                  return;
264          if (pMainForm->client() == NULL)          if (pMainForm->client() == NULL)
# Line 227  void MidiInstrumentsModel::refresh() { Line 266  void MidiInstrumentsModel::refresh() {
266    
267          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
268    
269            clear();
270    
271          // Load the whole bunch of instrument items...          // Load the whole bunch of instrument items...
272          lscp_midi_instrument_t* pInstrs          lscp_midi_instrument_t *pInstrs
273                  = ::lscp_list_midi_instruments(pMainForm->client(), m_iMidiMap);                  = ::lscp_list_midi_instruments(pMainForm->client(), m_iMidiMap);
274          for (int iInstr = 0; pInstrs && pInstrs[iInstr].map >= 0; ++iInstr) {          for (int iInstr = 0; pInstrs && pInstrs[iInstr].map >= 0; ++iInstr) {
275                  const int iMap  = pInstrs[iInstr].map;                  const int iMap  = pInstrs[iInstr].map;
# Line 236  void MidiInstrumentsModel::refresh() { Line 277  void MidiInstrumentsModel::refresh() {
277                  const int iProg = pInstrs[iInstr].prog;                  const int iProg = pInstrs[iInstr].prog;
278                  addInstrument(iMap, iBank, iProg);                  addInstrument(iMap, iBank, iProg);
279                  // Try to keep it snappy :)                  // Try to keep it snappy :)
280                  QApplication::processEvents(QEventLoop::ExcludeUserInput);                  QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
281          }          }
282    
283          QApplication::restoreOverrideCursor();          QApplication::restoreOverrideCursor();
284    
285          if (pInstrs == NULL && ::lscp_client_get_errno(pMainForm->client())) {          if (pInstrs == NULL && ::lscp_client_get_errno(pMainForm->client())) {
286                  pMainForm->appendMessagesClient("lscp_list_midi_instruments");                  pMainForm->appendMessagesClient("lscp_list_midi_instruments");
287                  pMainForm->appendMessagesError(tr("Could not get current list of MIDI instrument mappings.\n\nSorry."));                  pMainForm->appendMessagesError(
288                            tr("Could not get current list of MIDI instrument mappings.\n\nSorry."));
289          }          }
290    }
291    
292          // inform the outer world (QTableView) that our data changed  void InstrumentListModel::beginReset (void)
293          QAbstractTableModel::reset();  {
294    #if QT_VERSION >= 0x040600
295            QAbstractItemModel::beginResetModel();
296    #endif
297    }
298    
299    void InstrumentListModel::endReset (void)
300    {
301    #if QT_VERSION >= 0x040600
302            QAbstractItemModel::endResetModel();
303    #else
304            QAbstractItemModel::reset();
305    #endif
306    }
307    
308    
309    // Map clear.
310    void InstrumentListModel::clear (void)
311    {
312            InstrumentMap::iterator itMap = m_instruments.begin();
313            for ( ; itMap != m_instruments.end(); ++itMap) {
314                    InstrumentList& list = itMap.value();
315                    qDeleteAll(list);
316                    list.clear();
317            }
318    
319            m_instruments.clear();
320  }  }
321    
322    
323  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
324  // MidiInstrumentsDelegate - table cell renderer for MIDI prog mappings  // QSampler::InstrumentListView - list view for MIDI prog mappings
325  // (doesn't actually do anything ATM, but is already there for a future  //
 // cell editor widget implementation)  
326    
327  MidiInstrumentsDelegate::MidiInstrumentsDelegate(QObject* parent) : QItemDelegate(parent) {  // Constructor.
328    InstrumentListView::InstrumentListView ( QWidget *pParent )
329            : QTreeView(pParent)
330    {
331            m_pListModel = new InstrumentListModel(this);
332    
333            QTreeView::setModel(m_pListModel);
334    
335            QTreeView::setRootIsDecorated(false);
336            QTreeView::setUniformRowHeights(true);
337            QTreeView::setAlternatingRowColors(true);
338            QTreeView::setSelectionBehavior(QAbstractItemView::SelectRows);
339            QTreeView::setSelectionMode(QAbstractItemView::SingleSelection);
340            QTreeView::setItemsExpandable(false);
341    
342            QHeaderView *pHeader = QTreeView::header();
343            pHeader->setDefaultAlignment(Qt::AlignLeft);
344            pHeader->setMovable(false);
345            pHeader->setStretchLastSection(true);
346            pHeader->resizeSection(0, 120);                 // Name
347            QTreeView::resizeColumnToContents(1);   // Map
348            QTreeView::resizeColumnToContents(2);   // Bank
349            QTreeView::resizeColumnToContents(3);   // Prog
350            QTreeView::resizeColumnToContents(4);   // Engine
351            pHeader->resizeSection(5, 240);                 // File
352            QTreeView::resizeColumnToContents(6);   // Nr
353            pHeader->resizeSection(7, 60);                  // Vol
354    }
355    
356    
357    // Destructor.
358    InstrumentListView::~InstrumentListView (void)
359    {
360            delete m_pListModel;
361    }
362    
363    
364    void InstrumentListView::setMidiMap ( int iMidiMap )
365    {
366            m_pListModel->setMidiMap(iMidiMap);
367    }
368    
369    
370    int InstrumentListView::midiMap (void) const
371    {
372            return m_pListModel->midiMap();
373  }  }
374    
375  QWidget* MidiInstrumentsDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const {  
376      return QItemDelegate::createEditor(parent, option, index);  const Instrument *InstrumentListView::addInstrument (
377      //return new QLabel(index.model()->data(index, Qt::DisplayRole).toString(), parent);          int iMap, int iBank, int iProg )
378    {
379            m_pListModel->beginReset();
380            const Instrument *pInstrument
381                    = m_pListModel->addInstrument(iMap, iBank, iProg);
382            m_pListModel->endReset();
383    
384            return pInstrument;
385  }  }
386    
387  void MidiInstrumentsDelegate::setEditorData(QWidget* /*editor*/, const QModelIndex& /*index*/) const {  
388    void InstrumentListView::removeInstrument ( const Instrument *pInstrument )
389    {
390            m_pListModel->beginReset();
391            m_pListModel->removeInstrument(pInstrument);
392            m_pListModel->endReset();
393  }  }
394    
395  void MidiInstrumentsDelegate::setModelData(QWidget* /*editor*/, QAbstractItemModel* /*model*/, const QModelIndex& /*index*/) const {  
396    // Reposition the instrument in the model (called when map/bank/prg changed)
397    void InstrumentListView::updateInstrument ( const Instrument *pInstrument )
398    {
399            m_pListModel->beginReset();
400            m_pListModel->updateInstrument(pInstrument);
401            m_pListModel->endReset();
402  }  }
403    
404  void MidiInstrumentsDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const {  
405      QItemDelegate::updateEditorGeometry(editor, option, index);  // Refreshener.
406      //if (editor) editor->setGeometry(option.rect);  void InstrumentListView::refresh (void)
407    {
408            m_pListModel->beginReset();
409            m_pListModel->refresh();
410            m_pListModel->endReset();
411  }  }
412    
413    
414    } // namespace QSampler
415    
416    
417  // end of qsamplerInstrumentList.cpp  // end of qsamplerInstrumentList.cpp

Legend:
Removed from v.1492  
changed lines
  Added in v.2069

  ViewVC Help
Powered by ViewVC