Marble

DownloadRegionDialog.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2010 Jens-Michael Hoffmann <jmho@c-xx.com>
4//
5
6#include "DownloadRegionDialog.h"
7
8#include <cmath>
9
10#include <QButtonGroup>
11#include <QComboBox>
12#include <QDialogButtonBox>
13#include <QGroupBox>
14#include <QHBoxLayout>
15#include <QHideEvent>
16#include <QLabel>
17#include <QPushButton>
18#include <QRadioButton>
19#include <QScrollArea>
20#include <QSet>
21#include <QShowEvent>
22#include <QSpinBox>
23#include <QStandardItemModel>
24#include <QTimer>
25#include <QVBoxLayout>
26
27#include "DownloadRegion.h"
28#include "GeoDataCoordinates.h"
29#include "GeoDataLatLonAltBox.h"
30#include "GeoDataLineString.h"
31#include "GeoSceneDocument.h"
32#include "GeoSceneMap.h"
33#include "LatLonBoxWidget.h"
34#include "MarbleDebug.h"
35#include "MarbleModel.h"
36#include "MarbleWidget.h"
37#include "Route.h"
38#include "TextureLayer.h"
39#include "TileCoordsPyramid.h"
40#include "TileId.h"
41#include "TileLayer.h"
42#include "TileLevelRangeWidget.h"
43#include "TileLoaderHelper.h"
44#include "VectorTileLayer.h"
45#include "routing/RoutingManager.h"
46#include "routing/RoutingModel.h"
47
48namespace Marble
49{
50
51int const maxTilesCount = 100000;
52int const minimumRouteOffset = 0;
53int const maximumRouteOffset = 10000;
54int averageTextureTileSize = 13; // The average size of a tile in kilobytes
55int averageVectorTileSize = 30; // The average size of a vector tile in kilobytes
56
57class Q_DECL_HIDDEN DownloadRegionDialog::Private
58{
59public:
60 Private(MarbleWidget *const widget, QDialog *const dialog);
61 QWidget *createSelectionMethodBox();
62 QLayout *createTilesCounter();
63 QWidget *createOkCancelButtonBox();
64
65 bool hasRoute() const;
66 bool hasTextureLayers() const;
67 bool hasVectorLayers() const;
68 QDialog *m_dialog;
69 QLabel *m_layerLabel;
70 QComboBox *m_layerComboBox;
71 QButtonGroup *m_buttonGroup;
72 QRadioButton *m_visibleRegionMethodButton;
73 QRadioButton *m_specifiedRegionMethodButton;
74 LatLonBoxWidget *m_latLonBoxWidget;
75 TileLevelRangeWidget *m_tileLevelRangeWidget;
76 QRadioButton *m_routeDownloadMethodButton;
77 QLabel *m_routeOffsetLabel;
78 QDoubleSpinBox *m_routeOffsetSpinBox;
79 QLabel *m_tilesCountLabel;
80 QLabel *m_tileSizeInfo;
81 QPushButton *m_okButton;
82 QPushButton *m_applyButton;
83 TextureLayer const *m_textureLayer;
84 VectorTileLayer const *m_vectorTileLayer;
85 int m_visibleTileLevel;
86 MarbleModel const *const m_model;
87 MarbleWidget *const m_widget;
88 SelectionMethod m_selectionMethod;
89 GeoDataLatLonAltBox m_visibleRegion;
90 RoutingModel *m_routingModel;
91 DownloadRegion m_downloadRegion;
92 TileType m_tileType;
93};
94
95DownloadRegionDialog::Private::Private(MarbleWidget *const widget, QDialog *const dialog)
96 : m_dialog(dialog)
97 , m_layerLabel(nullptr)
98 , m_layerComboBox(nullptr)
99 , m_buttonGroup(nullptr)
100 , m_visibleRegionMethodButton(nullptr)
101 , m_specifiedRegionMethodButton(nullptr)
102 , m_latLonBoxWidget(new LatLonBoxWidget)
103 , m_tileLevelRangeWidget(new TileLevelRangeWidget)
104 , m_routeDownloadMethodButton(nullptr)
105 , m_routeOffsetLabel(nullptr)
106 , m_routeOffsetSpinBox(nullptr)
107 , m_tilesCountLabel(nullptr)
108 , m_tileSizeInfo(nullptr)
109 , m_okButton(nullptr)
110 , m_applyButton(nullptr)
111 , m_textureLayer(widget->textureLayer())
112 , m_vectorTileLayer(widget->vectorTileLayer())
113 , m_visibleTileLevel(0)
114 , m_model(widget->model())
115 , m_widget(widget)
116 , m_selectionMethod(VisibleRegionMethod)
117 , m_visibleRegion()
118 , m_routingModel(widget->model()->routingManager()->routingModel())
119{
120 m_latLonBoxWidget->setEnabled(false);
121 m_latLonBoxWidget->setLatLonBox(m_visibleRegion);
122 m_tileLevelRangeWidget->setDefaultLevel(m_visibleTileLevel);
123 m_downloadRegion.setMarbleModel(widget->model());
124}
125
126QWidget *DownloadRegionDialog::Private::createSelectionMethodBox()
127{
128 m_buttonGroup = new QButtonGroup(m_dialog);
129 m_buttonGroup->setExclusive(true);
130 m_visibleRegionMethodButton = new QRadioButton(tr("Visible region"));
131 m_buttonGroup->addButton(m_visibleRegionMethodButton);
132 m_specifiedRegionMethodButton = new QRadioButton(tr("Specify region"));
133 m_buttonGroup->addButton(m_specifiedRegionMethodButton);
134 m_routeDownloadMethodButton = new QRadioButton(tr("Download Route"));
135 m_buttonGroup->addButton(m_routeDownloadMethodButton);
136 m_routeDownloadMethodButton->setToolTip(tr("Enabled when a route exists"));
137 m_routeDownloadMethodButton->setEnabled(hasRoute());
138 m_routeDownloadMethodButton->setChecked(hasRoute());
139 m_routeOffsetSpinBox = new QDoubleSpinBox();
140 m_routeOffsetSpinBox->setEnabled(hasRoute());
141 m_routeOffsetSpinBox->setRange(minimumRouteOffset, maximumRouteOffset);
142 int defaultOffset = 500;
143 m_routeOffsetSpinBox->setValue(defaultOffset);
144 m_routeOffsetSpinBox->setSingleStep(100);
145 m_routeOffsetSpinBox->setSuffix(QStringLiteral(" m"));
146 m_routeOffsetSpinBox->setDecimals(0);
147 m_routeOffsetSpinBox->setAlignment(Qt::AlignRight);
148
149 m_routeOffsetLabel = new QLabel(tr("Offset from route:"));
150 m_routeOffsetLabel->setAlignment(Qt::AlignHCenter);
151
152 connect(m_buttonGroup, SIGNAL(buttonToggled(QAbstractButton *, bool)), m_dialog, SLOT(toggleSelectionMethod()));
153 connect(m_routingModel, SIGNAL(modelReset()), m_dialog, SLOT(updateRouteDialog()));
154 connect(m_routingModel, SIGNAL(rowsInserted(QModelIndex, int, int)), m_dialog, SLOT(updateRouteDialog()));
155 connect(m_routingModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), m_dialog, SLOT(updateRouteDialog()));
156
157 auto routeOffsetLayout = new QHBoxLayout;
158 routeOffsetLayout->addWidget(m_routeOffsetLabel);
159 routeOffsetLayout->insertSpacing(0, 25);
160 routeOffsetLayout->addWidget(m_routeOffsetSpinBox);
161
162 auto const routeLayout = new QVBoxLayout;
163 routeLayout->addWidget(m_routeDownloadMethodButton);
164 routeLayout->addLayout(routeOffsetLayout);
165
166 auto const layout = new QVBoxLayout;
167 layout->addWidget(m_visibleRegionMethodButton);
168 layout->addLayout(routeLayout);
169 layout->addWidget(m_specifiedRegionMethodButton);
170 layout->addWidget(m_latLonBoxWidget);
171
172 bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
173 m_specifiedRegionMethodButton->setVisible(!smallScreen);
174 m_latLonBoxWidget->setVisible(!smallScreen);
175
176 if (smallScreen) {
177 auto const selectionMethodWidget = new QWidget;
178 selectionMethodWidget->setLayout(layout);
179 return selectionMethodWidget;
180 } else {
181 auto const selectionMethodBox = new QGroupBox(tr("Selection Method"));
182 selectionMethodBox->setLayout(layout);
183 return selectionMethodBox;
184 }
185}
186
187QLayout *DownloadRegionDialog::Private::createTilesCounter()
188{
189 auto const description = new QLabel(tr("Number of tiles to download:"));
190 m_tilesCountLabel = new QLabel;
191 m_tileSizeInfo = new QLabel;
192
193 auto const tilesCountLayout = new QHBoxLayout;
194 tilesCountLayout->addWidget(description);
195 tilesCountLayout->addWidget(m_tilesCountLabel);
196 // tilesCountLayout->insertSpacing( 0, 5 );
197 auto const layout = new QVBoxLayout;
198 layout->addLayout(tilesCountLayout);
199 layout->addWidget(m_tileSizeInfo);
200 return layout;
201}
202
203QWidget *DownloadRegionDialog::Private::createOkCancelButtonBox()
204{
205 auto const buttonBox = new QDialogButtonBox;
206 m_okButton = buttonBox->addButton(QDialogButtonBox::Ok);
207 m_applyButton = buttonBox->addButton(QDialogButtonBox::Apply);
208 if (MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen) {
209 buttonBox->removeButton(m_applyButton);
210 m_applyButton->setVisible(false);
211 }
212 buttonBox->addButton(QDialogButtonBox::Cancel);
213 connect(buttonBox, SIGNAL(accepted()), m_dialog, SLOT(accept()));
214 connect(buttonBox, SIGNAL(rejected()), m_dialog, SLOT(reject()));
215 connect(m_applyButton, SIGNAL(clicked()), m_dialog, SIGNAL(applied()));
216 return buttonBox;
217}
218
219bool DownloadRegionDialog::Private::hasRoute() const
220{
221 return !m_routingModel->route().path().isEmpty();
222}
223
224bool DownloadRegionDialog::Private::hasTextureLayers() const
225{
226 return m_model->mapTheme()->map()->hasTextureLayers();
227}
228
229bool DownloadRegionDialog::Private::hasVectorLayers() const
230{
231 return m_model->mapTheme()->map()->hasVectorLayers();
232}
233
234DownloadRegionDialog::DownloadRegionDialog(MarbleWidget *const widget, QWidget *const parent, Qt::WindowFlags const f)
235 : QDialog(parent, f)
236 , d(new Private(widget, this))
237{
238 setWindowTitle(tr("Download Region"));
239 auto const layout = new QVBoxLayout;
240 d->m_layerLabel = new QLabel(tr("Tile type to be downloaded:"));
241 d->m_layerComboBox = new QComboBox();
242 d->m_layerComboBox->addItem(tr("Texture tiles"));
243 d->m_layerComboBox->addItem(tr("Vector tiles"));
244 d->m_layerComboBox->setToolTip(tr("Allows selection between layer types that are visibly being rendered."));
245 updateTileLayer();
246
247 layout->addWidget(d->m_layerLabel);
248 layout->addWidget(d->m_layerComboBox);
249 layout->addWidget(d->createSelectionMethodBox());
250 layout->addWidget(d->m_tileLevelRangeWidget);
251 layout->addStretch();
252 layout->addLayout(d->createTilesCounter());
253
254 if (MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen) {
255 auto widget = new QWidget(this);
256 widget->setLayout(layout);
257 auto scrollArea = new QScrollArea(this);
258 scrollArea->setFrameShape(QFrame::NoFrame);
259 scrollArea->setWidget(widget);
260 auto const mainLayout = new QVBoxLayout;
261 mainLayout->addWidget(scrollArea);
262 mainLayout->addWidget(d->createOkCancelButtonBox());
263 setLayout(mainLayout);
264 } else {
265 layout->addWidget(d->createOkCancelButtonBox());
266 setLayout(layout);
267 }
268
269 connect(d->m_layerComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &DownloadRegionDialog::updateTileCount);
270 connect(d->m_latLonBoxWidget, &Marble::LatLonBoxWidget::valueChanged, this, &DownloadRegionDialog::updateTileCount);
271 connect(d->m_tileLevelRangeWidget, &TileLevelRangeWidget::topLevelChanged, this, &DownloadRegionDialog::updateTileCount);
272 connect(d->m_tileLevelRangeWidget, &TileLevelRangeWidget::bottomLevelChanged, this, &DownloadRegionDialog::updateTileCount);
273 connect(d->m_routeOffsetSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &DownloadRegionDialog::updateTileCount);
274 connect(d->m_routeOffsetSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &DownloadRegionDialog::setOffsetUnit);
275 connect(d->m_model, &MarbleModel::themeChanged, this, &DownloadRegionDialog::delayUpdateTileLayer);
276}
277
278DownloadRegionDialog::~DownloadRegionDialog()
279{
280 delete d;
281}
282
283void DownloadRegionDialog::setAllowedTileLevelRange(int const minimumTileLevel, int const maximumTileLevel)
284{
285 d->m_tileLevelRangeWidget->setAllowedLevelRange(minimumTileLevel, maximumTileLevel);
286}
287
288void DownloadRegionDialog::setVisibleTileLevel(int const tileLevel)
289{
290 d->m_visibleTileLevel = tileLevel;
291 d->m_tileLevelRangeWidget->setDefaultLevel(tileLevel);
292 d->m_downloadRegion.setVisibleTileLevel(tileLevel);
293}
294
295void DownloadRegionDialog::setSelectionMethod(SelectionMethod const selectionMethod)
296{
297 d->m_selectionMethod = selectionMethod;
298 switch (selectionMethod) {
299 case VisibleRegionMethod:
300 d->m_visibleRegionMethodButton->setChecked(true);
301 d->m_routeOffsetLabel->setEnabled(false);
302 d->m_routeOffsetSpinBox->setEnabled(false);
303 d->m_latLonBoxWidget->setEnabled(false);
304 setSpecifiedLatLonAltBox(d->m_visibleRegion);
305 break;
306 case SpecifiedRegionMethod:
307 d->m_specifiedRegionMethodButton->setChecked(true);
308 d->m_routeOffsetLabel->setEnabled(false);
309 d->m_routeOffsetSpinBox->setEnabled(false);
310 d->m_latLonBoxWidget->setEnabled(true);
311 break;
312 case RouteDownloadMethod:
313 d->m_routeDownloadMethodButton->setChecked(true);
314 d->m_routeOffsetLabel->setEnabled(true);
315 d->m_routeOffsetSpinBox->setEnabled(true);
316 d->m_latLonBoxWidget->setEnabled(false);
317 }
318
319 updateTileCount();
320}
321
322QList<TileCoordsPyramid> DownloadRegionDialog::region() const
323{
324 if (!d->hasTextureLayers() && !d->hasVectorLayers()) {
325 return {};
326 }
327
328 d->m_visibleTileLevel = (tileType() == TextureTileType && d->m_textureLayer->tileZoomLevel() != -1) ? d->m_textureLayer->tileZoomLevel()
329 : d->m_vectorTileLayer->tileZoomLevel();
330
331 const TileLayer *tileLayer = (tileType() == TextureTileType && d->m_textureLayer->layerCount() > 0) ? dynamic_cast<const TileLayer *>(d->m_textureLayer)
332 : dynamic_cast<const TileLayer *>(d->m_vectorTileLayer);
333
334 d->m_downloadRegion.setTileLevelRange(d->m_tileLevelRangeWidget->topLevel(), d->m_tileLevelRangeWidget->bottomLevel());
335 d->m_downloadRegion.setVisibleTileLevel(d->m_visibleTileLevel);
336
337 // check whether "visible region" or "lat/lon region" is selection method
338 GeoDataLatLonAltBox downloadRegion;
339 switch (d->m_selectionMethod) {
340 case VisibleRegionMethod:
341 downloadRegion = d->m_visibleRegion;
342 break;
343 case SpecifiedRegionMethod:
344 downloadRegion = GeoDataLatLonAltBox(d->m_latLonBoxWidget->latLonBox(), 0, 0);
345 break;
346 case RouteDownloadMethod:
347 qreal offset = d->m_routeOffsetSpinBox->value();
348 if (d->m_routeOffsetSpinBox->suffix() == QLatin1StringView(" km")) {
349 offset *= KM2METER;
350 }
351 const GeoDataLineString waypoints = d->m_model->routingManager()->routingModel()->route().path();
352 return d->m_downloadRegion.fromPath(tileLayer, offset, waypoints);
353 }
354
355 // For Mercator tiles limit the LatLonBox to the valid tile range.
356 if (tileLayer->tileProjection()->type() == GeoSceneAbstractTileProjection::Mercator) {
357 downloadRegion.setNorth(qMin(downloadRegion.north(), +1.4835));
358 downloadRegion.setSouth(qMax(downloadRegion.south(), -1.4835));
359 }
360
361 return d->m_downloadRegion.region(tileLayer, downloadRegion);
362}
363
364TileType DownloadRegionDialog::tileType() const
365{
366 return d->m_layerComboBox->currentIndex() == 0 ? TextureTileType : VectorTileType;
367}
368
369void DownloadRegionDialog::setSpecifiedLatLonAltBox(GeoDataLatLonAltBox const &region)
370{
371 d->m_latLonBoxWidget->setLatLonBox(region);
372}
373
374void DownloadRegionDialog::setVisibleLatLonAltBox(GeoDataLatLonAltBox const &region)
375{
376 d->m_visibleRegion = region;
377
378 // update lat/lon widget only if not active to prevent that users unintentionally loose
379 // entered values
380 if (d->m_selectionMethod == VisibleRegionMethod) {
381 setSpecifiedLatLonAltBox(region);
382 }
383 updateTileCount();
384}
385
386void DownloadRegionDialog::updateTileLayer()
387{
388 updateTileType();
389 updateTileCount();
390}
391
392void DownloadRegionDialog::delayUpdateTileLayer()
393{
394 QTimer::singleShot(500, this, &DownloadRegionDialog::updateTileLayer);
395}
396
397void DownloadRegionDialog::hideEvent(QHideEvent *event)
398{
399 disconnect(d->m_widget, SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)), this, SLOT(setVisibleLatLonAltBox(GeoDataLatLonAltBox)));
400 disconnect(d->m_widget, SIGNAL(themeChanged(QString)), this, SLOT(delayUpdateTileLayer()));
401 disconnect(d->m_widget, SIGNAL(propertyValueChanged(QString, bool)), this, SLOT(delayUpdateTileLayer()));
402
403 Q_EMIT hidden();
404 event->accept();
405}
406
407void DownloadRegionDialog::showEvent(QShowEvent *event)
408{
409 connect(d->m_widget, SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)), this, SLOT(setVisibleLatLonAltBox(GeoDataLatLonAltBox)));
410 connect(d->m_widget, SIGNAL(themeChanged(QString)), this, SLOT(delayUpdateTileLayer()));
411 connect(d->m_widget, SIGNAL(propertyValueChanged(QString, bool)), this, SLOT(delayUpdateTileLayer()));
412
413 setVisibleTileLevel(d->m_widget->tileZoomLevel());
414
415 updateTileCount();
416
417 Q_EMIT shown();
418 event->accept();
419}
420
421void DownloadRegionDialog::toggleSelectionMethod()
422{
423 if (d->m_specifiedRegionMethodButton->isChecked()) {
424 setSelectionMethod(SpecifiedRegionMethod);
425 } else if (d->m_routeDownloadMethodButton->isChecked()) {
426 setSelectionMethod(RouteDownloadMethod);
427 } else if (d->m_specifiedRegionMethodButton->isChecked()) {
428 setSelectionMethod(SpecifiedRegionMethod);
429 }
430}
431
432void DownloadRegionDialog::updateTileType()
433{
434 bool hasVisibleTextureLayers = d->hasTextureLayers() && d->m_textureLayer->layerCount() > 0;
435 bool hasVisibleVectorLayers = d->hasVectorLayers() && d->m_vectorTileLayer->layerCount() > 0;
436
437 auto model = qobject_cast<QStandardItemModel *>(d->m_layerComboBox->model());
438 Q_ASSERT(model != nullptr);
439 QStandardItem *item = nullptr;
440 item = model->item(0);
441 item->setFlags(hasVisibleTextureLayers ? item->flags() | Qt::ItemIsEnabled : item->flags() & ~Qt::ItemIsEnabled);
442 item = model->item(1);
443 item->setFlags(hasVisibleVectorLayers ? item->flags() | Qt::ItemIsEnabled : item->flags() & ~Qt::ItemIsEnabled);
444
445 bool allTileTypesAvailable = hasVisibleTextureLayers && hasVisibleVectorLayers;
446
447 d->m_layerComboBox->setEnabled(allTileTypesAvailable);
448 if (hasVisibleVectorLayers) {
449 d->m_layerComboBox->setCurrentIndex(1);
450 } else if (hasVisibleTextureLayers && !hasVisibleVectorLayers) {
451 d->m_layerComboBox->setCurrentIndex(0);
452 }
453}
454
455void DownloadRegionDialog::updateTileCount()
456{
457 if (!isVisible()) {
458 return;
459 }
460
461 qint64 tilesCount = 0;
462 QString themeId(d->m_model->mapThemeId());
463 QList<TileCoordsPyramid> const pyramid = region();
464 Q_ASSERT(!pyramid.isEmpty());
465 if (pyramid.size() == 1) {
466 tilesCount = pyramid[0].tilesCount();
467 } else {
468 for (int level = pyramid[0].bottomLevel(); level >= pyramid[0].topLevel(); --level) {
469 QSet<TileId> tileIdSet;
470 for (int i = 0; i < pyramid.size(); ++i) {
471 QRect const coords = pyramid[i].coords(level);
472 int x1, y1, x2, y2;
473 coords.getCoords(&x1, &y1, &x2, &y2);
474 for (int x = x1; x <= x2; ++x) {
475 for (int y = y1; y <= y2; ++y) {
476 TileId const tileId(0, level, x, y);
477 tileIdSet.insert(tileId);
478 }
479 }
480 }
481 tilesCount += tileIdSet.count();
482 }
483 }
484
485 qreal tileDownloadSize = 0;
486
487 if (tilesCount > maxTilesCount) {
488 d->m_tileSizeInfo->setToolTip(QString());
489 //~ singular There is a limit of %n tile to download.
490 //~ plural There is a limit of %n tiles to download.
491 d->m_tileSizeInfo->setText(tr("There is a limit of %n tile(s) to download.", "", maxTilesCount));
492 } else {
493 if (themeId == QLatin1StringView("earth/openstreetmap/openstreetmap.dgml") || themeId == QLatin1StringView("earth/openstreetmap/openseamap.dgml")
494 || themeId == QLatin1StringView("earth/vectorosm/vectorosm.dgml")) {
495 tileDownloadSize = tileType() == TextureTileType ? tilesCount * averageTextureTileSize : tilesCount * averageVectorTileSize;
496
497 d->m_tileSizeInfo->setToolTip(tr("Approximate size of the tiles to be downloaded"));
498
499 if (tileDownloadSize > 1024) {
500 tileDownloadSize = tileDownloadSize / 1024;
501 d->m_tileSizeInfo->setText(tr("Estimated download size: %1 MB").arg(ceil(tileDownloadSize)));
502 } else {
503 d->m_tileSizeInfo->setText(tr("Estimated download size: %1 kB").arg(tileDownloadSize));
504 }
505 } else {
506 d->m_tileSizeInfo->setToolTip(QString());
507 d->m_tileSizeInfo->clear();
508 }
509 }
510
511 d->m_tilesCountLabel->setText(QString::number(tilesCount));
512 bool const tilesCountWithinLimits = tilesCount > 0 && tilesCount <= maxTilesCount;
513 d->m_okButton->setEnabled(tilesCountWithinLimits);
514 d->m_applyButton->setEnabled(tilesCountWithinLimits);
515}
516
517void DownloadRegionDialog::updateRouteDialog()
518{
519 d->m_routeDownloadMethodButton->setEnabled(d->hasRoute());
520 d->m_routeDownloadMethodButton->setChecked(d->hasRoute());
521 if (!d->hasRoute()) {
522 setSelectionMethod(VisibleRegionMethod);
523 }
524}
525
526void DownloadRegionDialog::setOffsetUnit()
527{
528 qreal offset = d->m_routeOffsetSpinBox->value();
529
530 if (offset >= 1100) {
531 d->m_routeOffsetSpinBox->setSuffix(QStringLiteral(" km"));
532 d->m_routeOffsetSpinBox->setRange(minimumRouteOffset * METER2KM, maximumRouteOffset * METER2KM);
533 d->m_routeOffsetSpinBox->setDecimals(1);
534 d->m_routeOffsetSpinBox->setValue(offset * METER2KM);
535 d->m_routeOffsetSpinBox->setSingleStep(0.1);
536 } else if (offset <= 1 && d->m_routeOffsetSpinBox->suffix() == QLatin1StringView(" km")) {
537 d->m_routeOffsetSpinBox->setSuffix(QStringLiteral(" m"));
538 d->m_routeOffsetSpinBox->setRange(minimumRouteOffset, maximumRouteOffset);
539 d->m_routeOffsetSpinBox->setDecimals(0);
540 d->m_routeOffsetSpinBox->setValue(offset * KM2METER);
541 d->m_routeOffsetSpinBox->setSingleStep(100);
542 }
543}
544
545}
546
547#include "moc_DownloadRegionDialog.cpp"
This file contains the headers for MarbleModel.
This file contains the headers for MarbleWidget.
QStringView level(QStringView ifopt)
Binds a QML item to a specific geodetic location in screen coordinates.
@ TextureTileType
Tiles that consist of bitmap data.
@ VectorTileType
Tiles that consist of vector data.
void addLayout(QLayout *layout, int stretch)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
void currentIndexChanged(int index)
QPushButton * addButton(StandardButton button)
void valueChanged(double d)
bool isEmpty() const const
qsizetype size() const const
void getCoords(int *x1, int *y1, int *x2, int *y2) const const
qsizetype count() const const
iterator insert(const T &value)
Qt::ItemFlags flags() const const
void setFlags(Qt::ItemFlags flags)
QString number(double n, char format, int precision)
AlignRight
ItemIsEnabled
typedef WindowFlags
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void setLayout(QLayout *layout)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 8 2024 12:02:43 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.