1 /*************************************************************************** 2 qgslayoutruler.h 3 ---------------- 4 Date : July 2017 5 Copyright : (C) 2017 Nyall Dawson 6 Email : nyall dot dawson at gmail dot com 7 *************************************************************************** 8 * * 9 * This program is free software; you can redistribute it and/or modify * 10 * it under the terms of the GNU General Public License as published by * 11 * the Free Software Foundation; either version 2 of the License, or * 12 * (at your option) any later version. * 13 * * 14 ***************************************************************************/ 15 #ifndef QGSLAYOUTRULER_H 16 #define QGSLAYOUTRULER_H 17 18 #include "qgis_gui.h" 19 #include "qgis_sip.h" 20 #include <QWidget> 21 #include <QPointer> 22 #include <QMenu> 23 #include <memory> 24 25 class QgsLayout; 26 class QGraphicsLineItem; 27 class QgsLayoutView; 28 class QgsLayoutGuide; 29 30 /** 31 * \ingroup gui 32 * \brief A custom ruler widget for use with QgsLayoutView, displaying the 33 * current zoom and position of the visible layout and for interacting 34 * with guides in a layout. 35 * 36 * \since QGIS 3.0 37 */ 38 class GUI_EXPORT QgsLayoutRuler: public QWidget 39 { 40 Q_OBJECT 41 42 public: 43 44 /** 45 * Constructor for QgsLayoutRuler, with the specified \a parent widget and \a orientation. 46 */ 47 explicit QgsLayoutRuler( QWidget *parent SIP_TRANSFERTHIS = nullptr, Qt::Orientation orientation = Qt::Horizontal ); 48 49 QSize minimumSizeHint() const override; 50 51 /** 52 * Sets the current scene \a transform. This is usually the transform set for a view 53 * showing the associated scene, in order to synchronize the view's display of 54 * the scene with the rulers. 55 */ 56 void setSceneTransform( const QTransform &transform ); 57 58 /** 59 * Returns the current layout view associated with the ruler. 60 * \see setLayoutView() 61 */ layoutView()62 QgsLayoutView *layoutView() { return mView; } 63 64 /** 65 * Sets the current layout \a view to synchronize the ruler with. 66 * \see layoutView() 67 */ 68 void setLayoutView( QgsLayoutView *view ); 69 70 /** 71 * Returns the ruler size (either the height of a horizontal ruler or the 72 * width of a vertical rule). 73 */ rulerSize()74 int rulerSize() const { return mRulerMinSize; } 75 76 /** 77 * Sets a context \a menu to show when right clicking occurs on the ruler. 78 * Ownership of \a menu is unchanged. 79 */ 80 void setContextMenu( QMenu *menu ); 81 82 public slots: 83 84 /** 85 * Updates the \a position of the marker showing the current mouse position within 86 * the view. 87 * \a position is in layout coordinates. 88 */ 89 void setCursorPosition( QPointF position ); 90 91 signals: 92 //! Emitted when mouse cursor coordinates change 93 void cursorPosChanged( QPointF ); 94 95 protected: 96 void paintEvent( QPaintEvent *event ) override; 97 void mouseMoveEvent( QMouseEvent *event ) override; 98 void mousePressEvent( QMouseEvent *event ) override; 99 void mouseReleaseEvent( QMouseEvent *event ) override; 100 101 private: 102 static const int VALID_SCALE_MULTIPLES[]; 103 static const int VALID_SCALE_MAGNITUDES[]; 104 105 Qt::Orientation mOrientation = Qt::Horizontal; 106 QgsLayoutView *mView = nullptr; 107 108 QTransform mTransform; 109 QPoint mMarkerPos; 110 111 QFont mRulerFont; 112 std::unique_ptr< QFontMetrics > mRulerFontMetrics; 113 114 double mScaleMinPixelsWidth = 0.0; 115 int mRulerMinSize; 116 int mMinPixelsPerDivision; 117 int mPixelsBetweenLineAndText; 118 int mTextBaseline; 119 int mMinSpacingVerticalLabels; 120 121 int mDragGuideTolerance = 0; 122 QgsLayoutGuide *mDraggingGuide = nullptr; 123 QgsLayoutGuide *mHoverGuide = nullptr; 124 125 bool mCreatingGuide = false; 126 QGraphicsLineItem *mGuideItem = nullptr; 127 128 //! Polygon for drawing guide markers 129 QPolygonF mGuideMarker; 130 131 QPointer< QMenu > mMenu; 132 133 //! Calculates the optimum labeled units for ruler so that labels are a good distance apart 134 int optimumScale( double minPixelDiff, int &magnitude, int &multiple ); 135 136 /** 137 * Calculate the number of small divisions for each ruler unit, ensuring that they 138 * are sufficiently spaced. 139 */ 140 int optimumNumberDivisions( double rulerScale, int scaleMultiple ); 141 142 //! Draws vertical text on a painter 143 void drawRotatedText( QPainter *painter, QPointF pos, const QString &text ); 144 145 /** 146 * Draws small ruler divisions. 147 * Starting at startPos in mm, for numDivisions divisions, with major division spacing of rulerScale (in mm) 148 * Stop drawing if position exceeds maxPos 149 */ 150 void drawSmallDivisions( QPainter *painter, double startPos, int numDivisions, double rulerScale, double maxPos = 0 ); 151 152 //! Draw current marker pos on ruler 153 void drawMarkerPos( QPainter *painter ); 154 155 void drawGuideMarkers( QPainter *painter, QgsLayout *layout ); 156 157 //! Draw a guide marker on the ruler 158 void drawGuideAtPos( QPainter *painter, QPoint pos ); 159 160 void createTemporaryGuideItem(); 161 162 QPointF convertLocalPointToLayout( QPoint localPoint ) const; 163 164 QPoint convertLayoutPointToLocal( QPointF layoutPoint ) const; 165 166 /** 167 * Returns the closest guide to a local ruler point, or NULLPTR if no guides 168 * are within the acceptable tolerance of the point. 169 */ 170 QgsLayoutGuide *guideAtPoint( QPoint localPoint ) const; 171 172 }; 173 174 #endif // QGSLAYOUTRULER_H 175