Marble

MapWizard.cpp
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2011 Utku Aydın <[email protected]>
4 //
5 
6 #include "MapWizard.h"
7 #include "ui_MapWizard.h"
8 
9 #include "MarbleGlobal.h"
10 #include "MarbleDirs.h"
11 #include "MarbleDebug.h"
12 #include "ServerLayout.h"
13 #include "GeoSceneDocument.h"
14 #include "GeoSceneHead.h"
15 #include "GeoSceneIcon.h"
16 #include "GeoSceneZoom.h"
17 #include "GeoSceneMap.h"
18 #include "GeoSceneLayer.h"
19 #include "GeoSceneTileDataset.h"
20 #include "GeoSceneSettings.h"
21 #include "GeoSceneProperty.h"
22 #include "GeoSceneGeodata.h"
23 #include "GeoSceneLegend.h"
24 #include "GeoSceneSection.h"
25 #include "GeoSceneItem.h"
26 #include "GeoSceneVector.h"
27 #include "GeoWriter.h"
28 #include "DgmlElementDictionary.h"
29 #include "MarbleWidget.h"
30 #include "MarbleNavigator.h"
31 
32 #include <QBuffer>
33 #include <QDir>
34 #include <QFile>
35 #include <QProcess>
36 #include <QSharedPointer>
37 #include <QTimer>
38 #include <QPixmap>
39 #include <QMessageBox>
40 #include <QFileDialog>
41 #include <QImageReader>
42 #include <QDialogButtonBox>
43 #include <QNetworkAccessManager>
44 #include <QNetworkReply>
45 #include <QNetworkRequest>
46 #include <QDomElement>
47 #include <QXmlStreamWriter>
48 #include <QUrlQuery>
49 
50 namespace Marble
51 {
52 
53 class MapWizardPrivate
54 {
55 public:
56  MapWizardPrivate()
57  : m_serverCapabilitiesValid( false ),
58  mapProviderType()
59  {}
60 
61  void pageEntered( int id );
62 
63  Ui::MapWizard uiWidget;
64 
65  QString mapTheme;
66 
67  QNetworkAccessManager xmlAccessManager;
68  QNetworkAccessManager legendAccessManager;
69  QNetworkAccessManager levelZeroAccessManager;
70  QStringList wmsServerList;
71  QMap<QString, QString> wmsFetchedMaps;
72  QStringList staticUrlServerList;
73  bool m_serverCapabilitiesValid;
74 
75  enum mapType
76  {
77  NoMap,
78  StaticImageMap,
79  WmsMap,
80  StaticUrlMap
81  };
82 
83  mapType mapProviderType;
84  QByteArray levelZero;
85  QImage previewImage;
86 
87  QString format;
88 
89  QStringList wmsLegends;
90 
91  QString sourceImage;
92 };
93 
94 class PreviewDialog : public QDialog
95 {
96  Q_OBJECT
97 public:
98  PreviewDialog( QWidget* parent, const QString& mapThemeId );
99  void closeEvent(QCloseEvent* e ) override;
100 private:
101  bool deleteTheme( const QString& directory );
102  QString m_mapThemeId;
103 };
104 
105 PreviewDialog::PreviewDialog( QWidget* parent, const QString& mapThemeId ) : QDialog( parent ), m_mapThemeId( mapThemeId )
106 {
107  QGridLayout *layout = new QGridLayout();
108  MarbleWidget *widget = new MarbleWidget();
109  MarbleNavigator *navigator = new MarbleNavigator();
110 
111  connect( navigator, SIGNAL(goHome()), widget, SLOT(goHome()) );
112  connect( navigator, SIGNAL(moveUp()), widget, SLOT(moveUp()) );
113  connect( navigator, SIGNAL(moveDown()), widget, SLOT(moveDown()) );
114  connect( navigator, SIGNAL(moveLeft()), widget, SLOT(moveLeft()) );
115  connect( navigator, SIGNAL(moveRight()), widget, SLOT(moveRight()) );
116  connect( navigator, SIGNAL(zoomIn()), widget, SLOT(zoomIn()) );
117  connect( navigator, SIGNAL(zoomOut()), widget, SLOT(zoomOut()) );
118  connect( navigator, SIGNAL(zoomChanged(int)), widget, SLOT(setZoom(int)) );
119 
120  widget->setMapThemeId( m_mapThemeId );
121  widget->setZoom( 1000 );
122 
123  layout->addWidget( navigator, 1, 1 );
124  layout->addWidget( widget, 1, 2 );
125  layout->setMargin( 0 );
126  layout->setSpacing( 0 );
127 
128  this->setLayout( layout );
129  this->setMinimumSize( 640, 480 );
130  this->setWindowTitle( tr( "Preview Map" ) );
131 }
132 
133 void PreviewDialog::closeEvent(QCloseEvent* e)
134 {
135  const QString dgmlPath = MarbleDirs::localPath() + QLatin1String("/maps/") + m_mapThemeId;
136  const QString directory = dgmlPath.left(dgmlPath.lastIndexOf(QLatin1Char('/')));
137  this->deleteTheme( directory );
138  QDialog::closeEvent( e );
139 }
140 
141 bool PreviewDialog::deleteTheme( const QString &directory )
142 {
143  QDir dir(directory);
144  bool result = true;
145 
146  if (dir.exists(directory)) {
148  if (info.isDir()) {
149  result = deleteTheme(info.absoluteFilePath());
150  } else {
151  result = QFile::remove(info.absoluteFilePath());
152  }
153 
154  if (!result) {
155  return result;
156  }
157  }
158  result = dir.rmdir(directory);
159  }
160 
161  return result;
162 }
163 
164 void MapWizardPrivate::pageEntered( int id )
165 {
166  if ( id == 1 ) {
167  m_serverCapabilitiesValid = false;
168  } else if ( id == 2 || id == 4 ) {
169  levelZero.clear();
170  uiWidget.comboBoxStaticUrlServer->clear();
171  uiWidget.comboBoxStaticUrlServer->addItems( staticUrlServerList );
172  uiWidget.comboBoxStaticUrlServer->addItem( "http://" );
173  } else if ( id == 5 ) {
174  if ( mapProviderType == MapWizardPrivate::StaticImageMap ) {
175  previewImage = QImage( uiWidget.lineEditSource->text() ).scaled( 136, 136, Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
176  } else {
177  previewImage = QImage::fromData( levelZero ).scaled( 136, 136, Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
178  }
179  uiWidget.labelPreview->setPixmap( QPixmap::fromImage( previewImage ) );
180  } else if ( id == 7 ) {
181  uiWidget.labelThumbnail->setPixmap( QPixmap::fromImage( previewImage ) );
182  }
183 }
184 
185 MapWizard::MapWizard( QWidget* parent ) : QWizard( parent ), d( new MapWizardPrivate )
186 {
187  d->uiWidget.setupUi( this );
188 
189  connect( this, SIGNAL(currentIdChanged(int)), this, SLOT(pageEntered(int)) );
190 
191  connect( &( d->xmlAccessManager ), SIGNAL(finished(QNetworkReply*)), this, SLOT(parseServerCapabilities(QNetworkReply*)) );
192  connect( &( d->legendAccessManager ), SIGNAL(finished(QNetworkReply*)), this, SLOT(createWmsLegend(QNetworkReply*)) );
193  connect( &( d->levelZeroAccessManager ), SIGNAL(finished(QNetworkReply*)), this, SLOT(createLevelZero(QNetworkReply*)) );
194 
195  connect( d->uiWidget.pushButtonSource, SIGNAL(clicked(bool)), this, SLOT(querySourceImage()) );
196  connect( d->uiWidget.pushButtonPreview, SIGNAL(clicked(bool)), this, SLOT(queryPreviewImage()) );
197  connect( d->uiWidget.pushButtonLegend_2, SIGNAL(clicked(bool)), this, SLOT(queryLegendImage()) );
198 
199  connect( d->uiWidget.comboBoxWmsServer, SIGNAL(currentIndexChanged(QString)), d->uiWidget.lineEditWmsUrl, SLOT(setText(QString)) );
200  connect( d->uiWidget.listWidgetWmsMaps, SIGNAL(itemSelectionChanged()), this, SLOT(autoFillDetails()) );
201 
202  connect( d->uiWidget.lineEditTitle, SIGNAL(textChanged(QString)), d->uiWidget.labelSumMName, SLOT(setText(QString)) );
203  connect( d->uiWidget.lineEditTheme, SIGNAL(textChanged(QString)), d->uiWidget.labelSumMTheme, SLOT(setText(QString)) );
204 
205  connect( d->uiWidget.pushButtonPreviewMap, SIGNAL(clicked(bool)), this, SLOT(showPreview()) );
206 
207 }
208 
209 MapWizard::~MapWizard()
210 {
211  delete d;
212 }
213 
214 void MapWizard::queryServerCapabilities()
215 {
216  QUrl url( d->uiWidget.lineEditWmsUrl->text() );
217  QUrlQuery urlQuery;
218  urlQuery.addQueryItem( "service", "WMS" );
219  urlQuery.addQueryItem( "request", "GetCapabilities" );
220  url.setQuery(urlQuery);
221 
222  QNetworkRequest request;
223  request.setUrl( url );
225 
226  mDebug() << "for url" << url;
227  d->xmlAccessManager.get( request );
228 }
229 
230 void MapWizard::parseServerCapabilities( QNetworkReply* reply )
231 {
232  button( MapWizard::NextButton )->setEnabled( true );
233 
234  mDebug() << "received reply from" << reply->url();
235  QString result( reply->readAll() );
236  QDomDocument xml;
237  if( !xml.setContent( result ) )
238  {
239  QMessageBox::critical( this, tr( "Error while parsing" ), tr( "Wizard cannot parse server's response" ) );
240  return;
241  }
242 
244  {
245  QMessageBox::critical( this, tr( "Error while parsing" ), tr( "Server is not a Web Map Server." ) );
246  return;
247  }
248 
249  QDomElement firstLayer = xml.documentElement().firstChildElement( "Capability" ).firstChildElement( "Layer" );
250  QDomNodeList layers = firstLayer.elementsByTagName( "Layer" );
251 
252  d->uiWidget.listWidgetWmsMaps->clear();
253  d->wmsFetchedMaps.clear();
254 
255  for( int i = 0; i < layers.size(); ++i )
256  {
257  QString theme = layers.at( i ).firstChildElement( "Name" ).text();
258  QString title = layers.at( i ).firstChildElement( "Title" ).text();
259  QDomElement legendUrl = layers.at( i ).firstChildElement( "Style" ).firstChildElement( "LegendURL" );
260  d->wmsFetchedMaps[ theme ] = title;
261 
262  d->wmsLegends.clear();
263  if( legendUrl.isNull() ) {
264  d->wmsLegends.append( QString() );
265  } else {
266  d->wmsLegends.append( legendUrl.firstChildElement( "OnlineResource" ).attribute( "xlink:href" ) );
267  }
268  }
269 
270  d->uiWidget.listWidgetWmsMaps->addItems( d->wmsFetchedMaps.values() );
271 
272  QDomElement format = xml.documentElement().firstChildElement( "Capability" ).firstChildElement( "Request" )
273  .firstChildElement( "GetMap" ).firstChildElement( "Format" );
274 
275  d->format = format.text().right(format.text().length() - format.text().indexOf(QLatin1Char('/')) - 1).toLower();
276 
277  if (d->format == QLatin1String("jpeg")) {
278  d->format = "jpg";
279  }
280 
281  if( !d->wmsFetchedMaps.isEmpty() && !d->wmsServerList.contains( d->uiWidget.lineEditWmsUrl->text() ) ) {
282  d->wmsServerList.append( d->uiWidget.lineEditWmsUrl->text() );
283  setWmsServers( d->wmsServerList );
284  }
285 
286  d->m_serverCapabilitiesValid = true;
287  next();
288 }
289 
290 void MapWizard::createWmsLegend( QNetworkReply* reply )
291 {
292  QByteArray result( reply->readAll() );
293  QDir map(MarbleDirs::localPath() + QLatin1String("/maps/earth/") + d->mapTheme);
294  if( !map.exists( "legend" ) ) {
295  map.mkdir( "legend" );
296  }
297 
298  QFile image(map.absolutePath() + QLatin1String("/legend/legend.png"));
299  image.open( QIODevice::ReadWrite );
300  image.write( result );
301  image.close();
302 
303  const QString legendHtml = createLegendHtml();
304  createLegendFile( legendHtml );
305 }
306 
307 void MapWizard::setWmsServers( const QStringList& uris )
308 {
309  d->wmsServerList = uris;
310 
311  d->uiWidget.comboBoxWmsServer->clear();
312  d->uiWidget.comboBoxWmsServer->addItems( d->wmsServerList );
313  d->uiWidget.comboBoxWmsServer->addItem( tr( "Custom" ), "http://" );
314 }
315 
316 QStringList MapWizard::wmsServers() const
317 {
318  return d->wmsServerList;
319 }
320 
321 QStringList MapWizard::staticUrlServers() const
322 {
323  return d->staticUrlServerList;
324 }
325 
326 void MapWizard::setStaticUrlServers( const QStringList& uris )
327 {
328  d->staticUrlServerList = uris;
329 }
330 
331 void MapWizard::autoFillDetails()
332 {
333  QString selected = d->uiWidget.listWidgetWmsMaps->currentItem()->text();
334  d->uiWidget.lineEditTitle->setText( selected );
335  d->uiWidget.lineEditTheme->setText( d->wmsFetchedMaps.key( selected ) );
336 }
337 
338 bool MapWizard::createFiles( const GeoSceneDocument* document )
339 {
340  // Create directories
341  QDir maps(MarbleDirs::localPath() + QLatin1String("/maps/earth/"));
342  if( !maps.exists( document->head()->theme() ) )
343  {
344  maps.mkdir( document->head()->theme() );
345 
346  if( d->mapProviderType == MapWizardPrivate::StaticImageMap )
347  {
348  // Source image
349  QFile sourceImage( d->sourceImage );
350  d->format = d->sourceImage.right(d->sourceImage.length() - d->sourceImage.lastIndexOf(QLatin1Char('.')) - 1).toLower();
351  sourceImage.copy( QString( "%1/%2/%2.%3" ).arg( maps.absolutePath() )
352  .arg( document->head()->theme() )
353  .arg( d->format ) );
354  }
355 
356  else if( d->mapProviderType == MapWizardPrivate::WmsMap )
357  {
358  maps.mkdir( QString( "%1/0/" ).arg( document->head()->theme() ) );
359  maps.mkdir( QString( "%1/0/0" ).arg( document->head()->theme() ) );
360  const QString path = QString( "%1/%2/0/0/0.%3" ).arg( maps.absolutePath() )
361  .arg( document->head()->theme() )
362  .arg( d->format );
363  QFile baseTile( path );
364  baseTile.open( QFile::WriteOnly );
365  baseTile.write( d->levelZero );
366  }
367 
368  else if( d->mapProviderType == MapWizardPrivate::StaticUrlMap )
369  {
370  maps.mkdir( QString( "%1/0/" ).arg( document->head()->theme() ) );
371  maps.mkdir( QString( "%1/0/0" ).arg( document->head()->theme() ) );
372  const QString path = QString( "%1/%2/0/0/0.%3" ).arg( maps.absolutePath() )
373  .arg( document->head()->theme() )
374  .arg( d->format );
375  QFile baseTile( path );
376  baseTile.open( QFile::WriteOnly );
377  baseTile.write( d->levelZero );
378  }
379 
380  // Preview image
381  QString pixmapPath = QString( "%1/%2/%3" ).arg( maps.absolutePath() )
382  .arg( document->head()->theme() )
383  .arg( document->head()->icon()->pixmap() );
384  d->previewImage.save( pixmapPath );
385 
386  // DGML
387  QFile file( QString( "%1/%2/%2.dgml" ).arg( maps.absolutePath() )
388  .arg( document->head()->theme() ) );
389  file.open( QIODevice::ReadWrite );
390  GeoWriter geoWriter;
391  geoWriter.setDocumentType( dgml::dgmlTag_nameSpace20 );
392  geoWriter.write( &file, document );
393  file.close();
394 
395  return true;
396  }
397 
398  else
399  return false;
400 }
401 
402 QString MapWizard::createLegendHtml( const QString& image )
403 {
404  QString htmlOutput;
405  QXmlStreamWriter stream( &htmlOutput );
406  stream.writeStartDocument();
407  stream.writeStartElement( "html" );
408  stream.writeStartElement( "head" );
409 
410  stream.writeTextElement( "title", "Marble: Legend" );
411  stream.writeStartElement( "link" );
412  stream.writeAttribute( "href", "legend.css" );
413  stream.writeAttribute( "rel", "stylesheet" );
414  stream.writeAttribute( "type", "text/css" );
415  stream.writeEndElement();
416 
417  stream.writeStartElement( "body" );
418  stream.writeStartElement( "img" );
419  stream.writeAttribute( "src", image );
420  stream.writeEndElement();
421  stream.writeComment( " ##customLegendEntries:all## " );
422  stream.writeEndElement();
423  stream.writeEndElement();
424 
425  return htmlOutput;
426 }
427 
428 void MapWizard::createLegendFile( const QString& legendHtml )
429 {
430  QDir map(MarbleDirs::localPath() + QLatin1String("/maps/earth/") + d->mapTheme);
431 
432  QFile html(map.absolutePath() + QLatin1String("/legend.html"));
433  html.open( QIODevice::ReadWrite );
434  html.write( legendHtml.toLatin1().data() );
435  html.close();
436 }
437 
438 void MapWizard::downloadLegend( const QString& url )
439 {
440  QUrl downloadUrl( url );
441  QNetworkRequest request( downloadUrl );
442  d->legendAccessManager.get( request );
443 }
444 
445 void MapWizard::downloadLevelZero()
446 {
447  if( d->mapProviderType == MapWizardPrivate::WmsMap )
448  {
449  QString selected = d->uiWidget.listWidgetWmsMaps->currentItem()->text();
450 
451  QUrl finalDownloadUrl( d->uiWidget.lineEditWmsUrl->text() );
452  QUrlQuery downloadUrl;
453  downloadUrl.addQueryItem( "request", "GetMap" );
454  downloadUrl.addQueryItem( "version", "1.1.1" );
455  downloadUrl.addQueryItem( "layers", d->wmsFetchedMaps.key( selected ) );
456  downloadUrl.addQueryItem( "srs", "EPSG:4326" );
457  downloadUrl.addQueryItem( "width", "400" );
458  downloadUrl.addQueryItem( "height", "200" );
459  downloadUrl.addQueryItem( "bbox", "-180,-90,180,90" );
460  downloadUrl.addQueryItem( "format", "image/jpeg" );
461  downloadUrl.addQueryItem( "styles", "" );
462 
463  finalDownloadUrl.setQuery( downloadUrl );
464  mDebug() << "requesting WMS" << finalDownloadUrl;
465 
466  QNetworkRequest request( finalDownloadUrl );
467 
468  d->levelZeroAccessManager.get( request );
469  }
470 
471  else if( d->mapProviderType == MapWizardPrivate::StaticUrlMap )
472  {
473  QString server = d->uiWidget.comboBoxStaticUrlServer->currentText();
474  QUrl downloadUrl;
475 
476  server.replace(server.indexOf(QLatin1String("{x}")), 3, QString::number(0));
477  server.replace(server.indexOf(QLatin1String("{y}")), 3, QString::number(0));
478  server.replace(server.indexOf(QLatin1String("{zoomLevel}")), 11, QString::number(0));
479  downloadUrl.setUrl( server );
480 
481  QNetworkRequest request( downloadUrl );
482  mDebug() << "requesting static map" << downloadUrl;
483  d->levelZeroAccessManager.get( request );
484  }
485 }
486 
487 void MapWizard::createLevelZero( QNetworkReply* reply )
488 {
489  button( MapWizard::NextButton )->setEnabled( true );
490 
491  d->levelZero = reply->readAll();
492  QImage testImage = QImage::fromData( d->levelZero );
493 
494  if ( d->levelZero.isNull() ) {
496  tr( "Base Tile" ),
497  tr( "The base tile could not be downloaded." ) );
498  return;
499  }
500 
501  if ( testImage.isNull() ) {
503  tr( "Base Tile" ),
504  tr( "The base tile could not be downloaded successfully. The server replied:\n\n%1" ).arg( QString( d->levelZero ) ) );
505  d->levelZero.clear();
506  return;
507  }
508 
509  QBuffer testBuffer( &d->levelZero );
510  d->format = QImageReader( &testBuffer ).format();
511 
512  if ( d->mapProviderType == MapWizardPrivate::StaticUrlMap ) {
513  const QString url = d->uiWidget.comboBoxStaticUrlServer->currentText();
514  d->staticUrlServerList.removeAll( url );
515  d->staticUrlServerList.prepend( url );
516  }
517 
518  next();
519 }
520 
521 void MapWizard::createLegend()
522 {
523  QDir map(MarbleDirs::localPath() + QLatin1String("/maps/earth/") + d->mapTheme);
524  if( !map.exists( "legend" ) ) {
525  map.mkdir( "legend" );
526  }
527 
528  QFile image;
529  image.setFileName( d->uiWidget.lineEditLegend_2->text() );
530  image.copy(map.absolutePath() + QLatin1String("/legend/legend.png"));
531 
532  const QString legendHtml = createLegendHtml();
533  createLegendFile( legendHtml );
534 }
535 
536 void MapWizard::querySourceImage()
537 {
538  d->uiWidget.lineEditSource->setText( QFileDialog::getOpenFileName() );
539 }
540 
541 void MapWizard::queryPreviewImage()
542 {
544  d->previewImage = QImage( fileName );
545 
546  QPixmap preview = QPixmap::fromImage( d->previewImage );
547  d->uiWidget.labelThumbnail->setPixmap( preview );
548  d->uiWidget.labelThumbnail->resize( preview.width(), preview.height() );
549 }
550 
551 void MapWizard::queryLegendImage()
552 {
554  d->uiWidget.lineEditLegend_2->setText( fileName );
555  const QString legendHtml = createLegendHtml( d->uiWidget.lineEditLegend_2->text() );
556  d->uiWidget.textBrowserLegend->setHtml( legendHtml );
557 }
558 
559 QString MapWizard::createArchive( QWidget *parent, const QString& mapId )
560 {
561  QStringList splitMapId( mapId.split(QLatin1Char('/')) );
562  QString body = splitMapId[0];
563  QString theme = splitMapId[1];
564  QDir themeDir;
565 
566  QStringList tarArgs;
567  tarArgs.append( "--create" );
568  tarArgs.append( "--gzip" );
569  tarArgs.append( "--file" );
570  tarArgs.append( QString( "%1/%2.tar.gz" ).arg( QDir::tempPath() ).arg( theme ) );
571  tarArgs.append( "--directory" );
572 
573  if( QFile::exists( QString( "%1/maps/%2" ).arg( MarbleDirs::localPath() ).arg( mapId ) ) )
574  {
575  tarArgs.append( QString( "%1/maps/" ).arg( MarbleDirs::localPath() ) );
576  themeDir.cd( QString( "%1/maps/%2/%3" ).arg( MarbleDirs::localPath() ).arg( body ).arg( theme ) );
577  }
578 
579  else if( QFile::exists( QString( "%1/maps/%2" ).arg( MarbleDirs::systemPath() ).arg( mapId ) ) )
580  {
581  tarArgs.append( QString( "%1/maps/" ).arg( MarbleDirs::systemPath() ) );
582  themeDir.cd( QString( "%1/maps/%2/%3" ).arg( MarbleDirs::systemPath() ).arg( body ).arg( theme ) );
583  }
584 
585  if( QFile::exists( QString( "%1/%2.dgml" ).arg( themeDir.absolutePath() ).arg( theme ) ) )
586  {
587  tarArgs.append( QString( "%1/%2/%2.dgml" ).arg( body ).arg( theme ) );
588  }
589 
590  if( QFile::exists( QString( "%1/legend.html" ).arg( themeDir.absolutePath() ) ) )
591  {
592  tarArgs.append( QString( "%1/%2/legend.html" ).arg( body ).arg( theme ) );
593  }
594 
595  if( QFile::exists( QString( "%1/legend" ).arg( themeDir.absolutePath() ) ) )
596  {
597  tarArgs.append( QString( "%1/%2/legend" ).arg( body ).arg( theme ) );
598  }
599 
600  if( QFile::exists( QString( "%1/0/000000" ).arg( themeDir.absolutePath() ) ) )
601  {
602  tarArgs.append( QString( "%1/%2/0/000000" ).arg( body ).arg( theme ) );
603  }
604 
605  QStringList previewFilters;
606  previewFilters << "preview.*";
607  QStringList preview = themeDir.entryList( previewFilters );
608  if( !preview.isEmpty() ) {
609  tarArgs.append( QString( "%1/%2/%3" ).arg( body ).arg( theme ).arg( preview[0] ) );
610  }
611 
612  QStringList sourceImgFilters;
613  sourceImgFilters << theme + QLatin1String(".jpg") << theme + QLatin1String(".png") << theme + QLatin1String(".jpeg");
614  QStringList sourceImg = themeDir.entryList( sourceImgFilters );
615  if( !sourceImg.isEmpty() ) {
616  tarArgs.append( QString( "%1/%2/%3" ).arg( body ).arg( theme ).arg( sourceImg[0] ) );
617  }
618 
619  QProcess archiver;
620  switch( archiver.execute( "tar", tarArgs ) )
621  {
622  case -2:
623  QMessageBox::critical( parent, tr( "Archiving failed" ), tr( "Archiving process cannot be started." ) );
624  break;
625  case -1:
626  QMessageBox::critical( parent, tr( "Archiving failed" ), tr( "Archiving process crashed." ) );
627  break;
628  case 0:
629  mDebug() << "Archived the theme successfully.";
630  break;
631  }
632  archiver.waitForFinished();
633  return QString( "%1/%2.tar.gz" ).arg( QDir::tempPath() ).arg( theme );
634 }
635 
636 void MapWizard::deleteArchive( const QString& mapId )
637 {
638  QStringList splitMapId( mapId.split(QLatin1Char('/')) );
639  QString theme = splitMapId[1];
640  QFile::remove( QString( "%1/%2.tar.gz" ).arg( QDir::tempPath() ).arg( theme ) );
641 }
642 
643 bool MapWizard::validateCurrentPage()
644 {
645  if ( currentId() == 1 && !d->m_serverCapabilitiesValid ) {
646  queryServerCapabilities();
647  button( MapWizard::NextButton )->setEnabled( false );
648  return false;
649  }
650 
651  if ( ( currentId() == 2 || currentId() == 4 ) && d->levelZero.isNull() ) {
652  downloadLevelZero();
653  button( MapWizard::NextButton )->setEnabled( false );
654  return false;
655  }
656 
657  if ( currentId() == 3 ) {
658  d->sourceImage = d->uiWidget.lineEditSource->text();
659  if ( d->sourceImage.isEmpty() ) {
661  tr( "Source Image" ),
662  tr( "Please specify a source image." ) );
663  d->uiWidget.lineEditSource->setFocus();
664  return false;
665  }
666 
667  if ( !QFileInfo( d->sourceImage ).exists() ) {
669  tr( "Source Image" ),
670  tr( "The source image you specified does not exist. Please specify a different one." ) );
671  d->uiWidget.lineEditSource->setFocus();
672  d->uiWidget.lineEditSource->selectAll();
673  return false;
674  }
675 
676  if ( QImage( d->sourceImage ).isNull() ) {
678  tr( "Source Image" ),
679  tr( "The source image you specified does not seem to be an image. Please specify a different image file." ) );
680  d->uiWidget.lineEditSource->setFocus();
681  d->uiWidget.lineEditSource->selectAll();
682  return false;
683  }
684  }
685 
686  if ( currentId() == 5 ) {
687  if ( d->uiWidget.lineEditTitle->text().isEmpty() ) {
688  QMessageBox::information( this, tr( "Map Title" ), tr( "Please specify a map title." ) );
689  d->uiWidget.lineEditTitle->setFocus();
690  return false;
691  }
692 
693  d->mapTheme = d->uiWidget.lineEditTheme->text();
694  if ( d->mapTheme.isEmpty() ) {
695  QMessageBox::information( this, tr( "Map Name" ), tr( "Please specify a map name." ) );
696  d->uiWidget.lineEditTheme->setFocus();
697  return false;
698  }
699 
700  const QDir destinationDir( QString( "%1/maps/earth/%2" ).arg( MarbleDirs::localPath() ).arg( d->mapTheme ) );
701  if ( destinationDir.exists() ) {
703  tr( "Map Name" ),
704  tr( "Please specify another map name, since there is already a map named \"%1\"." ).arg( d->mapTheme ) );
705  d->uiWidget.lineEditTheme->setFocus();
706  d->uiWidget.lineEditTheme->selectAll();
707  return false;
708  }
709 
710  if ( d->previewImage.isNull() ) {
711  QMessageBox::information( this, tr( "Preview Image" ), tr( "Please specify a preview image." ) );
712  d->uiWidget.pushButtonPreview->setFocus();
713  return false;
714  }
715  }
716 
718 }
719 
720 int MapWizard::nextId() const
721 {
722  switch( currentId() )
723  {
724  case 0:
725  if( d->uiWidget.radioButtonWms->isChecked() ) {
726  d->mapProviderType = MapWizardPrivate::WmsMap;
727  return 1;
728  } else if( d->uiWidget.radioButtonBitmap->isChecked() ) {
729  d->mapProviderType = MapWizardPrivate::StaticImageMap;
730  return 3;
731  } else if( d->uiWidget.radioButtonStaticUrl->isChecked() ) {
732  d->mapProviderType = MapWizardPrivate::StaticUrlMap;
733  return 4;
734  }
735  break;
736 
737  case 2: // WMS
738  return 5;
739 
740  case 3: // Static Image
741  return 5;
742 
743  case 7: // Finish
744  return -1;
745 
746  default:
747  break;
748 
749  }
750 
751  return currentId() + 1;
752 }
753 
754 GeoSceneDocument* MapWizard::createDocument()
755 {
756  GeoSceneDocument *document = new GeoSceneDocument;
757 
758  GeoSceneHead *head = document->head();
759  head->setName( d->uiWidget.lineEditTitle->text() );
760  head->setTheme( d->uiWidget.lineEditTheme->text() );
761  head->setTarget( "earth" );
762  head->setDescription( d->uiWidget.textEditDesc->document()->toHtml() );
763  head->setVisible( true );
764 
765  GeoSceneIcon *icon = head->icon();
766  icon->setPixmap( QString( "preview.png" ) );
767 
768  GeoSceneZoom *zoom = head->zoom();
769  zoom->setMinimum( 900 );
770  zoom->setMaximum( 3500 );
771  zoom->setDiscrete( false );
772 
773  GeoSceneTileDataset *texture = new GeoSceneTileDataset( "map" );
774  texture->setExpire( 31536000 );
775  texture->setSourceDir(QLatin1String("earth/") + document->head()->theme());
776  if( d->mapProviderType == MapWizardPrivate::WmsMap )
777  {
778  texture->setFileFormat( d->format );
779  QString layer = d->wmsFetchedMaps.key( d->uiWidget.listWidgetWmsMaps->currentItem()->text() );
780  QUrl downloadUrl = QUrl( d->uiWidget.lineEditWmsUrl->text() );
781  QUrlQuery urlQuery;
782  urlQuery.addQueryItem( "layers", layer );
783  downloadUrl.setQuery( urlQuery );
784  texture->addDownloadUrl( downloadUrl );
785  texture->setMaximumTileLevel( 20 );
786  texture->setLevelZeroRows( 1 );
787  texture->setLevelZeroColumns( 1 );
788  texture->setServerLayout( new WmsServerLayout( texture ) );
789  texture->setTileProjection(GeoSceneAbstractTileProjection::Equirectangular);
790  }
791 
792  else if( d->mapProviderType == MapWizardPrivate::StaticUrlMap )
793  {
794  texture->setFileFormat( d->format );
795  QUrl downloadUrl = QUrl( d->uiWidget.comboBoxStaticUrlServer->currentText() );
796  texture->addDownloadPolicy( DownloadBrowse, 20 );
797  texture->addDownloadPolicy( DownloadBulk, 2 );
798  texture->addDownloadUrl( downloadUrl );
799  texture->setMaximumTileLevel( 20 );
800  texture->setLevelZeroRows( 1 );
801  texture->setLevelZeroColumns( 1 );
802  texture->setServerLayout( new CustomServerLayout( texture ) );
803  texture->setTileProjection(GeoSceneAbstractTileProjection::Mercator);
804  }
805 
806  else if( d->mapProviderType == MapWizardPrivate::StaticImageMap )
807  {
808  QString image = d->uiWidget.lineEditSource->text();
809  d->format = image.right(image.length() - image.lastIndexOf(QLatin1Char('.')) - 1).toLower();
810  texture->setFileFormat( d->format.toUpper() );
811  texture->setInstallMap(document->head()->theme() + QLatin1Char('.') + d->format);
812  texture->setServerLayout( new MarbleServerLayout( texture ) );
813  texture->setTileProjection(GeoSceneAbstractTileProjection::Equirectangular);
814  int imageWidth = QImage( image ).width();
815  int tileSize = c_defaultTileSize;
816 
817  float approxMaxTileLevel = log( imageWidth / ( 2.0 * tileSize ) ) / log( 2.0 );
818  int maxTileLevel = 0;
819  if ( approxMaxTileLevel == int( approxMaxTileLevel ) ) {
820  maxTileLevel = static_cast<int>( approxMaxTileLevel );
821  } else {
822  maxTileLevel = static_cast<int>( approxMaxTileLevel + 1 );
823  }
824  texture->setMaximumTileLevel( maxTileLevel );
825  }
826 
827  GeoSceneLayer *layer = new GeoSceneLayer( d->uiWidget.lineEditTheme->text() );
828  layer->setBackend( "texture" );
829  layer->addDataset( texture );
830 
831  GeoSceneLayer* secondLayer = new GeoSceneLayer( "standardplaces" );
832  secondLayer->setBackend( "geodata" );
833 
834  GeoSceneGeodata* cityplacemarks = new GeoSceneGeodata( "cityplacemarks" );
835  cityplacemarks->setSourceFile( "cityplacemarks.kml" );
836  secondLayer->addDataset( cityplacemarks );
837 
838  GeoSceneGeodata* baseplacemarks = new GeoSceneGeodata( "baseplacemarks" );
839  baseplacemarks->setSourceFile( "baseplacemarks.kml" );
840  secondLayer->addDataset( baseplacemarks );
841 
842  GeoSceneGeodata* elevplacemarks = new GeoSceneGeodata( "elevplacemarks" );
843  elevplacemarks->setSourceFile( "elevplacemarks.kml" );
844  secondLayer->addDataset( elevplacemarks );
845 
846  GeoSceneGeodata* observatoryplacemarks = new GeoSceneGeodata( "observatoryplacemarks" );
847  observatoryplacemarks->setSourceFile( "observatoryplacemarks.kml" );
848  secondLayer->addDataset( observatoryplacemarks );
849 
850  GeoSceneGeodata* otherplacemarks = new GeoSceneGeodata( "otherplacemarks" );
851  otherplacemarks->setSourceFile( "otherplacemarks.kml" );
852  secondLayer->addDataset( otherplacemarks );
853 
854  GeoSceneGeodata* boundaryplacemarks = new GeoSceneGeodata( "boundaryplacemarks" );
855  boundaryplacemarks->setSourceFile( "boundaryplacemarks.kml" );
856  secondLayer->addDataset( boundaryplacemarks );
857 
858  GeoSceneMap *map = document->map();
859  map->addLayer( layer );
860  map->addLayer( secondLayer );
861 
862  GeoSceneSettings *settings = document->settings();
863  GeoSceneLegend *legend = document->legend();
864 
865  if( d->uiWidget.checkBoxCoord->checkState() == Qt::Checked )
866  {
867  GeoSceneProperty *coorGrid = new GeoSceneProperty( "coordinate-grid" );
868  coorGrid->setDefaultValue( true );
869  coorGrid->setAvailable( true );
870  settings->addProperty( coorGrid );
871 
872  GeoSceneSection *coorSection = new GeoSceneSection( "coordinate-grid" );
873  coorSection->setHeading( "Coordinate Grid" );
874  coorSection->setCheckable( true );
875  coorSection->setConnectTo( "coordinate-grid" );
876  coorSection->setSpacing( 12 );
877  legend->addSection( coorSection );
878  }
879 
880  if( d->uiWidget.checkBoxInterest->checkState() == Qt::Checked )
881  {
882  GeoSceneProperty *poiProperty = new GeoSceneProperty( "otherplaces" );
883  poiProperty->setDefaultValue( true );
884  poiProperty->setAvailable( true );
885  settings->addProperty( poiProperty );
886 
887  GeoSceneSection *poiSection = new GeoSceneSection( "otherplaces" );
888  poiSection->setHeading( "Places of Interest" );
889  poiSection->setCheckable( true );
890  poiSection->setConnectTo( "otherplaces" );
891  poiSection->setSpacing( 12 );
892 
893  GeoSceneItem *geoPole = new GeoSceneItem( "geographic-pole" );
894  GeoSceneIcon *geoPoleIcon = geoPole->icon();
895  geoPole->setText( tr("Geographic Pole") );
896  geoPoleIcon->setPixmap( "bitmaps/pole_1.png" );
897  poiSection->addItem( geoPole );
898 
899  GeoSceneItem *magPole = new GeoSceneItem( "magnetic-pole" );
900  GeoSceneIcon *magPoleIcon = magPole->icon();
901  magPole->setText( tr("Magnetic Pole") );
902  magPoleIcon->setPixmap( "bitmaps/pole_2.png" );
903  poiSection->addItem( magPole );
904 
905  GeoSceneItem *airport = new GeoSceneItem( "airport" );
906  GeoSceneIcon *airportIcon = airport->icon();
907  airport->setText( tr("Airport") );
908  airportIcon->setPixmap( "bitmaps/airport.png" );
909  poiSection->addItem( airport );
910 
911  GeoSceneItem *shipwreck = new GeoSceneItem( "shipwreck" );
912  GeoSceneIcon *shipwreckIcon = shipwreck->icon();
913  shipwreck->setText( tr("Shipwreck") );
914  shipwreckIcon->setPixmap( "bitmaps/shipwreck.png" );
915  poiSection->addItem( shipwreck );
916 
917  GeoSceneItem *observatory = new GeoSceneItem( "observatory" );
918  GeoSceneIcon *observatoryIcon = observatory->icon();
919  observatory->setText( tr("Observatory") );
920  observatoryIcon->setPixmap( "bitmaps/observatory.png" );
921  poiSection->addItem( observatory );
922 
923  legend->addSection( poiSection );
924  }
925 
926  if( d->uiWidget.checkBoxTer->checkState() == Qt::Checked )
927  {
928  GeoSceneProperty *terrainProperty = new GeoSceneProperty( "terrain" );
929  terrainProperty->setDefaultValue( true );
930  terrainProperty->setAvailable( true );
931  settings->addProperty( terrainProperty );
932 
933  GeoSceneSection *terrainSection = new GeoSceneSection( "terrain" );
934  terrainSection->setHeading( "Terrain" );
935  terrainSection->setCheckable( true );
936  terrainSection->setConnectTo( "terrain" );
937  terrainSection->setSpacing( 12 );
938 
939  GeoSceneItem *mountain = new GeoSceneItem( "mountain" );
940  GeoSceneIcon *mountainIcon = mountain->icon();
941  mountain->setText( tr("Mountain") );
942  mountainIcon->setPixmap( "bitmaps/mountain_1.png" );
943  terrainSection->addItem( mountain );
944 
945  GeoSceneItem *volcano = new GeoSceneItem( "volcano" );
946  GeoSceneIcon *volcanoIcon = volcano->icon();
947  volcano->setText( tr("Volcano") );
948  volcanoIcon->setPixmap( "bitmaps/volcano_1.png" );
949  terrainSection->addItem( volcano );
950 
951  legend->addSection( terrainSection );
952 
953  }
954 
955  if( d->uiWidget.checkBoxPop->checkState() == Qt::Checked )
956  {
957  GeoSceneProperty *placesProperty = new GeoSceneProperty( "places" );
958  placesProperty->setDefaultValue( true );
959  placesProperty->setAvailable( true );
960  settings->addProperty( placesProperty );
961 
962  GeoSceneProperty *citiesProperty = new GeoSceneProperty( "cities" );
963  citiesProperty->setDefaultValue( true );
964  citiesProperty->setAvailable( true );
965  settings->addProperty( citiesProperty );
966  }
967 
968  if( d->uiWidget.checkBoxBorder->checkState() == Qt::Checked )
969  {
970  GeoSceneSection *bordersSection = new GeoSceneSection( "borders" );
971  bordersSection->setHeading( "Boundaries" );
972  bordersSection->setCheckable( true );
973  bordersSection->setConnectTo( "borders" );
974  bordersSection->setSpacing( 12 );
975 
976  GeoSceneItem *internationalBoundary = new GeoSceneItem( "international-boundary" );
977  GeoSceneIcon *internationalBoundaryIcon = internationalBoundary->icon();
978  internationalBoundary->setText( tr("International") );
979  internationalBoundaryIcon->setPixmap( "bitmaps/border_1.png" );
980  bordersSection->addItem( internationalBoundary );
981 
982  GeoSceneItem *stateBoundary = new GeoSceneItem( "state" );
983  GeoSceneIcon *stateBoundaryIcon = stateBoundary->icon();
984  stateBoundary->setText( tr("State") );
985  stateBoundaryIcon->setPixmap( "bitmaps/border_2.png" );
986  bordersSection->addItem( stateBoundary );
987 
988  GeoSceneProperty *bordersProperty = new GeoSceneProperty( "borders" );
989  bordersProperty->setDefaultValue( false );
990  bordersProperty->setAvailable( true );
991  settings->addProperty( bordersProperty );
992 
993  GeoSceneProperty *intBoundariesProperty = new GeoSceneProperty( "international-boundaries" );
994  intBoundariesProperty->setDefaultValue( false );
995  intBoundariesProperty->setAvailable( true );
996  settings->addProperty( intBoundariesProperty );
997 
998  GeoSceneProperty *stateBounderiesProperty = new GeoSceneProperty( "state-boundaries" );
999  stateBounderiesProperty->setDefaultValue( false );
1000  stateBounderiesProperty->setAvailable( true );
1001  settings->addProperty( stateBounderiesProperty );
1002 
1003  legend->addSection( bordersSection );
1004 
1005  GeoSceneLayer* mwdbii = new GeoSceneLayer( "mwdbii" );
1006  mwdbii->setBackend( "vector" );
1007  mwdbii->setRole( "polyline" );
1008 
1009  GeoSceneVector* vector = new GeoSceneVector( "pdiffborder" );
1010  vector->setFeature( "border" );
1011  vector->setFileFormat( "PNT" );
1012  vector->setSourceFile( "earth/mwdbii/PDIFFBORDER.PNT" );
1013  vector->pen().setColor( "#ffe300" );
1014  mwdbii->addDataset( vector );
1015  map->addLayer( mwdbii );
1016  }
1017 
1018  GeoSceneProperty *overviewmap = new GeoSceneProperty( "overviewmap" );
1019  overviewmap->setDefaultValue( true );
1020  overviewmap->setAvailable( true );
1021  settings->addProperty( overviewmap );
1022 
1023  GeoSceneProperty *compass = new GeoSceneProperty( "compass" );
1024  compass->setDefaultValue( true );
1025  compass->setAvailable( true );
1026  settings->addProperty( compass );
1027 
1028  GeoSceneProperty *scalebar = new GeoSceneProperty( "scalebar" );
1029  scalebar->setDefaultValue( true );
1030  scalebar->setAvailable( true );
1031  settings->addProperty( scalebar );
1032 
1033  return document;
1034 }
1035 
1036 void MapWizard::accept()
1037 {
1038  Q_ASSERT( d->mapProviderType != MapWizardPrivate::NoMap );
1039 
1040  Q_ASSERT( d->format == d->format.toLower() );
1041  Q_ASSERT( !d->mapTheme.isEmpty() );
1042 
1043  if ( d->mapProviderType == MapWizardPrivate::StaticImageMap )
1044  {
1045  d->sourceImage = d->uiWidget.lineEditSource->text();
1046  Q_ASSERT( !d->sourceImage.isEmpty() );
1047  Q_ASSERT( QFile( d->sourceImage ).exists() );
1048  }
1049  else if ( d->mapProviderType == MapWizardPrivate::WmsMap )
1050  {
1051  Q_ASSERT( !d->wmsFetchedMaps.isEmpty() );
1052  Q_ASSERT( !d->levelZero.isNull() );
1053  Q_ASSERT( !QImage::fromData( d->levelZero ).isNull() );
1054  }
1055  else if ( d->mapProviderType == MapWizardPrivate::StaticUrlMap )
1056  {
1057  Q_ASSERT( !d->levelZero.isNull() );
1058  Q_ASSERT( !QImage::fromData( d->levelZero ).isNull() );
1059  }
1060 
1061  QSharedPointer<GeoSceneDocument> document( createDocument() );
1062  Q_ASSERT( !document->head()->description().isEmpty() );
1063  Q_ASSERT( !document->head()->name().isEmpty() );
1064 
1065  if( createFiles( document.data() ) )
1066  {
1067  if( d->mapProviderType == MapWizardPrivate::WmsMap )
1068  {
1069  if( d->wmsLegends.isEmpty() && d->wmsLegends.at( d->uiWidget.listWidgetWmsMaps->currentRow() ).isEmpty() )
1070  {
1071  downloadLegend( d->wmsLegends.at( d->uiWidget.listWidgetWmsMaps->currentRow() ) );
1072  }
1073  } else if( d->mapProviderType == MapWizardPrivate::StaticImageMap || d->mapProviderType == MapWizardPrivate::StaticUrlMap ) {
1074  createLegend();
1075  }
1076 
1077  QDialog::accept();
1078  d->uiWidget.lineEditTitle->clear();
1079  d->uiWidget.lineEditTheme->clear();
1080  d->uiWidget.textEditDesc->clear();
1081  d->uiWidget.labelPreview->clear();
1082  d->uiWidget.lineEditSource->clear();
1083  QTimer::singleShot( 0, this, SLOT(restart()) );
1084  }
1085 
1086  else
1087  {
1088  QMessageBox::critical( this, tr( "Problem while creating files" ), tr( "Check if a theme with the same name exists." ) );
1089  return;
1090  }
1091 }
1092 
1093 void MapWizard::showPreview()
1094 {
1095  QSharedPointer<GeoSceneDocument> document( createDocument() );
1096 
1097  if( createFiles( document.data() ) )
1098  {
1099  if( d->mapProviderType == MapWizardPrivate::WmsMap )
1100  {
1101  if( d->wmsLegends.isEmpty() && d->wmsLegends.at( d->uiWidget.listWidgetWmsMaps->currentRow() ).isEmpty() )
1102  {
1103  downloadLegend( d->wmsLegends.at( d->uiWidget.listWidgetWmsMaps->currentRow() ) );
1104  }
1105  } else if( d->mapProviderType == MapWizardPrivate::StaticImageMap || d->mapProviderType == MapWizardPrivate::StaticUrlMap ) {
1106  createLegend();
1107  }
1108  }
1109 
1110  QPointer<PreviewDialog> previewDialog = new PreviewDialog( this, document.data()->head()->mapThemeId() );
1111  previewDialog->exec();
1112  delete previewDialog;
1113 }
1114 
1115 
1116 }
1117 
1118 #include "moc_MapWizard.cpp"
1119 #include "MapWizard.moc" // needed for Q_OBJECT here in source
Q_OBJECTQ_OBJECT
void append(const T &value)
bool isNull() const const
QString text() const const
QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags)
@ DownloadBrowse
Browsing mode, normal operation of Marble, like a web browser.
Definition: MarbleGlobal.h:150
QString number(int n, int base)
QByteArray format() const const
bool waitForFinished(int msecs)
bool remove()
QString tagName() const const
void setMargin(int margin)
bool copy(const QString &newName)
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
void addQueryItem(const QString &key, const QString &value)
QDomNodeList elementsByTagName(const QString &tagname) const const
bool isNull() const const
void clear()
QString & prepend(QChar ch)
QImage scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const const
bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
QByteArray toLatin1() const const
NoDotAndDotDot
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
virtual void closeEvent(QCloseEvent *e) override
bool exists() const const
QDomNode at(int index) const const
bool exists() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
int size() const const
QString tempPath()
QAction * zoomOut(const QObject *recvr, const char *slot, QObject *parent)
QUrl url() const const
IgnoreAspectRatio
QAction * zoom(const QObject *recvr, const char *slot, QObject *parent)
int execute(const QString &program, const QStringList &arguments)
int length() const const
bool isNull() const const
virtual void accept()
void setFileName(const QString &name)
bool isEmpty() const const
void setSpacing(int spacing)
Binds a QML item to a specific geodetic location in screen coordinates.
QAction * restart(const QObject *recvr, const char *slot, QObject *parent)
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
int height() const const
void setupUi(QWidget *widget)
QString absolutePath() const const
QDomElement documentElement() const const
QDomElement firstChildElement(const QString &tagName) const const
QString & replace(int position, int n, QChar after)
void setQuery(const QString &query, QUrl::ParsingMode mode)
QAction * zoomIn(const QObject *recvr, const char *slot, QObject *parent)
QString toLower() const const
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
virtual bool validateCurrentPage()
void setUrl(const QString &url, QUrl::ParsingMode parsingMode)
KIOFILEWIDGETS_EXPORT QString dir(const QString &fileClass)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString left(int n) const const
QString right(int n) const const
void setUrl(const QUrl &url)
void clear()
void addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment)
@ DownloadBulk
Bulk download, for example "File/Download region".
Definition: MarbleGlobal.h:149
QByteArray readAll()
QString attribute(const QString &name, const QString &defValue) const const
QStringList entryList(QDir::Filters filters, QDir::SortFlags sort) const const
SmoothTransformation
QFuture< void > map(Sequence &sequence, MapFunctor function)
QAction * next(const QObject *recvr, const char *slot, QObject *parent)
QMessageBox::StandardButton information(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QString tr(const char *sourceText, const char *disambiguation, int n)
QImage fromData(const uchar *data, int size, const char *format)
bool cd(const QString &dirName)
QMessageBox::StandardButton critical(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QString & append(QChar ch)
void setAttribute(QNetworkRequest::Attribute code, const QVariant &value)
int width() const const
char * data()
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:31
int width() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu May 26 2022 04:07:49 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.