File indexing completed on 2024-04-21 03:49:55
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2012 Dennis Nienhüser <nienhueser@kde.org> 0004 // 0005 0006 #include "SearchWidget.h" 0007 0008 #include "GeoDataPlacemark.h" 0009 #include "GeoDataLatLonAltBox.h" 0010 #include "GeoDataDocument.h" 0011 #include "GeoDataTreeModel.h" 0012 #include "SearchInputWidget.h" 0013 #include "MarbleWidget.h" 0014 #include "MarbleModel.h" 0015 #include "BranchFilterProxyModel.h" 0016 #include "MarblePlacemarkModel.h" 0017 #include "SearchRunnerManager.h" 0018 #include "ViewportParams.h" 0019 #include "MarbleDebug.h" 0020 0021 #include <QListView> 0022 #include <QVBoxLayout> 0023 #include <QElapsedTimer> 0024 0025 namespace Marble { 0026 0027 class SearchWidgetPrivate 0028 { 0029 public: 0030 SearchRunnerManager* m_runnerManager; 0031 SearchInputWidget *m_searchField; 0032 QListView *m_searchResultView; 0033 MarbleWidget *m_widget; 0034 BranchFilterProxyModel m_branchfilter; 0035 QSortFilterProxyModel m_sortproxy; 0036 GeoDataDocument *m_document; 0037 QString m_planetId; 0038 0039 SearchWidgetPrivate(); 0040 void setSearchResult( const QVector<GeoDataPlacemark*>& ); 0041 void search( const QString &searchTerm, SearchMode searchMode ); 0042 void clearSearch(); 0043 void centerMapOn( const QModelIndex &index ); 0044 void handlePlanetChange(); 0045 }; 0046 0047 SearchWidgetPrivate::SearchWidgetPrivate() : 0048 m_runnerManager( nullptr ), 0049 m_searchField( nullptr ), 0050 m_searchResultView( nullptr ), 0051 m_widget( nullptr ), 0052 m_branchfilter(), 0053 m_sortproxy(), 0054 m_document( new GeoDataDocument ) 0055 { 0056 m_document->setName( QObject::tr( "Search Results" ) ); 0057 } 0058 0059 void SearchWidgetPrivate::setSearchResult( const QVector<GeoDataPlacemark *>& locations ) 0060 { 0061 if( locations.isEmpty() ) { 0062 return; 0063 } 0064 0065 QElapsedTimer timer; 0066 timer.start(); 0067 0068 // fill the local document with results 0069 m_widget->model()->placemarkSelectionModel()->clear(); 0070 GeoDataTreeModel *treeModel = m_widget->model()->treeModel(); 0071 treeModel->removeDocument( m_document ); 0072 m_document->clear(); 0073 m_document->setName( QString( QObject::tr( "Search for '%1'" ) ).arg( m_searchField->text() ) ); 0074 for (GeoDataPlacemark *placemark: locations ) { 0075 m_document->append( new GeoDataPlacemark( *placemark ) ); 0076 } 0077 treeModel->addDocument( m_document ); 0078 m_branchfilter.setBranchIndex( treeModel, treeModel->index( m_document ) ); 0079 m_searchResultView->setRootIndex( 0080 m_sortproxy.mapFromSource( 0081 m_branchfilter.mapFromSource( treeModel->index( m_document ) ) ) ); 0082 m_widget->centerOn( m_document->latLonAltBox() ); 0083 mDebug() << " Time elapsed:"<< timer.elapsed() << " ms"; 0084 } 0085 0086 SearchWidget::SearchWidget( QWidget *parent, Qt::WindowFlags flags ) : 0087 QWidget( parent, flags ), 0088 d( new SearchWidgetPrivate ) 0089 { 0090 d->m_sortproxy.setSortRole( MarblePlacemarkModel::PopularityIndexRole ); 0091 d->m_sortproxy.sort( 0, Qt::AscendingOrder ); 0092 d->m_sortproxy.setDynamicSortFilter( true ); 0093 d->m_sortproxy.setSourceModel( &d->m_branchfilter ); 0094 0095 d->m_searchField = new SearchInputWidget( this ); 0096 setFocusProxy( d->m_searchField ); 0097 connect( d->m_searchField, SIGNAL(search(QString,SearchMode)), 0098 this, SLOT(search(QString,SearchMode)) ); 0099 0100 d->m_searchResultView = new QListView( this ); 0101 d->m_searchResultView->setModel( &d->m_sortproxy ); 0102 d->m_searchResultView->setMinimumSize( 0, 0 ); 0103 connect( d->m_searchResultView, SIGNAL(activated(QModelIndex)), 0104 this, SLOT(centerMapOn(QModelIndex)) ); 0105 0106 QVBoxLayout* layout = new QVBoxLayout; 0107 layout->addWidget( d->m_searchField ); 0108 layout->addWidget( d->m_searchResultView ); 0109 layout->setMargin( 0 ); 0110 setLayout( layout ); 0111 } 0112 0113 SearchWidget::~SearchWidget() 0114 { 0115 delete d; 0116 } 0117 0118 void SearchWidget::setMarbleWidget( MarbleWidget* widget ) 0119 { 0120 if ( d->m_widget ) { 0121 return; 0122 } 0123 0124 d->m_widget = widget; 0125 0126 d->m_planetId = widget->model()->planetId(); 0127 connect( widget->model(), SIGNAL(themeChanged(QString)), 0128 this, SLOT(handlePlanetChange()) ); 0129 0130 d->m_searchField->setCompletionModel( widget->model()->placemarkModel() ); 0131 connect( d->m_searchField, SIGNAL(centerOn(GeoDataCoordinates)), 0132 widget, SLOT(centerOn(GeoDataCoordinates)) ); 0133 0134 d->m_runnerManager = new SearchRunnerManager( widget->model(), this ); 0135 connect( d->m_runnerManager, SIGNAL(searchResultChanged(QVector<GeoDataPlacemark*>)), 0136 this, SLOT(setSearchResult(QVector<GeoDataPlacemark*>)) ); 0137 connect( d->m_runnerManager, SIGNAL(searchFinished(QString)), 0138 d->m_searchField, SLOT(disableSearchAnimation())); 0139 0140 GeoDataTreeModel* treeModel = d->m_widget->model()->treeModel(); 0141 treeModel->addDocument( d->m_document ); 0142 0143 d->m_branchfilter.setSourceModel( treeModel ); 0144 d->m_branchfilter.setBranchIndex( treeModel, treeModel->index( d->m_document ) ); 0145 0146 d->m_searchResultView->setRootIndex( 0147 d->m_sortproxy.mapFromSource( 0148 d->m_branchfilter.mapFromSource( treeModel->index( d->m_document ) ) ) ); 0149 } 0150 0151 void SearchWidgetPrivate::search( const QString &searchTerm, SearchMode searchMode ) 0152 { 0153 if( searchTerm.isEmpty() ) { 0154 clearSearch(); 0155 } else { 0156 if ( searchMode == AreaSearch ) { 0157 m_runnerManager->findPlacemarks( searchTerm, m_widget->viewport()->viewLatLonAltBox() ); 0158 } else { 0159 m_runnerManager->findPlacemarks( searchTerm ); 0160 } 0161 } 0162 } 0163 0164 void SearchWidgetPrivate::clearSearch() 0165 { 0166 m_widget->model()->placemarkSelectionModel()->clear(); 0167 0168 // clear the local document 0169 GeoDataTreeModel *treeModel = m_widget->model()->treeModel(); 0170 treeModel->removeDocument( m_document ); 0171 m_document->clear(); 0172 treeModel->addDocument( m_document ); 0173 m_branchfilter.setBranchIndex( treeModel, treeModel->index( m_document ) ); 0174 m_searchResultView->setRootIndex( 0175 m_sortproxy.mapFromSource( 0176 m_branchfilter.mapFromSource( treeModel->index( m_document ) ) ) ); 0177 0178 // clear cached search results 0179 m_runnerManager->findPlacemarks( QString() ); 0180 } 0181 0182 void SearchWidgetPrivate::centerMapOn( const QModelIndex &index ) 0183 { 0184 if( !index.isValid() ) { 0185 return; 0186 } 0187 GeoDataObject *object 0188 = index.model()->data(index, MarblePlacemarkModel::ObjectPointerRole ).value<GeoDataObject*>(); 0189 GeoDataPlacemark *placemark = dynamic_cast<GeoDataPlacemark*>( object ); 0190 if ( placemark ) { 0191 m_widget->centerOn( *placemark, true ); 0192 m_widget->model()->placemarkSelectionModel()->select( index, QItemSelectionModel::ClearAndSelect ); 0193 } 0194 } 0195 0196 void SearchWidgetPrivate::handlePlanetChange() 0197 { 0198 const QString newPlanetId = m_widget->model()->planetId(); 0199 0200 if (newPlanetId == m_planetId) { 0201 return; 0202 } 0203 0204 m_planetId = newPlanetId; 0205 clearSearch(); 0206 } 0207 0208 } 0209 0210 #include "moc_SearchWidget.cpp"