File indexing completed on 2024-05-05 03:49:49

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2012 Mohammed Nafees <nafees.technocool@gmail.com>
0004 // SPDX-FileCopyrightText: 2012 Dennis Nienhüser <nienhueser@kde.org>
0005 // SPDX-FileCopyrightText: 2012 Illya Kovalevskyy <illya.kovalevskyy@gmail.com>
0006 // SPDX-FileCopyrightText: 2015 Imran Tatriev <itatriev@gmail.com>
0007 //
0008 
0009 #include "PopupLayer.h"
0010 
0011 #include "GeoDataCoordinates.h"
0012 #include "GeoPainter.h"
0013 #include "MarbleWidget.h"
0014 #include "PopupItem.h"
0015 #include "ViewportParams.h"
0016 #include "RenderPlugin.h"
0017 #include "RenderState.h"
0018 
0019 #include <QSizeF>
0020 
0021 namespace Marble
0022 {
0023 
0024 class Q_DECL_HIDDEN PopupLayer::Private
0025 {
0026 public:
0027     Private( MarbleWidget *marbleWidget, PopupLayer *q );
0028 
0029     /**
0030      * @brief Sets size of the popup item, based on the requested size and viewport size
0031      * @param viewport required to compute the maximum dimensions
0032      */
0033     void setAppropriateSize( const ViewportParams *viewport );
0034 
0035     static QString filterEmptyShortDescription(const QString &description);
0036     void setupDialogSatellite( const GeoDataPlacemark *index );
0037     void setupDialogCity( const GeoDataPlacemark *index );
0038     void setupDialogNation( const GeoDataPlacemark *index );
0039     void setupDialogGeoPlaces( const GeoDataPlacemark *index );
0040     void setupDialogSkyPlaces( const GeoDataPlacemark *index );
0041 
0042     PopupItem *const m_popupItem;
0043     MarbleWidget *const m_widget;
0044     QSizeF m_requestedSize;
0045     bool m_hasCrosshairsPlugin;
0046     bool m_crosshairsVisible;
0047 };
0048 
0049 PopupLayer::Private::Private( MarbleWidget *marbleWidget, PopupLayer *q ) :
0050     m_popupItem( new PopupItem( q ) ),
0051     m_widget( marbleWidget ),
0052     m_hasCrosshairsPlugin( false ),
0053     m_crosshairsVisible( true )
0054 {
0055 }
0056 
0057 PopupLayer::PopupLayer( MarbleWidget *marbleWidget, QObject *parent ) :
0058     QObject( parent ),
0059     d( new Private( marbleWidget, this ) )
0060 {
0061     for (const RenderPlugin *renderPlugin: d->m_widget->renderPlugins()) {
0062         if (renderPlugin->nameId() == QLatin1String("crosshairs")) {
0063             d->m_hasCrosshairsPlugin = true;
0064             break;
0065         }
0066     }
0067 
0068     connect( d->m_popupItem, SIGNAL(repaintNeeded()), this, SIGNAL(repaintNeeded()) );
0069     connect( d->m_popupItem, SIGNAL(hide()), this, SLOT(hidePopupItem()) );
0070 }
0071 
0072 PopupLayer::~PopupLayer()
0073 {
0074     delete d;
0075 }
0076 
0077 QStringList PopupLayer::renderPosition() const
0078 {
0079     return QStringList(QStringLiteral("ALWAYS_ON_TOP"));
0080 }
0081 
0082 bool PopupLayer::render( GeoPainter *painter, ViewportParams *viewport,
0083                                 const QString&, GeoSceneLayer* )
0084 {
0085     if ( visible() ) {
0086         d->setAppropriateSize( viewport );
0087         d->m_popupItem->paintEvent( painter, viewport );
0088     }
0089 
0090     return true;
0091 }
0092 
0093 bool PopupLayer::eventFilter( QObject *object, QEvent *e )
0094 {
0095     return visible() && d->m_popupItem->eventFilter( object, e );
0096 }
0097 
0098 qreal PopupLayer::zValue() const
0099 {
0100     return 4711.23;
0101 }
0102 
0103 RenderState PopupLayer::renderState() const
0104 {
0105     return RenderState(QStringLiteral("Popup Window"));
0106 }
0107 
0108 bool PopupLayer::visible() const
0109 {
0110     return d->m_popupItem->visible();
0111 }
0112 
0113 void PopupLayer::setVisible( bool visible )
0114 {
0115     d->m_popupItem->setVisible( visible );
0116     if ( !visible ) {
0117         disconnect( d->m_popupItem, SIGNAL(repaintNeeded()), this, SIGNAL(repaintNeeded()) );
0118         d->m_popupItem->clearHistory();
0119         emit repaintNeeded();
0120     }
0121     else {
0122         connect( d->m_popupItem, SIGNAL(repaintNeeded()), this, SIGNAL(repaintNeeded()) );
0123     }
0124 }
0125 
0126 void PopupLayer::popup()
0127 {
0128     GeoDataCoordinates coords = d->m_popupItem->coordinate();
0129     ViewportParams viewport( d->m_widget->viewport()->projection(),
0130                              coords.longitude(), coords.latitude(), d->m_widget->viewport()->radius(),
0131                              d->m_widget->viewport()->size() );
0132     qreal sx, sy, lon, lat;
0133     viewport.screenCoordinates( coords, sx, sy );
0134     sx = viewport.radius() < viewport.width() ? 0.5 * (viewport.width() + viewport.radius()) : 0.75 * viewport.width();
0135     viewport.geoCoordinates( sx, sy, lon, lat, GeoDataCoordinates::Radian );
0136     coords.setLatitude( lat );
0137     coords.setLongitude( lon );
0138     d->m_widget->centerOn( coords, true );
0139 
0140     if( d->m_hasCrosshairsPlugin ) {
0141         d->m_crosshairsVisible = d->m_widget->showCrosshairs();
0142 
0143         if( d->m_crosshairsVisible ) {
0144             d->m_widget->setShowCrosshairs( false );
0145         }
0146     }
0147 
0148     setVisible( true );
0149 }
0150 
0151 void PopupLayer::setCoordinates( const GeoDataCoordinates &coordinates , Qt::Alignment alignment )
0152 {
0153     d->m_popupItem->setCoordinate( coordinates );
0154     d->m_popupItem->setAlignment( alignment );
0155 }
0156 
0157 void PopupLayer::setUrl( const QUrl &url )
0158 {
0159     d->m_popupItem->setUrl( url );
0160 }
0161 
0162 void PopupLayer::setContent( const QString &html, const QUrl &baseUrl )
0163 {
0164     d->m_popupItem->setContent( html, baseUrl );
0165 }
0166 
0167 void PopupLayer::setBackgroundColor(const QColor &color)
0168 {
0169     if(color.isValid()) {
0170         d->m_popupItem->setBackgroundColor(color);
0171     }
0172 }
0173 
0174 void PopupLayer::setTextColor(const QColor &color)
0175 {
0176     if(color.isValid()) {
0177         d->m_popupItem->setTextColor(color);
0178     }
0179 }
0180 
0181 void PopupLayer::setSize( const QSizeF &size )
0182 {
0183     d->m_requestedSize = size;
0184 }
0185 
0186 void PopupLayer::Private::setAppropriateSize( const ViewportParams *viewport )
0187 {
0188     qreal margin = 15.0;
0189 
0190     QSizeF maximumSize;
0191     maximumSize.setWidth( viewport->width() - margin );
0192     maximumSize.setHeight( viewport->height() - margin );
0193 
0194     QSizeF minimumSize( 100.0, 100.0 );
0195 
0196     m_popupItem->setSize( m_requestedSize.boundedTo( maximumSize ).expandedTo( minimumSize ) );
0197 }
0198 
0199 void PopupLayer::hidePopupItem()
0200 {
0201     if( d->m_hasCrosshairsPlugin && d->m_crosshairsVisible ) {
0202         d->m_widget->setShowCrosshairs( d->m_crosshairsVisible );
0203     }
0204 
0205     setVisible( false );
0206 }
0207 
0208 }
0209 
0210 #include "moc_PopupLayer.cpp"