File indexing completed on 2024-05-05 03:50:38
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2009 Andrew Manson <g.real.ate@gmail.com> 0004 // SPDX-FileCopyrightText: 2013 Thibaut Gridel <tgridel@free.fr> 0005 // SPDX-FileCopyrightText: 2014 Calin Cruceru <crucerucalincristian@gmail.com> 0006 // 0007 0008 #ifndef AREAANNOTATION_H 0009 #define AREAANNOTATION_H 0010 0011 #include <QPointer> 0012 0013 #include "SceneGraphicsItem.h" 0014 #include "GeoDataCoordinates.h" 0015 0016 0017 namespace Marble 0018 { 0019 0020 class PolylineNode; 0021 class MergingPolygonNodesAnimation; 0022 0023 /** 0024 * @brief The AreaAnnotation class controls everything related to Polygons Editing Mode. 0025 * It includes polygons actions implementation and, at the same time, deals with painting 0026 * polygons on the map according to user's preference or to some particular states. 0027 */ 0028 class AreaAnnotation : public SceneGraphicsItem 0029 { 0030 friend class MergingPolygonNodesAnimation; 0031 0032 public: 0033 explicit AreaAnnotation( GeoDataPlacemark *placemark ); 0034 0035 ~AreaAnnotation() override; 0036 0037 /** 0038 * @brief Paints the nodes on the screen and updates the regions which correspond 0039 * to each node using the given GeoPainter. 0040 */ 0041 void paint( GeoPainter *painter, const ViewportParams *viewport, const QString &layer, int tileZoomLevel ) override; 0042 0043 /** 0044 * @brief Returns true if the given QPoint is contained by the current polygon. Note 0045 * that the return value depends on the state (e.g. in the AddingPolylineNodes state a 0046 * point is considered to be contained by the polygon if the virtual nodes or the 0047 * polygon's interior contain it, while in the Editing state, it is contained by the 0048 * polygon if either polygon's interior, the outer nodes or the inner nodes contain 0049 * it). 0050 */ 0051 bool containsPoint( const QPoint &point ) const override; 0052 0053 /** 0054 * @brief It is used so far to remove the hover effect while being in the 0055 * AddingPolylineNodes state (@see SceneGraphicsItem::dealWithItemChange documentation). 0056 */ 0057 void dealWithItemChange( const SceneGraphicsItem *other ) override; 0058 0059 /** 0060 * @brief Moves the whole polygon to the destination coordinates. 0061 */ 0062 void move( const GeoDataCoordinates &source, const GeoDataCoordinates &destination ) override; 0063 0064 /** 0065 * @brief Changes the busy state of the object according to @p enabled. It is mostly 0066 * used by Annotate Plugin to not send events to this object anymore but is different than 0067 * the focus property (you can have a focused polygon which does not accept events because 0068 * is busy). 0069 * 0070 * @param enabled the busy state of the object 0071 */ 0072 void setBusy( bool enabled ); 0073 0074 /** 0075 * @brief Returns whether the annotation is 'busy' or not - this usually means that something 0076 * is being performed and it does not accept events anymore. 0077 */ 0078 bool isBusy() const; 0079 0080 /** 0081 * @brief Iterates through all nodes which form the polygon's outer boundary as well 0082 * as all its inner boundaries and sets the IsSelected flag to false. 0083 */ 0084 void deselectAllNodes(); 0085 0086 /** 0087 * @brief Iterates through all nodes which form the polygon's outer boundary as well 0088 * as all its inner boundaries and deletes the selected ones. 0089 */ 0090 void deleteAllSelectedNodes(); 0091 0092 /** 0093 * @brief Deletes the last clicked node while being in the Editing state. 0094 */ 0095 void deleteClickedNode(); 0096 0097 /** 0098 * @brief If the last clicked node is selected, set its IsSelected flag to false and 0099 * vice versa. 0100 */ 0101 void changeClickedNodeSelection(); 0102 0103 /** 0104 * @brief Tests if there are any selected nodes. 0105 */ 0106 bool hasNodesSelected() const; 0107 0108 /** 0109 * @brief Tests if the last clicked node is selected. 0110 */ 0111 bool clickedNodeIsSelected() const; 0112 0113 /** 0114 * @brief Returns the animation to be handled by a QObject which can connect signals 0115 * and slots. 0116 */ 0117 QPointer<MergingPolygonNodesAnimation> animation(); 0118 0119 /** 0120 * @brief Provides information for downcasting a SceneGraphicsItem. 0121 */ 0122 const char *graphicType() const override; 0123 0124 protected: 0125 /** 0126 * @brief Protected methods which handle mouse events and are called by 0127 * SceneGraphicsItem::sceneEvent() (@see Template Method pattern). Each of these 0128 * event handlers are structured according to the state. 0129 */ 0130 bool mousePressEvent( QMouseEvent *event ) override; 0131 bool mouseMoveEvent( QMouseEvent *event ) override; 0132 bool mouseReleaseEvent( QMouseEvent *event ) override; 0133 0134 /** 0135 * @brief Protected method which applies the Polygons modifications when changing 0136 * states. 0137 */ 0138 void dealWithStateChange( SceneGraphicsItem::ActionState previousState ) override; 0139 0140 private: 0141 /** 0142 * @brief Returns true if the Polygon has a valid shape (so far, the only times when 0143 * it could have an invalid shape would be when deleting/merging nodes from its outer 0144 * boundary and it would not contains anymore all the nodes which form its inner 0145 * boundaries). 0146 */ 0147 bool isValidPolygon() const; 0148 0149 /** 0150 * @brief It is called when the ::paint method is called for the first time. It 0151 * initializes the m_outerNodesList by creating the PolylineNodes. 0152 * @see updateRegions() method for more detailed explanation. 0153 */ 0154 void setupRegionsLists( GeoPainter *painter ); 0155 0156 /** 0157 * @brief As briefly mentioned above, the PolylineNodes instances are not created at 0158 * each ::paint call, but only at its first call. Every time the ::paint method is 0159 * called after that, each node from the lists of PolylineNodes gets its setRegion() 0160 * method called. We need the GeoPainter for doing this because we have to get the 0161 * ellipse around the GeoDataCoordinates. 0162 */ 0163 void updateRegions( GeoPainter *painter ); 0164 0165 /** 0166 * @brief It iterates through all nodes and paints them on the map. It takes into 0167 * consideration the active flags of each PolylineNode. 0168 */ 0169 void drawNodes( GeoPainter *painter ); 0170 0171 /** 0172 * @brief The following functions test whether the given @p point is contained by 0173 * each list. 0174 * @return The QPair<int, int> returned by innerNodeContains is extensively used 0175 * within the implementation and has the following interpretation: the node which 0176 * contains the given point is the '.second'h node from the '.first'h inner boundary. 0177 */ 0178 int outerNodeContains( const QPoint &point ) const; 0179 QPair<int, int> innerNodeContains( const QPoint &point ) const; 0180 QPair<int, int> virtualNodeContains( const QPoint &point ) const; 0181 int innerBoundsContain( const QPoint &point ) const; 0182 bool polygonContains( const QPoint &point ) const; 0183 0184 /** 0185 * @brief It is called from processOnMove functions and deals with polygons 0186 * hovering. 0187 */ 0188 bool dealWithHovering( QMouseEvent *mouseEvent ); 0189 0190 /** 0191 * @brief Each state has its corresponding event handler, since in each state the 0192 * item may behave differently. These are the event handlers for the Editing state. 0193 */ 0194 bool processEditingOnPress( QMouseEvent *mouseEvent ); 0195 bool processEditingOnMove( QMouseEvent *mouseEvent ); 0196 bool processEditingOnRelease( QMouseEvent *mouseEvent ); 0197 0198 /** 0199 * @brief These are the event handlers for the AddingPolygonHole state. 0200 */ 0201 bool processAddingHoleOnPress( QMouseEvent *mouseEvent ); 0202 static bool processAddingHoleOnMove(QMouseEvent *mouseEvent); 0203 static bool processAddingHoleOnRelease(QMouseEvent *mouseEvent); 0204 0205 /** 0206 * @brief These are the event handlers for the MergingPolylineNodes state. 0207 */ 0208 bool processMergingOnPress( QMouseEvent *mouseEvent ); 0209 bool processMergingOnMove( QMouseEvent *mouseEvent ); 0210 static bool processMergingOnRelease(QMouseEvent *mouseEvent); 0211 0212 /** 0213 * @brief These are the event handlers for the AddingPolylineNodes state. 0214 */ 0215 bool processAddingNodesOnPress( QMouseEvent *mouseEvent ); 0216 bool processAddingNodesOnMove( QMouseEvent *mouseEvent ); 0217 bool processAddingNodesOnRelease( QMouseEvent *mouseEvent ); 0218 0219 /** 0220 * @brief Since they are used in many functions, the size and color of nodes for each 0221 * state are static and have class scope. 0222 */ 0223 static const int regularDim; 0224 static const int selectedDim; 0225 static const int mergedDim; 0226 static const int hoveredDim; 0227 static const QColor regularColor; 0228 static const QColor mergedColor; 0229 0230 const ViewportParams *m_viewport; 0231 bool m_regionsInitialized; 0232 bool m_busy; 0233 0234 QVector<PolylineNode> m_outerNodesList; 0235 QVector<PolylineNode> m_outerVirtualNodes; 0236 QVector< QVector<PolylineNode> > m_innerNodesList; 0237 QVector< QVector<PolylineNode> > m_innerVirtualNodes; 0238 QVector<QRegion> m_boundariesList; 0239 0240 // Used in the Editing state 0241 enum EditingInteractingObject { 0242 InteractingNothing, // e.g. when hovering 0243 InteractingNode, 0244 InteractingPolygon 0245 }; 0246 GeoDataCoordinates m_movedPointCoords; 0247 QPair<int, int> m_clickedNodeIndexes; 0248 QPair<int, int> m_hoveredNode; 0249 EditingInteractingObject m_interactingObj; 0250 0251 // Used in Merging Nodes state 0252 QPair<int, int> m_firstMergedNode; 0253 QPair<int, int> m_secondMergedNode; 0254 QPointer<MergingPolygonNodesAnimation> m_animation; 0255 0256 // Used in Adding Nodes state 0257 QPair<int, int> m_virtualHovered; 0258 0259 // It can have the following values: 0260 // -> -2 - means there is no node being adjusted; 0261 // -> -1 - means the node which is being adjusted is a node from polygon's 0262 // outer boundary (more exactly, the last; see below); 0263 // -> i - (i >= 0) means the node which is being adjusted is a node from 0264 // the i'th inner boundary (more exactly, the last one; see below). 0265 // Due to the way the node appending is done (by rotating the vector which 0266 // contains the coordinates), we can be sure that the node we want to adjust 0267 // is every time the last one. 0268 int m_adjustedNode; 0269 }; 0270 0271 } 0272 0273 #endif