diff options
author | r.kuznetsov <r.kuznetsov@corp.mail.ru> | 2018-07-27 16:12:23 +0300 |
---|---|---|
committer | Daria Volvenkova <d.volvenkova@corp.mail.ru> | 2018-07-31 18:41:09 +0300 |
commit | 0f6ae06579524c3a3888c88fdea78ade2328af1c (patch) | |
tree | ccbd4d73fd14640555b4c39fea935f87be710322 /qt | |
parent | 02b09ac12e62cb9451c9d43b3f76b405e53d5ca5 (diff) |
Added UI for bookmarks in Qt app
Diffstat (limited to 'qt')
-rw-r--r-- | qt/CMakeLists.txt | 2 | ||||
-rw-r--r-- | qt/bookmark_dialog.cpp | 325 | ||||
-rw-r--r-- | qt/bookmark_dialog.hpp | 50 | ||||
-rw-r--r-- | qt/mainwindow.cpp | 13 | ||||
-rw-r--r-- | qt/mainwindow.hpp | 3 | ||||
-rw-r--r-- | qt/res/bookmark.png | bin | 0 -> 960 bytes | |||
-rw-r--r-- | qt/res/resources.qrc | 1 | ||||
-rw-r--r-- | qt/res/traffic.png | bin | 1416 -> 1010 bytes |
8 files changed, 393 insertions, 1 deletions
diff --git a/qt/CMakeLists.txt b/qt/CMakeLists.txt index 39710b0cd0..a190fd4052 100644 --- a/qt/CMakeLists.txt +++ b/qt/CMakeLists.txt @@ -17,6 +17,8 @@ set( SRC about.cpp about.hpp + bookmark_dialog.cpp + bookmark_dialog.hpp build_style/build_common.cpp build_style/build_common.h build_style/build_drules.cpp diff --git a/qt/bookmark_dialog.cpp b/qt/bookmark_dialog.cpp new file mode 100644 index 0000000000..b96bd87c78 --- /dev/null +++ b/qt/bookmark_dialog.cpp @@ -0,0 +1,325 @@ +#include "qt/bookmark_dialog.hpp" + +#include "map/bookmark_manager.hpp" +#include "map/framework.hpp" + +#include "platform/measurement_utils.hpp" + +#include "base/assert.hpp" + +#include <QtCore/QFile> + +#include <QtWidgets/QFileDialog> +#include <QtWidgets/QHBoxLayout> +#include <QtWidgets/QHeaderView> +#include <QtWidgets/QLabel> +#include <QtWidgets/QMessageBox> +#include <QtWidgets/QPushButton> +#include <QtWidgets/QTreeWidget> +#include <QtWidgets/QVBoxLayout> + +#include <functional> + +using namespace std::placeholders; + +namespace qt +{ +BookmarkDialog::BookmarkDialog(QWidget * parent, Framework & framework) + : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint) + , m_framework(framework) +{ + setWindowModality(Qt::WindowModal); + + QPushButton * closeButton = new QPushButton(tr("Close"), this); + closeButton->setDefault(true); + connect(closeButton, SIGNAL(clicked()), this, SLOT(OnCloseClick())); + + QPushButton * deleteButton = new QPushButton(tr("Delete"), this); + connect(deleteButton, SIGNAL(clicked()), this, SLOT(OnDeleteClick())); + + QPushButton * importButton = new QPushButton(tr("Import KML/KMZ"), this); + connect(importButton, SIGNAL(clicked()), this, SLOT(OnImportClick())); + + QPushButton * exportButton = new QPushButton(tr("Export KMZ"), this); + connect(exportButton, SIGNAL(clicked()), this, SLOT(OnExportClick())); + + m_tree = new QTreeWidget(this); + m_tree->setColumnCount(2); + QStringList columnLabels; + columnLabels << tr("Bookmarks and tracks") << ""; + m_tree->setHeaderLabels(columnLabels); + m_tree->setSelectionBehavior(QAbstractItemView::SelectionBehavior::SelectItems); + connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(OnItemClick(QTreeWidgetItem *, int))); + + QHBoxLayout * horizontalLayout = new QHBoxLayout(); + horizontalLayout->addStretch(); + horizontalLayout->addWidget(importButton); + horizontalLayout->addWidget(exportButton); + horizontalLayout->addWidget(deleteButton); + horizontalLayout->addWidget(closeButton); + + QVBoxLayout * verticalLayout = new QVBoxLayout(); + verticalLayout->addWidget(m_tree); + verticalLayout->addLayout(horizontalLayout); + setLayout(verticalLayout); + + setWindowTitle(tr("Bookmarks and tracks")); + resize(700, 600); + + BookmarkManager::AsyncLoadingCallbacks callbacks; + callbacks.m_onStarted = std::bind(&BookmarkDialog::OnAsyncLoadingStarted, this); + callbacks.m_onFinished = std::bind(&BookmarkDialog::OnAsyncLoadingFinished, this); + callbacks.m_onFileSuccess = std::bind(&BookmarkDialog::OnAsyncLoadingFileSuccess, this, _1, _2); + callbacks.m_onFileError = std::bind(&BookmarkDialog::OnAsyncLoadingFileError, this, _1, _2); + m_framework.GetBookmarkManager().SetAsyncLoadingCallbacks(std::move(callbacks)); +} + +void BookmarkDialog::OnAsyncLoadingStarted() +{ + FillTree(); +} + +void BookmarkDialog::OnAsyncLoadingFinished() +{ + FillTree(); +} + +void BookmarkDialog::OnAsyncLoadingFileSuccess(std::string const & fileName, bool isTemporaryFile) +{ +} + +void BookmarkDialog::OnAsyncLoadingFileError(std::string const & fileName, bool isTemporaryFile) +{ +} + +void BookmarkDialog::OnItemClick(QTreeWidgetItem * item, int column) +{ + if (column != 1) + return; + + auto const categoryIt = m_categories.find(item); + if (categoryIt != m_categories.cend()) + { + m_framework.ShowBookmarkCategory(categoryIt->second); + done(0); + return; + } + + auto const bookmarkIt = m_bookmarks.find(item); + if (bookmarkIt != m_bookmarks.cend()) + { + done(0); + m_framework.ShowBookmark(bookmarkIt->second); + return; + } + + auto const trackIt = m_tracks.find(item); + if (trackIt != m_tracks.cend()) + { + auto const track = m_framework.GetBookmarkManager().GetTrack(trackIt->second); + if (track != nullptr) + { + done(0); + m_framework.ShowTrack(*track); + } + return; + } +} + +void BookmarkDialog::OnCloseClick() +{ + done(0); +} + +void BookmarkDialog::OnImportClick() +{ + auto const name = QFileDialog::getOpenFileName(this /* parent */, tr("Open KML/KMZ..."), + QString() /* dir */, "KML/KMZ files (*.kml *.kmz)"); + auto const file = name.toStdString(); + if (file.empty()) + return; + + m_framework.GetBookmarkManager().LoadBookmark(file, false /* isTemporaryFile */); +} + +void BookmarkDialog::OnExportClick() +{ + if (m_tree->selectedItems().empty()) + { + QMessageBox ask(this); + ask.setIcon(QMessageBox::Information); + ask.setText(tr("Select one of bookmarks category to export.")); + ask.addButton(tr("OK"), QMessageBox::NoRole); + ask.exec(); + return; + } + + auto const categoryIt = m_categories.find(m_tree->selectedItems().front()); + if (categoryIt == m_categories.cend()) + { + QMessageBox ask(this); + ask.setIcon(QMessageBox::Warning); + ask.setText(tr("Selected item is not a bookmarks category.")); + ask.addButton(tr("OK"), QMessageBox::NoRole); + ask.exec(); + return; + } + + auto const name = QFileDialog::getSaveFileName(this /* parent */, tr("Export KMZ..."), + QString() /* dir */, "KMZ files (*.kmz)"); + if (name.isEmpty()) + return; + + m_framework.GetBookmarkManager().PrepareFileForSharing(categoryIt->second, + [this, name](BookmarkManager::SharingResult const & result) + { + if (result.m_code == BookmarkManager::SharingResult::Code::Success) + { + QFile::rename(QString(result.m_sharingPath.c_str()), name); + + QMessageBox ask(this); + ask.setIcon(QMessageBox::Information); + ask.setText(tr("Bookmarks successfully exported.")); + ask.addButton(tr("OK"), QMessageBox::NoRole); + ask.exec(); + } + else + { + QMessageBox ask(this); + ask.setIcon(QMessageBox::Critical); + ask.setText(tr("Could not export bookmarks: ") + result.m_errorString.c_str()); + ask.addButton(tr("OK"), QMessageBox::NoRole); + ask.exec(); + } + }); +} + +void BookmarkDialog::OnDeleteClick() +{ + auto & bm = m_framework.GetBookmarkManager(); + for (auto item : m_tree->selectedItems()) + { + auto const categoryIt = m_categories.find(item); + if (categoryIt != m_categories.cend()) + { + if (m_categories.size() == 1) + { + QMessageBox ask(this); + ask.setIcon(QMessageBox::Information); + ask.setText(tr("Could not delete the last category.")); + ask.addButton(tr("OK"), QMessageBox::NoRole); + ask.exec(); + } + else + { + bm.GetEditSession().DeleteBmCategory(categoryIt->second); + FillTree(); + } + return; + } + + auto const bookmarkIt = m_bookmarks.find(item); + if (bookmarkIt != m_bookmarks.cend()) + { + bm.GetEditSession().DeleteBookmark(bookmarkIt->second); + FillTree(); + return; + } + + auto const trackIt = m_tracks.find(item); + if (trackIt != m_tracks.cend()) + { + bm.GetEditSession().DeleteTrack(trackIt->second); + FillTree(); + return; + } + } + + QMessageBox ask(this); + ask.setIcon(QMessageBox::Warning); + ask.setText(tr("Select category, bookmark or track to delete.")); + ask.addButton(tr("OK"), QMessageBox::NoRole); + ask.exec(); +} + +QTreeWidgetItem * BookmarkDialog::CreateTreeItem(std::string const & title, QTreeWidgetItem * parent) +{ + QStringList labels; + labels << QString(title.c_str()) << tr(parent != nullptr ? "Show on the map" : ""); + + QTreeWidgetItem * item = new QTreeWidgetItem(parent, labels); + item->setData(1, Qt::UserRole, QVariant(title.c_str())); + item->setData(2, Qt::UserRole, QVariant(tr(parent != nullptr ? "Show on the map" : ""))); + + if (parent == nullptr) + m_tree->addTopLevelItem(item); + + return item; +} + +void BookmarkDialog::FillTree() +{ + m_tree->setSortingEnabled(false); + m_tree->clear(); + m_categories.clear(); + m_bookmarks.clear(); + m_tracks.clear(); + + auto categoriesItem = CreateTreeItem("Categories", nullptr); + + auto const & bm = m_framework.GetBookmarkManager(); + + if (!bm.IsAsyncLoadingInProgress()) + { + for (auto catId : bm.GetBmGroupsIdList()) + { + auto categoryItem = CreateTreeItem(bm.GetCategoryName(catId), categoriesItem); + m_categories[categoryItem] = catId; + + for (auto bookmarkId : bm.GetUserMarkIds(catId)) + { + auto const bookmark = bm.GetBookmark(bookmarkId); + auto name = GetPreferredBookmarkStr(bookmark->GetName()); + if (name.empty()) + { + name = measurement_utils::FormatLatLon(MercatorBounds::YToLat(bookmark->GetPivot().y), + MercatorBounds::XToLon(bookmark->GetPivot().x), + true /* withSemicolon */); + } + auto bookmarkItem = CreateTreeItem(name + " (Bookmark)", categoryItem); + bookmarkItem->setTextColor(0, Qt::blue); + m_bookmarks[bookmarkItem] = bookmarkId; + } + + for (auto trackId : bm.GetTrackIds(catId)) + { + auto const track = bm.GetTrack(trackId); + auto name = track->GetName(); + if (name.empty()) + name = "No name"; + auto trackItem = CreateTreeItem(name + " (Track)", categoryItem); + trackItem->setTextColor(0, Qt::darkGreen); + m_tracks[trackItem] = trackId; + } + } + } + else + { + CreateTreeItem("Loading in progress...", categoriesItem); + } + + m_tree->expandAll(); + + m_tree->header()->setSectionResizeMode(0, QHeaderView::Stretch); + m_tree->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); +} + +void BookmarkDialog::ShowModal() +{ + // If called for first time. + if (!m_tree->topLevelItemCount()) + FillTree(); + + exec(); +} +} // namespace qt diff --git a/qt/bookmark_dialog.hpp b/qt/bookmark_dialog.hpp new file mode 100644 index 0000000000..4dad6d815e --- /dev/null +++ b/qt/bookmark_dialog.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "kml/types.hpp" + +#include <QtWidgets/QApplication> +#include <QtWidgets/QDialog> + +#include <string> +#include <unordered_map> + +class QTreeWidget; +class QTreeWidgetItem; +class QLabel; +class QPushButton; + +class Framework; + +namespace qt +{ +class BookmarkDialog : public QDialog +{ + Q_OBJECT + +public: + BookmarkDialog(QWidget * parent, Framework & framework); + + void ShowModal(); + +private slots: + void OnItemClick(QTreeWidgetItem * item, int column); + void OnCloseClick(); + void OnImportClick(); + void OnExportClick(); + void OnDeleteClick(); + +private: + void FillTree(); + QTreeWidgetItem * CreateTreeItem(std::string const & title, QTreeWidgetItem * parent); + void OnAsyncLoadingStarted(); + void OnAsyncLoadingFinished(); + void OnAsyncLoadingFileSuccess(std::string const & fileName, bool isTemporaryFile); + void OnAsyncLoadingFileError(std::string const & fileName, bool isTemporaryFile); + + QTreeWidget * m_tree; + Framework & m_framework; + std::unordered_map<QTreeWidgetItem *, kml::MarkGroupId> m_categories; + std::unordered_map<QTreeWidgetItem *, kml::MarkId> m_bookmarks; + std::unordered_map<QTreeWidgetItem *, kml::TrackId> m_tracks; +}; +} // namespace qt diff --git a/qt/mainwindow.cpp b/qt/mainwindow.cpp index 2712c5934d..673fcb3bba 100644 --- a/qt/mainwindow.cpp +++ b/qt/mainwindow.cpp @@ -1,4 +1,5 @@ #include "qt/about.hpp" +#include "qt/bookmark_dialog.hpp" #include "qt/draw_widget.hpp" #include "qt/mainwindow.hpp" #include "qt/osm_auth_dialog.hpp" @@ -268,6 +269,10 @@ void MainWindow::CreateNavigationBar() m_trafficEnableAction->setChecked(m_pDrawWidget->GetFramework().LoadTrafficEnabled()); pToolBar->addSeparator(); + m_bookmarksAction = pToolBar->addAction(QIcon(":/navig64/bookmark.png"), tr("Show bookmarks and tracks"), + this, SLOT(OnBookmarksAction())); + pToolBar->addSeparator(); + #ifndef BUILD_DESIGNER m_selectStartRoutePoint = new QAction(QIcon(":/navig64/point-start.png"), tr("Start point"), this); @@ -309,7 +314,6 @@ void MainWindow::CreateNavigationBar() clearAction->setToolTip(tr("Clear route")); pToolBar->addSeparator(); - // TODO(AlexZ): Replace icon. m_pCreateFeatureAction = pToolBar->addAction(QIcon(":/navig64/select.png"), tr("Create Feature"), this, SLOT(OnCreateFeatureClicked())); m_pCreateFeatureAction->setCheckable(true); @@ -865,6 +869,13 @@ void MainWindow::OnClearRoute() m_pDrawWidget->ClearRoute(); } +void MainWindow::OnBookmarksAction() +{ + BookmarkDialog dlg(this, m_pDrawWidget->GetFramework()); + dlg.ShowModal(); + m_pDrawWidget->update(); +} + // static void MainWindow::SetDefaultSurfaceFormat(bool apiOpenGLES3) { diff --git a/qt/mainwindow.hpp b/qt/mainwindow.hpp index 5ae9a88d90..de6e11b9eb 100644 --- a/qt/mainwindow.hpp +++ b/qt/mainwindow.hpp @@ -45,6 +45,7 @@ class MainWindow : public QMainWindow, location::LocationObserver QAction * m_clearSelection = nullptr; QAction * m_pSearchAction = nullptr; QAction * m_trafficEnableAction = nullptr; + QAction * m_bookmarksAction = nullptr; QAction * m_selectionCityBoundariesMode = nullptr; QToolButton * m_routePointsToolButton = nullptr; QAction * m_selectStartRoutePoint = nullptr; @@ -116,6 +117,8 @@ protected Q_SLOTS: void OnFollowRoute(); void OnClearRoute(); + void OnBookmarksAction(); + #ifdef BUILD_DESIGNER void OnBuildStyle(); void OnRecalculateGeomIndex(); diff --git a/qt/res/bookmark.png b/qt/res/bookmark.png Binary files differnew file mode 100644 index 0000000000..badfc22b51 --- /dev/null +++ b/qt/res/bookmark.png diff --git a/qt/res/resources.qrc b/qt/res/resources.qrc index bcbc2c0f87..1d0f1f70b9 100644 --- a/qt/res/resources.qrc +++ b/qt/res/resources.qrc @@ -25,6 +25,7 @@ <file>test.png</file> <file>geom.png</file> <file>phonepack.png</file> + <file>bookmark.png</file> </qresource> <qresource prefix="/ui"> <file>logo.png</file> diff --git a/qt/res/traffic.png b/qt/res/traffic.png Binary files differindex add88ebfba..871039503c 100644 --- a/qt/res/traffic.png +++ b/qt/res/traffic.png |