File indexing completed on 2024-05-05 03:50:40

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2014 Calin Cruceru <crucerucalincristian@gmail.com>
0004 //
0005 
0006 #ifndef POLYLINEANNOTATION_H
0007 #define POLYLINEANNOTATION_H
0008 
0009 #include <QColor>
0010 #include <QPointer>
0011 
0012 #include "SceneGraphicsItem.h"
0013 #include "GeoDataCoordinates.h"
0014 
0015 
0016 namespace Marble
0017 {
0018 
0019 class PolylineNode;
0020 class MergingPolylineNodesAnimation;
0021 
0022 class PolylineAnnotation : public SceneGraphicsItem
0023 {
0024     friend class MergingPolylineNodesAnimation;
0025 
0026 public:
0027     explicit PolylineAnnotation( GeoDataPlacemark *placemark );
0028     ~PolylineAnnotation() override;
0029 
0030     /**
0031      * @brief Paints the nodes on the screen and updates the regions which correspond
0032      * to each node using the given GeoPainter.
0033      */
0034     void paint( GeoPainter *painter, const ViewportParams *viewport, const QString &layer , int tileZoomLevel) override;
0035 
0036     /**
0037      * @brief Returns true if either the polyline's associated region or one of its nodes
0038      * contains the given QPoint. Note that the return value depends on the state.
0039      */
0040     bool containsPoint( const QPoint &eventPos ) const override;
0041 
0042     /**
0043      * @brief It is used so far to remove the hover effect while being in the
0044      * AddingPolylineNodes state (@see SceneGraphicsItem::dealWithItemChange documentation).
0045      */
0046     void dealWithItemChange( const SceneGraphicsItem *other ) override;
0047 
0048     /**
0049      * @brief Moves the whole polyline to the destination point.
0050      */
0051     void move( const GeoDataCoordinates &source, const GeoDataCoordinates &destination ) override;
0052 
0053     /**
0054      * @brief Changes the busy state of the object according to @p enabled. It is mostly used
0055      * by Annotate Plugin to not send events to this object anymore but is different than the
0056      * focus property (you can have a focused polyline which does not accept events because is
0057      * busy).
0058      */
0059     void setBusy( bool enabled );
0060 
0061     /**
0062      * @brief Returns whether the annotation is 'busy' or not - this usually means that something
0063      * is being performed and it does not accept events anymore.
0064      */
0065     bool isBusy() const;
0066 
0067     /**
0068      * @brief Iterates through all nodes which form the polyline and sets the IsSelected flag to
0069      * false.
0070      */
0071     void deselectAllNodes();
0072 
0073     /**
0074      * @brief Iterates through all nodes which form the polyline and deletes the selected ones.
0075      */
0076     void deleteAllSelectedNodes();
0077 
0078     /**
0079      * @brief Deletes the last clicked node while being in the Editing state.
0080      */
0081     void deleteClickedNode();
0082 
0083     /**
0084      * @brief If the last clicked node is selected, set its IsSelected flag to false and
0085      * vice versa.
0086      */
0087     void changeClickedNodeSelection();
0088 
0089     /**
0090      * @brief Tests if there are any selected nodes.
0091      */
0092     bool hasNodesSelected() const;
0093 
0094     /**
0095      * @brief Tests if the last clicked node is selected.
0096      */
0097     bool clickedNodeIsSelected() const;
0098 
0099     /**
0100      * @brief Returns the animation to be handled by a QObject which can connect signals
0101      * and slots.
0102      */
0103     QPointer<MergingPolylineNodesAnimation> animation();
0104 
0105     /**
0106      * @brief Provides information for downcasting a SceneGraphicsItem.
0107      */
0108     const char *graphicType() const override;
0109 
0110 protected:
0111     /**
0112      * @brief Protected methods which handle mouse events and are called by
0113      * SceneGraphicsItem::sceneEvent() (@see Template Method pattern). Each of these
0114      * event handlers are structured according to the state.
0115      */
0116     bool mousePressEvent( QMouseEvent *event ) override;
0117     bool mouseMoveEvent( QMouseEvent *event ) override;
0118     bool mouseReleaseEvent( QMouseEvent *event ) override;
0119 
0120     void dealWithStateChange( SceneGraphicsItem::ActionState previousState ) override;
0121 
0122 private:
0123     /**
0124     * @brief It is called when the ::paint method is called for the first time. It
0125     * initializes the m_nodesList by creating the PolylineNodes.
0126     * @see updateRegions() method for more detailed explanation.
0127     */
0128     void setupRegionsLists( GeoPainter *painter );
0129 
0130     /**
0131      * @brief As briefly mentioned above, the PolylineNodes instances are not created at
0132      * each ::paint call, but only at its first call. Every time the ::paint method is
0133      * called after that, each node from the lists of PolylineNodes gets its setRegion()
0134      * method called. We need the GeoPainter for doing this because we have to get the
0135      * ellipse around the GeoDataCoordinates.
0136      */
0137     void updateRegions( GeoPainter *painter );
0138 
0139     /**
0140      * @brief It iterates through all nodes and paints them on the map. It takes into
0141      * consideration the active flags of each PolylineNode.
0142      */
0143     void drawNodes( GeoPainter *painter );
0144 
0145     /**
0146      * @brief Tests if the polyline's nodes contain the given point and in case they do, it
0147      * returns the index of the first one.
0148      */
0149     int nodeContains( const QPoint &point ) const;
0150 
0151     /**
0152      * @brief Tests if the polyline's virtual nodes contain the given point and in case they
0153      * do, it returns the index of the first one.
0154      */
0155     int virtualNodeContains( const QPoint &point ) const;
0156 
0157     /**
0158      * @brief Returns true/false on how the polyline (its 'lines' excepting its nodes) contain
0159      * the given point or not.
0160      */
0161     bool polylineContains( const QPoint &point ) const;
0162 
0163     /**
0164      * @brief It is called from processOnMove functions and deals with polylines
0165      * hovering.
0166      */
0167     bool dealWithHovering( QMouseEvent *mouseEvent );
0168 
0169     /**
0170      * @brief Each state has its corresponding event handler, since in each state the
0171      * item may behave differently. These are the event handlers for the Editing state.
0172      */
0173     bool processEditingOnPress( QMouseEvent *mouseEvent );
0174     bool processEditingOnMove( QMouseEvent *mouseEvent );
0175     bool processEditingOnRelease( QMouseEvent *mouseEvent );
0176 
0177     /**
0178      * @brief These are the event handlers for the MergingPolylineNodes state.
0179      */
0180     bool processMergingOnPress( QMouseEvent *mouseEvent );
0181     bool processMergingOnMove( QMouseEvent *mouseEvent );
0182     static bool processMergingOnRelease(QMouseEvent *mouseEvent);
0183 
0184     /**
0185      * @brief These are the event handlers for the AddingPolylineNodes state.
0186      */
0187     bool processAddingNodesOnPress( QMouseEvent *mouseEvent );
0188     bool processAddingNodesOnMove( QMouseEvent *mouseEvent );
0189     bool processAddingNodesOnRelease( QMouseEvent *mouseEvent );
0190 
0191 
0192 
0193     /**
0194      * @brief Since they are used in many functions, the size and color of nodes for each
0195      * state are static and have class scope.
0196      */
0197     static const int regularDim;
0198     static const int selectedDim;
0199     static const int mergedDim;
0200     static const int hoveredDim;
0201     static const QColor regularColor;
0202     static const QColor mergedColor;
0203 
0204     const ViewportParams *m_viewport;
0205     bool m_regionsInitialized;
0206     bool m_busy;
0207 
0208     QVector<PolylineNode> m_nodesList;
0209     QVector<PolylineNode> m_virtualNodesList;
0210     QRegion               m_polylineRegion;
0211 
0212     // Used in Editing state
0213     enum EditingInteractingObject {
0214         InteractingNothing, // e.g. when hovering
0215         InteractingNode,
0216         InteractingPolyline
0217     };
0218     EditingInteractingObject m_interactingObj;
0219     GeoDataCoordinates m_movedPointCoords;
0220     int m_clickedNodeIndex;
0221     int m_hoveredNodeIndex;
0222 
0223     // Used in Merging Nodes state
0224     QPointer<MergingPolylineNodesAnimation> m_animation;
0225     int m_firstMergedNode;
0226     int m_secondMergedNode;
0227 
0228     // Used in Adding Nodes state
0229     int m_virtualHoveredNode;
0230     int m_adjustedNode;
0231 };
0232 
0233 }
0234 
0235 #endif