File indexing completed on 2024-04-28 03:50:18
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <tackat@kde.org> 0004 // SPDX-FileCopyrightText: 2007-2008 Inge Wallin <ingwa@kde.org> 0005 // SPDX-FileCopyrightText: 2007-2008 Carlos Licea <carlos.licea@kdemail.net> 0006 // SPDX-FileCopyrightText: 2011 Michael Henning <mikehenning@eclipse.net> 0007 // SPDX-FileCopyrightText: 2011 Valery Kharitonov <kharvd@gmail.com> 0008 // SPDX-FileCopyrightText: 2012 Mohammed Nafees <nafees.technocool@gmail.com> 0009 // 0010 0011 #include "MeasureToolPlugin.h" 0012 #include "MeasureConfigDialog.h" 0013 0014 #include "GeoPainter.h" 0015 #include "GeoDataLinearRing.h" 0016 #include "MarbleColors.h" 0017 #include "MarbleDebug.h" 0018 #include "MarbleWidgetPopupMenu.h" 0019 #include "MarbleModel.h" 0020 #include "MarbleLocale.h" 0021 #include "ViewportParams.h" 0022 #include "Planet.h" 0023 0024 #include <QDialog> 0025 #include <QColor> 0026 #include <QTextDocument> 0027 #include <qmath.h> 0028 0029 namespace Marble 0030 { 0031 0032 MeasureToolPlugin::MeasureToolPlugin( const MarbleModel *marbleModel ) 0033 : RenderPlugin( marbleModel ), 0034 m_measureLineString( GeoDataLineString( Tessellate ) ), 0035 #ifdef Q_OS_MACX 0036 m_font_regular( QFont( QStringLiteral( "Sans Serif" ), 10, 50, false ) ), 0037 #else 0038 m_font_regular( QFont( QStringLiteral( "Sans Serif" ), 8, 50, false ) ), 0039 #endif 0040 m_fontascent(-1), 0041 m_pen( Qt::red ), 0042 m_addMeasurePointAction( nullptr ), 0043 m_removeLastMeasurePointAction( nullptr ), 0044 m_removeMeasurePointsAction( nullptr ), 0045 m_separator( nullptr ), 0046 m_marbleWidget( nullptr ), 0047 m_configDialog( nullptr ), 0048 m_showDistanceLabel( true ), 0049 m_showBearingLabel( true ), 0050 m_showBearingChangeLabel( true ), 0051 m_showPolygonArea(false), 0052 m_showCircularArea(true), 0053 m_showRadius(true), 0054 m_showPerimeter(true), 0055 m_showCircumference(true), 0056 m_totalDistance(0.0), 0057 m_polygonArea(0.0), 0058 m_circularArea(0.0), 0059 m_radius(0.0), 0060 m_perimeter(0.0), 0061 m_circumference(0.0), 0062 m_paintMode(Polygon) 0063 { 0064 m_pen.setWidthF( 2.0 ); 0065 } 0066 0067 QStringList MeasureToolPlugin::backendTypes() const 0068 { 0069 return QStringList(QStringLiteral("measuretool")); 0070 } 0071 0072 QString MeasureToolPlugin::renderPolicy() const 0073 { 0074 return QStringLiteral("ALWAYS"); 0075 } 0076 0077 QStringList MeasureToolPlugin::renderPosition() const 0078 { 0079 return QStringList(QStringLiteral("ATMOSPHERE")); 0080 } 0081 0082 QString MeasureToolPlugin::name() const 0083 { 0084 return tr( "Measure Tool" ); 0085 } 0086 0087 QString MeasureToolPlugin::guiString() const 0088 { 0089 return tr( "&Measure Tool" ); 0090 } 0091 0092 QString MeasureToolPlugin::nameId() const 0093 { 0094 return QStringLiteral("measure-tool"); 0095 } 0096 0097 QString MeasureToolPlugin::version() const 0098 { 0099 return QStringLiteral("1.0"); 0100 } 0101 0102 QString MeasureToolPlugin::description() const 0103 { 0104 return tr( "Measure distances between two or more points." ); 0105 } 0106 0107 QString MeasureToolPlugin::copyrightYears() const 0108 { 0109 return QStringLiteral("2006-2008, 2011"); 0110 } 0111 0112 QVector<PluginAuthor> MeasureToolPlugin::pluginAuthors() const 0113 { 0114 return QVector<PluginAuthor>() 0115 << PluginAuthor(QStringLiteral("Dennis Nienhüser"), QStringLiteral("nienhueser@kde.org")) 0116 << PluginAuthor(QStringLiteral("Torsten Rahn"), QStringLiteral("tackat@kde.org")) 0117 << PluginAuthor(QStringLiteral("Inge Wallin"), QStringLiteral("ingwa@kde.org")) 0118 << PluginAuthor(QStringLiteral("Carlos Licea"), QStringLiteral("carlos.licea@kdemail.net")) 0119 << PluginAuthor(QStringLiteral("Michael Henning"), QStringLiteral("mikehenning@eclipse.net")) 0120 << PluginAuthor(QStringLiteral("Valery Kharitonov"), QStringLiteral("kharvd@gmail.com")) 0121 << PluginAuthor(QStringLiteral("Mohammed Nafees"), QStringLiteral("nafees.technocool@gmail.com")) 0122 << PluginAuthor(QStringLiteral("Illya Kovalevskyy"), QStringLiteral("illya.kovalevskyy@gmail.com")); 0123 } 0124 0125 QIcon MeasureToolPlugin::icon () const 0126 { 0127 return QIcon(QStringLiteral(":/icons/measure.png")); 0128 } 0129 0130 void MeasureToolPlugin::initialize () 0131 { 0132 m_fontascent = QFontMetrics( m_font_regular ).ascent(); 0133 } 0134 0135 bool MeasureToolPlugin::isInitialized () const 0136 { 0137 return m_fontascent >= 0; 0138 } 0139 0140 QDialog *MeasureToolPlugin::configDialog() 0141 { 0142 if ( !m_configDialog ) { 0143 m_configDialog = new MeasureConfigDialog(m_configDialog); 0144 connect( m_configDialog, SIGNAL(accepted()), 0145 SLOT(writeSettings()) ); 0146 connect( m_configDialog, SIGNAL(applied()), 0147 this, SLOT(writeSettings()) ); 0148 } 0149 0150 m_configDialog->setShowDistanceLabels( m_showDistanceLabel ); 0151 m_configDialog->setShowBearingLabel( m_showBearingLabel ); 0152 m_configDialog->setShowBearingLabelChange( m_showBearingChangeLabel ); 0153 m_configDialog->setShowPolygonArea( m_showPolygonArea ); 0154 m_configDialog->setShowCircularArea( m_showCircularArea ); 0155 m_configDialog->setShowRadius( m_showRadius ); 0156 m_configDialog->setShowPerimeter( m_showPerimeter ); 0157 m_configDialog->setShowCircumference( m_showCircumference ); 0158 m_configDialog->setPaintMode( m_paintMode ); 0159 0160 return m_configDialog; 0161 } 0162 0163 QHash<QString,QVariant> MeasureToolPlugin::settings() const 0164 { 0165 QHash<QString, QVariant> settings = RenderPlugin::settings(); 0166 0167 settings.insert(QStringLiteral("showDistanceLabel"), m_showDistanceLabel); 0168 settings.insert(QStringLiteral("showBearingLabel"), m_showBearingLabel); 0169 settings.insert(QStringLiteral("showBearingChangeLabel"), m_showBearingChangeLabel); 0170 settings.insert(QStringLiteral("showPolygonArea"), m_showPolygonArea); 0171 settings.insert(QStringLiteral("showCircularArea"), m_showCircularArea); 0172 settings.insert(QStringLiteral("showRadius"), m_showRadius); 0173 settings.insert(QStringLiteral("showPerimeter"), m_showPerimeter); 0174 settings.insert(QStringLiteral("showCircumference"), m_showCircumference); 0175 settings.insert(QStringLiteral("paintMode"), (int)m_paintMode); 0176 0177 return settings; 0178 } 0179 0180 void MeasureToolPlugin::setSettings( const QHash<QString,QVariant> &settings ) 0181 { 0182 RenderPlugin::setSettings( settings ); 0183 0184 m_showDistanceLabel = settings.value(QStringLiteral("showDistanceLabel"), true).toBool(); 0185 m_showBearingLabel = settings.value(QStringLiteral("showBearingLabel"), true).toBool(); 0186 m_showBearingChangeLabel = settings.value(QStringLiteral("showBearingChangeLabel"), true).toBool(); 0187 m_showPolygonArea = settings.value(QStringLiteral("showPolygonArea"), false).toBool(); 0188 m_showCircularArea = settings.value(QStringLiteral("showCircularArea"), true).toBool(); 0189 m_showRadius = settings.value(QStringLiteral("showRadius"), true).toBool(); 0190 m_showPerimeter = settings.value(QStringLiteral("showPerimeter"), true).toBool(); 0191 m_showCircumference = settings.value(QStringLiteral("showCircumference"), true).toBool(); 0192 m_paintMode = (PaintMode)settings.value(QStringLiteral("paintMode"), 0).toInt(); 0193 } 0194 0195 void MeasureToolPlugin::writeSettings() 0196 { 0197 m_showDistanceLabel = m_configDialog->showDistanceLabels(); 0198 m_showBearingLabel = m_configDialog->showBearingLabel(); 0199 m_showBearingChangeLabel = m_configDialog->showBearingLabelChange(); 0200 m_showPolygonArea = m_configDialog->showPolygonArea(); 0201 m_showCircularArea = m_configDialog->showCircularArea(); 0202 m_showRadius = m_configDialog->showRadius(); 0203 m_showPerimeter = m_configDialog->showPerimeter(); 0204 m_showCircumference = m_configDialog->showCircumference(); 0205 m_paintMode = (PaintMode)m_configDialog->paintMode(); 0206 0207 if (m_paintMode == Circular) { 0208 if (m_measureLineString.size() < 2) { 0209 m_addMeasurePointAction->setEnabled(true); 0210 } else { 0211 m_addMeasurePointAction->setEnabled(false); 0212 while (m_measureLineString.size() > 2) 0213 m_measureLineString.remove(m_measureLineString.size()-1); 0214 } 0215 } else { 0216 m_addMeasurePointAction->setEnabled(true); 0217 } 0218 0219 emit settingsChanged( nameId() ); 0220 emit repaintNeeded(); 0221 } 0222 0223 bool MeasureToolPlugin::render( GeoPainter *painter, 0224 ViewportParams *viewport, 0225 const QString& renderPos, 0226 GeoSceneLayer * layer ) 0227 { 0228 Q_UNUSED(renderPos) 0229 Q_UNUSED(layer) 0230 0231 m_latLonAltBox = viewport->viewLatLonAltBox(); 0232 0233 // No way to paint anything if the list is empty. 0234 if ( m_measureLineString.isEmpty() ) 0235 return true; 0236 0237 painter->save(); 0238 0239 // Prepare for painting the measure line string and paint it. 0240 painter->setPen( m_pen ); 0241 0242 if ( m_showDistanceLabel || m_showBearingLabel || m_showBearingChangeLabel ) { 0243 drawSegments( painter ); 0244 } else { 0245 painter->drawPolyline( m_measureLineString ); 0246 } 0247 0248 // Paint the nodes of the paths. 0249 drawMeasurePoints( painter ); 0250 0251 m_totalDistance = m_measureLineString.length( marbleModel()->planet()->radius() ); 0252 0253 if ( m_measureLineString.size() > 1 ) 0254 drawInfobox(painter); 0255 0256 painter->restore(); 0257 0258 return true; 0259 } 0260 0261 void MeasureToolPlugin::drawSegments( GeoPainter* painter ) 0262 { 0263 for ( int segmentIndex = 0; segmentIndex < m_measureLineString.size() - 1; ++segmentIndex ) { 0264 GeoDataLineString segment( Tessellate ); 0265 segment << m_measureLineString[segmentIndex] ; 0266 segment << m_measureLineString[segmentIndex + 1]; 0267 0268 QPen shadowPen( Oxygen::aluminumGray5 ); 0269 shadowPen.setWidthF(4.0); 0270 painter->setPen( shadowPen ); 0271 painter->drawPolyline( segment ); 0272 0273 QString infoString; 0274 0275 if ( (m_paintMode == Polygon && m_showDistanceLabel) 0276 || (m_paintMode == Circular && m_showRadius) ) { 0277 const qreal segmentLength = segment.length( marbleModel()->planet()->radius() ); 0278 m_radius = segmentLength; 0279 0280 infoString = meterToPreferredUnit(segmentLength); 0281 } 0282 0283 if ( m_showBearingLabel && m_paintMode != Circular ) { 0284 GeoDataCoordinates coordinates = segment.first(); 0285 qreal bearing = coordinates.bearing( segment.last(), GeoDataCoordinates::Degree ); 0286 0287 if ( bearing < 0 ) { 0288 bearing += 360; 0289 } 0290 QString bearingString = QString::fromUtf8( "%1°" ).arg( bearing, 0, 'f', 2 ); 0291 if ( !infoString.isEmpty() ) { 0292 infoString += QLatin1Char('\n'); 0293 } 0294 infoString.append( bearingString ); 0295 } 0296 0297 if ( m_showBearingChangeLabel && segmentIndex != 0 ) { 0298 GeoDataCoordinates currentCoordinates = m_measureLineString[segmentIndex]; 0299 qreal currentBearing = currentCoordinates.bearing(m_measureLineString[segmentIndex+1]); 0300 qreal previousBearing = currentCoordinates.bearing( m_measureLineString[segmentIndex-1]); 0301 0302 GeoDataLinearRing ring; 0303 painter->setPen( Qt::NoPen ); 0304 painter->setBrush( QBrush ( QColor ( 127, 127, 127, 127 ) ) ); 0305 0306 if (currentBearing < previousBearing) currentBearing += 2 * M_PI; 0307 ring << currentCoordinates; 0308 0309 qreal angleLength = qAbs(m_latLonAltBox.north() - m_latLonAltBox.south()) / 20; 0310 0311 qreal iterBearing = previousBearing; 0312 while ( iterBearing < currentBearing ) { 0313 ring << currentCoordinates.moveByBearing( iterBearing, angleLength ); 0314 iterBearing += 0.1; 0315 } 0316 0317 ring << currentCoordinates.moveByBearing( currentBearing, angleLength ); 0318 0319 painter->drawPolygon( ring ); 0320 0321 qreal currentBearingChange = (currentBearing - previousBearing) * RAD2DEG; 0322 if (currentBearingChange < 0) currentBearingChange += 360; 0323 QString bearingChangedString = QString::fromUtf8( "%1°" ).arg( currentBearingChange, 0, 'f', 2 ); 0324 painter->setPen( Qt::black ); 0325 GeoDataCoordinates textPosition = ring.latLonAltBox().center(); 0326 qreal deltaEast = ring.latLonAltBox().east() - currentCoordinates.longitude(); 0327 qreal deltaWest = currentCoordinates.longitude() - ring.latLonAltBox().west(); 0328 if (deltaEast > deltaWest) { 0329 textPosition.setLongitude(currentCoordinates.longitude() + deltaEast / 2); 0330 } 0331 else { 0332 textPosition.setLongitude(currentCoordinates.longitude() - deltaWest); 0333 } 0334 painter->drawText(textPosition, bearingChangedString ); 0335 } 0336 0337 // Drawing ellipse around 1st point towards the 2nd 0338 if ( m_paintMode == Circular ) { 0339 GeoDataCoordinates currentCoordinates = m_measureLineString[segmentIndex]; 0340 0341 GeoDataLinearRing ring; 0342 0343 // planetRadius - planet radius 0344 // d - distance between points 0345 // S - area of the painted circle 0346 qreal planetRadius = marbleModel()->planet()->radius(); 0347 qreal d = m_measureLineString.length(1); 0348 m_circularArea = 2 * M_PI * planetRadius * planetRadius * (1 - qCos(d)); 0349 0350 qreal iterBearing = 0; 0351 while ( iterBearing < 2 * M_PI ) { 0352 ring << currentCoordinates.moveByBearing(iterBearing, d); 0353 iterBearing += 0.1; 0354 } 0355 0356 painter->setPen( Qt::NoPen ); 0357 painter->setBrush( QBrush ( QColor ( 127, 127, 127, 127 ) ) ); 0358 painter->drawPolygon(ring); 0359 0360 if ( m_showCircularArea ) { 0361 painter->setPen(Qt::white); 0362 GeoDataCoordinates textPosition = ring.latLonAltBox().center(); 0363 0364 QString areaText = tr("Area:\n%1").arg(meterToPreferredUnit(m_circularArea, true)); 0365 0366 QFontMetrics fontMetrics = painter->fontMetrics(); 0367 QRect boundingRect = fontMetrics.boundingRect(QRect(), Qt::AlignCenter, areaText); 0368 0369 painter->drawText(textPosition, 0370 areaText, 0371 -boundingRect.width()/2, -boundingRect.height()*1.5, 0372 boundingRect.width(), boundingRect.height(), 0373 QTextOption(Qt::AlignCenter)); 0374 } 0375 0376 if ( m_showCircumference ) { 0377 painter->setPen(Qt::white); 0378 GeoDataCoordinates textPosition = ring.latLonAltBox().center(); 0379 0380 m_circumference = 2 * M_PI * planetRadius * qSin(d); 0381 0382 QString circumferenceText = tr("Circumference:\n%1").arg(meterToPreferredUnit(m_circumference)); 0383 0384 QFontMetrics fontMetrics = painter->fontMetrics(); 0385 QRect boundingRect = fontMetrics.boundingRect(QRect(),Qt::AlignCenter, 0386 circumferenceText); 0387 0388 painter->drawText(textPosition, 0389 circumferenceText, 0390 -boundingRect.width()/2, boundingRect.height(), 0391 boundingRect.width(), boundingRect.height(), 0392 QTextOption(Qt::AlignCenter)); 0393 } 0394 } 0395 0396 if ( !infoString.isEmpty() ) { 0397 QPen linePen; 0398 0399 // have three alternating colors for the segments 0400 switch ( segmentIndex % 3 ) { 0401 case 0: 0402 linePen.setColor( Oxygen::brickRed4 ); 0403 break; 0404 case 1: 0405 linePen.setColor( Oxygen::forestGreen4 ); 0406 break; 0407 case 2: 0408 linePen.setColor( Oxygen::skyBlue4 ); 0409 break; 0410 } 0411 0412 linePen.setWidthF(2.0); 0413 painter->setPen( linePen ); 0414 painter->drawPolyline( segment, infoString, LineCenter ); 0415 } 0416 } 0417 0418 if (m_paintMode == Polygon && m_measureLineString.size() > 2) { 0419 GeoDataLinearRing measureRing(m_measureLineString); 0420 0421 if (m_showPolygonArea || m_showPerimeter) { 0422 painter->setPen( Qt::NoPen ); 0423 painter->setBrush( QBrush ( QColor ( 127, 127, 127, 127 ) ) ); 0424 painter->drawPolygon(measureRing); 0425 0426 QPen shadowPen( Oxygen::aluminumGray5 ); 0427 shadowPen.setStyle(Qt::DashLine); 0428 shadowPen.setWidthF(3.0); 0429 painter->setPen( shadowPen ); 0430 painter->drawPolyline(GeoDataLineString( Tessellate ) << m_measureLineString.first() 0431 << m_measureLineString.last()); 0432 } 0433 0434 if (m_showPolygonArea) { 0435 qreal theta1 = 0.0; 0436 qreal n = m_measureLineString.size(); 0437 0438 for (int segmentIndex = 1; segmentIndex < m_measureLineString.size()-1; segmentIndex++) { 0439 GeoDataCoordinates current = m_measureLineString[segmentIndex]; 0440 qreal prevBearing = current.bearing(m_measureLineString[segmentIndex-1]); 0441 qreal nextBearing = current.bearing(m_measureLineString[segmentIndex+1]); 0442 if (nextBearing < prevBearing) 0443 nextBearing += 2 * M_PI; 0444 0445 qreal angle = nextBearing - prevBearing; 0446 theta1 += angle; 0447 } 0448 0449 // Traversing first vertex 0450 GeoDataCoordinates current = m_measureLineString[0]; 0451 qreal prevBearing = current.bearing(m_measureLineString[n-1]); 0452 qreal nextBearing = current.bearing(m_measureLineString[1]); 0453 if (nextBearing < prevBearing) 0454 nextBearing += 2 * M_PI; 0455 qreal angle = nextBearing - prevBearing; 0456 theta1 += angle; 0457 0458 // And the last one 0459 current = m_measureLineString[n-1]; 0460 prevBearing = current.bearing(m_measureLineString[n-2]); 0461 nextBearing = current.bearing(m_measureLineString[0]); 0462 if (nextBearing < prevBearing) 0463 nextBearing += 2 * M_PI; 0464 angle = nextBearing - prevBearing; 0465 theta1 += angle; 0466 0467 qreal theta2 = 2 * M_PI * n - theta1; 0468 0469 // theta = smaller of theta1 and theta2 0470 qreal theta = (theta1 < theta2) ? theta1 : theta2; 0471 0472 qreal planetRadius = marbleModel()->planet()->radius(); 0473 qreal S = qAbs((theta - (n-2) * M_PI) * planetRadius * planetRadius); 0474 m_polygonArea = S; 0475 0476 painter->setPen(Qt::white); 0477 GeoDataCoordinates textPosition = measureRing.latLonAltBox().center(); 0478 0479 QString areaText = tr("Area:\n%1").arg(meterToPreferredUnit(S, true)); 0480 0481 QFontMetrics fontMetrics = painter->fontMetrics(); 0482 QRect boundingRect = fontMetrics.boundingRect(QRect(), Qt::AlignCenter, areaText); 0483 0484 painter->drawText(textPosition, 0485 areaText, 0486 -boundingRect.width()/2, -(boundingRect.height()+fontMetrics.height()*0.25), 0487 boundingRect.width(), boundingRect.height(), 0488 QTextOption(Qt::AlignCenter)); 0489 } 0490 0491 if (m_showPerimeter) { 0492 painter->setPen(Qt::white); 0493 GeoDataCoordinates textPosition = measureRing.latLonAltBox().center(); 0494 0495 qreal P = measureRing.length(marbleModel()->planet()->radius()); 0496 m_perimeter = P; 0497 QString perimeterText = tr("Perimeter:\n%1").arg(meterToPreferredUnit(P)); 0498 0499 QFontMetrics fontMetrics = painter->fontMetrics(); 0500 QRect boundingRect = fontMetrics.boundingRect(QRect(),Qt::AlignCenter, 0501 perimeterText); 0502 0503 painter->drawText(textPosition, 0504 perimeterText, 0505 -boundingRect.width()/2, 0, 0506 boundingRect.width(), boundingRect.height(), 0507 QTextOption(Qt::AlignCenter)); 0508 } 0509 } 0510 } 0511 0512 QString MeasureToolPlugin::meterToPreferredUnit(qreal meters, bool isSquare) 0513 { 0514 MarbleLocale *locale = MarbleGlobal::getInstance()->locale(); 0515 const MarbleLocale::MeasurementSystem measurementSystem = locale->measurementSystem(); 0516 MarbleLocale::MeasureUnit unit; 0517 qreal convertedMeters; 0518 if (isSquare) 0519 meters = qSqrt(meters); 0520 0521 locale->meterToTargetUnit(meters, measurementSystem, convertedMeters, unit); 0522 QString unitString = locale->unitAbbreviation(unit); 0523 0524 if (isSquare) { 0525 qreal k = convertedMeters/meters; 0526 convertedMeters *= k; 0527 convertedMeters *= meters; 0528 0529 unitString.append(QChar(0xB2)); 0530 } 0531 0532 return QString("%L1 %2").arg(convertedMeters, 8, 'f', 1, QLatin1Char(' ')) 0533 .arg(unitString); 0534 } 0535 0536 void MeasureToolPlugin::drawMeasurePoints( GeoPainter *painter ) 0537 { 0538 // Paint the marks. 0539 GeoDataLineString::const_iterator itpoint = m_measureLineString.constBegin(); 0540 GeoDataLineString::const_iterator const endpoint = m_measureLineString.constEnd(); 0541 if (m_mark.isNull()) { 0542 m_mark = QPixmap(QStringLiteral(":/mark.png")); 0543 } 0544 for (; itpoint != endpoint; ++itpoint ) 0545 { 0546 painter->drawPixmap( *itpoint, m_mark ); 0547 } 0548 } 0549 0550 void MeasureToolPlugin::drawInfobox( GeoPainter *painter ) const 0551 { 0552 QString boxContent; 0553 0554 if (m_paintMode == Polygon) { 0555 boxContent += QLatin1String("<strong>") + tr("Polygon Ruler") + QLatin1String(":</strong><br/>\n"); 0556 } else /* Circular */ { 0557 boxContent += QLatin1String("<strong>") + tr("Circle Ruler") + QLatin1String(":</strong><br/>\n"); 0558 } 0559 if (m_paintMode == Polygon) { 0560 boxContent += tr("Total Distance: %1<br/>\n").arg( meterToPreferredUnit(m_totalDistance) ); 0561 if (m_showPolygonArea) 0562 boxContent += tr("Area: %1<br/>\n").arg( meterToPreferredUnit(m_polygonArea, true) ); 0563 if (m_showPerimeter) 0564 boxContent += tr("Perimeter: %1<br/>\n").arg( meterToPreferredUnit(m_perimeter) ); 0565 } else /* Circular */ { 0566 if (m_showRadius) 0567 boxContent += tr("Radius: %1<br/>\n").arg( meterToPreferredUnit(m_radius) ); 0568 if (m_showCircumference) 0569 boxContent += tr("Circumference: %1<br/>\n").arg( meterToPreferredUnit(m_circumference) ); 0570 if (m_showCircularArea) 0571 boxContent += tr("Area: %1<br/>\n").arg( meterToPreferredUnit(m_circularArea, true) ); 0572 } 0573 0574 painter->setPen( QColor( Qt::black ) ); 0575 painter->setBrush( QColor( 192, 192, 192, 192 ) ); 0576 0577 QTextDocument doc; 0578 doc.setHtml(boxContent); 0579 doc.setDefaultFont(m_font_regular); 0580 doc.adjustSize(); 0581 QSizeF pageSize = doc.size(); 0582 0583 painter->drawRect( 10, 105, 10 + pageSize.width(), pageSize.height() ); 0584 QTransform transform; 0585 transform.translate(15, 110); 0586 painter->setTransform(transform); 0587 doc.drawContents(painter); 0588 painter->setTransform(QTransform()); 0589 } 0590 0591 0592 void MeasureToolPlugin::addMeasurePoint( qreal lon, qreal lat ) 0593 { 0594 m_measureLineString << GeoDataCoordinates( lon, lat ); 0595 0596 emit numberOfMeasurePointsChanged( m_measureLineString.size() ); 0597 } 0598 0599 void MeasureToolPlugin::removeLastMeasurePoint() 0600 { 0601 if (!m_measureLineString.isEmpty()) 0602 m_measureLineString.remove( m_measureLineString.size() - 1 ); 0603 0604 emit numberOfMeasurePointsChanged( m_measureLineString.size() ); 0605 } 0606 0607 void MeasureToolPlugin::removeMeasurePoints() 0608 { 0609 m_measureLineString.clear(); 0610 0611 emit numberOfMeasurePointsChanged( m_measureLineString.size() ); 0612 } 0613 0614 void MeasureToolPlugin::addContextItems() 0615 { 0616 MarbleWidgetPopupMenu *menu = m_marbleWidget->popupMenu(); 0617 0618 // Connect the inputHandler and the measure tool to the popup menu 0619 m_addMeasurePointAction = new QAction(QIcon(QStringLiteral(":/icons/measure.png")), tr("Add &Measure Point"), this); 0620 m_removeLastMeasurePointAction = new QAction( tr( "Remove &Last Measure Point" ), this ); 0621 m_removeLastMeasurePointAction->setEnabled( false ); 0622 m_removeMeasurePointsAction = new QAction( tr( "&Remove Measure Points" ), this ); 0623 m_removeMeasurePointsAction->setEnabled( false ); 0624 m_separator = new QAction( this ); 0625 m_separator->setSeparator( true ); 0626 0627 bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen; 0628 if ( !smallScreen ) { 0629 menu->addAction( Qt::RightButton, m_addMeasurePointAction ); 0630 menu->addAction( Qt::RightButton, m_removeLastMeasurePointAction ); 0631 menu->addAction( Qt::RightButton, m_removeMeasurePointsAction ); 0632 menu->addAction( Qt::RightButton, m_separator ); 0633 } 0634 0635 connect( m_addMeasurePointAction, SIGNAL(triggered()), SLOT(addMeasurePointEvent()) ); 0636 connect( m_removeLastMeasurePointAction, SIGNAL(triggered()), SLOT(removeLastMeasurePoint()) ); 0637 connect( m_removeMeasurePointsAction, SIGNAL(triggered()), SLOT(removeMeasurePoints()) ); 0638 0639 connect( this, SIGNAL(numberOfMeasurePointsChanged(int)), SLOT(setNumberOfMeasurePoints(int)) ); 0640 } 0641 0642 void MeasureToolPlugin::removeContextItems() 0643 { 0644 delete m_addMeasurePointAction; 0645 delete m_removeLastMeasurePointAction; 0646 delete m_removeMeasurePointsAction; 0647 delete m_separator; 0648 } 0649 0650 void MeasureToolPlugin::addMeasurePointEvent() 0651 { 0652 QPoint p = m_marbleWidget->popupMenu()->mousePosition(); 0653 0654 qreal lat; 0655 qreal lon; 0656 m_marbleWidget->geoCoordinates( p.x(), p.y(), lon, lat, GeoDataCoordinates::Radian ); 0657 0658 addMeasurePoint( lon, lat ); 0659 } 0660 0661 void MeasureToolPlugin::setNumberOfMeasurePoints( int newNumber ) 0662 { 0663 const bool enableMeasureActions = ( newNumber > 0 ); 0664 m_removeMeasurePointsAction->setEnabled(enableMeasureActions); 0665 m_removeLastMeasurePointAction->setEnabled(enableMeasureActions); 0666 0667 if (m_paintMode == Circular) { 0668 if (newNumber >= 2) { 0669 m_addMeasurePointAction->setEnabled(false); 0670 } else { 0671 m_addMeasurePointAction->setEnabled(true); 0672 } 0673 } 0674 } 0675 0676 bool MeasureToolPlugin::eventFilter( QObject *object, QEvent *e ) 0677 { 0678 if ( m_marbleWidget && !enabled() ) { 0679 m_marbleWidget = nullptr; 0680 removeContextItems(); 0681 m_measureLineString.clear(); 0682 } 0683 0684 if ( m_marbleWidget || !enabled() || !visible() ) { 0685 return RenderPlugin::eventFilter( object, e ); 0686 } 0687 0688 MarbleWidget *widget = qobject_cast<MarbleWidget*>( object ); 0689 0690 if ( widget ) { 0691 m_marbleWidget = widget; 0692 addContextItems(); 0693 } 0694 0695 return RenderPlugin::eventFilter( object, e ); 0696 } 0697 0698 } 0699 0700 #include "moc_MeasureToolPlugin.cpp" 0701