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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 969 - (show annotations) (download)
Wed Dec 6 19:38:02 2006 UTC (17 years, 4 months ago) by capela
File size: 16085 byte(s)
* Fixed MIDI instrument volume setting.
* Enforcing uniqueness of bank and program key pair
  while editing the MIDI instrument map.

1 // qsamplerInstrumentList.cpp
2 //
3 /****************************************************************************
4 Copyright (C) 2003-2005, rncbc aka Rui Nuno Capela. All rights reserved.
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 *****************************************************************************/
21
22 #include "qsamplerAbout.h"
23 #include "qsamplerInstrumentList.h"
24
25 #include "qsamplerInstrument.h"
26 #include "qsamplerInstrumentForm.h"
27
28 #include "qsamplerMainForm.h"
29
30 #include <qaction.h>
31 #include <qfileinfo.h>
32 #include <qpopupmenu.h>
33
34 // Needed for lroundf()
35 #include <math.h>
36
37
38 //----------------------------------------------------------------------
39 // class qsamplerInstrumentGroup -- custom group list view item.
40 //
41
42 // Constructors.
43 qsamplerInstrumentGroup::qsamplerInstrumentGroup (
44 qsamplerInstrumentList *pListView, const QString& sName,
45 QListViewItem *pItemAfter )
46 : QListViewItem(pListView, pItemAfter ? pItemAfter : pListView->lastItem())
47 {
48 QListViewItem::setRenameEnabled(0, true);
49
50 QListViewItem::setPixmap(0, QPixmap::fromMimeSource("itemGroup.png"));
51 QListViewItem::setText(0, sName);
52 }
53
54
55 qsamplerInstrumentGroup::qsamplerInstrumentGroup (
56 qsamplerInstrumentGroup *pGroupItem, const QString& sName )
57 : QListViewItem(pGroupItem, sName)
58 {
59 QListViewItem::setRenameEnabled(0, true);
60
61 QListViewItem::setPixmap(0, QPixmap::fromMimeSource("itemGroup.png"));
62 }
63
64
65 // Default destructor.
66 qsamplerInstrumentGroup::~qsamplerInstrumentGroup (void)
67 {
68 }
69
70
71 // Instance accessors.
72 void qsamplerInstrumentGroup::setName ( const QString& sName )
73 {
74 QListViewItem::setText(0, sName);
75 }
76
77
78 QString qsamplerInstrumentGroup::name (void) const
79 {
80 return QListViewItem::text(0);
81 }
82
83
84 qsamplerInstrumentGroup *qsamplerInstrumentGroup::groupItem (void) const
85 {
86 QListViewItem *pParent = QListViewItem::parent();
87 while (pParent && pParent->rtti() != qsamplerInstrumentList::Group)
88 pParent = pParent->parent();
89 return static_cast<qsamplerInstrumentGroup *> (pParent);
90 }
91
92
93 qsamplerInstrumentList *qsamplerInstrumentGroup::listView (void) const
94 {
95 return static_cast<qsamplerInstrumentList *> (QListViewItem::listView());
96 }
97
98
99 // To show up whether its open or not.
100 void qsamplerInstrumentGroup::setOpen ( bool bOpen )
101 {
102 // Set the proper pixmap of this...
103 if (rtti() == qsamplerInstrumentList::Group) {
104 QListViewItem::setPixmap(0, QPixmap::fromMimeSource(
105 bOpen ? "itemGroupOpen.png" : "itemGroup.png"));
106 }
107 // Open it up...
108 QListViewItem::setOpen(bOpen);
109
110 // All ancestors should be also visible.
111 if (bOpen && QListViewItem::parent())
112 QListViewItem::parent()->setOpen(true);
113 }
114
115
116 // To virtually distinguish between list view items.
117 int qsamplerInstrumentGroup::rtti (void) const
118 {
119 return qsamplerInstrumentList::Group;
120 }
121
122
123 //----------------------------------------------------------------------
124 // class qsamplerInstrumentItem -- custom file list view item.
125 //
126
127 // Constructors.
128 qsamplerInstrumentItem::qsamplerInstrumentItem (
129 qsamplerInstrumentList *pListView,
130 qsamplerInstrument *pInstrument,
131 QListViewItem *pItemAfter )
132 : qsamplerInstrumentGroup(pListView, pInstrument->name(), pItemAfter)
133 {
134 m_pInstrument = pInstrument;
135
136 update();
137 }
138
139 qsamplerInstrumentItem::qsamplerInstrumentItem (
140 qsamplerInstrumentGroup *pGroupItem,
141 qsamplerInstrument *pInstrument )
142 : qsamplerInstrumentGroup(pGroupItem, pInstrument->name())
143 {
144 m_pInstrument = pInstrument;
145
146 update();
147 }
148
149
150 // Default destructor.
151 qsamplerInstrumentItem::~qsamplerInstrumentItem (void)
152 {
153 if (m_pInstrument)
154 delete m_pInstrument;
155 }
156
157
158 // To virtually distinguish between list view items.
159 int qsamplerInstrumentItem::rtti (void) const
160 {
161 return qsamplerInstrumentList::Item;
162 }
163
164
165 // Payload accessor.
166 qsamplerInstrument *qsamplerInstrumentItem::instrument (void) const
167 {
168 return m_pInstrument;
169 }
170
171
172 // Item refreshment.
173 void qsamplerInstrumentItem::update (void)
174 {
175 QListViewItem::setPixmap(0, QPixmap::fromMimeSource("itemFile.png"));
176
177 const QString s = "-";
178 if (m_pInstrument) {
179 setText(0, m_pInstrument->name());
180 setText(1, QString::number(m_pInstrument->bank()));
181 setText(2, QString::number(m_pInstrument->program()));
182 setText(3, m_pInstrument->engineName());
183 setText(4, QFileInfo(m_pInstrument->instrumentFile()).fileName());
184 setText(5, QString::number(m_pInstrument->instrumentNr()));
185 setText(6, QString::number(::lroundf(100.0f * m_pInstrument->volume())));
186 QString sLoadMode = s;
187 switch (m_pInstrument->loadMode()) {
188 case 3:
189 sLoadMode = QObject::tr("Persistent");
190 break;
191 case 2:
192 sLoadMode = QObject::tr("On Demand Hold");
193 break;
194 case 1:
195 sLoadMode = QObject::tr("On Demand");
196 break;
197 }
198 setText(7, sLoadMode);
199 } else {
200 for (int i = 0; i < listView()->columns(); i++)
201 setText(i, s);
202 }
203 }
204
205
206 //----------------------------------------------------------------------------
207 // qsamplerInstrumentList -- MIDI instrument list view.
208 //
209
210 // Constructor.
211 qsamplerInstrumentList::qsamplerInstrumentList (
212 QWidget *pParent, const char *pszName )
213 : QListView(pParent, pszName)
214 {
215 // QListView::setRootIsDecorated(true);
216 QListView::setResizeMode(QListView::NoColumn);
217 // QListView::setAcceptDrops(true);
218 QListView::setDragAutoScroll(true);
219 QListView::setSizePolicy(
220 QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
221 // QListView::setShowToolTips(false);
222 QListView::setSortColumn(-1);
223
224 QListView::addColumn(tr("Name"));
225 QListView::addColumn(tr("Bank"));
226 QListView::addColumn(tr("Prog"));
227 QListView::addColumn(tr("Engine"));
228 QListView::addColumn(tr("File"));
229 QListView::addColumn(tr("Nr"));
230 QListView::addColumn(tr("Vol"));
231 QListView::addColumn(tr("Mode"));
232
233 QListView::setColumnAlignment(1, Qt::AlignHCenter); // Bank
234 QListView::setColumnAlignment(2, Qt::AlignHCenter); // Prog
235 QListView::setColumnAlignment(5, Qt::AlignHCenter); // Nr
236 QListView::setColumnAlignment(6, Qt::AlignHCenter); // Vol
237
238 QListView::setColumnWidth(0, 60); // Name
239 QListView::setColumnWidth(0, 120); // File
240
241 m_pNewGroupAction = new QAction(tr("New &Group"), tr("Ctrl+G"), this);
242 m_pNewItemAction = new QAction(tr("New &Instrument..."), tr("Ctrl+I"), this);
243 m_pEditItemAction = new QAction(tr("&Edit..."), tr("Ctrl+E"), this);
244 m_pRenameAction = new QAction(tr("&Rename"), tr("Ctrl+R"), this);
245 m_pDeleteAction = new QAction(tr("&Delete"), tr("Ctrl+D"), this);
246 m_pRefreshAction = new QAction(tr("Re&fresh"), tr("Ctrl+F"), this);
247
248 QObject::connect(m_pNewGroupAction,
249 SIGNAL(activated()),
250 SLOT(newGroupSlot()));
251 QObject::connect(m_pNewItemAction,
252 SIGNAL(activated()),
253 SLOT(newItemSlot()));
254 QObject::connect(m_pEditItemAction,
255 SIGNAL(activated()),
256 SLOT(editItemSlot()));
257 QObject::connect(m_pRenameAction,
258 SIGNAL(activated()),
259 SLOT(renameSlot()));
260 QObject::connect(m_pDeleteAction,
261 SIGNAL(activated()),
262 SLOT(deleteSlot()));
263 QObject::connect(m_pRefreshAction,
264 SIGNAL(activated()),
265 SLOT(refresh()));
266
267 QObject::connect(this,
268 SIGNAL(selectionChanged()),
269 SLOT(selectionChangedSlot()));
270 QObject::connect(this,
271 SIGNAL(doubleClicked(QListViewItem*, const QPoint&, int)),
272 SLOT(activatedSlot(QListViewItem*)));
273 QObject::connect(this,
274 SIGNAL(returnPressed(QListViewItem*)),
275 SLOT(activatedSlot(QListViewItem*)));
276 QObject::connect(this,
277 SIGNAL(itemRenamed(QListViewItem*,int)),
278 SLOT(renamedSlot(QListViewItem*)));
279
280 selectionChangedSlot();
281 }
282
283
284 // Default destructor.
285 qsamplerInstrumentList::~qsamplerInstrumentList (void)
286 {
287 delete m_pNewGroupAction;
288 delete m_pNewItemAction;
289 delete m_pEditItemAction;
290 delete m_pRenameAction;
291 delete m_pDeleteAction;
292 }
293
294
295 // Add a new instrument item, optionally under a given group.
296 qsamplerInstrumentItem *qsamplerInstrumentList::addItem (
297 qsamplerInstrument *pInstrument,
298 qsamplerInstrumentGroup *pParentGroup )
299 {
300 qsamplerInstrumentItem *pItem = findItem(pInstrument);
301 if (pItem == NULL) {
302 if (pParentGroup)
303 pItem = new qsamplerInstrumentItem(pParentGroup, pInstrument);
304 else
305 pItem = new qsamplerInstrumentItem(this, pInstrument);
306 }
307 QListView::setSelected(pItem, true);
308 return pItem;
309 }
310
311
312 // Add a new instrument group, optionally under another group.
313 qsamplerInstrumentGroup *qsamplerInstrumentList::addGroup (
314 const QString& sName, qsamplerInstrumentGroup *pParentGroup )
315 {
316 qsamplerInstrumentGroup *pGroup = findGroup(sName);
317 if (pGroup == NULL) {
318 if (pParentGroup)
319 pGroup = new qsamplerInstrumentGroup(pParentGroup, sName);
320 else
321 pGroup = new qsamplerInstrumentGroup(this, sName);
322 }
323 QListView::setSelected(pGroup, true);
324 return pGroup;
325 }
326
327
328 // Find a group item, given its name.
329 qsamplerInstrumentGroup *qsamplerInstrumentList::findGroup (
330 const QString& sName ) const
331 {
332 // Iterate all over the place to search for the group.
333 QListViewItemIterator iter((QListView *) this);
334 while (iter.current()) {
335 QListViewItem *pItem = iter.current();
336 if (pItem->rtti() == Group && pItem->text(0) == sName)
337 return static_cast<qsamplerInstrumentGroup *> (pItem);
338 ++iter;
339 }
340 // Not found.
341 return NULL;
342 }
343
344
345 // Find a file item, given its name.
346 qsamplerInstrumentItem *qsamplerInstrumentList::findItem (
347 qsamplerInstrument *pInstrument ) const
348 {
349 if (pInstrument == NULL)
350 return NULL;
351
352 // Iterate all over the place to search for the group.
353 QListViewItemIterator iter((QListView *) this);
354 while (iter.current()) {
355 QListViewItem *pListItem = iter.current();
356 if (pListItem->rtti() == Item) {
357 qsamplerInstrumentItem *pItem
358 = static_cast<qsamplerInstrumentItem *> (pListItem);
359 if (pItem && pItem->instrument()
360 && pItem->instrument()->bank() == pInstrument->bank()
361 && pItem->instrument()->program() == pInstrument->program())
362 return pItem;
363 }
364 ++iter;
365 }
366 // Not found.
367 return NULL;
368 }
369
370
371 // Find and return the nearest group item...
372 qsamplerInstrumentGroup *qsamplerInstrumentList::groupItem (
373 QListViewItem *pItem ) const
374 {
375 while (pItem && pItem->rtti() != Group)
376 pItem = pItem->parent();
377 return static_cast<qsamplerInstrumentGroup *> (pItem);
378 }
379
380
381 // Add a new group item below the current one.
382 void qsamplerInstrumentList::newGroupSlot (void)
383 {
384 qsamplerInstrumentGroup *pParentGroup
385 = groupItem(QListView::selectedItem());
386 qsamplerInstrumentGroup *pNewGroup
387 = addGroup(tr("New Group"), pParentGroup);
388 if (pParentGroup)
389 pParentGroup->setOpen(true);
390 if (pNewGroup)
391 pNewGroup->startRename(0);
392
393 selectionChangedSlot();
394 }
395
396
397 // Add a new instrument item below the current one.
398 void qsamplerInstrumentList::newItemSlot (void)
399 {
400 qsamplerInstrument *pInstrument = new qsamplerInstrument();
401
402 qsamplerInstrumentForm form(this);
403 form.setup(pInstrument);
404 if (!form.exec()) {
405 delete pInstrument;
406 return;
407 }
408
409 // Check it there's already one for the same key (bank, program)
410 qsamplerInstrumentItem *pItem = findItem(pInstrument);
411 if (pItem)
412 delete pItem;
413
414 pInstrument->map();
415 emit instrumentsChanged();
416
417 qsamplerInstrumentGroup *pParentGroup
418 = groupItem(QListView::selectedItem());
419 addItem(pInstrument, pParentGroup);
420 if (pParentGroup)
421 pParentGroup->setOpen(true);
422
423 selectionChangedSlot();
424 }
425
426
427 // Edit current item below the current one.
428 void qsamplerInstrumentList::editItemSlot (void)
429 {
430 QListViewItem *pListItem = QListView::selectedItem();
431 if (pListItem == NULL)
432 return;
433 if (pListItem->rtti() == Item) {
434 qsamplerInstrumentItem *pItem
435 = static_cast<qsamplerInstrumentItem *> (pListItem);
436 if (pItem && pItem->instrument()) {
437 qsamplerInstrumentForm form(this);
438 form.setup(pItem->instrument());
439 if (form.exec()) {
440 pItem->instrument()->map();
441 emit instrumentsChanged();
442 pItem->update();
443 }
444 }
445 }
446
447 selectionChangedSlot();
448 }
449
450
451 // Rename current group/item.
452 void qsamplerInstrumentList::renameSlot (void)
453 {
454 QListViewItem *pListItem = QListView::selectedItem();
455 if (pListItem)
456 pListItem->startRename(0);
457
458 selectionChangedSlot();
459 }
460
461
462 // Remove current group/item.
463 void qsamplerInstrumentList::deleteSlot (void)
464 {
465 QListViewItem *pListItem = QListView::selectedItem();
466 if (pListItem) {
467 if (pListItem->rtti() == Item) {
468 qsamplerInstrumentItem *pItem
469 = static_cast<qsamplerInstrumentItem *> (pListItem);
470 if (pItem && pItem->instrument()) {
471 pItem->instrument()->unmap();
472 emit instrumentsChanged();
473 }
474 }
475 delete pListItem;
476 }
477
478 selectionChangedSlot();
479 }
480
481
482 // In-place selection slot.
483 void qsamplerInstrumentList::selectionChangedSlot (void)
484 {
485 qsamplerMainForm *pMainForm = qsamplerMainForm::getInstance();
486 QListViewItem *pListItem = QListView::selectedItem();
487 bool bEnabled = (pMainForm && pMainForm->client());
488 m_pNewItemAction->setEnabled(bEnabled);
489 bEnabled = (bEnabled && pListItem != NULL);
490 m_pEditItemAction->setEnabled(bEnabled && pListItem->rtti() == Item);
491 m_pRenameAction->setEnabled(bEnabled);
492 m_pDeleteAction->setEnabled(bEnabled);
493 }
494
495
496 // In-place activation slot.
497 void qsamplerInstrumentList::activatedSlot ( QListViewItem *pListItem )
498 {
499 // FIXME: Hope the list view item is the one selected.
500 if (pListItem->rtti() == Item)
501 editItemSlot();
502 }
503
504
505 // In-place aliasing slot.
506 void qsamplerInstrumentList::renamedSlot ( QListViewItem *pListItem )
507 {
508 if (pListItem->rtti() == Item) {
509 qsamplerInstrumentItem *pItem
510 = static_cast<qsamplerInstrumentItem *> (pListItem);
511 if (pItem && pItem->instrument()) {
512 pItem->instrument()->setName(pListItem->text(0));
513 pItem->instrument()->map();
514 emit instrumentsChanged();
515 pItem->update();
516 }
517 }
518 }
519
520
521 // Context menu request event handler.
522 void qsamplerInstrumentList::contextMenuEvent (
523 QContextMenuEvent *pContextMenuEvent )
524 {
525 QPopupMenu menu(this);
526
527 // Construct context menu.
528 m_pNewItemAction->addTo(&menu);
529 // m_pNewGroupAction->addTo(&menu);
530 menu.insertSeparator();
531 m_pEditItemAction->addTo(&menu);
532 m_pRenameAction->addTo(&menu);
533 m_pDeleteAction->addTo(&menu);
534 menu.insertSeparator();
535 m_pRefreshAction->addTo(&menu);
536
537 menu.exec(pContextMenuEvent->globalPos());
538 }
539
540
541 // General reloader.
542 void qsamplerInstrumentList::refresh (void)
543 {
544 clear();
545
546 qsamplerMainForm *pMainForm = qsamplerMainForm::getInstance();
547 if (pMainForm == NULL)
548 return;
549 if (pMainForm->client() == NULL)
550 return;
551
552 qsamplerInstrumentItem *pItem = NULL;
553 lscp_midi_instrument_t *pInstrs
554 = ::lscp_list_midi_instruments(pMainForm->client());
555 for (int iInstr = 0; pInstrs && pInstrs[iInstr].program >= 0; ++iInstr) {
556 int iBank = (pInstrs[iInstr].bank_msb << 7) | pInstrs[iInstr].bank_lsb;
557 int iProgram = pInstrs[iInstr].program;
558 qsamplerInstrument *pInstrument
559 = new qsamplerInstrument(iBank, iProgram);
560 if (pInstrument->get())
561 pItem = new qsamplerInstrumentItem(this, pInstrument, pItem);
562 }
563
564 if (pInstrs == NULL && ::lscp_client_get_errno(pMainForm->client())) {
565 pMainForm->appendMessagesClient("lscp_list_midi_instruments");
566 pMainForm->appendMessagesError(tr("Could not get current list of MIDI instrument mappings.\n\nSorry."));
567 }
568
569 selectionChangedSlot();
570 }
571
572
573 // end of qsamplerInstrumentList.cpp
574

  ViewVC Help
Powered by ViewVC