diff --git a/qt/mainwindow.cpp b/qt/mainwindow.cpp index d20e791e06..fee6b95de8 100644 --- a/qt/mainwindow.cpp +++ b/qt/mainwindow.cpp @@ -44,13 +44,13 @@ MainWindow::MainWindow() m_pDrawWidget = new DrawWidget(this, m_storage); CreateNavigationBar(); - CreateSearchBarAndPanel(); #ifndef NO_DOWNLOADER CreateClassifPanel(); CreateGuidePanel(); #endif // NO_DOWNLOADER + setCentralWidget(m_pDrawWidget); setWindowTitle(tr("MapsWithMe")); @@ -253,7 +253,7 @@ void MainWindow::CreateNavigationBar() // add view actions 1 button_t arr[] = { { QString(), 0, 0 }, -// { tr("Show all"), ":/navig64/world.png", SLOT(ShowAll()) }, + //{ tr("Show all"), ":/navig64/world.png", SLOT(ShowAll()) }, { tr("Scale +"), ":/navig64/plus.png", SLOT(ScalePlus()) } }; add_buttons(pToolBar, arr, ARRAY_SIZE(arr), m_pDrawWidget); @@ -274,6 +274,7 @@ void MainWindow::CreateNavigationBar() }; add_buttons(pToolBar, arr, ARRAY_SIZE(arr), m_pDrawWidget); } + #ifndef NO_DOWNLOADER { // add mainframe actions @@ -284,6 +285,7 @@ void MainWindow::CreateNavigationBar() add_buttons(pToolBar, arr, ARRAY_SIZE(arr), this); } #endif // NO_DOWNLOADER + addToolBar(Qt::RightToolBarArea, pToolBar); } diff --git a/qt/search_panel.cpp b/qt/search_panel.cpp index 3d02f17753..e947c958aa 100644 --- a/qt/search_panel.cpp +++ b/qt/search_panel.cpp @@ -4,23 +4,26 @@ #include "../std/bind.hpp" #include + #include #include #include #include #include #include +#include + namespace qt { SearchPanel::SearchPanel(DrawWidget * drawWidget, QWidget * parent) - : QWidget(parent), m_pDrawWidget(drawWidget), m_queryId(0) + : QWidget(parent), m_pDrawWidget(drawWidget), m_queryId(0), m_busyIcon(":/ui/busy.png") { m_pEditor = new QLineEdit(this); connect(m_pEditor, SIGNAL(textChanged(QString const &)), this, SLOT(OnSearchTextChanged(QString const &))); - m_pTable = new QTableWidget(0, 2, this); + m_pTable = new QTableWidget(0, 4, this); m_pTable->setFocusPolicy(Qt::NoFocus); m_pTable->setAlternatingRowColors(true); m_pTable->setShowGrid(false); @@ -28,7 +31,7 @@ SearchPanel::SearchPanel(DrawWidget * drawWidget, QWidget * parent) m_pTable->verticalHeader()->setVisible(false); m_pTable->horizontalHeader()->setVisible(false); m_pTable->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents); - connect(m_pTable, SIGNAL(cellClicked(int,int)), this, SLOT(OnSearchPanelItemClicked(int,int))); + connect(m_pTable, SIGNAL(cellClicked(int, int)), this, SLOT(OnSearchPanelItemClicked(int,int))); m_pClearButton = new QPushButton(this); connect(m_pClearButton, SIGNAL(pressed()), this, SLOT(OnClearButton())); @@ -46,8 +49,8 @@ SearchPanel::SearchPanel(DrawWidget * drawWidget, QWidget * parent) setLayout(verticalLayout); // for multithreading support - CHECK(connect(this, SIGNAL(SearchResultSignal(search::Result *, int)), - this, SLOT(OnSearchResult(search::Result *, int)), Qt::QueuedConnection), ()); + CHECK(connect(this, SIGNAL(SearchResultSignal(ResultT *, int)), + this, SLOT(OnSearchResult(ResultT *, int)), Qt::QueuedConnection), ()); setFocusPolicy(Qt::StrongFocus); setFocusProxy(m_pEditor); @@ -65,29 +68,100 @@ SearchPanel::~SearchPanel() ClearVector(m_results); } -void SearchPanel::SearchResultThreadFunc(search::Result const & result, int queryId) +void SearchPanel::SearchResultThreadFunc(ResultT const & result, int queryId) { if (queryId == m_queryId) - emit SearchResultSignal(new search::Result(result), queryId); + emit SearchResultSignal(new ResultT(result), queryId); } -void SearchPanel::OnSearchResult(search::Result * result, int queryId) +namespace +{ + QTableWidgetItem * create_item(QString const & s) + { + QTableWidgetItem * item = new QTableWidgetItem(s); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + return item; + } + + QString format_distance(double m, bool & drawDir) + { + drawDir = true; + if (m < 1.0) + { + drawDir = false; + return QString::fromAscii("0 m."); + } + + if (m >= 1.0E3) return QString("%1 km.").arg(m * 1.0E-3, 0, 'f', 1); + else return QString("%1 m.").arg(m, 0, 'f', 0); + } + + QIcon draw_direction(double a) + { + int const dim = 64; + + QPixmap pm(dim, dim); + + QBitmap mask(dim, dim); + mask.clear(); + pm.setMask(mask); + + QPainter painter(&pm); + painter.setBackgroundMode(Qt::TransparentMode); + + QMatrix m; + m.translate(dim/2, dim/2); + m.rotate(-a / math::pi * 180.0); + m.translate(-dim/2, -dim/2); + + typedef QPointF P; + QPolygonF poly(5); + poly[0] = P(dim/3, dim/2); + poly[1] = P(0, dim/2 - dim/3); + poly[2] = P(dim, dim/2); + poly[3] = P(0, dim/2 + dim/3); + poly[4] = P(dim/3, dim/2); + + painter.setBrush(Qt::black); + painter.drawPolygon(m.map(poly)); + + return pm; + } +} + +void SearchPanel::OnSearchResult(ResultT * res, int queryId) { if (queryId != m_queryId) return; - if (!result->GetString().empty()) + if (!res->IsEndMarker()) { int const rowCount = m_pTable->rowCount(); - m_pTable->setRowCount(rowCount + 1); - QTableWidgetItem * item = new QTableWidgetItem(QString::fromUtf8(result->GetString().c_str())); - item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - m_pTable->setItem(rowCount, 0, item); - m_results.push_back(result); + m_pTable->insertRow(rowCount); + + m_pTable->setItem(rowCount, 1, create_item(QString::fromUtf8(res->GetString()))); + + if (res->GetResultType() == ResultT::RESULT_FEATURE) + { + m_pTable->setItem(rowCount, 0, create_item(QString::fromUtf8(res->GetFetureTypeAsString().c_str()))); + + bool drawDir; + m_pTable->setItem(rowCount, 2, create_item(format_distance(res->GetDistanceFromCenter(), drawDir))); + + if (drawDir) + { + QTableWidgetItem * item = new QTableWidgetItem(draw_direction(res->GetDirectionFromCenter()), QString()); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + m_pTable->setItem(rowCount, 3, item); + } + } + + m_results.push_back(res); } else - { // last element - delete result; + { + // last element + delete res; // stop search busy indicator m_pAnimationTimer->stop(); m_pClearButton->setIcon(QIcon(":/ui/x.png")); @@ -115,7 +189,8 @@ void SearchPanel::OnSearchTextChanged(QString const & str) m_pClearButton->setVisible(true); } else - { // hide X button + { + // hide X button m_pClearButton->setVisible(false); } } @@ -124,12 +199,14 @@ void SearchPanel::OnSearchPanelItemClicked(int row, int) { disconnect(m_pDrawWidget, SIGNAL(ViewportChanged()), this, SLOT(OnViewportChanged())); ASSERT_EQUAL(m_results.size(), static_cast(m_pTable->rowCount()), ()); - if (m_results[row]->GetResultType() == search::Result::RESULT_FEATURE) - { // center viewport on clicked item + if (m_results[row]->GetResultType() == ResultT::RESULT_FEATURE) + { + // center viewport on clicked item m_pDrawWidget->ShowFeature(m_results[row]->GetFeatureRect()); } else - { // insert suggestion into the search bar + { + // insert suggestion into the search bar string const suggestion = m_results[row]->GetSuggestionString(); m_pEditor->setText(QString::fromUtf8(suggestion.c_str())); } @@ -156,15 +233,14 @@ void SearchPanel::OnViewportChanged() void SearchPanel::OnAnimationTimer() { static int angle = 0; - QPixmap pixmap(":/ui/busy.png"); - QSize const oldSize = pixmap.size(); + QMatrix rm; angle += 15; if (angle >= 360) angle = 0; rm.rotate(angle); - pixmap = pixmap.transformed(rm); - m_pClearButton->setIcon(QIcon(pixmap)); + + m_pClearButton->setIcon(QIcon(m_busyIcon.transformed(rm))); } void SearchPanel::OnClearButton() diff --git a/qt/search_panel.hpp b/qt/search_panel.hpp index 068eb1c7e9..6f987de2c8 100644 --- a/qt/search_panel.hpp +++ b/qt/search_panel.hpp @@ -4,7 +4,8 @@ #include "../std/vector.hpp" -#include +#include +#include class QTableWidget; class QLineEdit; @@ -24,17 +25,20 @@ class SearchPanel : public QWidget QPushButton * m_pClearButton; QTimer * m_pAnimationTimer; + QPixmap m_busyIcon; + /// Stores current search results - vector m_results; + typedef search::Result ResultT; + vector m_results; int volatile m_queryId; Q_OBJECT signals: - void SearchResultSignal(search::Result * result, int queryId); + void SearchResultSignal(ResultT * result, int queryId); private: - void SearchResultThreadFunc(search::Result const & result, int queryId); + void SearchResultThreadFunc(ResultT const & result, int queryId); virtual void showEvent(QShowEvent *); virtual void hideEvent(QHideEvent *); @@ -46,7 +50,7 @@ private slots: void OnSearchPanelItemClicked(int row, int column); void OnSearchTextChanged(QString const &); /// Called via signal to support multithreading - void OnSearchResult(search::Result * result, int queryId); + void OnSearchResult(ResultT * result, int queryId); void OnViewportChanged(); void OnAnimationTimer(); void OnClearButton(); diff --git a/search/engine.cpp b/search/engine.cpp index 92f745a865..053e2ffd7f 100644 --- a/search/engine.cpp +++ b/search/engine.cpp @@ -1,12 +1,14 @@ #include "engine.hpp" #include "query.hpp" #include "result.hpp" + #include "../platform/concurrent_runner.hpp" -#include "../indexer/feature.hpp" + #include "../std/function.hpp" #include "../std/string.hpp" #include "../std/vector.hpp" + namespace search { diff --git a/search/engine.hpp b/search/engine.hpp index ce983fb3b2..ce5d3d5063 100644 --- a/search/engine.hpp +++ b/search/engine.hpp @@ -1,13 +1,17 @@ #pragma once #include "../indexer/index.hpp" + #include "../geometry/rect2d.hpp" + #include "../base/base.hpp" #include "../base/mutex.hpp" #include "../base/runner.hpp" + #include "../std/function.hpp" #include "../std/scoped_ptr.hpp" #include "../std/string.hpp" + class FileReader; class FeatureType; diff --git a/search/intermediate_result.cpp b/search/intermediate_result.cpp index 8f618612d2..b5afe469ab 100644 --- a/search/intermediate_result.cpp +++ b/search/intermediate_result.cpp @@ -37,15 +37,15 @@ bool IntermediateResult::operator < (IntermediateResult const & o) const Result IntermediateResult::GenerateFinalResult() const { -#ifdef DEBUG - return Result(m_str - + ' ' + strings::to_string(m_distance * 0.001) - + ' ' + strings::to_string(m_direction / math::pi * 180.0) - + ' ' + strings::to_string(m_matchPenalty) - + ' ' + strings::to_string(m_minVisibleScale), -#else +//#ifdef DEBUG +// return Result(m_str +// + ' ' + strings::to_string(m_distance * 0.001) +// + ' ' + strings::to_string(m_direction / math::pi * 180.0) +// + ' ' + strings::to_string(m_matchPenalty) +// + ' ' + strings::to_string(m_minVisibleScale), +//#else return Result(m_str, -#endif +//#endif m_type, m_rect, m_distance, m_direction); } diff --git a/search/result.cpp b/search/result.cpp index 58e9ffdd09..b6ed717879 100644 --- a/search/result.cpp +++ b/search/result.cpp @@ -1,5 +1,8 @@ #include "result.hpp" +#include "../indexer/classificator.hpp" + + namespace search { @@ -34,12 +37,35 @@ uint32_t Result::GetFetureType() const return m_featureType; } +string Result::GetFetureTypeAsString() const +{ + ASSERT_EQUAL(GetResultType(), RESULT_FEATURE, ()); + + ClassifObject const * p = classif().GetRoot(); + + uint8_t i = 0; + uint8_t v; + while (ftype::GetValue(m_featureType, i, v) && i < 2) + { + p = p->GetObject(v); + ++i; + } + + return p->GetName(); +} + double Result::GetDistanceFromCenter() const { ASSERT_EQUAL(GetResultType(), RESULT_FEATURE, ()); return m_distanceFromCenter; } +double Result::GetDirectionFromCenter() const +{ + ASSERT_EQUAL(GetResultType(), RESULT_FEATURE, ()); + return m_directionFromCenter; +} + string Result::GetSuggestionString() const { ASSERT_EQUAL(GetResultType(), RESULT_SUGGESTION, ()); diff --git a/search/result.hpp b/search/result.hpp index 4241f77938..ae6eb9487c 100644 --- a/search/result.hpp +++ b/search/result.hpp @@ -19,8 +19,10 @@ public: double distanceFromCenter, double directionFromCenter); Result(string const & str, string const & suggestionStr); + bool IsEndMarker() const { return m_str.empty(); } + // String that is displayed in the GUI. - string GetString() const { return m_str; } + char const * GetString() const { return m_str.c_str(); } // Type of the result. ResultType GetResultType() const; @@ -30,6 +32,7 @@ public: // Type of a feature, if GetResultType() == RESULT_FEATURE. uint32_t GetFetureType() const; + string GetFetureTypeAsString() const; // Distance from the center of the screen, if GetResultType() == RESULT_FEATURE. double GetDistanceFromCenter() const;