File indexing completed on 2025-01-05 03:59:19
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <tackat@kde.org> 0004 // SPDX-FileCopyrightText: 2007 Inge Wallin <ingwa@kde.org> 0005 // 0006 0007 #include <QApplication> 0008 #include <QPainter> 0009 #include <QPainterPath> 0010 #include <QPalette> 0011 #include <QPixmapCache> 0012 0013 #include "VisiblePlacemark.h" 0014 #include "RemoteIconLoader.h" 0015 #include "GeoDataPlacemark.h" 0016 #include "GeoDataStyle.h" 0017 #include "GeoDataIconStyle.h" 0018 #include "GeoDataLabelStyle.h" 0019 #include "PlacemarkLayer.h" 0020 0021 #include "digikam_debug.h" 0022 0023 using namespace Marble; 0024 0025 VisiblePlacemark::VisiblePlacemark( const GeoDataPlacemark *placemark, const GeoDataCoordinates &coordinates, const GeoDataStyle::ConstPtr &style ) 0026 : m_placemark( placemark ), 0027 m_selected( false ), 0028 m_labelDirty(true), 0029 m_style(style), 0030 m_coordinates(coordinates) 0031 { 0032 const RemoteIconLoader *remoteLoader = style->iconStyle().remoteIconLoader(); 0033 QObject::connect( remoteLoader, SIGNAL(iconReady()), 0034 this, SLOT(setSymbolPixmap()) ); 0035 0036 setSymbolPixmap(); 0037 } 0038 0039 const GeoDataPlacemark* VisiblePlacemark::placemark() const 0040 { 0041 return m_placemark; 0042 } 0043 0044 const QPixmap& VisiblePlacemark::symbolPixmap() const 0045 { 0046 if (!m_symbolId.isEmpty() && m_symbolPixmap.isNull()) { 0047 if ( !QPixmapCache::find( m_symbolId, &m_symbolPixmap ) ) { 0048 m_symbolPixmap = QPixmap::fromImage(m_style->iconStyle().scaledIcon()); 0049 QPixmapCache::insert( m_symbolId, m_symbolPixmap); 0050 } 0051 } 0052 return m_symbolPixmap; 0053 } 0054 0055 const QString& VisiblePlacemark::symbolId() const 0056 { 0057 return m_symbolId; 0058 } 0059 0060 bool VisiblePlacemark::selected() const 0061 { 0062 return m_selected; 0063 } 0064 0065 void VisiblePlacemark::setSelected( bool selected ) 0066 { 0067 if (selected != m_selected) { 0068 m_selected = selected; 0069 m_labelDirty = true; 0070 } 0071 } 0072 0073 const QPointF& VisiblePlacemark::symbolPosition() const 0074 { 0075 return m_symbolPosition; 0076 } 0077 0078 const QPointF VisiblePlacemark::hotSpot() const 0079 { 0080 const QSize iconSize = m_style->iconStyle().scaledIcon().size(); 0081 0082 GeoDataHotSpot::Units xunits; 0083 GeoDataHotSpot::Units yunits; 0084 QPointF pixelHotSpot = m_style->iconStyle().hotSpot( xunits, yunits ); 0085 0086 switch ( xunits ) { 0087 case GeoDataHotSpot::Fraction: 0088 pixelHotSpot.setX( iconSize.width() * pixelHotSpot.x() ); 0089 break; 0090 case GeoDataHotSpot::Pixels: 0091 /* nothing to do */ 0092 break; 0093 case GeoDataHotSpot::InsetPixels: 0094 pixelHotSpot.setX( iconSize.width() - pixelHotSpot.x() ); 0095 break; 0096 } 0097 0098 switch ( yunits ) { 0099 case GeoDataHotSpot::Fraction: 0100 pixelHotSpot.setY( iconSize.height() * ( 1.0 - pixelHotSpot.y() ) ); 0101 break; 0102 case GeoDataHotSpot::Pixels: 0103 /* nothing to do */ 0104 break; 0105 case GeoDataHotSpot::InsetPixels: 0106 pixelHotSpot.setY( iconSize.height() - pixelHotSpot.y() ); 0107 break; 0108 } 0109 0110 return pixelHotSpot; 0111 } 0112 0113 void VisiblePlacemark::setSymbolPosition( const QPointF& position ) 0114 { 0115 m_symbolPosition = position; 0116 } 0117 0118 const QPixmap& VisiblePlacemark::labelPixmap() 0119 { 0120 if (m_labelDirty) { 0121 drawLabelPixmap(); 0122 } 0123 0124 return m_labelPixmap; 0125 } 0126 0127 void VisiblePlacemark::setSymbolPixmap() 0128 { 0129 if (m_style) { 0130 m_symbolId = m_style->iconStyle().iconPath() + QString::number(m_style->iconStyle().scale()); 0131 if (m_style->iconStyle().iconPath().isEmpty()) { 0132 m_symbolId.clear(); 0133 m_symbolPixmap = QPixmap::fromImage(m_style->iconStyle().scaledIcon()); 0134 } 0135 Q_EMIT updateNeeded(); 0136 } 0137 else { 0138 qCDebug(DIGIKAM_MARBLE_LOG) << "Style pointer is Null"; 0139 } 0140 } 0141 0142 const QRectF& VisiblePlacemark::labelRect() const 0143 { 0144 return m_labelRect; 0145 } 0146 0147 void VisiblePlacemark::setLabelRect( const QRectF& labelRect ) 0148 { 0149 m_labelRect = labelRect; 0150 } 0151 0152 void VisiblePlacemark::setStyle(const GeoDataStyle::ConstPtr &style) 0153 { 0154 m_style = style; 0155 m_labelDirty = true; 0156 setSymbolPixmap(); 0157 } 0158 0159 GeoDataStyle::ConstPtr VisiblePlacemark::style() const 0160 { 0161 return m_style; 0162 } 0163 0164 QRectF VisiblePlacemark::symbolRect() const 0165 { 0166 return QRectF(m_symbolPosition, m_symbolPixmap.size()); 0167 } 0168 0169 QRectF VisiblePlacemark::boundingBox() const 0170 { 0171 return m_labelRect.isEmpty() ? symbolRect() : m_labelRect.united(symbolRect()); 0172 } 0173 0174 const GeoDataCoordinates &VisiblePlacemark::coordinates() const 0175 { 0176 return m_coordinates; 0177 } 0178 0179 void VisiblePlacemark::drawLabelPixmap() 0180 { 0181 m_labelDirty = false; 0182 QString labelName = m_placemark->displayName(); 0183 if ( labelName.isEmpty() || m_style->labelStyle().color() == QColor(Qt::transparent) ) { 0184 m_labelPixmap = QPixmap(); 0185 return; 0186 } 0187 0188 QFont labelFont = m_style->labelStyle().scaledFont(); 0189 QColor labelColor = m_style->labelStyle().color(); 0190 0191 LabelStyle labelStyle = Normal; 0192 if ( m_selected ) { 0193 labelStyle = Selected; 0194 } else if ( m_style->labelStyle().glow() ) { 0195 labelStyle = Glow; 0196 } 0197 0198 int textHeight = QFontMetrics( labelFont ).height(); 0199 0200 int textWidth; 0201 if ( m_style->labelStyle().glow() ) { 0202 labelFont.setWeight( QFont::Bold ); // Needed to calculate the correct pixmap size; 0203 textWidth = ( QFontMetrics( labelFont ).horizontalAdvance( labelName ) 0204 + qRound( 2 * s_labelOutlineWidth ) ); 0205 } else { 0206 textWidth = ( QFontMetrics( labelFont ).horizontalAdvance( labelName ) ); 0207 } 0208 0209 m_labelPixmap = QPixmap( QSize( textWidth, textHeight ) ); 0210 m_labelPixmap.fill( Qt::transparent ); 0211 0212 QPainter labelPainter( &m_labelPixmap ); 0213 0214 drawLabelText( labelPainter, labelName, labelFont, labelStyle, labelColor ); 0215 } 0216 0217 void VisiblePlacemark::drawLabelText(QPainter &labelPainter, const QString &text, 0218 const QFont &labelFont, LabelStyle labelStyle, const QColor &color ) 0219 { 0220 QFont font = labelFont; 0221 QFontMetrics metrics = QFontMetrics( font ); 0222 int fontAscent = metrics.ascent(); 0223 0224 switch ( labelStyle ) { 0225 case Selected: { 0226 labelPainter.setPen( color ); 0227 labelPainter.setFont( font ); 0228 QRect textRect( 0, 0, metrics.horizontalAdvance( text ), metrics.height() ); 0229 labelPainter.fillRect( textRect, QApplication::palette().highlight() ); 0230 labelPainter.setPen( QPen( QApplication::palette().highlightedText(), 1 ) ); 0231 labelPainter.drawText( 0, fontAscent, text ); 0232 break; 0233 } 0234 case Glow: { 0235 font.setWeight( QFont::Bold ); 0236 fontAscent = QFontMetrics( font ).ascent(); 0237 0238 QPen outlinepen( (color.red() + color.green() + color.blue())/3 < 160 ? Qt::white : Qt::black); 0239 outlinepen.setWidthF( s_labelOutlineWidth ); 0240 QBrush outlinebrush( color ); 0241 0242 QPainterPath outlinepath; 0243 0244 const QPointF baseline( s_labelOutlineWidth / 2.0, fontAscent ); 0245 outlinepath.addText( baseline, font, text ); 0246 labelPainter.setRenderHint( QPainter::Antialiasing, true ); 0247 labelPainter.setPen( outlinepen ); 0248 labelPainter.setBrush( outlinebrush ); 0249 labelPainter.drawPath( outlinepath ); 0250 labelPainter.setPen( Qt::NoPen ); 0251 labelPainter.drawPath( outlinepath ); 0252 labelPainter.setRenderHint( QPainter::Antialiasing, false ); 0253 break; 0254 } 0255 default: { 0256 labelPainter.setPen( color ); 0257 labelPainter.setFont( font ); 0258 labelPainter.drawText( 0, fontAscent, text ); 0259 } 0260 } 0261 } 0262 0263 #include "moc_VisiblePlacemark.cpp"