Marble

MapViewWidget.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2004-2007 Torsten Rahn <tackat@kde.org>
4// SPDX-FileCopyrightText: 2007 Inge Wallin <ingwa@kde.org>
5// SPDX-FileCopyrightText: 2007 Thomas Zander <zander@kde.org>
6// SPDX-FileCopyrightText: 2010 Bastian Holst <bastianholst@gmx.de>
7// SPDX-FileCopyrightText: 2011-2013 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
8// SPDX-FileCopyrightText: 2012 Illya Kovalevskyy <illya.kovalevskyy@gmail.com>
9//
10
11// Self
12#include "MapViewWidget.h"
13
14// Marble
15#include "CelestialSortFilterProxyModel.h"
16#include "GeoSceneDocument.h"
17#include "GeoSceneHead.h"
18#include "MapThemeManager.h"
19#include "MapThemeSortFilterProxyModel.h"
20#include "MapViewItemDelegate.h"
21#include "MarbleDebug.h"
22#include "MarbleDirs.h"
23#include "MarbleModel.h"
24#include "MarbleWidget.h"
25
26// Qt
27#include <QDateTime>
28#include <QFileInfo>
29#include <QGridLayout>
30#include <QMenu>
31#include <QMessageBox>
32#include <QPainter>
33#include <QRegularExpression>
34#include <QResizeEvent>
35#include <QSettings>
36#include <QStandardItemModel>
37#include <QToolBar>
38#include <QToolButton>
39
40using namespace Marble;
41// Ui
42#include "ui_MapViewWidget.h"
43
44namespace Marble
45{
46
47class Q_DECL_HIDDEN MapViewWidget::Private
48{
49public:
50 Private(MapViewWidget *parent)
51 : q(parent)
52 , m_marbleModel(nullptr)
53 , m_mapSortProxy()
54 , m_celestialListProxy()
55 , m_toolBar(nullptr)
56 , m_globeViewButton(nullptr)
57 , m_mercatorViewButton(nullptr)
58 , m_popupMenuFlat(nullptr)
59 , m_flatViewAction(nullptr)
60 , m_mercatorViewAction(nullptr)
61 , m_celestialBodyAction(nullptr)
62 , m_gnomonicViewAction(nullptr)
63 , m_stereographicViewAction(nullptr)
64 , m_lambertAzimuthalViewAction(nullptr)
65 , m_azimuthalEquidistantViewAction(nullptr)
66 , m_verticalPerspectiveViewAction(nullptr)
67 , m_globeViewAction(nullptr)
68 , m_mapViewDelegate(nullptr)
69 {
70 m_mapSortProxy.setDynamicSortFilter(true);
71 m_celestialListProxy.setDynamicSortFilter(true);
72 }
73
74 ~Private()
75 {
76 delete m_mapViewDelegate;
77 }
78
79 void applyExtendedLayout()
80 {
81 m_mapViewUi.projectionLabel_2->setVisible(true);
82 m_mapViewUi.celestialBodyLabel->setVisible(true);
83 m_mapViewUi.projectionComboBox->setVisible(true);
84 m_mapViewUi.mapThemeLabel->setVisible(true);
85 m_mapViewUi.line->setVisible(true);
86
87 m_toolBar->setVisible(false);
88 const int labelId = m_mapViewUi.verticalLayout->indexOf(m_mapViewUi.celestialBodyLabel);
89 m_mapViewUi.verticalLayout->insertWidget(labelId + 1, m_mapViewUi.celestialBodyComboBox);
90 m_toolBar->removeAction(m_celestialBodyAction);
91 m_mapViewUi.celestialBodyComboBox->show();
92 }
93
94 void applyReducedLayout()
95 {
96 m_mapViewUi.projectionLabel_2->setVisible(false);
97 m_mapViewUi.celestialBodyLabel->setVisible(false);
98 m_mapViewUi.projectionComboBox->setVisible(false);
99 m_mapViewUi.mapThemeLabel->setVisible(false);
100 m_mapViewUi.line->setVisible(false);
101
102 m_toolBar->setVisible(true);
103 m_celestialBodyAction = m_toolBar->addWidget(m_mapViewUi.celestialBodyComboBox);
104 m_mapViewUi.verticalLayout->removeWidget(m_mapViewUi.celestialBodyComboBox);
105 m_mapViewUi.celestialBodyComboBox->show();
106 }
107
108 void setupToolBar()
109 {
110 m_toolBar = new QToolBar;
111
112 m_globeViewButton = new QToolButton;
113 m_globeViewButton->setIcon(QIcon(QStringLiteral(":/icons/map-globe.png")));
114 m_globeViewButton->setToolTip(tr("Globe View"));
115 m_globeViewButton->setCheckable(true);
116 m_globeViewButton->setChecked(false);
117
118 m_globeViewAction = new QAction(QIcon(QStringLiteral(":/icons/map-globe.png")), tr("Spherical view"), m_globeViewButton);
119 m_globeViewAction->setCheckable(true);
120 m_globeViewAction->setChecked(false);
121
122 m_mercatorViewButton = new QToolButton;
123 m_mercatorViewButton->setIcon(QIcon(QStringLiteral(":/icons/map-mercator.png")));
124 m_mercatorViewButton->setToolTip(tr("Mercator View"));
125 m_mercatorViewButton->setCheckable(true);
126 m_mercatorViewButton->setChecked(false);
127 m_mercatorViewButton->setPopupMode(QToolButton::MenuButtonPopup);
128
129 m_popupMenuFlat = new QMenu(q);
130
131 m_mercatorViewAction = new QAction(QIcon(QStringLiteral(":/icons/map-mercator.png")), tr("Mercator View"), m_popupMenuFlat);
132 m_mercatorViewAction->setCheckable(true);
133 m_mercatorViewAction->setChecked(false);
134
135 m_flatViewAction = new QAction(QIcon(QStringLiteral(":/icons/map-flat.png")), tr("Flat View"), m_popupMenuFlat);
136 m_flatViewAction->setCheckable(true);
137 m_flatViewAction->setChecked(false);
138
139 m_gnomonicViewAction = new QAction(QIcon(QStringLiteral(":/icons/map-gnomonic.png")), tr("Gnomonic view"), m_popupMenuFlat);
140 m_gnomonicViewAction->setCheckable(true);
141 m_gnomonicViewAction->setChecked(false);
142
143 m_stereographicViewAction = new QAction(QIcon(QStringLiteral(":/icons/map-globe.png")), tr("Stereographic view"), m_popupMenuFlat);
144 m_stereographicViewAction->setCheckable(true);
145 m_stereographicViewAction->setChecked(false);
146
147 m_lambertAzimuthalViewAction = new QAction(QIcon(QStringLiteral(":/icons/map-globe.png")), tr("Lambert Azimuthal Equal-Area view"), m_popupMenuFlat);
148 m_lambertAzimuthalViewAction->setCheckable(true);
149 m_lambertAzimuthalViewAction->setChecked(false);
150
151 m_azimuthalEquidistantViewAction = new QAction(QIcon(QStringLiteral(":/icons/map-globe.png")), tr("Azimuthal Equidistant view"), m_popupMenuFlat);
152 m_azimuthalEquidistantViewAction->setCheckable(true);
153 m_azimuthalEquidistantViewAction->setChecked(false);
154
155 m_verticalPerspectiveViewAction = new QAction(QIcon(QStringLiteral(":/icons/map-globe.png")), tr("Perspective Globe view"), m_popupMenuFlat);
156 m_verticalPerspectiveViewAction->setCheckable(true);
157 m_verticalPerspectiveViewAction->setChecked(false);
158
159 m_popupMenuFlat->addAction(m_mercatorViewAction);
160 m_popupMenuFlat->addAction(m_flatViewAction);
161 m_popupMenuFlat->addAction(m_gnomonicViewAction);
162 m_popupMenuFlat->addAction(m_stereographicViewAction);
163 m_popupMenuFlat->addAction(m_lambertAzimuthalViewAction);
164 m_popupMenuFlat->addAction(m_azimuthalEquidistantViewAction);
165 m_popupMenuFlat->addAction(m_verticalPerspectiveViewAction);
166 m_mercatorViewButton->setMenu(m_popupMenuFlat);
167
168 m_toolBar->addWidget(m_globeViewButton);
169 m_toolBar->addWidget(m_mercatorViewButton);
170 m_toolBar->addSeparator();
171 m_toolBar->setContentsMargins({});
172 m_toolBar->setIconSize(QSize(16, 16));
173 m_mapViewUi.toolBarLayout->insertWidget(0, m_toolBar);
174
175 connect(m_globeViewButton, SIGNAL(clicked()), q, SLOT(globeViewRequested()));
176 connect(m_mercatorViewButton, SIGNAL(clicked()), q, SLOT(mercatorViewRequested()));
177 connect(m_mercatorViewAction, SIGNAL(triggered()), q, SLOT(mercatorViewRequested()));
178 connect(m_flatViewAction, SIGNAL(triggered()), q, SLOT(flatViewRequested()));
179 connect(m_gnomonicViewAction, SIGNAL(triggered()), q, SLOT(gnomonicViewRequested()));
180 connect(m_stereographicViewAction, SIGNAL(triggered()), q, SLOT(stereographicViewRequested()));
181 connect(m_lambertAzimuthalViewAction, SIGNAL(triggered()), q, SLOT(lambertAzimuthalViewRequested()));
182 connect(m_azimuthalEquidistantViewAction, SIGNAL(triggered()), q, SLOT(azimuthalEquidistantViewRequested()));
183 connect(m_verticalPerspectiveViewAction, SIGNAL(triggered()), q, SLOT(verticalPerspectiveViewRequested()));
184 connect(m_globeViewAction, SIGNAL(triggered()), q, SLOT(globeViewRequested()));
185
186 applyReducedLayout();
187 }
188
189 void updateMapFilter()
190 {
191 int currentIndex = m_mapViewUi.celestialBodyComboBox->currentIndex();
192 const QString selectedId = m_celestialListProxy.data(m_celestialListProxy.index(currentIndex, 1)).toString();
193
194 if (!selectedId.isEmpty()) {
195 m_mapSortProxy.setFilterRegularExpression(QRegularExpression(selectedId)); // TODO_QT6: double check
196 // m_mapSortProxy.setFilterRegExp( QRegExp( selectedId, Qt::CaseInsensitive,QRegExp::FixedString ) );
197 }
198 }
199
200 void celestialBodySelected(int comboIndex);
201
202 void projectionSelected(int projectionIndex);
203
204 void mapThemeSelected(QModelIndex index);
205 void mapThemeSelected(int index);
206
207 void showContextMenu(const QPoint &pos);
208 void deleteMap();
209 void toggleFavorite();
210 void toggleIconSize();
211
212 bool isCurrentFavorite() const;
213 QString currentThemeName() const;
214 QString currentThemePath() const;
215 QString favoriteKey(const QModelIndex &index) const;
216
217 MapViewWidget *const q;
218
219 Ui::MapViewWidget m_mapViewUi;
220 MarbleModel *m_marbleModel;
221
222 MapThemeSortFilterProxyModel m_mapSortProxy;
223
224 CelestialSortFilterProxyModel m_celestialListProxy;
225 QSettings m_settings;
226 QToolBar *m_toolBar;
227 QToolButton *m_globeViewButton;
228 QToolButton *m_mercatorViewButton;
229 QMenu *m_popupMenuFlat;
230 QAction *m_flatViewAction;
231 QAction *m_mercatorViewAction;
232 QAction *m_celestialBodyAction;
233 QAction *m_gnomonicViewAction;
234 QAction *m_stereographicViewAction;
235 QAction *m_lambertAzimuthalViewAction;
236 QAction *m_azimuthalEquidistantViewAction;
237 QAction *m_verticalPerspectiveViewAction;
238 QAction *m_globeViewAction;
239 MapViewItemDelegate *m_mapViewDelegate;
240};
241
242MapViewWidget::MapViewWidget(QWidget *parent, Qt::WindowFlags f)
243 : QWidget(parent, f)
244 , d(new Private(this))
245{
246 d->m_mapViewUi.setupUi(this);
247 layout()->setContentsMargins({});
248
249 if (MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen) {
250 auto layout = new QGridLayout;
251 layout->addItem(d->m_mapViewUi.verticalLayout->takeAt(1), 0, 0);
252 layout->addItem(d->m_mapViewUi.verticalLayout->takeAt(1), 0, 1);
253 d->m_mapViewUi.line->setVisible(false);
254 layout->addItem(d->m_mapViewUi.verticalLayout->takeAt(2), 1, 0);
255 layout->addItem(d->m_mapViewUi.verticalLayout->takeAt(2), 1, 1);
256 layout->addItem(d->m_mapViewUi.verticalLayout->takeAt(3), 2, 0);
257 layout->addItem(d->m_mapViewUi.verticalLayout->takeAt(4), 2, 1);
258 d->m_mapViewUi.verticalLayout->insertLayout(0, layout);
259 d->m_mapViewUi.mapThemeComboBox->setModel(&d->m_mapSortProxy);
260 d->m_mapViewUi.mapThemeComboBox->setIconSize(QSize(48, 48));
261 connect(d->m_mapViewUi.mapThemeComboBox, SIGNAL(activated(int)), this, SLOT(mapThemeSelected(int)));
262 d->m_mapViewUi.marbleThemeSelectView->setVisible(false);
263 } else {
264 d->m_mapViewUi.marbleThemeSelectView->setViewMode(QListView::IconMode);
265 QSize const iconSize = d->m_settings.value(QStringLiteral("MapView/iconSize"), QSize(90, 90)).toSize();
266 d->m_mapViewUi.marbleThemeSelectView->setIconSize(iconSize);
267 delete d->m_mapViewDelegate;
268 d->m_mapViewDelegate = new MapViewItemDelegate(d->m_mapViewUi.marbleThemeSelectView);
269 d->m_mapViewUi.marbleThemeSelectView->setItemDelegate(d->m_mapViewDelegate);
270 d->m_mapViewUi.marbleThemeSelectView->setAlternatingRowColors(true);
271 d->m_mapViewUi.marbleThemeSelectView->setFlow(QListView::LeftToRight);
272 d->m_mapViewUi.marbleThemeSelectView->setWrapping(true);
273 d->m_mapViewUi.marbleThemeSelectView->setResizeMode(QListView::Adjust);
274 d->m_mapViewUi.marbleThemeSelectView->setUniformItemSizes(true);
275 d->m_mapViewUi.marbleThemeSelectView->setMovement(QListView::Static);
276 d->m_mapViewUi.marbleThemeSelectView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
277 d->m_mapViewUi.marbleThemeSelectView->setEditTriggers(QListView::NoEditTriggers);
278 d->m_mapViewUi.marbleThemeSelectView->setSelectionMode(QListView::SingleSelection);
279 d->m_mapViewUi.marbleThemeSelectView->setModel(&d->m_mapSortProxy);
280 connect(d->m_mapViewUi.marbleThemeSelectView, SIGNAL(pressed(QModelIndex)), this, SLOT(mapThemeSelected(QModelIndex)));
281 connect(d->m_mapViewUi.marbleThemeSelectView, SIGNAL(activated(QModelIndex)), this, SLOT(mapThemeSelected(QModelIndex)));
282 connect(d->m_mapViewUi.marbleThemeSelectView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
283
284 d->m_mapViewUi.mapThemeComboBox->setVisible(false);
285 d->setupToolBar();
286 }
287
288 connect(d->m_mapViewUi.projectionComboBox, SIGNAL(activated(int)), this, SLOT(projectionSelected(int)));
289
290 d->m_mapViewUi.projectionComboBox->setEnabled(true);
291 d->m_mapViewUi.celestialBodyComboBox->setModel(&d->m_celestialListProxy);
292
293 connect(d->m_mapViewUi.celestialBodyComboBox, SIGNAL(activated(int)), this, SLOT(celestialBodySelected(int)));
294
295 d->m_settings.beginGroup(QStringLiteral("Favorites"));
296 if (!d->m_settings.contains(QStringLiteral("initialized"))) {
297 d->m_settings.setValue(QStringLiteral("initialized"), true);
298 QDateTime currentDateTime = QDateTime::currentDateTime();
299 d->m_settings.setValue(QStringLiteral("Atlas"), currentDateTime);
300 d->m_settings.setValue(QStringLiteral("OpenStreetMap"), currentDateTime);
301 d->m_settings.setValue(QStringLiteral("Satellite View"), currentDateTime);
302 }
303 d->m_settings.endGroup();
304}
305
306MapViewWidget::~MapViewWidget()
307{
308 delete d;
309}
310
311void MapViewWidget::setMarbleWidget(MarbleWidget *widget, MapThemeManager *mapThemeManager)
312{
313 d->m_marbleModel = widget->model();
314 d->m_mapSortProxy.setSourceModel(mapThemeManager->mapThemeModel());
315 d->m_mapSortProxy.sort(0);
316 d->m_celestialListProxy.setSourceModel(mapThemeManager->celestialBodiesModel());
317 d->m_celestialListProxy.sort(0);
318
319 connect(this, SIGNAL(projectionChanged(Projection)), widget, SLOT(setProjection(Projection)));
320
321 connect(widget, SIGNAL(themeChanged(QString)), this, SLOT(setMapThemeId(QString)));
322
323 connect(widget, SIGNAL(projectionChanged(Projection)), this, SLOT(setProjection(Projection)));
324
325 connect(this, SIGNAL(mapThemeIdChanged(QString)), widget, SLOT(setMapThemeId(QString)));
326
327 setProjection(widget->projection());
328 setMapThemeId(widget->mapThemeId());
329}
330
331void MapViewWidget::resizeEvent(QResizeEvent *event)
332{
333 if (!d->m_toolBar)
334 return;
335
336 if (d->m_toolBar->isVisible() && event->size().height() > 400) {
337 d->applyExtendedLayout();
338 } else if (!d->m_toolBar->isVisible() && event->size().height() <= 400) {
339 d->applyReducedLayout();
340 }
341}
342
343void MapViewWidget::setMapThemeId(const QString &themeId)
344{
345 const bool smallscreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
346
347 const int currentRow = smallscreen ? d->m_mapViewUi.mapThemeComboBox->currentIndex() : d->m_mapViewUi.marbleThemeSelectView->currentIndex().row();
348 const QString oldThemeId = d->m_mapSortProxy.data(d->m_mapSortProxy.index(currentRow, 0), Qt::UserRole + 1).toString();
349
350 // Check if the new selected theme is different from the current one
351 if (themeId == oldThemeId)
352 return;
353
354 const QString oldCelestialBodyId = oldThemeId.section(QLatin1Char('/'), 0, 0);
355 const QString celestialBodyId = themeId.section(QLatin1Char('/'), 0, 0);
356
357 // select celestialBodyId in GUI
358 if (celestialBodyId != oldCelestialBodyId) {
359 for (int row = 0; row < d->m_celestialListProxy.rowCount(); ++row) {
360 if (d->m_celestialListProxy.data(d->m_celestialListProxy.index(row, 1)).toString() == celestialBodyId) {
361 d->m_mapViewUi.celestialBodyComboBox->setCurrentIndex(row);
362 break;
363 }
364 }
365
366 d->updateMapFilter();
367 }
368
369 // select themeId in GUI
370 for (int row = 0; row < d->m_mapSortProxy.rowCount(); ++row) {
371 if (d->m_mapSortProxy.data(d->m_mapSortProxy.index(row, 0), Qt::UserRole + 1).toString() == themeId) {
372 if (smallscreen) {
373 d->m_mapViewUi.mapThemeComboBox->setCurrentIndex(row);
374 } else {
375 const QModelIndex index = d->m_mapSortProxy.index(row, 0);
376 d->m_mapViewUi.marbleThemeSelectView->setCurrentIndex(index);
377 d->m_mapViewUi.marbleThemeSelectView->scrollTo(index);
378 }
379
380 break;
381 }
382 }
383}
384
385void MapViewWidget::setProjection(Projection projection)
386{
387 if ((int)projection != d->m_mapViewUi.projectionComboBox->currentIndex())
388 d->m_mapViewUi.projectionComboBox->setCurrentIndex((int)projection);
389
390 if (d->m_toolBar) {
391 switch (projection) {
393 d->m_globeViewButton->setChecked(true);
394 d->m_globeViewAction->setChecked(true);
395 d->m_mercatorViewButton->setChecked(false);
396 d->m_mercatorViewAction->setChecked(false);
397 d->m_flatViewAction->setChecked(false);
398 d->m_gnomonicViewAction->setChecked(false);
399 d->m_stereographicViewAction->setChecked(false);
400 d->m_lambertAzimuthalViewAction->setChecked(false);
401 d->m_azimuthalEquidistantViewAction->setChecked(false);
402 d->m_verticalPerspectiveViewAction->setChecked(false);
403 break;
404 case Marble::Mercator:
405 d->m_mercatorViewButton->setChecked(true);
406 d->m_mercatorViewAction->setChecked(true);
407 d->m_globeViewButton->setChecked(false);
408 d->m_flatViewAction->setChecked(false);
409 d->m_gnomonicViewAction->setChecked(false);
410 d->m_globeViewAction->setChecked(false);
411 d->m_stereographicViewAction->setChecked(false);
412 d->m_lambertAzimuthalViewAction->setChecked(false);
413 d->m_azimuthalEquidistantViewAction->setChecked(false);
414 d->m_verticalPerspectiveViewAction->setChecked(false);
415 break;
417 d->m_flatViewAction->setChecked(true);
418 d->m_mercatorViewButton->setChecked(true);
419 d->m_globeViewButton->setChecked(false);
420 d->m_mercatorViewAction->setChecked(false);
421 d->m_gnomonicViewAction->setChecked(false);
422 d->m_globeViewAction->setChecked(false);
423 d->m_stereographicViewAction->setChecked(false);
424 d->m_lambertAzimuthalViewAction->setChecked(false);
425 d->m_azimuthalEquidistantViewAction->setChecked(false);
426 d->m_verticalPerspectiveViewAction->setChecked(false);
427 break;
428 case Marble::Gnomonic:
429 d->m_flatViewAction->setChecked(false);
430 d->m_mercatorViewButton->setChecked(true);
431 d->m_globeViewButton->setChecked(false);
432 d->m_mercatorViewAction->setChecked(false);
433 d->m_gnomonicViewAction->setChecked(true);
434 d->m_globeViewAction->setChecked(false);
435 d->m_stereographicViewAction->setChecked(false);
436 d->m_lambertAzimuthalViewAction->setChecked(false);
437 d->m_azimuthalEquidistantViewAction->setChecked(false);
438 d->m_verticalPerspectiveViewAction->setChecked(false);
439 break;
441 d->m_flatViewAction->setChecked(false);
442 d->m_mercatorViewButton->setChecked(true);
443 d->m_globeViewButton->setChecked(false);
444 d->m_mercatorViewAction->setChecked(false);
445 d->m_gnomonicViewAction->setChecked(false);
446 d->m_globeViewAction->setChecked(false);
447 d->m_stereographicViewAction->setChecked(true);
448 d->m_lambertAzimuthalViewAction->setChecked(false);
449 d->m_azimuthalEquidistantViewAction->setChecked(false);
450 d->m_verticalPerspectiveViewAction->setChecked(false);
451 break;
453 d->m_flatViewAction->setChecked(false);
454 d->m_mercatorViewButton->setChecked(true);
455 d->m_globeViewButton->setChecked(false);
456 d->m_mercatorViewAction->setChecked(false);
457 d->m_gnomonicViewAction->setChecked(false);
458 d->m_globeViewAction->setChecked(false);
459 d->m_stereographicViewAction->setChecked(false);
460 d->m_lambertAzimuthalViewAction->setChecked(true);
461 d->m_azimuthalEquidistantViewAction->setChecked(false);
462 d->m_verticalPerspectiveViewAction->setChecked(false);
463 break;
465 d->m_flatViewAction->setChecked(false);
466 d->m_mercatorViewButton->setChecked(true);
467 d->m_globeViewButton->setChecked(false);
468 d->m_mercatorViewAction->setChecked(false);
469 d->m_gnomonicViewAction->setChecked(false);
470 d->m_globeViewAction->setChecked(false);
471 d->m_stereographicViewAction->setChecked(false);
472 d->m_lambertAzimuthalViewAction->setChecked(false);
473 d->m_azimuthalEquidistantViewAction->setChecked(true);
474 d->m_verticalPerspectiveViewAction->setChecked(false);
475 break;
477 d->m_flatViewAction->setChecked(false);
478 d->m_mercatorViewButton->setChecked(true);
479 d->m_globeViewButton->setChecked(false);
480 d->m_mercatorViewAction->setChecked(false);
481 d->m_gnomonicViewAction->setChecked(false);
482 d->m_globeViewAction->setChecked(false);
483 d->m_stereographicViewAction->setChecked(false);
484 d->m_lambertAzimuthalViewAction->setChecked(false);
485 d->m_azimuthalEquidistantViewAction->setChecked(false);
486 d->m_verticalPerspectiveViewAction->setChecked(true);
487 break;
488 }
489 }
490}
491
492void MapViewWidget::globeViewRequested()
493{
494 Q_EMIT projectionChanged(Marble::Spherical);
495}
496
497void MapViewWidget::flatViewRequested()
498{
499 Q_EMIT projectionChanged(Marble::Equirectangular);
500}
501
502void MapViewWidget::mercatorViewRequested()
503{
504 Q_EMIT projectionChanged(Marble::Mercator);
505}
506
507void MapViewWidget::gnomonicViewRequested()
508{
509 Q_EMIT projectionChanged(Marble::Gnomonic);
510}
511
512void MapViewWidget::stereographicViewRequested()
513{
514 Q_EMIT projectionChanged(Marble::Stereographic);
515}
516
517void MapViewWidget::lambertAzimuthalViewRequested()
518{
519 Q_EMIT projectionChanged(Marble::LambertAzimuthal);
520}
521
522void MapViewWidget::azimuthalEquidistantViewRequested()
523{
524 Q_EMIT projectionChanged(Marble::AzimuthalEquidistant);
525}
526
527void MapViewWidget::verticalPerspectiveViewRequested()
528{
529 Q_EMIT projectionChanged(Marble::VerticalPerspective);
530}
531
532void MapViewWidget::Private::celestialBodySelected(int comboIndex)
533{
534 Q_UNUSED(comboIndex)
535
536 updateMapFilter();
537
538 bool foundMapTheme = false;
539
540 QString currentMapThemeId = m_marbleModel->mapThemeId();
541 QString oldPlanetId = m_marbleModel->planetId();
542
543 int row = m_mapSortProxy.rowCount();
544
545 for (int i = 0; i < row; ++i) {
546 QModelIndex index = m_mapSortProxy.index(i, 0);
547 QString itMapThemeId = m_mapSortProxy.data(index, Qt::UserRole + 1).toString();
548 if (currentMapThemeId == itMapThemeId) {
549 foundMapTheme = true;
550 break;
551 }
552 }
553 if (!foundMapTheme) {
554 QModelIndex index = m_mapSortProxy.index(0, 0);
555 Q_EMIT q->mapThemeIdChanged(m_mapSortProxy.data(index, Qt::UserRole + 1).toString());
556 }
557
558 if (oldPlanetId != m_marbleModel->planetId()) {
559 Q_EMIT q->celestialBodyChanged(m_marbleModel->planetId());
560 }
561}
562
563// Relay a signal and convert the parameter from an int to a Projection.
564void MapViewWidget::Private::projectionSelected(int projectionIndex)
565{
566 Q_EMIT q->projectionChanged((Projection)projectionIndex);
567}
568
569void MapViewWidget::Private::mapThemeSelected(QModelIndex index)
570{
571 mapThemeSelected(index.row());
572}
573
574void MapViewWidget::Private::mapThemeSelected(int index)
575{
576 const QModelIndex columnIndex = m_mapSortProxy.index(index, 0);
577 const QString currentmaptheme = m_mapSortProxy.data(columnIndex, Qt::UserRole + 1).toString();
578
579 mDebug() << currentmaptheme;
580
581 Q_EMIT q->mapThemeIdChanged(currentmaptheme);
582}
583
584QString MapViewWidget::Private::currentThemeName() const
585{
586 const QModelIndex index = m_mapViewUi.marbleThemeSelectView->currentIndex();
587 const QModelIndex columnIndex = m_mapSortProxy.index(index.row(), 0, QModelIndex());
588
589 return m_mapSortProxy.data(columnIndex).toString();
590}
591
592QString MapViewWidget::Private::currentThemePath() const
593{
594 const QModelIndex index = m_mapViewUi.marbleThemeSelectView->currentIndex();
595 const QModelIndex columnIndex = m_mapSortProxy.index(index.row(), 0);
596
597 return m_mapSortProxy.data(columnIndex, Qt::UserRole + 1).toString();
598}
599
600QString MapViewWidget::Private::favoriteKey(const QModelIndex &index) const
601{
602 return QLatin1StringView("Favorites/") + m_mapSortProxy.data(index).toString();
603}
604
605void MapViewWidget::Private::showContextMenu(const QPoint &pos)
606{
607 qDebug();
608 Q_UNUSED(pos)
609 QMenu menu;
610
611 QAction *iconSizeAction = menu.addAction(tr("&Show Large Icons"), q, SLOT(toggleIconSize()));
612 iconSizeAction->setCheckable(true);
613 iconSizeAction->setChecked(m_mapViewUi.marbleThemeSelectView->iconSize() == QSize(96, 96));
614 QAction *favAction = menu.addAction(QIcon(QStringLiteral(":/icons/bookmarks.png")), tr("&Favorite"), q, SLOT(toggleFavorite()));
615 favAction->setCheckable(true);
616 favAction->setChecked(isCurrentFavorite());
617 menu.addSeparator();
618
619 menu.addAction(QIcon(QStringLiteral(":/icons/create-new-map.png")), tr("&Create a New Map..."), q, SIGNAL(showMapWizard()));
620 if (QFileInfo::exists(MarbleDirs::localPath() + QLatin1StringView("/maps/") + currentThemePath())) {
621 menu.addAction(tr("&Delete Map Theme"), q, SLOT(deleteMap()));
622 }
623 menu.exec(m_mapViewUi.marbleThemeSelectView->mapToGlobal(pos));
624}
625
626void MapViewWidget::Private::deleteMap()
627{
628 if (QMessageBox::warning(q, tr("Marble"), tr("Are you sure that you want to delete \"%1\"?").arg(currentThemeName()), QMessageBox::Yes | QMessageBox::No)
629 == QMessageBox::Yes) {
630 MapThemeManager::deleteMapTheme(currentThemePath());
631 Q_EMIT q->mapThemeDeleted();
632 }
633}
634
635void MapViewWidget::Private::toggleFavorite()
636{
637 QModelIndex index = m_mapViewUi.marbleThemeSelectView->currentIndex();
638 if (isCurrentFavorite()) {
639 m_settings.remove(favoriteKey(index));
640 } else {
641 m_settings.setValue(favoriteKey(index), QDateTime::currentDateTime());
642 }
643 auto sourceModel = qobject_cast<QStandardItemModel *>(m_mapSortProxy.sourceModel());
644 const QModelIndex sourceIndex = m_mapSortProxy.mapToSource(index);
645 Q_EMIT sourceModel->dataChanged(sourceIndex, sourceIndex);
646 index = m_mapViewUi.marbleThemeSelectView->currentIndex();
647 m_mapViewUi.marbleThemeSelectView->scrollTo(index);
648}
649
650void MapViewWidget::Private::toggleIconSize()
651{
652 bool const isLarge = m_mapViewUi.marbleThemeSelectView->iconSize() == QSize(96, 96);
653 int const size = isLarge ? 52 : 96;
654 m_mapViewUi.marbleThemeSelectView->setIconSize(QSize(size, size));
655 m_settings.setValue(QStringLiteral("MapView/iconSize"), m_mapViewUi.marbleThemeSelectView->iconSize());
656}
657
658bool MapViewWidget::Private::isCurrentFavorite() const
659{
660 const QModelIndex index = m_mapViewUi.marbleThemeSelectView->currentIndex();
661 return m_settings.contains(favoriteKey(index));
662}
663
664}
665
666#include "moc_MapViewWidget.cpp"
This file contains the headers for MarbleModel.
This file contains the headers for MarbleWidget.
Provides access to all map themes installed locally.
The CelestialSortFilterProxyModel class is a proxy used by both MapViewWidget's listview,...
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
A small trick to change names for dwarfs and moons.
static void deleteMapTheme(const QString &mapThemeId)
Deletes the map theme with the specified map theme ID.
The MapViewItemDelegate class is a delegate class for both the MapViewWidget's listView and MapChange...
The data model (not based on QAbstractModel) for a MarbleWidget.
Definition MarbleModel.h:84
A widget class that displays a view of the earth.
MarbleModel * model()
Return the model that this view shows.
Binds a QML item to a specific geodetic location in screen coordinates.
Projection
This enum is used to choose the projection shown in the view.
@ Mercator
Mercator projection.
@ VerticalPerspective
Vertical perspective projection.
@ AzimuthalEquidistant
Azimuthal Equidistant projection.
@ Gnomonic
Gnomonic projection.
@ LambertAzimuthal
Lambert Azimuthal Equal-Area projection.
@ Equirectangular
Flat projection ("plate carree")
@ Spherical
Spherical projection ("Orthographic")
@ Stereographic
Stereographic projection.
void setChecked(bool)
void setIcon(const QIcon &icon)
void setCheckable(bool)
void setChecked(bool)
QDateTime currentDateTime()
bool exists() const const
virtual void addItem(QLayoutItem *item) override
const char * data() const const
QAction * addAction(const QIcon &icon, const QString &text, Functor functor, const QKeySequence &shortcut)
QAction * addSeparator()
QAction * exec()
StandardButton warning(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons, StandardButton defaultButton)
QVariant data(int role) const const
int row() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
T qobject_cast(QObject *object)
QString tr(const char *sourceText, const char *disambiguation, int n)
virtual QVariant data(const QModelIndex &index, int role) const const override
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
virtual int rowCount(const QModelIndex &parent) const const override
virtual void setSourceModel(QAbstractItemModel *sourceModel) override
virtual void sort(int column, Qt::SortOrder order) override
QChar * data()
bool isEmpty() const const
QString section(QChar sep, qsizetype start, qsizetype end, SectionFlags flags) const const
UserRole
ScrollBarAlwaysOff
typedef WindowFlags
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QString toString() const const
virtual bool event(QEvent *event) override
void setupUi(QWidget *widget)
bool isVisible() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 8 2024 12:02:44 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.