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 #ifndef PIANOKEYBD_H 20 #define PIANOKEYBD_H 21 22 #include <QGraphicsView> 23 #include <QScopedPointer> 24 #include <QGraphicsScene> 25 #include "macros.h" 26 #include "pianopalette.h" 27 28 /** 29 * @file pianokeybd.h 30 * Piano Keyboard Widget 31 */ 32 33 namespace drumstick { namespace widgets { 34 35 /** 36 * @addtogroup Widgets 37 * @{ 38 * 39 * @class RawKbdHandler 40 * @brief The RawKbdHandler class callbacks 41 * 42 * RawKbdHandler provides callbacks for low level computer keyboard events 43 */ 44 class RawKbdHandler { 45 public: 46 virtual ~RawKbdHandler() = default; 47 /** 48 * @brief handleKeyPressed handles low level computer keyboard press events 49 * @param keycode The low level key code pressed 50 * @return whether the event has been processed or not 51 */ 52 virtual bool handleKeyPressed(int keycode) = 0; 53 /** 54 * @brief handleKeyReleased handles low level computer keyboard reelase events 55 * @param keycode The low level key code released 56 * @return whether the event has been processed or not 57 */ 58 virtual bool handleKeyReleased(int keycode) = 0; 59 }; 60 61 /** 62 * @brief The PianoHandler class callbacks 63 * 64 * This class provides handler methods for note events. This class must be 65 * inherited and implemented by a program using also PianoKeybd to receive the 66 * note events generated from a computer keyboard, mouse or touch events. It is 67 * provided using the method @ref PianoKeybd::setPianoHandler() and can be retrieved 68 * using @ref PianoKeybd::getPianoHandler(). This mechanism is an option alternative 69 * to proces signals @ref PianoKeybd::noteOn() and @ref PianoKeybd::noteOff() . 70 */ 71 class PianoHandler 72 { 73 public: 74 virtual ~PianoHandler() = default; 75 /** 76 * @brief noteOn handles MIDI note on events 77 * @param note MIDI note number 78 * @param vel MIDI velocity 79 */ 80 virtual void noteOn( const int note, const int vel ) = 0; 81 /** 82 * @brief noteOff handles MIDI note off events 83 * @param note MIDI note number 84 * @param vel MIDI velocity 85 */ 86 virtual void noteOff( const int note, const int vel ) = 0; 87 }; 88 89 /** 90 * @brief KeyboardMap 91 * 92 * KeyboardMap represents a mapping definition to translate from 93 * computer keyboard keys and MIDI notes, either for alphanumeric 94 * or low level (raw) events. 95 */ 96 typedef QHash<int, int> KeyboardMap; 97 98 extern DRUMSTICK_EXPORT KeyboardMap g_DefaultKeyMap; ///< Global Key Map Variable 99 extern DRUMSTICK_EXPORT KeyboardMap g_DefaultRawKeyMap; ///< Global Raw Key Map Variable 100 101 const int DEFAULTSTARTINGKEY = 9; ///< Default starting key (A) 102 const int DEFAULTBASEOCTAVE = 1; ///< Default base octave 103 const int DEFAULTNUMBEROFKEYS = 88; ///< Default number of piano keys 104 105 /** 106 * @brief Labels Visibility 107 */ 108 enum LabelVisibility { 109 ShowNever, ///< Don't show note names 110 ShowMinimum, ///< Show only note C names 111 ShowActivated, ///< Show names when notes are activated 112 ShowAlways ///< Show always note names 113 }; 114 115 /** 116 * @brief Labels for Alterations 117 */ 118 enum LabelAlteration { 119 ShowSharps, ///< Show sharps on black keys 120 ShowFlats, ///< Show flats on black keys 121 ShowNothing ///< Do not show names on black keys 122 }; 123 124 /** 125 * @brief Labels Orientation 126 */ 127 enum LabelOrientation { 128 HorizontalOrientation, ///< Show horizontal names 129 VerticalOrientation, ///< Show vertical names 130 AutomaticOrientation ///< Show horizonal or vertical names depending on the size 131 }; 132 133 /** 134 * @brief Labels Naming 135 */ 136 enum LabelNaming { 137 StandardNames, ///< Show standard names 138 CustomNamesWithSharps, ///< Show custom names with sharps 139 CustomNamesWithFlats ///< Show custom names with flats 140 }; 141 142 /** 143 * @brief Labels Central Octave 144 */ 145 enum LabelCentralOctave { 146 OctaveNothing = -1, ///< Don't show octave numbers 147 OctaveC3, ///< Central C, MIDI note #60 is C3 148 OctaveC4, ///< Central C, MIDI note #60 is C4 149 OctaveC5 ///< Central C, MIDI note #60 is C5 150 }; 151 152 /** 153 * @brief The PianoKeybd class 154 * 155 * This class is a widget providing the look and behavior of a musical piano keyboard. 156 * It is implemented as a QGraphicsView displaying the contents of a QGraphicsScene (PianoScene). 157 */ 158 class DRUMSTICK_EXPORT PianoKeybd : public QGraphicsView, public RawKbdHandler 159 { 160 Q_OBJECT 161 Q_PROPERTY( int baseOctave READ baseOctave WRITE setBaseOctave ) 162 Q_PROPERTY( int numKeys READ numKeys WRITE setNumKeys ) 163 Q_PROPERTY( int rotation READ getRotation WRITE setRotation ) 164 Q_PROPERTY( QColor keyPressedColor READ getKeyPressedColor WRITE setKeyPressedColor ) 165 Q_PROPERTY( LabelVisibility showLabels READ showLabels WRITE setShowLabels ) 166 Q_PROPERTY( LabelAlteration alterations READ labelAlterations WRITE setLabelAlterations ) 167 Q_PROPERTY( LabelOrientation labelOrientation READ labelOrientation WRITE setLabelOrientation ) 168 Q_PROPERTY( LabelCentralOctave labelOctave READ labelOctave WRITE setLabelOctave ) 169 Q_PROPERTY( int transpose READ getTranspose WRITE setTranspose ) 170 171 #ifndef Q_MOC_RUN 172 Q_CLASSINFO("Author", "Pedro Lopez-Cabanillas <plcl@users.sf.net>") 173 Q_CLASSINFO("URL", "https://sourceforge.net/projects/drumstick") 174 Q_CLASSINFO("Version", QT_STRINGIFY(VERSION)) 175 #endif 176 177 public: 178 explicit PianoKeybd(QWidget *parent = nullptr); 179 PianoKeybd(const int baseOctave, const int numKeys, const int startKey, QWidget *parent = nullptr); 180 virtual ~PianoKeybd(); 181 182 Q_ENUM(LabelVisibility); 183 Q_ENUM(LabelAlteration); 184 Q_ENUM(LabelOrientation); 185 Q_ENUM(LabelNaming); 186 Q_ENUM(LabelCentralOctave); 187 188 void setFont(const QFont &font); 189 PianoHandler* getPianoHandler() const; 190 void setPianoHandler(PianoHandler* handler); 191 192 PianoPalette getHighlightPalette() const; 193 void setHighlightPalette(const PianoPalette& p ); 194 PianoPalette getBackgroundPalette() const; 195 void setBackgroundPalette(const PianoPalette& p ); 196 PianoPalette getForegroundPalette() const; 197 void setForegroundPalette(const PianoPalette& p ); 198 199 bool showColorScale() const; 200 void setShowColorScale(const bool show); 201 202 void useCustomNoteNames(const QStringList& names); 203 void useStandardNoteNames(); 204 QStringList customNoteNames() const; 205 QStringList standardNoteNames() const; 206 void retranslate(); 207 208 int baseOctave() const; 209 void setBaseOctave(const int baseOctave); 210 int numKeys() const; 211 int startKey() const; 212 void setNumKeys(const int numKeys, const int startKey = DEFAULTSTARTINGKEY); 213 int getRotation() const; 214 void setRotation(int r); 215 QColor getKeyPressedColor() const; 216 void setKeyPressedColor(const QColor& c); 217 void resetKeyPressedColor(); 218 LabelVisibility showLabels() const; 219 void setShowLabels(const LabelVisibility show); 220 LabelAlteration labelAlterations() const; 221 void setLabelAlterations(const LabelAlteration use); 222 LabelOrientation labelOrientation() const; 223 void setLabelOrientation(const LabelOrientation orientation); 224 LabelCentralOctave labelOctave() const; 225 void setLabelOctave(const LabelCentralOctave octave); 226 int getTranspose() const; 227 void setTranspose(int t); 228 int getChannel() const; 229 void setChannel(const int c); 230 int getVelocity() const; 231 void setVelocity(const int v); 232 233 bool isKeyboardEnabled() const; 234 void setKeyboardEnabled( const bool enable ); 235 bool isMouseEnabled() const; 236 void setMouseEnabled( const bool enable ); 237 bool isTouchEnabled() const; 238 void setTouchEnabled( const bool enable ); 239 bool velocityTint() const ; 240 void setVelocityTint( const bool enable ); 241 void allKeysOff(); 242 243 QSize sizeHint() const override; 244 void setKeyboardMap(KeyboardMap* m); 245 KeyboardMap* getKeyboardMap(); 246 void resetKeyboardMap(); 247 void setRawKeyboardMap(KeyboardMap* m); 248 KeyboardMap* getRawKeyboardMap(); 249 void resetRawKeyboardMap(); 250 bool getRawKeyboardMode() const; 251 void setRawKeyboardMode(const bool b); 252 253 void showNoteOn( const int note, QColor color, int vel = -1 ); 254 void showNoteOn( const int note, int vel = -1 ); 255 void showNoteOff( const int note, int vel = -1 ); 256 257 // RawKbdHandler methods 258 bool handleKeyPressed(int keycode) override; 259 bool handleKeyReleased(int keycode) override; 260 261 void setKeyPicture(const bool natural, const QPixmap& pix); 262 QPixmap getKeyPicture(const bool natural); 263 264 void setUseKeyPictures(const bool enable); 265 bool getUseKeyPictures() const; 266 267 signals: 268 /** 269 * This signal is emitted for each Note On MIDI event created using 270 * the computer keyboard, mouse or touch screen. It is not emitted if 271 * a PianoHandler has been assigned using setPianoHandler(). 272 * @param midiNote the MIDI note number 273 * @param vel the MIDI velocity 274 */ 275 void noteOn( int midiNote, int vel ); 276 /** 277 * This signal is emitted for each Note Off MIDI event created using 278 * the computer keyboard, mouse or touch screen. It is not emitted if 279 * a PianoHandler has been assigned using setPianoHandler(). 280 * @param midiNote the MIDI note number 281 * @param vel the MIDI velocity 282 */ 283 void noteOff( int midiNote, int vel ); 284 /** 285 * signalName is emitted for each note created, and contains a string 286 * with the MIDI note number and the note name for each note on event. 287 * @param name the MIDI note number and name 288 */ 289 void signalName( const QString& name ); 290 291 protected: 292 void initialize(); 293 void initDefaultMap(); 294 void initScene(int base, int num, int ini, const QColor& c = QColor()); 295 void resizeEvent(QResizeEvent *event) override; 296 297 private: 298 class PianoKeybdPrivate; 299 QScopedPointer<PianoKeybdPrivate> d; 300 }; 301 302 /** @} */ 303 304 }} // namespace drumstick::widgets 305 306 #endif // PIANOKEYBD_H 307