/[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 1509 by capela, Thu Nov 22 11:10:44 2007 UTC revision 2070 by capela, Mon Mar 15 17:06:46 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>  #include <QApplication>
 #include <QMessageBox>  
 #include <QMenu>  
 #include <QAction>  
32  #include <QCursor>  #include <QCursor>
 #include <QFileInfo>  
33    
 // Needed for lroundf()  
 #include <math.h>  
   
 #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  
   
 using namespace QSampler;  
34    
35    namespace QSampler {
36    
37  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
38  // MidiInstrumentsModel - data model for MIDI prog mappings (used for QTableView)  // QSampler::InstrumentListModel - data model for MIDI prog mappings
39  //  //
40    
41  MidiInstrumentsModel::MidiInstrumentsModel ( QObject* pParent)  InstrumentListModel::InstrumentListModel ( QObject *pParent )
42          : QAbstractTableModel(pParent)          : QAbstractItemModel(pParent), m_iMidiMap(LSCP_MIDI_MAP_ALL)
43  {  {
44          m_iMidiMap = LSCP_MIDI_MAP_ALL;  //      QAbstractItemModel::reset();
45  }  }
46    
47    InstrumentListModel::~InstrumentListModel (void)
48    {
49            clear();
50    }
51    
52  int MidiInstrumentsModel::rowCount ( const QModelIndex& /*parent*/) const  
53    int InstrumentListModel::rowCount ( const QModelIndex& /*parent*/) const
54  {  {
55            int nrows = 0;
56    
57          if (m_iMidiMap == LSCP_MIDI_MAP_ALL) {          if (m_iMidiMap == LSCP_MIDI_MAP_ALL) {
58                  int n = 0;                  InstrumentMap::const_iterator itMap = m_instruments.constBegin();
59                  for (InstrumentsMap::const_iterator itMap = m_instruments.begin();                  for ( ; itMap != m_instruments.constEnd(); ++itMap)
60                                  itMap != m_instruments.end(); ++itMap)                          nrows += (*itMap).size();
61                          n += (*itMap).size();          } else {
62                  return n;                  InstrumentMap::const_iterator itMap = m_instruments.find(m_iMidiMap);
63                    if (itMap != m_instruments.constEnd())
64                            nrows += (*itMap).size();
65          }          }
66          InstrumentsMap::const_iterator itMap = m_instruments.find(m_iMidiMap);  
67          if (itMap == m_instruments.end()) return 0;          return nrows;
         return (*itMap).size();  
68  }  }
69    
70    
71  int MidiInstrumentsModel::columnCount ( const QModelIndex& /*parent*/) const  int InstrumentListModel::columnCount ( const QModelIndex& /*parent*/) const
72  {  {
73          return 9;          return 9;
74  }  }
75    
76    
77  QVariant MidiInstrumentsModel::data ( const QModelIndex &index, int role ) const  QVariant InstrumentListModel::data (
78            const QModelIndex &index, int role ) const
79  {  {
80          if (!index.isValid())          if (!index.isValid())
81                  return QVariant();                  return QVariant();
82            const Instrument *pInstr
83                    = static_cast<Instrument *> (index.internalPointer());
84    
85          const qsamplerInstrument* pInstr = NULL;          if (pInstr && role == Qt::DisplayRole) {
   
         if (m_iMidiMap == LSCP_MIDI_MAP_ALL) {  
                 int n = 0;  
                 for (InstrumentsMap::const_iterator itMap = m_instruments.begin();  
                                 itMap != m_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 = m_instruments.find(m_iMidiMap);  
                 if (itMap == m_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) {  
86                  switch (index.column()) {                  switch (index.column()) {
87                          case 0: return pInstr->name();                          case 0: return pInstr->name();
88                          case 1: return QVariant::fromValue(pInstr->map());                          case 1: return QVariant::fromValue(pInstr->map());
89                          case 2: return QVariant::fromValue(pInstr->bank());                          case 2: return QVariant::fromValue(pInstr->bank());
90                          case 3: return QVariant::fromValue(pInstr->prog());                          case 3: return QVariant::fromValue(pInstr->prog() + 1);
91                          case 4: return pInstr->engineName();                          case 4: return pInstr->engineName();
92                          case 5: return pInstr->instrumentFile();                          case 5: return pInstr->instrumentFile();
93                          case 6: return QVariant::fromValue(pInstr->instrumentNr());                          case 6: return QVariant::fromValue(pInstr->instrumentNr());
94                          case 7: return QString::number(pInstr->volume() * 100.0) + " %";                          case 7: return QString::number(pInstr->volume() * 100.0) + " %";
95                          case 8: {                          case 8: {
96                                  switch (pInstr->loadMode()) {                                  switch (pInstr->loadMode()) {
97                                          case 3: return QObject::tr("Persistent");                                          case 3: return tr("Persistent");
98                                          case 2: return QObject::tr("On Demand Hold");                                          case 2: return tr("On Demand Hold");
99                                          case 1: return QObject::tr("On Demand");                                          case 1: return tr("On Demand");
                                         default: return QVariant();  
100                                  }                                  }
101                          }                          }
102                          default: return QVariant();                          default:
103                                    break;
104                  }                  }
105          }          }
106    
# Line 140  QVariant MidiInstrumentsModel::data ( co Line 108  QVariant MidiInstrumentsModel::data ( co
108  }  }
109    
110    
111  QVariant MidiInstrumentsModel::headerData (  QModelIndex InstrumentListModel::index (
112          int section, Qt::Orientation orientation, int role ) const          int row, int col, const QModelIndex& /*parent*/ ) const
113  {  {
114          if (orientation != Qt::Horizontal || role != Qt::DisplayRole)          const Instrument *pInstr = NULL;
115                  return QVariant();  
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
140                    return QModelIndex();
141    }
142    
143    
144    QModelIndex InstrumentListModel::parent ( const QModelIndex& /*child*/ ) const
145    {
146            return QModelIndex();
147    }
148    
149          switch (section) {  
150                  case 0: return tr("Name");  QVariant InstrumentListModel::headerData (
151                  case 1: return tr("Map");          int section, Qt::Orientation orientation, int role ) const
152                  case 2: return tr("Bank");  {
153                  case 3: return tr("Prog");          if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
154                  case 4: return tr("Engine");                  switch (section) {
155                  case 5: return tr("File");                          case 0: return tr("Name");
156                  case 6: return tr("Nr");                          case 1: return tr("Map");
157                  case 7: return tr("Vol");                          case 2: return tr("Bank");
158                  case 8: return tr("Mode");                          case 3: return tr("Prog");
159                  default: return QVariant();                          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            return QAbstractItemModel::headerData(section, orientation, role);
168  }  }
169    
170    
171  qsamplerInstrument* MidiInstrumentsModel::addInstrument (  void InstrumentListModel::setMidiMap ( int iMidiMap )
172    {
173            if (iMidiMap < 0)
174                    iMidiMap = LSCP_MIDI_MAP_ALL;
175    
176            m_iMidiMap = iMidiMap;
177    }
178    
179    
180    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 )          int iMap, int iBank, int iProg )
188  {  {
189          // Check it there's already one instrument item          // Check it there's already one instrument item
190          // with the very same key (bank, program);          // with the very same key (bank, program);
191          // if yes, just remove it without prejudice...          // if yes, just remove it without prejudice...
192          for (int i = 0; i < m_instruments[iMap].size(); i++) {          InstrumentList& list = m_instruments[iMap];
193                  if (m_instruments[iMap][i].bank() == iBank &&          for (int i = 0; i < list.size(); ++i) {
194                          m_instruments[iMap][i].prog() == iProg) {                  const Instrument *pInstr = list.at(i);
195                          m_instruments[iMap].removeAt(i);                  if (pInstr->bank() == iBank && pInstr->prog() == iProg) {
196                            delete pInstr;
197                            list.removeAt(i);
198                          break;                          break;
199                  }                  }
200          }          }
201    
202          // resolve the appropriate place, we keep the list sorted that way ...          // Resolve the appropriate place, we keep the list sorted that way...
203          int i = 0;          int i = 0;
204          for (; i < m_instruments[iMap].size(); i++)          for ( ; i < list.size(); ++i) {
205                  if (iBank > m_instruments[iMap][i].bank()                  const Instrument *pInstr = list.at(i);
206                          || (iBank == m_instruments[iMap][i].bank() &&                  if (iBank < pInstr->bank()
207                                  iProg > m_instruments[iMap][i].prog()))                          || (iBank == pInstr->bank() && iProg < pInstr->prog())) {
208                          break;                          break;
209                    }
210            }
211    
212          m_instruments[iMap].insert(i, qsamplerInstrument(iMap, iBank, iProg));          Instrument *pInstr = new Instrument(iMap, iBank, iProg);
213          qsamplerInstrument& instr = m_instruments[iMap][i];          if (pInstr->getInstrument()) {
214          if (!instr.getInstrument())                  list.insert(i, pInstr);
215                  m_instruments[iMap].removeAt(i);          } else {
216                    delete pInstr;
217                    pInstr = NULL;
218            }
219    
220          return &instr;          return pInstr;
221  }  }
222    
223    
224  void MidiInstrumentsModel::removeInstrument (  void InstrumentListModel::removeInstrument ( Instrument *pInstrument )
         const qsamplerInstrument& instrument )  
225  {  {
226          const int iMap  = instrument.map();          const int iMap  = pInstrument->map();
227          const int iBank = instrument.bank();          const int iBank = pInstrument->bank();
228          const int iProg = instrument.prog();          const int iProg = pInstrument->prog();
229          for (int i = 0; i < m_instruments[iMap].size(); i++) {  
230                  if (m_instruments[iMap][i].bank() == iBank &&          if (m_instruments.contains(iMap)) {
231                          m_instruments[iMap][i].prog() == iProg) {                  InstrumentList& list = m_instruments[iMap];
232                          m_instruments[iMap].removeAt(i);                  for (int i = 0; i < list.size(); ++i) {
233                          break;                          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)  void InstrumentListModel::updateInstrument ( Instrument *pInstrument )
 void MidiInstrumentsModel::resort ( const qsamplerInstrument instrument )  
245  {  {
246          const int iMap  = instrument.map();          pInstrument->getInstrument();
         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);  
247  }  }
248    
249    
250  void MidiInstrumentsModel::setMidiMap ( int iMidiMap )  // Reposition the instrument in the model (called when map/bank/prg changed)
251    void InstrumentListModel::resortInstrument ( Instrument *pInstrument )
252  {  {
253          if (iMidiMap < 0)          const int iMap  = pInstrument->map();
254                  iMidiMap = LSCP_MIDI_MAP_ALL;          const int iBank = pInstrument->bank();
255            const int iProg = pInstrument->prog();
         m_iMidiMap = iMidiMap;  
 }  
256    
257            // Remove given instrument from its current list...
258            removeInstrument(pInstrument);
259    
260  int MidiInstrumentsModel::midiMap (void) const          // Re-add the instrument...
261  {          addInstrument(iMap, iBank, iProg);
         return m_iMidiMap;  
262  }  }
263    
 void MidiInstrumentsModel::refresh (void)  
 {  
         m_instruments.clear();  
264    
265          MainForm* pMainForm = MainForm::getInstance();  void InstrumentListModel::refresh (void)
266    {
267            MainForm *pMainForm = MainForm::getInstance();
268          if (pMainForm == NULL)          if (pMainForm == NULL)
269                  return;                  return;
270          if (pMainForm->client() == NULL)          if (pMainForm->client() == NULL)
# Line 247  void MidiInstrumentsModel::refresh (void Line 272  void MidiInstrumentsModel::refresh (void
272    
273          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));          QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
274    
275            clear();
276    
277          // Load the whole bunch of instrument items...          // Load the whole bunch of instrument items...
278          lscp_midi_instrument_t* pInstrs          lscp_midi_instrument_t *pInstrs
279                  = ::lscp_list_midi_instruments(pMainForm->client(), m_iMidiMap);                  = ::lscp_list_midi_instruments(pMainForm->client(), m_iMidiMap);
280          for (int iInstr = 0; pInstrs && pInstrs[iInstr].map >= 0; ++iInstr) {          for (int iInstr = 0; pInstrs && pInstrs[iInstr].map >= 0; ++iInstr) {
281                  const int iMap  = pInstrs[iInstr].map;                  const int iMap  = pInstrs[iInstr].map;
# Line 266  void MidiInstrumentsModel::refresh (void Line 293  void MidiInstrumentsModel::refresh (void
293                  pMainForm->appendMessagesError(                  pMainForm->appendMessagesError(
294                          tr("Could not get current list of MIDI instrument mappings.\n\nSorry."));                          tr("Could not get current list of MIDI instrument mappings.\n\nSorry."));
295          }          }
296    }
297    
298    void InstrumentListModel::beginReset (void)
299    {
300    #if QT_VERSION >= 0x040600
301            QAbstractItemModel::beginResetModel();
302    #endif
303    }
304    
305    void InstrumentListModel::endReset (void)
306    {
307    #if QT_VERSION >= 0x040600
308            QAbstractItemModel::endResetModel();
309    #else
310            QAbstractItemModel::reset();
311    #endif
312    }
313    
314    
315    // Map clear.
316    void InstrumentListModel::clear (void)
317    {
318            InstrumentMap::iterator itMap = m_instruments.begin();
319            for ( ; itMap != m_instruments.end(); ++itMap) {
320                    InstrumentList& list = itMap.value();
321                    qDeleteAll(list);
322                    list.clear();
323            }
324    
325          // inform the outer world (QTableView) that our data changed          m_instruments.clear();
         QAbstractTableModel::reset();  
326  }  }
327    
328    
329  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
330  // MidiInstrumentsDelegate - table cell renderer for MIDI prog mappings  // QSampler::InstrumentListView - list view for MIDI prog mappings
331  // (doesn't actually do anything ATM, but is already there for a future  //
 // cell editor widget implementation)  
332    
333  MidiInstrumentsDelegate::MidiInstrumentsDelegate ( QObject* pParent )  // Constructor.
334          : QItemDelegate(pParent)  InstrumentListView::InstrumentListView ( QWidget *pParent )
335            : QTreeView(pParent)
336  {  {
337            m_pListModel = new InstrumentListModel(this);
338    
339            QTreeView::setModel(m_pListModel);
340    
341            QTreeView::setRootIsDecorated(false);
342            QTreeView::setUniformRowHeights(true);
343            QTreeView::setAlternatingRowColors(true);
344            QTreeView::setSelectionBehavior(QAbstractItemView::SelectRows);
345            QTreeView::setSelectionMode(QAbstractItemView::SingleSelection);
346            QTreeView::setItemsExpandable(false);
347    
348            QHeaderView *pHeader = QTreeView::header();
349            pHeader->setDefaultAlignment(Qt::AlignLeft);
350            pHeader->setMovable(false);
351            pHeader->setStretchLastSection(true);
352            pHeader->resizeSection(0, 120);                 // Name
353            QTreeView::resizeColumnToContents(1);   // Map
354            QTreeView::resizeColumnToContents(2);   // Bank
355            QTreeView::resizeColumnToContents(3);   // Prog
356            QTreeView::resizeColumnToContents(4);   // Engine
357            pHeader->resizeSection(5, 240);                 // File
358            QTreeView::resizeColumnToContents(6);   // Nr
359            pHeader->resizeSection(7, 60);                  // Vol
360  }  }
361    
362    
363  QWidget* MidiInstrumentsDelegate::createEditor ( QWidget* pParent,  // Destructor.
364          const QStyleOptionViewItem& option, const QModelIndex& index ) const  InstrumentListView::~InstrumentListView (void)
365  {  {
366          return QItemDelegate::createEditor(pParent, option, index);          delete m_pListModel;
 //      return new QLabel(index.model()->data(index, Qt::DisplayRole).toString(), parent);  
367  }  }
368    
369    
370  void MidiInstrumentsDelegate::setEditorData ( QWidget */*pEditor*/,  void InstrumentListView::setMidiMap ( int iMidiMap )
         const QModelIndex& /*index*/) const  
371  {  {
372            m_pListModel->setMidiMap(iMidiMap);
373  }  }
374    
375    
376  void MidiInstrumentsDelegate::setModelData ( QWidget */*pEditor*/,  int InstrumentListView::midiMap (void) const
         QAbstractItemModel* /*model*/, const QModelIndex& /*index*/) const  
377  {  {
378            return m_pListModel->midiMap();
379  }  }
380    
381    
382  void MidiInstrumentsDelegate::updateEditorGeometry ( QWidget *pEditor,  const Instrument *InstrumentListView::addInstrument (
383          const QStyleOptionViewItem& option, const QModelIndex& index) const          int iMap, int iBank, int iProg )
384  {  {
385          QItemDelegate::updateEditorGeometry(pEditor, option, index);          m_pListModel->beginReset();
386  //      if (pEditor) pEditor->setGeometry(option.rect);          const Instrument *pInstrument
387                    = m_pListModel->addInstrument(iMap, iBank, iProg);
388            m_pListModel->endReset();
389    
390            return pInstrument;
391  }  }
392    
393    
394    void InstrumentListView::removeInstrument ( Instrument *pInstrument )
395    {
396            m_pListModel->beginReset();
397            m_pListModel->removeInstrument(pInstrument);
398            m_pListModel->endReset();
399    }
400    
401    
402    void InstrumentListView::updateInstrument ( Instrument *pInstrument )
403    {
404            m_pListModel->beginReset();
405            m_pListModel->updateInstrument(pInstrument);
406            m_pListModel->endReset();
407    }
408    
409    
410    // Reposition the instrument in the model (called when map/bank/prg changed)
411    void InstrumentListView::resortInstrument ( Instrument *pInstrument )
412    {
413            m_pListModel->beginReset();
414            m_pListModel->resortInstrument(pInstrument);
415            m_pListModel->endReset();
416    }
417    
418    
419    // Refreshener.
420    void InstrumentListView::refresh (void)
421    {
422            m_pListModel->beginReset();
423            m_pListModel->refresh();
424            m_pListModel->endReset();
425    }
426    
427    
428    } // namespace QSampler
429    
430    
431  // end of qsamplerInstrumentList.cpp  // end of qsamplerInstrumentList.cpp

Legend:
Removed from v.1509  
changed lines
  Added in v.2070

  ViewVC Help
Powered by ViewVC