File indexing completed on 2024-05-05 04:22:10

0001 // SPDX-FileCopyrightText: 2016-2021 Johannes Zarl-Zierl <johannes@zarl-zierl.at>
0002 // SPDX-FileCopyrightText: 2014-2022 Tobias Leupold <tl at stonemx dot de>
0003 //
0004 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 
0006 #ifndef MAPVIEW_H
0007 #define MAPVIEW_H
0008 
0009 #include "GeoCoordinates.h"
0010 #include "enums.h"
0011 
0012 #include <DB/ImageInfo.h>
0013 #include <DB/ImageInfoPtr.h>
0014 #include <kpabase/config-kpa-marble.h>
0015 
0016 #include <QList>
0017 #include <QPixmap>
0018 #include <QWidget>
0019 #include <marble/GeoDataLatLonAltBox.h>
0020 #include <marble/LayerInterface.h>
0021 
0022 namespace DB
0023 {
0024 class ImageSearchInfo;
0025 }
0026 namespace Marble
0027 {
0028 class MarbleWidget;
0029 }
0030 
0031 class QLabel;
0032 class QPushButton;
0033 
0034 namespace Map
0035 {
0036 class GeoBin;
0037 class GeoCluster;
0038 
0039 /**
0040  * UsageType: determines whether the widget is used as a standalone widget
0041  * or within another widget (e.g. the AnnotationDialog).
0042  * @see Viewer::ViewerWidget::UsageType
0043  */
0044 enum class UsageType {
0045     InlineMapView,
0046     MapViewWindow
0047 };
0048 
0049 /**
0050  * MapStatus: determines the visibility and text of the status label and the visibility of the
0051  * map, depending on the availability of coordinates of the image(s) that are displayed.
0052  */
0053 enum class MapStatus {
0054     Loading,
0055     ImageHasCoordinates,
0056     ImageHasNoCoordinates,
0057     NoImagesHaveNoCoordinates,
0058     SomeImagesHaveNoCoordinates,
0059     SearchCoordinates
0060 };
0061 
0062 /**
0063  * \brief A conveniently 64bit word-sized type that holds an imprecise representation of a GeoCoordinate.
0064  * 64 bit allow for enough precision to represent the lat/lon part of the GeoCoordinate of a GeoBin,
0065  * while also having nice properties for being used as a key to a hashmap lookup.
0066  */
0067 using GeoBinAddress = quint64;
0068 
0069 class MapView
0070     : public QWidget,
0071       public Marble::LayerInterface
0072 {
0073     Q_OBJECT
0074 
0075 public:
0076     explicit MapView(QWidget *parent, UsageType type);
0077     ~MapView() override = default;
0078 
0079     /**
0080      * Removes all images from the map.
0081      */
0082     void clear();
0083 
0084     /**
0085      * Add an image to the map.
0086      * If you fill the Map using this method, don't forget to call buildImageClusters() afterwards.
0087      * @return \c true, if the image has coordinates and was added, \c false otherwise.
0088      */
0089     bool addImage(DB::ImageInfoPtr image);
0090 
0091     /**
0092      * @brief addImages adds images matching a search info to the map.
0093      * @param searchInfo
0094      */
0095     void addImages(const DB::ImageSearchInfo &searchInfo);
0096 
0097     /**
0098      * @brief buildImageClusters creates the GeoClusters that are used to group images that are close to each other.
0099      * This function is automatically called by addImages(),
0100      * but you need to call it yourself when adding individual images using addImage().
0101      */
0102     void buildImageClusters();
0103     /**
0104      * Sets the map's zoom so that all images on the map are visible.
0105      * If no images have been added, the zoom is not altered.
0106      */
0107     void zoomToMarkers();
0108 
0109     /**
0110      * Sets the state of the "Show Thumbnails" button on the map's control widget.
0111      */
0112     void setShowThumbnails(bool state);
0113     /**
0114      * @brief Sets the state of the "Group Thumbnails" button on lthe map's control widget.
0115      */
0116     void setGroupThumbnails(bool state);
0117 
0118     /**
0119      * @brief Returns the appropriate map style depending on the state of the "Show Thumbnails" and "Group Thumbnails" buttons.
0120      * @return the currently active MapStyle
0121      */
0122     MapStyle mapStyle() const;
0123 
0124     /**
0125      * This sets the status label text and it's visibility, as well as the visibilty of the map
0126      * itself to the state indicated by the given MapStatus.
0127      */
0128     void displayStatus(MapStatus status);
0129 
0130     GeoCoordinates::LatLonBox getRegionSelection() const;
0131     bool regionSelected() const;
0132 
0133     void mousePressEvent(QMouseEvent *event) override;
0134     void mouseReleaseEvent(QMouseEvent *event) override;
0135     void mouseMoveEvent(QMouseEvent *event) override;
0136     void keyPressEvent(QKeyEvent *event) override;
0137 
0138     // LayerInterface:
0139     /**
0140      * @brief renderPosition tells the LayerManager what layers we (currently) want to paint on.
0141      * Part of the LayerInterface; called by the LayerManager.
0142      * @return
0143      */
0144     QStringList renderPosition() const override;
0145     /**
0146      * @brief Render all markers onto the marbleWidget.
0147      * Part of the LayerInterface; called by the LayerManager.
0148      * @param painter the painter used by the LayerManager
0149      * @param viewPortParams information about the region being in view
0150      * @param renderPos the layer name
0151      * @return \c true (return value is discarded by LayerManager::renderLayers())
0152      */
0153     bool render(Marble::GeoPainter *painter, Marble::ViewportParams *viewPortParams,
0154                 const QString &renderPos, Marble::GeoSceneLayer * /*nullptr*/) override;
0155 
0156     /**
0157      * @return The size of the rendered thumbnails/markers in pixels.
0158      */
0159     int markerSize() const;
0160     /**
0161      * @brief Set the markerSize for rendering on the map
0162      * Note: Apart from thumbnails, this also affects the size of clusters and therefore the clustering.
0163      * @param markerSizePx a size in pixels
0164      */
0165     void setMarkerSize(int markerSizePx);
0166 
0167 Q_SIGNALS:
0168     void newRegionSelected(Map::GeoCoordinates::LatLonBox coordinates);
0169     void displayStatusChanged(MapStatus);
0170 
0171 public Q_SLOTS:
0172     /**
0173      * Centers the map on the coordinates of the given image.
0174      */
0175     void setCenter(const DB::ImageInfoPtr image);
0176 
0177     void increaseMarkerSize();
0178     void decreaseMarkerSize();
0179 
0180 private Q_SLOTS:
0181     void saveSettings();
0182     void setLastCenter();
0183     void updateRegionSelection(const Marble::GeoDataLatLonBox &selection);
0184 #ifndef MARBLE_HAS_regionSelected_NEW
0185     // remove once we don't care about Marble v17.12.3 and older anymore
0186     void updateRegionSelectionOld(const QList<double> &selection);
0187 #endif
0188 
0189 private: // Variables
0190     Marble::MarbleWidget *m_mapWidget;
0191     QLabel *m_statusLabel;
0192     QPushButton *m_setLastCenterButton;
0193     GeoCoordinates m_lastCenter;
0194     QWidget *m_kpaButtons;
0195     QWidget *m_floaters;
0196     /**
0197      * If the user clicks a cluster on the map, it gets preselected (and highlighted) before the mouse release event finalizes the selection.
0198      * @see mousePressEvent
0199      * @see mouseReleaseEvent
0200      * @see render
0201      */
0202     const GeoCluster *m_preselectedCluster = nullptr;
0203 
0204     // filled by addImage()
0205     QHash<GeoBinAddress, GeoBin *> m_baseBins;
0206     QList<GeoCluster *> m_geoClusters;
0207 
0208     Marble::GeoDataLatLonBox m_markersBox;
0209     bool m_showThumbnails = true;
0210     bool m_groupThumbnails = true;
0211     QPixmap m_pin;
0212     Marble::GeoDataLatLonBox m_regionSelection;
0213     bool m_regionSelected = false;
0214     int m_markerSize;
0215 };
0216 
0217 }
0218 
0219 #endif // MAPVIEW_H
0220 
0221 // vi:expandtab:tabstop=4 shiftwidth=4: