diff --git a/src/lib/marble/MarbleWidgetPopupMenu.cpp b/src/lib/marble/MarbleWidgetPopupMenu.cpp index 055c64f5b..919605487 100644 --- a/src/lib/marble/MarbleWidgetPopupMenu.cpp +++ b/src/lib/marble/MarbleWidgetPopupMenu.cpp @@ -1,919 +1,919 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2006-2007 Torsten Rahn // Copyright 2007 Inge Wallin // Copyright 2012 Illya Kovalevskyy // Copyright 2014 Gábor Péterffy // // Self #include "MarbleWidgetPopupMenu.h" // Marble #include "AbstractDataPluginItem.h" #include "AbstractFloatItem.h" #include "MarbleAboutDialog.h" #include "MarbleDirs.h" #include "MarbleWidget.h" #include "MarbleModel.h" #include "GeoDataExtendedData.h" #include "GeoDataFolder.h" #include "GeoDataPlacemark.h" #include "GeoDataLookAt.h" #include "GeoDataData.h" #include "GeoDataSnippet.h" #include "GeoDataStyle.h" #include "GeoDataBalloonStyle.h" #include "GeoDataIconStyle.h" #include "GeoDataPoint.h" #include "GeoDataTypes.h" #include "GeoDataPhotoOverlay.h" #include "GeoSceneDocument.h" #include "GeoSceneHead.h" #include "MarbleClock.h" #include "MarbleDebug.h" #include "PopupLayer.h" #include "Planet.h" #include "routing/RoutingManager.h" #include "routing/RoutingLayer.h" #include "routing/RouteRequest.h" #include "EditBookmarkDialog.h" #include "BookmarkManager.h" #include "ReverseGeocodingRunnerManager.h" #include "TemplateDocument.h" #include "OsmPlacemarkData.h" #include "StyleBuilder.h" // Qt #include #include #include #include #include #include #include #include namespace Marble { /* TRANSLATOR Marble::MarbleWidgetPopupMenu */ class Q_DECL_HIDDEN MarbleWidgetPopupMenu::Private { public: const MarbleModel *const m_model; MarbleWidget *const m_widget; QVector m_featurelist; QList m_itemList; QMenu m_lmbMenu; QMenu m_rmbMenu; QAction *m_infoDialogAction; QAction *m_directionsFromHereAction; QAction *m_directionsToHereAction; QAction *const m_copyCoordinateAction; QAction *m_rmbExtensionPoint; ReverseGeocodingRunnerManager m_runnerManager; QPoint m_mousePosition; public: Private( MarbleWidget *widget, const MarbleModel *model, MarbleWidgetPopupMenu* parent ); QMenu* createInfoBoxMenu(); /** * Returns the geo coordinates of the mouse pointer at the last right button menu. * You must not pass 0 as coordinates parameter. The result indicates whether the * coordinates are valid, which will be true if the right button menu was opened at least once. */ GeoDataCoordinates mouseCoordinates( QAction* dataContainer ) const; static QString filterEmptyShortDescription( const QString &description ); void setupDialogOsm( PopupLayer *popup, const GeoDataPlacemark* placemark ); void setupDialogSatellite( const GeoDataPlacemark *placemark ); static void setupDialogCity( PopupLayer *popup, const GeoDataPlacemark *placemark ); static void setupDialogNation( PopupLayer *popup, const GeoDataPlacemark *placemark ); static void setupDialogGeoPlaces( PopupLayer *popup, const GeoDataPlacemark *placemark ); static void setupDialogSkyPlaces( PopupLayer *popup, const GeoDataPlacemark *placemark ); static void setupDialogPhotoOverlay( PopupLayer *popup, const GeoDataPhotoOverlay *overlay); }; MarbleWidgetPopupMenu::Private::Private( MarbleWidget *widget, const MarbleModel *model, MarbleWidgetPopupMenu* parent ) : m_model(model), m_widget(widget), m_lmbMenu( m_widget ), m_rmbMenu( m_widget ), m_directionsFromHereAction( 0 ), m_directionsToHereAction( 0 ), m_copyCoordinateAction(new QAction(QIcon(QStringLiteral(":/icons/copy-coordinates.png")), tr("Copy Coordinates"), parent)), m_rmbExtensionPoint( 0 ), m_runnerManager( model ) { // Property actions (Left mouse button) m_infoDialogAction = new QAction( parent ); m_infoDialogAction->setData( 0 ); // Tool actions (Right mouse button) m_directionsFromHereAction = new QAction( tr( "Directions &from here" ), parent ); m_directionsToHereAction = new QAction( tr( "Directions &to here" ), parent ); RouteRequest* request = m_widget->model()->routingManager()->routeRequest(); if ( request ) { m_directionsFromHereAction->setIcon( QIcon( request->pixmap( 0, 16 ) ) ); int const lastIndex = qMax( 1, request->size()-1 ); m_directionsToHereAction->setIcon( QIcon( request->pixmap( lastIndex, 16 ) ) ); } QAction* addBookmark = new QAction( QIcon(QStringLiteral(":/icons/bookmark-new.png")), tr( "Add &Bookmark" ), parent ); QAction* fullscreenAction = new QAction( tr( "&Full Screen Mode" ), parent ); fullscreenAction->setCheckable( true ); QAction* aboutDialogAction = new QAction(QIcon(QStringLiteral(":/icons/marble.png")), tr("&About"), parent); QMenu* infoBoxMenu = createInfoBoxMenu(); const bool smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen; if ( !smallScreen ) { m_rmbExtensionPoint = m_rmbMenu.addSeparator(); } m_rmbMenu.addAction( m_directionsFromHereAction ); m_rmbMenu.addAction( m_directionsToHereAction ); m_rmbMenu.addSeparator(); m_rmbMenu.addAction( addBookmark ); if ( !smallScreen ) { m_rmbMenu.addAction( m_copyCoordinateAction ); } m_rmbMenu.addAction(QIcon(QStringLiteral(":/icons/addressbook-details.png")), tr("&Address Details"), parent, SLOT(startReverseGeocoding())); m_rmbMenu.addSeparator(); m_rmbMenu.addMenu( infoBoxMenu ); if ( !smallScreen ) { m_rmbMenu.addAction( aboutDialogAction ); } else { m_rmbMenu.addAction( fullscreenAction ); } parent->connect( &m_lmbMenu, SIGNAL(aboutToHide()), SLOT(resetMenu()) ); parent->connect( m_directionsFromHereAction, SIGNAL(triggered()), SLOT(directionsFromHere()) ); parent->connect( m_directionsToHereAction, SIGNAL(triggered()), SLOT(directionsToHere()) ); parent->connect( addBookmark, SIGNAL(triggered()), SLOT(addBookmark()) ); parent->connect( aboutDialogAction, SIGNAL(triggered()), SLOT(slotAboutDialog()) ); parent->connect( m_copyCoordinateAction, SIGNAL(triggered()), SLOT(slotCopyCoordinates()) ); parent->connect( m_infoDialogAction, SIGNAL(triggered()), SLOT(slotInfoDialog()) ); parent->connect( fullscreenAction, SIGNAL(triggered(bool)), parent, SLOT(toggleFullscreen(bool)) ); parent->connect( &m_runnerManager, SIGNAL(reverseGeocodingFinished(GeoDataCoordinates,GeoDataPlacemark)), parent, SLOT(showAddressInformation(GeoDataCoordinates,GeoDataPlacemark)) ); } QString MarbleWidgetPopupMenu::Private::filterEmptyShortDescription(const QString &description) { if(description.isEmpty()) return tr("No description available."); return description; } void MarbleWidgetPopupMenu::Private::setupDialogOsm( PopupLayer *popup, const GeoDataPlacemark *placemark ) { const GeoDataCoordinates location = placemark->coordinate(); popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter); QFile descriptionFile(QStringLiteral(":/marble/webpopup/osm.html")); if (!descriptionFile.open(QIODevice::ReadOnly)) { return; } const QString none = QStringLiteral("none"); QString description = descriptionFile.readAll(); const OsmPlacemarkData& data = placemark->osmData(); if (!data.containsTagKey("addr:street") && !data.containsTagKey("addr:housenumber")){ description.replace(QStringLiteral("
%postcode%"), QStringLiteral("%postcode%")); } TemplateDocument doc(description); doc[QStringLiteral("name")] = data.tagValue(QStringLiteral("name")); QString natural = data.tagValue(QStringLiteral("natural")); if (!natural.isEmpty()) { natural[0] = natural[0].toUpper(); if (natural == QLatin1String("Peak")) { QString elevation = data.tagValue(QStringLiteral("ele")); if (!elevation.isEmpty()) { natural = natural + QLatin1String(" - ") + elevation + QLatin1String(" m"); } } doc[QStringLiteral("details")] = natural; } else { doc[QStringLiteral("detailsVisibility")] = none; } QString amenity; QString shop = data.tagValue(QStringLiteral("shop")); if (!shop.isEmpty()) { shop[0] = shop[0].toUpper(); if (shop == QLatin1String("Clothes")) { QString type = data.tagValue(QStringLiteral("clothes")); if (type.isEmpty()) { type = data.tagValue(QStringLiteral("designation")); } if (!type.isEmpty()) { type[0] = type[0].toUpper(); amenity = QLatin1String("Shop - ") + shop + QLatin1String(" (") + type + QLatin1Char(')'); } } if (amenity.isEmpty()) { amenity = QLatin1String("Shop - ") + shop; } } else { amenity = data.tagValue(QStringLiteral("amenity")); if (!amenity.isEmpty()) { amenity[0] = amenity[0].toUpper(); } } if (!amenity.isEmpty()) { doc[QStringLiteral("amenity")] = amenity; } else { doc[QStringLiteral("amenityVisibility")] = none; } QString cuisine = data.tagValue(QStringLiteral("cuisine")); if (!cuisine.isEmpty()) { cuisine[0] = cuisine[0].toUpper(); doc[QStringLiteral("cuisine")] = cuisine; } else { doc[QStringLiteral("cuisineVisibility")] = none; } QString openingHours = data.tagValue(QStringLiteral("opening_hours")); if (!openingHours.isEmpty()) { doc[QStringLiteral("openinghours")] = openingHours; } else { doc[QStringLiteral("openinghoursVisibility")] = none; } bool hasContactsData = false; const QStringList addressItemKeys = QStringList() << QStringLiteral("street") << QStringLiteral("housenumber") << QStringLiteral("postcode") << QStringLiteral("city"); bool hasAddressItem = false; QStringList addressItems; foreach (const QString& key, addressItemKeys) { const QString item = data.tagValue(QLatin1String("addr:") + key); if (!item.isEmpty()) { hasAddressItem = true; } addressItems << item; } if (hasAddressItem) { hasContactsData = true; for(int i = 0; i < addressItemKeys.size(); ++i) { doc[addressItemKeys[i]] = addressItems[i]; } } else { doc[QStringLiteral("addressVisibility")] = none; } QString phoneData = data.tagValue(QStringLiteral("phone")); if (!phoneData.isEmpty()) { hasContactsData = true; doc[QStringLiteral("phone")] = phoneData; } else { doc[QStringLiteral("phoneVisibility")] = none; } QString websiteData; foreach(const QString &tag, QStringList() << "website" << "contact:website" << "facebook" << "contact:facebook" << "url") { websiteData = data.tagValue(tag); if (!websiteData.isEmpty()) { break; } } if (!websiteData.isEmpty()) { hasContactsData = true; doc[QStringLiteral("website")] = websiteData; } else { doc[QStringLiteral("websiteVisibility")] = none; } if (!hasContactsData) { doc[QStringLiteral("contactVisibility")] = none; } bool hasFacilitiesData = false; const QString wheelchair = data.tagValue(QStringLiteral("wheelchair")); if (!wheelchair.isEmpty()) { hasFacilitiesData = true; doc[QStringLiteral("wheelchair")] = wheelchair; } else { doc[QStringLiteral("wheelchairVisibility")] = none; } const QString internetAccess = data.tagValue(QStringLiteral("internet_access")); if (!internetAccess.isEmpty()) { hasFacilitiesData = true; doc[QStringLiteral("internetaccess")] = internetAccess; } else { doc[QStringLiteral("internetVisibility")] = none; } const QString smoking = data.tagValue(QStringLiteral("smoking")); if (!smoking.isEmpty()) { hasFacilitiesData = true; doc[QStringLiteral("smoking")] = smoking; } else { doc[QStringLiteral("smokingVisibility")] = none; } if (!hasFacilitiesData) { doc[QStringLiteral("facilitiesVisibility")] = none; } const QString flagPath = m_widget->styleBuilder()->createStyle(StyleParameters(placemark))->iconStyle().iconPath(); doc["flag"] = flagPath; popup->setContent(doc.finalText()); } void MarbleWidgetPopupMenu::Private::setupDialogSatellite( const GeoDataPlacemark *placemark ) { PopupLayer *const popup = m_widget->popupLayer(); const GeoDataCoordinates location = placemark->coordinate(m_widget->model()->clockDateTime()); popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter); const QString description = placemark->description(); TemplateDocument doc(description); doc["altitude"] = QString::number(location.altitude(), 'f', 2); doc["latitude"] = location.latToString(); doc["longitude"] = location.lonToString(); popup->setContent(doc.finalText()); } void MarbleWidgetPopupMenu::Private::setupDialogCity( PopupLayer *popup, const GeoDataPlacemark *placemark ) { const GeoDataCoordinates location = placemark->coordinate(); popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter); QFile descriptionFile(QStringLiteral(":/marble/webpopup/city.html")); if (!descriptionFile.open(QIODevice::ReadOnly)) { return; } const QString description = descriptionFile.readAll(); TemplateDocument doc(description); doc["name"] = placemark->name(); QString roleString; const QString role = placemark->role(); if (role == QLatin1String("PPLC")) { roleString = tr("National Capital"); } else if (role == QLatin1String("PPL")) { roleString = tr("City"); } else if (role == QLatin1String("PPLA")) { roleString = tr("State Capital"); } else if (role == QLatin1String("PPLA2")) { roleString = tr("County Capital"); } else if (role == QLatin1String("PPLA3") || role == QLatin1String("PPLA4")) { roleString = tr("Capital"); } else if (role == QLatin1String("PPLF") || role == QLatin1String("PPLG") || role == QLatin1String("PPLL") || role == QLatin1String("PPLQ") || role == QLatin1String("PPLR") || role == QLatin1String("PPLS") || role == QLatin1String("PPLW")) { roleString = tr("Village"); } doc["category"] = roleString; doc["shortDescription"] = filterEmptyShortDescription(placemark->description()); doc["latitude"] = location.latToString(); doc["longitude"] = location.lonToString(); doc["elevation"] = QString::number(location.altitude(), 'f', 2); doc["population"] = QString::number(placemark->population()); doc["country"] = placemark->countryCode(); doc["state"] = placemark->state(); QString dst = QStringLiteral("%1").arg((placemark->extendedData().value(QStringLiteral("gmt")).value().toInt() + placemark->extendedData().value(QStringLiteral("dst")).value().toInt()) / ( double ) 100, 0, 'f', 1 ); // There is an issue about UTC. // It's possible to variants (e.g.): // +1.0 and -1.0, but dst does not have + an the start if (dst.startsWith(QLatin1Char('-'))) { doc["timezone"] = dst; } else { doc["timezone"] = QLatin1Char('+') + dst; } const QString flagPath = MarbleDirs::path( QLatin1String("flags/flag_") + placemark->countryCode().toLower() + QLatin1String(".svg")); doc["flag"] = flagPath; popup->setContent(doc.finalText()); } void MarbleWidgetPopupMenu::Private::setupDialogNation( PopupLayer *popup, const GeoDataPlacemark *index) { const GeoDataCoordinates location = index->coordinate(); popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter); QFile descriptionFile(QStringLiteral(":/marble/webpopup/nation.html")); if (!descriptionFile.open(QIODevice::ReadOnly)) { return; } const QString description = descriptionFile.readAll(); TemplateDocument doc(description); doc["name"] = index->name(); doc["shortDescription"] = filterEmptyShortDescription(index->description()); doc["latitude"] = location.latToString(); doc["longitude"] = location.lonToString(); doc["elevation"] = QString::number(location.altitude(), 'f', 2); doc["population"] = QString::number(index->population()); doc["area"] = QString::number(index->area(), 'f', 2); const QString flagPath = MarbleDirs::path(QString("flags/flag_%1.svg").arg(index->countryCode().toLower()) ); doc["flag"] = flagPath; popup->setContent(doc.finalText()); } void MarbleWidgetPopupMenu::Private::setupDialogGeoPlaces( PopupLayer *popup, const GeoDataPlacemark *index) { const GeoDataCoordinates location = index->coordinate(); popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter); QFile descriptionFile(QStringLiteral(":/marble/webpopup/geoplace.html")); if (!descriptionFile.open(QIODevice::ReadOnly)) { return; } const QString description = descriptionFile.readAll(); TemplateDocument doc(description); doc["name"] = index->name(); doc["latitude"] = location.latToString(); doc["longitude"] = location.lonToString(); doc["elevation"] = QString::number(location.altitude(), 'f', 2); doc["shortDescription"] = filterEmptyShortDescription(index->description()); popup->setContent(doc.finalText()); } void MarbleWidgetPopupMenu::Private::setupDialogSkyPlaces( PopupLayer *popup, const GeoDataPlacemark *index) { const GeoDataCoordinates location = index->coordinate(); popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter); QFile descriptionFile(QStringLiteral(":/marble/webpopup/skyplace.html")); if (!descriptionFile.open(QIODevice::ReadOnly)) { return; } const QString description = descriptionFile.readAll(); TemplateDocument doc(description); doc["name"] = index->name(); doc["latitude"] = GeoDataCoordinates::latToString( location.latitude(), GeoDataCoordinates::Astro, GeoDataCoordinates::Radian, -1, 'f'); doc["longitude"] = GeoDataCoordinates::lonToString( location.longitude(), GeoDataCoordinates::Astro, GeoDataCoordinates::Radian, -1, 'f'); doc["shortDescription"] = filterEmptyShortDescription(index->description()); popup->setContent(doc.finalText()); } void MarbleWidgetPopupMenu::Private::setupDialogPhotoOverlay( PopupLayer *popup, const GeoDataPhotoOverlay *index ) { const GeoDataCoordinates location = index->point().coordinates(); popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter); QFile descriptionFile(QStringLiteral(":/marble/webpopup/photooverlay.html")); if ( !descriptionFile.open(QIODevice::ReadOnly) ) { return; } const QString description = descriptionFile.readAll(); TemplateDocument doc(description); doc["name"] = index->name(); doc["latitude"] = location.latToString(); doc["longitude"] = location.lonToString(); doc["elevation"] = QString::number(location.altitude(), 'f', 2); doc["shortDescription"] = filterEmptyShortDescription(index->description()); doc["source"] = index->absoluteIconFile(); doc["width"] = QString::number(200); doc["height"] = QString::number(100); QString const basePath = index->resolvePath("."); QUrl const baseUrl = (basePath != QLatin1String(".")) ? QUrl::fromLocalFile(basePath + QLatin1Char('/')) : QUrl(); popup->setContent(doc.finalText(), baseUrl ); } MarbleWidgetPopupMenu::MarbleWidgetPopupMenu(MarbleWidget *widget, const MarbleModel *model) : QObject(widget), d( new Private( widget, model, this ) ) { // nothing to do } MarbleWidgetPopupMenu::~MarbleWidgetPopupMenu() { delete d; } QMenu* MarbleWidgetPopupMenu::Private::createInfoBoxMenu() { QMenu* menu = new QMenu( tr( "&Info Boxes" ) ); QList floatItemList = m_widget->floatItems(); QList::const_iterator iter = floatItemList.constBegin(); QList::const_iterator const end = floatItemList.constEnd(); for (; iter != end; ++iter ) { menu->addAction( (*iter)->action() ); } return menu; } void MarbleWidgetPopupMenu::showLmbMenu( int xpos, int ypos ) { bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen; if ( smallScreen ) { showRmbMenu( xpos, ypos ); return; } d->m_mousePosition.setX(xpos); d->m_mousePosition.setY(ypos); const QPoint curpos = QPoint( xpos, ypos ); d->m_featurelist = d->m_widget->whichFeatureAt( curpos ); int actionidx = 1; QVector::const_iterator it = d->m_featurelist.constBegin(); QVector::const_iterator const itEnd = d->m_featurelist.constEnd(); for (; it != itEnd; ++it ) { QString name = (*it)->name(); QPixmap icon = QPixmap::fromImage( ( *it)->style()->iconStyle().icon() ); d->m_infoDialogAction->setData( actionidx ); d->m_infoDialogAction->setText( name ); d->m_infoDialogAction->setIcon( icon ); // Insert as first action in the menu QAction *firstAction = 0; if( !d->m_lmbMenu.actions().isEmpty() ) { firstAction = d->m_lmbMenu.actions().first(); } d->m_lmbMenu.insertAction( firstAction, d->m_infoDialogAction ); actionidx++; } d->m_itemList = d->m_widget->whichItemAt( curpos ); QList::const_iterator itW = d->m_itemList.constBegin(); QList::const_iterator const itWEnd = d->m_itemList.constEnd(); for (; itW != itWEnd; ++itW ) { foreach ( QAction* action, (*itW)->actions() ) { d->m_lmbMenu.addAction( action ); } } switch ( d->m_lmbMenu.actions().size() ) { case 0: // nothing to do, ignore break; case 1: // one action? perform immediately d->m_lmbMenu.actions().first()->activate( QAction::Trigger ); d->m_lmbMenu.clear(); break; default: d->m_lmbMenu.popup( d->m_widget->mapToGlobal( curpos ) ); } } void MarbleWidgetPopupMenu::showRmbMenu( int xpos, int ypos ) { qreal lon, lat; const bool visible = d->m_widget->geoCoordinates( xpos, ypos, lon, lat, GeoDataCoordinates::Radian ); if ( !visible ) return; d->m_mousePosition.setX(xpos); d->m_mousePosition.setY(ypos); QPoint curpos = QPoint( xpos, ypos ); d->m_copyCoordinateAction->setData( curpos ); bool const showDirectionButtons = d->m_widget->routingLayer() && d->m_widget->routingLayer()->isInteractive(); d->m_directionsFromHereAction->setVisible( showDirectionButtons ); d->m_directionsToHereAction->setVisible( showDirectionButtons ); RouteRequest* request = d->m_widget->model()->routingManager()->routeRequest(); if ( request ) { int const lastIndex = qMax( 1, request->size()-1 ); d->m_directionsToHereAction->setIcon( QIcon( request->pixmap( lastIndex, 16 ) ) ); } d->m_rmbMenu.popup( d->m_widget->mapToGlobal( curpos ) ); } void MarbleWidgetPopupMenu::resetMenu() { d->m_lmbMenu.clear(); } void MarbleWidgetPopupMenu::slotInfoDialog() { QAction *action = qobject_cast( sender() ); if ( action == 0 ) { mDebug() << "Warning: slotInfoDialog should be called by a QAction signal"; return; } int actionidx = action->data().toInt(); if ( actionidx > 0 ) { const GeoDataPlacemark *placemark = dynamic_cast(d->m_featurelist.at( actionidx -1 )); const GeoDataPhotoOverlay *overlay = dynamic_cast(d->m_featurelist.at( actionidx - 1 )); PopupLayer* popup = d->m_widget->popupLayer(); bool isSatellite = false; bool isCity = false; bool isNation = false; const OsmPlacemarkData& data = placemark->osmData(); bool hasOsmData = false; QStringList recognizedTags; recognizedTags << "name" << "amenity" << "cuisine" << "opening_hours"; recognizedTags << "addr:street" << "addr:housenumber" << "addr:postcode"; recognizedTags << "addr:city" << "phone" << "wheelchair" << "internet_access"; recognizedTags << "smoking" << "website" << "contact:website" << "facebook"; recognizedTags << "contact:facebook" << "url"; foreach(const QString &tag, recognizedTags) { if (data.containsTagKey(tag)) { hasOsmData = true; break; } } if ( placemark ) { isSatellite = (placemark->visualCategory() == GeoDataPlacemark::Satellite); isCity = (placemark->visualCategory() >= GeoDataPlacemark::SmallCity && placemark->visualCategory() <= GeoDataPlacemark::LargeNationCapital); isNation = (placemark->visualCategory() == GeoDataPlacemark::Nation); } bool isSky = false; if ( d->m_widget->model()->mapTheme() ) { isSky = d->m_widget->model()->mapTheme()->head()->target() == QLatin1String("sky"); } - popup->setSize(QSizeF(400, 400)); + popup->setSize(QSizeF(420, 420)); if (hasOsmData){ d->setupDialogOsm( popup, placemark ); } else if (isSatellite) { d->setupDialogSatellite( placemark ); } else if (isCity) { Private::setupDialogCity( popup, placemark ); } else if (isNation) { Private::setupDialogNation( popup, placemark ); } else if (isSky) { Private::setupDialogSkyPlaces( popup, placemark ); } else if ( overlay ) { Private::setupDialogPhotoOverlay( popup, overlay ); } else if ( placemark && placemark->role().isEmpty() ) { popup->setContent( placemark->description() ); } else if ( placemark ) { Private::setupDialogGeoPlaces( popup, placemark ); } if ( placemark ) { if ( placemark->style() == 0 ) { popup->setBackgroundColor(QColor(Qt::white)); popup->setTextColor(QColor(Qt::black)); return; } if ( placemark->style()->balloonStyle().displayMode() == GeoDataBalloonStyle::Hide ) { popup->setVisible(false); return; } QString content = placemark->style()->balloonStyle().text(); if (content.length() > 0) { content.replace(QStringLiteral("$[name]"), placemark->name(), Qt::CaseInsensitive); content.replace(QStringLiteral("$[description]"), placemark->description(), Qt::CaseInsensitive); content.replace(QStringLiteral("$[address]"), placemark->address(), Qt::CaseInsensitive); // @TODO: implement the line calculation, so that snippet().maxLines actually has effect. content.replace(QStringLiteral("$[snippet]"), placemark->snippet().text(), Qt::CaseInsensitive); content.replace(QStringLiteral("$[id]"), placemark->id(), Qt::CaseInsensitive); QString const basePath = placemark->resolvePath("."); QUrl const baseUrl = (basePath != QLatin1String(".")) ? QUrl::fromLocalFile(basePath + QLatin1Char('/')) : QUrl(); popup->setContent(content, baseUrl ); } popup->setBackgroundColor(placemark->style()->balloonStyle().backgroundColor()); popup->setTextColor(placemark->style()->balloonStyle().textColor()); } popup->popup(); } } void MarbleWidgetPopupMenu::slotCopyCoordinates() { const GeoDataCoordinates coordinates = d->mouseCoordinates( d->m_copyCoordinateAction ); if ( coordinates.isValid() ) { const qreal longitude_degrees = coordinates.longitude(GeoDataCoordinates::Degree); const qreal latitude_degrees = coordinates.latitude(GeoDataCoordinates::Degree); // importing this representation into Marble does not show anything, // but Merkaartor shows the point const QString kmlRepresentation = QString::fromLatin1( "\n" "\n" "\n" " \n" // " \n" " \n" " %1,%2\n" " \n" " \n" "\n" "\n" ).arg(longitude_degrees, 0, 'f', 10).arg(latitude_degrees, 0, 'f', 10); // importing this data into Marble and Merkaartor works const QString gpxRepresentation = QString::fromLatin1( "\n" "\n" " \n" // " %3\n" // " \n" // " %4\n" " \n" "\n" ).arg(latitude_degrees, 0, 'f', 10).arg(longitude_degrees, 0, 'f', 10); QString positionString = coordinates.toString(); QMimeData * const myMimeData = new QMimeData(); myMimeData->setText(positionString); myMimeData->setData(QLatin1String("application/vnd.google-earth.kml+xml"), kmlRepresentation.toUtf8()); myMimeData->setData(QLatin1String("application/gpx+xml"), gpxRepresentation.toUtf8()); QClipboard * const clipboard = QApplication::clipboard(); clipboard->setMimeData(myMimeData); } } void MarbleWidgetPopupMenu::slotAboutDialog() { QPointer dialog = new MarbleAboutDialog( d->m_widget ); dialog->exec(); delete dialog; } void MarbleWidgetPopupMenu::addAction( Qt::MouseButton button, QAction* action ) { if ( button == Qt::RightButton ) { d->m_rmbMenu.insertAction( d->m_rmbExtensionPoint, action ); } else { d->m_lmbMenu.addAction( action ); } } void MarbleWidgetPopupMenu::directionsFromHere() { RouteRequest* request = d->m_widget->model()->routingManager()->routeRequest(); if ( request ) { const GeoDataCoordinates coordinates = d->mouseCoordinates( d->m_copyCoordinateAction ); if ( coordinates.isValid() ) { if ( request->size() > 0 ) { request->setPosition( 0, coordinates ); } else { request->append( coordinates ); } d->m_widget->model()->routingManager()->retrieveRoute(); } } } void MarbleWidgetPopupMenu::directionsToHere() { RouteRequest* request = d->m_widget->model()->routingManager()->routeRequest(); if ( request ) { const GeoDataCoordinates coordinates = d->mouseCoordinates( d->m_copyCoordinateAction ); if ( coordinates.isValid() ) { if ( request->size() > 1 ) { request->setPosition( request->size()-1, coordinates ); } else { request->append( coordinates ); } d->m_widget->model()->routingManager()->retrieveRoute(); } } } GeoDataCoordinates MarbleWidgetPopupMenu::Private::mouseCoordinates( QAction* dataContainer ) const { if ( !dataContainer ) { return GeoDataCoordinates(); } if ( !m_featurelist.isEmpty() && m_featurelist.first()->nodeType() == GeoDataTypes::GeoDataPlacemarkType ) { const GeoDataPlacemark * placemark = static_cast( m_featurelist.first() ); return placemark->coordinate( m_model->clock()->dateTime() ); } else { QPoint p = dataContainer->data().toPoint(); qreal lat( 0.0 ), lon( 0.0 ); const bool valid = m_widget->geoCoordinates( p.x(), p.y(), lon, lat, GeoDataCoordinates::Radian ); if ( valid ) { return GeoDataCoordinates( lon, lat ); } } return GeoDataCoordinates(); } void MarbleWidgetPopupMenu::startReverseGeocoding() { const GeoDataCoordinates coordinates = d->mouseCoordinates( d->m_copyCoordinateAction ); if ( coordinates.isValid() ) { d->m_runnerManager.reverseGeocoding( coordinates ); } } void MarbleWidgetPopupMenu::showAddressInformation(const GeoDataCoordinates &, const GeoDataPlacemark &placemark) { QString text = placemark.address(); if ( !text.isEmpty() ) { QMessageBox::information( d->m_widget, tr( "Address Details" ), text, QMessageBox::Ok ); } } void MarbleWidgetPopupMenu::addBookmark() { const GeoDataCoordinates coordinates = d->mouseCoordinates( d->m_copyCoordinateAction ); if ( coordinates.isValid() ) { QPointer dialog = new EditBookmarkDialog( d->m_widget->model()->bookmarkManager(), d->m_widget ); dialog->setMarbleWidget( d->m_widget ); dialog->setCoordinates( coordinates ); dialog->setRange( d->m_widget->lookAt().range() ); dialog->setReverseGeocodeName(); if ( dialog->exec() == QDialog::Accepted ) { d->m_widget->model()->bookmarkManager()->addBookmark( dialog->folder(), dialog->bookmark() ); } delete dialog; } } void MarbleWidgetPopupMenu::toggleFullscreen( bool enabled ) { QWidget* parent = d->m_widget; for ( ; parent->parentWidget(); parent = parent->parentWidget() ) { // nothing to do } if ( enabled ) { parent->setWindowState( parent->windowState() | Qt::WindowFullScreen ); } else { parent->setWindowState( parent->windowState() & ~Qt::WindowFullScreen ); } } QPoint MarbleWidgetPopupMenu::mousePosition() const { return d->m_mousePosition; } } #include "moc_MarbleWidgetPopupMenu.cpp" diff --git a/src/lib/marble/TourPlayback.cpp b/src/lib/marble/TourPlayback.cpp index 6df81a1f0..629206b47 100644 --- a/src/lib/marble/TourPlayback.cpp +++ b/src/lib/marble/TourPlayback.cpp @@ -1,319 +1,319 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2014 Sanjiban Bairagya // #include "TourPlayback.h" #include #include #include #include "MarbleDebug.h" #include "MarbleWidget.h" #include "PopupLayer.h" #include "GeoDataPoint.h" #include "GeoDataPlacemark.h" #include "GeoDataPlaylist.h" #include "GeoDataTour.h" #include "GeoDataWait.h" #include "GeoDataFlyTo.h" #include "GeoDataLookAt.h" #include "GeoDataTourControl.h" #include "GeoDataSoundCue.h" #include "GeoDataAnimatedUpdate.h" #include "MarbleModel.h" #include "GeoDataTreeModel.h" #include "GeoDataTypes.h" #include "PlaybackFlyToItem.h" #include "PlaybackAnimatedUpdateItem.h" #include "PlaybackWaitItem.h" #include "PlaybackTourControlItem.h" #include "PlaybackSoundCueItem.h" #include "SerialTrack.h" #include "SoundTrack.h" #include "AnimatedUpdateTrack.h" namespace Marble { class TourPlaybackPrivate { public: TourPlaybackPrivate(); ~TourPlaybackPrivate(); GeoDataTour *m_tour; bool m_pause; SerialTrack m_mainTrack; QList m_soundTracks; QList m_animatedUpdateTracks; GeoDataFlyTo m_mapCenter; QPointer m_widget; QUrl m_baseUrl; }; TourPlaybackPrivate::TourPlaybackPrivate() : m_tour( 0 ), m_pause( false ), m_mainTrack(), m_widget( 0 ) { // do nothing } TourPlaybackPrivate::~TourPlaybackPrivate() { qDeleteAll(m_soundTracks); qDeleteAll(m_animatedUpdateTracks); } TourPlayback::TourPlayback(QObject *parent) : QObject(parent), d(new TourPlaybackPrivate()) { connect( &d->m_mainTrack, SIGNAL(centerOn(GeoDataCoordinates)), this, SLOT(centerOn(GeoDataCoordinates)) ); connect( &d->m_mainTrack, SIGNAL(progressChanged(double)), this, SIGNAL(progressChanged(double)) ); connect( &d->m_mainTrack, SIGNAL(finished()), this, SLOT(stopTour()) ); connect( &d->m_mainTrack, SIGNAL(itemFinished(int)), this, SLOT(handleFinishedItem(int)) ); } TourPlayback::~TourPlayback() { stop(); delete d; } void TourPlayback::handleFinishedItem( int index ) { emit itemFinished( index ); } void TourPlayback::stopTour() { foreach( SoundTrack* track, d->m_soundTracks ){ track->stop(); track->setPaused( false ); } for( int i = d->m_animatedUpdateTracks.size()-1; i >= 0; i-- ){ d->m_animatedUpdateTracks[ i ]->stop(); d->m_animatedUpdateTracks[ i ]->setPaused( false ); } emit finished(); } void TourPlayback::showBalloon( GeoDataPlacemark* placemark ) { GeoDataPoint* point = static_cast( placemark->geometry() ); d->m_widget->popupLayer()->setCoordinates( point->coordinates(), Qt::AlignRight | Qt::AlignVCenter ); d->m_widget->popupLayer()->setContent( placemark->description(), d->m_baseUrl ); d->m_widget->popupLayer()->setVisible( true ); - d->m_widget->popupLayer()->setSize( QSizeF( 480, 500 ) ); + d->m_widget->popupLayer()->setSize(QSizeF(500, 520)); } void TourPlayback::hideBalloon() { if( d->m_widget ){ d->m_widget->popupLayer()->setVisible( false ); } } bool TourPlayback::isPlaying() const { return !d->m_pause; } void TourPlayback::setMarbleWidget(MarbleWidget* widget) { d->m_widget = widget; connect( this, SIGNAL(added(GeoDataContainer*,GeoDataFeature*,int)), d->m_widget->model()->treeModel(), SLOT(addFeature(GeoDataContainer*,GeoDataFeature*,int)) ); connect( this, SIGNAL(removed(const GeoDataFeature*)), d->m_widget->model()->treeModel(), SLOT(removeFeature(const GeoDataFeature*)) ); connect( this, SIGNAL(updated(GeoDataFeature*)), d->m_widget->model()->treeModel(), SLOT(updateFeature(GeoDataFeature*)) ); } void TourPlayback::setBaseUrl( const QUrl &baseUrl ) { d->m_baseUrl = baseUrl; } QUrl TourPlayback::baseUrl() const { return d->m_baseUrl; } void TourPlayback::centerOn( const GeoDataCoordinates &coordinates ) { if ( d->m_widget ) { GeoDataLookAt lookat; lookat.setCoordinates( coordinates ); lookat.setRange( coordinates.altitude() ); d->m_widget->flyTo( lookat, Instant ); } } void TourPlayback::setTour(GeoDataTour *tour) { d->m_tour = tour; if ( !d->m_tour ) { clearTracks(); return; } updateTracks(); } void TourPlayback::play() { d->m_pause = false; GeoDataLookAt* lookat = new GeoDataLookAt( d->m_widget->lookAt() ); lookat->setAltitude( lookat->range() ); d->m_mapCenter.setView( lookat ); d->m_mainTrack.play(); foreach( SoundTrack* track, d->m_soundTracks) { track->play(); } foreach( AnimatedUpdateTrack* track, d->m_animatedUpdateTracks) { track->play(); } } void TourPlayback::pause() { d->m_pause = true; d->m_mainTrack.pause(); foreach( SoundTrack* track, d->m_soundTracks) { track->pause(); } foreach( AnimatedUpdateTrack* track, d->m_animatedUpdateTracks) { track->pause(); } } void TourPlayback::stop() { d->m_pause = true; d->m_mainTrack.stop(); foreach( SoundTrack* track, d->m_soundTracks) { track->stop(); } for( int i = d->m_animatedUpdateTracks.size()-1; i >= 0; i-- ){ d->m_animatedUpdateTracks[ i ]->stop(); } hideBalloon(); } void TourPlayback::seek( double value ) { double const offset = qBound( 0.0, value, d->m_mainTrack.duration() ); d->m_mainTrack.seek( offset ); foreach( SoundTrack* track, d->m_soundTracks ){ track->seek( offset ); } foreach( AnimatedUpdateTrack* track, d->m_animatedUpdateTracks ){ track->seek( offset ); } } int TourPlayback::mainTrackSize() { return d->m_mainTrack.size(); } PlaybackItem* TourPlayback::mainTrackItemAt( int i ) { return d->m_mainTrack.at( i ); } void TourPlayback::updateTracks() { clearTracks(); double delay = 0; for( int i = 0; i < d->m_tour->playlist()->size(); i++){ GeoDataTourPrimitive* primitive = d->m_tour->playlist()->primitive( i ); if( primitive->nodeType() == GeoDataTypes::GeoDataFlyToType ){ const GeoDataFlyTo *flyTo = dynamic_cast(primitive); d->m_mainTrack.append( new PlaybackFlyToItem( flyTo ) ); delay += flyTo->duration(); } else if( primitive->nodeType() == GeoDataTypes::GeoDataWaitType ){ const GeoDataWait *wait = dynamic_cast(primitive); d->m_mainTrack.append( new PlaybackWaitItem( wait ) ); delay += wait->duration(); } else if( primitive->nodeType() == GeoDataTypes::GeoDataTourControlType ){ const GeoDataTourControl *tourControl = dynamic_cast(primitive); d->m_mainTrack.append( new PlaybackTourControlItem( tourControl ) ); } else if( primitive->nodeType() == GeoDataTypes::GeoDataSoundCueType ){ const GeoDataSoundCue *soundCue = dynamic_cast(primitive); PlaybackSoundCueItem *item = new PlaybackSoundCueItem( soundCue ); SoundTrack *track = new SoundTrack( item ); track->setDelayBeforeTrackStarts( delay ); d->m_soundTracks.append( track ); } else if( primitive->nodeType() == GeoDataTypes::GeoDataAnimatedUpdateType ){ GeoDataAnimatedUpdate *animatedUpdate = dynamic_cast(primitive); PlaybackAnimatedUpdateItem *item = new PlaybackAnimatedUpdateItem( animatedUpdate ); AnimatedUpdateTrack *track = new AnimatedUpdateTrack( item ); track->setDelayBeforeTrackStarts( delay + animatedUpdate->delayedStart() ); d->m_animatedUpdateTracks.append( track ); connect( track, SIGNAL(balloonHidden()), this, SLOT(hideBalloon()) ); connect( track, SIGNAL(balloonShown(GeoDataPlacemark*)), this, SLOT(showBalloon(GeoDataPlacemark*)) ); connect( track, SIGNAL(updated(GeoDataFeature*)), this, SIGNAL(updated(GeoDataFeature*)) ); connect( track, SIGNAL(added(GeoDataContainer*,GeoDataFeature*,int)), this, SIGNAL(added(GeoDataContainer*,GeoDataFeature*,int)) ); connect( track, SIGNAL(removed(const GeoDataFeature*)), this, SIGNAL(removed(const GeoDataFeature*)) ); } } Q_ASSERT( d->m_widget ); GeoDataLookAt* lookat = new GeoDataLookAt( d->m_widget->lookAt() ); lookat->setAltitude( lookat->range() ); d->m_mapCenter.setView( lookat ); PlaybackFlyToItem* mapCenterItem = new PlaybackFlyToItem( &d->m_mapCenter ); PlaybackFlyToItem* before = mapCenterItem; for ( int i=0; im_mainTrack.size(); ++i ) { PlaybackFlyToItem* item = qobject_cast( d->m_mainTrack.at(i) ); if ( item ) { item->setBefore( before ); before = item; } } PlaybackFlyToItem* next = 0; for ( int i=d->m_mainTrack.size()-1; i>=0; --i ) { PlaybackFlyToItem* item = qobject_cast( d->m_mainTrack.at(i) ); if ( item ) { item->setNext( next ); next = item; } } } void TourPlayback::clearTracks() { d->m_mainTrack.clear(); qDeleteAll(d->m_soundTracks); qDeleteAll(d->m_animatedUpdateTracks); d->m_soundTracks.clear(); d->m_animatedUpdateTracks.clear(); } double TourPlayback::duration() const { return d->m_mainTrack.duration(); } } // namespace Marble #include "moc_TourPlayback.cpp" diff --git a/src/plugins/render/panoramio/PanoramioItem.cpp b/src/plugins/render/panoramio/PanoramioItem.cpp index dffb45b40..d84696761 100644 --- a/src/plugins/render/panoramio/PanoramioItem.cpp +++ b/src/plugins/render/panoramio/PanoramioItem.cpp @@ -1,103 +1,103 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2009 Bastian Holst // // Self #include "PanoramioItem.h" // Marble #include "MarbleDebug.h" #include "MarbleWidget.h" #include "layers/PopupLayer.h" #include #include using namespace Marble; PanoramioItem::PanoramioItem( MarbleWidget *marbleWidget, QObject *parent ) : AbstractDataPluginItem( parent ), m_marbleWidget( marbleWidget ) { m_action = new QAction( this ); connect( m_action, SIGNAL(triggered()), this, SLOT(openBrowser()) ); } bool PanoramioItem::initialized() const { return !smallImage.isNull(); } void PanoramioItem::addDownloadedFile( const QString &url, const QString &type ) { if( standardImageSize == type ) { // Loading original image QImage largeImage; largeImage.load( url ); // Scaling the image to the half of the original size smallImage = largeImage.scaled( largeImage.size() / 3, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); setSize( smallImage.size() ); update(); } else { mDebug() << Q_FUNC_INFO << "can't handle type" << type; } } void PanoramioItem::setPhotoUrl( const QUrl &url ) { m_url = url; } QDate PanoramioItem::uploadDate() const { return m_uploadDate; } void PanoramioItem::setUploadDate( const QDate &uploadDate ) { m_uploadDate = uploadDate; } bool PanoramioItem::operator<( const AbstractDataPluginItem *other ) const { Q_ASSERT( dynamic_cast( other ) != 0 ); return uploadDate() > static_cast( other )->uploadDate(); } void PanoramioItem::paint( QPainter *painter ) { painter->drawImage( 0, 0, smallImage ); } QAction *Marble::PanoramioItem::action() { if( m_action->icon().isNull() ) { m_action->setIcon( QIcon( QPixmap::fromImage( smallImage ) ) ); } return m_action; } void PanoramioItem::openBrowser() { if ( m_marbleWidget ) { PopupLayer* popup = m_marbleWidget->popupLayer(); popup->setCoordinates( coordinate(), Qt::AlignRight | Qt::AlignVCenter ); - popup->setSize( QSizeF( 700, 450 ) ); + popup->setSize(QSizeF(720, 470)); popup->setUrl( m_url ); popup->popup(); } } #include "moc_PanoramioItem.cpp" diff --git a/src/plugins/render/photo/PhotoPluginItem.cpp b/src/plugins/render/photo/PhotoPluginItem.cpp index bdcce8a56..e6bef50ed 100644 --- a/src/plugins/render/photo/PhotoPluginItem.cpp +++ b/src/plugins/render/photo/PhotoPluginItem.cpp @@ -1,203 +1,203 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2009 Bastian Holst // Copyright 2012 Mohammed Nafees // // Self #include "PhotoPluginItem.h" // Plugin #include "CoordinatesParser.h" #include "PhotoPluginModel.h" // Marble #include "AbstractDataPluginItem.h" #include "GeoDataCoordinates.h" #include "GeoPainter.h" #include "LabelGraphicsItem.h" #include "MarbleGraphicsGridLayout.h" #include "TinyWebBrowser.h" #include "ViewportParams.h" #include "MarbleDebug.h" #include "MarbleWidget.h" #include "MarbleModel.h" #include "RenderPlugin.h" #include "PluginManager.h" #include "layers/PopupLayer.h" // Qt #include #include #include #include #include #include using namespace Marble; PhotoPluginItem::PhotoPluginItem( MarbleWidget *widget, QObject *parent ) : AbstractDataPluginItem( parent ), m_marbleWidget( widget ), m_image( this ), m_browser( 0 ) { m_action = new QAction( this ); connect( m_action, SIGNAL(triggered()), this, SLOT(openBrowser()) ); setCacheMode( ItemCoordinateCache ); m_image.setFrame( FrameGraphicsItem::ShadowFrame ); m_image.setBorderBrush( QBrush( QColor( Qt::white ) ) ); m_image.setBorderWidth( 2.0 ); m_image.setMargin( 5 ); MarbleGraphicsGridLayout *layout = new MarbleGraphicsGridLayout( 1, 1 ); layout->addItem( &m_image, 0, 0 ); setLayout( layout ); } PhotoPluginItem::~PhotoPluginItem() { delete m_browser; } QString PhotoPluginItem::name() const { return title(); } bool PhotoPluginItem::initialized() const { return !m_smallImage.isNull() && coordinate().isValid(); } void PhotoPluginItem::addDownloadedFile( const QString& url, const QString& type ) { if (type == QLatin1String("thumbnail")) { m_smallImage.load( url ); m_image.setImage( m_smallImage.scaled( QSize( 50, 50 ) ) ); } else if (type == QLatin1String("info")) { QFile file( url ); if( !file.open( QIODevice::ReadOnly | QIODevice::Text ) ) { return; } GeoDataCoordinates coordinates; CoordinatesParser parser( &coordinates ); if( parser.read( &file ) ) { setCoordinate( coordinates ); } } if ( initialized() ) { emit updated(); } } bool PhotoPluginItem::operator<( const AbstractDataPluginItem *other ) const { return this->id() < other->id(); } QUrl PhotoPluginItem::photoUrl() const { QString url = "https://farm%1.static.flickr.com/%2/%3_%4_s.jpg"; return QUrl( url.arg( farm() ).arg( server() ).arg( id() ).arg( secret() ) ); } QUrl PhotoPluginItem::infoUrl() const { QHash options; options.insert( "photo_id", id() ); return PhotoPluginModel::generateUrl( "flickr", "flickr.photos.geo.getLocation", options ); } QString PhotoPluginItem::server() const { return m_server; } void PhotoPluginItem::setServer( const QString& server ) { m_server = server; } QString PhotoPluginItem::farm() const { return m_farm; } void PhotoPluginItem::setFarm( const QString& farm ) { m_farm = farm; } QString PhotoPluginItem::secret() const { return m_secret; } void PhotoPluginItem::setSecret( const QString& secret ) { m_secret = secret; } QString PhotoPluginItem::owner() const { return m_owner; } void PhotoPluginItem::setOwner( const QString& owner ) { m_owner = owner; } QString PhotoPluginItem::title() const { return m_title; } void PhotoPluginItem::setTitle( const QString& title ) { m_title = title; m_action->setText( title ); } QAction *PhotoPluginItem::action() { if( m_action->icon().isNull() ) { m_action->setIcon( QIcon( QPixmap::fromImage( m_smallImage ) ) ); } return m_action; } void PhotoPluginItem::openBrowser() { if ( m_marbleWidget ) { PopupLayer* popup = m_marbleWidget->popupLayer(); popup->setCoordinates( coordinate(), Qt::AlignRight | Qt::AlignVCenter ); - popup->setSize( QSizeF( 700, 450 ) ); + popup->setSize(QSizeF(720, 470)); popup->setUrl(QUrl(QLatin1String("http://m.flickr.com/photos/") + owner() + QLatin1Char('/') + id() + QLatin1Char('/'))); popup->popup(); } else { if( !m_browser ) { m_browser = new TinyWebBrowser(); } QString url = "http://www.flickr.com/photos/%1/%2/"; m_browser->load( QUrl( url.arg( owner() ).arg( id() ) ) ); m_browser->show(); } } #include "moc_PhotoPluginItem.cpp" diff --git a/src/plugins/render/weather/WeatherItem.cpp b/src/plugins/render/weather/WeatherItem.cpp index eafd1a0e8..e04d1fef2 100644 --- a/src/plugins/render/weather/WeatherItem.cpp +++ b/src/plugins/render/weather/WeatherItem.cpp @@ -1,580 +1,580 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2009 Bastian Holst // Copyright 2012 Illya Kovalevskyy // // Self #include "WeatherItem.h" // Marble #include "GeoPainter.h" #include "MarbleDirs.h" #include "WeatherData.h" #include "weatherGlobal.h" #include "FrameGraphicsItem.h" #include "LabelGraphicsItem.h" #include "MarbleGraphicsGridLayout.h" #include "WidgetGraphicsItem.h" #include "TinyWebBrowser.h" #include "MarbleDebug.h" #include "MarbleWidget.h" #include "layers/PopupLayer.h" // Qt #include #include #include #include #include #include #include #include namespace Marble { const QSize borderSpacing( 4, 4 ); const QSize imageSize( 28, 28 ); const double imageSizeRatio = ( (double) imageSize.width()) / ( (double) imageSize.height() ); class WeatherItemPrivate { Q_DECLARE_TR_FUNCTIONS(WeatherItemPrivate) public: WeatherItemPrivate( WeatherItem *parent ) : m_marbleWidget( 0 ), m_priority( 0 ), m_browserAction( tr( "Weather" ), parent ), m_favoriteAction( parent ), m_parent( parent ), m_frameItem( m_parent ), m_conditionLabel( &m_frameItem ), m_temperatureLabel( &m_frameItem ), m_windDirectionLabel( &m_frameItem ), m_windSpeedLabel( &m_frameItem ), m_favoriteButton( &m_frameItem ) { // Setting minimum sizes m_temperatureLabel.setMinimumSize( QSizeF( 0, imageSize.height() ) ); m_windSpeedLabel.setMinimumSize( QSizeF( 0, imageSize.height() ) ); QPushButton *button = new QPushButton(); button->setStyleSheet( "border-style: outset;" ); button->setIcon(QIcon(QStringLiteral(":/icons/bookmarks.png"))); button->setFixedSize( 22, 22 ); button->setFlat( true ); button->setCheckable( true ); m_favoriteButton.setWidget( button ); // Layouting the item MarbleGraphicsGridLayout *topLayout = new MarbleGraphicsGridLayout( 1, 1 ); parent->setLayout( topLayout ); topLayout->addItem( &m_frameItem, 0, 0 ); MarbleGraphicsGridLayout *gridLayout = new MarbleGraphicsGridLayout( 2, 3 ); gridLayout->setAlignment( Qt::AlignCenter ); gridLayout->setSpacing( 4 ); m_frameItem.setLayout( gridLayout ); m_frameItem.setFrame( FrameGraphicsItem::RoundedRectFrame ); gridLayout->addItem( &m_conditionLabel, 0, 0 ); gridLayout->addItem( &m_temperatureLabel, 0, 1 ); gridLayout->setAlignment( &m_temperatureLabel, Qt::AlignRight | Qt::AlignVCenter ); gridLayout->addItem( &m_windDirectionLabel, 1, 0 ); gridLayout->addItem( &m_windSpeedLabel, 1, 1 ); gridLayout->setAlignment( &m_windSpeedLabel, Qt::AlignRight | Qt::AlignVCenter ); gridLayout->addItem( &m_favoriteButton, 0, 2 ); updateLabels(); } ~WeatherItemPrivate() { } void updateToolTip() { QLocale locale = QLocale::system(); QString toolTip; toolTip += tr( "Station: %1\n" ).arg( m_parent->stationName() ); if ( m_currentWeather.hasValidCondition() && m_currentWeather.hasValidTemperature() ) toolTip += QString( "%2, %3\n" ).arg( m_currentWeather.conditionString() ) .arg( temperatureString() ); else if ( m_currentWeather.hasValidCondition() ) toolTip += QString( "%2\n" ).arg( m_currentWeather.conditionString() ); else if ( m_currentWeather.hasValidTemperature() ) toolTip += QString( "%2\n" ).arg( temperatureString() ); if ( m_currentWeather.hasValidWindSpeed() && m_currentWeather.hasValidWindDirection() ) toolTip += tr( "Wind: %4, %5\n", "Wind: WindSpeed, WindDirection" ) .arg( windSpeedString( ) ) .arg( m_currentWeather.windDirectionString() ); else if ( m_currentWeather.hasValidWindSpeed() ) toolTip += tr( "Wind: %4\n", "Wind: WindSpeed" ) .arg( m_currentWeather.windSpeedString() ); else if ( m_currentWeather.hasValidWindDirection() ) toolTip += tr( "Wind: %4\n", "Wind: WindDirection" ) .arg( m_currentWeather.windDirectionString() ); if ( m_currentWeather.hasValidPressure() && m_currentWeather.hasValidPressureDevelopment() ) toolTip += tr( "Pressure: %6, %7", "Pressure: Pressure, Development" ) .arg( pressureString() ) .arg( m_currentWeather.pressureDevelopmentString() ); else if ( m_currentWeather.hasValidPressure() ) toolTip += tr( "Pressure: %6", "Pressure: Pressure" ) .arg( pressureString() ); else if ( m_currentWeather.hasValidPressureDevelopment() ) toolTip += tr( "Pressure %7", "Pressure Development" ) .arg( m_currentWeather.pressureDevelopmentString() ); if ( !m_forecastWeather.isEmpty() ) { toolTip += QLatin1Char('\n'); QDate const minDate = QDate::currentDate(); foreach( const WeatherData& data, m_forecastWeather ) { QDate date = data.dataDate(); if( date >= minDate && data.hasValidCondition() && data.hasValidMinTemperature() && data.hasValidMaxTemperature() ) { toolTip += QLatin1Char('\n') + tr( "%1: %2, %3 to %4", "DayOfWeek: Condition, MinTemp to MaxTemp" ) .arg( locale.standaloneDayName( date.dayOfWeek() ) ) .arg( data.conditionString() ) .arg( data.minTemperatureString( temperatureUnit() ) ) .arg( data.maxTemperatureString( temperatureUnit() ) ); } } } m_parent->setToolTip( toolTip ); } void updateLabels() { if ( isConditionShown() ) { m_conditionLabel.setImage( m_currentWeather.icon(), imageSize ); } else { m_conditionLabel.clear(); } if ( isTemperatureShown() ) { m_temperatureLabel.setText( temperatureString() ); } else { m_temperatureLabel.clear(); } if ( isWindDirectionShown() ) { QString windDirectionString = m_currentWeather.windDirectionString(); QSizeF windDirectionImageSize; QSvgRenderer s_windIcons(MarbleDirs::path(QStringLiteral("weather/wind-arrows.svgz"))); QSizeF windDirectionSizeF = s_windIcons.boundsOnElement( windDirectionString ).size(); double windDirectionRatio = windDirectionSizeF.width() / windDirectionSizeF.height(); if ( windDirectionRatio >= imageSizeRatio ) { windDirectionImageSize.setWidth( imageSize.width() ); windDirectionImageSize.setHeight( imageSize.width() / windDirectionRatio ); } else { windDirectionImageSize.setHeight( imageSize.height() ); windDirectionImageSize.setWidth( imageSize.height() * windDirectionRatio ); } QImage windArrow( windDirectionImageSize.toSize(), QImage::Format_ARGB32 ); windArrow.fill( Qt::transparent ); QPainter painter( &windArrow ); s_windIcons.render( &painter, windDirectionString ); m_windDirectionLabel.setImage( windArrow ); } else { m_windDirectionLabel.clear(); } if ( isWindSpeedShown() ) { m_windSpeedLabel.setText( windSpeedString() ); } else { m_windSpeedLabel.clear(); } m_parent->update(); } void updateFavorite() { QStringList items = m_settings.value(QStringLiteral("favoriteItems")).toString() .split(QLatin1Char(','), QString::SkipEmptyParts); bool favorite = items.contains( m_parent->id() ); m_favoriteButton.setVisible( favorite ); m_favoriteAction.setText( favorite ? tr( "Remove from Favorites" ) : tr( "Add to Favorites" ) ); if ( m_parent->isFavorite() != favorite ) { m_parent->setFavorite( favorite ); } m_parent->update(); } bool isConditionShown() const { return m_currentWeather.hasValidCondition() && m_settings.value(QStringLiteral("showCondition"), showConditionDefault).toBool(); } bool isTemperatureShown() const { return m_currentWeather.hasValidTemperature() && m_settings.value(QStringLiteral("showTemperature"), showTemperatureDefault).toBool(); } bool isWindDirectionShown() const { return m_currentWeather.hasValidWindDirection() && m_settings.value(QStringLiteral("showWindDirection"), showWindDirectionDefault).toBool(); } bool isWindSpeedShown() const { return m_currentWeather.hasValidWindSpeed() && m_settings.value(QStringLiteral("showWindSpeed"), showWindSpeedDefault).toBool(); } QString temperatureString() const { WeatherData::TemperatureUnit tUnit = temperatureUnit(); return m_currentWeather.temperatureString( tUnit ); } WeatherData::TemperatureUnit temperatureUnit() const { WeatherData::TemperatureUnit tUnit = (WeatherData::TemperatureUnit) m_settings.value(QStringLiteral("temperatureUnit"), WeatherData::Celsius ).toInt(); return tUnit; } QString windSpeedString() const { return m_currentWeather.windSpeedString( speedUnit() ); } WeatherData::SpeedUnit speedUnit() const { return (WeatherData::SpeedUnit) m_settings.value(QStringLiteral("windSpeedUnit"), WeatherData::kph ).toInt(); } QString pressureString() const { return m_currentWeather.pressureString( pressureUnit() ); } WeatherData::PressureUnit pressureUnit() const { return (WeatherData::PressureUnit) m_settings.value(QStringLiteral("pressureUnit"), WeatherData::HectoPascal ).toInt(); } MarbleWidget *m_marbleWidget; WeatherData m_currentWeather; QMap m_forecastWeather; int m_priority; QAction m_browserAction; QAction m_favoriteAction; WeatherItem *m_parent; QString m_stationName; QHash m_settings; static QFont s_font; // Labels and Layout // We are not the owner of these items. FrameGraphicsItem m_frameItem; LabelGraphicsItem m_conditionLabel; LabelGraphicsItem m_temperatureLabel; LabelGraphicsItem m_windDirectionLabel; LabelGraphicsItem m_windSpeedLabel; WidgetGraphicsItem m_favoriteButton; }; // FIXME: Fonts to be defined globally #ifdef Q_OS_MACX QFont WeatherItemPrivate::s_font = QFont( QStringLiteral( "Sans Serif" ), 10 ); #else QFont WeatherItemPrivate::s_font = QFont( QStringLiteral( "Sans Serif" ), 8 ); #endif WeatherItem::WeatherItem(QObject *parent ) : AbstractDataPluginItem( parent ), d( new WeatherItemPrivate( this ) ) { setCacheMode( ItemCoordinateCache ); } WeatherItem::WeatherItem(MarbleWidget* widget, QObject *parent ) : AbstractDataPluginItem( parent ), d( new WeatherItemPrivate( this ) ) { setCacheMode( ItemCoordinateCache ); d->m_marbleWidget = widget; } WeatherItem::~WeatherItem() { delete d; } QAction *WeatherItem::action() { disconnect( &d->m_browserAction, SIGNAL(triggered()), this, SLOT(openBrowser()) ); connect( &d->m_browserAction, SIGNAL(triggered()), this, SLOT(openBrowser()) ); return &d->m_browserAction; } bool WeatherItem::request( const QString& type ) { Q_UNUSED( type ) return true; } bool WeatherItem::initialized() const { return d->isConditionShown() || d->isTemperatureShown() || d->isWindDirectionShown() || d->isWindSpeedShown(); } bool WeatherItem::operator<( const AbstractDataPluginItem *other ) const { const WeatherItem *weatherItem = qobject_cast(other); if( weatherItem ) { return ( priority() > weatherItem->priority() ); } else { return false; } } QString WeatherItem::stationName() const { return d->m_stationName; } void WeatherItem::setStationName( const QString& name ) { if ( name != d->m_stationName ) { d->m_browserAction.setText( name ); d->m_stationName = name; d->updateToolTip(); d->updateLabels(); emit stationNameChanged(); } } WeatherData WeatherItem::currentWeather() const { return d->m_currentWeather; } void WeatherItem::setCurrentWeather( const WeatherData &weather ) { d->m_currentWeather = weather; d->updateToolTip(); d->updateLabels(); emit updated(); emit descriptionChanged(); emit imageChanged(); emit temperatureChanged(); } QMap WeatherItem::forecastWeather() const { return d->m_forecastWeather; } void WeatherItem::setForecastWeather( const QMap& forecasts ) { d->m_forecastWeather = forecasts; d->updateToolTip(); emit updated(); } void WeatherItem::addForecastWeather( const QList& forecasts ) { foreach( const WeatherData& data, forecasts ) { QDate date = data.dataDate(); WeatherData other = d->m_forecastWeather.value( date ); if ( !other.isValid() ) { d->m_forecastWeather.insert( date, data ); } else if ( other.publishingTime() < data.publishingTime() ) { d->m_forecastWeather.remove( date ); d->m_forecastWeather.insert( date, data ); } } // Remove old items QDate const minDate = QDate::currentDate(); QMap::iterator it = d->m_forecastWeather.begin(); while( it != d->m_forecastWeather.end() ) { if ( it.key() < minDate ) { it = d->m_forecastWeather.erase( it ); } else { ++it; } } d->updateToolTip(); emit updated(); } quint8 WeatherItem::priority() const { return d->m_priority; } void WeatherItem::setPriority( quint8 priority ) { d->m_priority = priority; } void WeatherItem::setSettings( const QHash& settings ) { if ( d->m_settings == settings ) { return; } d->m_settings = settings; d->updateToolTip(); d->updateLabels(); d->updateFavorite(); } void WeatherItem::setMarbleWidget(MarbleWidget *widget) { d->m_marbleWidget = widget; } void WeatherItem::openBrowser() { if (d->m_marbleWidget) { PopupLayer *popup = d->m_marbleWidget->popupLayer(); popup->setCoordinates( coordinate(), Qt::AlignRight | Qt::AlignVCenter ); - popup->setSize( QSizeF( 610, 550 ) ); // +10 pixels for the width + popup->setSize(QSizeF(630, 580)); // +10 pixels for the width popup->popup(); QFile weatherHtmlFile(QStringLiteral(":/marble/weather/weather.html")); if ( !weatherHtmlFile.open(QIODevice::ReadOnly) ) { return; } QString templateHtml = weatherHtmlFile.readAll(); popup->setContent( createFromTemplate(templateHtml) ); } } QString WeatherItem::createFromTemplate(const QString &templateHtml) { QString html = templateHtml; QLocale locale = QLocale::system(); html.replace("%city_name%", stationName()); if (!d->m_currentWeather.iconSource().isEmpty()) { html.replace("%weather_situation%", QLatin1String("m_currentWeather.iconSource() + QLatin1String("\" />")); } else { html.remove("%weather_situation%"); } html.replace("%current_temp%", d->temperatureString()); html.replace("%current_condition%", d->m_currentWeather.conditionString()); html.replace("%wind_direction%", d->m_currentWeather.windDirectionString()); html.replace("%wind_speed%", d->m_currentWeather.windSpeedString()); html.replace("%humidity_level%", d->m_currentWeather.humidityString()); html.replace("%publish_time%", d->m_currentWeather.publishingTime().toString()); if(d->m_forecastWeather.size() < 1) { html.replace("%forecast_available%", "none"); } else { html.replace("%forecast_available%", "block"); } int forecastNumber = 0; foreach ( const WeatherData &forecast, d->m_forecastWeather ) { forecastNumber++; const QString suffix = QString::number(forecastNumber); QDate date = forecast.dataDate(); html.replace(QLatin1String("%day_f") + suffix + QLatin1Char('%'), locale.standaloneDayName(date.dayOfWeek())); html.replace(QLatin1String("%weather_situation_f") + suffix + QLatin1Char('%'), QLatin1String("file://")+forecast.iconSource()); html.replace(QLatin1String("%max_temp_f") + suffix + QLatin1Char('%'), forecast.maxTemperatureString(WeatherData::Celsius)); html.replace(QLatin1String("%min_temp_f") + suffix + QLatin1Char('%'), forecast.minTemperatureString(WeatherData::Celsius)); html.replace(QLatin1String("%condition_f") + suffix + QLatin1Char('%'), forecast.conditionString()); html.replace(QLatin1String("%wind_direction_f") + suffix + QLatin1Char('%'), forecast.windDirectionString()); html.replace(QLatin1String("%wind_speed_f") + suffix + QLatin1Char('%'), forecast.windSpeedString()); html.replace(QLatin1String("%publish_time_f") + suffix + QLatin1Char('%'), forecast.publishingTime().toString()); } return html; } QList WeatherItem::actions() { QList result; result << &d->m_browserAction; disconnect( &d->m_favoriteAction, SIGNAL(triggered()), this, SLOT(toggleFavorite()) ); connect( &d->m_favoriteAction, SIGNAL(triggered()), this, SLOT(toggleFavorite()) ); result << &d->m_favoriteAction; return result; } QString WeatherItem::description() const { return d->m_currentWeather.toHtml( WeatherData::Celsius, WeatherData::kph, WeatherData::Bar ); } QString WeatherItem::image() const { return d->m_currentWeather.iconSource(); } double WeatherItem::temperature() const { return d->m_currentWeather.hasValidTemperature() ? d->m_currentWeather.temperature( WeatherData::Celsius ) : 0.0; } } // namespace Marble #include "moc_WeatherItem.cpp" diff --git a/src/plugins/render/wikipedia/WikipediaItem.cpp b/src/plugins/render/wikipedia/WikipediaItem.cpp index 1a87d87a5..f86ae3b4c 100644 --- a/src/plugins/render/wikipedia/WikipediaItem.cpp +++ b/src/plugins/render/wikipedia/WikipediaItem.cpp @@ -1,248 +1,248 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2009 Bastian Holst // // Self #include "WikipediaItem.h" // Qt #include #include // Marble #include "MarbleDebug.h" #include "ViewportParams.h" #include "TinyWebBrowser.h" #include "MarbleWidget.h" #include "MarbleModel.h" #include "RenderPlugin.h" #include "PluginManager.h" #include "layers/PopupLayer.h" using namespace Marble; /* TRANSLATOR Marble::WikipediaItem */ // The Wikipedia icon is not a square const QRect wikiIconRect( 0, 0, 22, 19 ); const QSize miniWikiIconSize( 22, 19 ); const int miniWikiIconBorder = 3; WikipediaItem::WikipediaItem( MarbleWidget* widget, QObject *parent ) : AbstractDataPluginItem( parent ), m_marbleWidget( widget ), m_rank( 0.0 ), m_browser( 0 ), m_wikiIcon(), m_showThumbnail( false ) { m_action = new QAction( this ); connect( m_action, SIGNAL(triggered()), this, SLOT(openBrowser()) ); setCacheMode( ItemCoordinateCache ); } WikipediaItem::~WikipediaItem() { delete m_browser; } QString WikipediaItem::name() const { return id(); } void WikipediaItem::setName( const QString& name ) { setId( name ); updateToolTip(); } bool WikipediaItem::initialized() const { return true; } void WikipediaItem::addDownloadedFile( const QString& url, const QString& type ) { if (type == QLatin1String("thumbnail")) { m_thumbnail.load( url ); updateSize(); emit updated(); } } bool WikipediaItem::operator<( const AbstractDataPluginItem *other ) const { WikipediaItem const * otherItem = dynamic_cast( other ); return otherItem ? m_rank > otherItem->m_rank : id() < other->id(); } void WikipediaItem::paint( QPainter *painter ) { if ( !showThumbnail() ) { m_wikiIcon.paint( painter, wikiIconRect ); } else { painter->drawPixmap( 0, 0, m_thumbnail ); QSize minSize = miniWikiIconSize; minSize *= 2; QSize thumbnailSize = m_thumbnail.size(); if ( thumbnailSize.width() >= minSize.width() && thumbnailSize.height() >= minSize.height() ) { QRect wikiRect( QPoint( 0, 0 ), miniWikiIconSize ); wikiRect.moveBottomRight( QPoint( m_thumbnail.width() - miniWikiIconBorder, m_thumbnail.height() - miniWikiIconBorder ) ); m_wikiIcon.paint( painter, wikiRect ); } } } qreal WikipediaItem::longitude() const { return coordinate().longitude(); } void WikipediaItem::setLongitude( qreal longitude ) { GeoDataCoordinates updatedCoordinates = coordinate(); updatedCoordinates.setLongitude( longitude ); setCoordinate( updatedCoordinates ); } qreal WikipediaItem::latitude() const { return coordinate().latitude(); } void WikipediaItem::setLatitude( qreal latitude ) { GeoDataCoordinates updatedCoordinates = coordinate(); updatedCoordinates.setLatitude( latitude ); setCoordinate( updatedCoordinates ); } QUrl WikipediaItem::url() const { return m_url; } void WikipediaItem::setUrl( const QUrl& url ) { m_url = url; } QUrl WikipediaItem::thumbnailImageUrl() const { return m_thumbnailImageUrl; } void WikipediaItem::setThumbnailImageUrl( const QUrl& thumbnailImageUrl ) { m_thumbnailImageUrl = thumbnailImageUrl; } QString WikipediaItem::summary() const { return m_summary; } void WikipediaItem::setSummary( const QString& summary ) { m_summary = summary; updateToolTip(); } QAction *WikipediaItem::action() { m_action->setText( id() ); return m_action; } void WikipediaItem::openBrowser( ) { if ( m_marbleWidget ) { PopupLayer* popup = m_marbleWidget->popupLayer(); popup->setCoordinates( coordinate(), Qt::AlignRight | Qt::AlignVCenter ); - popup->setSize( QSizeF( 500, 550 ) ); + popup->setSize(QSizeF(520, 570)); popup->setUrl( url() ); popup->popup(); } else { if ( !m_browser ) { m_browser = new TinyWebBrowser(); } m_browser->load( url() ); m_browser->show(); } } void WikipediaItem::setIcon( const QIcon& icon ) { m_action->setIcon( icon ); m_wikiIcon = icon; updateSize(); } void WikipediaItem::setSettings( const QHash& settings ) { const bool showThumbnail = settings.value(QStringLiteral("showThumbnails"), false).toBool(); if ( showThumbnail != m_showThumbnail ) { m_showThumbnail = showThumbnail; updateSize(); updateToolTip(); update(); } } void WikipediaItem::setRank( double rank ) { m_rank = rank; } double WikipediaItem::rank() const { return m_rank; } void WikipediaItem::updateSize() { if ( showThumbnail() ) { setSize( m_thumbnail.size() ); } else { setSize( wikiIconRect.size() ); } } void WikipediaItem::updateToolTip() { QString toolTip = QLatin1String( "" "" "

"); if ( summary().isEmpty() ) { toolTip += name() + QLatin1String("

\n"); setToolTip(toolTip); } else { toolTip += tr("%1
%2", "Title:\nSummary") + QLatin1String("

\n"); setToolTip( toolTip.arg( name() ).arg( summary() ) ); } } bool WikipediaItem::showThumbnail() const { return m_showThumbnail && !m_thumbnail.isNull(); } #include "moc_WikipediaItem.cpp"