drumstick 2.3.1
pianoscene.cpp
Go to the documentation of this file.
1/*
2 Virtual Piano Widget for Qt5
3 Copyright (C) 2008-2021, Pedro Lopez-Cabanillas <plcl@users.sf.net>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#include <QApplication>
20#include <QDataStream>
21#include <QByteArray>
22#include <QGraphicsSceneMouseEvent>
23#include <QKeyEvent>
24#include <QPalette>
25#include <QPixmap>
26#include <QtMath>
27#if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
28#include <QTouchDevice>
29#else
30#include <QInputDevice>
31#endif
33#include "pianoscene.h"
34
46namespace drumstick { namespace widgets {
47
48class PianoScene::PianoScenePrivate
49{
50public:
51 PianoScenePrivate ( const int baseOctave,
52 const int numKeys,
53 const int startKey ):
54 m_baseOctave( baseOctave ),
55 m_numKeys( numKeys ),
56 m_startKey( startKey ),
57 m_minNote( 0 ),
58 m_maxNote( 127 ),
59 m_transpose( 0 ),
60 m_showLabels( ShowNever ),
61 m_alterations( ShowSharps ),
62 m_octave( OctaveC4 ),
63 m_orientation( HorizontalOrientation ),
64 m_rawkbd( false ),
65 m_keyboardEnabled( true ),
66 m_mouseEnabled( true ),
67 m_touchEnabled( true ),
68 m_mousePressed( false ),
69 m_velocity( 100 ),
70 m_channel( 0 ),
71 m_velocityTint( true ),
72 m_handler( nullptr ),
73 m_keybdMap( nullptr ),
74 m_showColorScale( false ),
75 m_hilightPalette(PianoPalette(PAL_SINGLE)),
76 m_backgroundPalette(PianoPalette(PAL_KEYS)),
77 m_foregroundPalette(PianoPalette(PAL_FONT)),
78 m_useKeyPix( true )
79 { }
80
81 void saveData(QByteArray& buffer)
82 {
83 QDataStream ds(&buffer, QIODevice::WriteOnly);
84 ds << m_minNote;
85 ds << m_maxNote;
86 ds << m_transpose;
87 ds << m_showLabels;
88 ds << m_alterations;
89 ds << m_octave;
90 ds << m_orientation;
91 ds << m_rawkbd;
92 ds << m_keyboardEnabled;
93 ds << m_mouseEnabled;
94 ds << m_touchEnabled;
95 ds << m_mousePressed;
96 ds << m_velocity;
97 ds << m_channel;
98 ds << m_velocityTint;
99 ds << m_noteNames;
100 ds << m_names_s;
101 ds << m_names_f;
102 ds << m_showColorScale;
103 ds << m_hilightPalette;
104 ds << m_backgroundPalette;
105 ds << m_foregroundPalette;
106 ds << m_useKeyPix;
107 ds << m_keyPix[0];
108 ds << m_keyPix[1];
109 }
110
111 void loadData(QByteArray& buffer)
112 {
113 quint32 u;
114 QDataStream ds(&buffer, QIODevice::ReadOnly);
115 ds >> m_minNote;
116 ds >> m_maxNote;
117 ds >> m_transpose;
118 ds >> u; m_showLabels = LabelVisibility(u);
119 ds >> u; m_alterations = LabelAlteration(u);
120 ds >> u; m_octave = LabelCentralOctave(u);
121 ds >> u; m_orientation = LabelOrientation(u);
122 ds >> m_rawkbd;
123 ds >> m_keyboardEnabled;
124 ds >> m_mouseEnabled;
125 ds >> m_touchEnabled;
126 ds >> m_mousePressed;
127 ds >> m_velocity;
128 ds >> m_channel;
129 ds >> m_velocityTint;
130 ds >> m_noteNames;
131 ds >> m_names_s;
132 ds >> m_names_f;
133 ds >> m_showColorScale;
134 ds >> m_hilightPalette;
135 ds >> m_backgroundPalette;
136 ds >> m_foregroundPalette;
137 ds >> m_useKeyPix;
138 ds >> m_keyPix[0];
139 ds >> m_keyPix[1];
140 }
141
142 int m_baseOctave;
143 int m_numKeys;
144 int m_startKey;
145 int m_minNote;
146 int m_maxNote;
147 int m_transpose;
148 LabelVisibility m_showLabels;
149 LabelAlteration m_alterations;
150 LabelCentralOctave m_octave;
151 LabelOrientation m_orientation;
152 bool m_rawkbd;
153 bool m_keyboardEnabled;
154 bool m_mouseEnabled;
155 bool m_touchEnabled;
156 bool m_mousePressed;
157 int m_velocity;
158 int m_channel;
159 bool m_velocityTint;
160 PianoHandler *m_handler;
161 KeyboardMap *m_keybdMap;
162 QHash<int, PianoKey *> m_keys;
163 QMap<int, KeyLabel *> m_labels;
164 QStringList m_noteNames;
165 QStringList m_names_s;
166 QStringList m_names_f;
167 bool m_showColorScale;
168 PianoPalette m_hilightPalette;
169 PianoPalette m_backgroundPalette;
170 PianoPalette m_foregroundPalette;
171 bool m_useKeyPix;
172 QPixmap m_keyPix[2];
173};
174
175const int KEYWIDTH = 180;
176const int KEYHEIGHT = 720;
177
178static qreal sceneWidth(int keys) {
179 return KEYWIDTH * qCeil( keys * 7.0 / 12.0 );
180}
181
190PianoScene::PianoScene ( const int baseOctave,
191 const int numKeys,
192 const int startKey,
193 const QColor& keyPressedColor,
194 QObject * parent )
195 : QGraphicsScene( QRectF(0, 0, sceneWidth(numKeys), KEYHEIGHT), parent ),
196 d(new PianoScenePrivate(baseOctave, numKeys, startKey))
197{
198 if (keyPressedColor.isValid()) {
199 setKeyPressedColor(keyPressedColor);
200 }
201 QBrush hilightBrush(getKeyPressedColor());
202 PianoKeybd* view = dynamic_cast<PianoKeybd*>(parent);
203 if (view != nullptr) {
204 setFont(view->font());
205 }
206 int upperLimit = d->m_numKeys + d->m_startKey;
207 int adj = d->m_startKey % 12;
208 if (adj >= 5) adj++;
209 for(int i = d->m_startKey; i < upperLimit; ++i)
210 {
211 float x = 0;
212 PianoKey* key = nullptr;
213 KeyLabel* lbl = nullptr;
214 int ocs = i / 12 * 7;
215 int j = i % 12;
216 if (j >= 5) j++;
217 if ((j % 2) == 0) {
218 x = (ocs + qFloor((j-adj) / 2.0)) * KEYWIDTH;
219 key = new PianoKey( QRectF(x, 0, KEYWIDTH, KEYHEIGHT), false, i );
220 lbl = new KeyLabel(key);
221 lbl->setDefaultTextColor(d->m_foregroundPalette.getColor(0));
222 } else {
223 x = (ocs + qFloor((j-adj) / 2.0)) * KEYWIDTH + KEYWIDTH * 0.6 + 1;
224 key = new PianoKey( QRectF( x, 0, KEYWIDTH * 0.8 - 1, KEYHEIGHT * 0.6 ), true, i );
225 key->setZValue( 1 );
226 lbl = new KeyLabel(key);
227 lbl->setDefaultTextColor(d->m_foregroundPalette.getColor(1));
228 }
229 addItem( key );
230 lbl->setFont(font());
231 key->setAcceptTouchEvents(true);
232 key->setPressedBrush(hilightBrush);
233 d->m_keys.insert(i, key);
234 d->m_labels.insert(i, lbl);
235 }
237 retranslate();
238}
239
244{ }
245
251{
252 return {static_cast<int>(sceneWidth(d->m_numKeys)), KEYHEIGHT};
253}
254
260{
261 d->m_keybdMap = map;
262}
263
269{
270 return d->m_keybdMap;
271}
272
281{
282 return d->m_handler;
283}
284
294{
295 d->m_handler = handler;
296}
297
303{
304 return d->m_hilightPalette;
305}
306
311void PianoScene::displayKeyOn(PianoKey* key)
312{
313 key->setPressed(true);
314 int n = key->getNote() + d->m_baseOctave*12 + d->m_transpose;
315 QString s = QString("#%1 (%2)").arg(n).arg(noteName(key));
316 emit signalName(s);
317 KeyLabel* lbl = dynamic_cast<KeyLabel*>(key->childItems().constFirst());
318 if (lbl != nullptr) {
319 lbl->setDefaultTextColor(d->m_foregroundPalette.getColor(key->isBlack() ? 3 : 2));
320 if (d->m_showLabels == ShowActivated) {
321 lbl->setVisible(true);
322 }
323 }
324}
325
332void PianoScene::showKeyOn( PianoKey* key, QColor color, int vel )
333{
334 //qDebug() << Q_FUNC_INFO << key->getNote() << vel << color << d->m_velocityTint;
335 if (d->m_velocityTint && (vel >= 0) && (vel < 128) && color.isValid() ) {
336 QBrush hilightBrush(color.lighter(200 - vel));
337 key->setPressedBrush(hilightBrush);
338 } else if (color.isValid()) {
339 key->setPressedBrush(color);
340 }
341 displayKeyOn(key);
342}
343
349void PianoScene::showKeyOn( PianoKey* key, int vel )
350{
352 displayKeyOn(key);
353}
354
360void PianoScene::showKeyOff( PianoKey* key, int vel)
361{
362 Q_UNUSED(vel)
363 key->setPressed(false);
364 emit signalName(QString());
365 KeyLabel* lbl = dynamic_cast<KeyLabel*>(key->childItems().constFirst());
366 if (lbl != nullptr) {
367 lbl->restoreColor();
368 if (d->m_showLabels == ShowActivated) {
369 lbl->setVisible(false);
370 }
371 }
372}
373
380void PianoScene::showNoteOn( const int note, QColor color, int vel )
381{
382 //qDebug() << Q_FUNC_INFO << note << vel << color;
383 int n = note - d->m_baseOctave*12 - d->m_transpose;
384 if ((note >= d->m_minNote) && (note <= d->m_maxNote) && d->m_keys.contains(n) && color.isValid())
385 showKeyOn(d->m_keys.value(n), color, vel);
386}
387
393void PianoScene::showNoteOn( const int note, int vel )
394{
395 //qDebug() << Q_FUNC_INFO << note << vel;
396 int n = note - d->m_baseOctave*12 - d->m_transpose;
397 if ((note >= d->m_minNote) && (note <= d->m_maxNote) && d->m_keys.contains(n)) {
398 showKeyOn(d->m_keys.value(n), vel);
399 }
400}
401
407void PianoScene::showNoteOff( const int note, int vel )
408{
409 int n = note - d->m_baseOctave*12 - d->m_transpose;
410 if ((note >= d->m_minNote) && (note <= d->m_maxNote) && d->m_keys.contains(n)) {
411 showKeyOff(d->m_keys.value(n), vel);
412 }
413}
414
420int PianoScene::baseOctave() const { return d->m_baseOctave; }
421
429void PianoScene::triggerNoteOn( const int note, const int vel )
430{
431 int n = d->m_baseOctave*12 + note + d->m_transpose;
432 if ((n >= d->m_minNote) && (n <= d->m_maxNote)) {
433 if (d->m_handler != nullptr) {
434 d->m_handler->noteOn(n, vel);
435 } else {
436 emit noteOn(n, vel);
437 }
438 }
439}
440
448void PianoScene::triggerNoteOff( const int note, const int vel )
449{
450 int n = d->m_baseOctave*12 + note + d->m_transpose;
451 if ((n >= d->m_minNote) && (n <= d->m_maxNote)) {
452 if (d->m_handler != nullptr) {
453 d->m_handler->noteOff(n, vel);
454 } else {
455 emit noteOff(n, vel);
456 }
457 }
458}
459
466void PianoScene::setHighlightColorFromPolicy(PianoKey* key, int vel)
467{
468 QColor c;
469 //qDebug() << Q_FUNC_INFO << key->getNote() << vel << d->m_velocityTint;
470 switch (d->m_hilightPalette.paletteId()) {
471 case PAL_SINGLE:
472 c = d->m_hilightPalette.getColor(0);
473 break;
474 case PAL_DOUBLE:
475 c = d->m_hilightPalette.getColor(key->getType());
476 break;
477 case PAL_CHANNELS:
478 c = d->m_hilightPalette.getColor(d->m_channel);
479 break;
480 case PAL_HISCALE:
481 c = d->m_hilightPalette.getColor(key->getDegree());
482 break;
483 default:
484 return;
485 }
486 if (c.isValid()) {
487 if (d->m_velocityTint && (vel >= 0) && (vel < 128)) {
488 QBrush h(c.lighter(200 - vel));
489 key->setPressedBrush(h);
490 } else {
491 key->setPressedBrush(c);
492 }
493 }
494}
495
500void PianoScene::keyOn( PianoKey* key )
501{
502 triggerNoteOn(key->getNote(), d->m_velocity);
503 showKeyOn(key, d->m_velocity);
504}
505
510void PianoScene::keyOff( PianoKey* key )
511{
512 triggerNoteOff(key->getNote(), 0);
513 showKeyOff(key, 0);
514}
515
521void PianoScene::keyOn( PianoKey* key, qreal pressure )
522{
523 int vel = d->m_velocity * pressure;
524 triggerNoteOn(key->getNote(), vel);
525 showKeyOn(key, vel);
526}
527
533void PianoScene::keyOff( PianoKey* key, qreal pressure )
534{
535 int vel = d->m_velocity * pressure;
536 triggerNoteOff(key->getNote(), vel);
537 showKeyOff(key, vel);
538}
539
544void PianoScene::keyOn(const int note)
545{
546 if (d->m_keys.contains(note))
547 keyOn(d->m_keys.value(note));
548 else
549 triggerNoteOn(note, d->m_velocity);
550}
551
556void PianoScene::keyOff(const int note)
557{
558 if (d->m_keys.contains(note))
559 keyOff(d->m_keys.value(note));
560 else
561 triggerNoteOff(note, d->m_velocity);
562}
563
569{
570 return d->m_rawkbd;
571}
572
578PianoKey* PianoScene::getKeyForPos( const QPointF& p ) const
579{
580 PianoKey* key = nullptr;
581 QList<QGraphicsItem *> ptitems = this->items(p, Qt::IntersectsItemShape, Qt::DescendingOrder);
582 foreach(QGraphicsItem *itm, ptitems) {
583 key = dynamic_cast<PianoKey*>(itm);
584 if (key != nullptr)
585 break;
586 }
587 return key;
588}
589
594void PianoScene::mouseMoveEvent ( QGraphicsSceneMouseEvent * mouseEvent )
595{
596 if (d->m_mouseEnabled) {
597 if (d->m_mousePressed) {
598 PianoKey* key = getKeyForPos(mouseEvent->scenePos());
599 PianoKey* lastkey = getKeyForPos(mouseEvent->lastScenePos());
600 if ((lastkey != nullptr) && (lastkey != key) && lastkey->isPressed()) {
601 keyOff(lastkey);
602 }
603 if ((key != nullptr) && !key->isPressed()) {
604 keyOn(key);
605 }
606 mouseEvent->accept();
607 return;
608 }
609 }
610}
611
616void PianoScene::mousePressEvent ( QGraphicsSceneMouseEvent * mouseEvent )
617{
618 if (d->m_mouseEnabled) {
619 PianoKey* key = getKeyForPos(mouseEvent->scenePos());
620 if (key != nullptr && !key->isPressed()) {
621 keyOn(key);
622 d->m_mousePressed = true;
623 mouseEvent->accept();
624 return;
625 }
626 }
627}
628
633void PianoScene::mouseReleaseEvent ( QGraphicsSceneMouseEvent * mouseEvent )
634{
635 if (d->m_mouseEnabled) {
636 d->m_mousePressed = false;
637 PianoKey* key = getKeyForPos(mouseEvent->scenePos());
638 if (key != nullptr && key->isPressed()) {
639 keyOff(key);
640 mouseEvent->accept();
641 return;
642 }
643 }
644}
645
651int PianoScene::getNoteFromKey( const int key ) const
652{
653 if (d->m_keybdMap != nullptr) {
654 KeyboardMap::ConstIterator it = d->m_keybdMap->constFind(key);
655 if ((it != d->m_keybdMap->constEnd()) && (it.key() == key)) {
656 int note = it.value();
657 return note;
658 }
659 }
660 return -1;
661}
662
668PianoKey* PianoScene::getPianoKey( const int key ) const
669{
670 int note = getNoteFromKey(key);
671 if (d->m_keys.contains(note))
672 return d->m_keys.value(note);
673 return nullptr;
674}
675
680void PianoScene::keyPressEvent ( QKeyEvent * keyEvent )
681{
682 if ( d->m_keyboardEnabled) {
683 if ( !d->m_rawkbd && !keyEvent->isAutoRepeat() ) { // ignore auto-repeats
684 int note = getNoteFromKey(keyEvent->key());
685 if (note > -1)
686 keyOn(note);
687 }
688 keyEvent->accept();
689 return;
690 }
691 keyEvent->ignore();
692}
693
698void PianoScene::keyReleaseEvent ( QKeyEvent * keyEvent )
699{
700 if (d->m_keyboardEnabled) {
701 if ( !d->m_rawkbd && !keyEvent->isAutoRepeat() ) { // ignore auto-repeats
702 int note = getNoteFromKey(keyEvent->key());
703 if (note > -1)
704 keyOff(note);
705 }
706 keyEvent->accept();
707 return;
708 }
709 keyEvent->ignore();
710}
711
718{
719 switch(event->type()) {
720 case QEvent::TouchBegin:
721 case QEvent::TouchEnd:
722 case QEvent::TouchUpdate:
723 {
724 QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
725#if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
726 const auto touchScreen = QTouchDevice::DeviceType::TouchScreen;
727#else
728 const auto touchScreen = QInputDevice::DeviceType::TouchScreen;
729#endif
730 if (d->m_touchEnabled && touchEvent->device()->type() == touchScreen) {
731 QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
732 bool hasPressure =
733#if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
734 touchEvent->device()->capabilities().testFlag(QTouchDevice::Pressure);
735#else
736 touchEvent->device()->capabilities().testFlag(QInputDevice::Capability::Pressure);
737#endif
738 foreach(const QTouchEvent::TouchPoint& touchPoint, touchPoints) {
739 switch (touchPoint.state()) {
740 //case Qt::TouchPointPrimary:
741 case Qt::TouchPointStationary:
742 continue;
743 case Qt::TouchPointReleased: {
744 PianoKey* key = getKeyForPos(touchPoint.scenePos());
745 if (key != nullptr && key->isPressed()) {
746 if (hasPressure) {
747 keyOff(key, touchPoint.pressure());
748 } else {
749 keyOff(key);
750 }
751 }
752 break;
753 }
754 case Qt::TouchPointPressed: {
755 PianoKey* key = getKeyForPos(touchPoint.scenePos());
756 if (key != nullptr && !key->isPressed()) {
757 if (hasPressure) {
758 keyOn(key, touchPoint.pressure());
759 } else {
760 keyOn(key);
761 }
762 key->ensureVisible();
763 }
764 break;
765 }
766 case Qt::TouchPointMoved: {
767 PianoKey* key = getKeyForPos(touchPoint.scenePos());
768 PianoKey* lastkey = getKeyForPos(touchPoint.lastScenePos());
769 if ((lastkey != nullptr) && (lastkey != key) && lastkey->isPressed()) {
770 if (hasPressure) {
771 keyOff(lastkey, touchPoint.pressure());
772 } else {
773 keyOff(lastkey);
774 }
775 }
776 if ((key != nullptr) && !key->isPressed()) {
777 if (hasPressure) {
778 keyOn(key, touchPoint.pressure());
779 } else {
780 keyOn(key);
781 }
782 }
783 break;
784 }
785 default:
786 //qDebug() << "TouchPoint state: " << touchPoint.state();
787 break;
788 }
789 }
790 //qDebug() << "accepted event: " << event;
791 event->accept();
792 return true;
793 }
794 break;
795 }
796 default:
797 break;
798 }
799 //qDebug() << "unprocessed event: " << event;
800 return QGraphicsScene::event(event);
801}
802
807{
808 foreach(PianoKey* key, d->m_keys) {
809 key->setPressed(false);
810 }
811}
812
819void PianoScene::setKeyPressedColor(const QColor& color)
820{
821 if (color.isValid()) {
822 d->m_hilightPalette = PianoPalette(PAL_SINGLE);
823 d->m_hilightPalette.setColor(0, color);
824 QBrush hilightBrush(color);
825 for (PianoKey* key : qAsConst(d->m_keys)) {
826 key->setPressedBrush(hilightBrush);
827 }
828 }
829}
830
835{
836 d->m_hilightPalette.resetColors();
837 QBrush hilightBrush(getKeyPressedColor());
838 for (PianoKey* key : qAsConst(d->m_keys)) {
839 key->setPressedBrush(hilightBrush);
840 }
841}
842
848{
849 return d->m_minNote;
850}
851
856{
857 for (PianoKey* key : qAsConst(d->m_keys)) {
858 int n = d->m_baseOctave*12 + key->getNote() + d->m_transpose;
859 bool b = !(n > d->m_maxNote) && !(n < d->m_minNote);
860 key->setVisible(b);
861 }
862}
863
868void PianoScene::setMinNote(const int note)
869{
870 if (d->m_minNote != note) {
871 d->m_minNote = note;
873 }
874}
875
881{
882 return d->m_maxNote;
883}
884
889void PianoScene::setMaxNote(const int note)
890{
891 if (d->m_maxNote != note) {
892 d->m_maxNote = note;
894 }
895}
896
902{
903 return d->m_transpose;
904}
905
910void PianoScene::setBaseOctave(const int base)
911{
912 if (d->m_baseOctave != base) {
913 d->m_baseOctave = base;
916 }
917}
918
924{
925 return d->m_numKeys;
926}
927
933{
934 return d->m_startKey;
935}
936
942bool PianoScene::isOctaveStart(const int note)
943{
944 return (note + d->m_transpose + 12) % 12 == 0;
945}
946
952QString PianoScene::noteName( PianoKey* key )
953{
954 Q_ASSERT(key != nullptr);
955 int note = key->getNote();
956 int num = (note + d->m_transpose + 12) % 12;
957 int adj = ((note + d->m_transpose < 0) ? 2 : 1) - d->m_octave + 1;
958 int oct = d->m_baseOctave + ((note + d->m_transpose) / 12) - adj;
959 if (d->m_noteNames.isEmpty()) {
960 QString name;
961 if (!d->m_names_f.isEmpty() && !d->m_names_s.isEmpty()) {
962 switch(d->m_alterations) {
963 case ShowFlats:
964 name = d->m_names_f.value(num);
965 break;
966 case ShowSharps:
967 name = d->m_names_s.value(num);
968 break;
969 case ShowNothing:
970 if (key->isBlack()) {
971 return QString();
972 }
973 name = d->m_names_s.value(num);
974 break;
975 default:
976 break;
977 }
978 }
979 if (d->m_octave==OctaveNothing) {
980 return name;
981 } else {
982 return QString("%1%2").arg(name).arg(oct);
983 }
984 } else {
985 if (d->m_noteNames.length() == 128) {
986 int n = d->m_baseOctave*12 + note + d->m_transpose;
987 //qDebug() << Q_FUNC_INFO << n << note;
988 if (n >= 0 && n < d->m_noteNames.length()) {
989 return d->m_noteNames.value(n);
990 }
991 } else if (d->m_noteNames.length() >= 12) {
992 if (d->m_octave==OctaveNothing) {
993 return d->m_noteNames.value(num);
994 } else {
995 return QString("%1%2").arg(d->m_noteNames.value(num)).arg(oct);
996 }
997 }
998 return QString();
999 }
1000}
1001
1006{
1007 for (KeyLabel* lbl : qAsConst(d->m_labels)) {
1008 PianoKey* key = dynamic_cast<PianoKey*>(lbl->parentItem());
1009 if (key != nullptr) {
1010 lbl->setVisible(false);
1011 lbl->setFont(font());
1012 lbl->setDefaultTextColor(d->m_foregroundPalette.getColor(key->isBlack() ? 1 : 0));
1013 lbl->setOrientation(d->m_orientation);
1014 lbl->setPlainText(noteName(key));
1015 lbl->adjust();
1016 lbl->setVisible((d->m_showLabels == ShowAlways) ||
1017 (d->m_showLabels == ShowMinimum && isOctaveStart(key->getNote())));
1018 }
1019 }
1020}
1021
1026{
1027 for (PianoKey* key : qAsConst(d->m_keys)) {
1028 if (d->m_showColorScale && (d->m_backgroundPalette.paletteId() == PAL_SCALE)) {
1029 int degree = key->getNote() % 12;
1030 key->setBrush(d->m_backgroundPalette.getColor(degree));
1031 } else {
1032 key->setBrush(d->m_backgroundPalette.getColor(key->isBlack() ? 1 : 0));
1033 }
1034 key->setPressed(false);
1035 }
1036}
1037
1044{
1045 //qDebug() << Q_FUNC_INFO << show;
1046 if (d->m_showLabels != show) {
1047 d->m_showLabels = show;
1048 refreshLabels();
1049 }
1050}
1051
1058{
1059 return d->m_alterations;
1060}
1061
1068{
1069 if (d->m_alterations != use) {
1070 d->m_alterations = use;
1071 refreshLabels();
1072 }
1073}
1074
1080{
1081 return d->m_octave;
1082}
1083
1089{
1090 if (d->m_orientation != orientation) {
1091 d->m_orientation = orientation;
1092 refreshLabels();
1093 }
1094}
1095
1096bool PianoScene::isKeyboardEnabled() const
1097{
1098 return d->m_keyboardEnabled;
1099}
1100
1101void PianoScene::setOctave(const LabelCentralOctave octave)
1102{
1103 if (d->m_octave != octave) {
1104 d->m_octave = octave;
1105 refreshLabels();
1106 }
1107}
1108
1109LabelOrientation PianoScene::getOrientation() const
1110{
1111 return d->m_orientation;
1112}
1113
1118void PianoScene::setTranspose(const int transpose)
1119{
1120 if (d->m_transpose != transpose && transpose > -12 && transpose < 12) {
1121 d->m_transpose = transpose;
1123 refreshLabels();
1124 }
1125}
1126
1133{
1134 return d->m_showLabels;
1135}
1136
1142{
1143 if (d->m_rawkbd != b) {
1144 d->m_rawkbd = b;
1145 }
1146}
1147
1153{
1154 return d->m_noteNames;
1155}
1156
1162{
1163 return d->m_names_s;
1164}
1165
1171{
1172 return d->m_velocity;
1173}
1174
1179void PianoScene::setVelocity(const int velocity)
1180{
1181 d->m_velocity = velocity;
1182}
1183
1190{
1191 return d->m_channel;
1192}
1193
1199void PianoScene::setChannel(const int channel)
1200{
1201 d->m_channel = channel;
1202}
1203
1208void PianoScene::useCustomNoteNames(const QStringList& names)
1209{
1210 //qDebug() << Q_FUNC_INFO << names;
1211 d->m_noteNames = names;
1212 refreshLabels();
1213}
1214
1219{
1220 //qDebug() << Q_FUNC_INFO;
1221 d->m_noteNames.clear();
1222 refreshLabels();
1223}
1224
1229void PianoScene::setKeyboardEnabled(const bool enable)
1230{
1231 if (enable != d->m_keyboardEnabled) {
1232 d->m_keyboardEnabled = enable;
1233 }
1234}
1235
1241{
1242 return d->m_mouseEnabled;
1243}
1244
1249void PianoScene::setMouseEnabled(const bool enable)
1250{
1251 if (enable != d->m_mouseEnabled) {
1252 d->m_mouseEnabled = enable;
1253 }
1254}
1255
1261{
1262 return d->m_touchEnabled;
1263}
1264
1269void PianoScene::setTouchEnabled(const bool enable)
1270{
1271 if (enable != d->m_touchEnabled) {
1272 d->m_touchEnabled = enable;
1273 }
1274}
1275
1281{
1282 return d->m_velocityTint;
1283}
1284
1289void PianoScene::setVelocityTint(const bool enable)
1290{
1291 //qDebug() << Q_FUNC_INFO << enable;
1292 d->m_velocityTint = enable;
1293}
1294
1299{
1300 d->m_names_s = QStringList{
1301 tr("C"),
1302 tr("C♯"),
1303 tr("D"),
1304 tr("D♯"),
1305 tr("E"),
1306 tr("F"),
1307 tr("F♯"),
1308 tr("G"),
1309 tr("G♯"),
1310 tr("A"),
1311 tr("A♯"),
1312 tr("B")};
1313 d->m_names_f = QStringList{
1314 tr("C"),
1315 tr("Dâ™­"),
1316 tr("D"),
1317 tr("Eâ™­"),
1318 tr("E"),
1319 tr("F"),
1320 tr("Gâ™­"),
1321 tr("G"),
1322 tr("Aâ™­"),
1323 tr("A"),
1324 tr("Bâ™­"),
1325 tr("B")};
1326 refreshLabels();
1327}
1328
1334{
1335 if (d->m_showColorScale != show) {
1336 d->m_showColorScale = show;
1337 refreshKeys();
1338 invalidate();
1339 }
1340}
1341
1347{
1348 return d->m_hilightPalette.getColor(0);
1349}
1350
1356{
1357 if (d->m_hilightPalette != p) {
1358 d->m_hilightPalette = p;
1359 refreshKeys();
1360 invalidate();
1361 }
1362}
1363
1369{
1370 return d->m_backgroundPalette;
1371}
1372
1378{
1379 if (d->m_backgroundPalette != p) {
1380 d->m_backgroundPalette = p;
1381 refreshKeys();
1382 invalidate();
1383 }
1384}
1385
1391{
1392 return d->m_foregroundPalette;
1393}
1394
1400{
1401 if (d->m_foregroundPalette != p) {
1402 d->m_foregroundPalette = p;
1403 refreshLabels();
1404 invalidate();
1405 }
1406}
1407
1413{
1414 return d->m_showColorScale;
1415}
1416
1417void PianoScene::setKeyPicture(const bool natural, const QPixmap &pix)
1418{
1419 d->m_keyPix[int(natural)] = pix;
1420 for (PianoKey* key : qAsConst(d->m_keys)) {
1421 if (key->isBlack() == !natural) {
1422 key->setPixmap(pix);
1423 }
1424 }
1425}
1426
1427QPixmap PianoScene::getKeyPicture(const bool natural)
1428{
1429 return d->m_keyPix[int(natural)];
1430}
1431
1432void PianoScene::setUseKeyPictures(const bool enable)
1433{
1434 d->m_useKeyPix = enable;
1435 for (PianoKey* key : qAsConst(d->m_keys)) {
1436 key->setUsePixmap(enable);
1437 }
1438}
1439
1440bool PianoScene::getUseKeyPictures() const
1441{
1442 return d->m_useKeyPix;
1443}
1444
1445void PianoScene::saveData(QByteArray &ba)
1446{
1447 d->saveData(ba);
1448}
1449
1450void PianoScene::loadData(QByteArray &ba)
1451{
1452 d->loadData(ba);
1453}
1454
1455} // namespace widgets
1456} // namespace drumstick
The QEvent class is the base class of all event classes.
The QGraphicsScene class provides a surface for managing a large number of 2D graphical items.
The QObject class is the base class of all Qt objects.
The PianoHandler class callbacks.
Definition: pianokeybd.h:72
The PianoKeybd class.
Definition: pianokeybd.h:159
The PianoPalette class.
Definition: pianopalette.h:61
void allKeysOff()
Deactivates all keys.
Definition: pianoscene.cpp:806
void triggerNoteOn(const int note, const int vel)
Performs a Note On MIDI event for the given MIDI note number and velocity.
Definition: pianoscene.cpp:429
void resetKeyPressedColor()
Assigns the default highlight palette colors and assigns it to the scene.
Definition: pianoscene.cpp:834
void keyOff(const int note)
Produces a MIDI Note Off event and deactivates the corresponding key for the given MIDI note number.
Definition: pianoscene.cpp:556
void showKeyOff(PianoKey *key, int vel)
Displays as deactivated a key.
Definition: pianoscene.cpp:360
void setBackgroundPalette(const PianoPalette &p)
Assigns the active background palette.
void setKeyPressedColor(const QColor &color)
Assigns a single color for key highlight.
Definition: pianoscene.cpp:819
void setRawKeyboardMode(const bool b)
Assigns the low level computer keyboard mode.
void keyOn(const int note)
Produces a MIDI Note On event and highlights the corresponding key for the given MIDI note number.
Definition: pianoscene.cpp:544
void useStandardNoteNames()
Assigns the standard note names, clearing the list of custom note names.
void hideOrShowKeys()
Hides or shows keys.
Definition: pianoscene.cpp:855
LabelCentralOctave getOctave() const
Returns the central octave name policy.
PianoScene(const int baseOctave, const int numKeys, const int startKey, const QColor &keyPressedColor=QColor(), QObject *parent=nullptr)
Constructor.
Definition: pianoscene.cpp:190
bool event(QEvent *event) override
Processes touch screen events.
Definition: pianoscene.cpp:717
int baseOctave() const
Returns the base octave number.
Definition: pianoscene.cpp:420
PianoPalette getForegroundPalette()
Returns the active foreground palette.
void setHighlightPalette(const PianoPalette &p)
Assigns the active highlight palette.
void setShowColorScale(const bool show)
Enables or disables the color scale key background mode.
void setPianoHandler(PianoHandler *handler)
Assigns a PianoHandler pointer for processing note events.
Definition: pianoscene.cpp:293
void setKeyboardMap(KeyboardMap *map)
Assigns the computer keyboard note map.
Definition: pianoscene.cpp:259
void noteOff(int n, int v)
This signal is emitted for each Note Off MIDI event created using the computer keyboard,...
void setVelocity(const int velocity)
Assigns the MIDI note velocity parameter that is assigned to the MIDI OUT notes.
void setMinNote(const int note)
Assigns the minimum MIDI note number that will be displayed.
Definition: pianoscene.cpp:868
bool showColorScale() const
Returns whether the color scale mode is enabled.
void setBaseOctave(const int base)
Assigns the octave base number.
Definition: pianoscene.cpp:910
PianoKey * getKeyForPos(const QPointF &p) const
Returns the piano key for the given scene point coordenates.
Definition: pianoscene.cpp:578
void signalName(const QString &name)
signalName is emitted for each note created, and contains a string with the MIDI note number and the ...
int numKeys() const
Returns the number of keys that will be displayed.
Definition: pianoscene.cpp:923
PianoPalette getHighlightPalette()
Returns the palette used for highlighting the played keys.
Definition: pianoscene.cpp:302
void setKeyboardEnabled(const bool enable)
Enables or disables the computer keyboard note generation.
void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) override
This event handler, for event mouseEvent, is reimplemented to receive mouse move events for the scene...
Definition: pianoscene.cpp:594
void triggerNoteOff(const int note, const int vel)
Performs a Note Off MIDI event for the given MIDI note number and velocity.
Definition: pianoscene.cpp:448
PianoKey * getPianoKey(const int key) const
Returns the piano key object corresponding to the given computer keyboard key.
Definition: pianoscene.cpp:668
int getVelocity()
Returns the MIDI note velocity parameter that is assigned to the MIDI OUT notes.
int getChannel() const
Returns the MIDI channel that is assigned to the output events, or used to filter the input events (u...
void setForegroundPalette(const PianoPalette &p)
Assigns the active foreground palette.
void keyPressEvent(QKeyEvent *keyEvent) override
This event handler, for event keyEvent, is reimplemented to receive keypress events.
Definition: pianoscene.cpp:680
void setVelocityTint(const bool enable)
Enables or disables the velocity parameter of note events to influence the highlight key colors.
bool velocityTint() const
Returns whether the velocity parameter of note events is used to influence the highlight key colors.
QColor getKeyPressedColor() const
Returns the single highlight palette color.
int getNoteFromKey(const int key) const
Returns the note number for the given computer keyboard key code.
Definition: pianoscene.cpp:651
void refreshLabels()
Refresh the visibility and other attributes of the labels shown over the piano keys.
void showNoteOff(const int note, int vel=-1)
Displays deactivated the corresponding key for a given MIDI note, with MIDI velocity.
Definition: pianoscene.cpp:407
void setShowLabels(const LabelVisibility show)
Assigns the label visibility policy to the piano keys.
void refreshKeys()
Refresh the background colors of all the piano keys.
QSize sizeHint() const
Returns the calculated size of the scene.
Definition: pianoscene.cpp:250
bool isOctaveStart(const int note)
Returns whether the given note number is a octave startup note.
Definition: pianoscene.cpp:942
void setAlterations(const LabelAlteration use)
Assigns the alterations name policy.
PianoPalette getBackgroundPalette()
Returns the background palette.
QStringList standardNoteNames() const
Returns the standard note names list.
void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) override
This event handler, for event mouseEvent, is reimplemented to receive mouse press events for the scen...
Definition: pianoscene.cpp:616
void setTranspose(const int transpose)
Assigns the transpose amount in semitones.
int getMaxNote() const
Returns the maximum MIDI note number that will be displayed.
Definition: pianoscene.cpp:880
LabelAlteration alterations() const
Returns the alterations name policy.
void setHighlightColorFromPolicy(PianoKey *key, const int vel)
Assigns to the given key the highlight color from the active highlight palette and the given MIDI vel...
Definition: pianoscene.cpp:466
PianoHandler * getPianoHandler() const
Gets the PianoHandler pointer to the note receiver.
Definition: pianoscene.cpp:280
void showKeyOn(PianoKey *key, QColor color, int vel)
Displays highlighted the activated key with the supplied color and note velocity.
Definition: pianoscene.cpp:332
KeyboardMap * getKeyboardMap() const
Returns the computer keyboard note map.
Definition: pianoscene.cpp:268
bool isMouseEnabled() const
Returns whether the computer keyboard note generation is enabled.
bool getRawKeyboardMode() const
Returns whether the low level computer keyboard mode is enabled.
Definition: pianoscene.cpp:568
void noteOn(int n, int v)
This signal is emitted for each Note On MIDI event created using the computer keyboard,...
void showNoteOn(const int note, QColor color, int vel=-1)
Displays highlighted the corresponding key for a given MIDI note, with a color and MIDI velocity.
Definition: pianoscene.cpp:380
void keyReleaseEvent(QKeyEvent *keyEvent) override
This event handler, for event keyEvent, is reimplemented to receive key release events.
Definition: pianoscene.cpp:698
void setMaxNote(const int note)
Assigns the maximum MIDI note number that will be displayed.
Definition: pianoscene.cpp:889
void retranslate()
Retranslates the standard note names.
int startKey() const
Returns the first key number that will be displayed.
Definition: pianoscene.cpp:932
void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) override
This event handler, for event mouseEvent, is reimplemented to receive mouse release events for the sc...
Definition: pianoscene.cpp:633
void setTouchEnabled(const bool enable)
Enables or disables the touch screen note generation.
void displayKeyOn(PianoKey *key)
Displays the note label over a highligted key.
Definition: pianoscene.cpp:311
void useCustomNoteNames(const QStringList &names)
Assigns the list of custom note names, and enables this mode.
void setMouseEnabled(const bool enable)
Enables or disables the mouse note generation.
void setChannel(const int channel)
Assigns the MIDI channel that is included into the output events, or used to filter the input events ...
int getMinNote() const
Returns the minimum MIDI note number that will be displayed.
Definition: pianoscene.cpp:847
void setOrientation(const LabelOrientation orientation)
Assigns the label orientation policy.
QStringList customNoteNames() const
Returns the custom note names list.
LabelVisibility showLabels() const
Returns the label visibility policy (display note names over the piano keys).
bool isTouchEnabled() const
Returns whether the touch screen note generation is enabled.
int getTranspose() const
Returns the transpose amount in semitones.
Definition: pianoscene.cpp:901
QString noteName(PianoKey *key)
Returns the note name string that will be displayed over a given piano key.
Definition: pianoscene.cpp:952
LabelAlteration
Labels for Alterations.
Definition: pianokeybd.h:118
LabelCentralOctave
Labels Central Octave.
Definition: pianokeybd.h:145
LabelVisibility
Labels Visibility.
Definition: pianokeybd.h:108
LabelOrientation
Labels Orientation.
Definition: pianokeybd.h:127
QHash< int, int > KeyboardMap
KeyboardMap.
Definition: pianokeybd.h:96
@ ShowSharps
Show sharps on black keys.
Definition: pianokeybd.h:119
@ ShowNothing
Do not show names on black keys.
Definition: pianokeybd.h:121
@ ShowFlats
Show flats on black keys.
Definition: pianokeybd.h:120
@ OctaveNothing
Don't show octave numbers.
Definition: pianokeybd.h:146
@ OctaveC4
Central C, MIDI note #60 is C4.
Definition: pianokeybd.h:148
@ ShowAlways
Show always note names.
Definition: pianokeybd.h:112
@ ShowMinimum
Show only note C names.
Definition: pianokeybd.h:110
@ ShowActivated
Show names when notes are activated.
Definition: pianokeybd.h:111
@ ShowNever
Don't show note names.
Definition: pianokeybd.h:109
@ HorizontalOrientation
Show horizontal names.
Definition: pianokeybd.h:128
@ PAL_SCALE
Background colors for each chromatic scale note.
Definition: pianopalette.h:49
@ PAL_SINGLE
Single highlihgting color for all keys.
Definition: pianopalette.h:46
@ PAL_HISCALE
Highlighting colors for each chromatic scale note.
Definition: pianopalette.h:52
@ PAL_CHANNELS
Different highlihgting colors for each channel.
Definition: pianopalette.h:48
@ PAL_KEYS
Two background colors (naturals/alterations)
Definition: pianopalette.h:50
@ PAL_DOUBLE
Two highlihgting colors (naturals/alterations)
Definition: pianopalette.h:47
@ PAL_FONT
Foreground font colors for names.
Definition: pianopalette.h:51
Drumstick common.
Definition: alsaclient.cpp:68
Piano Keyboard Widget.
PianoScene class declaration.