mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-09 00:08:52 -04:00
Merge pull request #8404 from 3nids/locator_core
Move parts of QgsLocatorFilter to core
This commit is contained in:
commit
30cf2d37bc
@ -67,6 +67,8 @@ which may occur if the model is being updated quickly multiple times as a result
|
|||||||
|
|
||||||
virtual Qt::ItemFlags flags( const QModelIndex &index ) const;
|
virtual Qt::ItemFlags flags( const QModelIndex &index ) const;
|
||||||
|
|
||||||
|
virtual QHash<int, QByteArray> roleNames() const;
|
||||||
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
104
python/core/auto_generated/locator/qgslocatormodelbridge.sip.in
Normal file
104
python/core/auto_generated/locator/qgslocatormodelbridge.sip.in
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/locator/qgslocatormodelbridge.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class QgsLocatorModelBridge : QObject
|
||||||
|
{
|
||||||
|
%Docstring
|
||||||
|
The QgsLocatorModelBridge class provides the core functionality
|
||||||
|
to be used in a locator widget.
|
||||||
|
|
||||||
|
.. versionadded:: 3.6
|
||||||
|
%End
|
||||||
|
|
||||||
|
%TypeHeaderCode
|
||||||
|
#include "qgslocatormodelbridge.h"
|
||||||
|
%End
|
||||||
|
public:
|
||||||
|
explicit QgsLocatorModelBridge( QObject *parent = 0 );
|
||||||
|
%Docstring
|
||||||
|
Constructor of QgsLocatorModelBridge
|
||||||
|
%End
|
||||||
|
virtual ~QgsLocatorModelBridge();
|
||||||
|
|
||||||
|
void performSearch( const QString &text );
|
||||||
|
%Docstring
|
||||||
|
Perform a search
|
||||||
|
%End
|
||||||
|
|
||||||
|
QgsLocator *locator() const;
|
||||||
|
%Docstring
|
||||||
|
Returns the locator
|
||||||
|
%End
|
||||||
|
|
||||||
|
QgsLocatorProxyModel *proxyModel() const;
|
||||||
|
%Docstring
|
||||||
|
Returns the proxy model
|
||||||
|
%End
|
||||||
|
|
||||||
|
bool hasQueueRequested() const;
|
||||||
|
%Docstring
|
||||||
|
Returns true if some text to be search is pending in the queue
|
||||||
|
%End
|
||||||
|
|
||||||
|
bool isRunning() const;
|
||||||
|
%Docstring
|
||||||
|
Returns true if the a search is currently running
|
||||||
|
%End
|
||||||
|
|
||||||
|
void triggerResult( const QModelIndex &index );
|
||||||
|
%Docstring
|
||||||
|
Triggers the result at given index
|
||||||
|
%End
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void resultAdded();
|
||||||
|
%Docstring
|
||||||
|
Emitted when a result is added
|
||||||
|
%End
|
||||||
|
|
||||||
|
void isRunningChanged();
|
||||||
|
%Docstring
|
||||||
|
Emitted when the running status changes
|
||||||
|
%End
|
||||||
|
|
||||||
|
void resultsCleared();
|
||||||
|
%Docstring
|
||||||
|
Emitted when the results are cleared
|
||||||
|
%End
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void invalidateResults();
|
||||||
|
%Docstring
|
||||||
|
This will invalidate current search results
|
||||||
|
%End
|
||||||
|
|
||||||
|
void updateCanvasExtent( const QgsRectangle &extent );
|
||||||
|
%Docstring
|
||||||
|
Update the canvas extent used to create search context
|
||||||
|
%End
|
||||||
|
|
||||||
|
void updateCanvasCrs( const QgsCoordinateReferenceSystem &crs );
|
||||||
|
%Docstring
|
||||||
|
Update the canvas CRS used to create search context
|
||||||
|
%End
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/locator/qgslocatormodelbridge.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||||
|
************************************************************************/
|
@ -0,0 +1,98 @@
|
|||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/locator/qgslocatormodelbridge.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class QgsLocatorModelBridge : QObject
|
||||||
|
{
|
||||||
|
%Docstring
|
||||||
|
The QgsLocatorModelBridge class provides the core functionality
|
||||||
|
to be used in a locator widget.
|
||||||
|
|
||||||
|
.. versionadded:: 3.6
|
||||||
|
%End
|
||||||
|
|
||||||
|
%TypeHeaderCode
|
||||||
|
#include "qgslocatormodelbridge.h"
|
||||||
|
%End
|
||||||
|
public:
|
||||||
|
explicit QgsLocatorModelBridge( QObject *parent = 0 );
|
||||||
|
%Docstring
|
||||||
|
Constructor of QgsLocatorModelBridge
|
||||||
|
%End
|
||||||
|
|
||||||
|
void performSearch( const QString &text );
|
||||||
|
%Docstring
|
||||||
|
Perform a search
|
||||||
|
%End
|
||||||
|
|
||||||
|
QgsLocator *locator() const;
|
||||||
|
%Docstring
|
||||||
|
Returns the locator
|
||||||
|
%End
|
||||||
|
|
||||||
|
QgsLocatorProxyModel *proxyModel() const;
|
||||||
|
%Docstring
|
||||||
|
Returns the proxy model
|
||||||
|
%End
|
||||||
|
|
||||||
|
bool hasQueueRequested() const;
|
||||||
|
%Docstring
|
||||||
|
Returns true if some text to be search is pending in the queue
|
||||||
|
%End
|
||||||
|
|
||||||
|
bool isRunning() const;
|
||||||
|
%Docstring
|
||||||
|
Returns true if the a search is currently running
|
||||||
|
%End
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void resultAdded();
|
||||||
|
%Docstring
|
||||||
|
Emitted when a result is added
|
||||||
|
%End
|
||||||
|
|
||||||
|
void isRunningChanged();
|
||||||
|
%Docstring
|
||||||
|
Emitted when the running status changes
|
||||||
|
%End
|
||||||
|
|
||||||
|
void resultsCleared();
|
||||||
|
%Docstring
|
||||||
|
Emitted when the results are cleared
|
||||||
|
%End
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void invalidateResults();
|
||||||
|
%Docstring
|
||||||
|
This will invalidate current search results
|
||||||
|
%End
|
||||||
|
|
||||||
|
void updateCanvasExtent( const QgsRectangle &extent );
|
||||||
|
%Docstring
|
||||||
|
Update the canvas extent used to create search context
|
||||||
|
%End
|
||||||
|
|
||||||
|
void updateCanvasCrs( const QgsCoordinateReferenceSystem &crs );
|
||||||
|
%Docstring
|
||||||
|
Update the canvas CRS used to create search context
|
||||||
|
%End
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/locator/qgslocatormodelbridge.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||||
|
************************************************************************/
|
@ -382,6 +382,7 @@
|
|||||||
%Include auto_generated/locator/qgslocator.sip
|
%Include auto_generated/locator/qgslocator.sip
|
||||||
%Include auto_generated/locator/qgslocatorfilter.sip
|
%Include auto_generated/locator/qgslocatorfilter.sip
|
||||||
%Include auto_generated/locator/qgslocatormodel.sip
|
%Include auto_generated/locator/qgslocatormodel.sip
|
||||||
|
%Include auto_generated/locator/qgslocatormodelbridge.sip
|
||||||
%Include auto_generated/processing/qgsprocessingalgrunnertask.sip
|
%Include auto_generated/processing/qgsprocessingalgrunnertask.sip
|
||||||
%Include auto_generated/processing/qgsprocessingfeedback.sip
|
%Include auto_generated/processing/qgsprocessingfeedback.sip
|
||||||
%Include auto_generated/processing/qgsprocessingprovider.sip
|
%Include auto_generated/processing/qgsprocessingprovider.sip
|
||||||
|
@ -64,7 +64,6 @@ Emitted when the configure option is triggered in the widget.
|
|||||||
%End
|
%End
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual bool eventFilter( QObject *obj, QEvent *event );
|
virtual bool eventFilter( QObject *obj, QEvent *event );
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,6 +109,7 @@ SET(QGIS_CORE_SRCS
|
|||||||
locator/qgslocator.cpp
|
locator/qgslocator.cpp
|
||||||
locator/qgslocatorfilter.cpp
|
locator/qgslocatorfilter.cpp
|
||||||
locator/qgslocatormodel.cpp
|
locator/qgslocatormodel.cpp
|
||||||
|
locator/qgslocatormodelbridge.cpp
|
||||||
|
|
||||||
processing/qgsprocessingalgorithm.cpp
|
processing/qgsprocessingalgorithm.cpp
|
||||||
processing/qgsprocessingalgrunnertask.cpp
|
processing/qgsprocessingalgrunnertask.cpp
|
||||||
@ -681,6 +682,7 @@ SET(QGIS_CORE_MOC_HDRS
|
|||||||
locator/qgslocator.h
|
locator/qgslocator.h
|
||||||
locator/qgslocatorfilter.h
|
locator/qgslocatorfilter.h
|
||||||
locator/qgslocatormodel.h
|
locator/qgslocatormodel.h
|
||||||
|
locator/qgslocatormodelbridge.h
|
||||||
|
|
||||||
processing/qgsprocessingalgrunnertask.h
|
processing/qgsprocessingalgrunnertask.h
|
||||||
processing/qgsprocessingfeedback.h
|
processing/qgsprocessingfeedback.h
|
||||||
|
@ -179,6 +179,19 @@ Qt::ItemFlags QgsLocatorModel::flags( const QModelIndex &index ) const
|
|||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> QgsLocatorModel::roleNames() const
|
||||||
|
{
|
||||||
|
QHash<int, QByteArray> roles;
|
||||||
|
roles[ResultDataRole] = "ResultData";
|
||||||
|
roles[ResultTypeRole] = "ResultType";
|
||||||
|
roles[ResultFilterPriorityRole] = "ResultFilterPriority";
|
||||||
|
roles[ResultScoreRole] = "ResultScore";
|
||||||
|
roles[ResultFilterNameRole] = "ResultFilterName";
|
||||||
|
roles[ResultFilterGroupSortingRole] = "ResultFilterGroupSorting";
|
||||||
|
roles[Qt::DisplayRole] = "Text";
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
void QgsLocatorModel::addResult( const QgsLocatorResult &result )
|
void QgsLocatorModel::addResult( const QgsLocatorResult &result )
|
||||||
{
|
{
|
||||||
mDeferredClearTimer.stop();
|
mDeferredClearTimer.stop();
|
||||||
|
@ -81,6 +81,7 @@ class CORE_EXPORT QgsLocatorModel : public QAbstractTableModel
|
|||||||
int columnCount( const QModelIndex &parent = QModelIndex() ) const override;
|
int columnCount( const QModelIndex &parent = QModelIndex() ) const override;
|
||||||
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override;
|
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override;
|
||||||
Qt::ItemFlags flags( const QModelIndex &index ) const override;
|
Qt::ItemFlags flags( const QModelIndex &index ) const override;
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
139
src/core/locator/qgslocatormodelbridge.cpp
Normal file
139
src/core/locator/qgslocatormodelbridge.cpp
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgslocatormodelbridge.cpp
|
||||||
|
------------------
|
||||||
|
begin : November 2018
|
||||||
|
copyright : (C) 2018 by Denis Rouzaud
|
||||||
|
email : denis@opengis.ch
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "qgslocatormodelbridge.h"
|
||||||
|
#include "qgslocator.h"
|
||||||
|
#include "qgslocatormodel.h"
|
||||||
|
|
||||||
|
|
||||||
|
QgsLocatorModelBridge::QgsLocatorModelBridge( QObject *parent )
|
||||||
|
: QObject( parent )
|
||||||
|
, mLocator( new QgsLocator( this ) )
|
||||||
|
, mLocatorModel( new QgsLocatorModel( this ) )
|
||||||
|
{
|
||||||
|
mProxyModel = new QgsLocatorProxyModel( mLocatorModel );
|
||||||
|
mProxyModel->setSourceModel( mLocatorModel );
|
||||||
|
|
||||||
|
connect( mLocator, &QgsLocator::foundResult, this, &QgsLocatorModelBridge::addResult );
|
||||||
|
connect( mLocator, &QgsLocator::finished, this, &QgsLocatorModelBridge::searchFinished );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsLocatorModelBridge::isRunning() const
|
||||||
|
{
|
||||||
|
return mIsRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsLocatorModelBridge::triggerResult( const QModelIndex &index )
|
||||||
|
{
|
||||||
|
mLocator->clearPreviousResults();
|
||||||
|
QgsLocatorResult result = mProxyModel->data( index, QgsLocatorModel::ResultDataRole ).value< QgsLocatorResult >();
|
||||||
|
if ( result.filter )
|
||||||
|
result.filter->triggerResult( result );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsLocatorModelBridge::setIsRunning( bool isRunning )
|
||||||
|
{
|
||||||
|
if ( mIsRunning == isRunning )
|
||||||
|
return;
|
||||||
|
|
||||||
|
mIsRunning = isRunning;
|
||||||
|
emit isRunningChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsLocatorModelBridge::invalidateResults()
|
||||||
|
{
|
||||||
|
mLocator->cancelWithoutBlocking();
|
||||||
|
mLocatorModel->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsLocatorModelBridge::updateCanvasExtent( const QgsRectangle &extent )
|
||||||
|
{
|
||||||
|
mCanvasExtent = extent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsLocatorModelBridge::updateCanvasCrs( const QgsCoordinateReferenceSystem &crs )
|
||||||
|
{
|
||||||
|
mCanvasCrs = crs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsLocatorModelBridge::addResult( const QgsLocatorResult &result )
|
||||||
|
{
|
||||||
|
mLocatorModel->addResult( result );
|
||||||
|
emit resultAdded();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QgsLocatorModelBridge::searchFinished()
|
||||||
|
{
|
||||||
|
if ( mHasQueuedRequest )
|
||||||
|
{
|
||||||
|
// a queued request was waiting for this - run the queued search now
|
||||||
|
QString nextSearch = mNextRequestedString;
|
||||||
|
mNextRequestedString.clear();
|
||||||
|
mHasQueuedRequest = false;
|
||||||
|
performSearch( nextSearch );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( !mLocator->isRunning() )
|
||||||
|
setIsRunning( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsLocatorModelBridge::performSearch( const QString &text )
|
||||||
|
{
|
||||||
|
setIsRunning( true );
|
||||||
|
if ( mLocator->isRunning() )
|
||||||
|
{
|
||||||
|
// can't do anything while a query is running, and can't block
|
||||||
|
// here waiting for the current query to cancel
|
||||||
|
// so we queue up this string until cancel has happened
|
||||||
|
mLocator->cancelWithoutBlocking();
|
||||||
|
mNextRequestedString = text;
|
||||||
|
mHasQueuedRequest = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emit resultsCleared();
|
||||||
|
mLocatorModel->deferredClear();
|
||||||
|
mLocator->fetchResults( text, createContext() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsLocator *QgsLocatorModelBridge::locator() const
|
||||||
|
{
|
||||||
|
return mLocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsLocatorProxyModel *QgsLocatorModelBridge::proxyModel() const
|
||||||
|
{
|
||||||
|
return mProxyModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsLocatorModelBridge::hasQueueRequested() const
|
||||||
|
{
|
||||||
|
return mHasQueuedRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsLocatorContext QgsLocatorModelBridge::createContext()
|
||||||
|
{
|
||||||
|
QgsLocatorContext context;
|
||||||
|
context.targetExtent = mCanvasExtent;
|
||||||
|
context.targetExtentCrs = mCanvasCrs;
|
||||||
|
return context;
|
||||||
|
}
|
111
src/core/locator/qgslocatormodelbridge.h
Normal file
111
src/core/locator/qgslocatormodelbridge.h
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgslocatormodelbridge.h
|
||||||
|
------------------
|
||||||
|
begin : November 2018
|
||||||
|
copyright : (C) 2018 by Denis Rouzaud
|
||||||
|
email : denis@opengis.ch
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QGSLOCATORMODELBRIDGE_H
|
||||||
|
#define QGSLOCATORMODELBRIDGE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "qgis_core.h"
|
||||||
|
#include "qgscoordinatereferencesystem.h"
|
||||||
|
#include "qgsrectangle.h"
|
||||||
|
|
||||||
|
class QgsLocatorResult;
|
||||||
|
class QgsLocator;
|
||||||
|
class QgsLocatorContext;
|
||||||
|
class QgsLocatorModel;
|
||||||
|
class QgsLocatorProxyModel;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \ingroup core
|
||||||
|
* The QgsLocatorModelBridge class provides the core functionality
|
||||||
|
* to be used in a locator widget.
|
||||||
|
* \since QGIS 3.6
|
||||||
|
*/
|
||||||
|
class CORE_EXPORT QgsLocatorModelBridge : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY( bool isRunning READ isRunning NOTIFY isRunningChanged )
|
||||||
|
public:
|
||||||
|
//! Constructor of QgsLocatorModelBridge
|
||||||
|
explicit QgsLocatorModelBridge( QObject *parent = nullptr );
|
||||||
|
virtual ~QgsLocatorModelBridge() = default;
|
||||||
|
|
||||||
|
//! Perform a search
|
||||||
|
Q_INVOKABLE void performSearch( const QString &text );
|
||||||
|
|
||||||
|
//! Returns the locator
|
||||||
|
QgsLocator *locator() const;
|
||||||
|
|
||||||
|
//! Returns the proxy model
|
||||||
|
Q_INVOKABLE QgsLocatorProxyModel *proxyModel() const;
|
||||||
|
|
||||||
|
//! Returns true if some text to be search is pending in the queue
|
||||||
|
bool hasQueueRequested() const;
|
||||||
|
|
||||||
|
//! Returns true if the a search is currently running
|
||||||
|
bool isRunning() const;
|
||||||
|
|
||||||
|
//! Triggers the result at given index
|
||||||
|
void triggerResult( const QModelIndex &index );
|
||||||
|
|
||||||
|
signals:
|
||||||
|
//! Emitted when a result is added
|
||||||
|
void resultAdded();
|
||||||
|
|
||||||
|
//! Emitted when the running status changes
|
||||||
|
void isRunningChanged();
|
||||||
|
|
||||||
|
//! Emitted when the results are cleared
|
||||||
|
void resultsCleared();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
//! This will invalidate current search results
|
||||||
|
void invalidateResults();
|
||||||
|
|
||||||
|
//! Update the canvas extent used to create search context
|
||||||
|
void updateCanvasExtent( const QgsRectangle &extent );
|
||||||
|
|
||||||
|
//! Update the canvas CRS used to create search context
|
||||||
|
void updateCanvasCrs( const QgsCoordinateReferenceSystem &crs );
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void searchFinished();
|
||||||
|
void addResult( const QgsLocatorResult &result );
|
||||||
|
|
||||||
|
private:
|
||||||
|
QgsLocatorContext createContext();
|
||||||
|
void setIsRunning( bool isRunning );
|
||||||
|
|
||||||
|
QgsLocator *mLocator = nullptr;
|
||||||
|
QgsLocatorModel *mLocatorModel = nullptr;
|
||||||
|
QgsLocatorProxyModel *mProxyModel = nullptr;
|
||||||
|
|
||||||
|
QString mNextRequestedString;
|
||||||
|
bool mHasQueuedRequest = false;
|
||||||
|
bool mIsRunning = false;
|
||||||
|
|
||||||
|
// keep track of map canvas extent and CRS
|
||||||
|
// if much if needed, it would be possible to add
|
||||||
|
// a QgsMapCanvasController in core to achieve this
|
||||||
|
// see discussion in https://github.com/qgis/QGIS/pull/8404
|
||||||
|
QgsRectangle mCanvasExtent;
|
||||||
|
QgsCoordinateReferenceSystem mCanvasCrs;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QGSLOCATORMODELBRIDGE_H
|
@ -15,10 +15,10 @@
|
|||||||
* *
|
* *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#include "qgslocatorwidget.h"
|
|
||||||
#include "qgslocator.h"
|
#include "qgslocator.h"
|
||||||
#include "qgslocatormodel.h"
|
#include "qgslocatormodel.h"
|
||||||
|
#include "qgslocatorwidget.h"
|
||||||
|
#include "qgslocatormodelbridge.h"
|
||||||
#include "qgsfilterlineedit.h"
|
#include "qgsfilterlineedit.h"
|
||||||
#include "qgsmapcanvas.h"
|
#include "qgsmapcanvas.h"
|
||||||
#include "qgsapplication.h"
|
#include "qgsapplication.h"
|
||||||
@ -29,9 +29,8 @@
|
|||||||
|
|
||||||
QgsLocatorWidget::QgsLocatorWidget( QWidget *parent )
|
QgsLocatorWidget::QgsLocatorWidget( QWidget *parent )
|
||||||
: QWidget( parent )
|
: QWidget( parent )
|
||||||
, mLocator( new QgsLocator( this ) )
|
, mModelBridge( new QgsLocatorModelBridge( this ) )
|
||||||
, mLineEdit( new QgsFilterLineEdit() )
|
, mLineEdit( new QgsFilterLineEdit() )
|
||||||
, mLocatorModel( new QgsLocatorModel( this ) )
|
|
||||||
, mResultsView( new QgsLocatorResultsView() )
|
, mResultsView( new QgsLocatorResultsView() )
|
||||||
{
|
{
|
||||||
mLineEdit->setShowClearButton( true );
|
mLineEdit->setShowClearButton( true );
|
||||||
@ -71,17 +70,16 @@ QgsLocatorWidget::QgsLocatorWidget( QWidget *parent )
|
|||||||
mResultsContainer->setLayout( containerLayout );
|
mResultsContainer->setLayout( containerLayout );
|
||||||
mResultsContainer->hide();
|
mResultsContainer->hide();
|
||||||
|
|
||||||
mProxyModel = new QgsLocatorProxyModel( mLocatorModel );
|
mResultsView->setModel( mModelBridge->proxyModel() );
|
||||||
mProxyModel->setSourceModel( mLocatorModel );
|
|
||||||
mResultsView->setModel( mProxyModel );
|
|
||||||
mResultsView->setUniformRowHeights( true );
|
mResultsView->setUniformRowHeights( true );
|
||||||
mResultsView->setIconSize( QSize( 16, 16 ) );
|
mResultsView->setIconSize( QSize( 16, 16 ) );
|
||||||
mResultsView->recalculateSize();
|
mResultsView->recalculateSize();
|
||||||
|
|
||||||
connect( mLocator, &QgsLocator::foundResult, this, &QgsLocatorWidget::addResult );
|
|
||||||
connect( mLocator, &QgsLocator::finished, this, &QgsLocatorWidget::searchFinished );
|
|
||||||
connect( mLineEdit, &QLineEdit::textChanged, this, &QgsLocatorWidget::scheduleDelayedPopup );
|
connect( mLineEdit, &QLineEdit::textChanged, this, &QgsLocatorWidget::scheduleDelayedPopup );
|
||||||
connect( mResultsView, &QAbstractItemView::activated, this, &QgsLocatorWidget::acceptCurrentEntry );
|
connect( mResultsView, &QAbstractItemView::activated, this, &QgsLocatorWidget::acceptCurrentEntry );
|
||||||
|
connect( mModelBridge, &QgsLocatorModelBridge::resultAdded, this, &QgsLocatorWidget::resultAdded );
|
||||||
|
connect( mModelBridge, &QgsLocatorModelBridge::isRunningChanged, this, [ = ]() {mLineEdit->setShowSpinner( mModelBridge->isRunning() );} );
|
||||||
|
connect( mModelBridge, & QgsLocatorModelBridge::resultsCleared, this, [ = ]() {mHasSelectedResult = false;} );
|
||||||
|
|
||||||
// have a tiny delay between typing text in line edit and showing the window
|
// have a tiny delay between typing text in line edit and showing the window
|
||||||
mPopupTimer.setInterval( 100 );
|
mPopupTimer.setInterval( 100 );
|
||||||
@ -97,7 +95,7 @@ QgsLocatorWidget::QgsLocatorWidget( QWidget *parent )
|
|||||||
installEventFilter( this );
|
installEventFilter( this );
|
||||||
window()->installEventFilter( this );
|
window()->installEventFilter( this );
|
||||||
|
|
||||||
mLocator->registerFilter( new QgsLocatorFilterFilter( this, this ) );
|
mModelBridge->locator()->registerFilter( new QgsLocatorFilterFilter( this, this ) );
|
||||||
|
|
||||||
mMenu = new QMenu( this );
|
mMenu = new QMenu( this );
|
||||||
QAction *menuAction = mLineEdit->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/search.svg" ) ), QLineEdit::LeadingPosition );
|
QAction *menuAction = mLineEdit->addAction( QgsApplication::getThemeIcon( QStringLiteral( "/search.svg" ) ), QLineEdit::LeadingPosition );
|
||||||
@ -113,12 +111,29 @@ QgsLocatorWidget::QgsLocatorWidget( QWidget *parent )
|
|||||||
|
|
||||||
QgsLocator *QgsLocatorWidget::locator()
|
QgsLocator *QgsLocatorWidget::locator()
|
||||||
{
|
{
|
||||||
return mLocator;
|
return mModelBridge->locator();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsLocatorWidget::setMapCanvas( QgsMapCanvas *canvas )
|
void QgsLocatorWidget::setMapCanvas( QgsMapCanvas *canvas )
|
||||||
{
|
{
|
||||||
|
if ( mMapCanvas == canvas )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for ( const QMetaObject::Connection &conn : qgis::as_const( mCanvasConnections ) )
|
||||||
|
{
|
||||||
|
disconnect( conn );
|
||||||
|
}
|
||||||
|
mCanvasConnections.clear();
|
||||||
|
|
||||||
mMapCanvas = canvas;
|
mMapCanvas = canvas;
|
||||||
|
if ( mMapCanvas )
|
||||||
|
{
|
||||||
|
mModelBridge->updateCanvasExtent( mMapCanvas->mapSettings().visibleExtent() );
|
||||||
|
mModelBridge->updateCanvasCrs( mMapCanvas->mapSettings().destinationCrs() );
|
||||||
|
mCanvasConnections
|
||||||
|
<< connect( mMapCanvas, &QgsMapCanvas::extentsChanged, this, [ = ]() {mModelBridge->updateCanvasExtent( mMapCanvas->mapSettings().visibleExtent() );} )
|
||||||
|
<< connect( mMapCanvas, &QgsMapCanvas::destinationCrsChanged, this, [ = ]() {mModelBridge->updateCanvasCrs( mMapCanvas->mapSettings().destinationCrs() );} ) ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsLocatorWidget::search( const QString &string )
|
void QgsLocatorWidget::search( const QString &string )
|
||||||
@ -131,8 +146,7 @@ void QgsLocatorWidget::search( const QString &string )
|
|||||||
|
|
||||||
void QgsLocatorWidget::invalidateResults()
|
void QgsLocatorWidget::invalidateResults()
|
||||||
{
|
{
|
||||||
mLocator->cancelWithoutBlocking();
|
mModelBridge->invalidateResults();
|
||||||
mLocatorModel->clear();
|
|
||||||
mResultsContainer->hide();
|
mResultsContainer->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,10 +155,27 @@ void QgsLocatorWidget::scheduleDelayedPopup()
|
|||||||
mPopupTimer.start();
|
mPopupTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsLocatorWidget::resultAdded()
|
||||||
|
{
|
||||||
|
bool selectFirst = !mHasSelectedResult || mModelBridge->proxyModel()->rowCount() == 0;
|
||||||
|
if ( selectFirst )
|
||||||
|
{
|
||||||
|
int row = -1;
|
||||||
|
bool selectable = false;
|
||||||
|
while ( !selectable && row < mModelBridge->proxyModel()->rowCount() )
|
||||||
|
{
|
||||||
|
row++;
|
||||||
|
selectable = mModelBridge->proxyModel()->flags( mModelBridge->proxyModel()->index( row, 0 ) ).testFlag( Qt::ItemIsSelectable );
|
||||||
|
}
|
||||||
|
if ( selectable )
|
||||||
|
mResultsView->setCurrentIndex( mModelBridge->proxyModel()->index( row, 0 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QgsLocatorWidget::performSearch()
|
void QgsLocatorWidget::performSearch()
|
||||||
{
|
{
|
||||||
mPopupTimer.stop();
|
mPopupTimer.stop();
|
||||||
updateResults( mLineEdit->text() );
|
mModelBridge->performSearch( mLineEdit->text() );
|
||||||
showList();
|
showList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,29 +187,12 @@ void QgsLocatorWidget::showList()
|
|||||||
|
|
||||||
void QgsLocatorWidget::triggerSearchAndShowList()
|
void QgsLocatorWidget::triggerSearchAndShowList()
|
||||||
{
|
{
|
||||||
if ( mProxyModel->rowCount() == 0 )
|
if ( mModelBridge->proxyModel()->rowCount() == 0 )
|
||||||
performSearch();
|
performSearch();
|
||||||
else
|
else
|
||||||
showList();
|
showList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsLocatorWidget::searchFinished()
|
|
||||||
{
|
|
||||||
if ( mHasQueuedRequest )
|
|
||||||
{
|
|
||||||
// a queued request was waiting for this - run the queued search now
|
|
||||||
QString nextSearch = mNextRequestedString;
|
|
||||||
mNextRequestedString.clear();
|
|
||||||
mHasQueuedRequest = false;
|
|
||||||
updateResults( nextSearch );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( !mLocator->isRunning() )
|
|
||||||
mLineEdit->setShowSpinner( false );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QgsLocatorWidget::eventFilter( QObject *obj, QEvent *event )
|
bool QgsLocatorWidget::eventFilter( QObject *obj, QEvent *event )
|
||||||
{
|
{
|
||||||
if ( obj == mLineEdit && event->type() == QEvent::KeyPress )
|
if ( obj == mLineEdit && event->type() == QEvent::KeyPress )
|
||||||
@ -246,28 +260,10 @@ bool QgsLocatorWidget::eventFilter( QObject *obj, QEvent *event )
|
|||||||
return QWidget::eventFilter( obj, event );
|
return QWidget::eventFilter( obj, event );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsLocatorWidget::addResult( const QgsLocatorResult &result )
|
|
||||||
{
|
|
||||||
bool selectFirst = !mHasSelectedResult || mProxyModel->rowCount() == 0;
|
|
||||||
mLocatorModel->addResult( result );
|
|
||||||
if ( selectFirst )
|
|
||||||
{
|
|
||||||
int row = -1;
|
|
||||||
bool selectable = false;
|
|
||||||
while ( !selectable && row < mProxyModel->rowCount() )
|
|
||||||
{
|
|
||||||
row++;
|
|
||||||
selectable = mProxyModel->flags( mProxyModel->index( row, 0 ) ).testFlag( Qt::ItemIsSelectable );
|
|
||||||
}
|
|
||||||
if ( selectable )
|
|
||||||
mResultsView->setCurrentIndex( mProxyModel->index( row, 0 ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsLocatorWidget::configMenuAboutToShow()
|
void QgsLocatorWidget::configMenuAboutToShow()
|
||||||
{
|
{
|
||||||
mMenu->clear();
|
mMenu->clear();
|
||||||
for ( QgsLocatorFilter *filter : mLocator->filters() )
|
for ( QgsLocatorFilter *filter : mModelBridge->locator()->filters() )
|
||||||
{
|
{
|
||||||
if ( !filter->enabled() )
|
if ( !filter->enabled() )
|
||||||
continue;
|
continue;
|
||||||
@ -281,7 +277,7 @@ void QgsLocatorWidget::configMenuAboutToShow()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
QStringList parts = currentText.split( ' ' );
|
QStringList parts = currentText.split( ' ' );
|
||||||
if ( parts.count() > 1 && mLocator->filters( parts.at( 0 ) ).count() > 0 )
|
if ( parts.count() > 1 && mModelBridge->locator()->filters( parts.at( 0 ) ).count() > 0 )
|
||||||
{
|
{
|
||||||
parts.pop_front();
|
parts.pop_front();
|
||||||
currentText = parts.join( ' ' );
|
currentText = parts.join( ' ' );
|
||||||
@ -297,33 +293,13 @@ void QgsLocatorWidget::configMenuAboutToShow()
|
|||||||
QAction *configAction = new QAction( tr( "Configure…" ), mMenu );
|
QAction *configAction = new QAction( tr( "Configure…" ), mMenu );
|
||||||
connect( configAction, &QAction::triggered, this, &QgsLocatorWidget::configTriggered );
|
connect( configAction, &QAction::triggered, this, &QgsLocatorWidget::configTriggered );
|
||||||
mMenu->addAction( configAction );
|
mMenu->addAction( configAction );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsLocatorWidget::updateResults( const QString &text )
|
|
||||||
{
|
|
||||||
mLineEdit->setShowSpinner( true );
|
|
||||||
if ( mLocator->isRunning() )
|
|
||||||
{
|
|
||||||
// can't do anything while a query is running, and can't block
|
|
||||||
// here waiting for the current query to cancel
|
|
||||||
// so we queue up this string until cancel has happened
|
|
||||||
mLocator->cancelWithoutBlocking();
|
|
||||||
mNextRequestedString = text;
|
|
||||||
mHasQueuedRequest = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mHasSelectedResult = false;
|
|
||||||
mLocatorModel->deferredClear();
|
|
||||||
mLocator->fetchResults( text, createContext() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsLocatorWidget::acceptCurrentEntry()
|
void QgsLocatorWidget::acceptCurrentEntry()
|
||||||
{
|
{
|
||||||
if ( mHasQueuedRequest )
|
if ( mModelBridge->hasQueueRequested() )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -336,24 +312,13 @@ void QgsLocatorWidget::acceptCurrentEntry()
|
|||||||
if ( !index.isValid() )
|
if ( !index.isValid() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QgsLocatorResult result = mProxyModel->data( index, QgsLocatorModel::ResultDataRole ).value< QgsLocatorResult >();
|
|
||||||
mResultsContainer->hide();
|
mResultsContainer->hide();
|
||||||
mLineEdit->clearFocus();
|
mLineEdit->clearFocus();
|
||||||
mLocator->clearPreviousResults();
|
mModelBridge->triggerResult( index );
|
||||||
result.filter->triggerResult( result );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsLocatorContext QgsLocatorWidget::createContext()
|
|
||||||
{
|
|
||||||
QgsLocatorContext context;
|
|
||||||
if ( mMapCanvas )
|
|
||||||
{
|
|
||||||
context.targetExtent = mMapCanvas->mapSettings().visibleExtent();
|
|
||||||
context.targetExtentCrs = mMapCanvas->mapSettings().destinationCrs();
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
///@cond PRIVATE
|
///@cond PRIVATE
|
||||||
|
|
||||||
|
@ -29,10 +29,9 @@
|
|||||||
|
|
||||||
class QgsLocator;
|
class QgsLocator;
|
||||||
class QgsFilterLineEdit;
|
class QgsFilterLineEdit;
|
||||||
class QgsLocatorModel;
|
|
||||||
class QgsLocatorResultsView;
|
class QgsLocatorResultsView;
|
||||||
class QgsMapCanvas;
|
class QgsMapCanvas;
|
||||||
class QgsLocatorProxyModel;
|
class QgsLocatorModelBridge;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \class QgsLocatorWidget
|
* \class QgsLocatorWidget
|
||||||
@ -86,40 +85,30 @@ class GUI_EXPORT QgsLocatorWidget : public QWidget
|
|||||||
void configTriggered();
|
void configTriggered();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
bool eventFilter( QObject *obj, QEvent *event ) override;
|
bool eventFilter( QObject *obj, QEvent *event ) override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void scheduleDelayedPopup();
|
|
||||||
void performSearch();
|
void performSearch();
|
||||||
void showList();
|
void showList();
|
||||||
void triggerSearchAndShowList();
|
void triggerSearchAndShowList();
|
||||||
void searchFinished();
|
|
||||||
void addResult( const QgsLocatorResult &result );
|
|
||||||
void configMenuAboutToShow();
|
void configMenuAboutToShow();
|
||||||
|
void scheduleDelayedPopup();
|
||||||
|
void resultAdded();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QgsLocatorModelBridge *mModelBridge = nullptr;
|
||||||
QgsLocator *mLocator = nullptr;
|
|
||||||
QgsFilterLineEdit *mLineEdit = nullptr;
|
QgsFilterLineEdit *mLineEdit = nullptr;
|
||||||
QgsLocatorModel *mLocatorModel = nullptr;
|
|
||||||
QgsLocatorProxyModel *mProxyModel = nullptr;
|
|
||||||
QgsFloatingWidget *mResultsContainer = nullptr;
|
QgsFloatingWidget *mResultsContainer = nullptr;
|
||||||
QgsLocatorResultsView *mResultsView = nullptr;
|
QgsLocatorResultsView *mResultsView = nullptr;
|
||||||
QgsMapCanvas *mMapCanvas = nullptr;
|
QgsMapCanvas *mMapCanvas = nullptr;
|
||||||
|
QList<QMetaObject::Connection> mCanvasConnections;
|
||||||
QMenu *mMenu = nullptr;
|
QMenu *mMenu = nullptr;
|
||||||
|
|
||||||
QString mNextRequestedString;
|
|
||||||
bool mHasQueuedRequest = false;
|
|
||||||
bool mHasSelectedResult = false;
|
|
||||||
QTimer mPopupTimer;
|
|
||||||
QTimer mFocusTimer;
|
QTimer mFocusTimer;
|
||||||
|
QTimer mPopupTimer;
|
||||||
|
bool mHasSelectedResult = false;
|
||||||
|
|
||||||
void updateResults( const QString &text );
|
|
||||||
void acceptCurrentEntry();
|
void acceptCurrentEntry();
|
||||||
QgsLocatorContext createContext();
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef SIP_RUN
|
#ifndef SIP_RUN
|
||||||
@ -144,7 +133,6 @@ class QgsLocatorFilterFilter : public QgsLocatorFilter
|
|||||||
void triggerResult( const QgsLocatorResult &result ) override;
|
void triggerResult( const QgsLocatorResult &result ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QgsLocatorWidget *mLocator = nullptr;
|
QgsLocatorWidget *mLocator = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user