42 #include <QApplication>
49 #include <QMessageBox>
54 class MarbleWidgetPopupMenu::Private {
56 const MarbleModel *
const m_model;
66 QAction *m_directionsFromHereAction;
67 QAction *m_directionsToHereAction;
69 QAction *
const m_copyCoordinateAction;
73 ReverseGeocodingRunnerManager m_runnerManager;
79 QMenu* createInfoBoxMenu();
86 GeoDataCoordinates mouseCoordinates(
QAction* dataContainer )
const;
88 static QString filterEmptyShortDescription(
const QString &description );
89 void setupDialogSatellite(
const GeoDataPlacemark *placemark );
90 static void setupDialogCity( PopupLayer *popup,
const GeoDataPlacemark *placemark );
91 static void setupDialogNation( PopupLayer *popup,
const GeoDataPlacemark *placemark );
92 static void setupDialogGeoPlaces( PopupLayer *popup,
const GeoDataPlacemark *placemark );
93 static void setupDialogSkyPlaces( PopupLayer *popup,
const GeoDataPlacemark *placemark );
96 MarbleWidgetPopupMenu::Private::Private(
MarbleWidget *widget,
const MarbleModel *model, MarbleWidgetPopupMenu* parent ) :
99 m_lmbMenu( m_widget ),
100 m_rmbMenu( m_widget ),
101 m_directionsFromHereAction( 0 ),
102 m_directionsToHereAction( 0 ),
103 m_copyCoordinateAction( new
QAction(
QIcon(
":/icons/copy-coordinates.png"), tr(
"Copy Coordinates"), parent ) ),
104 m_rmbExtensionPoint( 0 ),
105 m_runnerManager( model )
108 m_infoDialogAction =
new QAction( parent );
109 m_infoDialogAction->setData( 0 );
112 m_directionsFromHereAction =
new QAction(
tr(
"Directions &from here" ), parent );
113 m_directionsToHereAction =
new QAction(
tr(
"Directions &to here" ), parent );
114 RouteRequest* request = m_widget->model()->routingManager()->routeRequest();
116 m_directionsFromHereAction->setIcon(
QIcon( request->pixmap( 0, 16 ) ) );
117 int const lastIndex = qMax( 1, request->size()-1 );
118 m_directionsToHereAction->setIcon(
QIcon( request->pixmap( lastIndex, 16 ) ) );
121 tr(
"Add &Bookmark" ), parent );
122 QAction* fullscreenAction =
new QAction(
tr(
"&Full Screen Mode" ), parent );
127 QMenu* infoBoxMenu = createInfoBoxMenu();
129 const bool smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
131 if ( !smallScreen ) {
132 m_rmbExtensionPoint = m_rmbMenu.addSeparator();
135 m_rmbMenu.addAction( m_directionsFromHereAction );
136 m_rmbMenu.addAction( m_directionsToHereAction );
137 m_rmbMenu.addSeparator();
138 m_rmbMenu.addAction( addBookmark );
139 if ( !smallScreen ) {
140 m_rmbMenu.addAction( m_copyCoordinateAction );
142 m_rmbMenu.addAction(
QIcon(
":/icons/addressbook-details.png"),
tr(
"&Address Details" ), parent, SLOT(startReverseGeocoding()) );
143 m_rmbMenu.addSeparator();
144 m_rmbMenu.addMenu( infoBoxMenu );
146 if ( !smallScreen ) {
147 m_rmbMenu.addAction( aboutDialogAction );
149 m_rmbMenu.addAction( fullscreenAction );
152 parent->connect( &m_lmbMenu, SIGNAL(aboutToHide()), SLOT(resetMenu()) );
153 parent->connect( m_directionsFromHereAction, SIGNAL(triggered()), SLOT(directionsFromHere()) );
154 parent->connect( m_directionsToHereAction, SIGNAL(triggered()), SLOT(directionsToHere()) );
155 parent->connect( addBookmark, SIGNAL(triggered()), SLOT(addBookmark()) );
156 parent->connect( aboutDialogAction, SIGNAL(triggered()), SLOT(slotAboutDialog()) );
157 parent->connect( m_copyCoordinateAction, SIGNAL(triggered()), SLOT(slotCopyCoordinates()) );
158 parent->connect( m_infoDialogAction, SIGNAL(triggered()), SLOT(slotInfoDialog()) );
159 parent->connect( fullscreenAction, SIGNAL(triggered(
bool)), parent, SLOT(toggleFullscreen(
bool)) );
161 parent->connect( &m_runnerManager, SIGNAL(reverseGeocodingFinished(GeoDataCoordinates,GeoDataPlacemark)),
162 parent, SLOT(showAddressInformation(GeoDataCoordinates,GeoDataPlacemark)) );
165 QString MarbleWidgetPopupMenu::Private::filterEmptyShortDescription(
const QString &description)
168 return tr(
"No description available.");
172 void MarbleWidgetPopupMenu::Private::setupDialogSatellite(
const GeoDataPlacemark *placemark )
174 PopupLayer *
const popup = m_widget->popupLayer();
175 const GeoDataCoordinates location = placemark->coordinate(m_widget->model()->clockDateTime());
176 popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter);
178 const QString description = placemark->description();
179 TemplateDocument doc(description);
181 doc[
"latitude"] = location.latToString();
182 doc[
"longitude"] = location.lonToString();
183 popup->setContent(doc.finalText());
186 void MarbleWidgetPopupMenu::Private::setupDialogCity( PopupLayer *popup,
const GeoDataPlacemark *placemark )
188 const GeoDataCoordinates location = placemark->coordinate();
189 popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter);
191 QFile descriptionFile(
":/marble/webpopup/city.html");
192 if (!descriptionFile.open(QIODevice::ReadOnly)) {
196 const QString description = descriptionFile.readAll();
197 TemplateDocument doc(description);
199 doc[
"name"] = placemark->name();
201 const QString role = placemark->role();
203 roleString = tr(
"National Capital");
204 }
else if(role==
"PPL") {
205 roleString = tr(
"City");
206 }
else if(role==
"PPLA") {
207 roleString = tr(
"State Capital");
208 }
else if(role==
"PPLA2") {
209 roleString = tr(
"County Capital");
210 }
else if(role==
"PPLA3" || role==
"PPLA4" ) {
211 roleString = tr(
"Capital");
212 }
else if(role==
"PPLF" || role==
"PPLG" || role==
"PPLL" || role==
"PPLQ" ||
213 role==
"PPLR" || role==
"PPLS" || role==
"PPLW" ) {
214 roleString = tr(
"Village");
217 doc[
"category"] = roleString;
218 doc[
"shortDescription"] = filterEmptyShortDescription(placemark->description());
219 doc[
"latitude"] = location.latToString();
220 doc[
"longitude"] = location.lonToString();
223 doc[
"country"] = placemark->countryCode();
224 doc[
"state"] = placemark->state();
226 QString dst =
QString(
"%1" ).
arg( ( placemark->extendedData().value(
"gmt").value().toInt() +
227 placemark->extendedData().value(
"dst").value().toInt() ) /
228 (
double ) 100, 0,
'f', 1 );
233 doc[
"timezone"] = dst;
235 doc[
"timezone"] =
'+'+dst;
238 const QString flagPath = MarbleDirs::path(
239 QString(
"flags/flag_%1.svg").arg(placemark->countryCode().toLower()));
240 doc[
"flag"] = flagPath;
242 popup->setContent(doc.finalText());
245 void MarbleWidgetPopupMenu::Private::setupDialogNation( PopupLayer *popup,
const GeoDataPlacemark *index)
247 const GeoDataCoordinates location = index->coordinate();
248 popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter);
250 QFile descriptionFile(
":/marble/webpopup/nation.html");
251 if (!descriptionFile.open(QIODevice::ReadOnly)) {
255 const QString description = descriptionFile.readAll();
256 TemplateDocument doc(description);
258 doc[
"name"] = index->name();
259 doc[
"shortDescription"] = filterEmptyShortDescription(index->description());
260 doc[
"latitude"] = location.latToString();
261 doc[
"longitude"] = location.lonToString();
266 const QString flagPath = MarbleDirs::path(
QString(
"flags/flag_%1.svg").arg(index->countryCode().toLower()) );
267 doc[
"flag"] = flagPath;
269 popup->setContent(doc.finalText());
272 void MarbleWidgetPopupMenu::Private::setupDialogGeoPlaces( PopupLayer *popup,
const GeoDataPlacemark *index)
274 const GeoDataCoordinates location = index->coordinate();
275 popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter);
277 QFile descriptionFile(
":/marble/webpopup/geoplace.html");
278 if (!descriptionFile.open(QIODevice::ReadOnly)) {
282 const QString description = descriptionFile.readAll();
283 TemplateDocument doc(description);
285 doc[
"name"] = index->name();
286 doc[
"latitude"] = location.latToString();
287 doc[
"longitude"] = location.lonToString();
289 doc[
"shortDescription"] = filterEmptyShortDescription(index->description());
291 popup->setContent(doc.finalText());
294 void MarbleWidgetPopupMenu::Private::setupDialogSkyPlaces( PopupLayer *popup,
const GeoDataPlacemark *index)
296 const GeoDataCoordinates location = index->coordinate();
297 popup->setCoordinates(location, Qt::AlignRight | Qt::AlignVCenter);
299 QFile descriptionFile(
":/marble/webpopup/skyplace.html");
300 if (!descriptionFile.open(QIODevice::ReadOnly)) {
304 const QString description = descriptionFile.readAll();
305 TemplateDocument doc(description);
307 doc[
"name"] = index->name();
308 doc[
"latitude"] = GeoDataCoordinates::latToString(
309 location.latitude(), GeoDataCoordinates::Astro, GeoDataCoordinates::Radian, -1,
'f');
310 doc[
"longitude"] = GeoDataCoordinates::lonToString(
311 location.longitude(), GeoDataCoordinates::Astro, GeoDataCoordinates::Radian, -1,
'f');
312 doc[
"shortDescription"] = filterEmptyShortDescription(index->description());
314 popup->setContent(doc.finalText());
320 d( new Private( widget, model, this ) )
330 QMenu* MarbleWidgetPopupMenu::Private::createInfoBoxMenu()
332 QMenu* menu =
new QMenu( tr(
"&Info Boxes" ) );
337 for (; iter != end; ++iter )
352 d->m_mousePosition.setX(xpos);
353 d->m_mousePosition.setY(ypos);
356 d->m_featurelist = d->m_widget->whichFeatureAt( curpos );
362 for (; it != itEnd; ++it )
366 d->m_infoDialogAction->setData( actionidx );
367 d->m_infoDialogAction->setText( name );
368 d->m_infoDialogAction->setIcon( icon );
371 if( !d->m_lmbMenu.actions().isEmpty() ) {
372 firstAction = d->m_lmbMenu.actions().first();
374 d->m_lmbMenu.insertAction( firstAction, d->m_infoDialogAction );
378 d->m_itemList = d->m_widget->whichItemAt( curpos );
381 for (; itW != itWEnd; ++itW )
383 foreach (
QAction* action, (*itW)->actions() ) {
384 d->m_lmbMenu.addAction( action );
388 switch ( d->m_lmbMenu.actions().size() ) {
393 d->m_lmbMenu.actions().first()->activate( QAction::Trigger );
394 d->m_lmbMenu.clear();
398 d->m_lmbMenu.popup( d->m_widget->mapToGlobal( curpos ) );
406 const bool visible = d->m_widget->geoCoordinates( xpos, ypos, lon, lat, GeoDataCoordinates::Radian );
410 d->m_mousePosition.setX(xpos);
411 d->m_mousePosition.setY(ypos);
414 d->m_copyCoordinateAction->setData( curpos );
416 bool const showDirectionButtons = d->m_widget->routingLayer() && d->m_widget->routingLayer()->isInteractive();
417 d->m_directionsFromHereAction->setVisible( showDirectionButtons );
418 d->m_directionsToHereAction->setVisible( showDirectionButtons );
419 RouteRequest* request = d->m_widget->model()->routingManager()->routeRequest();
421 int const lastIndex = qMax( 1, request->
size()-1 );
422 d->m_directionsToHereAction->setIcon(
QIcon( request->
pixmap( lastIndex, 16 ) ) );
425 d->m_rmbMenu.popup( d->m_widget->mapToGlobal( curpos ) );
428 void MarbleWidgetPopupMenu::resetMenu()
430 d->m_lmbMenu.clear();
433 void MarbleWidgetPopupMenu::slotInfoDialog()
437 mDebug() <<
"Warning: slotInfoDialog should be called by a QAction signal";
443 if ( actionidx > 0 ) {
444 const GeoDataPlacemark *placemark = d->m_featurelist.at( actionidx -1 );
445 PopupLayer* popup = d->m_widget->popupLayer();
451 if ( d->m_widget->model()->mapTheme() ) {
452 isSky = d->m_widget->model()->mapTheme()->head()->target() ==
"sky";
454 popup->setSize(
QSizeF(400, 400));
456 d->setupDialogSatellite( placemark );
458 Private::setupDialogCity( popup, placemark );
459 }
else if (isNation) {
460 Private::setupDialogNation( popup, placemark );
462 Private::setupDialogSkyPlaces( popup, placemark );
463 }
else if ( placemark->role().isEmpty() ) {
464 popup->setContent( placemark->description() );
466 Private::setupDialogGeoPlaces( popup, placemark );
469 if (placemark->style() == 0) {
470 popup->setBackgroundColor(
QColor(Qt::white));
471 popup->setTextColor(
QColor(Qt::black));
475 popup->setVisible(
false);
479 QString content = placemark->style()->balloonStyle().text();
480 if (content.
length() > 0) {
481 content = content.
replace(
"$[name]", placemark->name(), Qt::CaseInsensitive);
482 content = content.
replace(
"$[description]", placemark->description(), Qt::CaseInsensitive);
483 content = content.
replace(
"$[address]", placemark->address(), Qt::CaseInsensitive);
485 content = content.
replace(
"$[snippet]", placemark->snippet().text(), Qt::CaseInsensitive);
486 content = content.
replace(
"$[id]", placemark->id(), Qt::CaseInsensitive);
487 QString const basePath = placemark->resolvePath(
".");
489 popup->setContent(content, baseUrl );
491 popup->setBackgroundColor(placemark->style()->balloonStyle().backgroundColor());
492 popup->setTextColor(placemark->style()->balloonStyle().textColor());
497 void MarbleWidgetPopupMenu::slotCopyCoordinates()
499 const GeoDataCoordinates coordinates = d->mouseCoordinates( d->m_copyCoordinateAction );
500 if ( coordinates.isValid() ) {
507 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
508 "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
513 " <coordinates>%1,%2</coordinates>\n"
518 ).
arg(longitude_degrees, 0,
'f', 10).
arg(latitude_degrees, 0,
'f', 10);
522 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n"
523 "<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" creator=\"trippy\" version=\"0.1\"\n"
524 " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
525 " xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">\n"
526 " <wpt lat=\"%1\" lon=\"%2\">\n"
532 ).
arg(latitude_degrees, 0,
'f', 10).
arg(longitude_degrees, 0,
'f', 10);
534 QString positionString = coordinates.toString();
537 myMimeData->
setText(positionString);
546 void MarbleWidgetPopupMenu::slotAboutDialog()
555 if ( button == Qt::RightButton ) {
556 d->m_rmbMenu.insertAction( d->m_rmbExtensionPoint, action );
558 d->m_lmbMenu.addAction( action );
562 void MarbleWidgetPopupMenu::directionsFromHere()
564 RouteRequest* request = d->m_widget->model()->routingManager()->routeRequest();
567 const GeoDataCoordinates coordinates = d->mouseCoordinates( d->m_copyCoordinateAction );
569 if ( request->
size() > 0 ) {
572 request->
append( coordinates );
574 d->m_widget->model()->routingManager()->retrieveRoute();
579 void MarbleWidgetPopupMenu::directionsToHere()
581 RouteRequest* request = d->m_widget->model()->routingManager()->routeRequest();
584 const GeoDataCoordinates coordinates = d->mouseCoordinates( d->m_copyCoordinateAction );
585 if ( coordinates.isValid() ) {
586 if ( request->size() > 1 ) {
587 request->setPosition( request->size()-1, coordinates );
589 request->append( coordinates );
591 d->m_widget->model()->routingManager()->retrieveRoute();
596 GeoDataCoordinates MarbleWidgetPopupMenu::Private::mouseCoordinates(
QAction* dataContainer )
const
598 if ( !dataContainer ) {
599 return GeoDataCoordinates();
602 if ( !m_featurelist.isEmpty() ) {
603 return m_featurelist.first()->coordinate( m_model->clock()->dateTime() );
606 qreal lat( 0.0 ), lon( 0.0 );
610 return GeoDataCoordinates( lon, lat );
614 return GeoDataCoordinates();
617 void MarbleWidgetPopupMenu::startReverseGeocoding()
619 const GeoDataCoordinates coordinates = d->mouseCoordinates( d->m_copyCoordinateAction );
620 if ( coordinates.isValid() ) {
621 d->m_runnerManager.reverseGeocoding( coordinates );
625 void MarbleWidgetPopupMenu::showAddressInformation(
const GeoDataCoordinates &,
const GeoDataPlacemark &placemark)
627 QString text = placemark.address();
633 void MarbleWidgetPopupMenu::addBookmark()
635 const GeoDataCoordinates coordinates = d->mouseCoordinates( d->m_copyCoordinateAction );
636 if ( coordinates.isValid() ) {
638 dialog->setMarbleWidget( d->m_widget );
639 dialog->setCoordinates( coordinates );
640 dialog->setRange( d->m_widget->lookAt().range() );
641 dialog->setReverseGeocodeName();
642 if ( dialog->exec() == QDialog::Accepted ) {
643 d->m_widget->model()->bookmarkManager()->addBookmark( dialog->folder(), dialog->bookmark() );
649 void MarbleWidgetPopupMenu::toggleFullscreen(
bool enabled )
665 return d->m_mousePosition;
670 #include "MarbleWidgetPopupMenu.moc"
int size() const
Number of points in the route.
A 3d point representation.
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.
QPixmap fromImage(const QImage &image, QFlags< Qt::ImageConversionFlag > flags)
void append(const GeoDataCoordinates &coordinates, const QString &name=QString())
Add the given element to the end.
QString tr(const char *sourceText, const char *disambiguation, int n)
Points to be included in a route.
const char * name() const
QString number(int n, int base)
int toInt(bool *ok) const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
void setText(const QString &text)
void setMimeData(QMimeData *src, Mode mode)
static MarbleGlobal * getInstance()
QString & replace(int position, int n, QChar after)
The data model (not based on QAbstractModel) for a MarbleWidget.
Profiles profiles() const
QString fromLatin1(const char *str, int size)
void setPosition(int index, const GeoDataCoordinates &position, const QString &name=QString())
Change the value of the element at the given position.
void setData(const QString &mimeType, const QByteArray &data)
const_iterator constEnd() const
bool isValid() const
Returns.
const_iterator constBegin() const
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QDebug mDebug()
a function to replace qDebug() in Marble library code
QUrl fromLocalFile(const QString &localFile)
QByteArray toUtf8() const