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

Legend:
Removed from v.1523  
changed lines
  Added in v.2387

  ViewVC Help
Powered by ViewVC