12#include "MapViewWidget.h"
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"
33#include <QRegularExpression>
34#include <QResizeEvent>
36#include <QStandardItemModel>
42#include "ui_MapViewWidget.h"
47class Q_DECL_HIDDEN MapViewWidget::Private
50 Private(MapViewWidget *parent)
52 , m_marbleModel(nullptr)
54 , m_celestialListProxy()
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)
70 m_mapSortProxy.setDynamicSortFilter(
true);
71 m_celestialListProxy.setDynamicSortFilter(
true);
76 delete m_mapViewDelegate;
79 void applyExtendedLayout()
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);
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();
94 void applyReducedLayout()
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);
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();
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);
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);
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);
129 m_popupMenuFlat =
new QMenu(q);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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()));
186 applyReducedLayout();
189 void updateMapFilter()
191 int currentIndex = m_mapViewUi.celestialBodyComboBox->currentIndex();
192 const QString selectedId = m_celestialListProxy.
data(m_celestialListProxy.index(currentIndex, 1)).toString();
200 void celestialBodySelected(
int comboIndex);
202 void projectionSelected(
int projectionIndex);
205 void mapThemeSelected(
int index);
207 void showContextMenu(
const QPoint &pos);
209 void toggleFavorite();
210 void toggleIconSize();
212 bool isCurrentFavorite()
const;
213 QString currentThemeName()
const;
214 QString currentThemePath()
const;
217 MapViewWidget *
const q;
219 Ui::MapViewWidget m_mapViewUi;
222 MapThemeSortFilterProxyModel m_mapSortProxy;
229 QMenu *m_popupMenuFlat;
232 QAction *m_celestialBodyAction;
234 QAction *m_stereographicViewAction;
235 QAction *m_lambertAzimuthalViewAction;
236 QAction *m_azimuthalEquidistantViewAction;
237 QAction *m_verticalPerspectiveViewAction;
244 , d(new Private(this))
247 layout()->setContentsMargins({});
249 if (MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen) {
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);
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;
269 d->m_mapViewUi.marbleThemeSelectView->setItemDelegate(d->m_mapViewDelegate);
270 d->m_mapViewUi.marbleThemeSelectView->setAlternatingRowColors(
true);
272 d->m_mapViewUi.marbleThemeSelectView->setWrapping(
true);
274 d->m_mapViewUi.marbleThemeSelectView->setUniformItemSizes(
true);
279 d->m_mapViewUi.marbleThemeSelectView->setModel(&d->m_mapSortProxy);
282 connect(d->m_mapViewUi.marbleThemeSelectView, SIGNAL(customContextMenuRequested(
QPoint)),
this, SLOT(showContextMenu(
QPoint)));
284 d->m_mapViewUi.mapThemeComboBox->setVisible(
false);
288 connect(d->m_mapViewUi.projectionComboBox, SIGNAL(activated(
int)),
this, SLOT(projectionSelected(
int)));
290 d->m_mapViewUi.projectionComboBox->setEnabled(
true);
291 d->m_mapViewUi.celestialBodyComboBox->setModel(&d->m_celestialListProxy);
293 connect(d->m_mapViewUi.celestialBodyComboBox, SIGNAL(activated(
int)),
this, SLOT(celestialBodySelected(
int)));
295 d->m_settings.beginGroup(QStringLiteral(
"Favorites"));
296 if (!d->m_settings.contains(QStringLiteral(
"initialized"))) {
297 d->m_settings.setValue(QStringLiteral(
"initialized"),
true);
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);
303 d->m_settings.endGroup();
306MapViewWidget::~MapViewWidget()
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);
327 setProjection(widget->projection());
328 setMapThemeId(widget->mapThemeId());
337 d->applyExtendedLayout();
338 }
else if (!d->m_toolBar->
isVisible() &&
event->size().height() <= 400) {
339 d->applyReducedLayout();
343void MapViewWidget::setMapThemeId(
const QString &themeId)
345 const bool smallscreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
347 const int currentRow = smallscreen ? d->m_mapViewUi.mapThemeComboBox->currentIndex() : d->m_mapViewUi.marbleThemeSelectView->currentIndex().row();
351 if (themeId == oldThemeId)
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);
366 d->updateMapFilter();
370 for (
int row = 0; row < d->m_mapSortProxy.
rowCount(); ++row) {
373 d->m_mapViewUi.mapThemeComboBox->setCurrentIndex(row);
376 d->m_mapViewUi.marbleThemeSelectView->setCurrentIndex(index);
377 d->m_mapViewUi.marbleThemeSelectView->scrollTo(index);
385void MapViewWidget::setProjection(
Projection projection)
387 if ((
int)projection != d->m_mapViewUi.projectionComboBox->currentIndex())
388 d->m_mapViewUi.projectionComboBox->setCurrentIndex((
int)projection);
391 switch (projection) {
399 d->m_stereographicViewAction->
setChecked(
false);
400 d->m_lambertAzimuthalViewAction->
setChecked(
false);
401 d->m_azimuthalEquidistantViewAction->
setChecked(
false);
402 d->m_verticalPerspectiveViewAction->
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);
423 d->m_stereographicViewAction->
setChecked(
false);
424 d->m_lambertAzimuthalViewAction->
setChecked(
false);
425 d->m_azimuthalEquidistantViewAction->
setChecked(
false);
426 d->m_verticalPerspectiveViewAction->
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);
447 d->m_stereographicViewAction->
setChecked(
true);
448 d->m_lambertAzimuthalViewAction->
setChecked(
false);
449 d->m_azimuthalEquidistantViewAction->
setChecked(
false);
450 d->m_verticalPerspectiveViewAction->
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);
471 d->m_stereographicViewAction->
setChecked(
false);
472 d->m_lambertAzimuthalViewAction->
setChecked(
false);
473 d->m_azimuthalEquidistantViewAction->
setChecked(
true);
474 d->m_verticalPerspectiveViewAction->
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);
492void MapViewWidget::globeViewRequested()
497void MapViewWidget::flatViewRequested()
502void MapViewWidget::mercatorViewRequested()
507void MapViewWidget::gnomonicViewRequested()
512void MapViewWidget::stereographicViewRequested()
517void MapViewWidget::lambertAzimuthalViewRequested()
522void MapViewWidget::azimuthalEquidistantViewRequested()
527void MapViewWidget::verticalPerspectiveViewRequested()
532void MapViewWidget::Private::celestialBodySelected(
int comboIndex)
538 bool foundMapTheme =
false;
540 QString currentMapThemeId = m_marbleModel->mapThemeId();
541 QString oldPlanetId = m_marbleModel->planetId();
543 int row = m_mapSortProxy.
rowCount();
545 for (
int i = 0; i < row; ++i) {
548 if (currentMapThemeId == itMapThemeId) {
549 foundMapTheme =
true;
553 if (!foundMapTheme) {
558 if (oldPlanetId != m_marbleModel->planetId()) {
559 Q_EMIT q->celestialBodyChanged(m_marbleModel->planetId());
564void MapViewWidget::Private::projectionSelected(
int projectionIndex)
569void MapViewWidget::Private::mapThemeSelected(
QModelIndex index)
571 mapThemeSelected(index.
row());
574void MapViewWidget::Private::mapThemeSelected(
int index)
576 const QModelIndex columnIndex = m_mapSortProxy.index(index, 0);
579 mDebug() << currentmaptheme;
581 Q_EMIT q->mapThemeIdChanged(currentmaptheme);
584QString MapViewWidget::Private::currentThemeName()
const
586 const QModelIndex index = m_mapViewUi.marbleThemeSelectView->currentIndex();
592QString MapViewWidget::Private::currentThemePath()
const
594 const QModelIndex index = m_mapViewUi.marbleThemeSelectView->currentIndex();
595 const QModelIndex columnIndex = m_mapSortProxy.index(index.
row(), 0);
605void MapViewWidget::Private::showContextMenu(
const QPoint &
pos)
611 QAction *iconSizeAction = menu.
addAction(
tr(
"&Show Large Icons"), q, SLOT(toggleIconSize()));
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()));
619 menu.
addAction(
QIcon(QStringLiteral(
":/icons/create-new-map.png")),
tr(
"&Create a New Map..."), q, SIGNAL(showMapWizard()));
621 menu.
addAction(
tr(
"&Delete Map Theme"), q, SLOT(deleteMap()));
623 menu.
exec(m_mapViewUi.marbleThemeSelectView->mapToGlobal(
pos));
626void MapViewWidget::Private::deleteMap()
631 Q_EMIT q->mapThemeDeleted();
635void MapViewWidget::Private::toggleFavorite()
637 QModelIndex index = m_mapViewUi.marbleThemeSelectView->currentIndex();
638 if (isCurrentFavorite()) {
639 m_settings.remove(favoriteKey(index));
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);
650void MapViewWidget::Private::toggleIconSize()
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());
658bool MapViewWidget::Private::isCurrentFavorite()
const
660 const QModelIndex index = m_mapViewUi.marbleThemeSelectView->currentIndex();
661 return m_settings.contains(favoriteKey(index));
666#include "moc_MapViewWidget.cpp"
This file contains the headers for MarbleModel.
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.
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.
QDateTime currentDateTime()
bool exists() const const
virtual void addItem(QLayoutItem *item) override
const char * data() const const
StandardButton warning(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons, StandardButton defaultButton)
QVariant data(int role) const const
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
bool isEmpty() const const
QString section(QChar sep, qsizetype start, qsizetype end, SectionFlags flags) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QString toString() const const