Marble

MapWizard.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2011 Utku Aydın <utkuaydin34@gmail.com>
4//
5
6#include "MapWizard.h"
7#include "ui_MapWizard.h"
8
9#include "DgmlElementDictionary.h"
10#include "GeoSceneDocument.h"
11#include "GeoSceneGeodata.h"
12#include "GeoSceneHead.h"
13#include "GeoSceneIcon.h"
14#include "GeoSceneItem.h"
15#include "GeoSceneLayer.h"
16#include "GeoSceneLegend.h"
17#include "GeoSceneMap.h"
18#include "GeoSceneProperty.h"
19#include "GeoSceneSection.h"
20#include "GeoSceneSettings.h"
21#include "GeoSceneTileDataset.h"
22#include "GeoSceneVector.h"
23#include "GeoSceneZoom.h"
24#include "GeoWriter.h"
25#include "MarbleDebug.h"
26#include "MarbleDirs.h"
27#include "MarbleGlobal.h"
28#include "MarbleNavigator.h"
29#include "MarbleWidget.h"
30#include "OwsServiceManager.h"
31#include "ServerLayout.h"
32
33#include <QBuffer>
34#include <QColorDialog>
35#include <QDialogButtonBox>
36#include <QDir>
37#include <QDomElement>
38#include <QFile>
39#include <QFileDialog>
40#include <QImageReader>
41#include <QMessageBox>
42#include <QNetworkReply>
43#include <QNetworkRequest>
44#include <QPixmap>
45#include <QProcess>
46#include <QSharedPointer>
47#include <QSortFilterProxyModel>
48#include <QStandardItemModel>
49#include <QTimer>
50#include <QUrlQuery>
51#include <QXmlStreamWriter>
52
53namespace Marble
54{
55
56int const layerIdRole = 1001;
57
58enum wizardPage {
59 WelcomePage,
60 WmsSelectionPage,
61 LayerSelectionPage,
62 GlobalSourceImagePage,
63 XYZUrlPage,
64 ThemeInfoPage,
65 LegendPage,
66 SummaryPage
67};
68
69class MapWizardPrivate
70{
71public:
72 MapWizardPrivate()
73 : m_serverCapabilitiesValid(false)
74 , m_levelZeroTileValid(false)
75 , m_previewImageValid(false)
76 , m_legendImageValid(false)
77 , mapProviderType()
78 , model(new QStandardItemModel())
79 , sortModel(new QSortFilterProxyModel())
80
81 {
83 sortModel->setSourceModel(model);
84 }
85
86 void pageEntered(int id);
87
88 Ui::MapWizard uiWidget;
89
90 QString mapTheme;
91
92 OwsServiceManager owsManager;
93
94 QStringList wmsServerList;
95 QStringList wmtsServerList;
96 QStringList staticUrlServerList;
97 bool m_serverCapabilitiesValid;
98 bool m_levelZeroTileValid;
99 bool m_previewImageValid;
100 bool m_legendImageValid;
101
102 enum mapType {
103 NoMap,
104 StaticImageMap,
105 WmsMap,
106 WmtsMap,
107 StaticUrlMap
108 };
109 QStringList selectedLayers;
110 QString selectedProjection;
111
112 mapType mapProviderType;
113 QByteArray levelZero;
114 QByteArray preview;
115 QByteArray legend;
116 QImage levelZeroTile;
117 QImage previewImage;
118 QImage legendImage;
119
120 QString format;
121
122 QStringList wmsLegends;
123
124 QString sourceImage;
125
126 QStandardItemModel *model;
127 QSortFilterProxyModel *sortModel;
128};
129
130class PreviewDialog : public QDialog
131{
133public:
134 PreviewDialog(QWidget *parent, const QString &mapThemeId);
135 void closeEvent(QCloseEvent *e) override;
136
137private:
138 bool deleteTheme(const QString &directory);
139 QString m_mapThemeId;
140};
141
142PreviewDialog::PreviewDialog(QWidget *parent, const QString &mapThemeId)
143 : QDialog(parent)
144 , m_mapThemeId(mapThemeId)
145{
146 auto layout = new QGridLayout(this);
147 auto widget = new MarbleWidget();
148 auto navigator = new MarbleNavigator();
149
150 connect(navigator, SIGNAL(goHome()), widget, SLOT(goHome()));
151 connect(navigator, SIGNAL(moveUp()), widget, SLOT(moveUp()));
152 connect(navigator, SIGNAL(moveDown()), widget, SLOT(moveDown()));
153 connect(navigator, SIGNAL(moveLeft()), widget, SLOT(moveLeft()));
154 connect(navigator, SIGNAL(moveRight()), widget, SLOT(moveRight()));
155 connect(navigator, SIGNAL(zoomIn()), widget, SLOT(zoomIn()));
156 connect(navigator, SIGNAL(zoomOut()), widget, SLOT(zoomOut()));
157 connect(navigator, SIGNAL(zoomChanged(int)), widget, SLOT(setZoom(int)));
158
159 widget->setMapThemeId(m_mapThemeId);
160 widget->setZoom(1000);
161
162 layout->addWidget(navigator, 1, 1);
163 layout->addWidget(widget, 1, 2);
164 layout->setContentsMargins({});
165 layout->setSpacing(0);
166
167 this->setMinimumSize(640, 480);
168 this->setWindowTitle(tr("Preview Map"));
169}
170
171void PreviewDialog::closeEvent(QCloseEvent *e)
172{
173 const QString dgmlPath = MarbleDirs::localPath() + QLatin1StringView("/maps/") + m_mapThemeId;
174 const QString directory = dgmlPath.left(dgmlPath.lastIndexOf(QLatin1Char('/')));
175 this->deleteTheme(directory);
177}
178
179bool PreviewDialog::deleteTheme(const QString &directory)
180{
181 QDir dir(directory);
182 bool result = true;
183
184 if (dir.exists(directory)) {
186 if (info.isDir()) {
187 result = deleteTheme(info.absoluteFilePath());
188 } else {
189 result = QFile::remove(info.absoluteFilePath());
190 }
191
192 if (!result) {
193 return result;
194 }
195 }
196 result = dir.rmdir(directory);
197 }
198
199 return result;
200}
201
202void MapWizardPrivate::pageEntered(int id)
203{
204 if (id == WmsSelectionPage) {
205 m_serverCapabilitiesValid = false;
206 uiWidget.lineEditWmsUrl->setFocus();
207 } else if (id == LayerSelectionPage || id == GlobalSourceImagePage) {
208 m_legendImageValid = false;
209 m_previewImageValid = false;
210 levelZero.clear();
211 uiWidget.comboBoxStaticUrlServer->clear();
212 uiWidget.comboBoxStaticUrlServer->addItems(staticUrlServerList);
213 uiWidget.comboBoxStaticUrlServer->addItem(QStringLiteral("http://"));
214 } else if (id == ThemeInfoPage) {
215 m_legendImageValid = false;
216 if (mapProviderType == MapWizardPrivate::StaticImageMap) {
217 previewImage = QImage(uiWidget.lineEditSource->text()).scaled(136, 136, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
218 uiWidget.labelPreview->setPixmap(QPixmap::fromImage(previewImage));
219 }
220 } else if (id == LegendPage) {
221 m_levelZeroTileValid = false;
222 }
223}
224
225MapWizard::MapWizard(QWidget *parent)
226 : QWizard(parent)
227 , d(new MapWizardPrivate)
228{
229 d->uiWidget.setupUi(this);
230
231 connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(pageEntered(int)));
232
233 connect(&d->owsManager, &OwsServiceManager::wmsCapabilitiesReady, this, &MapWizard::processCapabilitiesResults);
234 connect(&d->owsManager, &OwsServiceManager::imageRequestResultReady, this, &MapWizard::processImageResults);
235
236 connect(&d->owsManager, &OwsServiceManager::wmtsCapabilitiesReady, this, &MapWizard::processCapabilitiesResults);
237
238 connect(d->uiWidget.pushButtonSource, &QAbstractButton::clicked, this, &MapWizard::querySourceImage);
239 connect(d->uiWidget.pushButtonPreview, &QAbstractButton::clicked, this, &MapWizard::queryPreviewImage);
240 connect(d->uiWidget.pushButtonLegend_2, &QAbstractButton::clicked, this, &MapWizard::queryLegendImage);
241
242 connect(d->uiWidget.comboBoxWmsServer, SIGNAL(textActivated(QString)), this, SLOT(setLineEditWms(QString)));
243 connect(d->uiWidget.listViewWmsLayers, &QListView::pressed, this, &MapWizard::processSelectedLayerInformation);
244
245 connect(d->uiWidget.lineEditTitle, &QLineEdit::textChanged, d->uiWidget.labelSumMName, &QLabel::setText);
246 connect(d->uiWidget.lineEditTheme, &QLineEdit::textChanged, d->uiWidget.labelSumMTheme, &QLabel::setText);
247
248 connect(d->uiWidget.pushButtonPreviewMap, &QAbstractButton::clicked, this, &MapWizard::showPreview);
249 connect(d->uiWidget.lineEditWmsSearch, &QLineEdit::textChanged, this, &MapWizard::updateSearchFilter);
250 connect(d->uiWidget.comboBoxWmsMaps, SIGNAL(currentIndexChanged(int)), this, SLOT(updateBackdropCheckBox()));
251 connect(d->uiWidget.checkBoxWmsBackdrop, &QCheckBox::stateChanged, this, &MapWizard::updateBackdropCheckBox);
252
253 connect(d->uiWidget.checkBoxWmsMultipleSelections, &QCheckBox::stateChanged, this, &MapWizard::updateListViewSelection);
254 connect(d->uiWidget.pushButtonColor, &QPushButton::clicked, this, &MapWizard::chooseBackgroundColor);
255 updateListViewSelection();
256
257 d->uiWidget.checkBoxWmsMultipleSelections->setVisible(true);
258 d->uiWidget.checkBoxWmsBackdrop->setVisible(true);
259 d->uiWidget.listViewWmsLayers->setModel(d->sortModel);
260 d->uiWidget.listViewWmsLayers->setSelectionMode(QAbstractItemView::ExtendedSelection);
261
262 d->uiWidget.progressBarWmsCapabilities->setVisible(false);
263 setLayerButtonsVisible(true);
264
265 d->uiWidget.tabWidgetLayers->setCurrentIndex(0);
266
267 QPalette p = d->uiWidget.labelBackgroundColor->palette();
268 p.setColor(QPalette::Window, d->uiWidget.labelBackgroundColor->text());
269 d->uiWidget.labelBackgroundColor->setAutoFillBackground(true);
270 d->uiWidget.labelBackgroundColor->setPalette(p);
271
272 d->uiWidget.radioButtonXYZServer->setVisible(false);
273}
274
275MapWizard::~MapWizard()
276{
277 delete d;
278}
279
280void MapWizard::processCapabilitiesResults()
281{
282 d->uiWidget.progressBarWmsCapabilities->setVisible(false);
283
284 button(MapWizard::NextButton)->setEnabled(true);
285
286 if (d->owsManager.capabilitiesStatus() == OwsCapabilitiesReplyUnreadable) {
287 QMessageBox::critical(this, tr("Error while parsing"), tr("Wizard cannot parse server's response"));
288 return;
289 }
290 if (d->owsManager.capabilitiesStatus() == OwsCapabilitiesNoOwsServer) {
291 QMessageBox::critical(this, tr("Error while parsing"), tr("Server is not an OWS Server."));
292 return;
293 }
294 d->model->clear();
295
296 OwsMappingCapabilities owsCapabilities;
297 if (d->owsManager.owsServiceType() == WmsType) {
298 owsCapabilities = d->owsManager.wmsCapabilities();
299 } else if (d->owsManager.owsServiceType() == WmtsType) {
300 owsCapabilities = d->owsManager.wmtsCapabilities();
301 }
302
303 d->uiWidget.labelWmsTitle->setText(QStringLiteral("Web Service: <b>%1</b>").arg(owsCapabilities.title()));
304 d->uiWidget.labelWmsTitle->setToolTip(QStringLiteral("<small>%1</small>").arg(owsCapabilities.abstract()));
305
306 for (const auto &layer : owsCapabilities.layers()) {
307 if (!layer.isEmpty()) {
308 auto item = new QStandardItem(owsCapabilities.title(layer));
309 item->setData(layer, layerIdRole);
310 item->setToolTip(owsCapabilities.abstract(layer));
311 d->model->appendRow(item);
312 }
313 }
314
315 // default to the first layer
316 d->uiWidget.listViewWmsLayers->setCurrentIndex(d->sortModel->index(0, 0));
317 d->uiWidget.lineEditWmsSearch->setText(QString());
318
319 d->uiWidget.comboBoxWmsFormat->clear();
320 if (d->owsManager.owsServiceType() == WmsType) {
321 d->uiWidget.comboBoxWmsFormat->addItems(d->owsManager.wmsCapabilities().formats());
322
323 // default to png or jpeg
324 d->uiWidget.comboBoxWmsFormat->setCurrentText(QStringLiteral("png"));
325 if (d->uiWidget.comboBoxWmsFormat->currentText() != QStringLiteral("png")) {
326 d->uiWidget.comboBoxWmsFormat->setCurrentText(QStringLiteral("jpeg"));
327 }
328 }
329
330 QString serviceInfo;
331 serviceInfo += QStringLiteral("<html>");
332 serviceInfo += d->owsManager.wmsCapabilities().abstract();
333 serviceInfo += QStringLiteral("<br><br><i>Contact:</i> %1").arg(d->owsManager.wmsCapabilities().contactInformation());
334 serviceInfo += QStringLiteral("<br><br><i>Fees:</i> %1").arg(d->owsManager.wmsCapabilities().fees());
335 serviceInfo += QStringLiteral("</html>");
336
337 d->uiWidget.textEditWmsServiceInfo->setText(serviceInfo);
338 d->uiWidget.tabServiceInfo->setEnabled(!serviceInfo.isEmpty());
339
340 if (d->uiWidget.listViewWmsLayers->model()->rowCount() > 0) {
341 processSelectedLayerInformation();
342 }
343
344 d->m_serverCapabilitiesValid = true;
345
346 if (d->owsManager.owsServiceType() == WmsType) {
347 if (!d->wmsServerList.contains(d->uiWidget.lineEditWmsUrl->text())) {
348 d->wmsServerList.append(d->uiWidget.lineEditWmsUrl->text());
349 }
350 setWmsServers(d->wmsServerList);
351 } else if (d->owsManager.owsServiceType() == WmtsType) {
352 if (!d->wmtsServerList.contains(d->uiWidget.lineEditWmsUrl->text())) {
353 d->wmtsServerList.append(d->uiWidget.lineEditWmsUrl->text());
354 }
355 setWmtsServers(d->wmtsServerList);
356 }
357
358 next();
359
360 setSearchFieldVisible(d->model->rowCount() > 20);
361}
362
363void MapWizard::processSelectedLayerInformation()
364{
365 updateListViewSelection();
366
367 QStringList selectedList;
368 QModelIndexList selectedIndexes = d->uiWidget.listViewWmsLayers->selectionModel()->selectedIndexes();
369 for (auto selectedIndex : std::as_const(selectedIndexes)) {
370 selectedList << d->sortModel->data(selectedIndex, layerIdRole).toString();
371 }
372 d->selectedLayers = selectedList;
373 OwsMappingCapabilities owsCapabilities;
374 if (d->owsManager.owsServiceType() == WmsType) {
375 owsCapabilities = d->owsManager.wmsCapabilities();
376 } else if (d->owsManager.owsServiceType() == WmtsType) {
377 owsCapabilities = d->owsManager.wmtsCapabilities();
378 }
379 d->uiWidget.comboBoxWmsMaps->clear();
380 QMap<QString, QString> epsgToText;
381 epsgToText[QStringLiteral("epsg:3857")] = tr("Web Mercator (epsg:3857)");
382 epsgToText[QStringLiteral("epsg:4326")] = tr("Equirectangular (epsg:4326)");
383 epsgToText[QStringLiteral("crs:84")] = tr("Equirectangular (crs:84)");
384 QStringList projectionTextList;
385 if (d->selectedLayers.isEmpty()) {
386 return;
387 }
388
389 if (d->owsManager.owsServiceType() == WmsType) {
390 WmsCapabilities capabilities = d->owsManager.wmsCapabilities();
391 for (const auto &projection : capabilities.projections(d->selectedLayers.first())) {
392 projectionTextList << epsgToText[projection];
393 }
394 d->uiWidget.labelWmsTileProjection->setText(tr("Tile Projection:"));
395 d->uiWidget.comboBoxWmsMaps->addItems(projectionTextList);
396
397 // default to Web Mercator
398 d->uiWidget.comboBoxWmsMaps->setCurrentText(tr("Web Mercator (epsg:3857)"));
399
400 updateBackdropCheckBox(); // align the backdrop checkbox state with the available/selected projection
401
402 // bool projectionSelectionVisible = d->uiWidget.comboBoxWmsMaps->count() > 0;
403 // d->uiWidget.comboBoxWmsMaps->setVisible(projectionSelectionVisible);
404 // d->uiWidget.labelWmsTileProjection->setVisible(projectionSelectionVisible);
405 // d->uiWidget.comboBoxWmsMaps->setEnabled(d->uiWidget.comboBoxWmsMaps->count() > 1);
406 }
407 if (d->owsManager.owsServiceType() == WmtsType) {
408 WmtsCapabilities capabilities = d->owsManager.wmtsCapabilities();
409 QString selectedLayer = d->selectedLayers.first();
410 d->uiWidget.labelWmsTileProjection->setText(tr("Tile Matrix Set:"));
411 d->uiWidget.comboBoxWmsMaps->addItems(capabilities.wmtsTileMatrixSets()[selectedLayer]);
412 d->uiWidget.comboBoxWmsFormat->addItems(capabilities.wmtsTileResource()[selectedLayer].keys());
413 // default to png or jpeg
414 d->uiWidget.comboBoxWmsFormat->setCurrentText(QStringLiteral("png"));
415 if (d->uiWidget.comboBoxWmsFormat->currentText() != QStringLiteral("png")) {
416 d->uiWidget.comboBoxWmsFormat->setCurrentText(QStringLiteral("jpeg"));
417 }
418 }
419
420 d->uiWidget.lineEditTitle->setText(owsCapabilities.title(d->selectedLayers.first()));
421
422 // Remove all invalid characters from the theme-String
423 // that will make the TileLoader malfunction.
424 QString themeString = d->selectedLayers.first();
425 themeString.remove(QRegularExpression(QStringLiteral(R"([:"\\/])")));
426 d->uiWidget.lineEditTheme->setText(themeString);
427 QRegularExpression rx(QStringLiteral(R"(^[^:"\\/]*$)"));
428 QValidator *validator = new QRegularExpressionValidator(rx, this);
429 d->uiWidget.lineEditTheme->setValidator(validator);
430
431 QString description;
432 description += QStringLiteral("<html>");
433 description += owsCapabilities.abstract(d->selectedLayers.first());
434 if (d->owsManager.owsServiceType() == WmsType) {
435 description += QStringLiteral("<br><br><i>Contact:</i> %1").arg(d->owsManager.wmsCapabilities().contactInformation());
436 description += QStringLiteral("<br><br><i>Fees:</i> %1").arg(d->owsManager.wmsCapabilities().fees());
437 }
438 description += QStringLiteral("</html>");
439 d->uiWidget.textEditDesc->setText(description);
440
441 QString layerInfo;
442 layerInfo += owsCapabilities.abstract(d->selectedLayers.first());
443 d->uiWidget.tabLayerInfo->setEnabled(!layerInfo.isEmpty());
444 d->uiWidget.textEditWmsLayerInfo->setText(layerInfo);
445}
446
447void MapWizard::processImageResults()
448{
449 setLayerButtonsVisible(true);
450 QString imageType;
451 if (d->owsManager.imageRequestResult().resultType() == PreviewImage) {
452 d->m_previewImageValid = true;
453 imageType = tr("Preview Image");
454 }
455 if (d->owsManager.imageRequestResult().resultType() == LevelZeroTile) {
456 d->m_levelZeroTileValid = true;
457 imageType = tr("Base Tile");
458 }
459 if (d->owsManager.imageRequestResult().resultType() == LevelZeroTile) {
460 d->m_legendImageValid = true;
461 imageType = tr("Legend Image");
462 }
463
464 button(MapWizard::NextButton)->setEnabled(true);
465
466 if (d->owsManager.imageRequestResult().imageStatus() == WmsImageFailed) {
467 QMessageBox::information(this, tr("%1").arg(imageType), tr("The %1 could not be downloaded.").arg(imageType));
468 if (imageType == QChar(PreviewImage))
469 d->m_previewImageValid = false; // PORT_QT6 : comparison between enum and QString???
470 if (imageType == QChar(LevelZeroTile))
471 d->m_levelZeroTileValid = false;
472 if (imageType == QChar(LegendImage))
473 d->m_legendImageValid = false;
474 } else if (d->owsManager.imageRequestResult().imageStatus() == WmsImageFailedServerMessage) {
476 this,
477 tr("%1").arg(imageType),
478 tr("The %1 could not be downloaded successfully. The server replied:\n\n%2").arg(imageType, QString::fromLatin1(d->owsManager.resultRaw())));
479 if (imageType == QChar(PreviewImage))
480 d->m_previewImageValid = false;
481 if (imageType == QChar(LevelZeroTile))
482 d->m_levelZeroTileValid = false;
483 if (imageType == QChar(LegendImage))
484 d->m_legendImageValid = false;
485 } else {
486 if (d->owsManager.imageRequestResult().resultType() == PreviewImage) {
487 d->previewImage = d->owsManager.resultImage().scaled(100, 100, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
488 QPixmap previewPixmap = QPixmap::fromImage(d->previewImage);
489 d->uiWidget.labelThumbnail->setPixmap(previewPixmap);
490 d->uiWidget.labelThumbnail->resize(QSize(100, 100));
491 d->uiWidget.labelPreview->setPixmap(previewPixmap);
492 d->uiWidget.labelPreview->resize(QSize(100, 100));
493 }
494 if (d->owsManager.imageRequestResult().resultType() == LevelZeroTile) {
495 d->levelZeroTile = d->owsManager.resultImage();
496 d->levelZero = d->owsManager.resultRaw();
497 }
498 if (d->owsManager.imageRequestResult().resultType() == LegendImage) {
499 d->legendImage = d->owsManager.resultImage();
500 d->legend = d->owsManager.resultRaw();
501 QPixmap legendPixmap = QPixmap::fromImage(d->legendImage);
502 d->uiWidget.labelLegendImage->resize(legendPixmap.size());
503 d->uiWidget.labelLegendImage->setPixmap(legendPixmap);
504 }
505 next();
506 }
507}
508
509void MapWizard::createWmsLegend()
510{
511 QDir map(MarbleDirs::localPath() + QLatin1StringView("/maps/earth/") + d->mapTheme);
512 if (!map.exists(QStringLiteral("legend"))) {
513 map.mkdir(QStringLiteral("legend"));
514 }
515
516 QFile image(map.absolutePath() + QLatin1StringView("/legend/legend.png"));
517 image.open(QIODevice::ReadWrite);
518 image.write(d->legend);
519 image.close();
520
521 const QString legendHtml = createLegendHtml();
522 createLegendFile(legendHtml);
523}
524
525void MapWizard::setWmsServers(const QStringList &uris)
526{
527 d->wmsServerList = uris;
528}
529
530QStringList MapWizard::wmtsServers() const
531{
532 return d->wmtsServerList;
533}
534
535void MapWizard::setWmtsServers(const QStringList &uris)
536{
537 d->wmtsServerList = uris;
538}
539
540QStringList MapWizard::wmsServers() const
541{
542 return d->wmsServerList;
543}
544
545QStringList MapWizard::staticUrlServers() const
546{
547 return d->staticUrlServerList;
548}
549
550void MapWizard::setStaticUrlServers(const QStringList &uris)
551{
552 d->staticUrlServerList = uris;
553}
554
555void MapWizard::setLineEditWms(const QString &text)
556{
557 if (text == tr("Custom")) {
558 d->uiWidget.lineEditWmsUrl->setText(QString());
559 } else {
560 d->uiWidget.lineEditWmsUrl->setText(text);
561 }
562}
563
564void MapWizard::setLayerButtonsVisible(bool visible)
565{
566 d->uiWidget.checkBoxWmsMultipleSelections->setVisible(visible);
567 d->uiWidget.checkBoxWmsBackdrop->setVisible(visible);
568 d->uiWidget.comboBoxWmsFormat->setVisible(visible);
569 d->uiWidget.comboBoxWmsMaps->setVisible(visible);
570 d->uiWidget.labelWmsTileFormat->setVisible(visible);
571 d->uiWidget.labelWmsTileProjection->setVisible(visible);
572 d->uiWidget.progressBarWmsLayers->setVisible(!visible);
573}
574
575void MapWizard::setSearchFieldVisible(bool visible)
576{
577 d->uiWidget.labelWmsSearch->setVisible(visible);
578 d->uiWidget.lineEditWmsSearch->setText(QString());
579 d->uiWidget.lineEditWmsSearch->setVisible(visible);
580 d->uiWidget.lineEditWmsSearch->setFocus();
581}
582
583bool MapWizard::createFiles(const GeoSceneDocument *document)
584{
585 // Create directories
586 QDir maps(MarbleDirs::localPath() + QLatin1StringView("/maps/earth/"));
587 if (!maps.exists(document->head()->theme())) {
588 maps.mkdir(document->head()->theme());
589
590 if (d->mapProviderType == MapWizardPrivate::StaticImageMap) {
591 // Source image
592 QFile sourceImage(d->sourceImage);
593 d->format = d->sourceImage.right(d->sourceImage.length() - d->sourceImage.lastIndexOf(QLatin1Char('.')) - 1).toLower();
594 sourceImage.copy(QStringLiteral("%1/%2/%2.%3").arg(maps.absolutePath(), document->head()->theme(), d->format));
595 }
596
597 else if (d->mapProviderType == MapWizardPrivate::WmsMap || d->mapProviderType == MapWizardPrivate::WmtsMap) {
598 maps.mkdir(QStringLiteral("%1/0/").arg(document->head()->theme()));
599 maps.mkdir(QStringLiteral("%1/0/0").arg(document->head()->theme()));
600 const QString path = QStringLiteral("%1/%2/0/0/0.%3").arg(maps.absolutePath(), document->head()->theme(), d->owsManager.resultFormat());
601 QFile baseTile(path);
602 baseTile.open(QFile::WriteOnly);
603 baseTile.write(d->levelZero);
604 }
605
606 else if (d->mapProviderType == MapWizardPrivate::StaticUrlMap) {
607 maps.mkdir(QStringLiteral("%1/0/").arg(document->head()->theme()));
608 maps.mkdir(QStringLiteral("%1/0/0").arg(document->head()->theme()));
609 const QString path = QStringLiteral("%1/%2/0/0/0.%3").arg(maps.absolutePath(), document->head()->theme(), d->format);
610 QFile baseTile(path);
611 baseTile.open(QFile::WriteOnly);
612 baseTile.write(d->levelZero);
613 }
614
615 // Preview image
616 QString pixmapPath = QStringLiteral("%1/%2/%3").arg(maps.absolutePath(), document->head()->theme(), document->head()->icon()->pixmap());
617 d->previewImage.save(pixmapPath);
618
619 // DGML
620 QFile file(QStringLiteral("%1/%2/%2.dgml").arg(maps.absolutePath(), document->head()->theme()));
621 file.open(QIODevice::ReadWrite);
622 GeoWriter geoWriter;
623 geoWriter.setDocumentType(QString::fromLatin1(dgml::dgmlTag_nameSpace20));
624 geoWriter.write(&file, document);
625 file.close();
626
627 return true;
628 }
629
630 else
631 return false;
632}
633
634QString MapWizard::createLegendHtml(const QString &image)
635{
636 QString htmlOutput;
637 QXmlStreamWriter stream(&htmlOutput);
638 stream.writeStartDocument();
639 stream.writeStartElement("html");
640 stream.writeStartElement("head");
641
642 stream.writeTextElement("title", "Marble: Legend");
643 stream.writeStartElement("link");
644 stream.writeAttribute("href", "legend.css");
645 stream.writeAttribute("rel", "stylesheet");
646 stream.writeAttribute("type", "text/css");
647 stream.writeEndElement();
648
649 stream.writeStartElement("body");
650 stream.writeStartElement("img");
651 stream.writeAttribute("src", image);
652 stream.writeEndElement();
653 stream.writeComment(" ##customLegendEntries:all## ");
654 stream.writeEndElement();
655 stream.writeEndElement();
656
657 return htmlOutput;
658}
659
660void MapWizard::createLegendFile(const QString &legendHtml)
661{
662 QDir map(MarbleDirs::localPath() + QLatin1StringView("/maps/earth/") + d->mapTheme);
663
664 QFile html(map.absolutePath() + QLatin1StringView("/legend.html"));
665 html.open(QIODevice::ReadWrite);
666 html.write(legendHtml.toLatin1().data());
667 html.close();
668}
669
670void MapWizard::createLegend()
671{
672 QDir map(MarbleDirs::localPath() + QLatin1StringView("/maps/earth/") + d->mapTheme);
673 if (!map.exists(QStringLiteral("legend"))) {
674 map.mkdir(QStringLiteral("legend"));
675 }
676
677 QFile image;
678 image.setFileName(d->uiWidget.lineEditLegend_2->text());
679 image.copy(map.absolutePath() + QLatin1StringView("/legend/legend.png"));
680
681 const QString legendHtml = createLegendHtml();
682 createLegendFile(legendHtml);
683}
684
685void MapWizard::querySourceImage()
686{
687 d->uiWidget.lineEditSource->setText(QFileDialog::getOpenFileName());
688}
689
690void MapWizard::queryPreviewImage()
691{
693 d->previewImage = QImage(fileName);
694
695 QPixmap preview = QPixmap::fromImage(d->previewImage);
696 d->uiWidget.labelThumbnail->setPixmap(preview);
697 d->uiWidget.labelThumbnail->resize(preview.width(), preview.height());
698}
699
700void MapWizard::queryLegendImage()
701{
703 d->uiWidget.lineEditLegend_2->setText(fileName);
704 QImage legendImage(fileName);
705 QPixmap legendPixmap = QPixmap::fromImage(legendImage);
706 d->uiWidget.labelLegendImage->setPixmap(legendPixmap);
707}
708
709QString MapWizard::createArchive(QWidget *parent, const QString &mapId)
710{
711 QStringList splitMapId(mapId.split(QLatin1Char('/')));
712 QString body = splitMapId[0];
713 QString theme = splitMapId[1];
714 QDir themeDir;
715
716 QStringList tarArgs;
717 tarArgs.append(QStringLiteral("--create"));
718 tarArgs.append(QStringLiteral("--gzip"));
719 tarArgs.append(QStringLiteral("--file"));
720 tarArgs.append(QStringLiteral("%1/%2.tar.gz").arg(QDir::tempPath(), theme));
721 tarArgs.append(QStringLiteral("--directory"));
722
723 if (QFile::exists(QStringLiteral("%1/maps/%2").arg(MarbleDirs::localPath(), mapId))) {
724 tarArgs.append(QStringLiteral("%1/maps/").arg(MarbleDirs::localPath()));
725 themeDir.cd(QStringLiteral("%1/maps/%2/%3").arg(MarbleDirs::localPath(), body, theme));
726 }
727
728 else if (QFile::exists(QStringLiteral("%1/maps/%2").arg(MarbleDirs::systemPath(), mapId))) {
729 tarArgs.append(QStringLiteral("%1/maps/").arg(MarbleDirs::systemPath()));
730 themeDir.cd(QStringLiteral("%1/maps/%2/%3").arg(MarbleDirs::systemPath(), body, theme));
731 }
732
733 if (QFile::exists(QStringLiteral("%1/%2.dgml").arg(themeDir.absolutePath(), theme))) {
734 tarArgs.append(QStringLiteral("%1/%2/%2.dgml").arg(body, theme));
735 }
736
737 if (QFile::exists(QStringLiteral("%1/legend.html").arg(themeDir.absolutePath()))) {
738 tarArgs.append(QStringLiteral("%1/%2/legend.html").arg(body, theme));
739 }
740
741 if (QFile::exists(QStringLiteral("%1/legend").arg(themeDir.absolutePath()))) {
742 tarArgs.append(QStringLiteral("%1/%2/legend").arg(body, theme));
743 }
744
745 if (QFile::exists(QStringLiteral("%1/0/000000").arg(themeDir.absolutePath()))) {
746 tarArgs.append(QStringLiteral("%1/%2/0/000000").arg(body, theme));
747 }
748
749 QStringList previewFilters;
750 previewFilters << QStringLiteral("preview.*");
751 QStringList preview = themeDir.entryList(previewFilters);
752 if (!preview.isEmpty()) {
753 tarArgs.append(QStringLiteral("%1/%2/%3").arg(body).arg(theme, preview[0]));
754 }
755
756 QStringList sourceImgFilters;
757 sourceImgFilters << theme + QLatin1StringView(".jpg") << theme + QLatin1StringView(".png") << theme + QLatin1StringView(".jpeg");
758 QStringList sourceImg = themeDir.entryList(sourceImgFilters);
759 if (!sourceImg.isEmpty()) {
760 tarArgs.append(QStringLiteral("%1/%2/%3").arg(body).arg(theme, sourceImg[0]));
761 }
762
763 QProcess archiver;
764 switch (archiver.execute(QStringLiteral("tar"), tarArgs)) {
765 case -2:
766 QMessageBox::critical(parent, tr("Archiving failed"), tr("Archiving process cannot be started."));
767 break;
768 case -1:
769 QMessageBox::critical(parent, tr("Archiving failed"), tr("Archiving process crashed."));
770 break;
771 case 0:
772 mDebug() << "Archived the theme successfully.";
773 break;
774 }
775 archiver.waitForFinished();
776 return QStringLiteral("%1/%2.tar.gz").arg(QDir::tempPath(), theme);
777}
778
779void MapWizard::deleteArchive(const QString &mapId)
780{
781 QStringList splitMapId(mapId.split(QLatin1Char('/')));
782 QString theme = splitMapId[1];
783 QFile::remove(QStringLiteral("%1/%2.tar.gz").arg(QDir::tempPath(), theme));
784}
785
786bool MapWizard::validateCurrentPage()
787{
788 if (currentId() == WelcomePage) {
789 updateOwsServiceType();
790 return true;
791 }
792 if (currentId() == WmsSelectionPage && !d->m_serverCapabilitiesValid) {
793 d->uiWidget.progressBarWmsCapabilities->setVisible(true);
794 QString serviceString = d->uiWidget.radioButtonWms->isChecked() ? QStringLiteral("WMS")
795 : d->uiWidget.radioButtonWmts->isChecked() ? QStringLiteral("WMTS")
796 : QString();
797 d->owsManager.queryOwsCapabilities(QUrl(d->uiWidget.lineEditWmsUrl->text()), serviceString);
798 button(MapWizard::NextButton)->setEnabled(false);
799 return false;
800 }
801
802 if ((currentId() == LayerSelectionPage && !d->m_previewImageValid) || (currentId() == XYZUrlPage && !d->m_previewImageValid)) {
803 if (d->mapProviderType == MapWizardPrivate::WmsMap && d->uiWidget.listViewWmsLayers->currentIndex().isValid()) {
804 QStringList selectedList;
805 QModelIndexList selectedIndexes = d->uiWidget.listViewWmsLayers->selectionModel()->selectedIndexes();
806 for (auto selectedIndex : std::as_const(selectedIndexes)) {
807 selectedList << d->sortModel->data(selectedIndex, layerIdRole).toString();
808 }
809 d->selectedLayers = selectedList;
810
811 QString projection;
812 if (d->uiWidget.comboBoxWmsMaps->currentText() == tr("Equirectangular (epsg:4326)"))
813 projection = QStringLiteral("epsg:4326");
814 else if (d->uiWidget.comboBoxWmsMaps->currentText() == tr("Equirectangular (crs:84)"))
815 projection = QStringLiteral("crs:84");
816 else
817 projection = QStringLiteral("epsg:3857");
818 d->selectedProjection = projection;
819 QString format = d->uiWidget.comboBoxWmsFormat->currentText();
820 QStringList styles = d->owsManager.wmsCapabilities().styles(d->selectedLayers);
821 d->owsManager.queryWmsPreviewImage(QUrl(d->uiWidget.lineEditWmsUrl->text()),
822 d->selectedLayers.join(QLatin1Char(',')),
823 projection,
824 format,
825 styles.join(QLatin1Char(',')));
826 setLayerButtonsVisible(false);
827 button(MapWizard::NextButton)->setEnabled(false);
828 } else if (d->mapProviderType == MapWizardPrivate::WmtsMap && d->uiWidget.listViewWmsLayers->currentIndex().isValid()) {
829 QStringList selectedList;
830 QModelIndexList selectedIndexes = d->uiWidget.listViewWmsLayers->selectionModel()->selectedIndexes();
831 for (auto selectedIndex : std::as_const(selectedIndexes)) {
832 selectedList << d->sortModel->data(selectedIndex, layerIdRole).toString();
833 }
834 d->selectedLayers = selectedList;
835
836 QString tileMatrixSet = d->uiWidget.comboBoxWmsMaps->currentText();
837 QString tileFormat = d->uiWidget.comboBoxWmsFormat->currentText();
838 QString url = d->owsManager.wmtsCapabilities().wmtsTileResource()[d->selectedLayers.first()][tileFormat];
839 QString style = d->owsManager.wmtsCapabilities().style(d->selectedLayers.first());
840 d->owsManager.queryWmtsPreviewImage(url, style, tileMatrixSet);
841 setLayerButtonsVisible(false);
842 button(MapWizard::NextButton)->setEnabled(false);
843 } else if (d->mapProviderType == MapWizardPrivate::StaticUrlMap) {
844 QString urlString = d->uiWidget.comboBoxStaticUrlServer->currentText();
845 d->owsManager.queryXYZPreviewImage(urlString);
846 d->staticUrlServerList.removeAll(urlString);
847 d->staticUrlServerList.prepend(urlString);
848 // Reset the Theme Description page
849 d->uiWidget.lineEditTitle->clear();
850 d->uiWidget.lineEditTheme->clear();
851 d->uiWidget.textEditDesc->clear();
852 d->uiWidget.labelPreview->clear();
853 d->uiWidget.lineEditTitle->setFocus();
854 button(MapWizard::NextButton)->setEnabled(false);
855 }
856 return false;
857 }
858
859 if (currentId() == GlobalSourceImagePage) {
860 d->sourceImage = d->uiWidget.lineEditSource->text();
861 if (d->sourceImage.isEmpty()) {
862 QMessageBox::information(this, tr("Source Image"), tr("Please specify a source image."));
863 d->uiWidget.lineEditSource->setFocus();
864 return false;
865 }
866
867 if (!QFileInfo::exists(d->sourceImage)) {
868 QMessageBox::information(this, tr("Source Image"), tr("The source image you specified does not exist. Please specify a different one."));
869 d->uiWidget.lineEditSource->setFocus();
870 d->uiWidget.lineEditSource->selectAll();
871 return false;
872 }
873
874 if (QImage(d->sourceImage).isNull()) {
876 tr("Source Image"),
877 tr("The source image you specified does not seem to be an image. Please specify a different image file."));
878 d->uiWidget.lineEditSource->setFocus();
879 d->uiWidget.lineEditSource->selectAll();
880 return false;
881 }
882 // Reset the Theme Description page
883 d->uiWidget.lineEditTitle->clear();
884 d->uiWidget.lineEditTheme->clear();
885 d->uiWidget.textEditDesc->clear();
886 d->uiWidget.labelPreview->clear();
887 d->previewImage = QImage(d->sourceImage).scaled(100, 100, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
888 ;
889 QPixmap previewPixmap = QPixmap::fromImage(d->previewImage);
890 d->uiWidget.labelPreview->setPixmap(previewPixmap);
891 d->uiWidget.labelPreview->resize(QSize(100, 100));
892 d->uiWidget.labelThumbnail->setPixmap(previewPixmap);
893 d->uiWidget.labelThumbnail->resize(QSize(100, 100));
894 }
895
896 if (currentId() == ThemeInfoPage) {
897 if (d->mapProviderType == MapWizardPrivate::WmsMap && !d->m_legendImageValid) {
898 QString legendUrl = d->owsManager.wmsCapabilities().legendUrl(d->selectedLayers.first());
899 if (!legendUrl.isEmpty()) {
900 d->m_legendImageValid = true;
901 d->owsManager.queryWmsLegendImage(QUrl(legendUrl));
902 button(MapWizard::NextButton)->setEnabled(false);
903 return false;
904 }
905 }
906 if (d->uiWidget.lineEditTitle->text().isEmpty()) {
907 QMessageBox::information(this, tr("Map Title"), tr("Please specify a map title."));
908 d->uiWidget.lineEditTitle->setFocus();
909 return false;
910 }
911
912 d->mapTheme = d->uiWidget.lineEditTheme->text();
913 if (d->mapTheme.isEmpty()) {
914 QMessageBox::information(this, tr("Map Name"), tr("Please specify a map name."));
915 d->uiWidget.lineEditTheme->setFocus();
916 return false;
917 }
918
919 const QDir destinationDir(QStringLiteral("%1/maps/earth/%2").arg(MarbleDirs::localPath(), d->mapTheme));
920 if (destinationDir.exists()) {
921 QMessageBox::information(this, tr("Map Name"), tr("Please specify another map name, since there is already a map named \"%1\".").arg(d->mapTheme));
922 d->uiWidget.lineEditTheme->setFocus();
923 d->uiWidget.lineEditTheme->selectAll();
924 return false;
925 }
926
927 if (d->previewImage.isNull()) {
928 QMessageBox::information(this, tr("Preview Image"), tr("Please specify a preview image."));
929 d->uiWidget.pushButtonPreview->setFocus();
930 return false;
931 }
932 }
933 if (currentId() == LegendPage && !d->m_levelZeroTileValid && d->mapProviderType != MapWizardPrivate::StaticImageMap) {
934 if (d->mapProviderType == MapWizardPrivate::WmsMap) {
935 QString projection;
936 if (d->uiWidget.comboBoxWmsMaps->currentText() == tr("Equirectangular (epsg:4326)"))
937 projection = QStringLiteral("epsg:4326");
938 else if (d->uiWidget.comboBoxWmsMaps->currentText() == tr("Equirectangular (crs:84)"))
939 projection = QStringLiteral("crs:84");
940 else
941 projection = QStringLiteral("epsg:3857");
942 d->selectedProjection = projection;
943 QString format = d->uiWidget.comboBoxWmsFormat->currentText();
944 QStringList styles = d->owsManager.wmsCapabilities().styles(d->selectedLayers);
945 d->owsManager.queryWmsLevelZeroTile(QUrl(d->uiWidget.lineEditWmsUrl->text()), d->selectedLayers.first(), projection, format, styles.first());
946 } else if (d->mapProviderType == MapWizardPrivate::WmtsMap) {
947 QStringList selectedList;
948 QModelIndexList selectedIndexes = d->uiWidget.listViewWmsLayers->selectionModel()->selectedIndexes();
949 for (auto selectedIndex : std::as_const(selectedIndexes)) {
950 selectedList << d->sortModel->data(selectedIndex, layerIdRole).toString();
951 }
952 d->selectedLayers = selectedList;
953
954 QString tileMatrixSet = d->uiWidget.comboBoxWmsMaps->currentText();
955 QString tileFormat = d->uiWidget.comboBoxWmsFormat->currentText();
956 QString url = d->owsManager.wmtsCapabilities().wmtsTileResource()[d->selectedLayers.first()][tileFormat];
957 QString style = d->owsManager.wmtsCapabilities().style(d->selectedLayers.first());
958 d->owsManager.queryWmtsLevelZeroTile(url, style, tileMatrixSet);
959 } else if (d->mapProviderType == MapWizardPrivate::StaticUrlMap) {
960 QString urlString = d->uiWidget.comboBoxStaticUrlServer->currentText();
961 d->owsManager.queryXYZLevelZeroTile(urlString);
962 }
963 button(MapWizard::NextButton)->setEnabled(false);
964 return false;
965 }
966
968}
969
970int MapWizard::nextId() const
971{
972 switch (currentId()) {
973 case WelcomePage:
974 if (d->uiWidget.radioButtonWms->isChecked()) {
975 d->mapProviderType = MapWizardPrivate::WmsMap;
976 return WmsSelectionPage;
977 } else if (d->uiWidget.radioButtonWmts->isChecked()) {
978 d->mapProviderType = MapWizardPrivate::WmtsMap;
979 return WmsSelectionPage;
980 } else if (d->uiWidget.radioButtonBitmap->isChecked()) {
981 d->mapProviderType = MapWizardPrivate::StaticImageMap;
982 return GlobalSourceImagePage;
983 } else if (d->uiWidget.radioButtonStaticUrl->isChecked()) {
984 d->mapProviderType = MapWizardPrivate::StaticUrlMap;
985 return XYZUrlPage;
986 }
987 break;
988
989 case WmsSelectionPage: // WMS Servers
990 return LayerSelectionPage;
991
992 case LayerSelectionPage: // WMS Layers
993 return ThemeInfoPage;
994
995 case GlobalSourceImagePage: // Static Image
996 return ThemeInfoPage;
997
998 case ThemeInfoPage:
999 return LegendPage;
1000
1001 case LegendPage:
1002 return SummaryPage;
1003
1004 case SummaryPage: // Finish
1005 return -1;
1006
1007 default:
1008 break;
1009 }
1010
1011 return currentId() + 1;
1012}
1013
1014void MapWizard::cleanupPage(int id)
1015{
1016 if (d->mapProviderType == MapWizardPrivate::StaticUrlMap) {
1017 if (id == ThemeInfoPage) {
1018 d->levelZero.clear();
1019 d->preview.clear();
1020 }
1021 }
1023}
1024
1025GeoSceneDocument *MapWizard::createDocument()
1026{
1027 auto document = new GeoSceneDocument;
1028
1029 GeoSceneHead *head = document->head();
1030 head->setName(d->uiWidget.lineEditTitle->text());
1031 head->setTheme(d->uiWidget.lineEditTheme->text());
1032 head->setTarget(QStringLiteral("earth"));
1033 head->setDescription(d->uiWidget.textEditDesc->document()->toHtml());
1034 head->setVisible(true);
1035
1036 GeoSceneIcon *icon = head->icon();
1037 icon->setPixmap(QStringLiteral("%1-preview.png").arg(document->head()->theme()));
1038
1039 GeoSceneZoom *zoom = head->zoom();
1040 zoom->setMinimum(900);
1041 zoom->setMaximum(3500);
1042 zoom->setDiscrete(false);
1043
1044 GeoSceneTileDataset *backdropTexture = nullptr;
1045 bool isBackdropTextureAvailable =
1046 d->uiWidget.checkBoxWmsBackdrop->isEnabled() && d->uiWidget.checkBoxWmsBackdrop->isChecked() && d->uiWidget.radioButtonOpenStreetMap->isChecked();
1047 if (isBackdropTextureAvailable) {
1048 if (d->uiWidget.radioButtonXYZServer) {
1049 backdropTexture = new GeoSceneTileDataset(QStringLiteral("backdrop"));
1050 backdropTexture->setExpire(31536000);
1051 backdropTexture->setSourceDir(QLatin1StringView("earth/openstreetmap"));
1052 backdropTexture->setFileFormat(QStringLiteral("PNG"));
1053 backdropTexture->addDownloadPolicy(DownloadBrowse, 20);
1054 backdropTexture->addDownloadPolicy(DownloadBulk, 2);
1055 backdropTexture->addDownloadUrl(QUrl(QStringLiteral("https://tile.openstreetmap.org/")));
1056 backdropTexture->setMaximumTileLevel(20);
1057 backdropTexture->setTileSize(QSize(256, 256));
1058 backdropTexture->setLevelZeroRows(1);
1059 backdropTexture->setLevelZeroColumns(1);
1060 backdropTexture->setServerLayout(new OsmServerLayout(backdropTexture));
1061 backdropTexture->setTileProjection(GeoSceneAbstractTileProjection::Mercator);
1062 }
1063 }
1064
1065 auto texture = new GeoSceneTileDataset(QStringLiteral("map"));
1066 texture->setExpire(31536000);
1067 texture->setSourceDir(QLatin1StringView("earth/") + document->head()->theme());
1068 if (d->mapProviderType == MapWizardPrivate::WmsMap) {
1069 texture->setFileFormat(d->owsManager.resultFormat());
1070 QStringList styles = d->owsManager.wmsCapabilities().styles(d->selectedLayers);
1071 QUrl downloadUrl = QUrl(d->uiWidget.lineEditWmsUrl->text());
1072 QUrlQuery urlQuery;
1073 urlQuery.addQueryItem(QStringLiteral("layers"), d->selectedLayers.join(QLatin1Char(',')));
1074 urlQuery.addQueryItem(QStringLiteral("styles"), styles.join(QStringLiteral(",")));
1075 bool isBackdropAvailable = d->uiWidget.checkBoxWmsBackdrop->isEnabled() && d->uiWidget.checkBoxWmsBackdrop->isChecked();
1076 urlQuery.addQueryItem(QStringLiteral("transparent"), isBackdropTextureAvailable ? QStringLiteral("true") : QStringLiteral("false"));
1077
1078 if (d->uiWidget.checkBoxWmsBackdrop->isChecked() && d->uiWidget.radioButtonColor->isChecked()) {
1079 QString bgColorName = d->uiWidget.labelBackgroundColor->palette().color(QPalette::Window).name();
1080 bgColorName = bgColorName.remove(QStringLiteral("#"));
1081 bgColorName = QStringLiteral("0x") + bgColorName;
1082 urlQuery.addQueryItem(QStringLiteral("bgcolor"), bgColorName);
1083 }
1084 downloadUrl.setQuery(urlQuery);
1085 texture->addDownloadUrl(downloadUrl);
1086 texture->setMaximumTileLevel(20);
1087 texture->setTileSize(QSize(256, 256));
1088 texture->setLevelZeroRows(1);
1089 texture->setLevelZeroColumns(1);
1090 texture->setServerLayout(new WmsServerLayout(texture));
1091 if (d->uiWidget.comboBoxWmsMaps->currentText() == tr("Web Mercator (epsg:3857)")) {
1092 texture->setTileProjection(GeoSceneAbstractTileProjection::Mercator);
1093 } else {
1094 texture->setTileProjection(GeoSceneAbstractTileProjection::Equirectangular);
1095 }
1096 if (isBackdropAvailable) {
1097 texture->setBlending(QStringLiteral("AlphaBlending"));
1098 }
1099 }
1100 if (d->mapProviderType == MapWizardPrivate::WmtsMap) {
1101 QString format = d->uiWidget.comboBoxWmsFormat->currentText();
1102 texture->setFileFormat(format);
1103 QString selectedLayer = d->selectedLayers.first();
1104 QString urlString = d->owsManager.wmtsCapabilities().wmtsTileResource()[selectedLayer][format];
1105 urlString.replace(urlString.indexOf(QLatin1StringView("{Time}")), 6, QStringLiteral("current"));
1106 urlString.replace(urlString.indexOf(QLatin1StringView("{style}")), 7, d->owsManager.wmtsCapabilities().style(selectedLayer));
1107 urlString.replace(urlString.indexOf(QLatin1StringView("{Style}")), 7, d->owsManager.wmtsCapabilities().style(selectedLayer));
1108 urlString.replace(urlString.indexOf(QLatin1StringView("{TileMatrixSet}")), 15, d->uiWidget.comboBoxWmsMaps->currentText());
1109 QUrl downloadUrl = QUrl(urlString);
1110 texture->addDownloadPolicy(DownloadBrowse, 20);
1111 texture->addDownloadPolicy(DownloadBulk, 2);
1112 texture->addDownloadUrl(downloadUrl);
1113 texture->setMaximumTileLevel(20);
1114 texture->setTileSize(QSize(256, 256));
1115 texture->setLevelZeroRows(1);
1116 texture->setLevelZeroColumns(1);
1117 texture->setServerLayout(new WmtsServerLayout(texture));
1118 texture->setTileProjection(GeoSceneAbstractTileProjection::Mercator);
1119 }
1120
1121 else if (d->mapProviderType == MapWizardPrivate::StaticUrlMap) {
1122 texture->setFileFormat(d->format);
1123 QUrl downloadUrl = QUrl(d->uiWidget.comboBoxStaticUrlServer->currentText());
1124 texture->addDownloadPolicy(DownloadBrowse, 20);
1125 texture->addDownloadPolicy(DownloadBulk, 2);
1126 texture->addDownloadUrl(downloadUrl);
1127 texture->setMaximumTileLevel(20);
1128 texture->setTileSize(QSize(256, 256));
1129 texture->setLevelZeroRows(1);
1130 texture->setLevelZeroColumns(1);
1131 texture->setServerLayout(new CustomServerLayout(texture));
1132 texture->setTileProjection(GeoSceneAbstractTileProjection::Mercator);
1133 }
1134
1135 else if (d->mapProviderType == MapWizardPrivate::StaticImageMap) {
1136 QString image = d->uiWidget.lineEditSource->text();
1137 d->format = image.right(image.length() - image.lastIndexOf(QLatin1Char('.')) - 1).toLower();
1138 texture->setFileFormat(d->format.toUpper());
1139 texture->setInstallMap(document->head()->theme() + QLatin1Char('.') + d->format);
1140 texture->setServerLayout(new MarbleServerLayout(texture));
1141 texture->setTileProjection(GeoSceneAbstractTileProjection::Equirectangular);
1142 int imageWidth = QImage(image).width();
1143 int tileSize = c_defaultTileSize;
1144
1145 float approxMaxTileLevel = log(imageWidth / (2.0 * tileSize)) / log(2.0);
1146 int maxTileLevel = 0;
1147 if (approxMaxTileLevel == int(approxMaxTileLevel)) {
1148 maxTileLevel = static_cast<int>(approxMaxTileLevel);
1149 } else {
1150 maxTileLevel = static_cast<int>(approxMaxTileLevel + 1);
1151 }
1152 texture->setMaximumTileLevel(maxTileLevel);
1153 }
1154
1155 auto layer = new GeoSceneLayer(d->uiWidget.lineEditTheme->text());
1156 layer->setBackend(QStringLiteral("texture"));
1157 layer->addDataset(backdropTexture);
1158 layer->addDataset(texture);
1159
1160 auto secondLayer = new GeoSceneLayer(QStringLiteral("standardplaces"));
1161 secondLayer->setBackend(QStringLiteral("geodata"));
1162
1163 auto cityplacemarks = new GeoSceneGeodata(QStringLiteral("cityplacemarks"));
1164 cityplacemarks->setSourceFile(QStringLiteral("cityplacemarks.kml"));
1165 secondLayer->addDataset(cityplacemarks);
1166
1167 auto baseplacemarks = new GeoSceneGeodata(QStringLiteral("baseplacemarks"));
1168 baseplacemarks->setSourceFile(QStringLiteral("baseplacemarks.kml"));
1169 secondLayer->addDataset(baseplacemarks);
1170
1171 auto elevplacemarks = new GeoSceneGeodata(QStringLiteral("elevplacemarks"));
1172 elevplacemarks->setSourceFile(QStringLiteral("elevplacemarks.kml"));
1173 secondLayer->addDataset(elevplacemarks);
1174
1175 auto observatoryplacemarks = new GeoSceneGeodata(QStringLiteral("observatoryplacemarks"));
1176 observatoryplacemarks->setSourceFile(QStringLiteral("observatoryplacemarks.kml"));
1177 secondLayer->addDataset(observatoryplacemarks);
1178
1179 auto otherplacemarks = new GeoSceneGeodata(QStringLiteral("otherplacemarks"));
1180 otherplacemarks->setSourceFile(QStringLiteral("otherplacemarks.kml"));
1181 secondLayer->addDataset(otherplacemarks);
1182
1183 auto boundaryplacemarks = new GeoSceneGeodata(QStringLiteral("boundaryplacemarks"));
1184 boundaryplacemarks->setSourceFile(QStringLiteral("boundaryplacemarks.kml"));
1185 secondLayer->addDataset(boundaryplacemarks);
1186
1187 GeoSceneMap *map = document->map();
1188
1189 if (d->mapProviderType == MapWizardPrivate::WmsMap) {
1190 QString bbox;
1191 bbox = d->owsManager.wmsCapabilities().boundingBoxNSEWDegrees(d->selectedLayers, d->selectedProjection);
1192 QStringList bboxList = bbox.split(QLatin1Char(','));
1193 // Only center if the bbox does not cover roughly the whole earth
1194 if (bboxList.at(0).toDouble() < 85 && bboxList.at(1).toDouble() > -85 && bboxList.at(2).toDouble() < 179 && bboxList.at(3).toDouble() > -179) {
1195 map->setCenter(bbox);
1196 }
1197 }
1198
1199 map->addLayer(layer);
1200 map->addLayer(secondLayer);
1201
1202 GeoSceneSettings *settings = document->settings();
1203 // GeoSceneLegend *legend = document->legend();
1204
1205 /*
1206 if( d->uiWidget.checkBoxCoord->checkState() == Qt::Checked )
1207 {
1208 GeoSceneProperty *coorGrid = new GeoSceneProperty( "coordinate-grid" );
1209 coorGrid->setDefaultValue( true );
1210 coorGrid->setAvailable( true );
1211 settings->addProperty( coorGrid );
1212
1213 GeoSceneSection *coorSection = new GeoSceneSection( "coordinate-grid" );
1214 coorSection->setHeading( "Coordinate Grid" );
1215 coorSection->setCheckable( true );
1216 coorSection->setConnectTo( "coordinate-grid" );
1217 coorSection->setSpacing( 12 );
1218 legend->addSection( coorSection );
1219 }
1220
1221 if( d->uiWidget.checkBoxInterest->checkState() == Qt::Checked )
1222 {
1223 GeoSceneProperty *poiProperty = new GeoSceneProperty( "otherplaces" );
1224 poiProperty->setDefaultValue( true );
1225 poiProperty->setAvailable( true );
1226 settings->addProperty( poiProperty );
1227
1228 GeoSceneSection *poiSection = new GeoSceneSection( "otherplaces" );
1229 poiSection->setHeading( "Places of Interest" );
1230 poiSection->setCheckable( true );
1231 poiSection->setConnectTo( "otherplaces" );
1232 poiSection->setSpacing( 12 );
1233
1234 GeoSceneItem *geoPole = new GeoSceneItem( "geographic-pole" );
1235 GeoSceneIcon *geoPoleIcon = geoPole->icon();
1236 geoPole->setText( tr("Geographic Pole") );
1237 geoPoleIcon->setPixmap( "bitmaps/pole_1.png" );
1238 poiSection->addItem( geoPole );
1239
1240 GeoSceneItem *magPole = new GeoSceneItem( "magnetic-pole" );
1241 GeoSceneIcon *magPoleIcon = magPole->icon();
1242 magPole->setText( tr("Magnetic Pole") );
1243 magPoleIcon->setPixmap( "bitmaps/pole_2.png" );
1244 poiSection->addItem( magPole );
1245
1246 GeoSceneItem *airport = new GeoSceneItem( "airport" );
1247 GeoSceneIcon *airportIcon = airport->icon();
1248 airport->setText( tr("Airport") );
1249 airportIcon->setPixmap( "bitmaps/airport.png" );
1250 poiSection->addItem( airport );
1251
1252 GeoSceneItem *shipwreck = new GeoSceneItem( "shipwreck" );
1253 GeoSceneIcon *shipwreckIcon = shipwreck->icon();
1254 shipwreck->setText( tr("Shipwreck") );
1255 shipwreckIcon->setPixmap( "bitmaps/shipwreck.png" );
1256 poiSection->addItem( shipwreck );
1257
1258 GeoSceneItem *observatory = new GeoSceneItem( "observatory" );
1259 GeoSceneIcon *observatoryIcon = observatory->icon();
1260 observatory->setText( tr("Observatory") );
1261 observatoryIcon->setPixmap( "bitmaps/observatory.png" );
1262 poiSection->addItem( observatory );
1263
1264 legend->addSection( poiSection );
1265 }
1266
1267 if( d->uiWidget.checkBoxTer->checkState() == Qt::Checked )
1268 {
1269 GeoSceneProperty *terrainProperty = new GeoSceneProperty( "terrain" );
1270 terrainProperty->setDefaultValue( true );
1271 terrainProperty->setAvailable( true );
1272 settings->addProperty( terrainProperty );
1273
1274 GeoSceneSection *terrainSection = new GeoSceneSection( "terrain" );
1275 terrainSection->setHeading( "Terrain" );
1276 terrainSection->setCheckable( true );
1277 terrainSection->setConnectTo( "terrain" );
1278 terrainSection->setSpacing( 12 );
1279
1280 GeoSceneItem *mountain = new GeoSceneItem( "mountain" );
1281 GeoSceneIcon *mountainIcon = mountain->icon();
1282 mountain->setText( tr("Mountain") );
1283 mountainIcon->setPixmap( "bitmaps/mountain_1.png" );
1284 terrainSection->addItem( mountain );
1285
1286 GeoSceneItem *volcano = new GeoSceneItem( "volcano" );
1287 GeoSceneIcon *volcanoIcon = volcano->icon();
1288 volcano->setText( tr("Volcano") );
1289 volcanoIcon->setPixmap( "bitmaps/volcano_1.png" );
1290 terrainSection->addItem( volcano );
1291
1292 legend->addSection( terrainSection );
1293
1294 }
1295
1296 if( d->uiWidget.checkBoxPop->checkState() == Qt::Checked )
1297 {
1298 GeoSceneProperty *placesProperty = new GeoSceneProperty( "places" );
1299 placesProperty->setDefaultValue( true );
1300 placesProperty->setAvailable( true );
1301 settings->addProperty( placesProperty );
1302
1303 GeoSceneProperty *citiesProperty = new GeoSceneProperty( "cities" );
1304 citiesProperty->setDefaultValue( true );
1305 citiesProperty->setAvailable( true );
1306 settings->addProperty( citiesProperty );
1307 }
1308
1309 if( d->uiWidget.checkBoxBorder->checkState() == Qt::Checked )
1310 {
1311 GeoSceneSection *bordersSection = new GeoSceneSection( "borders" );
1312 bordersSection->setHeading( "Boundaries" );
1313 bordersSection->setCheckable( true );
1314 bordersSection->setConnectTo( "borders" );
1315 bordersSection->setSpacing( 12 );
1316
1317 GeoSceneItem *internationalBoundary = new GeoSceneItem( "international-boundary" );
1318 GeoSceneIcon *internationalBoundaryIcon = internationalBoundary->icon();
1319 internationalBoundary->setText( tr("International") );
1320 internationalBoundaryIcon->setPixmap( "bitmaps/border_1.png" );
1321 bordersSection->addItem( internationalBoundary );
1322
1323 GeoSceneItem *stateBoundary = new GeoSceneItem( "state" );
1324 GeoSceneIcon *stateBoundaryIcon = stateBoundary->icon();
1325 stateBoundary->setText( tr("State") );
1326 stateBoundaryIcon->setPixmap( "bitmaps/border_2.png" );
1327 bordersSection->addItem( stateBoundary );
1328
1329 GeoSceneProperty *bordersProperty = new GeoSceneProperty( "borders" );
1330 bordersProperty->setDefaultValue( false );
1331 bordersProperty->setAvailable( true );
1332 settings->addProperty( bordersProperty );
1333
1334 GeoSceneProperty *intBoundariesProperty = new GeoSceneProperty( "international-boundaries" );
1335 intBoundariesProperty->setDefaultValue( false );
1336 intBoundariesProperty->setAvailable( true );
1337 settings->addProperty( intBoundariesProperty );
1338
1339 GeoSceneProperty *stateBounderiesProperty = new GeoSceneProperty( "state-boundaries" );
1340 stateBounderiesProperty->setDefaultValue( false );
1341 stateBounderiesProperty->setAvailable( true );
1342 settings->addProperty( stateBounderiesProperty );
1343
1344 legend->addSection( bordersSection );
1345
1346 GeoSceneLayer* mwdbii = new GeoSceneLayer( "mwdbii" );
1347 mwdbii->setBackend( "vector" );
1348 mwdbii->setRole( "polyline" );
1349
1350 GeoSceneVector* vector = new GeoSceneVector( "pdiffborder" );
1351 vector->setFeature( "border" );
1352 vector->setFileFormat( "PNT" );
1353 vector->setSourceFile( "earth/mwdbii/PDIFFBORDER.PNT" );
1354 vector->pen().setColor( "#ffe300" );
1355 mwdbii->addDataset( vector );
1356 map->addLayer( mwdbii );
1357 }
1358 */
1359 auto overviewmap = new GeoSceneProperty(QStringLiteral("overviewmap"));
1360 overviewmap->setDefaultValue(true);
1361 overviewmap->setAvailable(true);
1362 settings->addProperty(overviewmap);
1363
1364 auto compass = new GeoSceneProperty(QStringLiteral("compass"));
1365 compass->setDefaultValue(true);
1366 compass->setAvailable(true);
1367 settings->addProperty(compass);
1368
1369 auto scalebar = new GeoSceneProperty(QStringLiteral("scalebar"));
1370 scalebar->setDefaultValue(true);
1371 scalebar->setAvailable(true);
1372 settings->addProperty(scalebar);
1373
1374 return document;
1375}
1376
1377void MapWizard::accept()
1378{
1379 Q_ASSERT(d->mapProviderType != MapWizardPrivate::NoMap);
1380
1381 Q_ASSERT(d->format == d->format.toLower());
1382 Q_ASSERT(!d->mapTheme.isEmpty());
1383
1384 if (d->mapProviderType == MapWizardPrivate::StaticImageMap) {
1385 d->sourceImage = d->uiWidget.lineEditSource->text();
1386 Q_ASSERT(!d->sourceImage.isEmpty());
1387 Q_ASSERT(QFile(d->sourceImage).exists());
1388 } else if (d->mapProviderType == MapWizardPrivate::WmsMap) {
1389 Q_ASSERT(!d->owsManager.wmsCapabilities().layers().isEmpty());
1390 Q_ASSERT(!d->levelZero.isNull());
1391 } else if (d->mapProviderType == MapWizardPrivate::WmtsMap) {
1392 Q_ASSERT(!d->owsManager.wmtsCapabilities().layers().isEmpty());
1393 Q_ASSERT(!d->levelZero.isNull());
1394 } else if (d->mapProviderType == MapWizardPrivate::StaticUrlMap) {
1395 Q_ASSERT(!d->levelZero.isNull());
1396 Q_ASSERT(!QImage::fromData(d->levelZero).isNull());
1397 }
1398
1399 QSharedPointer<GeoSceneDocument> document(createDocument());
1400 Q_ASSERT(!document->head()->description().isEmpty());
1401 Q_ASSERT(!document->head()->name().isEmpty());
1402
1403 if (createFiles(document.data())) {
1404 if (d->mapProviderType == MapWizardPrivate::WmsMap) {
1405 if (!d->owsManager.wmsCapabilities()
1406 .legendUrl(d->sortModel->data(d->uiWidget.listViewWmsLayers->currentIndex(), layerIdRole).toString())
1407 .isEmpty()) {
1408 createWmsLegend();
1409 }
1410 } else if (d->mapProviderType == MapWizardPrivate::StaticImageMap || d->mapProviderType == MapWizardPrivate::StaticUrlMap) {
1411 createLegend();
1412 }
1413
1415 d->uiWidget.lineEditTitle->clear();
1416 d->uiWidget.lineEditTheme->clear();
1417 d->uiWidget.textEditDesc->clear();
1418 d->uiWidget.labelPreview->clear();
1419 d->uiWidget.lineEditSource->clear();
1420 QTimer::singleShot(0, this, SLOT(restart()));
1421 }
1422
1423 else {
1424 QMessageBox::critical(this, tr("Problem while creating files"), tr("Check if a theme with the same name exists."));
1425 return;
1426 }
1427}
1428
1429void MapWizard::showPreview()
1430{
1431 QSharedPointer<GeoSceneDocument> document(createDocument());
1432
1433 if (createFiles(document.data())) {
1434 if (d->mapProviderType == MapWizardPrivate::WmsMap) {
1435 if (!d->owsManager.wmsCapabilities()
1436 .legendUrl(d->sortModel->data(d->uiWidget.listViewWmsLayers->currentIndex(), layerIdRole).toString())
1437 .isEmpty()) {
1438 createWmsLegend();
1439 }
1440 } else if (d->mapProviderType == MapWizardPrivate::StaticImageMap || d->mapProviderType == MapWizardPrivate::StaticUrlMap) {
1441 createLegend();
1442 }
1443 }
1444
1445 QPointer<PreviewDialog> previewDialog = new PreviewDialog(this, document.data()->head()->mapThemeId());
1446 previewDialog->exec();
1447 delete previewDialog;
1448}
1449
1450void MapWizard::updateSearchFilter(const QString &text)
1451{
1452 d->sortModel->setFilterFixedString(text);
1453}
1454
1455void MapWizard::updateListViewSelection()
1456{
1457 QAbstractItemView::SelectionMode selectionModeWMS =
1458 d->uiWidget.checkBoxWmsMultipleSelections->isChecked() ? QAbstractItemView::MultiSelection : QAbstractItemView::ExtendedSelection;
1459 QAbstractItemView::SelectionMode selectionMode = d->owsManager.owsServiceType() == WmtsType ? QAbstractItemView::SingleSelection : selectionModeWMS;
1460 d->uiWidget.listViewWmsLayers->setSelectionMode(selectionMode);
1461 d->uiWidget.checkBoxWmsMultipleSelections->setVisible(d->uiWidget.radioButtonWms->isChecked());
1462}
1463
1464void MapWizard::updateBackdropCheckBox()
1465{
1466 // The only backdrop supported is the Mercator-based OSM tile server map
1467 bool isMercator = d->uiWidget.comboBoxWmsMaps->currentText() == QStringLiteral("Web Mercator (epsg:3857)");
1468 d->uiWidget.checkBoxWmsBackdrop->setEnabled(isMercator);
1469 d->uiWidget.tabCustomizeBackdrop->setEnabled(isMercator && d->uiWidget.checkBoxWmsBackdrop->isChecked());
1470}
1471
1472void MapWizard::updateOwsServiceType()
1473{
1474 if (d->uiWidget.radioButtonWms->isChecked()) {
1475 d->uiWidget.labelWmsServer->setText(tr("WMS Server"));
1476 d->uiWidget.labelOwsServiceHeader->setText(
1477 tr("<h4>WMS Server</h4>Please choose a <a href=\"https://en.wikipedia.org/wiki/Web_Map_Service\">WMS</a> server or enter a custom server URL."));
1478 d->uiWidget.comboBoxWmsServer->clear();
1479 d->uiWidget.comboBoxWmsServer->addItems(d->wmsServerList);
1480 d->uiWidget.comboBoxWmsServer->addItem(tr("Custom"), QStringLiteral("http://"));
1481 d->uiWidget.comboBoxWmsServer->setCurrentText(tr("Custom"));
1482
1483 } else if (d->uiWidget.radioButtonWmts->isChecked()) {
1484 d->uiWidget.labelWmsServer->setText(tr("WMTS Server"));
1485 d->uiWidget.labelOwsServiceHeader->setText(
1486 tr("<h4>WMTS Server</h4>Please choose a <a href=\"https://de.wikipedia.org/wiki/Web_Map_Tile_Service\">WMTS</a> server or enter a custom server "
1487 "URL."));
1488 d->uiWidget.comboBoxWmsServer->clear();
1489 d->uiWidget.comboBoxWmsServer->addItems(d->wmtsServerList);
1490 d->uiWidget.comboBoxWmsServer->addItem(tr("Custom"), QStringLiteral("http://"));
1491 d->uiWidget.comboBoxWmsServer->setCurrentText(tr("Custom"));
1492 } else if (d->uiWidget.radioButtonStaticUrl->isChecked()) {
1493 d->uiWidget.comboBoxStaticUrlServer->clear();
1494 d->uiWidget.comboBoxStaticUrlServer->addItems(d->staticUrlServerList);
1495 // d->uiWidget.comboBoxWmsServer->addItem( tr( "Custom" ), "http://" );
1496 // d->uiWidget.comboBoxWmsServer->setCurrentText( tr( "Custom" ) );
1497 }
1498}
1499
1500void MapWizard::chooseBackgroundColor()
1501{
1502 QColor selectedColor = QColorDialog::getColor(d->uiWidget.pushButtonColor->text());
1503 if (selectedColor.isValid()) {
1504 d->uiWidget.labelBackgroundColor->setText(selectedColor.name());
1505 QPalette p = d->uiWidget.labelBackgroundColor->palette();
1506 p.setColor(QPalette::Window, selectedColor);
1507 d->uiWidget.labelBackgroundColor->setPalette(p);
1508 }
1509}
1510
1511}
1512
1513#include "MapWizard.moc" // needed for Q_OBJECT here in source
1514#include "moc_MapWizard.cpp"
This file contains the header for MapWizard.
This file contains the header for MarbleNavigator.
This file contains the headers for MarbleWidget.
Capabilities capabilities()
QAction * restart(const QObject *recvr, const char *slot, QObject *parent)
QString path(const QString &relativePath)
KIOCORE_EXPORT QString dir(const QString &fileClass)
QAction * zoom(const QObject *recvr, const char *slot, QObject *parent)
const QList< QKeySequence > & zoomIn()
const QList< QKeySequence > & zoomOut()
const QList< QKeySequence > & next()
Binds a QML item to a specific geodetic location in screen coordinates.
void clicked(bool checked)
void pressed(const QModelIndex &index)
bool isEnabled() const const
char * data()
void stateChanged(int state)
bool isValid() const const
QString name(NameFormat format) const const
QColor getColor(const QColor &initial, QWidget *parent, const QString &title, ColorDialogOptions options)
virtual void accept()
virtual void closeEvent(QCloseEvent *e) override
NoDotAndDotDot
QString absolutePath() const const
bool cd(const QString &dirName)
QStringList entryList(Filters filters, SortFlags sort) const const
QString tempPath()
bool copy(const QString &fileName, const QString &newName)
bool exists(const QString &fileName)
bool exists() const const
bool remove()
void setFileName(const QString &name)
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, Options options)
bool exists() const const
QImage fromData(QByteArrayView data, const char *format)
bool isNull() const const
QImage scaled(const QSize &size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const const
int width() const const
void setText(const QString &)
void textChanged(const QString &text)
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
void clear()
pointer data()
T & first()
bool isEmpty() const const
StandardButton critical(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons, StandardButton defaultButton)
StandardButton information(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons, StandardButton defaultButton)
Q_OBJECTQ_OBJECT
QObject * parent() const const
void setColor(ColorGroup group, ColorRole role, const QColor &color)
QPixmap fromImage(QImage &&image, Qt::ImageConversionFlags flags)
int height() const const
QSize size() const const
int width() const const
int execute(const QString &program, const QStringList &arguments)
bool waitForFinished(int msecs)
void setFilterCaseSensitivity(Qt::CaseSensitivity cs)
virtual void setSourceModel(QAbstractItemModel *sourceModel) override
QString arg(Args &&... args) const const
void clear()
QString first(qsizetype n) const const
QString fromLatin1(QByteArrayView str)
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype lastIndexOf(QChar ch, Qt::CaseSensitivity cs) const const
QString left(qsizetype n) const const
qsizetype length() const const
QString & prepend(QChar ch)
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
QString right(qsizetype n) const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
QByteArray toLatin1() const const
QString toLower() const const
QString join(QChar separator) const const
IgnoreAspectRatio
CaseInsensitive
SmoothTransformation
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void setQuery(const QString &query, ParsingMode mode)
void addQueryItem(const QString &key, const QString &value)
void setupUi(QWidget *widget)
virtual void cleanupPage(int id)
virtual bool validateCurrentPage()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 17:04:14 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.