LCOV - code coverage report
Current view: top level - src/notationscene/qml/MuseScore/NotationScene - notationviewinputcontroller.h Coverage Total Hit
Test: filtered_coverage.info Lines: 50.0 % 2 1
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : #pragma once
      23              : 
      24              : #include <QtEvents>
      25              : 
      26              : #include "../../../internal/inotationviewcontroller.h"
      27              : 
      28              : #include "modularity/ioc.h"
      29              : 
      30              : #include "async/asyncable.h"
      31              : 
      32              : #include "project/iprojectsession.h"
      33              : 
      34              : #include "notation/inotationinteraction.h"
      35              : #include "notation/inotationplayback.h"
      36              : #include "notation/inotationconfiguration.h"
      37              : #include "notation/inotationcontextconfiguration.h"
      38              : #include "notation/types/viewmode.h"
      39              : 
      40              : #include "notationscene/inotationcommandscontroller.h"
      41              : 
      42              : #include "playback/iplaybackcontroller.h"
      43              : 
      44              : #include "global/iglobalconfiguration.h"
      45              : #include "ui/idragcontroller.h"
      46              : #include "ui/iuiconfiguration.h"
      47              : #include "rcommand/icommanddispatcher.h"
      48              : 
      49              : #include "abstractelementpopupmodel.h"
      50              : 
      51              : class QQuickItem;
      52              : 
      53              : namespace mu::notation {
      54              : class IControlledView
      55              : {
      56              : public:
      57           12 :     virtual ~IControlledView() = default;
      58              : 
      59              :     virtual qreal width() const = 0;
      60              :     virtual qreal height() const = 0;
      61              : 
      62              :     virtual muse::PointF viewportTopLeft() const = 0;
      63              : 
      64              :     //! muse::Returns true if the canvas has been moved
      65              :     virtual bool moveCanvas(qreal dx, qreal dy) = 0;
      66              :     virtual void moveCanvasHorizontal(qreal dx) = 0;
      67              :     virtual void moveCanvasVertical(qreal dy) = 0;
      68              : 
      69              :     virtual muse::RectF notationContentRect() const = 0;
      70              :     virtual qreal currentScaling() const = 0;
      71              :     virtual void setScaling(qreal scaling, const muse::PointF& pos, bool overrideZoomType = true) = 0;
      72              : 
      73              :     virtual muse::PointF toLogical(const muse::PointF& p) const = 0;
      74              :     virtual muse::PointF toLogical(const QPointF& p) const = 0;
      75              :     virtual muse::PointF fromLogical(const muse::PointF& r) const = 0;
      76              :     virtual muse::RectF fromLogical(const muse::RectF& r) const = 0;
      77              : 
      78              :     virtual bool isNoteEnterMode() const = 0;
      79              : 
      80              :     virtual void showContextMenu(const ElementType& elementType, const QPointF& pos) = 0;
      81              :     virtual void hideContextMenu() = 0;
      82              : 
      83              :     virtual void showSearch() = 0;
      84              : 
      85              :     virtual void showElementPopup(const ElementType& elementType) = 0;
      86              :     virtual void hideElementPopup(const ElementType& elementType) = 0;
      87              :     virtual void hideElementPopup(PopupModelType modelType = PopupModelType::TYPE_UNDEFINED) = 0;
      88              :     virtual void toggleElementPopup(const ElementType& elementType) = 0;
      89              : 
      90              :     virtual bool elementPopupIsOpen(const ElementType& elementType) const = 0;
      91              : 
      92              :     virtual INotationInteractionPtr notationInteraction() const = 0;
      93              :     virtual INotationPlaybackPtr notationPlayback() const = 0;
      94              : 
      95              :     virtual QQuickItem* asItem() = 0;
      96              : 
      97              :     virtual void scheduleRedraw(const muse::RectF& rect = muse::RectF()) = 0;
      98              : };
      99              : 
     100              : class NotationViewInputController : public INotationViewController, public muse::Contextable, public muse::async::Asyncable
     101              : {
     102              : public:
     103              :     muse::GlobalInject<muse::IGlobalConfiguration> globalConfiguration;
     104              :     muse::GlobalInject<INotationConfiguration> configuration;
     105              :     muse::GlobalInject<muse::ui::IUiConfiguration> uiConfiguration;
     106              :     muse::ContextInject<INotationContextConfiguration> contextConfiguration = { this };
     107              :     muse::ContextInject<muse::rcommand::ICommandDispatcher> commandDispatcher = { this };
     108              :     muse::ContextInject<playback::IPlaybackController> playbackController = { this };
     109              :     muse::ContextInject<project::IProjectSession> projectSession = { this };
     110              :     muse::ContextInject<muse::ui::IDragController> dragController = { this };
     111              :     muse::ContextInject<INotationCommandsController> commandsController = { this };
     112              : 
     113              : public:
     114              :     NotationViewInputController(IControlledView* view, const muse::modularity::ContextPtr& iocCtx);
     115              :     ~NotationViewInputController();
     116              : 
     117              :     void init();
     118              :     void deinit();
     119              : 
     120              :     // INotationViewController
     121              :     void zoomIn() override;
     122              :     void zoomOut() override;
     123              :     void zoomToPageWidth() override;
     124              :     void zoomToWholePage() override;
     125              :     void zoomToTwoPages() override;
     126              :     void setZoom(int zoomPercentage) override;
     127              : 
     128              :     void setViewMode(ViewMode viewMode) override;
     129              : 
     130              :     void nextScreen() override;
     131              :     void previousScreen() override;
     132              :     void nextPage() override;
     133              :     void previousPage() override;
     134              :     void startOfScore() override;
     135              :     void endOfScore() override;
     136              : 
     137              :     void openContextMenuOfSelection() override;
     138              : 
     139              :     void togglePopupForItemIfSupports(const EngravingItem* item) override;
     140              : 
     141              :     void showSearch() override;
     142              : 
     143              :     void redrawView() override;
     144              :     // -----------------------
     145              : 
     146              :     void initZoom();
     147              :     void updateZoomAfterSizeChange();
     148              : 
     149              :     void initCanvasPos();
     150              : 
     151              :     bool readonly() const;
     152              :     void setReadonly(bool readonly);
     153              : 
     154              :     void pinchToZoom(qreal scaleFactor, const QPointF& pos);
     155              :     void wheelEvent(QWheelEvent* event);
     156              :     void mousePressEvent(QMouseEvent* event);
     157              :     void mouseMoveEvent(QMouseEvent* event);
     158              :     void mouseReleaseEvent(QMouseEvent* event);
     159              :     void mouseDoubleClickEvent(QMouseEvent* event);
     160              :     void hoverMoveEvent(QHoverEvent* event);
     161              :     void hoverLeaveEvent(QHoverEvent* event);
     162              :     bool shortcutOverrideEvent(QKeyEvent* event);
     163              :     void keyPressEvent(QKeyEvent* event);
     164              :     void keyReleaseEvent(QKeyEvent* event);
     165              :     void inputMethodEvent(QInputMethodEvent* event);
     166              : 
     167              :     bool canHandleInputMethodQuery(Qt::InputMethodQuery query) const;
     168              :     QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
     169              : 
     170            0 :     bool ignoreNextMouseContextMenuEvent() const { return m_ignoreNextMouseContextMenuEvent; }
     171              : 
     172              :     void dragEnterEvent(QDragEnterEvent* event);
     173              :     void dragLeaveEvent(QDragLeaveEvent* event);
     174              :     void dragMoveEvent(QDragMoveEvent* event);
     175              :     void dropEvent(QDropEvent* event);
     176              : 
     177              :     ElementType selectionType() const;
     178              :     muse::PointF selectionElementPos() const;
     179              : 
     180              : private:
     181              :     INotationPtr currentNotation() const;
     182              :     INotationStylePtr notationStyle() const;
     183              :     INotationInteractionPtr viewInteraction() const;
     184              :     const INotationInteraction::HitElementContext& hitElementContext() const;
     185              : 
     186              :     void onNotationChanged();
     187              : 
     188              :     void doZoomToPageWidth();
     189              :     void doZoomToWholePage();
     190              :     void doZoomToTwoPages();
     191              :     int currentZoomIndex() const;
     192              :     int currentZoomPercentage() const;
     193              :     muse::PointF findZoomFocusPoint() const;
     194              :     void doSetZoom(int zoomPercentage, const muse::PointF& pos);
     195              :     qreal scalingFromZoomPercentage(int zoomPercentage) const;
     196              :     int zoomPercentageFromScaling(qreal scaling) const;
     197              : 
     198              :     void moveScreen(int direction);
     199              :     void movePage(int direction);
     200              : 
     201              :     void setScaling(qreal scaling, const muse::PointF& pos = muse::PointF(), bool overrideZoomType = true);
     202              : 
     203              :     void startDragElements(ElementType elementsType, const muse::PointF& elementsOffset);
     204              : 
     205              :     void updateShadowNotePopupVisibility(bool forceHide = false);
     206              : 
     207              :     float hitWidth() const;
     208              : 
     209              :     struct ClickContext {
     210              :         muse::PointF logicClickPos;
     211              :         const QMouseEvent* event = nullptr;
     212              :         mu::engraving::EngravingItem* hitElement = nullptr;
     213              :         mu::engraving::staff_idx_t hitStaff = muse::nidx;
     214              :         bool isHitGrip = false;
     215              :     };
     216              : 
     217              :     void handleClickInNoteInputMode(QMouseEvent* event);
     218              :     bool mousePress_considerGrip(const ClickContext& ctx); // returns true if event is consumed
     219              :     bool mousePress_considerDragOutgoingElement(const ClickContext& ctx);
     220              :     void mousePress_considerSelect(const ClickContext& ctx);
     221              :     void mousePress_seekSelection(const ClickContext& ctx);
     222              :     void cycleOverlappingHitElements(const std::vector<EngravingItem*>& hitElements, staff_idx_t hitStaffIndex);
     223              :     bool mousePress_considerDragOutgoingRange(const ClickContext& ctx);
     224              :     bool mousePress_considerStartPasteRangeOnRelease(const ClickContext& ctx);
     225              :     void handleLeftClick(const ClickContext& ctx);
     226              :     void handleRightClick();
     227              :     void handleLeftClickRelease(const QPointF& releasePoint);
     228              : 
     229              :     bool startTextEditingAllowed() const;
     230              :     void updateTextCursorPosition();
     231              : 
     232              :     bool isAnchorEditingEvent(QKeyEvent* event) const;
     233              : 
     234              :     bool tryPercussionShortcut(QKeyEvent* event);
     235              : 
     236              :     IControlledView* m_view = nullptr;
     237              : 
     238              :     QList<int> m_possibleZoomPercentages;
     239              : 
     240              :     bool m_readonly = false;
     241              :     bool m_isCanvasDragged = false;
     242              :     bool m_tripleClickPending = false;
     243              : 
     244              :     struct MouseDownInfo {
     245              :         enum DragAction {
     246              :             DragOutgoingElement,
     247              :             DragOutgoingRange,
     248              :             PasteRangeOnRelease,
     249              :             Other,
     250              :             Nothing
     251              :         } dragAction = Other;
     252              : 
     253              :         QPointF physicalBeginPoint;
     254              :         muse::PointF logicalBeginPoint;
     255              :     } m_mouseDownInfo;
     256              : 
     257              :     struct DragMoveEvent {
     258              :         QPointF position;
     259              :         Qt::KeyboardModifiers modifiers;
     260              :         Qt::DropAction dropAction = Qt::DropAction::CopyAction;
     261              :         QObject* source = nullptr;
     262              :     };
     263              : 
     264              :     bool dropEvent(const DragMoveEvent& event, const QMimeData* mimeData = nullptr);
     265              : 
     266              :     std::vector<int> pitchesBeingDragged() const;
     267              : 
     268              :     DragMoveEvent m_lastDragMoveEvent;
     269              : 
     270              :     const mu::engraving::EngravingItem* m_prevSelectedElement = nullptr;
     271              :     std::vector<const mu::engraving::EngravingItem*> m_notesBeingDragged;
     272              : 
     273              :     bool m_hitElementWasAlreadySingleSelected = false;
     274              :     bool m_shouldSelectOnLeftClickRelease = false;
     275              :     bool m_shouldStartEditOnLeftClickRelease = false;
     276              :     bool m_ignoreNextMouseContextMenuEvent = false;
     277              : };
     278              : }
        

Generated by: LCOV version 2.0-1