mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Add a QgsLocatorModel subclass which automatically sets up
required connections to a QgsLocator Use this QgsLocatorModel subclass when you want the connections between a QgsLocator and the model to be automatically created for you. If more flexibility in model behavior is required, use the base QgsLocatorModel class instead and setup the connections manually.
This commit is contained in:
parent
a8e1d335bb
commit
26830949d9
@ -14,6 +14,10 @@ class QgsLocatorModel : QAbstractTableModel
|
||||
{
|
||||
%Docstring
|
||||
An abstract list model for displaying the results of locator searches.
|
||||
|
||||
Note that this class should generally be used with a QgsLocatorProxyModel
|
||||
in order to ensure correct sorting of results by priority and match level.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
@ -31,7 +35,7 @@ class QgsLocatorModel : QAbstractTableModel
|
||||
ResultFilterNameRole,
|
||||
};
|
||||
|
||||
QgsLocatorModel( QObject *parent = 0 );
|
||||
QgsLocatorModel( QObject *parent /TransferThis/ = 0 );
|
||||
%Docstring
|
||||
Constructor for QgsLocatorModel.
|
||||
%End
|
||||
@ -68,6 +72,64 @@ class QgsLocatorModel : QAbstractTableModel
|
||||
|
||||
};
|
||||
|
||||
class QgsLocatorAutomaticModel : QgsLocatorModel
|
||||
{
|
||||
%Docstring
|
||||
A QgsLocatorModel which has is associated directly with a
|
||||
QgsLocator, and is automatically populated with results
|
||||
from locator searches.
|
||||
|
||||
Use this QgsLocatorModel subclass when you want the connections
|
||||
between a QgsLocator and the model to be automatically created
|
||||
for you. If more flexibility in model behavior is required,
|
||||
use the base QgsLocatorModel class instead and setup the
|
||||
connections manually.
|
||||
|
||||
Note that this class should generally be used with a QgsLocatorProxyModel
|
||||
in order to ensure correct sorting of results by priority and match level.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgslocatormodel.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
explicit QgsLocatorAutomaticModel( QgsLocator *locator /TransferThis/ );
|
||||
%Docstring
|
||||
Constructor for QgsLocatorAutomaticModel, linked with the specified ``locator``.
|
||||
|
||||
The ``locator`` is used as the model's parent.
|
||||
%End
|
||||
|
||||
QgsLocator *locator();
|
||||
%Docstring
|
||||
Returns a pointer to the locator utilized by this model.
|
||||
:rtype: QgsLocator
|
||||
%End
|
||||
|
||||
void search( const QString &string );
|
||||
%Docstring
|
||||
Enqueues a search for a specified ``string`` within the model.
|
||||
|
||||
Note that the search may not begin immediately if an existing search request
|
||||
is still running. In this case the existing search must be completely
|
||||
terminated before the new search can begin. The model handles this
|
||||
situation automatically, and will trigger a search for the new
|
||||
search string as soon as possible.
|
||||
%End
|
||||
|
||||
virtual QgsLocatorContext createContext();
|
||||
%Docstring
|
||||
Returns a new locator context for searches. The default implementation
|
||||
returns a default constructed QgsLocatorContext. Subclasses can override
|
||||
this method to implement custom context creation logic.
|
||||
:rtype: QgsLocatorContext
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
class QgsLocatorProxyModel : QSortFilterProxyModel
|
||||
{
|
||||
%Docstring
|
||||
@ -81,7 +143,10 @@ class QgsLocatorProxyModel : QSortFilterProxyModel
|
||||
%End
|
||||
public:
|
||||
|
||||
explicit QgsLocatorProxyModel( QObject *parent = 0 );
|
||||
explicit QgsLocatorProxyModel( QObject *parent /TransferThis/ = 0 );
|
||||
%Docstring
|
||||
Constructor for QgsLocatorProxyModel, with the specified ``parent`` object.
|
||||
%End
|
||||
virtual bool lessThan( const QModelIndex &left, const QModelIndex &right ) const;
|
||||
|
||||
};
|
||||
|
@ -193,6 +193,65 @@ void QgsLocatorModel::addResult( const QgsLocatorResult &result )
|
||||
mDeferredClear = false;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// QgsLocatorAutomaticModel
|
||||
//
|
||||
|
||||
QgsLocatorAutomaticModel::QgsLocatorAutomaticModel( QgsLocator *locator )
|
||||
: QgsLocatorModel( locator )
|
||||
, mLocator( locator )
|
||||
{
|
||||
Q_ASSERT( mLocator );
|
||||
connect( mLocator, &QgsLocator::foundResult, this, &QgsLocatorAutomaticModel::addResult );
|
||||
connect( mLocator, &QgsLocator::finished, this, &QgsLocatorAutomaticModel::searchFinished );
|
||||
}
|
||||
|
||||
QgsLocator *QgsLocatorAutomaticModel::locator()
|
||||
{
|
||||
return mLocator;
|
||||
}
|
||||
|
||||
void QgsLocatorAutomaticModel::search( const QString &string )
|
||||
{
|
||||
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 = string;
|
||||
mHasQueuedRequest = true;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
deferredClear();
|
||||
mLocator->fetchResults( string, createContext() );
|
||||
}
|
||||
}
|
||||
|
||||
QgsLocatorContext QgsLocatorAutomaticModel::createContext()
|
||||
{
|
||||
return QgsLocatorContext();
|
||||
}
|
||||
|
||||
void QgsLocatorAutomaticModel::searchFinished()
|
||||
{
|
||||
if ( mHasQueuedRequest )
|
||||
{
|
||||
// a queued request was waiting for this - run the queued search now
|
||||
QString nextSearch = mNextRequestedString;
|
||||
mNextRequestedString.clear();
|
||||
mHasQueuedRequest = false;
|
||||
search( nextSearch );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// QgsLocatorProxyModel
|
||||
//
|
||||
@ -238,3 +297,4 @@ bool QgsLocatorProxyModel::lessThan( const QModelIndex &left, const QModelIndex
|
||||
return QString::localeAwareCompare( leftFilter, rightFilter ) < 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -33,6 +33,10 @@ class QgsLocatorProxyModel;
|
||||
* \class QgsLocatorModel
|
||||
* \ingroup core
|
||||
* An abstract list model for displaying the results of locator searches.
|
||||
*
|
||||
* Note that this class should generally be used with a QgsLocatorProxyModel
|
||||
* in order to ensure correct sorting of results by priority and match level.
|
||||
*
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
class CORE_EXPORT QgsLocatorModel : public QAbstractTableModel
|
||||
@ -54,7 +58,7 @@ class CORE_EXPORT QgsLocatorModel : public QAbstractTableModel
|
||||
/**
|
||||
* Constructor for QgsLocatorModel.
|
||||
*/
|
||||
QgsLocatorModel( QObject *parent = nullptr );
|
||||
QgsLocatorModel( QObject *parent SIP_TRANSFERTHIS = nullptr );
|
||||
|
||||
/**
|
||||
* Resets the model and clears all existing results.
|
||||
@ -103,6 +107,72 @@ class CORE_EXPORT QgsLocatorModel : public QAbstractTableModel
|
||||
QTimer mDeferredClearTimer;
|
||||
};
|
||||
|
||||
/**
|
||||
* \class QgsLocatorAutomaticModel
|
||||
* \ingroup core
|
||||
* A QgsLocatorModel which has is associated directly with a
|
||||
* QgsLocator, and is automatically populated with results
|
||||
* from locator searches.
|
||||
*
|
||||
* Use this QgsLocatorModel subclass when you want the connections
|
||||
* between a QgsLocator and the model to be automatically created
|
||||
* for you. If more flexibility in model behavior is required,
|
||||
* use the base QgsLocatorModel class instead and setup the
|
||||
* connections manually.
|
||||
*
|
||||
* Note that this class should generally be used with a QgsLocatorProxyModel
|
||||
* in order to ensure correct sorting of results by priority and match level.
|
||||
*
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
class CORE_EXPORT QgsLocatorAutomaticModel : public QgsLocatorModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor for QgsLocatorAutomaticModel, linked with the specified \a locator.
|
||||
*
|
||||
* The \a locator is used as the model's parent.
|
||||
*/
|
||||
explicit QgsLocatorAutomaticModel( QgsLocator *locator SIP_TRANSFERTHIS );
|
||||
|
||||
/**
|
||||
* Returns a pointer to the locator utilized by this model.
|
||||
*/
|
||||
QgsLocator *locator();
|
||||
|
||||
/**
|
||||
* Enqueues a search for a specified \a string within the model.
|
||||
*
|
||||
* Note that the search may not begin immediately if an existing search request
|
||||
* is still running. In this case the existing search must be completely
|
||||
* terminated before the new search can begin. The model handles this
|
||||
* situation automatically, and will trigger a search for the new
|
||||
* search string as soon as possible.
|
||||
*/
|
||||
void search( const QString &string );
|
||||
|
||||
/**
|
||||
* Returns a new locator context for searches. The default implementation
|
||||
* returns a default constructed QgsLocatorContext. Subclasses can override
|
||||
* this method to implement custom context creation logic.
|
||||
*/
|
||||
virtual QgsLocatorContext createContext();
|
||||
|
||||
private slots:
|
||||
|
||||
void searchFinished();
|
||||
|
||||
private:
|
||||
|
||||
QgsLocator *mLocator = nullptr;
|
||||
|
||||
QString mNextRequestedString;
|
||||
bool mHasQueuedRequest = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* \class QgsLocatorProxyModel
|
||||
* \ingroup core
|
||||
@ -116,7 +186,10 @@ class CORE_EXPORT QgsLocatorProxyModel : public QSortFilterProxyModel
|
||||
|
||||
public:
|
||||
|
||||
explicit QgsLocatorProxyModel( QObject *parent = nullptr );
|
||||
/**
|
||||
* Constructor for QgsLocatorProxyModel, with the specified \a parent object.
|
||||
*/
|
||||
explicit QgsLocatorProxyModel( QObject *parent SIP_TRANSFERTHIS = nullptr );
|
||||
bool lessThan( const QModelIndex &left, const QModelIndex &right ) const override;
|
||||
};
|
||||
|
||||
|
@ -19,7 +19,8 @@ from qgis.core import (QgsLocator,
|
||||
QgsLocatorFilter,
|
||||
QgsLocatorContext,
|
||||
QgsLocatorResult,
|
||||
QgsLocatorModel)
|
||||
QgsLocatorModel,
|
||||
QgsLocatorAutomaticModel)
|
||||
from qgis.PyQt.QtCore import QVariant, pyqtSignal, QCoreApplication
|
||||
from time import sleep
|
||||
from qgis.testing import start_app, unittest
|
||||
@ -210,6 +211,51 @@ class TestQgsLocator(unittest.TestCase):
|
||||
QCoreApplication.processEvents()
|
||||
self.assertEqual(m.rowCount(), 0)
|
||||
|
||||
def testAutoModel(self):
|
||||
"""
|
||||
Test automatic model, QgsLocatorAutomaticModel - should be no need
|
||||
for any manual connections
|
||||
"""
|
||||
l = QgsLocator()
|
||||
m = QgsLocatorAutomaticModel(l)
|
||||
|
||||
filter_a = test_filter('a')
|
||||
l.registerFilter(filter_a)
|
||||
|
||||
m.search('a')
|
||||
|
||||
for i in range(100):
|
||||
sleep(0.002)
|
||||
QCoreApplication.processEvents()
|
||||
|
||||
# 4 results - one is locator name
|
||||
self.assertEqual(m.rowCount(), 4)
|
||||
self.assertEqual(m.data(m.index(0, 0)), 'test')
|
||||
self.assertEqual(m.data(m.index(0, 0), QgsLocatorModel.ResultTypeRole), 0)
|
||||
self.assertEqual(m.data(m.index(0, 0), QgsLocatorModel.ResultFilterNameRole), 'test')
|
||||
self.assertEqual(m.data(m.index(1, 0)), 'a0')
|
||||
self.assertEqual(m.data(m.index(1, 0), QgsLocatorModel.ResultTypeRole), 1)
|
||||
self.assertEqual(m.data(m.index(1, 0), QgsLocatorModel.ResultFilterNameRole), 'test')
|
||||
self.assertEqual(m.data(m.index(2, 0)), 'a1')
|
||||
self.assertEqual(m.data(m.index(2, 0), QgsLocatorModel.ResultTypeRole), 1)
|
||||
self.assertEqual(m.data(m.index(2, 0), QgsLocatorModel.ResultFilterNameRole), 'test')
|
||||
self.assertEqual(m.data(m.index(3, 0)), 'a2')
|
||||
self.assertEqual(m.data(m.index(3, 0), QgsLocatorModel.ResultTypeRole), 1)
|
||||
self.assertEqual(m.data(m.index(3, 0), QgsLocatorModel.ResultFilterNameRole), 'test')
|
||||
|
||||
m.search('a')
|
||||
|
||||
for i in range(100):
|
||||
sleep(0.002)
|
||||
QCoreApplication.processEvents()
|
||||
|
||||
# 4 results - one is locator name
|
||||
self.assertEqual(m.rowCount(), 4)
|
||||
self.assertEqual(m.data(m.index(0, 0)), 'test')
|
||||
self.assertEqual(m.data(m.index(1, 0)), 'a0')
|
||||
self.assertEqual(m.data(m.index(2, 0)), 'a1')
|
||||
self.assertEqual(m.data(m.index(3, 0)), 'a2')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user