drumstick  2.2.0
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 
28 #include <drumstick/pianokeybd.h>
29 #include "pianoscene.h"
30 
42 namespace drumstick { namespace widgets {
43 
44 class PianoScene::PianoScenePrivate
45 {
46 public:
47  PianoScenePrivate ( const int baseOctave,
48  const int numKeys,
49  const int startKey ):
50  m_baseOctave( baseOctave ),
51  m_numKeys( numKeys ),
52  m_startKey( startKey ),
53  m_minNote( 0 ),
54  m_maxNote( 127 ),
55  m_transpose( 0 ),
56  m_showLabels( ShowNever ),
57  m_alterations( ShowSharps ),
58  m_octave( OctaveC4 ),
59  m_orientation( HorizontalOrientation ),
60  m_rawkbd( false ),
61  m_keyboardEnabled( true ),
62  m_mouseEnabled( true ),
63  m_touchEnabled( true ),
64  m_mousePressed( false ),
65  m_velocity( 100 ),
66  m_channel( 0 ),
67  m_velocityTint( true ),
68  m_handler( nullptr ),
69  m_keybdMap( nullptr ),
70  m_showColorScale( false ),
71  m_hilightPalette(PianoPalette(PAL_SINGLE)),
72  m_backgroundPalette(PianoPalette(PAL_KEYS)),
73  m_foregroundPalette(PianoPalette(PAL_FONT)),
74  m_useKeyPix( true )
75  { }
76 
77  void saveData(QByteArray& buffer)
78  {
79  QDataStream ds(&buffer, QIODevice::WriteOnly);
80  ds << m_minNote;
81  ds << m_maxNote;
82  ds << m_transpose;
83  ds << m_showLabels;
84  ds << m_alterations;
85  ds << m_octave;
86  ds << m_orientation;
87  ds << m_rawkbd;
88  ds << m_keyboardEnabled;
89  ds << m_mouseEnabled;
90  ds << m_touchEnabled;
91  ds << m_mousePressed;
92  ds << m_velocity;
93  ds << m_channel;
94  ds << m_velocityTint;
95  ds << m_noteNames;
96  ds << m_names_s;
97  ds << m_names_f;
98  ds << m_showColorScale;
99  ds << m_hilightPalette;
100  ds << m_backgroundPalette;
101  ds << m_foregroundPalette;
102  ds << m_useKeyPix;
103  ds << m_keyPix[0];
104  ds << m_keyPix[1];
105  }
106 
107  void loadData(QByteArray& buffer)
108  {
109  quint32 u;
110  QDataStream ds(&buffer, QIODevice::ReadOnly);
111  ds >> m_minNote;
112  ds >> m_maxNote;
113  ds >> m_transpose;
114  ds >> u; m_showLabels = LabelVisibility(u);
115  ds >> u; m_alterations = LabelAlteration(u);
116  ds >> u; m_octave = LabelCentralOctave(u);
117  ds >> u; m_orientation = LabelOrientation(u);
118  ds >> m_rawkbd;
119  ds >> m_keyboardEnabled;
120  ds >> m_mouseEnabled;
121  ds >> m_touchEnabled;
122  ds >> m_mousePressed;
123  ds >> m_velocity;
124  ds >> m_channel;
125  ds >> m_velocityTint;
126  ds >> m_noteNames;
127  ds >> m_names_s;
128  ds >> m_names_f;
129  ds >> m_showColorScale;
130  ds >> m_hilightPalette;
131  ds >> m_backgroundPalette;
132  ds >> m_foregroundPalette;
133  ds >> m_useKeyPix;
134  ds >> m_keyPix[0];
135  ds >> m_keyPix[1];
136  }
137 
138  int m_baseOctave;
139  int m_numKeys;
140  int m_startKey;
141  int m_minNote;
142  int m_maxNote;
143  int m_transpose;
144  LabelVisibility m_showLabels;
145  LabelAlteration m_alterations;
146  LabelCentralOctave m_octave;
147  LabelOrientation m_orientation;
148  bool m_rawkbd;
149  bool m_keyboardEnabled;
150  bool m_mouseEnabled;
151  bool m_touchEnabled;
152  bool m_mousePressed;
153  int m_velocity;
154  int m_channel;
155  bool m_velocityTint;
156  PianoHandler *m_handler;
157  KeyboardMap *m_keybdMap;
158  QHash<int, PianoKey *> m_keys;
159  QMap<int, KeyLabel *> m_labels;
160  QStringList m_noteNames;
161  QStringList m_names_s;
162  QStringList m_names_f;
163  bool m_showColorScale;
164  PianoPalette m_hilightPalette;
165  PianoPalette m_backgroundPalette;
166  PianoPalette m_foregroundPalette;
167  bool m_useKeyPix;
168  QPixmap m_keyPix[2];
169 };
170 
171 const int KEYWIDTH = 180;
172 const int KEYHEIGHT = 720;
173 
174 static qreal sceneWidth(int keys) {
175  return KEYWIDTH * qCeil( keys * 7.0 / 12.0 );
176 }
177 
186 PianoScene::PianoScene ( const int baseOctave,
187  const int numKeys,
188  const int startKey,
189  const QColor& keyPressedColor,
190  QObject * parent )
191  : QGraphicsScene( QRectF(0, 0, sceneWidth(numKeys), KEYHEIGHT), parent ),
192  d(new PianoScenePrivate(baseOctave, numKeys, startKey))
193 {
194  if (keyPressedColor.isValid()) {
195  setKeyPressedColor(keyPressedColor);
196  }
197  QBrush hilightBrush(getKeyPressedColor());
198  PianoKeybd* view = dynamic_cast<PianoKeybd*>(parent);
199  if (view != nullptr) {
200  setFont(view->font());
201  }
202  int upperLimit = d->m_numKeys + d->m_startKey;
203  int adj = d->m_startKey % 12;
204  if (adj >= 5) adj++;
205  for(int i = d->m_startKey; i < upperLimit; ++i)
206  {
207  float x = 0;
208  PianoKey* key = nullptr;
209  KeyLabel* lbl = nullptr;
210  int ocs = i / 12 * 7;
211  int j = i % 12;
212  if (j >= 5) j++;
213  if ((j % 2) == 0) {
214  x = (ocs + qFloor((j-adj) / 2.0)) * KEYWIDTH;
215  key = new PianoKey( QRectF(x, 0, KEYWIDTH, KEYHEIGHT), false, i );
216  lbl = new KeyLabel(key);
217  lbl->setDefaultTextColor(d->m_foregroundPalette.getColor(0));
218  } else {
219  x = (ocs + qFloor((j-adj) / 2.0)) * KEYWIDTH + KEYWIDTH * 0.6 + 1;
220  key = new PianoKey( QRectF( x, 0, KEYWIDTH * 0.8 - 1, KEYHEIGHT * 0.6 ), true, i );
221  key->setZValue( 1 );
222  lbl = new KeyLabel(key);
223  lbl->setDefaultTextColor(d->m_foregroundPalette.getColor(1));
224  }
225  addItem( key );
226  lbl->setFont(font());
227  key->setAcceptTouchEvents(true);
228  key->setPressedBrush(hilightBrush);
229  d->m_keys.insert(i, key);
230  d->m_labels.insert(i, lbl);
231  }
232  hideOrShowKeys();
233  retranslate();
234 }
235 
240 { }
241 
246 QSize PianoScene::sizeHint() const
247 {
248  return {static_cast<int>(sceneWidth(d->m_numKeys)), KEYHEIGHT};
249 }
250 
256 {
257  d->m_keybdMap = map;
258 }
259 
265 {
266  return d->m_keybdMap;
267 }
268 
277 {
278  return d->m_handler;
279 }
280 
290 {
291  d->m_handler = handler;
292 }
293 
299 {
300  return d->m_hilightPalette;
301 }
302 
307 void PianoScene::displayKeyOn(PianoKey* key)
308 {
309  key->setPressed(true);
310  int n = key->getNote() + d->m_baseOctave*12 + d->m_transpose;
311  QString s = QString("#%1 (%2)").arg(n).arg(noteName(key));
312  emit signalName(s);
313  KeyLabel* lbl = dynamic_cast<KeyLabel*>(key->childItems().constFirst());
314  if (lbl != nullptr) {
315  lbl->setDefaultTextColor(d->m_foregroundPalette.getColor(key->isBlack() ? 3 : 2));
316  if (d->m_showLabels == ShowActivated) {
317  lbl->setVisible(true);
318  }
319  }
320 }
321 
328 void PianoScene::showKeyOn( PianoKey* key, QColor color, int vel )
329 {
330  //qDebug() << Q_FUNC_INFO << key->getNote() << vel << color << d->m_velocityTint;
331  if (d->m_velocityTint && (vel >= 0) && (vel < 128) && color.isValid() ) {
332  QBrush hilightBrush(color.lighter(200 - vel));
333  key->setPressedBrush(hilightBrush);
334  } else if (color.isValid()) {
335  key->setPressedBrush(color);
336  }
337  displayKeyOn(key);
338 }
339 
345 void PianoScene::showKeyOn( PianoKey* key, int vel )
346 {
347  setHighlightColorFromPolicy(key, vel);
348  displayKeyOn(key);
349 }
350 
356 void PianoScene::showKeyOff( PianoKey* key, int vel)
357 {
358  Q_UNUSED(vel)
359  key->setPressed(false);
360  emit signalName(QString());
361  KeyLabel* lbl = dynamic_cast<KeyLabel*>(key->childItems().constFirst());
362  if (lbl != nullptr) {
363  lbl->restoreColor();
364  if (d->m_showLabels == ShowActivated) {
365  lbl->setVisible(false);
366  }
367  }
368 }
369 
376 void PianoScene::showNoteOn( const int note, QColor color, int vel )
377 {
378  //qDebug() << Q_FUNC_INFO << note << vel << color;
379  int n = note - d->m_baseOctave*12 - d->m_transpose;
380  if ((note >= d->m_minNote) && (note <= d->m_maxNote) && d->m_keys.contains(n) && color.isValid())
381  showKeyOn(d->m_keys.value(n), color, vel);
382 }
383 
389 void PianoScene::showNoteOn( const int note, int vel )
390 {
391  //qDebug() << Q_FUNC_INFO << note << vel;
392  int n = note - d->m_baseOctave*12 - d->m_transpose;
393  if ((note >= d->m_minNote) && (note <= d->m_maxNote) && d->m_keys.contains(n)) {
394  showKeyOn(d->m_keys.value(n), vel);
395  }
396 }
397 
403 void PianoScene::showNoteOff( const int note, int vel )
404 {
405  int n = note - d->m_baseOctave*12 - d->m_transpose;
406  if ((note >= d->m_minNote) && (note <= d->m_maxNote) && d->m_keys.contains(n)) {
407  showKeyOff(d->m_keys.value(n), vel);
408  }
409 }
410 
416 int PianoScene::baseOctave() const { return d->m_baseOctave; }
417 
425 void PianoScene::triggerNoteOn( const int note, const int vel )
426 {
427  int n = d->m_baseOctave*12 + note + d->m_transpose;
428  if ((n >= d->m_minNote) && (n <= d->m_maxNote)) {
429  if (d->m_handler != nullptr) {
430  d->m_handler->noteOn(n, vel);
431  } else {
432  emit noteOn(n, vel);
433  }
434  }
435 }
436 
444 void PianoScene::triggerNoteOff( const int note, const int vel )
445 {
446  int n = d->m_baseOctave*12 + note + d->m_transpose;
447  if ((n >= d->m_minNote) && (n <= d->m_maxNote)) {
448  if (d->m_handler != nullptr) {
449  d->m_handler->noteOff(n, vel);
450  } else {
451  emit noteOff(n, vel);
452  }
453  }
454 }
455 
462 void PianoScene::setHighlightColorFromPolicy(PianoKey* key, int vel)
463 {
464  QColor c;
465  //qDebug() << Q_FUNC_INFO << key->getNote() << vel << d->m_velocityTint;
466  switch (d->m_hilightPalette.paletteId()) {
467  case PAL_SINGLE:
468  c = d->m_hilightPalette.getColor(0);
469  break;
470  case PAL_DOUBLE:
471  c = d->m_hilightPalette.getColor(key->getType());
472  break;
473  case PAL_CHANNELS:
474  c = d->m_hilightPalette.getColor(d->m_channel);
475  break;
476  case PAL_HISCALE:
477  c = d->m_hilightPalette.getColor(key->getDegree());
478  break;
479  default:
480  return;
481  }
482  if (c.isValid()) {
483  if (d->m_velocityTint && (vel >= 0) && (vel < 128)) {
484  QBrush h(c.lighter(200 - vel));
485  key->setPressedBrush(h);
486  } else {
487  key->setPressedBrush(c);
488  }
489  }
490 }
491 
496 void PianoScene::keyOn( PianoKey* key )
497 {
498  triggerNoteOn(key->getNote(), d->m_velocity);
499  showKeyOn(key, d->m_velocity);
500 }
501 
506 void PianoScene::keyOff( PianoKey* key )
507 {
508  triggerNoteOff(key->getNote(), 0);
509  showKeyOff(key, 0);
510 }
511 
517 void PianoScene::keyOn( PianoKey* key, qreal pressure )
518 {
519  int vel = d->m_velocity * pressure;
520  triggerNoteOn(key->getNote(), vel);
521  showKeyOn(key, vel);
522 }
523 
529 void PianoScene::keyOff( PianoKey* key, qreal pressure )
530 {
531  int vel = d->m_velocity * pressure;
532  triggerNoteOff(key->getNote(), vel);
533  showKeyOff(key, vel);
534 }
535 
540 void PianoScene::keyOn(const int note)
541 {
542  if (d->m_keys.contains(note))
543  keyOn(d->m_keys.value(note));
544  else
545  triggerNoteOn(note, d->m_velocity);
546 }
547 
552 void PianoScene::keyOff(const int note)
553 {
554  if (d->m_keys.contains(note))
555  keyOff(d->m_keys.value(note));
556  else
557  triggerNoteOff(note, d->m_velocity);
558 }
559 
565 {
566  return d->m_rawkbd;
567 }
568 
574 PianoKey* PianoScene::getKeyForPos( const QPointF& p ) const
575 {
576  PianoKey* key = nullptr;
577  QList<QGraphicsItem *> ptitems = this->items(p, Qt::IntersectsItemShape, Qt::DescendingOrder);
578  foreach(QGraphicsItem *itm, ptitems) {
579  key = dynamic_cast<PianoKey*>(itm);
580  if (key != nullptr)
581  break;
582  }
583  return key;
584 }
585 
590 void PianoScene::mouseMoveEvent ( QGraphicsSceneMouseEvent * mouseEvent )
591 {
592  if (d->m_mouseEnabled) {
593  if (d->m_mousePressed) {
594  PianoKey* key = getKeyForPos(mouseEvent->scenePos());
595  PianoKey* lastkey = getKeyForPos(mouseEvent->lastScenePos());
596  if ((lastkey != nullptr) && (lastkey != key) && lastkey->isPressed()) {
597  keyOff(lastkey);
598  }
599  if ((key != nullptr) && !key->isPressed()) {
600  keyOn(key);
601  }
602  mouseEvent->accept();
603  return;
604  }
605  }
606 }
607 
612 void PianoScene::mousePressEvent ( QGraphicsSceneMouseEvent * mouseEvent )
613 {
614  if (d->m_mouseEnabled) {
615  PianoKey* key = getKeyForPos(mouseEvent->scenePos());
616  if (key != nullptr && !key->isPressed()) {
617  keyOn(key);
618  d->m_mousePressed = true;
619  mouseEvent->accept();
620  return;
621  }
622  }
623 }
624 
629 void PianoScene::mouseReleaseEvent ( QGraphicsSceneMouseEvent * mouseEvent )
630 {
631  if (d->m_mouseEnabled) {
632  d->m_mousePressed = false;
633  PianoKey* key = getKeyForPos(mouseEvent->scenePos());
634  if (key != nullptr && key->isPressed()) {
635  keyOff(key);
636  mouseEvent->accept();
637  return;
638  }
639  }
640 }
641 
647 int PianoScene::getNoteFromKey( const int key ) const
648 {
649  if (d->m_keybdMap != nullptr) {
650  KeyboardMap::ConstIterator it = d->m_keybdMap->constFind(key);
651  if ((it != d->m_keybdMap->constEnd()) && (it.key() == key)) {
652  int note = it.value();
653  return note;
654  }
655  }
656  return -1;
657 }
658 
664 PianoKey* PianoScene::getPianoKey( const int key ) const
665 {
666  int note = getNoteFromKey(key);
667  if (d->m_keys.contains(note))
668  return d->m_keys.value(note);
669  return nullptr;
670 }
671 
676 void PianoScene::keyPressEvent ( QKeyEvent * keyEvent )
677 {
678  if ( d->m_keyboardEnabled) {
679  if ( !d->m_rawkbd && !keyEvent->isAutoRepeat() ) { // ignore auto-repeats
680  int note = getNoteFromKey(keyEvent->key());
681  if (note > -1)
682  keyOn(note);
683  }
684  keyEvent->accept();
685  return;
686  }
687  keyEvent->ignore();
688 }
689 
694 void PianoScene::keyReleaseEvent ( QKeyEvent * keyEvent )
695 {
696  if (d->m_keyboardEnabled) {
697  if ( !d->m_rawkbd && !keyEvent->isAutoRepeat() ) { // ignore auto-repeats
698  int note = getNoteFromKey(keyEvent->key());
699  if (note > -1)
700  keyOff(note);
701  }
702  keyEvent->accept();
703  return;
704  }
705  keyEvent->ignore();
706 }
707 
714 {
715  switch(event->type()) {
716  case QEvent::TouchBegin:
717  case QEvent::TouchEnd:
718  case QEvent::TouchUpdate:
719  {
720  QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
721  if (d->m_touchEnabled && touchEvent->device()->type() == QTouchDevice::DeviceType::TouchScreen) {
722  QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
723  foreach(const QTouchEvent::TouchPoint& touchPoint, touchPoints) {
724  switch (touchPoint.state()) {
725  //case Qt::TouchPointPrimary:
726  case Qt::TouchPointStationary:
727  continue;
728  case Qt::TouchPointReleased: {
729  PianoKey* key = getKeyForPos(touchPoint.scenePos());
730  if (key != nullptr && key->isPressed()) {
731  keyOff(key, touchPoint.pressure());
732  }
733  break;
734  }
735  case Qt::TouchPointPressed: {
736  PianoKey* key = getKeyForPos(touchPoint.scenePos());
737  if (key != nullptr && !key->isPressed()) {
738  keyOn(key, touchPoint.pressure());
739  key->ensureVisible();
740  }
741  break;
742  }
743  case Qt::TouchPointMoved: {
744  PianoKey* key = getKeyForPos(touchPoint.scenePos());
745  PianoKey* lastkey = getKeyForPos(touchPoint.lastScenePos());
746  if ((lastkey != nullptr) && (lastkey != key) && lastkey->isPressed()) {
747  keyOff(lastkey, touchPoint.pressure());
748  }
749  if ((key != nullptr) && !key->isPressed()) {
750  keyOn(key, touchPoint.pressure());
751  }
752  break;
753  }
754  default:
755  //qDebug() << "TouchPoint state: " << touchPoint.state();
756  break;
757  }
758  }
759  //qDebug() << "accepted event: " << event;
760  event->accept();
761  return true;
762  }
763  break;
764  }
765  default:
766  break;
767  }
768  //qDebug() << "unprocessed event: " << event;
769  return QGraphicsScene::event(event);
770 }
771 
776 {
777  foreach(PianoKey* key, d->m_keys) {
778  key->setPressed(false);
779  }
780 }
781 
788 void PianoScene::setKeyPressedColor(const QColor& color)
789 {
790  if (color.isValid()) {
791  d->m_hilightPalette = PianoPalette(PAL_SINGLE);
792  d->m_hilightPalette.setColor(0, color);
793  QBrush hilightBrush(color);
794  for (PianoKey* key : qAsConst(d->m_keys)) {
795  key->setPressedBrush(hilightBrush);
796  }
797  }
798 }
799 
804 {
805  d->m_hilightPalette.resetColors();
806  QBrush hilightBrush(getKeyPressedColor());
807  for (PianoKey* key : qAsConst(d->m_keys)) {
808  key->setPressedBrush(hilightBrush);
809  }
810 }
811 
817 {
818  return d->m_minNote;
819 }
820 
825 {
826  for (PianoKey* key : qAsConst(d->m_keys)) {
827  int n = d->m_baseOctave*12 + key->getNote() + d->m_transpose;
828  bool b = !(n > d->m_maxNote) && !(n < d->m_minNote);
829  key->setVisible(b);
830  }
831 }
832 
837 void PianoScene::setMinNote(const int note)
838 {
839  if (d->m_minNote != note) {
840  d->m_minNote = note;
841  hideOrShowKeys();
842  }
843 }
844 
850 {
851  return d->m_maxNote;
852 }
853 
858 void PianoScene::setMaxNote(const int note)
859 {
860  if (d->m_maxNote != note) {
861  d->m_maxNote = note;
862  hideOrShowKeys();
863  }
864 }
865 
871 {
872  return d->m_transpose;
873 }
874 
879 void PianoScene::setBaseOctave(const int base)
880 {
881  if (d->m_baseOctave != base) {
882  d->m_baseOctave = base;
883  hideOrShowKeys();
884  refreshLabels();
885  }
886 }
887 
893 {
894  return d->m_numKeys;
895 }
896 
902 {
903  return d->m_startKey;
904 }
905 
911 bool PianoScene::isOctaveStart(const int note)
912 {
913  return (note + d->m_transpose + 12) % 12 == 0;
914 }
915 
921 QString PianoScene::noteName( PianoKey* key )
922 {
923  Q_ASSERT(key != nullptr);
924  int note = key->getNote();
925  int num = (note + d->m_transpose + 12) % 12;
926  int adj = ((note + d->m_transpose < 0) ? 2 : 1) - d->m_octave + 1;
927  int oct = d->m_baseOctave + ((note + d->m_transpose) / 12) - adj;
928  if (d->m_noteNames.isEmpty()) {
929  QString name;
930  if (!d->m_names_f.isEmpty() && !d->m_names_s.isEmpty()) {
931  switch(d->m_alterations) {
932  case ShowFlats:
933  name = d->m_names_f.value(num);
934  break;
935  case ShowSharps:
936  name = d->m_names_s.value(num);
937  break;
938  case ShowNothing:
939  if (key->isBlack()) {
940  return QString();
941  }
942  name = d->m_names_s.value(num);
943  break;
944  default:
945  break;
946  }
947  }
948  if (d->m_octave==OctaveNothing) {
949  return name;
950  } else {
951  return QString("%1%2").arg(name).arg(oct);
952  }
953  } else {
954  if (d->m_noteNames.length() == 128) {
955  int n = d->m_baseOctave*12 + note + d->m_transpose;
956  //qDebug() << Q_FUNC_INFO << n << note;
957  if (n >= 0 && n < d->m_noteNames.length()) {
958  return d->m_noteNames.value(n);
959  }
960  } else if (d->m_noteNames.length() >= 12) {
961  if (d->m_octave==OctaveNothing) {
962  return d->m_noteNames.value(num);
963  } else {
964  return QString("%1%2").arg(d->m_noteNames.value(num)).arg(oct);
965  }
966  }
967  return QString();
968  }
969 }
970 
975 {
976  for (KeyLabel* lbl : qAsConst(d->m_labels)) {
977  PianoKey* key = dynamic_cast<PianoKey*>(lbl->parentItem());
978  if (key != nullptr) {
979  lbl->setVisible(false);
980  lbl->setFont(font());
981  lbl->setDefaultTextColor(d->m_foregroundPalette.getColor(key->isBlack() ? 1 : 0));
982  lbl->setOrientation(d->m_orientation);
983  lbl->setPlainText(noteName(key));
984  lbl->adjust();
985  lbl->setVisible((d->m_showLabels == ShowAlways) ||
986  (d->m_showLabels == ShowMinimum && isOctaveStart(key->getNote())));
987  }
988  }
989 }
990 
995 {
996  for (PianoKey* key : qAsConst(d->m_keys)) {
997  if (d->m_showColorScale && (d->m_backgroundPalette.paletteId() == PAL_SCALE)) {
998  int degree = key->getNote() % 12;
999  key->setBrush(d->m_backgroundPalette.getColor(degree));
1000  } else {
1001  key->setBrush(d->m_backgroundPalette.getColor(key->isBlack() ? 1 : 0));
1002  }
1003  key->setPressed(false);
1004  }
1005 }
1006 
1013 {
1014  //qDebug() << Q_FUNC_INFO << show;
1015  if (d->m_showLabels != show) {
1016  d->m_showLabels = show;
1017  refreshLabels();
1018  }
1019 }
1020 
1027 {
1028  return d->m_alterations;
1029 }
1030 
1037 {
1038  if (d->m_alterations != use) {
1039  d->m_alterations = use;
1040  refreshLabels();
1041  }
1042 }
1043 
1049 {
1050  return d->m_octave;
1051 }
1052 
1058 {
1059  if (d->m_orientation != orientation) {
1060  d->m_orientation = orientation;
1061  refreshLabels();
1062  }
1063 }
1064 
1065 bool PianoScene::isKeyboardEnabled() const
1066 {
1067  return d->m_keyboardEnabled;
1068 }
1069 
1070 void PianoScene::setOctave(const LabelCentralOctave octave)
1071 {
1072  if (d->m_octave != octave) {
1073  d->m_octave = octave;
1074  refreshLabels();
1075  }
1076 }
1077 
1078 LabelOrientation PianoScene::getOrientation() const
1079 {
1080  return d->m_orientation;
1081 }
1082 
1087 void PianoScene::setTranspose(const int transpose)
1088 {
1089  if (d->m_transpose != transpose && transpose > -12 && transpose < 12) {
1090  d->m_transpose = transpose;
1091  hideOrShowKeys();
1092  refreshLabels();
1093  }
1094 }
1095 
1102 {
1103  return d->m_showLabels;
1104 }
1105 
1111 {
1112  if (d->m_rawkbd != b) {
1113  d->m_rawkbd = b;
1114  }
1115 }
1116 
1121 QStringList PianoScene::customNoteNames() const
1122 {
1123  return d->m_noteNames;
1124 }
1125 
1131 {
1132  return d->m_names_s;
1133 }
1134 
1140 {
1141  return d->m_velocity;
1142 }
1143 
1148 void PianoScene::setVelocity(const int velocity)
1149 {
1150  d->m_velocity = velocity;
1151 }
1152 
1159 {
1160  return d->m_channel;
1161 }
1162 
1168 void PianoScene::setChannel(const int channel)
1169 {
1170  d->m_channel = channel;
1171 }
1172 
1177 void PianoScene::useCustomNoteNames(const QStringList& names)
1178 {
1179  //qDebug() << Q_FUNC_INFO << names;
1180  d->m_noteNames = names;
1181  refreshLabels();
1182 }
1183 
1188 {
1189  //qDebug() << Q_FUNC_INFO;
1190  d->m_noteNames.clear();
1191  refreshLabels();
1192 }
1193 
1198 void PianoScene::setKeyboardEnabled(const bool enable)
1199 {
1200  if (enable != d->m_keyboardEnabled) {
1201  d->m_keyboardEnabled = enable;
1202  }
1203 }
1204 
1210 {
1211  return d->m_mouseEnabled;
1212 }
1213 
1218 void PianoScene::setMouseEnabled(const bool enable)
1219 {
1220  if (enable != d->m_mouseEnabled) {
1221  d->m_mouseEnabled = enable;
1222  }
1223 }
1224 
1230 {
1231  return d->m_touchEnabled;
1232 }
1233 
1238 void PianoScene::setTouchEnabled(const bool enable)
1239 {
1240  if (enable != d->m_touchEnabled) {
1241  d->m_touchEnabled = enable;
1242  }
1243 }
1244 
1250 {
1251  return d->m_velocityTint;
1252 }
1253 
1258 void PianoScene::setVelocityTint(const bool enable)
1259 {
1260  //qDebug() << Q_FUNC_INFO << enable;
1261  d->m_velocityTint = enable;
1262 }
1263 
1268 {
1269  d->m_names_s = QStringList{
1270  tr("C"),
1271  tr("C♯"),
1272  tr("D"),
1273  tr("D♯"),
1274  tr("E"),
1275  tr("F"),
1276  tr("F♯"),
1277  tr("G"),
1278  tr("G♯"),
1279  tr("A"),
1280  tr("A♯"),
1281  tr("B")};
1282  d->m_names_f = QStringList{
1283  tr("C"),
1284  tr("Dâ™­"),
1285  tr("D"),
1286  tr("Eâ™­"),
1287  tr("E"),
1288  tr("F"),
1289  tr("Gâ™­"),
1290  tr("G"),
1291  tr("Aâ™­"),
1292  tr("A"),
1293  tr("Bâ™­"),
1294  tr("B")};
1295  refreshLabels();
1296 }
1297 
1302 void PianoScene::setShowColorScale(const bool show)
1303 {
1304  if (d->m_showColorScale != show) {
1305  d->m_showColorScale = show;
1306  refreshKeys();
1307  invalidate();
1308  }
1309 }
1310 
1316 {
1317  return d->m_hilightPalette.getColor(0);
1318 }
1319 
1325 {
1326  if (d->m_hilightPalette != p) {
1327  d->m_hilightPalette = p;
1328  refreshKeys();
1329  invalidate();
1330  }
1331 }
1332 
1338 {
1339  return d->m_backgroundPalette;
1340 }
1341 
1347 {
1348  if (d->m_backgroundPalette != p) {
1349  d->m_backgroundPalette = p;
1350  refreshKeys();
1351  invalidate();
1352  }
1353 }
1354 
1360 {
1361  return d->m_foregroundPalette;
1362 }
1363 
1369 {
1370  if (d->m_foregroundPalette != p) {
1371  d->m_foregroundPalette = p;
1372  refreshLabels();
1373  invalidate();
1374  }
1375 }
1376 
1382 {
1383  return d->m_showColorScale;
1384 }
1385 
1386 void PianoScene::setKeyPicture(const bool natural, const QPixmap &pix)
1387 {
1388  d->m_keyPix[int(natural)] = pix;
1389  for (PianoKey* key : qAsConst(d->m_keys)) {
1390  if (key->isBlack() == !natural) {
1391  key->setPixmap(pix);
1392  }
1393  }
1394 }
1395 
1396 QPixmap PianoScene::getKeyPicture(const bool natural)
1397 {
1398  return d->m_keyPix[int(natural)];
1399 }
1400 
1401 void PianoScene::setUseKeyPictures(const bool enable)
1402 {
1403  d->m_useKeyPix = enable;
1404  for (PianoKey* key : qAsConst(d->m_keys)) {
1405  key->setUsePixmap(enable);
1406  }
1407 }
1408 
1409 bool PianoScene::getUseKeyPictures() const
1410 {
1411  return d->m_useKeyPix;
1412 }
1413 
1414 void PianoScene::saveData(QByteArray &ba)
1415 {
1416  d->saveData(ba);
1417 }
1418 
1419 void PianoScene::loadData(QByteArray &ba)
1420 {
1421  d->loadData(ba);
1422 }
1423 
1424 } // namespace widgets
1425 } // 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:775
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:425
void resetKeyPressedColor()
Assigns the default highlight palette colors and assigns it to the scene.
Definition: pianoscene.cpp:803
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:552
void showKeyOff(PianoKey *key, int vel)
Displays as deactivated a key.
Definition: pianoscene.cpp:356
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:788
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:540
void useStandardNoteNames()
Assigns the standard note names, clearing the list of custom note names.
void hideOrShowKeys()
Hides or shows keys.
Definition: pianoscene.cpp:824
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:186
bool event(QEvent *event) override
Processes touch screen events.
Definition: pianoscene.cpp:713
int baseOctave() const
Returns the base octave number.
Definition: pianoscene.cpp:416
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:289
void setKeyboardMap(KeyboardMap *map)
Assigns the computer keyboard note map.
Definition: pianoscene.cpp:255
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:837
bool showColorScale() const
Returns whether the color scale mode is enabled.
void setBaseOctave(const int base)
Assigns the octave base number.
Definition: pianoscene.cpp:879
PianoKey * getKeyForPos(const QPointF &p) const
Returns the piano key for the given scene point coordenates.
Definition: pianoscene.cpp:574
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:892
PianoPalette getHighlightPalette()
Returns the palette used for highlighting the played keys.
Definition: pianoscene.cpp:298
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:590
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:444
PianoKey * getPianoKey(const int key) const
Returns the piano key object corresponding to the given computer keyboard key.
Definition: pianoscene.cpp:664
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:676
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:647
void refreshLabels()
Refresh the visibility and other attributes of the labels shown over the piano keys.
Definition: pianoscene.cpp:974
void showNoteOff(const int note, int vel=-1)
Displays deactivated the corresponding key for a given MIDI note, with MIDI velocity.
Definition: pianoscene.cpp:403
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.
Definition: pianoscene.cpp:994
QSize sizeHint() const
Returns the calculated size of the scene.
Definition: pianoscene.cpp:246
bool isOctaveStart(const int note)
Returns whether the given note number is a octave startup note.
Definition: pianoscene.cpp:911
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:612
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:849
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:462
PianoHandler * getPianoHandler() const
Gets the PianoHandler pointer to the note receiver.
Definition: pianoscene.cpp:276
void showKeyOn(PianoKey *key, QColor color, int vel)
Displays highlighted the activated key with the supplied color and note velocity.
Definition: pianoscene.cpp:328
KeyboardMap * getKeyboardMap() const
Returns the computer keyboard note map.
Definition: pianoscene.cpp:264
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:564
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:376
void keyReleaseEvent(QKeyEvent *keyEvent) override
This event handler, for event keyEvent, is reimplemented to receive key release events.
Definition: pianoscene.cpp:694
void setMaxNote(const int note)
Assigns the maximum MIDI note number that will be displayed.
Definition: pianoscene.cpp:858
void retranslate()
Retranslates the standard note names.
int startKey() const
Returns the first key number that will be displayed.
Definition: pianoscene.cpp:901
void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) override
This event handler, for event mouseEvent, is reimplemented to receive mouse release events for the sc...
Definition: pianoscene.cpp:629
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:307
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:816
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:870
QString noteName(PianoKey *key)
Returns the note name string that will be displayed over a given piano key.
Definition: pianoscene.cpp:921
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.