40 #include <QApplication>
46 #include <QMessageBox>
51 class MarbleWidgetPopupMenu::Private {
53 const MarbleModel *
const m_model;
56 QVector<const GeoDataPlacemark*> m_featurelist;
57 QList<AbstractDataPluginItem *> m_itemList;
59 QMenu *
const m_lmbMenu;
60 QMenu *
const m_rmbMenu;
62 QAction *m_infoDialogAction;
63 QAction *m_showOrbitAction;
64 QAction *m_trackPlacemarkAction;
65 QAction *m_directionsToHereAction;
67 QAction *
const m_copyCoordinateAction;
69 QAction *m_rmbExtensionPoint;
71 ReverseGeocodingRunnerManager *
const m_runnerManager;
73 QPoint m_mousePosition;
77 QMenu* createInfoBoxMenu();
78 QString filterEmptyShortDescription(
const QString &description)
const;
79 void setupDialogSatellite(PopupLayer *popup,
const GeoDataPlacemark *index);
80 void setupDialogCity(PopupLayer *popup,
const GeoDataPlacemark *index);
81 void setupDialogNation(PopupLayer *popup,
const GeoDataPlacemark *index);
82 void setupDialogGeoPlaces(PopupLayer *popup,
const GeoDataPlacemark *index);
83 void setupDialogSkyPlaces(PopupLayer *popup,
const GeoDataPlacemark *index);
90 bool mouseCoordinates( GeoDataCoordinates* coordinates, QAction* dataContainer );
93 MarbleWidgetPopupMenu::Private::Private(
MarbleWidget *widget,
const MarbleModel *model, MarbleWidgetPopupMenu* parent ) :
96 m_lmbMenu( new QMenu( m_widget ) ),
97 m_rmbMenu( new QMenu( m_widget ) ),
98 m_directionsToHereAction( 0 ),
99 m_copyCoordinateAction( new QAction( QIcon(
":/icons/copy-coordinates.png"), tr(
"Copy Coordinates"), parent ) ),
100 m_rmbExtensionPoint( 0 ),
101 m_runnerManager( new ReverseGeocodingRunnerManager( model, parent ) )
104 m_infoDialogAction =
new QAction( parent );
105 m_infoDialogAction->setData( 0 );
107 m_showOrbitAction =
new QAction( tr(
"Display orbit" ), parent );
108 m_showOrbitAction->setCheckable(
true );
109 m_showOrbitAction->setData( 0 );
111 m_trackPlacemarkAction =
new QAction( tr(
"Keep centered" ), parent );
112 m_trackPlacemarkAction->setData( 0 );
115 QAction* fromHere =
new QAction( tr(
"Directions &from here" ), parent );
116 m_directionsToHereAction =
new QAction( tr(
"Directions &to here" ), parent );
117 RouteRequest* request = m_widget->model()->routingManager()->routeRequest();
119 fromHere->setIcon( QIcon( request->pixmap( 0, 16 ) ) );
120 int const lastIndex = qMax( 1, request->size()-1 );
121 m_directionsToHereAction->setIcon( QIcon( request->pixmap( lastIndex, 16 ) ) );
123 QAction* addBookmark =
new QAction( QIcon(
":/icons/bookmark-new.png"),
124 tr(
"Add &Bookmark" ), parent );
125 QAction* fullscreenAction =
new QAction( tr(
"&Full Screen Mode" ), parent );
126 fullscreenAction->setCheckable(
true );
128 QAction* aboutDialogAction =
new QAction( QIcon(
":/icons/marble.png"), tr(
"&About" ), parent );
130 QMenu* infoBoxMenu = createInfoBoxMenu();
132 const bool smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
134 if ( !smallScreen ) {
135 m_rmbExtensionPoint = m_rmbMenu->addSeparator();
138 m_rmbMenu->addAction( fromHere );
139 m_rmbMenu->addAction( m_directionsToHereAction );
140 m_rmbMenu->addSeparator();
141 m_rmbMenu->addAction( addBookmark );
142 if ( !smallScreen ) {
143 m_rmbMenu->addAction( m_copyCoordinateAction );
145 m_rmbMenu->addAction( QIcon(
":/icons/addressbook-details.png"), tr(
"&Address Details" ), parent, SLOT(startReverseGeocoding()) );
146 m_rmbMenu->addSeparator();
147 m_rmbMenu->addMenu( infoBoxMenu );
149 if ( !smallScreen ) {
150 m_rmbMenu->addAction( aboutDialogAction );
152 m_rmbMenu->addAction( fullscreenAction );
155 parent->connect( fromHere, SIGNAL(triggered()), SLOT(directionsFromHere()) );
156 parent->connect( m_directionsToHereAction, SIGNAL(triggered()), SLOT(directionsToHere()) );
157 parent->connect( addBookmark, SIGNAL(triggered()), SLOT(addBookmark()) );
158 parent->connect( aboutDialogAction, SIGNAL(triggered()), SLOT(slotAboutDialog()) );
159 parent->connect( m_copyCoordinateAction, SIGNAL(triggered()), SLOT(slotCopyCoordinates()) );
160 parent->connect( m_infoDialogAction, SIGNAL(triggered()), SLOT(slotInfoDialog()) );
161 parent->connect( m_showOrbitAction, SIGNAL(triggered(
bool)), SLOT(slotShowOrbit(
bool)) );
162 parent->connect( m_trackPlacemarkAction, SIGNAL(triggered(
bool)), SLOT(slotTrackPlacemark()) );
163 parent->connect( fullscreenAction, SIGNAL(triggered(
bool)), parent, SLOT(toggleFullscreen(
bool)) );
165 parent->connect( m_runnerManager, SIGNAL(reverseGeocodingFinished(GeoDataCoordinates,GeoDataPlacemark)),
166 parent, SLOT(showAddressInformation(GeoDataCoordinates,GeoDataPlacemark)) );
172 d( new Private( widget, model, this ) )
182 QMenu* MarbleWidgetPopupMenu::Private::createInfoBoxMenu()
184 QMenu* menu =
new QMenu( tr(
"&Info Boxes" ) );
185 QList<AbstractFloatItem *> floatItemList = m_widget->floatItems();
187 QList<AbstractFloatItem *>::const_iterator iter = floatItemList.constBegin();
188 QList<AbstractFloatItem *>::const_iterator
const end = floatItemList.constEnd();
189 for (; iter != end; ++iter )
191 menu->addAction( (*iter)->action() );
204 if (!d->m_lmbMenu->isEmpty()) {
205 d->m_lmbMenu->clear();
207 foreach(
QObject *child, d->m_lmbMenu->children() ) {
208 child->deleteLater();
212 d->m_mousePosition.setX(xpos);
213 d->m_mousePosition.setY(ypos);
215 const QPoint curpos = QPoint( xpos, ypos );
216 d->m_featurelist = d->m_widget->whichFeatureAt( curpos );
219 bool hasSatellites =
false;
221 QVector<const GeoDataPlacemark*>::const_iterator it = d->m_featurelist.constBegin();
222 QVector<const GeoDataPlacemark*>::const_iterator
const itEnd = d->m_featurelist.constEnd();
223 for (; it != itEnd; ++it )
225 QString name = (*it)->name();
226 QPixmap icon = QPixmap::fromImage( ( *it)->style()->iconStyle().icon() );
227 d->m_infoDialogAction->setData( actionidx );
231 d->m_infoDialogAction->setText( name );
232 d->m_infoDialogAction->setIcon( icon );
234 d->m_lmbMenu->addAction( d->m_infoDialogAction );
236 hasSatellites =
true;
237 QMenu *subMenu =
new QMenu( name, d->m_lmbMenu );
238 subMenu->setIcon( icon );
239 d->m_infoDialogAction->setText( tr(
"Satellite information" ) );
240 d->m_infoDialogAction->setIcon( QIcon() );
241 subMenu->addAction( d->m_infoDialogAction );
243 d->m_showOrbitAction->setChecked( (*it)->style()->lineStyle().penStyle() != Qt::NoPen );
244 d->m_showOrbitAction->setData( actionidx );
245 subMenu->addAction( d->m_showOrbitAction );
247 d->m_trackPlacemarkAction->setData( actionidx );
248 subMenu->addAction( d->m_trackPlacemarkAction );
250 d->m_lmbMenu->addAction( subMenu->menuAction() );
255 d->m_itemList = d->m_widget->whichItemAt( curpos );
256 QList<AbstractDataPluginItem *>::const_iterator itW = d->m_itemList.constBegin();
257 QList<AbstractDataPluginItem *>::const_iterator
const itWEnd = d->m_itemList.constEnd();
258 for (; itW != itWEnd; ++itW )
260 foreach ( QAction* action, (*itW)->actions() ) {
261 d->m_lmbMenu->addAction( action );
265 switch ( d->m_lmbMenu->actions().size() ) {
267 case 1:
if ( ! hasSatellites ) {
268 d->m_lmbMenu->actions().first()->activate( QAction::Trigger );
271 default: d->m_lmbMenu->popup( d->m_widget->mapToGlobal( curpos ) );
283 d->m_mousePosition.setX(xpos);
284 d->m_mousePosition.setY(ypos);
286 QPoint curpos = QPoint( xpos, ypos );
287 d->m_copyCoordinateAction->setData( curpos );
288 RouteRequest* request = d->m_widget->model()->routingManager()->routeRequest();
290 int const lastIndex = qMax( 1, request->
size()-1 );
291 d->m_directionsToHereAction->setIcon( QIcon( request->
pixmap( lastIndex, 16 ) ) );
294 d->m_rmbMenu->popup( d->m_widget->mapToGlobal( curpos ) );
297 void MarbleWidgetPopupMenu::slotInfoDialog()
299 QAction *action = qobject_cast<QAction *>( sender() );
301 mDebug() <<
"Warning: slotInfoDialog should be called by a QAction signal";
305 int actionidx = action->data().toInt();
307 if ( actionidx > 0 ) {
308 const GeoDataPlacemark *index = d->m_featurelist.at( actionidx -1 );
314 if ( d->m_model->mapTheme() ) {
315 isSky = d->m_model->mapTheme()->head()->target() ==
"sky";
317 PopupLayer* popup = d->m_widget->popupLayer();
318 popup->setSize(QSizeF(580, 620));
319 if (index->role().isEmpty() || isSatellite || isCity || isNation || isSky) {
321 d->setupDialogSatellite(popup, index);
323 d->setupDialogCity(popup, index);
324 }
else if (isNation) {
325 d->setupDialogNation(popup, index);
327 d->setupDialogSkyPlaces(popup, index);
329 popup->setContent(index->description());
332 d->setupDialogGeoPlaces(popup, index);
338 QString MarbleWidgetPopupMenu::Private::filterEmptyShortDescription(
const QString &description)
const
340 if(description.isEmpty())
341 return tr(
"No description available.");
345 void MarbleWidgetPopupMenu::Private::setupDialogSatellite(PopupLayer *popup,
const GeoDataPlacemark *index)
347 GeoDataCoordinates location = index->coordinate(m_model->clockDateTime());
348 popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter);
350 const QString description = index->description();
351 TemplateDocument doc(description);
352 doc[
"altitude"] = QString::number(location.altitude(),
'f', 2);
353 doc[
"latitude"] = location.latToString();
354 doc[
"longitude"] = location.lonToString();
355 popup->setContent(doc.finalText());
358 void MarbleWidgetPopupMenu::Private::setupDialogCity(PopupLayer *popup,
const GeoDataPlacemark *index)
360 GeoDataCoordinates location = index->coordinate(m_model->clockDateTime());
361 popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter);
363 QFile descriptionFile(
":/marble/webpopup/city.html");
364 if (!descriptionFile.open(QIODevice::ReadOnly)) {
368 const QString description = descriptionFile.readAll();
369 TemplateDocument doc(description);
371 doc[
"name"] = index->name();
373 const QString role = index->role();
375 roleString = tr(
"National Capital");
376 }
else if(role==
"PPL") {
377 roleString = tr(
"City");
378 }
else if(role==
"PPLA") {
379 roleString = tr(
"State Capital");
380 }
else if(role==
"PPLA2") {
381 roleString = tr(
"County Capital");
382 }
else if(role==
"PPLA3" || role==
"PPLA4" ) {
383 roleString = tr(
"Capital");
384 }
else if(role==
"PPLF" || role==
"PPLG" || role==
"PPLL" || role==
"PPLQ" ||
385 role==
"PPLR" || role==
"PPLS" || role==
"PPLW" ) {
386 roleString = tr(
"Village");
389 doc[
"category"] = roleString;
390 doc[
"shortDescription"] = filterEmptyShortDescription(index->description());
391 doc[
"latitude"] = location.latToString();
392 doc[
"longitude"] = location.lonToString();
393 doc[
"elevation"] = QString::number(location.altitude(),
'f', 2);
394 doc[
"population"] = QString::number(index->population());
395 doc[
"country"] = index->countryCode();
396 doc[
"state"] = index->state();
398 QString dst = QString(
"%1" ).arg( ( index->extendedData().value(
"gmt").value().toInt() +
399 index->extendedData().value(
"dst").value().toInt() ) /
400 (
double ) 100, 0,
'f', 1 );
404 if(dst.startsWith(
'-')) {
405 doc[
"timezone"] = dst;
407 doc[
"timezone"] =
"+"+dst;
411 QString(
"flags/flag_%1.svg").arg(index->countryCode().toLower()));
412 doc[
"flag"] = flagPath;
414 popup->setContent(doc.finalText());
417 void MarbleWidgetPopupMenu::Private::setupDialogNation(PopupLayer *popup,
const GeoDataPlacemark *index)
419 GeoDataCoordinates location = index->coordinate(m_model->clockDateTime());
420 popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter);
422 QFile descriptionFile(
":/marble/webpopup/nation.html");
423 if (!descriptionFile.open(QIODevice::ReadOnly)) {
427 const QString description = descriptionFile.readAll();
428 TemplateDocument doc(description);
430 doc[
"name"] = index->name();
431 doc[
"shortDescription"] = filterEmptyShortDescription(index->description());
432 doc[
"latitude"] = location.latToString();
433 doc[
"longitude"] = location.lonToString();
434 doc[
"elevation"] = QString::number(location.altitude(),
'f', 2);
435 doc[
"population"] = QString::number(index->population());
436 doc[
"area"] = QString::number(index->area(),
'f', 2);
438 const QString flagPath =
MarbleDirs::path(QString(
"flags/flag_%1.svg").arg(index->countryCode().toLower()) );
439 doc[
"flag"] = flagPath;
441 popup->setContent(doc.finalText());
444 void MarbleWidgetPopupMenu::Private::setupDialogGeoPlaces(PopupLayer *popup,
const GeoDataPlacemark *index)
446 GeoDataCoordinates location = index->coordinate(m_model->clockDateTime());
447 popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter);
449 QFile descriptionFile(
":/marble/webpopup/geoplace.html");
450 if (!descriptionFile.open(QIODevice::ReadOnly)) {
454 const QString description = descriptionFile.readAll();
455 TemplateDocument doc(description);
457 doc[
"name"] = index->name();
458 doc[
"latitude"] = location.latToString();
459 doc[
"longitude"] = location.lonToString();
460 doc[
"elevation"] = QString::number(location.altitude(),
'f', 2);
461 doc[
"shortDescription"] = filterEmptyShortDescription(index->description());
463 popup->setContent(doc.finalText());
466 void MarbleWidgetPopupMenu::Private::setupDialogSkyPlaces(PopupLayer *popup,
const GeoDataPlacemark *index)
468 GeoDataCoordinates location = index->coordinate(m_model->clockDateTime());
469 popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter);
471 QFile descriptionFile(
":/marble/webpopup/skyplace.html");
472 if (!descriptionFile.open(QIODevice::ReadOnly)) {
476 const QString description = descriptionFile.readAll();
477 TemplateDocument doc(description);
479 doc[
"name"] = index->name();
484 doc[
"shortDescription"] = filterEmptyShortDescription(index->description());
486 popup->setContent(doc.finalText());
489 void MarbleWidgetPopupMenu::slotShowOrbit(
bool show )
491 QAction *action = qobject_cast<QAction *>( sender() );
493 mDebug() <<
"Warning: slotShowOrbit should be called by a QAction signal";
497 int actionidx = action->data().toInt();
499 if ( actionidx > 0 ) {
500 const GeoDataPlacemark *index = d->m_featurelist.at( actionidx -1 );
502 Qt::PenStyle penStyle = show ? Qt::SolidLine : Qt::NoPen;
503 index->style()->lineStyle().setPenStyle( penStyle );
507 void MarbleWidgetPopupMenu::slotTrackPlacemark()
509 QAction *action = qobject_cast<QAction *>( sender() );
511 mDebug() <<
"Warning: slotTrackPlacemark should be called by a QAction signal";
515 int actionidx = action->data().toInt();
517 if ( actionidx > 0 ) {
519 const GeoDataPlacemark *index = d->m_featurelist.at( actionidx -1 );
524 void MarbleWidgetPopupMenu::slotCopyCoordinates()
526 GeoDataCoordinates coordinates;
527 if ( d->mouseCoordinates( &coordinates, d->m_copyCoordinateAction ) ) {
533 const QString kmlRepresentation = QString::fromLatin1(
534 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
535 "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
540 " <coordinates>%1,%2</coordinates>\n"
545 ).arg(longitude_degrees, 0,
'f', 10).arg(latitude_degrees, 0,
'f', 10);
548 const QString gpxRepresentation = QString::fromLatin1(
549 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n"
550 "<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" creator=\"trippy\" version=\"0.1\"\n"
551 " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
552 " xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">\n"
553 " <wpt lat=\"%1\" lon=\"%2\">\n"
559 ).arg(latitude_degrees, 0,
'f', 10).arg(longitude_degrees, 0,
'f', 10);
561 QString positionString = coordinates.toString();
563 QMimeData *
const myMimeData =
new QMimeData();
564 myMimeData->setText(positionString);
565 myMimeData->setData(QLatin1String(
"application/vnd.google-earth.kml+xml"), kmlRepresentation.toUtf8());
566 myMimeData->setData(QLatin1String(
"application/gpx+xml"), gpxRepresentation.toUtf8());
568 QClipboard *
const clipboard = QApplication::clipboard();
569 clipboard->setMimeData(myMimeData);
573 void MarbleWidgetPopupMenu::slotAboutDialog()
575 MarbleAboutDialog dlg( d->m_widget );
581 if ( button == Qt::RightButton ) {
582 d->m_rmbMenu->insertAction( d->m_rmbExtensionPoint, action );
586 void MarbleWidgetPopupMenu::directionsFromHere()
588 RouteRequest* request = d->m_widget->model()->routingManager()->routeRequest();
592 if ( d->mouseCoordinates( &coordinates, d->m_copyCoordinateAction ) ) {
593 if ( request->
size() > 0 ) {
596 request->
append( coordinates );
598 d->m_widget->model()->routingManager()->retrieveRoute();
603 void MarbleWidgetPopupMenu::directionsToHere()
605 RouteRequest* request = d->m_widget->model()->routingManager()->routeRequest();
608 GeoDataCoordinates coordinates;
609 if ( d->mouseCoordinates( &coordinates, d->m_copyCoordinateAction ) ) {
610 if ( request->size() > 1 ) {
611 request->setPosition( request->size()-1, coordinates );
613 request->append( coordinates );
615 d->m_widget->model()->routingManager()->retrieveRoute();
620 bool MarbleWidgetPopupMenu::Private::mouseCoordinates( GeoDataCoordinates* coordinates, QAction* dataContainer )
622 Q_ASSERT( coordinates &&
"You must not pass 0 as coordinates parameter");
623 if ( !dataContainer ) {
628 if ( !m_featurelist.isEmpty() ) {
629 *coordinates = m_featurelist.first()->coordinate( m_model->clock()->dateTime() );
631 QPoint p = dataContainer->data().toPoint();
632 qreal lat( 0.0 ), lon( 0.0 );
636 *coordinates = GeoDataCoordinates( lon, lat );
643 void MarbleWidgetPopupMenu::startReverseGeocoding()
645 GeoDataCoordinates coordinates;
646 if ( d->mouseCoordinates( &coordinates, d->m_copyCoordinateAction ) ) {
647 d->m_runnerManager->reverseGeocoding( coordinates );
651 void MarbleWidgetPopupMenu::showAddressInformation(
const GeoDataCoordinates &,
const GeoDataPlacemark &placemark)
653 QString text = placemark.address();
654 if ( !text.isEmpty() ) {
655 QMessageBox::information( d->m_widget, tr(
"Address Details" ), text, QMessageBox::Ok );
659 void MarbleWidgetPopupMenu::addBookmark()
661 GeoDataCoordinates coordinates;
662 if ( d->mouseCoordinates( &coordinates, d->m_copyCoordinateAction ) ) {
663 QPointer<EditBookmarkDialog> dialog =
new EditBookmarkDialog( d->m_widget->model()->bookmarkManager(), d->m_widget );
664 dialog->setMarbleWidget( d->m_widget );
665 dialog->setCoordinates( coordinates );
666 dialog->setRange( d->m_widget->lookAt().range() );
667 dialog->setReverseGeocodeName();
668 if ( dialog->exec() == QDialog::Accepted ) {
669 d->m_widget->model()->bookmarkManager()->addBookmark( dialog->folder(), dialog->bookmark() );
675 void MarbleWidgetPopupMenu::toggleFullscreen(
bool enabled )
678 for ( ; parent->parentWidget(); parent = parent->parentWidget() ) {
683 parent->setWindowState( parent->windowState() | Qt::WindowFullScreen );
685 parent->setWindowState( parent->windowState() & ~Qt::WindowFullScreen );
691 return d->m_mousePosition;
696 #include "MarbleWidgetPopupMenu.moc"
int size() const
Number of points in the route.
A 3d point representation.
static QString path(const QString &relativePath)
This file contains the headers for MarbleModel.
QPixmap pixmap(int index, int size=-1, int margin=2) const
Returns a pixmap which indicates the position of the element.
void append(const GeoDataCoordinates &coordinates, const QString &name=QString())
Add the given element to the end.
Points to be included in a route.
QString latToString() const
return a string representation of latitude of the coordinate convenience function that uses the defau...
QString lonToString() const
return a string representation of longitude of the coordinate convenience function that uses the defa...
static MarbleGlobal * getInstance()
The data model (not based on QAbstractModel) for a MarbleWidget.
Profiles profiles() const
void setPosition(int index, const GeoDataCoordinates &position, const QString &name=QString())
Change the value of the element at the given position.
QDebug mDebug()
a function to replace qDebug() in Marble library code
< "RA and DEC" notation (used for astronomical sky coordinates)