mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-09 00:08:52 -04:00
Add a way for QgsSingleItemModel to have multiple column items
This commit is contained in:
parent
1f63112e6d
commit
f5f552aa61
@ -22,13 +22,26 @@ A :py:class:`QgsSingleItemModel` subclass which contains a single read-only item
|
||||
%End
|
||||
public:
|
||||
|
||||
explicit QgsSingleItemModel( QObject *parent /TransferThis/ = 0, const QString &text = QString(), const QMap< int, QVariant > &data = QMap< int, QVariant >(), Qt::ItemFlags flags = Qt::NoItemFlags );
|
||||
explicit QgsSingleItemModel( QObject *parent /TransferThis/ = 0, const QString &text = QString(),
|
||||
const QMap< int, QVariant > &data = QMap< int, QVariant >(), Qt::ItemFlags flags = Qt::NoItemFlags );
|
||||
%Docstring
|
||||
Constructor for QgsSingleItemModel with the specified ``parent`` object and display ``text``.
|
||||
|
||||
The ``data`` map specifies the data which should be returned for the specified roles, where
|
||||
map keys are Qt item roles.
|
||||
|
||||
Custom ``flags`` can also be specified for the item.
|
||||
%End
|
||||
|
||||
explicit QgsSingleItemModel( QObject *parent /TransferThis/,
|
||||
const QList< QMap< int, QVariant > > &columnData,
|
||||
Qt::ItemFlags flags = Qt::NoItemFlags );
|
||||
%Docstring
|
||||
Constructor for a multi-column QgsSingleItemModel with the specified ``parent`` object.
|
||||
|
||||
The ``columnData`` list specifies the data which should be returned for the specified roles for each column in the model, where
|
||||
each entry in the list must be a QMap of Qt item role to value.
|
||||
|
||||
Custom ``flags`` can also be specified for the item.
|
||||
%End
|
||||
|
||||
|
@ -765,6 +765,134 @@ template<TYPE>
|
||||
%End
|
||||
};
|
||||
|
||||
template<TYPE>
|
||||
%MappedType QList<QMap<int, TYPE>>
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qmap.h>
|
||||
#include <qlist.h>
|
||||
%End
|
||||
|
||||
%ConvertFromTypeCode
|
||||
|
||||
// Create the list
|
||||
PyObject *l = PyList_New(sipCpp->size());
|
||||
|
||||
if (!l)
|
||||
return NULL;
|
||||
|
||||
// Set the list elements.
|
||||
QList<QMap<int, TYPE>>::const_iterator it = sipCpp->constBegin();
|
||||
int i = 0;
|
||||
while (it != sipCpp->constEnd())
|
||||
{
|
||||
// Create the dictionary.
|
||||
PyObject *d = PyDict_New();
|
||||
if (!d)
|
||||
{
|
||||
Py_DECREF(l);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QMap<int, TYPE>::const_iterator mapIt = it->constBegin();
|
||||
while (mapIt != it->constEnd())
|
||||
{
|
||||
TYPE *t = new TYPE(mapIt.value());
|
||||
|
||||
PyObject *kobj = PyLong_FromLong(mapIt.key());
|
||||
PyObject *tobj = sipConvertFromNewType(t, sipType_TYPE, sipTransferObj);
|
||||
|
||||
if (kobj == NULL || tobj == NULL || PyDict_SetItem(d, kobj, tobj) < 0)
|
||||
{
|
||||
Py_DECREF(d);
|
||||
|
||||
if (kobj)
|
||||
{
|
||||
Py_DECREF(kobj);
|
||||
}
|
||||
|
||||
if (tobj)
|
||||
{
|
||||
Py_DECREF(tobj);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete t;
|
||||
}
|
||||
|
||||
Py_DECREF(l);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_DECREF(kobj);
|
||||
Py_DECREF(tobj);
|
||||
|
||||
++mapIt;
|
||||
}
|
||||
|
||||
PyList_SET_ITEM(l, i, d);
|
||||
++i;
|
||||
++it;
|
||||
}
|
||||
|
||||
return l;
|
||||
%End
|
||||
|
||||
%ConvertToTypeCode
|
||||
PyObject *kobj, *tobj;
|
||||
SIP_SSIZE_T i = 0;
|
||||
|
||||
// Check the type if that is all that is required.
|
||||
if (sipIsErr == NULL)
|
||||
{
|
||||
if (!PyList_Check(sipPy))
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < PyList_GET_SIZE(sipPy); ++i)
|
||||
{
|
||||
if (!PyDict_Check(PyList_GET_ITEM(sipPy, i)))
|
||||
return 0;
|
||||
|
||||
Py_ssize_t j = 0;
|
||||
while (PyDict_Next(PyList_GET_ITEM(sipPy, i), &j, &kobj, &tobj))
|
||||
if (!sipCanConvertToType(tobj, sipType_TYPE, SIP_NOT_NONE))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
QList< QMap<int, TYPE> >* ql = new QList< QMap<int, TYPE> >;
|
||||
for (int i = 0; i < PyList_GET_SIZE(sipPy); ++i)
|
||||
{
|
||||
Py_ssize_t j = 0;
|
||||
QMap<int, TYPE> qm;
|
||||
while (PyDict_Next(PyList_GET_ITEM(sipPy, i), &j, &kobj, &tobj))
|
||||
{
|
||||
int state;
|
||||
int k = PyLong_AsLong(kobj);
|
||||
TYPE *t = reinterpret_cast<TYPE *>(sipConvertToType(tobj, sipType_TYPE, sipTransferObj, SIP_NOT_NONE, &state, sipIsErr));
|
||||
|
||||
if (*sipIsErr)
|
||||
{
|
||||
sipReleaseType(t, sipType_TYPE, state);
|
||||
|
||||
delete ql;
|
||||
return 0;
|
||||
}
|
||||
|
||||
qm.insert(k, *t);
|
||||
sipReleaseType(t, sipType_TYPE, state);
|
||||
}
|
||||
ql->append( qm );
|
||||
}
|
||||
|
||||
*sipCppPtr = ql;
|
||||
|
||||
return sipGetState(sipTransferObj);
|
||||
%End
|
||||
};
|
||||
|
||||
|
||||
%MappedType QMap<QString, int>
|
||||
{
|
||||
|
@ -25,21 +25,38 @@ QgsSingleItemModel::QgsSingleItemModel( QObject *parent, const QString &text, co
|
||||
|
||||
}
|
||||
|
||||
QgsSingleItemModel::QgsSingleItemModel( QObject *parent, const QList<QMap<int, QVariant> > &columnData, Qt::ItemFlags flags )
|
||||
: QAbstractItemModel( parent )
|
||||
, mColumnData( columnData )
|
||||
, mFlags( flags )
|
||||
{
|
||||
}
|
||||
|
||||
QVariant QgsSingleItemModel::data( const QModelIndex &index, int role ) const
|
||||
{
|
||||
if ( index.row() < 0 || index.row() >= rowCount( QModelIndex() ) )
|
||||
return QVariant();
|
||||
|
||||
switch ( role )
|
||||
if ( index.column() < 0 || index.column() >= columnCount( QModelIndex() ) )
|
||||
return QVariant();
|
||||
|
||||
if ( !mColumnData.isEmpty() )
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
return mText;
|
||||
return mColumnData.value( index.column() ).value( role );
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ( role )
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
return mText;
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
return mData.value( Qt::ToolTipRole, mText );
|
||||
case Qt::ToolTipRole:
|
||||
return mData.value( Qt::ToolTipRole, mText );
|
||||
|
||||
default:
|
||||
return mData.value( role );
|
||||
default:
|
||||
return mData.value( role );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,5 +101,8 @@ int QgsSingleItemModel::rowCount( const QModelIndex &parent ) const
|
||||
|
||||
int QgsSingleItemModel::columnCount( const QModelIndex & ) const
|
||||
{
|
||||
if ( !mColumnData.empty() )
|
||||
return mColumnData.size();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -42,7 +42,20 @@ class CORE_EXPORT QgsSingleItemModel: public QAbstractItemModel
|
||||
*
|
||||
* Custom \a flags can also be specified for the item.
|
||||
*/
|
||||
explicit QgsSingleItemModel( QObject *parent SIP_TRANSFERTHIS = nullptr, const QString &text = QString(), const QMap< int, QVariant > &data = QMap< int, QVariant >(), Qt::ItemFlags flags = Qt::NoItemFlags );
|
||||
explicit QgsSingleItemModel( QObject *parent SIP_TRANSFERTHIS = nullptr, const QString &text = QString(),
|
||||
const QMap< int, QVariant > &data = QMap< int, QVariant >(), Qt::ItemFlags flags = Qt::NoItemFlags );
|
||||
|
||||
/**
|
||||
* Constructor for a multi-column QgsSingleItemModel with the specified \a parent object.
|
||||
*
|
||||
* The \a columnData list specifies the data which should be returned for the specified roles for each column in the model, where
|
||||
* each entry in the list must be a QMap of Qt item role to value.
|
||||
*
|
||||
* Custom \a flags can also be specified for the item.
|
||||
*/
|
||||
explicit QgsSingleItemModel( QObject *parent SIP_TRANSFERTHIS,
|
||||
const QList< QMap< int, QVariant > > &columnData,
|
||||
Qt::ItemFlags flags = Qt::NoItemFlags );
|
||||
|
||||
QVariant data( const QModelIndex &index, int role ) const override;
|
||||
Qt::ItemFlags flags( const QModelIndex &index ) const override;
|
||||
@ -56,6 +69,7 @@ class CORE_EXPORT QgsSingleItemModel: public QAbstractItemModel
|
||||
|
||||
QString mText;
|
||||
QMap< int, QVariant > mData;
|
||||
QList< QMap< int, QVariant > > mColumnData;
|
||||
Qt::ItemFlags mFlags = Qt::NoItemFlags;
|
||||
};
|
||||
|
||||
|
@ -65,6 +65,28 @@ class TestQgsSingleItemModel(unittest.TestCase):
|
||||
# manually specified tooltip should take precedence
|
||||
self.assertEqual(model.data(index, Qt.ToolTipRole), 'abc')
|
||||
|
||||
def testModelWithColumns(self):
|
||||
model = QgsSingleItemModel(None, [
|
||||
{Qt.DisplayRole: 'col 1', Qt.ToolTipRole: 'column 1'},
|
||||
{Qt.DisplayRole: 'col 2', Qt.ToolTipRole: 'column 2'},
|
||||
{Qt.DisplayRole: 'col 3'},
|
||||
], Qt.ItemIsSelectable | Qt.ItemIsDropEnabled)
|
||||
|
||||
self.assertEqual(model.rowCount(), 1)
|
||||
self.assertEqual(model.columnCount(), 3)
|
||||
|
||||
index = model.index(0, 0)
|
||||
self.assertEqual(model.data(index, Qt.DisplayRole), 'col 1')
|
||||
self.assertEqual(model.data(index, Qt.ToolTipRole), 'column 1')
|
||||
index = model.index(0, 1)
|
||||
self.assertEqual(model.data(index, Qt.DisplayRole), 'col 2')
|
||||
self.assertEqual(model.data(index, Qt.ToolTipRole), 'column 2')
|
||||
index = model.index(0, 2)
|
||||
self.assertEqual(model.data(index, Qt.DisplayRole), 'col 3')
|
||||
self.assertFalse(model.data(index, Qt.ToolTipRole))
|
||||
|
||||
self.assertEqual(model.flags(index), Qt.ItemIsSelectable | Qt.ItemIsDropEnabled)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user