Marble

SearchWidget.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2012 Dennis Nienhüser <nienhueser@kde.org>
4//
5
6#include "SearchWidget.h"
7
8#include "GeoDataPlacemark.h"
9#include "GeoDataLatLonAltBox.h"
10#include "GeoDataDocument.h"
11#include "GeoDataTreeModel.h"
12#include "SearchInputWidget.h"
13#include "MarbleWidget.h"
14#include "MarbleModel.h"
15#include "BranchFilterProxyModel.h"
16#include "MarblePlacemarkModel.h"
17#include "SearchRunnerManager.h"
18#include "ViewportParams.h"
19#include "MarbleDebug.h"
20
21#include <QListView>
22#include <QVBoxLayout>
23#include <QElapsedTimer>
24
25namespace Marble {
26
27class SearchWidgetPrivate
28{
29public:
30 SearchRunnerManager* m_runnerManager;
31 SearchInputWidget *m_searchField;
32 QListView *m_searchResultView;
33 MarbleWidget *m_widget;
34 BranchFilterProxyModel m_branchfilter;
35 QSortFilterProxyModel m_sortproxy;
36 GeoDataDocument *m_document;
37 QString m_planetId;
38
39 SearchWidgetPrivate();
40 void setSearchResult( const QVector<GeoDataPlacemark*>& );
41 void search( const QString &searchTerm, SearchMode searchMode );
42 void clearSearch();
43 void centerMapOn( const QModelIndex &index );
44 void handlePlanetChange();
45};
46
47SearchWidgetPrivate::SearchWidgetPrivate() :
48 m_runnerManager( nullptr ),
49 m_searchField( nullptr ),
50 m_searchResultView( nullptr ),
51 m_widget( nullptr ),
52 m_branchfilter(),
53 m_sortproxy(),
54 m_document( new GeoDataDocument )
55{
56 m_document->setName( QObject::tr( "Search Results" ) );
57}
58
59void SearchWidgetPrivate::setSearchResult( const QVector<GeoDataPlacemark *>& locations )
60{
61 if( locations.isEmpty() ) {
62 return;
63 }
64
65 QElapsedTimer timer;
66 timer.start();
67
68 // fill the local document with results
69 m_widget->model()->placemarkSelectionModel()->clear();
70 GeoDataTreeModel *treeModel = m_widget->model()->treeModel();
71 treeModel->removeDocument( m_document );
72 m_document->clear();
73 m_document->setName( QString( QObject::tr( "Search for '%1'" ) ).arg( m_searchField->text() ) );
74 for (GeoDataPlacemark *placemark: locations ) {
75 m_document->append( new GeoDataPlacemark( *placemark ) );
76 }
77 treeModel->addDocument( m_document );
78 m_branchfilter.setBranchIndex( treeModel, treeModel->index( m_document ) );
79 m_searchResultView->setRootIndex(
80 m_sortproxy.mapFromSource(
81 m_branchfilter.mapFromSource( treeModel->index( m_document ) ) ) );
82 m_widget->centerOn( m_document->latLonAltBox() );
83 mDebug() << " Time elapsed:"<< timer.elapsed() << " ms";
84}
85
86SearchWidget::SearchWidget( QWidget *parent, Qt::WindowFlags flags ) :
87 QWidget( parent, flags ),
88 d( new SearchWidgetPrivate )
89{
90 d->m_sortproxy.setSortRole( MarblePlacemarkModel::PopularityIndexRole );
91 d->m_sortproxy.sort( 0, Qt::AscendingOrder );
92 d->m_sortproxy.setDynamicSortFilter( true );
93 d->m_sortproxy.setSourceModel( &d->m_branchfilter );
94
95 d->m_searchField = new SearchInputWidget( this );
96 setFocusProxy( d->m_searchField );
97 connect( d->m_searchField, SIGNAL(search(QString,SearchMode)),
98 this, SLOT(search(QString,SearchMode)) );
99
100 d->m_searchResultView = new QListView( this );
101 d->m_searchResultView->setModel( &d->m_sortproxy );
102 d->m_searchResultView->setMinimumSize( 0, 0 );
103 connect( d->m_searchResultView, SIGNAL(activated(QModelIndex)),
104 this, SLOT(centerMapOn(QModelIndex)) );
105
106 QVBoxLayout* layout = new QVBoxLayout;
107 layout->addWidget( d->m_searchField );
108 layout->addWidget( d->m_searchResultView );
109 layout->setMargin( 0 );
110 setLayout( layout );
111}
112
113SearchWidget::~SearchWidget()
114{
115 delete d;
116}
117
118void SearchWidget::setMarbleWidget( MarbleWidget* widget )
119{
120 if ( d->m_widget ) {
121 return;
122 }
123
124 d->m_widget = widget;
125
126 d->m_planetId = widget->model()->planetId();
127 connect( widget->model(), SIGNAL(themeChanged(QString)),
128 this, SLOT(handlePlanetChange()) );
129
130 d->m_searchField->setCompletionModel( widget->model()->placemarkModel() );
131 connect( d->m_searchField, SIGNAL(centerOn(GeoDataCoordinates)),
132 widget, SLOT(centerOn(GeoDataCoordinates)) );
133
134 d->m_runnerManager = new SearchRunnerManager( widget->model(), this );
135 connect( d->m_runnerManager, SIGNAL(searchResultChanged(QVector<GeoDataPlacemark*>)),
136 this, SLOT(setSearchResult(QVector<GeoDataPlacemark*>)) );
137 connect( d->m_runnerManager, SIGNAL(searchFinished(QString)),
138 d->m_searchField, SLOT(disableSearchAnimation()));
139
140 GeoDataTreeModel* treeModel = d->m_widget->model()->treeModel();
141 treeModel->addDocument( d->m_document );
142
143 d->m_branchfilter.setSourceModel( treeModel );
144 d->m_branchfilter.setBranchIndex( treeModel, treeModel->index( d->m_document ) );
145
146 d->m_searchResultView->setRootIndex(
147 d->m_sortproxy.mapFromSource(
148 d->m_branchfilter.mapFromSource( treeModel->index( d->m_document ) ) ) );
149}
150
151void SearchWidgetPrivate::search( const QString &searchTerm, SearchMode searchMode )
152{
153 if( searchTerm.isEmpty() ) {
154 clearSearch();
155 } else {
156 if ( searchMode == AreaSearch ) {
157 m_runnerManager->findPlacemarks( searchTerm, m_widget->viewport()->viewLatLonAltBox() );
158 } else {
159 m_runnerManager->findPlacemarks( searchTerm );
160 }
161 }
162}
163
164void SearchWidgetPrivate::clearSearch()
165{
166 m_widget->model()->placemarkSelectionModel()->clear();
167
168 // clear the local document
169 GeoDataTreeModel *treeModel = m_widget->model()->treeModel();
170 treeModel->removeDocument( m_document );
171 m_document->clear();
172 treeModel->addDocument( m_document );
173 m_branchfilter.setBranchIndex( treeModel, treeModel->index( m_document ) );
174 m_searchResultView->setRootIndex(
175 m_sortproxy.mapFromSource(
176 m_branchfilter.mapFromSource( treeModel->index( m_document ) ) ) );
177
178 // clear cached search results
179 m_runnerManager->findPlacemarks( QString() );
180}
181
182void SearchWidgetPrivate::centerMapOn( const QModelIndex &index )
183{
184 if( !index.isValid() ) {
185 return;
186 }
187 GeoDataObject *object
188 = index.model()->data(index, MarblePlacemarkModel::ObjectPointerRole ).value<GeoDataObject*>();
189 GeoDataPlacemark *placemark = dynamic_cast<GeoDataPlacemark*>( object );
190 if ( placemark ) {
191 m_widget->centerOn( *placemark, true );
192 m_widget->model()->placemarkSelectionModel()->select( index, QItemSelectionModel::ClearAndSelect );
193 }
194}
195
196void SearchWidgetPrivate::handlePlanetChange()
197{
198 const QString newPlanetId = m_widget->model()->planetId();
199
200 if (newPlanetId == m_planetId) {
201 return;
202 }
203
204 m_planetId = newPlanetId;
205 clearSearch();
206}
207
208}
209
210#include "moc_SearchWidget.cpp"
This file contains the headers for MarbleModel.
This file contains the headers for MarbleWidget.
This file contains the headers for ViewportParams.
Binds a QML item to a specific geodetic location in screen coordinates.
SearchMode
Search mode: Global (worldwide) versus area (local, regional) search.
virtual QVariant data(const QModelIndex &index, int role) const const=0
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
qint64 elapsed() const const
bool isEmpty() const const
bool isValid() const const
const QAbstractItemModel * model() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
bool isEmpty() const const
AscendingOrder
typedef WindowFlags
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
T value() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:18:17 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.