1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 2 3 /* 4 Rosegarden 5 A MIDI and audio sequencer and musical notation editor. 6 Copyright 2000-2021 the Rosegarden development team. 7 8 Other copyrights also apply to some parts of this work. Please 9 see the AUTHORS file and individual file headers for details. 10 11 This program is free software; you can redistribute it and/or 12 modify it under the terms of the GNU General Public License as 13 published by the Free Software Foundation; either version 2 of the 14 License, or (at your option) any later version. See the file 15 COPYING included with this distribution for more information. 16 */ 17 18 #ifndef RG_MATRIX_WIDGET_H 19 #define RG_MATRIX_WIDGET_H 20 21 #include "base/Event.h" // for timeT 22 #include "MatrixTool.h" 23 #include "base/MidiTypes.h" // for MidiByte 24 #include "gui/general/AutoScroller.h" 25 #include "gui/general/SelectionManager.h" 26 27 #include <vector> 28 29 #include <QSharedPointer> 30 #include <QTimer> 31 #include <QWidget> 32 33 class QGraphicsScene; 34 class QGridLayout; 35 class QLabel; 36 class QPushButton; 37 38 namespace Rosegarden 39 { 40 41 class RosegardenDocument; 42 class Segment; 43 class MatrixScene; 44 class MatrixToolBox; 45 class MatrixMouseEvent; 46 class SnapGrid; 47 class ZoomableRulerScale; 48 class Panner; 49 class Panned; 50 class EventSelection; 51 class PitchRuler; 52 class MidiKeyMapping; 53 class ControlRulerWidget; 54 class StandardRuler; 55 class TempoRuler; 56 class ChordNameRuler; 57 class Device; 58 class Instrument; 59 class Thumbwheel; 60 61 62 /// QWidget that fills the Matrix Editor's (MatrixView) client area. 63 /** 64 * The main Matrix Editor window, MatrixView, owns the only instance 65 * of this class. See MatrixView::m_matrixWidget. 66 * 67 * MatrixWidget contains the matrix itself (m_view and m_scene). 68 * MatrixWidget also contains all the other parts of the Matrix Editor 69 * that appear around the matrix. From left to right, top to bottom: 70 * 71 * - The chord name ruler 72 * - The tempo ruler 73 * - The top standard ruler 74 * - The pitch ruler, m_pianoView (to the left of the matrix) 75 * - The matrix itself, m_view and m_scene 76 * - The bottom standard ruler, m_bottomStandardRuler 77 * - The controls widget, m_controlsWidget (optional) 78 * - The Segment label, m_segmentLabel 79 * - The Segment changer, m_segmentChanger (knob in the bottom left corner) 80 * - The panner, m_hpanner (navigation area) 81 * - The zoom area, m_HVzoom et al. (knobs in the bottom right corner) 82 * 83 * This class also owns the editing tools. 84 */ 85 class MatrixWidget : public QWidget, 86 public SelectionManager 87 { 88 Q_OBJECT 89 90 public: 91 MatrixWidget(bool drumMode); 92 virtual ~MatrixWidget() override; 93 94 Device *getCurrentDevice(); getScene()95 MatrixScene *getScene() { return m_scene; } 96 97 /** 98 * Show the pointer. Used by MatrixView upon construction, this ensures 99 * the pointer is visible initially. 100 */ 101 void showInitialPointer(); 102 103 /// Set the Segment(s) to display. 104 /** 105 * ??? Only one caller. Might want to fold this into the ctor. 106 */ 107 void setSegments(RosegardenDocument *document, 108 std::vector<Segment *> segments); 109 /// MatrixScene::getCurrentSegment() 110 Segment *getCurrentSegment(); 111 /// MatrixScene::segmentsContainNotes() 112 bool segmentsContainNotes() const; 113 114 /// All segments only have a key mapping. hasOnlyKeyMapping()115 bool hasOnlyKeyMapping() const { return m_onlyKeyMapping; } 116 getControlsWidget()117 ControlRulerWidget *getControlsWidget() { return m_controlsWidget; } 118 119 /// MatrixScene::getSnapGrid() 120 const SnapGrid *getSnapGrid() const; 121 /// MatrixScene::setSnap() 122 void setSnap(timeT); 123 124 void setChordNameRulerVisible(bool visible); 125 void setTempoRulerVisible(bool visible); 126 127 /// Show the highlight on the piano/percussion rulers. 128 void showHighlight(bool visible); 129 130 131 // SelectionManager interface. 132 133 // These delegate to MatrixScene, which possesses the selection 134 /// MatrixScene::getSelection() 135 EventSelection *getSelection() const override; 136 /// MatrixScene::setSelection() 137 void setSelection(EventSelection *s, bool preview) override; 138 139 140 // Tools 141 getToolBox()142 MatrixToolBox *getToolBox() { return m_toolBox; } 143 144 /// Used by the tools to set an appropriate mouse cursor. 145 void setCanvasCursor(QCursor cursor); 146 isDrumMode()147 bool isDrumMode() const { return m_drumMode; } 148 149 /// Velocity for new notes. (And moved notes too.) getCurrentVelocity()150 int getCurrentVelocity() const { return m_currentVelocity; } 151 152 153 // Interface for MatrixView menu commands 154 155 /// Edit > Select All 156 void selectAll(); 157 /// Edit > Clear Selection 158 void clearSelection(); 159 /// Move > Previous Segment 160 void previousSegment(); 161 /// Move > Next Segment 162 void nextSegment(); 163 /// Tools > Draw 164 void setDrawTool(); 165 /// Tools > Erase 166 void setEraseTool(); 167 /// Tools > Select and Edit 168 void setSelectAndEditTool(); 169 /// Tools > Move 170 void setMoveTool(); 171 /// Tools > Resize 172 void setResizeTool(); 173 /// Tools > Velocity 174 void setVelocityTool(); 175 /// Move > Scroll to Follow Playback 176 void setScrollToFollowPlayback(bool); 177 /// View > Rulers > Show Velocity Ruler 178 void showVelocityRuler(); 179 /// View > Rulers > Show Pitch Bend Ruler 180 void showPitchBendRuler(); 181 /// View > Rulers > Add Control Ruler 182 void addControlRuler(QAction *); 183 184 signals: 185 void toolChanged(QString); 186 187 /** 188 * Emitted when the user double-clicks on a note that triggers a 189 * segment. 190 * 191 * RosegardenMainViewWidget::slotEditTriggerSegment() launches the event 192 * editor on the triggered segment in response to this. 193 */ 194 void editTriggerSegment(int); 195 196 /// Forwarded from MatrixScene::segmentDeleted(). 197 void segmentDeleted(Segment *); 198 /// Forwarded from MatrixScene::sceneDeleted(). 199 void sceneDeleted(); 200 /// Forwarded from MatrixScene::selectionChanged() 201 void selectionChanged(); 202 203 void showContextHelp(const QString &); 204 205 public slots: 206 /// Velocity combo box. slotSetCurrentVelocity(int velocity)207 void slotSetCurrentVelocity(int velocity) { m_currentVelocity = velocity; } 208 209 /// Plays the preview note when using the computer keyboard to enter notes. 210 void slotPlayPreviewNote(Segment *segment, int pitch); 211 212 protected: 213 // QWidget Override 214 /// Make sure the rulers are in sync when we are shown. 215 void showEvent(QShowEvent *event) override; 216 217 private slots: 218 /// Called when the document is modified in some way. 219 void slotDocumentModified(bool); 220 221 /// Connected to Panned::zoomIn() for ctrl+wheel. 222 void slotZoomIn(); 223 /// Connected to Panned::zoomOut() for ctrl+wheel. 224 void slotZoomOut(); 225 226 /// Scroll rulers to sync up with view. 227 void slotScrollRulers(); 228 229 // MatrixScene Interface 230 void slotDispatchMousePress(const MatrixMouseEvent *); 231 void slotDispatchMouseMove(const MatrixMouseEvent *); 232 void slotDispatchMouseRelease(const MatrixMouseEvent *); 233 void slotDispatchMouseDoubleClick(const MatrixMouseEvent *); 234 235 /// Display the playback position pointer. 236 void slotPointerPositionChanged(timeT t); 237 void slotStandardRulerDrag(timeT t); 238 /// Handle StandardRuler startMouseMove() 239 void slotSRStartMouseMove(); 240 /// Handle StandardRuler stopMouseMove() 241 void slotSRStopMouseMove(); 242 243 /// Handle ControlRulerWidget::mousePress(). 244 void slotCRWMousePress(); 245 /// Handle ControlRulerWidget::mouseMove(). 246 void slotCRWMouseMove(FollowMode followMode); 247 /// Handle ControlRulerWidget::mouseRelease(). 248 void slotCRWMouseRelease(); 249 250 /// Handle TempoRuler::mousePress(). 251 void slotTRMousePress(); 252 /// Handle TempoRuler::mouseRelease(). 253 void slotTRMouseRelease(); 254 255 /// Hide the horizontal scrollbar when not needed. 256 /** 257 * ??? Why do we need to manage this? We turn off the horizontal 258 * scrollbar in the ctor with Qt::ScrollBarAlwaysOff. 259 */ 260 void slotHScrollBarRangeChanged(int min, int max); 261 262 // PitchRuler slots 263 /// Draw the highlight as we move from one pitch to the next. 264 void slotHoveredOverKeyChanged(unsigned int); 265 void slotKeyPressed(unsigned int, bool); 266 void slotKeySelected(unsigned int, bool); 267 void slotKeyReleased(unsigned int, bool); 268 269 /// The horizontal zoom thumbwheel moved 270 void slotHorizontalThumbwheelMoved(int); 271 272 /// The vertical zoom thumbwheel moved 273 void slotVerticalThumbwheelMoved(int); 274 275 /// The primary (combined axes) thumbwheel moved 276 void slotPrimaryThumbwheelMoved(int); 277 278 /// Reset the zoom to 100% and reset the zoomy wheels 279 void slotResetZoomClicked(); 280 281 /// Trap a zoom in from the panner and sync it to the primary thumb wheel 282 void slotSyncPannerZoomIn(); 283 284 /// Trap a zoom out from the panner and sync it to the primary thumb wheel 285 void slotSyncPannerZoomOut(); 286 287 /// The Segment control thumbwheel moved, display a different Segment. 288 void slotSegmentChangerMoved(int); 289 290 /// The mouse has left the view, hide the highlight note. 291 void slotMouseLeavesView(); 292 293 /// Instrument is being destroyed 294 void slotInstrumentGone(); 295 296 private: 297 // ??? Instead of storing the document, which can change, get the 298 // document as needed via RosegardenMainWindow::self()->getDocument(). 299 RosegardenDocument *m_document; // I do not own this 300 301 QGridLayout *m_layout; // I own this 302 303 304 // View 305 306 /// QGraphicsScene holding the note Events. 307 MatrixScene *m_scene; // I own this 308 309 /// The main view of the MatrixScene (m_scene). 310 Panned *m_view; // I own this 311 312 /// Whether the view will scroll along with the playback position pointer. 313 bool m_playTracking; 314 315 /// View horizontal zoom factor. 316 double m_hZoomFactor; 317 void setHorizontalZoomFactor(double factor); 318 319 /// View vertical zoom factor. 320 double m_vZoomFactor; 321 void setVerticalZoomFactor(double factor); 322 323 324 // Pointer 325 326 void updatePointer(timeT t); 327 328 329 // Panner (Navigation Area below the matrix) 330 331 /// Navigation area under the main view. 332 Panner *m_panner; // I own this 333 void zoomInFromPanner(); 334 void zoomOutFromPanner(); 335 336 QWidget *m_changerWidget; 337 Thumbwheel *m_segmentChanger; 338 int m_lastSegmentChangerValue; 339 void updateSegmentChangerBackground(); 340 QLabel *m_segmentLabel; 341 342 343 // Pitch Ruler 344 345 // This can be nullptr. It tracks what pitchruler corresponds to. 346 Instrument *m_instrument; // Studio owns this (TBC) 347 /// Key mapping from the Instrument. 348 QSharedPointer<MidiKeyMapping> m_localMapping; 349 /// Either a PercussionPitchRuler or a PianoKeyboard object. 350 PitchRuler *m_pitchRuler; // I own this 351 /// (Re)generate the pitch ruler (useful when key mapping changed) 352 void generatePitchRuler(); 353 /// Contains m_pitchRuler. 354 QGraphicsScene *m_pianoScene; // I own this 355 /// Contains m_pianoScene. 356 Panned *m_pianoView; // I own this 357 /// All Segments only have key mappings. Use a PercussionPitchRuler. 358 bool m_onlyKeyMapping; 359 /// Percussion matrix editor? 360 /** 361 * For the Percussion matrix editor, we ignore key release events from 362 * the PitchRuler. 363 */ 364 bool m_drumMode; 365 366 /// First note selected when doing a run up/down the keyboard. 367 /** 368 * Used to allow selection of a range of pitches by shift-clicking a 369 * note on the pitch ruler then dragging up or down to another note. 370 */ 371 MidiByte m_firstNote; 372 373 /// Last note selected when doing a run up/down the keyboard. 374 /** 375 * Used to prevent redundant note on/offs when doing a run up/down the 376 * pitch ruler. 377 */ 378 MidiByte m_lastNote; 379 380 /// Hide pitch ruler highlight when mouse move is not related to a pitch change. 381 bool m_highlightVisible; 382 383 384 // Tools 385 386 MatrixToolBox *m_toolBox; // I own this 387 MatrixTool *m_currentTool; // Toolbox owns this 388 void setTool(QString name); 389 /// Used by the MatrixMover and MatrixPainter tools for preview notes. 390 int m_currentVelocity; 391 392 393 // Zoom Area (to the right of the Panner) 394 395 /// The big zoom wheel. 396 Thumbwheel *m_HVzoom; 397 /// Used to compute how far the big zoom wheel has moved. 398 int m_lastHVzoomValue; 399 /// Which zoom factor to use. For the pitch ruler. 400 bool m_lastZoomWasHV; 401 /// Thin horizontal zoom wheel under the big zoom wheel. 402 Thumbwheel *m_Hzoom; 403 /// Used to compute how far the horizontal zoom wheel has moved. 404 int m_lastH; 405 /// Thin vertical zoom wheel to the right of the big zoom wheel. 406 Thumbwheel *m_Vzoom; 407 /// Used to compute how far the vertical zoom wheel has moved. 408 int m_lastV; 409 /// Small reset button to the lower right of the big zoom wheel. 410 QPushButton *m_reset; 411 412 413 // Rulers 414 415 ChordNameRuler *m_chordNameRuler; // I own this 416 TempoRuler *m_tempoRuler; // I own this 417 StandardRuler *m_topStandardRuler; // I own this 418 StandardRuler *m_bottomStandardRuler; // I own this 419 ControlRulerWidget *m_controlsWidget; // I own this 420 421 /// Used by all rulers to make sure they are all zoomed to the same scale. 422 /** 423 * See MatrixScene::getReferenceScale(). 424 */ 425 ZoomableRulerScale *m_referenceScale; // Owned by MatrixScene 426 427 428 // Auto-scroll 429 430 AutoScroller m_autoScroller; 431 432 }; 433 434 } 435 436 #endif 437