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_NOTATION_WIDGET_H 19 #define RG_NOTATION_WIDGET_H 20 21 #include "StaffLayout.h" 22 23 #include "gui/general/AutoScroller.h" 24 #include "base/NotationTypes.h" 25 #include "gui/general/SelectionManager.h" 26 #include "gui/widgets/Thumbwheel.h" 27 28 #include <QWidget> 29 #include <QPushButton> 30 #include <QBoxLayout> 31 #include <QLabel> 32 33 #include <vector> 34 35 class QGridLayout; 36 class QString; 37 class QGraphicsScene; 38 class QTimer; 39 40 namespace Rosegarden 41 { 42 43 class Device; 44 class RosegardenDocument; 45 class Segment; 46 class NotationScene; 47 class Note; 48 class NotationToolBox; 49 class NotationTool; 50 class NotationMouseEvent; 51 class NotationStaff; 52 class ViewSegment; 53 class NotationElement; 54 class Panner; 55 class Panned; 56 class ZoomableRulerScale; 57 class StandardRuler; 58 class TempoRuler; 59 class ChordNameRuler; 60 class RawNoteRuler; 61 class ControlRulerWidget; 62 class HeadersGroup; 63 64 class NotationWidget : public QWidget, 65 public SelectionManager 66 { 67 Q_OBJECT 68 69 public: 70 NotationWidget(); 71 ~NotationWidget() override; ExecInitGatherMerge(GatherMerge * node,EState * estate,int eflags)72 73 // Delete and zero the pointer members if they are allocated. For 74 // 2-stage deletion. 75 void clearAll(); 76 77 void setSegments(RosegardenDocument *document, 78 std::vector<Segment *> segments); 79 80 void scrollToTopLeft(); 81 82 NotationScene *getScene() { return m_scene; } 83 Panned *getView() { return m_view; } 84 ControlRulerWidget *getControlsWidget() 85 { return m_controlRulerWidget; } 86 87 EventSelection *getSelection() const override; 88 void setSelection(EventSelection* s, bool preview) override; 89 90 timeT getInsertionTime() const; 91 92 bool isInChordMode() { return m_chordMode; } 93 bool isInTupletMode() { return m_tupletMode; } 94 bool isInGraceMode() { return m_graceMode; } 95 96 void setChordMode(bool state = true) { m_chordMode = state; } 97 void setTupletMode(bool state = true) { m_tupletMode = state;} 98 void setTupledCount(const unsigned short n = 2) { m_tupledCount = n;} 99 void setUntupledCount(const unsigned short d = 3) { m_untupledCount = d;} 100 unsigned int getTupledCount() const { return m_tupledCount;} 101 unsigned int getUntupledCount() const { return m_untupledCount;} 102 void setGraceMode(bool state = true) { m_graceMode = state; } 103 104 bool getPlayTracking() const { return m_playTracking; } 105 106 NotationToolBox *getToolBox() { return m_toolBox; } 107 NotationTool *getCurrentTool() const; 108 109 void setCanvasCursor(QCursor cursor); 110 111 Segment *getCurrentSegment(); 112 Device *getCurrentDevice(); 113 bool segmentsContainNotes() const; 114 115 void setTempoRulerVisible(bool visible); 116 void setChordNameRulerVisible(bool visible); 117 void setRawNoteRulerVisible(bool visible); 118 void setHeadersVisible(bool visible); 119 void setHeadersVisibleIfNeeded(); 120 void toggleHeadersView(); 121 122 double getViewLeftX(); 123 double getViewRightX(); 124 int getNotationViewWidth(); 125 double getNotationSceneHeight(); 126 127 void suspendLayoutUpdates(); 128 void resumeLayoutUpdates(); 129 130 void setPointerPosition(timeT); 131 132 void setHorizontalZoomFactor(double factor); 133 void setVerticalZoomFactor(double factor); 134 135 double getHorizontalZoomFactor() const; 136 double getVerticalZoomFactor() const; 137 138 // used in pitchtracker 139 void addWidgetToBottom(QWidget *bottomWidget); 140 141 void updateSegmentChangerBackground(); 142 void updatePointerPosition(bool moveView = false); 143 144 signals: 145 void sceneNeedsRebuilding(); 146 void toolChanged(QString); 147 void hoveredOverNoteChanged(QString); 148 void headersVisibilityChanged(bool); 149 void showContextHelp(const QString &); 150 151 public slots: 152 void slotSetTool(QString name); 153 void slotSetSelectTool(); 154 void slotSetSelectNoTiesTool(); 155 void slotSetEraseTool(); 156 void slotSetNoteRestInserter(); 157 void slotSetNoteInserter(); 158 void slotSetRestInserter(); 159 void slotSetInsertedNote(Note::Type type, int dots); 160 void slotSetAccidental(Accidental accidental, bool follow); 161 void slotSetClefInserter(); 162 void slotSetInsertedClef(Clef type); 163 void slotSetTextInserter(); 164 void slotSetGuitarChordInserter(); 165 void slotSetLinearMode(); 166 void slotSetContinuousPageMode(); 167 void slotSetMultiPageMode(); 168 void slotSetFontName(QString); 169 void slotSetFontSize(int); 170 void slotSetPlayTracking(bool); 171 void slotTogglePlayTracking(); 172 void slotSetSymbolInserter(); 173 void slotSetInsertedSymbol(Symbol type); 174 175 void slotToggleVelocityRuler(); 176 void slotTogglePitchbendRuler(); 177 void slotAddControlRuler(QAction*); 178 179 void slotRegenerateHeaders(); 180 181 private: 182 void showEvent(QShowEvent * event) override; 183 void hideOrShowRulers(); 184 bool linearMode() const; // Return true when notation page layout is linear 185 void updatePointer(timeT t); 186 187 private slots: ExecGatherMerge(PlanState * pstate)188 void slotDispatchMousePress(const NotationMouseEvent *); 189 void slotDispatchMouseRelease(const NotationMouseEvent *); 190 void slotDispatchMouseMove(const NotationMouseEvent *); 191 void slotDispatchMouseDoubleClick(const NotationMouseEvent *); 192 void slotDispatchWheelTurned(int, const NotationMouseEvent *); 193 194 void slotPointerPositionChanged(timeT t); 195 196 // Standard Ruler 197 void slotStandardRulerDrag(timeT t); 198 void slotSRStartMouseMove(); 199 void slotSRStopMouseMove(); 200 201 // ControlRulerWidget 202 void slotCRWMousePress(); 203 void slotCRWMouseMove(FollowMode followMode); 204 void slotCRWMouseRelease(); 205 206 // TempoRuler 207 void slotTRMousePress(); 208 void slotTRMouseRelease(); 209 210 void slotZoomInFromPanner(); 211 void slotZoomOutFromPanner(); 212 213 void slotHScroll(); 214 void slotHScrollBarRangeChanged(int min, int max); 215 216 /// The horizontal zoom thumbwheel moved 217 void slotHorizontalThumbwheelMoved(int); 218 219 /// The vertical zoom thumbwheel moved 220 void slotVerticalThumbwheelMoved(int); 221 222 /// The primary (combined axes) thumbwheel moved 223 void slotPrimaryThumbwheelMoved(int); 224 225 /// Reset the zoom to 100% and reset the zoomy wheels 226 void slotResetZoomClicked(); 227 228 /// Trap a zoom in from the panner and sync it to the primary thumb wheel 229 void slotSyncPannerZoomIn(); 230 231 /// Trap a zoom out from the panner and sync it to the primary thumb wheel 232 void slotSyncPannerZoomOut(); 233 234 void slotGenerateHeaders(); 235 void slotShowHeaderToolTip(QString toolTipText); 236 void slotHeadersResized(int width); 237 void slotAdjustHeadersHorizontalPos(bool last); 238 void slotAdjustHeadersVerticalPos(QRectF r); 239 void slotCloseHeaders(); 240 241 /// The segment control thumbwheel moved 242 void slotSegmentChangerMoved(int); 243 244 void slotStaffChanged(); 245 246 void slotUpdateRawNoteRuler(ViewSegment *); 247 void slotUpdateSegmentChangerBackground(); 248 void resizeEvent(QResizeEvent *event) override; 249 void slotResizeTimerDone(); 250 251 signals : 252 void adjustNeeded(bool last); 253 void editElement(NotationStaff *, NotationElement *, bool advanced); 254 void currentSegmentPrior(); 255 void currentSegmentNext(); 256 257 private: 258 RosegardenDocument *m_document; // I do not own this 259 Panned *m_view; // I own this 260 Panner *m_hpanner; // I own this 261 NotationScene *m_scene; // I own this 262 int m_leftGutter; 263 NotationToolBox *m_toolBox; 264 NotationTool *m_currentTool; 265 bool m_playTracking; 266 267 double m_hZoomFactor; 268 double m_vZoomFactor; 269 ZoomableRulerScale *m_referenceScale; // I own this (refers to scene scale) 270 271 QWidget *m_panner; 272 QBoxLayout *m_pannerLayout; 273 Thumbwheel *m_HVzoom; 274 Thumbwheel *m_Hzoom; 275 Thumbwheel *m_Vzoom; 276 QPushButton *m_reset; 277 278 /** The primary zoom wheel behaves just like using the mouse wheel over any 279 * part of the Panner. We don't need to keep track of absolute values here, 280 * just whether we rolled up or down. We'll do that by keeping track of the 281 * last setting and comparing it to see which way it moved. 282 */ 283 int m_lastHVzoomValue; 284 bool m_lastZoomWasHV; 285 int m_lastV; 286 int m_lastH; 287 288 QWidget *m_changerWidget; ExecEndGatherMerge(GatherMergeState * node)289 Thumbwheel *m_HsegmentChanger; 290 Thumbwheel *m_VsegmentChanger; 291 int m_lastSegmentChangerValue; 292 293 StandardRuler *m_topStandardRuler; // I own this 294 StandardRuler *m_bottomStandardRuler; // I own this 295 TempoRuler *m_tempoRuler; // I own this 296 ChordNameRuler *m_chordNameRuler; // I own this 297 RawNoteRuler *m_rawNoteRuler; // I own this 298 ControlRulerWidget *m_controlRulerWidget; // I own this 299 300 QLabel *m_segmentLabel; 301 302 // Track Headers 303 // View > Show Track Headers 304 ExecShutdownGatherMerge(GatherMergeState * node)305 HeadersGroup *m_headersGroup; // I own this 306 /// Track Headers that appear to the left of the staves. 307 Panned *m_headersView; // I own this 308 QGraphicsScene *m_headersScene; // I own this 309 QWidget *m_headersButtons; // I own this 310 double m_headersLastY; 311 bool m_headersNeedRegeneration; 312 QTimer *m_headersTimer; // I own this 313 314 QGridLayout *m_layout; // I own this 315 316 bool m_tempoRulerIsVisible; // Only valid in linear mode 317 bool m_rawNoteRulerIsVisible; // Only valid in linear mode 318 bool m_chordNameRulerIsVisible; // Only valid in linear mode 319 bool m_headersAreVisible; // Only valid in linear mode 320 321 bool m_chordMode; 322 bool m_tupletMode; 323 bool m_graceMode; ExecShutdownGatherMergeWorkers(GatherMergeState * node)324 325 unsigned short m_tupledCount; 326 unsigned short m_untupledCount; 327 328 /// Timer to reduce the number of layout resets that occur while resizing. 329 /** 330 * ??? I can't help but wonder if there is a simpler solution where 331 * we assume the scene (or whatever) is always at the very least 332 * big enough to fill the user's screen. So the scrollbars are 333 * always there and there is always empty space to the right 334 * and below. This would then prevent the jumping without the 335 * need for a timer and a layout reset. (I have no idea what I'm 336 * talking about, so you might need to translate that into 337 * whatever is actually going on in the code.) See Bug #1570 for 338 * details. 339 */ 340 QTimer *m_resizeTimer; 341 ExecReScanGatherMerge(GatherMergeState * node)342 bool m_updatesSuspended; 343 344 void locatePanner(bool vertical); 345 346 /** 347 * Widgets vertical positions inside the main QGridLayout 348 */ 349 enum { 350 CHORDNAMERULER_ROW, 351 TEMPORULER_ROW, 352 RAWNOTERULER_ROW, 353 TOPRULER_ROW, 354 PANNED_ROW, 355 BOTTOMRULER_ROW, 356 CONTROLS_ROW, 357 HSLIDER_ROW, 358 SEGMENTLABEL_ROW, 359 PANNER_ROW, 360 BOTTOM_ROW 361 }; 362 363 /** 364 * Widgets horizontal positions inside the main QGridLayout 365 */ 366 enum { 367 HEADER_COL, 368 MAIN_COL, 369 VPANNER_COL 370 }; 371 372 AutoScroller m_autoScroller; 373 374 private slots: 375 /// Connected to Panned::zoomIn() for ctrl+wheel. 376 void slotZoomIn(); 377 /// Connected to Panned::zoomOut() for ctrl+wheel. 378 void slotZoomOut(); 379 380 }; 381 382 } 383 384 #endif 385 386 387