File indexing completed on 2025-01-05 03:58:36
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2009-12-01 0007 * Description : world map widget library 0008 * 0009 * SPDX-FileCopyrightText: 2010-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2009-2011 by Michael G. Hansen <mike at mghansen dot de> 0011 * SPDX-FileCopyrightText: 2014 by Justus Schwartz <justus at gmx dot li> 0012 * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * 0015 * ============================================================ */ 0016 0017 #ifndef DIGIKAM_MAP_WIDGET_H 0018 #define DIGIKAM_MAP_WIDGET_H 0019 0020 // Qt includes 0021 0022 #include <QWidget> 0023 #include <QList> 0024 #include <QStringList> 0025 0026 // Local includes 0027 0028 #include "digikam_export.h" 0029 #include "digikam_config.h" 0030 #include "geoifacetypes.h" 0031 #include "geocoordinates.h" 0032 #include "geogroupstate.h" 0033 0034 class QAction; 0035 class QDragEnterEvent; 0036 class QDropEvent; 0037 class QMenu; 0038 0039 class KConfigGroup; 0040 0041 namespace Digikam 0042 { 0043 0044 class GeoIfaceSharedData; 0045 class GeoModelHelper; 0046 class GeoDragDropHandler; 0047 class AbstractMarkerTiler; 0048 class TrackManager; 0049 class MapBackend; 0050 0051 /** 0052 * @class MapWidget 0053 * @brief The central map view class of geolocation interface 0054 * 0055 * The MapWidget class is the central widget of geolocation interface. It provides a widget which can display maps using 0056 * either the Marble or Google Maps backend. Using a model, items can be displayed on the map. For 0057 * models containing only a small number of items, the items can be shown directly, but for models with 0058 * a larger number of items, the items can also be grouped. Currently, any number of ungrouped models 0059 * can be shown, but only one grouped model. Item selection models can also be used along with the models, 0060 * to interact with the selection states of the items on the map. In order to use a model with geolocation interface, however, 0061 * a model helper has to be implemented, which extracts data from the model that is not provided by the Qt part 0062 * of a model's API. 0063 * 0064 * Now, a brief introduction on how to get geolocation interface working is provided: 0065 * @li First, an instance of @c MapWidget has to be created. 0066 * @li Next, @c GeoModelHelper has to be subclassed and at least the pure virtual functions have to be implemented. 0067 * @li To show the model's data ungrouped, the model helper has to be added to @c MapWidget instance using addUngroupedModel. 0068 * @li To show the model's data grouped, an instance of @c AbstractMarkerTiler has to be created and the model helper has to be 0069 * set to it using setMarkerGeoModelHelper. The @c AbstractMarkerTiler has then to be given to MapWidget using setGroupedModel. If 0070 * the items to be displayed do not reside in a model, a subclass of @c AbstractMarkerTiler can be created which returns 0071 * just the number of items in a particular area, and picks representative items for thumbnails. 0072 * @li To handle dropping of items from the host applications UI onto the map, @c DragDropHandler has to be subclassed 0073 * as well and added to the model using setDragDropHandler. 0074 * @li Finally, setActive() has to be called to tell the widget that it should start displaying things. 0075 */ 0076 0077 class DIGIKAM_EXPORT MapWidget : public QWidget 0078 { 0079 Q_OBJECT 0080 0081 public: 0082 0083 explicit MapWidget(QWidget* const parent = nullptr); 0084 ~MapWidget() override; 0085 0086 // -------------------------------------------------- 0087 0088 /// @name Settings Management related functions 0089 //@{ 0090 0091 public: 0092 0093 void saveSettingsToGroup(KConfigGroup* const group); 0094 void readSettingsFromGroup(const KConfigGroup* const group); 0095 0096 protected Q_SLOTS: 0097 0098 void slotItemDisplaySettingsChanged(); 0099 0100 private Q_SLOTS: 0101 0102 void slotApplySettings(); 0103 //@} 0104 0105 // -------------------------------------------------- 0106 0107 /// @name Map related functions 0108 //@{ 0109 0110 public: 0111 0112 QStringList availableBackends() const; 0113 bool setBackend(const QString& backendName); 0114 0115 QList<MapBackend*> backends() const; 0116 0117 GeoCoordinates getCenter() const; 0118 void setCenter(const GeoCoordinates& coordinate); 0119 0120 void setZoom(const QString& newZoom); 0121 QString getZoom(); 0122 0123 /** 0124 * @brief Adjusts the visible map area such that all grouped markers are visible. 0125 * 0126 * Note that a call to this function currently has no effect if the widget has been 0127 * set inactive via setActive() or the backend is not yet ready. 0128 * 0129 * @param useSaneZoomLevel Stop zooming at a sane level, if markers are too close together. 0130 */ 0131 void adjustBoundariesToGroupedMarkers(const bool useSaneZoomLevel = true); 0132 void refreshMap(); 0133 0134 void setRegionSelection(const GeoCoordinates::Pair& region); 0135 GeoCoordinates::Pair getRegionSelection(); 0136 void clearRegionSelection(); 0137 0138 void updateMarkers(); 0139 void updateClusters(); 0140 void markClustersAsDirty(); 0141 0142 QPixmap getDecoratedPixmapForCluster(const int clusterId, const GeoGroupState* const selectedStateOverride, 0143 const int* const countOverride, QPoint* const centerPoint); 0144 QVariant getClusterRepresentativeMarker(const int clusterIndex, const int sortKey); 0145 0146 protected: 0147 0148 bool currentBackendReady() const; 0149 void applyCacheToBackend(); 0150 void saveBackendToCache(); 0151 void setShowPlaceholderWidget(const bool state); 0152 0153 /** 0154 * @brief Set @p widgetForFrame as the widget in the frame, but does not show it. 0155 */ 0156 void setMapWidgetInFrame(QWidget* const widgetForFrame); 0157 0158 void removeMapWidgetFromFrame(); 0159 0160 public Q_SLOTS: 0161 0162 void slotClustersNeedUpdating(); 0163 0164 protected Q_SLOTS: 0165 0166 void slotBackendReadyChanged(const QString& backendName); 0167 void slotChangeBackend(QAction* action); 0168 void slotBackendZoomChanged(const QString& newZoom); 0169 void slotClustersMoved(const QIntList& clusterIndices, const QPair<int, QModelIndex>& snapTarget); 0170 void slotClustersClicked(const QIntList& clusterIndices); 0171 0172 /** 0173 * @brief Helper function to buffer reclustering 0174 */ 0175 void slotLazyReclusteringRequestCallBack(); 0176 0177 /** 0178 * @brief Request reclustering, repeated calls should generate only one actual update of the clusters 0179 */ 0180 void slotRequestLazyReclustering(); 0181 0182 void slotRemoveCurrentRegionSelection(); 0183 void slotNewSelectionFromMap(const Digikam::GeoCoordinates::Pair& sel); 0184 0185 Q_SIGNALS: 0186 0187 void signalRegionSelectionChanged(); 0188 //@} 0189 0190 // -------------------------------------------------- 0191 0192 /// @name Data Management 0193 //@{ 0194 0195 public: 0196 0197 void addUngroupedModel(GeoModelHelper* const modelHelper); 0198 void removeUngroupedModel(GeoModelHelper* const modelHelper); 0199 void setGroupedModel(AbstractMarkerTiler* const markerModel); 0200 void setDragDropHandler(GeoDragDropHandler* const dragDropHandler); 0201 void setTrackManager(TrackManager* const trackManager); 0202 0203 protected Q_SLOTS: 0204 0205 void slotUngroupedModelChanged(); 0206 0207 Q_SIGNALS: 0208 0209 void signalLoadTracksFromAlbums(); 0210 void signalUngroupedModelChanged(const int index); 0211 //@} 0212 0213 // -------------------------------------------------- 0214 0215 /// @name UI setup 0216 //@{ 0217 0218 public: 0219 0220 QAction* getControlAction(const QString& actionName); 0221 0222 /** 0223 * @brief Returns the control widget instance. 0224 */ 0225 QWidget* getControlWidget(); 0226 0227 void addWidgetToControlWidget(QWidget* const newWidget); 0228 void setSortOptionsMenu(QMenu* const sortMenu); 0229 void setMouseMode(const GeoMouseModes mouseMode); 0230 void setAvailableMouseModes(const GeoMouseModes mouseModes); 0231 void setVisibleMouseModes(const GeoMouseModes mouseModes); 0232 void setAllowModifications(const bool state); 0233 void setActive(const bool state); 0234 bool getActiveState(); 0235 bool getStickyModeState() const; 0236 void setStickyModeState(const bool state); 0237 void setVisibleExtraActions(const GeoExtraActions actions); 0238 void setEnabledExtraActions(const GeoExtraActions actions); 0239 0240 public Q_SLOTS: 0241 0242 void slotUpdateActionsEnabled(); 0243 void slotStickyModeChanged(); 0244 0245 protected Q_SLOTS: 0246 0247 void slotMouseModeChanged(QAction* triggeredAction); 0248 0249 protected: 0250 0251 void rebuildConfigurationMenu(); 0252 void createActions(); 0253 void createActionsForBackendSelection(); 0254 0255 void dropEvent(QDropEvent* event) override; 0256 void dragMoveEvent(QDragMoveEvent* event) override; 0257 void dragEnterEvent(QDragEnterEvent* event) override; 0258 void dragLeaveEvent(QDragLeaveEvent* event) override; 0259 0260 Q_SIGNALS: 0261 0262 void signalMouseModeChanged(const Digikam::GeoMouseModes& currentMouseMode); 0263 //@} 0264 0265 // -------------------------------------------------- 0266 0267 /// @name Appearance 0268 //@{ 0269 0270 public: 0271 0272 void setSortKey(const int sortKey); 0273 void setThumnailSize(const int newThumbnailSize); 0274 void setThumbnailGroupingRadius(const int newGroupingRadius); 0275 void setMarkerGroupingRadius(const int newGroupingRadius); 0276 int getThumbnailSize() const; 0277 int getUndecoratedThumbnailSize() const; 0278 void setShowThumbnails(const bool state); 0279 0280 QString convertZoomToBackendZoom(const QString& someZoom, const QString& targetBackend) const; 0281 0282 /** 0283 * @brief Return color and style information for rendering the cluster 0284 * @param clusterIndex Index of the cluster 0285 * @param fillColor Color used to fill the circle 0286 * @param strokeColor Color used for the stroke around the circle 0287 * @param strokeStyle Style used to draw the stroke around the circle 0288 * @param labelText Text for the label 0289 * @param labelColor Color for the label text 0290 * @param overrideSelection Get the colors for a different selection state 0291 * @param overrideCount Get the colors for a different amount of markers 0292 */ 0293 void getColorInfos(const int clusterIndex, QColor* fillColor, QColor* strokeColor, 0294 Qt::PenStyle* strokeStyle, QString* labelText, QColor* labelColor, 0295 const GeoGroupState* const overrideSelection = nullptr, 0296 const int* const overrideCount = nullptr) const; 0297 0298 void getColorInfos(const GeoGroupState groupState, 0299 const int nMarkers, 0300 QColor* fillColor, QColor* strokeColor, 0301 Qt::PenStyle* strokeStyle, QString* labelText, QColor* labelColor) const; 0302 0303 public Q_SLOTS: 0304 0305 void slotZoomIn(); 0306 void slotZoomOut(); 0307 void slotDecreaseThumbnailSize(); 0308 void slotIncreaseThumbnailSize(); 0309 void stopThumbnailTimer(); 0310 0311 protected Q_SLOTS: 0312 0313 void slotShowThumbnailsChanged(); 0314 0315 Q_SIGNALS: 0316 0317 void signalRemoveCurrentFilter(); 0318 void signalStickyModeChanged(); 0319 //@} 0320 0321 // -------------------------------------------------- 0322 0323 private: 0324 0325 const QExplicitlySharedDataPointer<GeoIfaceSharedData> s; 0326 0327 class Private; 0328 Private* const d; 0329 0330 Q_DISABLE_COPY(MapWidget) 0331 }; 0332 0333 } // namespace Digikam 0334 0335 #endif // DIGIKAM_MAP_WIDGET_H