1 //============================================================================= 2 // MuseScore 3 // Music Composition & Notation 4 // 5 // Copyright (C) 2002-2009 Werner Schweer 6 // 7 // This program is free software; you can redistribute it and/or modify 8 // it under the terms of the GNU General Public License version 2 9 // as published by the Free Software Foundation and appearing in 10 // the file LICENCE.GPL 11 //============================================================================= 12 13 #ifndef __SCANVAS_H__ 14 #define __SCANVAS_H__ 15 16 #include "globals.h" 17 #include "libmscore/element.h" 18 #include "libmscore/elementgroup.h" 19 #include "libmscore/durationtype.h" 20 #include "libmscore/mscore.h" 21 #include "libmscore/mscoreview.h" 22 #include "libmscore/pos.h" 23 #include "libmscore/harmony.h" 24 #include "mscore/zoombox.h" 25 26 namespace Ms { 27 28 class ChordRest; 29 class Rest; 30 class Element; 31 class Page; 32 class XmlWriter; 33 class Note; 34 class Lasso; 35 class FotoLasso; 36 class ShadowNote; 37 class Segment; 38 class Measure; 39 class System; 40 class Score; 41 class ScoreView; 42 class Text; 43 class MeasureBase; 44 class Staff; 45 class OmrView; 46 class PositionCursor; 47 class ContinuousPanel; 48 class Tuplet; 49 class FretDiagram; 50 class Bend; 51 class TremoloBar; 52 class TimeSig; 53 class StaffTextBase; 54 class Articulation; 55 56 #ifdef Q_OS_MAC 57 #define CONTROL_MODIFIER Qt::AltModifier 58 #else 59 #define CONTROL_MODIFIER Qt::ControlModifier 60 #endif 61 62 enum class Grip : int; 63 enum class POS : char; 64 enum class ZoomIndex : char; 65 66 //--------------------------------------------------------- 67 // SmoothPanSettings 68 //--------------------------------------------------------- 69 70 struct SmoothPanSettings { 71 // these are all actually loaded from the loadFromPreferences fuction so don't change these to change the default values, 72 // change the corresponding preferences 73 bool enabled { false }; 74 75 double controlModifierBase { 1 }; // initial speed modifier 76 double controlModifierSteps { 0.01 }; // modification steps for the modifier 77 double minContinuousModifier { 0.2 }; // minimum speed, 0.2 was chosen instead of 0 to remove stuttering 78 double maxContinuousModifier { 5 }; // maximum speed 79 80 // Changing the distance will change the sensitivity/accuracy/jitter of the algorithm. Larger absolute values are generally smoother. 81 double leftDistance { -250 }; // decelarate 82 double leftDistance1 { -125 }; 83 double leftDistance2 { -50 }; 84 double leftDistance3 { -25 }; 85 double rightDistance { 500 }; // accelerate 86 double rightDistance1 { 250 }; 87 double rightDistance2 { 125 }; 88 double rightDistance3 { 50 }; 89 // used to smoothly go back to normal speed when the playback cursor is getting closer 90 double leftMod1 { 0.8 }; // minimum speed at the first level 91 double leftMod2 { 0.9 }; // etc 92 double leftMod3 { 0.95 }; 93 // used to smoothly go back to normal speed when the control cursor is getting closer to the playback cursor 94 double rightMod1 { 1.2 }; // maximum speed at the first level 95 double rightMod2 { 1.1 }; // etc 96 double rightMod3 { 1.05 }; 97 98 double controlCursorScreenPos { 0.3 }; 99 bool teleportLeftEnabled { true }; 100 bool teleportRightEnabled { false }; 101 102 bool advancedWeighting { false }; // enables the 'smart weight' 103 double normalWeight { 1 }; 104 double smartWeight { 0 }; // uses the distance between the 2 cursors to calculate the speed of the control cursor 105 int cursorTimerDuration { 1000 }; // how often the smart weight is updated 106 107 void loadFromPreferences(); 108 }; 109 110 //--------------------------------------------------------- 111 // ViewState 112 //--------------------------------------------------------- 113 114 enum class ViewState { 115 NORMAL, 116 DRAG, 117 DRAG_OBJECT, 118 EDIT, 119 DRAG_EDIT, 120 LASSO, 121 NOTE_ENTRY, 122 PLAY, 123 ENTRY_PLAY, 124 125 FOTO, 126 FOTO_DRAG, 127 FOTO_DRAG_EDIT, 128 FOTO_DRAG_OBJECT, 129 FOTO_LASSO, 130 }; 131 132 //--------------------------------------------------------- 133 // ScoreViewState 134 //--------------------------------------------------------- 135 136 struct ScoreViewState { 137 qreal logicalZoomLevel = 1.0; 138 ZoomIndex zoomIndex = ZoomIndex::ZOOM_FREE; 139 qreal xOffset = 0.0; 140 qreal yOffset = 0.0; 141 ScoreViewStateScoreViewState142 ScoreViewState() {} ScoreViewStateScoreViewState143 ScoreViewState(qreal zl, ZoomIndex zi, qreal x, qreal y) 144 { 145 logicalZoomLevel = zl; 146 zoomIndex = zi; 147 xOffset = x; 148 yOffset = y; 149 } 150 }; 151 152 //--------------------------------------------------------- 153 // ScoreView 154 //--------------------------------------------------------- 155 156 class ScoreView : public QWidget, public MuseScoreView { 157 Q_OBJECT 158 159 ViewState state; 160 OmrView* _omrView; 161 162 // the next elements are used during dragMove to give some visual 163 // feedback: 164 // dropTarget: if valid, the element is drawn in a different color 165 // to mark it as a valid drop target 166 // dropRectangle: if valid, the rectangle is filled with a 167 // color to visualize a valid drop area 168 // dropAnchor: if valid the line is drawn from the current 169 // cursor position to the current anchor point 170 // Note: 171 // only one of the elements is active during drag 172 173 const Element* dropTarget; ///< current drop target during dragMove 174 QRectF dropRectangle; ///< current drop rectangle during dragMove 175 QLineF dropAnchor; ///< line to current anchor point during dragMove 176 QVector<QLineF> m_dropAnchorLines; 177 178 QTransform _matrix, imatrix; 179 ZoomIndex _zoomIndex; 180 ZoomState _previousLogicalZoom { ZoomIndex::ZOOM_PAGE_WIDTH, 0.0 }; // for zoom-level toggling 181 182 QFocusFrame* focusFrame; 183 184 EditData editData; 185 std::vector<std::unique_ptr<ElementGroup>> dragGroups; 186 187 //--input state: 188 PositionCursor* _cursor; 189 190 PositionCursor* _controlCursor; 191 SmoothPanSettings _panSettings; 192 double _timeElapsed; 193 double _controlModifier; // a control modifier of 1 means that the cursor is moving at it's normal speed 194 // if all measures are of the same size, this will stay equal to 1 (unless the distance settings are changed, and make the algorithm over-sensitive) 195 double _playbackCursorOldPosition; 196 double _playbackCursorNewPosition; 197 double _playbackCursorDistanceTravelled; 198 199 ShadowNote* shadowNote; 200 201 // Realtime state: Note: always set allowRealtimeRests to desired value before starting a timer. 202 QTimer* realtimeTimer; // multi-shot timer for advancing in automatic realtime mode 203 QTimer* extendNoteTimer; // single-shot timer for initial advancement when a note is held 204 bool allowRealtimeRests; // Allow entering rests in realtime mode? (See note above) 205 206 bool tripleClickPending = false; 207 bool popupActive = false; 208 bool modifySelection = false; 209 Element* elementToSelect = nullptr; 210 211 // Loop In/Out marks in the score 212 PositionCursor* _curLoopIn; 213 PositionCursor* _curLoopOut; 214 215 // Continuous panel 216 ContinuousPanel* _continuousPanel; 217 218 Lasso* lasso; ///< temporarily drawn lasso selection 219 FotoLasso* _foto; 220 221 QColor _bgColor; 222 QColor _fgColor; 223 QPixmap* _bgPixmap; 224 QPixmap* _fgPixmap; 225 226 // By default when the view will prevent viewpoint changes if 227 // it is inactive. Set this flag to true to change this behaviour. 228 bool _moveWhenInactive = false; 229 230 bool _blockShowEdit = false; 231 232 virtual void paintEvent(QPaintEvent*); 233 void paint(const QRect&, QPainter&); 234 235 void objectPopup(const QPoint&, Element*); 236 void measurePopup(QContextMenuEvent* ev, Measure*); 237 238 void saveChord(XmlWriter&); 239 240 virtual bool event(QEvent* event) override; 241 virtual bool gestureEvent(QGestureEvent*); // ?? 242 virtual void resizeEvent(QResizeEvent*) override; 243 virtual void dragEnterEvent(QDragEnterEvent*) override; 244 virtual void dragLeaveEvent(QDragLeaveEvent*) override; 245 virtual void dragMoveEvent(QDragMoveEvent*) override; 246 virtual void dropEvent(QDropEvent*) override; 247 virtual void focusInEvent(QFocusEvent*) override; 248 virtual void focusOutEvent(QFocusEvent*) override; 249 250 virtual void wheelEvent(QWheelEvent*) override; 251 virtual void mouseMoveEvent(QMouseEvent*) override; 252 virtual void mousePressEvent(QMouseEvent*) override; 253 virtual void mouseReleaseEvent(QMouseEvent*) override; 254 virtual void mouseDoubleClickEvent(QMouseEvent*); 255 256 virtual void keyPressEvent(QKeyEvent*) override; 257 virtual void keyReleaseEvent(QKeyEvent*) override; 258 virtual void inputMethodEvent(QInputMethodEvent*) override; 259 260 bool handleArrowKeyPress(const QKeyEvent*); 261 262 virtual void contextMenuEvent(QContextMenuEvent*) override; 263 264 void mousePressEventNormal(QMouseEvent*); 265 void escapeCmd(); 266 bool startTextEditingOnMouseRelease(QMouseEvent*); 267 void adjustCursorForTextEditing(QMouseEvent*); 268 269 void constraintCanvas(int *dxx, int *dyy); 270 271 void setShadowNote(const QPointF&); 272 void drawElements(QPainter& p,QList<Element*>& el, Element* editElement); 273 bool dragTimeAnchorElement(const QPointF& pos); 274 bool dragMeasureAnchorElement(const QPointF& pos); 275 virtual void lyricsTab(bool back, bool end, bool moveOnly) override; 276 virtual void lyricsReturn() override; 277 virtual void lyricsEndEdit() override; 278 virtual void lyricsUpDown(bool up, bool end) override; 279 virtual void lyricsMinus() override; 280 virtual void lyricsUnderscore() override; 281 virtual void textTab(bool back = false) override; 282 void harmonyTab(bool back); 283 void harmonyBeatsTab(bool noterest, bool back); 284 void harmonyTicksTab(const Fraction& ticks); 285 void figuredBassTab(bool meas, bool back); 286 void figuredBassTicksTab(const Fraction& ticks); 287 void realtimeAdvance(bool allowRests); 288 void cmdAddFret(int fret); 289 void cmdAddChordName(HarmonyType ht); 290 void cmdAddText(Tid tid, Tid customTid = Tid::DEFAULT, PropertyFlags pf = PropertyFlags::STYLED, Placement p = Placement::ABOVE); 291 void cmdEnterRest(const TDuration&); 292 void cmdEnterRest(); 293 void cmdTuplet(int n, ChordRest*); 294 void cmdTuplet(int); 295 void cmdCreateTuplet(ChordRest* cr, Tuplet* tuplet); 296 void cmdRepeatSelection(); 297 void cmdChangeEnharmonic(bool); 298 299 MeasureBase* insertMeasure(ElementType, MeasureBase*); 300 MeasureBase* checkSelectionStateForInsertMeasure(); 301 302 void appendMeasures(int, ElementType); 303 MeasureBase* appendMeasure(ElementType); 304 void cmdInsertMeasure(ElementType); 305 void createElementPropertyMenu(Element* e, QMenu*); 306 void genPropertyMenu1(Element* e, QMenu* popup); 307 void genPropertyMenuText(Element* e, QMenu* popup); 308 void elementPropertyAction(const QString&, Element* e); 309 void paintPageBorder(QPainter& p, Page* page); 310 bool dropCanvas(Element*); 311 void editCmd(const QString&); 312 void setLoopCursor(PositionCursor* curLoop, const Fraction& tick, bool isInPos); 313 void cmdMoveCR(bool left); 314 void cmdGotoElement(Element*); 315 bool checkCopyOrCut(); 316 QVariant inputMethodQuery(Qt::InputMethodQuery query) const override; 317 void startFotomode(); 318 void stopFotomode(); 319 void startFotoDrag(); 320 void endFotoDrag(); 321 void endFotoDragEdit(); 322 QImage getRectImage(const QRectF& rect, double dpi, bool transparent, bool printMode); 323 324 void startEdit(bool editMode = true); 325 void endEdit(); 326 327 void startDrag(); 328 void endDrag(); 329 330 void endDragEdit(); 331 332 void startNoteEntry(); 333 virtual void startNoteEntryMode() override; 334 void endNoteEntry(); 335 336 void endLasso(); 337 Element* getDropTarget(EditData&); 338 339 private slots: 340 void posChanged(POS pos, unsigned tick); 341 void loopToggled(bool); 342 void triggerCmdRealtimeAdvance(); 343 void cmdRealtimeAdvance(); 344 void extendCurrentNote(); 345 void seqStopped(); 346 void tripleClickTimeOut(); 347 348 public slots: 349 void setViewRect(const QRectF&); 350 351 void deselectAll(); 352 353 void editCopy(); 354 void editCut(); 355 void editPaste(); 356 void editSwap(); 357 358 void normalCut(); 359 void normalCopy(); 360 void fotoModeCopy(bool includeLink = false); 361 bool normalPaste(Fraction scale = Fraction(1, 1)); 362 void normalSwap(); 363 364 void setControlCursorVisible(bool v); 365 366 void cloneElement(Element* e); 367 void doFotoDragEdit(QMouseEvent* ev); 368 369 void updateContinuousPanel(); 370 void ticksTab(const Fraction& ticks); // helper function 371 372 signals: 373 void viewRectChanged(); 374 void scaleChanged(double); 375 void offsetChanged(double, double); 376 void sizeChanged(); 377 378 public: 379 ScoreView(QWidget* parent = 0); 380 ~ScoreView(); 381 fgPixmap()382 QPixmap* fgPixmap() { return _fgPixmap; } 383 384 void startEdit(Element*, Grip) override; 385 void startEditMode(Element*); 386 387 void moveCursor(const Fraction& tick); 388 void moveControlCursor(const Fraction& tick); 389 bool isCursorDistanceReasonable(); 390 void moveControlCursorNearCursor(); 391 Fraction cursorTick() const; 392 void setCursorOn(bool); 393 void setBackground(QPixmap*); 394 void setBackground(const QColor&); 395 void setForeground(QPixmap*); 396 void setForeground(const QColor&); 397 398 Page* addPage(); 399 virtual void setScore(Score* s); removeScore()400 virtual void removeScore() { _score = 0; } 401 402 void setPhysicalZoomLevel(qreal logicalLevel); 403 404 bool navigatorVisible() const; 405 void cmd(const QAction*); 406 void cmd(const char*); 407 408 void startUndoRedo(bool); 409 void zoomBySteps(qreal numSteps, bool usingMouse = false, const QPointF& pos = QPointF()); 410 void setLogicalZoom(ZoomIndex index, qreal logicalLevel, const QPointF& pos = QPointF()); 411 qreal calculateLogicalZoomLevel(const ZoomIndex index, const qreal logicalFreeZoomLevel = 0.0) const; 412 qreal calculatePhysicalZoomLevel(const ZoomIndex index, const qreal logicalFreeZoomLevel = 0.0) const; 413 void contextPopup(QContextMenuEvent* ev); 414 bool editKeyLyrics(); 415 bool editKeySticking(); 416 void dragScoreView(QMouseEvent* ev); 417 void doDragElement(QMouseEvent* ev); 418 void doDragLasso(QMouseEvent* ev); 419 void doDragFoto(QMouseEvent* ev); 420 void doDragEdit(QMouseEvent* ev); 421 bool testElementDragTransition(QMouseEvent* ev); 422 bool fotoEditElementDragTransition(QMouseEvent* ev); 423 void cmdAddSlur(const Slur* slurTemplate = nullptr); 424 void addSlur(ChordRest*, ChordRest*, const Slur*) override; 425 virtual void cmdAddHairpin(HairpinType); 426 void cmdAddNoteLine(); 427 428 void setEditElement(Element*); 429 void updateEditElement(); 430 431 bool wasShown = false; noteEntryMode()432 bool noteEntryMode() const { return state == ViewState::NOTE_ENTRY; } editMode()433 bool editMode() const { return state == ViewState::EDIT; } textEditMode()434 bool textEditMode() const { return editMode() && editData.element && editData.element->isTextBase(); } hasEditGrips()435 bool hasEditGrips() const { return editData.element && editData.grips; } 436 bool fotoMode() const; 437 438 virtual void setDropRectangle(const QRectF&); 439 virtual void setDropTarget(const Element*) override; 440 void setDropAnchorLines(const QVector<QLineF> &anchorList); matrix()441 const QTransform& matrix() const { return _matrix; } 442 zoomIndex()443 ZoomIndex zoomIndex() const { return _zoomIndex; } 444 qreal logicalZoomLevel() const; 445 qreal physicalZoomLevel() const; logicalZoom()446 ZoomState logicalZoom() const { return { _zoomIndex, logicalZoomLevel() }; } setLogicalZoom(const ZoomState & logicalZoom)447 void setLogicalZoom(const ZoomState& logicalZoom) { setLogicalZoom(logicalZoom.index, logicalZoom.level); } 448 previousZoomIndex()449 ZoomIndex previousZoomIndex() const { return _previousLogicalZoom.index; } previousLogicalZoomLevel()450 qreal previousLogicalZoomLevel() const { return _previousLogicalZoom.level; } previousLogicalZoom()451 const ZoomState& previousLogicalZoom() const { return _previousLogicalZoom; } setPreviousLogicalZoom(ZoomState previousLogicalZoom)452 void setPreviousLogicalZoom(ZoomState previousLogicalZoom) { _previousLogicalZoom = std::move(previousLogicalZoom); } 453 454 qreal xoffset() const; 455 qreal yoffset() const; 456 void setOffset(qreal x, qreal y); 457 QSizeF fsize() const; 458 void screenNext(); 459 void screenPrev(); 460 void pageNext(); 461 void pagePrev(); 462 void pageTop(); 463 void pageEnd(); toLogical(const QPoint & p)464 QPointF toLogical(const QPoint& p) const { return imatrix.map(QPointF(p)); } toPhysical(const QPointF & p)465 QPointF toPhysical(const QPointF& p) const {return _matrix.map(p); } toLogical(const QRectF & r)466 QRectF toLogical(const QRectF& r) const { return imatrix.mapRect(r); } toPhysical(const QRectF & r)467 QRect toPhysical(const QRectF& r) const { return _matrix.mapRect(r).toRect(); } 468 canvasViewport()469 QRectF canvasViewport() const { return toLogical(geometry()); } 470 471 bool searchMeasure(int i); 472 bool searchPage(int i); 473 bool searchRehearsalMark(const QString& s); 474 void gotoMeasure(Measure*); 475 void setFocusRect(); 476 void changeVoice(int voice); 477 virtual void drawBackground(QPainter* p, const QRectF& r) const; 478 bool fotoScoreViewDragTest(QMouseEvent*); 479 bool fotoScoreViewDragRectTest(QMouseEvent*); 480 void doDragFotoRect(QMouseEvent*); 481 void fotoContextPopup(QContextMenuEvent*); 482 bool fotoRectHit(const QPoint& p); 483 void paintRect(bool printMode, QPainter& p, const QRectF& r, double mag); 484 bool saveFotoAs(bool printMode, const QRectF&); 485 void fotoDragDrop(QMouseEvent*); 486 void changeEditElement(Element*); 487 488 void cmdAppendMeasures(int, ElementType); 489 void cmdInsertMeasures(int, ElementType); 490 491 void cmdAddRemoveBreaks(); 492 void cmdCopyLyricsToClipboard(); 493 494 ScoreState mscoreState() const; 495 void setCursorVisible(bool v); 496 void showOmr(bool flag); 497 void midiNoteReceived(int pitch, bool chord, int velocity); 498 499 virtual void moveCursor() override; 500 panSettings()501 SmoothPanSettings& panSettings() { return _panSettings; } 502 503 virtual void layoutChanged(); 504 virtual void dataChanged(const QRectF&); updateAll()505 virtual void updateAll() { update(); } 506 virtual void adjustCanvasPosition(const Element* el, bool playBack, int staff = -1) override; setCursor(const QCursor & c)507 virtual void setCursor(const QCursor& c) { QWidget::setCursor(c); } cursor()508 virtual QCursor cursor() const { return QWidget::cursor(); } loopUpdate(bool val)509 void loopUpdate(bool val) { loopToggled(val); } 510 511 void moveViewportToLastEdit(); 512 513 void updateShadowNotes(); 514 omrView()515 OmrView* omrView() const { return _omrView; } setOmrView(OmrView * v)516 void setOmrView(OmrView* v) { _omrView = v; } fotoLasso()517 FotoLasso* fotoLasso() const { return _foto; } 518 Element* getEditElement(); 519 void onElementDestruction(Element*) override; 520 521 virtual Element* elementNear(QPointF); 522 QList<Element*> elementsNear(QPointF); 523 void editArticulationProperties(Articulation*); 524 void editTimeSigProperties(TimeSig*); 525 void editStaffTextProperties(StaffTextBase*); 526 void selectInstrument(InstrumentChange*); getEditData()527 EditData& getEditData() { return editData; } 528 void changeState(ViewState); 529 geometry()530 virtual const QRect geometry() const override { return QWidget::geometry(); } 531 532 void updateGrips(); moveWhenInactive()533 bool moveWhenInactive() const { return _moveWhenInactive; } moveWhenInactive(bool move)534 bool moveWhenInactive(bool move) { bool m = _moveWhenInactive; _moveWhenInactive = move; return m; } 535 536 QElapsedTimer _controlCursorTimer, _playbackCursorTimer; 537 friend struct SmoothPanSettings; 538 539 private: 540 void drawAnchorLines(QPainter& painter); 541 }; 542 543 } // namespace Ms 544 #endif 545 546