1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2009-12-01
7  * Description : An abstract base class for tiling of markers
8  *
9  * Copyright (C) 2009-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
10  * Copyright (C) 2009-2011 by Michael G. Hansen <mike at mghansen dot de>
11  *
12  * This program is free software; you can redistribute it
13  * and/or modify it under the terms of the GNU General
14  * Public License as published by the Free Software Foundation;
15  * either version 2, or (at your option)
16  * any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * ============================================================ */
24 
25 #ifndef DIGIKAM_ABSTRACT_MARKER_TILER_H
26 #define DIGIKAM_ABSTRACT_MARKER_TILER_H
27 
28 // Qt includes
29 
30 #include <QBitArray>
31 #include <QObject>
32 #include <QPoint>
33 
34 // Local includes
35 
36 #include "tileindex.h"
37 #include "geoifacetypes.h"
38 #include "digikam_export.h"
39 #include "geogroupstate.h"
40 
41 namespace Digikam
42 {
43 
44 class DIGIKAM_EXPORT AbstractMarkerTiler : public QObject
45 {
46     Q_OBJECT
47 
48 public:
49 
50     enum TilerFlag
51     {
52         FlagNull    = 0,
53         FlagMovable = 1
54     };
55 
Q_DECLARE_FLAGS(TilerFlags,TilerFlag)56     Q_DECLARE_FLAGS(TilerFlags, TilerFlag)
57 
58 public:
59 
60     class ClickInfo
61     {
62     public:
63 
64         TileIndex::List tileIndicesList;
65         QVariant        representativeIndex;
66         GeoGroupState   groupSelectionState;
67         GeoMouseModes   currentMouseMode;
68     };
69 
70 public:
71 
72     class Tile
73     {
74     public:
75 
76         explicit Tile();
77 
78         virtual ~Tile();
79 
80         Tile* getChild(const int linearIndex);
81 
82         Tile* addChild(const int linearIndex, Tile* tilePointer);
83 
84         /**
85          * @brief Sets the pointer to a child tile to zero and deletes the child.
86          */
87         void deleteChild(Tile* const childTile, const int knownLinearIndex = -1);
88 
89         bool childrenEmpty() const;
90 
91         /**
92          * @brief returns the next non empty child index or -1.
93          */
94         int nextNonEmptyIndex(int linearIndex) const;
95 
96 
97     private:
98 
99         static int maxChildCount();
100 
101         void prepareForChildren();
102 
103     private:
104 
105         QVector<Tile*> children;
106         QVector<int> nonEmptyIndices;
107     };
108 
109 public:
110 
111     class NonEmptyIterator
112     {
113     public:
114 
115         NonEmptyIterator(AbstractMarkerTiler* const model, const int level);
116         NonEmptyIterator(AbstractMarkerTiler* const model, const int level, const TileIndex& startIndex, const TileIndex& endIndex);
117         NonEmptyIterator(AbstractMarkerTiler* const model, const int level, const GeoCoordinates::PairList& normalizedMapBounds);
118         ~NonEmptyIterator();
119 
120         bool                 atEnd()        const;
121         TileIndex            nextIndex();
122         TileIndex            currentIndex() const;
123         AbstractMarkerTiler* model()        const;
124 
125     private:
126 
127         bool initializeNextBounds();
128 
129     private:
130 
131         // Disable
132         NonEmptyIterator(const NonEmptyIterator&)            = delete;
133         NonEmptyIterator& operator=(const NonEmptyIterator&) = delete;
134 
135     private:
136 
137         class Private;
138         Private* const d;
139     };
140 
141 public:
142 
143     explicit AbstractMarkerTiler(QObject* const parent = nullptr);
144     ~AbstractMarkerTiler() override;
145 
146     /// these have to be implemented
147     virtual TilerFlags tilerFlags() const;
148     virtual Tile* tileNew()                                                                                 = 0;
149     virtual void prepareTiles(const GeoCoordinates& upperLeft, const GeoCoordinates& lowerRight, int level) = 0;
150     virtual void regenerateTiles()                                                                          = 0;
151     virtual Tile* getTile(const TileIndex& tileIndex, const bool stopIfEmpty)                               = 0;
152     virtual int getTileMarkerCount(const TileIndex& tileIndex)                                              = 0;
153     virtual int getTileSelectedCount(const TileIndex& tileIndex)                                            = 0;
154 
155     /// these should be implemented for thumbnail handling
156     virtual QVariant getTileRepresentativeMarker(const TileIndex& tileIndex, const int sortKey)             = 0;
157     virtual QVariant bestRepresentativeIndexFromList(const QList<QVariant>& indices, const int sortKey)     = 0;
158     virtual QPixmap pixmapFromRepresentativeIndex(const QVariant& index, const QSize& size)                 = 0;
159     virtual bool indicesEqual(const QVariant& a, const QVariant& b) const                                   = 0;
160     virtual GeoGroupState getTileGroupState(const TileIndex& tileIndex)                                     = 0;
161     virtual GeoGroupState getGlobalGroupState()                                                             = 0;
162 
163     /// these can be implemented if you want to react to actions in geolocation interface
164     virtual void onIndicesClicked(const ClickInfo& clickInfo);
165     virtual void onIndicesMoved(const TileIndex::List& tileIndicesList, const GeoCoordinates& targetCoordinates,
166                                 const QPersistentModelIndex& targetSnapIndex);
167 
168     virtual void setActive(const bool state)                                                                = 0;
169     Tile* rootTile();
170     bool indicesEqual(const QIntList& a, const QIntList& b, const int upToLevel) const;
171     bool isDirty() const;
172     void setDirty(const bool state = true);
173     void resetRootTile();
174 
175 Q_SIGNALS:
176 
177     void signalTilesOrSelectionChanged();
178     void signalThumbnailAvailableForIndex(const QVariant& index, const QPixmap& pixmap);
179 
180 private:
181 
182     class Private;
183     Private* const d;
184 };
185 
186 } // namespace Digikam
187 
188 Q_DECLARE_OPERATORS_FOR_FLAGS(Digikam::AbstractMarkerTiler::TilerFlags)
189 
190 #endif // DIGIKAM_ABSTRACT_MARKER_TILER_H
191