mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-08 00:05:09 -04:00
Add method to sort a list of layers by layer type
This commit is contained in:
parent
7c6baf8be8
commit
904a312f40
@ -56,6 +56,16 @@ uses a data provider which does not specify paths in a layer URI.
|
|||||||
.. versionadded:: 3.22
|
.. versionadded:: 3.22
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
static QList< QgsMapLayer * > sortLayersByType( const QList< QgsMapLayer * > &layers, const QList< QgsMapLayerType > &order );
|
||||||
|
%Docstring
|
||||||
|
Sorts a list of map ``layers`` by their layer type, respecting the ``order`` of types specified.
|
||||||
|
|
||||||
|
Layer types which appear earlier in the ``order`` list will result in matching layers appearing earlier in the
|
||||||
|
result list.
|
||||||
|
|
||||||
|
.. versionadded:: 3.26
|
||||||
|
%End
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -22,6 +22,108 @@ which are not wrapped by PyQt:
|
|||||||
- NULL QVariant which is missing in PyQt5 with sip.enableautoconversion
|
- NULL QVariant which is missing in PyQt5 with sip.enableautoconversion
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// adapted from the qpymultimedia_qlist.sip file from the PyQt6 sources
|
||||||
|
%MappedType QList<QgsMapLayerType>
|
||||||
|
/TypeHintIn="Iterable[QgsMapLayerType]",
|
||||||
|
TypeHintOut="List[QgsMapLayerType]", TypeHintValue="[]"/
|
||||||
|
{
|
||||||
|
%TypeHeaderCode
|
||||||
|
#include "qgis.h"
|
||||||
|
%End
|
||||||
|
|
||||||
|
%ConvertFromTypeCode
|
||||||
|
PyObject *l = PyList_New(sipCpp->size());
|
||||||
|
|
||||||
|
if (!l)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < sipCpp->size(); ++i)
|
||||||
|
{
|
||||||
|
PyObject *eobj = sipConvertFromEnum(static_cast<int>(sipCpp->at(i)),
|
||||||
|
sipType_QgsMapLayerType);
|
||||||
|
|
||||||
|
if (!eobj)
|
||||||
|
{
|
||||||
|
Py_DECREF(l);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyList_SetItem(l, i, eobj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return l;
|
||||||
|
%End
|
||||||
|
|
||||||
|
%ConvertToTypeCode
|
||||||
|
PyObject *iter = PyObject_GetIter(sipPy);
|
||||||
|
|
||||||
|
if (!sipIsErr)
|
||||||
|
{
|
||||||
|
PyErr_Clear();
|
||||||
|
Py_XDECREF(iter);
|
||||||
|
|
||||||
|
return (iter && !PyBytes_Check(sipPy) && !PyUnicode_Check(sipPy));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!iter)
|
||||||
|
{
|
||||||
|
*sipIsErr = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QgsMapLayerType> *ql = new QList<QgsMapLayerType>;
|
||||||
|
|
||||||
|
for (Py_ssize_t i = 0; ; ++i)
|
||||||
|
{
|
||||||
|
PyErr_Clear();
|
||||||
|
PyObject *itm = PyIter_Next(iter);
|
||||||
|
|
||||||
|
if (!itm)
|
||||||
|
{
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
{
|
||||||
|
delete ql;
|
||||||
|
Py_DECREF(iter);
|
||||||
|
*sipIsErr = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int v = sipConvertToEnum(itm, sipType_QgsMapLayerType);
|
||||||
|
|
||||||
|
if (PyErr_Occurred())
|
||||||
|
{
|
||||||
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"index %zd has type '%s' but 'QgsMapLayerType' is expected",
|
||||||
|
i, sipPyTypeName(Py_TYPE(itm)));
|
||||||
|
|
||||||
|
Py_DECREF(itm);
|
||||||
|
delete ql;
|
||||||
|
Py_DECREF(iter);
|
||||||
|
*sipIsErr = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ql->append(static_cast<QgsMapLayerType>(v));
|
||||||
|
|
||||||
|
Py_DECREF(itm);
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_DECREF(iter);
|
||||||
|
|
||||||
|
*sipCppPtr = ql;
|
||||||
|
|
||||||
|
return sipGetState(sipTransferObj);
|
||||||
|
%End
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <TYPE>
|
template <TYPE>
|
||||||
%MappedType QVector< QVector<TYPE> >
|
%MappedType QVector< QVector<TYPE> >
|
||||||
|
@ -137,3 +137,20 @@ bool QgsMapLayerUtils::updateLayerSourcePath( QgsMapLayer *layer, const QString
|
|||||||
layer->setDataSource( newUri, layer->name(), layer->providerType() );
|
layer->setDataSource( newUri, layer->name(), layer->providerType() );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<QgsMapLayer *> QgsMapLayerUtils::sortLayersByType( const QList<QgsMapLayer *> &layers, const QList<QgsMapLayerType> &order )
|
||||||
|
{
|
||||||
|
QList< QgsMapLayer * > res = layers;
|
||||||
|
std::sort( res.begin(), res.end(), [&order]( const QgsMapLayer * a, const QgsMapLayer * b ) -> bool
|
||||||
|
{
|
||||||
|
for ( QgsMapLayerType type : order )
|
||||||
|
{
|
||||||
|
if ( a->type() == type && b->type() != type )
|
||||||
|
return true;
|
||||||
|
else if ( b->type() == type )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} );
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
@ -70,6 +70,16 @@ class CORE_EXPORT QgsMapLayerUtils
|
|||||||
*/
|
*/
|
||||||
static bool updateLayerSourcePath( QgsMapLayer *layer, const QString &newPath );
|
static bool updateLayerSourcePath( QgsMapLayer *layer, const QString &newPath );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts a list of map \a layers by their layer type, respecting the \a order of types specified.
|
||||||
|
*
|
||||||
|
* Layer types which appear earlier in the \a order list will result in matching layers appearing earlier in the
|
||||||
|
* result list.
|
||||||
|
*
|
||||||
|
* \since QGIS 3.26
|
||||||
|
*/
|
||||||
|
static QList< QgsMapLayer * > sortLayersByType( const QList< QgsMapLayer * > &layers, const QList< QgsMapLayerType > &order );
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -20,7 +20,11 @@ from qgis.core import (
|
|||||||
QgsCoordinateTransformContext,
|
QgsCoordinateTransformContext,
|
||||||
QgsVectorLayer,
|
QgsVectorLayer,
|
||||||
QgsRasterLayer,
|
QgsRasterLayer,
|
||||||
QgsRectangle
|
QgsAnnotationLayer,
|
||||||
|
QgsGroupLayer,
|
||||||
|
QgsRectangle,
|
||||||
|
QgsProject,
|
||||||
|
QgsMapLayerType
|
||||||
)
|
)
|
||||||
from qgis.testing import start_app, unittest
|
from qgis.testing import start_app, unittest
|
||||||
from utilities import unitTestDataPath
|
from utilities import unitTestDataPath
|
||||||
@ -123,6 +127,38 @@ class TestQgsMapLayerUtils(unittest.TestCase):
|
|||||||
self.assertFalse(QgsMapLayerUtils.updateLayerSourcePath(layer, unitTestDataPath() + '/mixed_layers22.gpkg'))
|
self.assertFalse(QgsMapLayerUtils.updateLayerSourcePath(layer, unitTestDataPath() + '/mixed_layers22.gpkg'))
|
||||||
self.assertEqual(layer.source(), old_source)
|
self.assertEqual(layer.source(), old_source)
|
||||||
|
|
||||||
|
def test_sort_layers_by_type(self):
|
||||||
|
vl1 = QgsVectorLayer("Point?field=x:string", 'vector 1', "memory")
|
||||||
|
vl2 = QgsVectorLayer("Point?field=x:string", 'vector 2', "memory")
|
||||||
|
options = QgsAnnotationLayer.LayerOptions(QgsProject.instance().transformContext())
|
||||||
|
al1 = QgsAnnotationLayer('annotations 1', options)
|
||||||
|
al2 = QgsAnnotationLayer('annotations 2', options)
|
||||||
|
rl1 = QgsRasterLayer(f'GPKG:{unitTestDataPath()}/mixed_layers.gpkg:band1', 'raster 1')
|
||||||
|
options = QgsGroupLayer.LayerOptions(QgsProject.instance().transformContext())
|
||||||
|
gp1 = QgsGroupLayer('group 1', options)
|
||||||
|
|
||||||
|
self.assertEqual(QgsMapLayerUtils.sortLayersByType([vl1, rl1, gp1, vl2, al2, al1], []), [vl1, rl1, gp1, vl2, al2, al1])
|
||||||
|
self.assertEqual(QgsMapLayerUtils.sortLayersByType([vl1, rl1, gp1, vl2, al2, al1], [QgsMapLayerType.VectorLayer]), [vl1, vl2, rl1, gp1, al2, al1])
|
||||||
|
self.assertEqual(QgsMapLayerUtils.sortLayersByType([vl1, rl1, gp1, vl2, al2, al1], [QgsMapLayerType.RasterLayer, QgsMapLayerType.VectorLayer]),
|
||||||
|
[rl1, vl1, vl2, gp1, al2, al1])
|
||||||
|
self.assertEqual(QgsMapLayerUtils.sortLayersByType([vl1, rl1, gp1, vl2, al2, al1], [QgsMapLayerType.GroupLayer, QgsMapLayerType.VectorLayer]),
|
||||||
|
[gp1, vl1, vl2, rl1, al2, al1])
|
||||||
|
self.assertEqual(QgsMapLayerUtils.sortLayersByType([vl1, rl1, gp1, vl2, al2, al1], [QgsMapLayerType.GroupLayer,
|
||||||
|
QgsMapLayerType.VectorLayer,
|
||||||
|
QgsMapLayerType.AnnotationLayer]),
|
||||||
|
[gp1, vl1, vl2, al2, al1, rl1])
|
||||||
|
self.assertEqual(QgsMapLayerUtils.sortLayersByType([vl1, rl1, gp1, vl2, al2, al1], [QgsMapLayerType.GroupLayer,
|
||||||
|
QgsMapLayerType.VectorLayer,
|
||||||
|
QgsMapLayerType.RasterLayer,
|
||||||
|
QgsMapLayerType.AnnotationLayer]),
|
||||||
|
[gp1, vl1, vl2, rl1, al2, al1])
|
||||||
|
self.assertEqual(QgsMapLayerUtils.sortLayersByType([vl1, rl1, gp1, vl2], [QgsMapLayerType.GroupLayer,
|
||||||
|
QgsMapLayerType.VectorLayer,
|
||||||
|
QgsMapLayerType.RasterLayer]),
|
||||||
|
[gp1, vl1, vl2, rl1])
|
||||||
|
self.assertEqual(QgsMapLayerUtils.sortLayersByType([vl1, rl1, gp1, vl2], [QgsMapLayerType.AnnotationLayer]),
|
||||||
|
[vl1, rl1, gp1, vl2])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user