File indexing completed on 2024-05-05 03:49:20

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2015 Gábor Péterffy <peterffy95@gmail.com>
0004 //
0005 
0006 #include "SearchBackend.h"
0007 
0008 #include "SearchRunnerManager.h"
0009 #include "MarbleModel.h"
0010 #include "Coordinate.h"
0011 
0012 #include <QCompleter>
0013 
0014 using namespace Marble;
0015 
0016 
0017 SearchBackend::SearchBackend(QObject *parent) :
0018     QObject(parent),
0019     m_searchManager( nullptr ),
0020     m_marbleQuickItem( nullptr ),
0021     m_placemarkModel( nullptr ),
0022     m_completer( nullptr ),
0023     m_completionModel( new MarblePlacemarkModel ),
0024     m_completionContainer( new QVector<GeoDataPlacemark*>() ),
0025     m_selectedPlacemark( )
0026 {
0027     m_model.setSortRole( MarblePlacemarkModel::PopularityIndexRole );
0028     m_model.sort(0);
0029     m_model.setDynamicSortFilter(true);
0030     m_completionModel->setPlacemarkContainer(m_completionContainer);
0031 }
0032 
0033 void SearchBackend::search(const QString &place)
0034 {
0035     if (m_marbleQuickItem)
0036     {
0037         m_searchManager->searchPlacemarks(place);
0038     }
0039 }
0040 
0041 void SearchBackend::setCompletionPrefix(const QString &prefix)
0042 {
0043     if( m_completer != nullptr && m_completer->completionPrefix() != prefix ) {
0044         if (!m_lastSuccessfulCompletion.isEmpty()
0045                 && prefix.startsWith(m_lastSuccessfulCompletion)
0046                 && prefix.size() > m_lastSuccessfulCompletion.size()) {
0047             return;
0048         }
0049 
0050         m_completionModel->removePlacemarks(QStringLiteral("Completion model"), 0, m_completionModel->rowCount());
0051         m_completionContainer->clear();
0052         QString const lastPrefix = m_completer->completionPrefix();
0053         m_completer->setCompletionPrefix(prefix);
0054         if( prefix.isEmpty() ) {
0055             emit completionModelChanged(m_completionModel);
0056             return;
0057         }
0058         QVector<GeoDataPlacemark*> *container = new QVector<GeoDataPlacemark*>();
0059         QAbstractProxyModel *model = qobject_cast<QAbstractProxyModel*>(m_completer->completionModel());
0060         for( int i = 0; i<m_completer->completionModel()->rowCount(); ++i ) {
0061             QModelIndex index = model->mapToSource(model->index(i,0));
0062             QVariant data = m_marbleQuickItem->model()->placemarkModel()->data(index, MarblePlacemarkModel::ObjectPointerRole);
0063             GeoDataPlacemark *placemark = placemarkFromQVariant(data);
0064             if( placemark != nullptr ) {
0065                 container->append(placemark);
0066             }
0067         }
0068         if (container->isEmpty() && prefix.startsWith(lastPrefix) ) {
0069             m_lastSuccessfulCompletion = lastPrefix;
0070         } else if (!container->isEmpty()) {
0071             m_lastSuccessfulCompletion.clear();
0072         }
0073         m_completionModel->setPlacemarkContainer(container);
0074         m_completionModel->addPlacemarks(0, container->size());
0075         delete m_completionContainer;
0076         m_completionContainer = container;
0077         emit completionModelChanged(m_completionModel);
0078     }
0079 }
0080 
0081 QObject * SearchBackend::marbleQuickItem()
0082 {
0083     return m_marbleQuickItem;
0084 }
0085 
0086 MarblePlacemarkModel *SearchBackend::completionModel()
0087 {
0088     return m_completionModel;
0089 }
0090 
0091 const QObject * SearchBackend::marbleQuickItem() const
0092 {
0093     return m_marbleQuickItem;
0094 }
0095 
0096 Placemark *SearchBackend::selectedPlacemark()
0097 {
0098     return &m_selectedPlacemark;
0099 }
0100 
0101 void SearchBackend::setSelectedPlacemark(int placemarkIndex)
0102 {
0103     QVariant data = m_placemarkModel->data(m_placemarkModel->index(placemarkIndex), MarblePlacemarkModel::ObjectPointerRole);
0104     GeoDataPlacemark *placemark = placemarkFromQVariant(data);
0105     if( placemark == nullptr ) {
0106         return;
0107     }
0108 
0109     m_selectedPlacemark.setGeoDataPlacemark(*placemark);
0110     m_marbleQuickItem->centerOn(*placemark, true);
0111     emit selectedPlacemarkChanged(&m_selectedPlacemark);
0112 }
0113 
0114 void SearchBackend::setMarbleQuickItem(QObject *marbleQuickItem)
0115 {
0116     MarbleQuickItem * item = qobject_cast<MarbleQuickItem*>(marbleQuickItem);
0117     if (m_marbleQuickItem == item)
0118     {
0119         return;
0120     }
0121 
0122     if (item)
0123     {
0124         delete m_searchManager;
0125         delete m_completer;
0126         m_marbleQuickItem = item;
0127         m_searchManager = new SearchRunnerManager(m_marbleQuickItem->model(), this);
0128 
0129         connect(m_searchManager, SIGNAL(searchResultChanged(QAbstractItemModel*)),
0130                 this, SLOT(updateSearchResult(QAbstractItemModel*)));
0131         connect(m_searchManager, SIGNAL(searchFinished(QString)),
0132                 this, SIGNAL(searchFinished(QString)));
0133 
0134         m_completer = new QCompleter();
0135         m_completer->setModel(m_marbleQuickItem->model()->placemarkModel());
0136         m_completer->setCompletionRole(Qt::DisplayRole);
0137         m_completer->setCaseSensitivity(Qt::CaseInsensitive);
0138 
0139         emit marbleQuickItemChanged(marbleQuickItem);
0140     }
0141 }
0142 
0143 void SearchBackend::updateSearchResult(QAbstractItemModel *result)
0144 {
0145     m_placemarkModel = qobject_cast<MarblePlacemarkModel*>(result);
0146     emit searchResultChanged(m_placemarkModel);
0147 }
0148 
0149 GeoDataPlacemark *SearchBackend::placemarkFromQVariant(const QVariant &data)
0150 {
0151     if( !data.isValid() ) {
0152         return nullptr;
0153     }
0154     GeoDataObject *object = qvariant_cast<GeoDataObject*>( data );
0155     if( object == nullptr ) {
0156         return nullptr;
0157     }
0158     GeoDataPlacemark *placemark = dynamic_cast<GeoDataPlacemark*>( object );
0159     if( placemark == nullptr ) {
0160         return nullptr;
0161     }
0162     return placemark;
0163 }
0164 
0165 #include "moc_SearchBackend.cpp"