drumstick  2.1.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  }
335  displayKeyOn(key);
336 }
337 
343 void PianoScene::showKeyOn( PianoKey* key, int vel )
344 {
345  setHighlightColorFromPolicy(key, vel);
346  displayKeyOn(key);
347 }
348 
354 void PianoScene::showKeyOff( PianoKey* key, int vel)
355 {
356  Q_UNUSED(vel)
357  key->setPressed(false);
358  emit signalName(QString());
359  KeyLabel* lbl = dynamic_cast<KeyLabel*>(key->childItems().constFirst());
360  if (lbl != nullptr) {
361  lbl->restoreColor();
362  if (d->m_showLabels == ShowActivated) {
363  lbl->setVisible(false);
364  }
365  }
366 }
367 
374 void PianoScene::showNoteOn( const int note, QColor color, int vel )
375 {
376  //qDebug() << Q_FUNC_INFO << note << vel << color;
377  int n = note - d->m_baseOctave*12 - d->m_transpose;
378  if ((note >= d->m_minNote) && (note <= d->m_maxNote) && d->m_keys.contains(n) && color.isValid())
379  showKeyOn(d->m_keys.value(n), color, vel);
380 }
381 
387 void PianoScene::showNoteOn( const int note, int vel )
388 {
389  //qDebug() << Q_FUNC_INFO << note << vel;
390  int n = note - d->m_baseOctave*12 - d->m_transpose;
391  if ((note >= d->m_minNote) && (note <= d->m_maxNote) && d->m_keys.contains(n)) {
392  showKeyOn(d->m_keys.value(n), vel);
393  }
394 }
395 
401 void PianoScene::showNoteOff( const int note, int vel )
402 {
403  int n = note - d->m_baseOctave*12 - d->m_transpose;
404  if ((note >= d->m_minNote) && (note <= d->m_maxNote) && d->m_keys.contains(n)) {
405  showKeyOff(d->m_keys.value(n), vel);
406  }
407 }
408 
414 int PianoScene::baseOctave() const { return d->m_baseOctave; }
415 
423 void PianoScene::triggerNoteOn( const int note, const int vel )
424 {
425  int n = d->m_baseOctave*12 + note + d->m_transpose;
426  if ((n >= d->m_minNote) && (n <= d->m_maxNote)) {
427  if (d->m_handler != nullptr) {
428  d->m_handler->noteOn(n, vel);
429  } else {
430  emit noteOn(n, vel);
431  }
432  }
433 }
434 
442 void PianoScene::triggerNoteOff( const int note, const int vel )
443 {
444  int n = d->m_baseOctave*12 + note + d->m_transpose;
445  if ((n >= d->m_minNote) && (n <= d->m_maxNote)) {
446  if (d->m_handler != nullptr) {
447  d->m_handler->noteOff(n, vel);
448  } else {
449  emit noteOff(n, vel);
450  }
451  }
452 }
453 
460 void PianoScene::setHighlightColorFromPolicy(PianoKey* key, int vel)
461 {
462  QColor c;
463  //qDebug() << Q_FUNC_INFO << key->getNote() << vel << d->m_velocityTint;
464  switch (d->m_hilightPalette.paletteId()) {
465  case PAL_SINGLE:
466  c = d->m_hilightPalette.getColor(0);
467  break;
468  case PAL_DOUBLE:
469  c = d->m_hilightPalette.getColor(key->getType());
470  break;
471  case PAL_CHANNELS:
472  c = d->m_hilightPalette.getColor(d->m_channel);
473  break;
474  case PAL_HISCALE:
475  c = d->m_hilightPalette.getColor(key->getDegree());
476  break;
477  default:
478  return;
479  }
480  if (c.isValid()) {
481  if (d->m_velocityTint && (vel >= 0) && (vel < 128)) {
482  QBrush h(c.lighter(200 - vel));
483  key->setPressedBrush(h);
484  } else {
485  key->setPressedBrush(c);
486  }
487  }
488 }
489 
494 void PianoScene::keyOn( PianoKey* key )
495 {
496  triggerNoteOn(key->getNote(), d->m_velocity);
497  showKeyOn(key, d->m_velocity);
498 }
499 
504 void PianoScene::keyOff( PianoKey* key )
505 {
506  triggerNoteOff(key->getNote(), 0);
507  showKeyOff(key, 0);
508 }
509 
515 void PianoScene::keyOn( PianoKey* key, qreal pressure )
516 {
517  int vel = d->m_velocity * pressure;
518  triggerNoteOn(key->getNote(), vel);
519  showKeyOn(key, vel);
520 }
521 
527 void PianoScene::keyOff( PianoKey* key, qreal pressure )
528 {
529  int vel = d->m_velocity * pressure;
530  triggerNoteOff(key->getNote(), vel);
531  showKeyOff(key, vel);
532 }
533 
538 void PianoScene::keyOn(const int note)
539 {
540  if (d->m_keys.contains(note))
541  keyOn(d->m_keys.value(note));
542  else
543  triggerNoteOn(note, d->m_velocity);
544 }
545 
550 void PianoScene::keyOff(const int note)
551 {
552  if (d->m_keys.contains(note))
553  keyOff(d->m_keys.value(note));
554  else
555  triggerNoteOff(note, d->m_velocity);
556 }
557 
563 {
564  return d->m_rawkbd;
565 }
566 
572 PianoKey* PianoScene::getKeyForPos( const QPointF& p ) const
573 {
574  PianoKey* key = nullptr;
575  QList<QGraphicsItem *> ptitems = this->items(p, Qt::IntersectsItemShape, Qt::DescendingOrder);
576  foreach(QGraphicsItem *itm, ptitems) {
577  key = dynamic_cast<PianoKey*>(itm);
578  if (key != nullptr)
579  break;
580  }
581  return key;
582 }
583 
588 void PianoScene::mouseMoveEvent ( QGraphicsSceneMouseEvent * mouseEvent )
589 {
590  if (d->m_mouseEnabled) {
591  if (d->m_mousePressed) {
592  PianoKey* key = getKeyForPos(mouseEvent->scenePos());
593  PianoKey* lastkey = getKeyForPos(mouseEvent->lastScenePos());
594  if ((lastkey != nullptr) && (lastkey != key) && lastkey->isPressed()) {
595  keyOff(lastkey);
596  }
597  if ((key != nullptr) && !key->isPressed()) {
598  keyOn(key);
599  }
600  mouseEvent->accept();
601  return;
602  }
603  }
604 }
605 
610 void PianoScene::mousePressEvent ( QGraphicsSceneMouseEvent * mouseEvent )
611 {
612  if (d->m_mouseEnabled) {
613  PianoKey* key = getKeyForPos(mouseEvent->scenePos());
614  if (key != nullptr && !key->isPressed()) {
615  keyOn(key);
616  d->m_mousePressed = true;
617  mouseEvent->accept();
618  return;
619  }
620  }
621 }
622 
627 void PianoScene::mouseReleaseEvent ( QGraphicsSceneMouseEvent * mouseEvent )
628 {
629  if (d->m_mouseEnabled) {
630  d->m_mousePressed = false;
631  PianoKey* key = getKeyForPos(mouseEvent->scenePos());
632  if (key != nullptr && key->isPressed()) {
633  keyOff(key);
634  mouseEvent->accept();
635  return;
636  }
637  }
638 }
639 
645 int PianoScene::getNoteFromKey( const int key ) const
646 {
647  if (d->m_keybdMap != nullptr) {
648  KeyboardMap::ConstIterator it = d->m_keybdMap->constFind(key);
649  if ((it != d->m_keybdMap->constEnd()) && (it.key() == key)) {
650  int note = it.value();
651  return note;
652  }
653  }
654  return -1;
655 }
656 
662 PianoKey* PianoScene::getPianoKey( const int key ) const
663 {
664  int note = getNoteFromKey(key);
665  if (d->m_keys.contains(note))
666  return d->m_keys.value(note);
667  return nullptr;
668 }
669 
674 void PianoScene::keyPressEvent ( QKeyEvent * keyEvent )
675 {
676  if ( d->m_keyboardEnabled) {
677  if ( !d->m_rawkbd && !keyEvent->isAutoRepeat() ) { // ignore auto-repeats
678  int note = getNoteFromKey(keyEvent->key());
679  if (note > -1)
680  keyOn(note);
681  }
682  keyEvent->accept();
683  return;
684  }
685  keyEvent->ignore();
686 }
687 
692 void PianoScene::keyReleaseEvent ( QKeyEvent * keyEvent )
693 {
694  if (d->m_keyboardEnabled) {
695  if ( !d->m_rawkbd && !keyEvent->isAutoRepeat() ) { // ignore auto-repeats
696  int note = getNoteFromKey(keyEvent->key());
697  if (note > -1)
698  keyOff(note);
699  }
700  keyEvent->accept();
701  return;
702  }
703  keyEvent->ignore();
704 }
705 
712 {
713  switch(event->type()) {
714  case QEvent::TouchBegin:
715  case QEvent::TouchEnd:
716  case QEvent::TouchUpdate:
717  {
718  QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
719  if (d->m_touchEnabled && touchEvent->device()->type() == QTouchDevice::DeviceType::TouchScreen) {
720  QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
721  foreach(const QTouchEvent::TouchPoint& touchPoint, touchPoints) {
722  switch (touchPoint.state()) {
723  //case Qt::TouchPointPrimary:
724  case Qt::TouchPointStationary:
725  continue;
726  case Qt::TouchPointReleased: {
727  PianoKey* key = getKeyForPos(touchPoint.scenePos());
728  if (key != nullptr && key->isPressed()) {
729  keyOff(key, touchPoint.pressure());
730  }
731  break;
732  }
733  case Qt::TouchPointPressed: {
734  PianoKey* key = getKeyForPos(touchPoint.scenePos());
735  if (key != nullptr && !key->isPressed()) {
736  keyOn(key, touchPoint.pressure());
737  key->ensureVisible();
738  }
739  break;
740  }
741  case Qt::TouchPointMoved: {
742  PianoKey* key = getKeyForPos(touchPoint.scenePos());
743  PianoKey* lastkey = getKeyForPos(touchPoint.lastScenePos());
744  if ((lastkey != nullptr) && (lastkey != key) && lastkey->isPressed()) {
745  keyOff(lastkey, touchPoint.pressure());
746  }
747  if ((key != nullptr) && !key->isPressed()) {
748  keyOn(key, touchPoint.pressure());
749  }
750  break;
751  }
752  default:
753  //qDebug() << "TouchPoint state: " << touchPoint.state();
754  break;
755  }
756  }
757  //qDebug() << "accepted event: " << event;
758  event->accept();
759  return true;
760  }
761  break;
762  }
763  default:
764  break;
765  }
766  //qDebug() << "unprocessed event: " << event;
767  return QGraphicsScene::event(event);
768 }
769 
774 {
775  foreach(PianoKey* key, d->m_keys) {
776  key->setPressed(false);
777  }
778 }
779 
786 void PianoScene::setKeyPressedColor(const QColor& color)
787 {
788  if (color.isValid()) {
789  d->m_hilightPalette = PianoPalette(PAL_SINGLE);
790  d->m_hilightPalette.setColor(0, color);
791  QBrush hilightBrush(color);
792  for (PianoKey* key : qAsConst(d->m_keys)) {
793  key->setPressedBrush(hilightBrush);
794  }
795  }
796 }
797 
802 {
803  d->m_hilightPalette.resetColors();
804  QBrush hilightBrush(getKeyPressedColor());
805  for (PianoKey* key : qAsConst(d->m_keys)) {
806  key->setPressedBrush(hilightBrush);
807  }
808 }
809 
815 {
816  return d->m_minNote;
817 }
818 
823 {
824  for (PianoKey* key : qAsConst(d->m_keys)) {
825  int n = d->m_baseOctave*12 + key->getNote() + d->m_transpose;
826  bool b = !(n > d->m_maxNote) && !(n < d->m_minNote);
827  key->setVisible(b);
828  }
829 }
830 
835 void PianoScene::setMinNote(const int note)
836 {
837  if (d->m_minNote != note) {
838  d->m_minNote = note;
839  hideOrShowKeys();
840  }
841 }
842 
848 {
849  return d->m_maxNote;
850 }
851 
856 void PianoScene::setMaxNote(const int note)
857 {
858  if (d->m_maxNote != note) {
859  d->m_maxNote = note;
860  hideOrShowKeys();
861  }
862 }
863 
869 {
870  return d->m_transpose;
871 }
872 
877 void PianoScene::setBaseOctave(const int base)
878 {
879  if (d->m_baseOctave != base) {
880  d->m_baseOctave = base;
881  hideOrShowKeys();
882  refreshLabels();
883  }
884 }
885 
891 {
892  return d->m_numKeys;
893 }
894 
900 {
901  return d->m_startKey;
902 }
903 
909 bool PianoScene::isOctaveStart(const int note)
910 {
911  return (note + d->m_transpose + 12) % 12 == 0;
912 }
913 
919 QString PianoScene::noteName( PianoKey* key )
920 {
921  Q_ASSERT(key != nullptr);
922  int note = key->getNote();
923  int num = (note + d->m_transpose + 12) % 12;
924  int adj = ((note + d->m_transpose < 0) ? 2 : 1) - d->m_octave + 1;
925  int oct = d->m_baseOctave + ((note + d->m_transpose) / 12) - adj;
926  if (d->m_noteNames.isEmpty()) {
927  QString name;
928  if (!d->m_names_f.isEmpty() && !d->m_names_s.isEmpty()) {
929  switch(d->m_alterations) {
930  case ShowFlats:
931  name = d->m_names_f.value(num);
932  break;
933  case ShowSharps:
934  name = d->m_names_s.value(num);
935  break;
936  case ShowNothing:
937  if (key->isBlack()) {
938  return QString();
939  }
940  name = d->m_names_s.value(num);
941  break;
942  default:
943  break;
944  }
945  }
946  if (d->m_octave==OctaveNothing) {
947  return name;
948  } else {
949  return QString("%1%2").arg(name).arg(oct);
950  }
951  } else {
952  if (d->m_noteNames.length() == 128) {
953  int n = d->m_baseOctave*12 + note + d->m_transpose;
954  //qDebug() << Q_FUNC_INFO << n << note;
955  if (n >= 0 && n < d->m_noteNames.length()) {
956  return d->m_noteNames.value(n);
957  }
958  } else if (d->m_noteNames.length() >= 12) {
959  if (d->m_octave==OctaveNothing) {
960  return d->m_noteNames.value(num);
961  } else {
962  return QString("%1%2").arg(d->m_noteNames.value(num)).arg(oct);
963  }
964  }
965  return QString();
966  }
967 }
968 
973 {
974  for (KeyLabel* lbl : qAsConst(d->m_labels)) {
975  PianoKey* key = dynamic_cast<PianoKey*>(lbl->parentItem());
976  if (key != nullptr) {
977  lbl->setVisible(false);
978  lbl->setFont(font());
979  lbl->setDefaultTextColor(d->m_foregroundPalette.getColor(key->isBlack() ? 1 : 0));
980  lbl->setOrientation(d->m_orientation);
981  lbl->setPlainText(noteName(key));
982  lbl->adjust();
983  lbl->setVisible((d->m_showLabels == ShowAlways) ||
984  (d->m_showLabels == ShowMinimum && isOctaveStart(key->getNote())));
985  }
986  }
987 }
988 
993 {
994  for (PianoKey* key : qAsConst(d->m_keys)) {
995  if (d->m_showColorScale && (d->m_backgroundPalette.paletteId() == PAL_SCALE)) {
996  int degree = key->getNote() % 12;
997  key->setBrush(d->m_backgroundPalette.getColor(degree));
998  } else {
999  key->setBrush(d->m_backgroundPalette.getColor(key->isBlack() ? 1 : 0));
1000  }
1001  key->setPressed(false);
1002  }
1003 }
1004 
1011 {
1012  //qDebug() << Q_FUNC_INFO << show;
1013  if (d->m_showLabels != show) {
1014  d->m_showLabels = show;
1015  refreshLabels();
1016  }
1017 }
1018 
1025 {
1026  return d->m_alterations;
1027 }
1028 
1035 {
1036  if (d->m_alterations != use) {
1037  d->m_alterations = use;
1038  refreshLabels();
1039  }
1040 }
1041 
1047 {
1048  return d->m_octave;
1049 }
1050 
1056 {
1057  if (d->m_orientation != orientation) {
1058  d->m_orientation = orientation;
1059  refreshLabels();
1060  }
1061 }
1062 
1063 bool PianoScene::isKeyboardEnabled() const
1064 {
1065  return d->m_keyboardEnabled;
1066 }
1067 
1068 void PianoScene::setOctave(const LabelCentralOctave octave)
1069 {
1070  if (d->m_octave != octave) {
1071  d->m_octave = octave;
1072  refreshLabels();
1073  }
1074 }
1075 
1076 LabelOrientation PianoScene::getOrientation() const
1077 {
1078  return d->m_orientation;
1079 }
1080 
1085 void PianoScene::setTranspose(const int transpose)
1086 {
1087  if (d->m_transpose != transpose && transpose > -12 && transpose < 12) {
1088  d->m_transpose = transpose;
1089  hideOrShowKeys();
1090  refreshLabels();
1091  }
1092 }
1093 
1100 {
1101  return d->m_showLabels;
1102 }
1103 
1109 {
1110  if (d->m_rawkbd != b) {
1111  d->m_rawkbd = b;
1112  }
1113 }
1114 
1119 QStringList PianoScene::customNoteNames() const
1120 {
1121  return d->m_noteNames;
1122 }
1123 
1129 {
1130  return d->m_names_s;
1131 }
1132 
1138 {
1139  return d->m_velocity;
1140 }
1141 
1146 void PianoScene::setVelocity(const int velocity)
1147 {
1148  d->m_velocity = velocity;
1149 }
1150 
1157 {
1158  return d->m_channel;
1159 }
1160 
1166 void PianoScene::setChannel(const int channel)
1167 {
1168  d->m_channel = channel;
1169 }
1170 
1175 void PianoScene::useCustomNoteNames(const QStringList& names)
1176 {
1177  //qDebug() << Q_FUNC_INFO << names;
1178  d->m_noteNames = names;
1179  refreshLabels();
1180 }
1181 
1186 {
1187  //qDebug() << Q_FUNC_INFO;
1188  d->m_noteNames.clear();
1189  refreshLabels();
1190 }
1191 
1196 void PianoScene::setKeyboardEnabled(const bool enable)
1197 {
1198  if (enable != d->m_keyboardEnabled) {
1199  d->m_keyboardEnabled = enable;
1200  }
1201 }
1202 
1208 {
1209  return d->m_mouseEnabled;
1210 }
1211 
1216 void PianoScene::setMouseEnabled(const bool enable)
1217 {
1218  if (enable != d->m_mouseEnabled) {
1219  d->m_mouseEnabled = enable;
1220  }
1221 }
1222 
1228 {
1229  return d->m_touchEnabled;
1230 }
1231 
1236 void PianoScene::setTouchEnabled(const bool enable)
1237 {
1238  if (enable != d->m_touchEnabled) {
1239  d->m_touchEnabled = enable;
1240  }
1241 }
1242 
1248 {
1249  return d->m_velocityTint;
1250 }
1251 
1256 void PianoScene::setVelocityTint(const bool enable)
1257 {
1258  //qDebug() << Q_FUNC_INFO << enable;
1259  d->m_velocityTint = enable;
1260 }
1261 
1266 {
1267  d->m_names_s = QStringList{
1268  tr("C"),
1269  tr("C♯"),
1270  tr("D"),
1271  tr("D♯"),
1272  tr("E"),
1273  tr("F"),
1274  tr("F♯"),
1275  tr("G"),
1276  tr("G♯"),
1277  tr("A"),
1278  tr("A♯"),
1279  tr("B")};
1280  d->m_names_f = QStringList{
1281  tr("C"),
1282  tr("Dâ™­"),
1283  tr("D"),
1284  tr("Eâ™­"),
1285  tr("E"),
1286  tr("F"),
1287  tr("Gâ™­"),
1288  tr("G"),
1289  tr("Aâ™­"),
1290  tr("A"),
1291  tr("Bâ™­"),
1292  tr("B")};
1293  refreshLabels();
1294 }
1295 
1300 void PianoScene::setShowColorScale(const bool show)
1301 {
1302  if (d->m_showColorScale != show) {
1303  d->m_showColorScale = show;
1304  refreshKeys();
1305  invalidate();
1306  }
1307 }
1308 
1314 {
1315  return d->m_hilightPalette.getColor(0);
1316 }
1317 
1323 {
1324  if (d->m_hilightPalette != p) {
1325  d->m_hilightPalette = p;
1326  refreshKeys();
1327  invalidate();
1328  }
1329 }
1330 
1336 {
1337  return d->m_backgroundPalette;
1338 }
1339 
1345 {
1346  if (d->m_backgroundPalette != p) {
1347  d->m_backgroundPalette = p;
1348  refreshKeys();
1349  invalidate();
1350  }
1351 }
1352 
1358 {
1359  return d->m_foregroundPalette;
1360 }
1361 
1367 {
1368  if (d->m_foregroundPalette != p) {
1369  d->m_foregroundPalette = p;
1370  refreshLabels();
1371  invalidate();
1372  }
1373 }
1374 
1380 {
1381  return d->m_showColorScale;
1382 }
1383 
1384 void PianoScene::setKeyPicture(const bool natural, const QPixmap &pix)
1385 {
1386  d->m_keyPix[int(natural)] = pix;
1387  for (PianoKey* key : qAsConst(d->m_keys)) {
1388  if (key->isBlack() == !natural) {
1389  key->setPixmap(pix);
1390  }
1391  }
1392 }
1393 
1394 QPixmap PianoScene::getKeyPicture(const bool natural)
1395 {
1396  return d->m_keyPix[int(natural)];
1397 }
1398 
1399 void PianoScene::setUseKeyPictures(const bool enable)
1400 {
1401  d->m_useKeyPix = enable;
1402  for (PianoKey* key : qAsConst(d->m_keys)) {
1403  key->setUsePixmap(enable);
1404  }
1405 }
1406 
1407 bool PianoScene::getUseKeyPictures() const
1408 {
1409  return d->m_useKeyPix;
1410 }
1411 
1412 void PianoScene::saveData(QByteArray &ba)
1413 {
1414  d->saveData(ba);
1415 }
1416 
1417 void PianoScene::loadData(QByteArray &ba)
1418 {
1419  d->loadData(ba);
1420 }
1421 
1422 } // namespace widgets
1423 } // 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:773
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:423
void resetKeyPressedColor()
Assigns the default highlight palette colors and assigns it to the scene.
Definition: pianoscene.cpp:801
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:550
void showKeyOff(PianoKey *key, int vel)
Displays as deactivated a key.
Definition: pianoscene.cpp:354
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:786
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:538
void useStandardNoteNames()
Assigns the standard note names, clearing the list of custom note names.
void hideOrShowKeys()
Hides or shows keys.
Definition: pianoscene.cpp:822
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:711
int baseOctave() const
Returns the base octave number.
Definition: pianoscene.cpp:414
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:835
bool showColorScale() const
Returns whether the color scale mode is enabled.
void setBaseOctave(const int base)
Assigns the octave base number.
Definition: pianoscene.cpp:877
PianoKey * getKeyForPos(const QPointF &p) const
Returns the piano key for the given scene point coordenates.
Definition: pianoscene.cpp:572
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:890
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:588
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:442
PianoKey * getPianoKey(const int key) const
Returns the piano key object corresponding to the given computer keyboard key.
Definition: pianoscene.cpp:662
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:674
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:645
void refreshLabels()
Refresh the visibility and other attributes of the labels shown over the piano keys.
Definition: pianoscene.cpp:972
void showNoteOff(const int note, int vel=-1)
Displays deactivated the corresponding key for a given MIDI note, with MIDI velocity.
Definition: pianoscene.cpp:401
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:992
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:909
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:610
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:847
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:460
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:562
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:374
void keyReleaseEvent(QKeyEvent *keyEvent) override
This event handler, for event keyEvent, is reimplemented to receive key release events.
Definition: pianoscene.cpp:692
void setMaxNote(const int note)
Assigns the maximum MIDI note number that will be displayed.
Definition: pianoscene.cpp:856
void retranslate()
Retranslates the standard note names.
int startKey() const
Returns the first key number that will be displayed.
Definition: pianoscene.cpp:899
void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) override
This event handler, for event mouseEvent, is reimplemented to receive mouse release events for the sc...
Definition: pianoscene.cpp:627
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:814
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:868
QString noteName(PianoKey *key)
Returns the note name string that will be displayed over a given piano key.
Definition: pianoscene.cpp:919
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.