Skip to content

Commit d86e0a2

Browse files
committed
QRM: set ItemIsDrag/DropEnabled flags if there are mime types
Items in a read-only models that implement support for any mime type can be dragged. If the model is mutable, then data can also be dropped on items. In addition, items can also be dropped into invalid indexes, i.e. into the empty areas of a view. Since mimeTypes() is likely to construct a QStringList on each call, and since that list is implementation-static and never changes, cache the value. [ChangeLog][QtCore][QRangeModel] The flags() implementation sets the ItemIsDragEnabled flag for all items in a model that supports mime types (including the default mime type), and the ItemIsDropEnabled flag for items in models that are not read-only. ItemIsDropEnabled is also set for the invalid index to allow dropping of data into empty spaces of a view. Task-number: QTBUG-145800 Change-Id: I81567e4a8a11e21eedb10ec4e542369e4c220260 Reviewed-by: Artem Dyomin <artem.dyomin@qt.io>
1 parent 4261142 commit d86e0a2

5 files changed

Lines changed: 38 additions & 10 deletions

File tree

src/corelib/itemmodels/qrangemodel.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class QRangeModelPrivate : QAbstractItemModelPrivate
4040
int m_interfaceVersion = -1;
4141
int m_sortRole = Qt::DisplayRole;
4242
std::optional<QCollator> m_sortCollator;
43+
mutable std::optional<QStringList> m_mimeTypes;
4344
Qt::DropActions m_supportedDragActions = Qt::CopyAction;
4445
Qt::DropActions m_supportedDropActions = Qt::CopyAction;
4546

@@ -1053,6 +1054,13 @@ int QRangeModel::columnCount(const QModelIndex &parent) const
10531054
models operating on a range with mutable data, it also sets the flag
10541055
that allows the item to be editable (\c ItemIsEditable).
10551056
1057+
Models that return a non-empty list of \l{mimeTypes()}{mimeTypes()} also
1058+
set the Qt::ItemIsDragEnabled, and - unless read-only - the
1059+
Qt::ItemIsDropEnabled flag.
1060+
1061+
Flat models set the Qt::ItemNeverHasChildren for all items, while
1062+
hierarchical models set that flag for all items in columns above 0.
1063+
10561064
To customize the flags for your own data types, provide a specialization
10571065
of RowOptions and/or ItemAccess for your row or item types.
10581066
@@ -1426,9 +1434,12 @@ QMimeData *QRangeModel::mimeData(const QModelIndexList &indexes) const
14261434
QStringList QRangeModel::mimeTypes() const
14271435
{
14281436
Q_D(const QRangeModel);
1429-
if (d->m_interfaceVersion < QT_VERSION_CHECK(6, 12, 0))
1430-
return QAbstractItemModel::mimeTypes();
1431-
return d->impl->call<QRangeModelImplBase::MimeTypes>();
1437+
if (!d->m_mimeTypes) {
1438+
d->m_mimeTypes = d->m_interfaceVersion < QT_VERSION_CHECK(6, 12, 0)
1439+
? QAbstractItemModel::mimeTypes()
1440+
: d->impl->call<QRangeModelImplBase::MimeTypes>();
1441+
}
1442+
return *d->m_mimeTypes;
14321443
}
14331444

14341445
/*!

src/corelib/itemmodels/qrangemodel_impl.h

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,8 +1360,12 @@ class QRangeModelImpl
13601360

13611361
Qt::ItemFlags flags(const QModelIndex &index) const
13621362
{
1363-
if (!index.isValid())
1364-
return Qt::NoItemFlags;
1363+
if (!index.isValid()) {
1364+
if constexpr (isMutable())
1365+
return Qt::ItemIsDropEnabled;
1366+
else
1367+
return Qt::NoItemFlags;
1368+
}
13651369

13661370
// try customization
13671371
std::optional<Qt::ItemFlags> customFlags;
@@ -1384,14 +1388,24 @@ class QRangeModelImpl
13841388
Qt::ItemFlags f = customFlags ? *customFlags : Structure::defaultFlags();
13851389
// adjust custom flags based on what is not possible
13861390
if constexpr (!isMutable())
1387-
f &= ~Qt::ItemIsEditable;
1391+
f &= ~(Qt::ItemIsEditable | Qt::ItemIsDropEnabled);
13881392
if (index.column())
13891393
f |= Qt::ItemNeverHasChildren;
13901394
if (customFlags)
13911395
return f;
13921396

13931397
// compute flags ourselves
1398+
if (!this->itemModel().mimeTypes().isEmpty()) {
1399+
f |= Qt::ItemIsDragEnabled;
1400+
if constexpr (isMutable())
1401+
f |= Qt::ItemIsDropEnabled;
1402+
}
1403+
13941404
if constexpr (isMutable()) {
1405+
// Note: Read-only items are still droppable - we can't know here
1406+
// whether the model will insert data as new rows or children, or if
1407+
// it will overwrite the data of the dropped-on item. So we allow
1408+
// dropping on items that are not editable.
13951409
if constexpr (row_traits::hasMetaObject) {
13961410
if (index.column() < row_traits::fixed_size()) {
13971411
const QMetaObject mo = wrapped_row_type::staticMetaObject;
@@ -1416,7 +1430,7 @@ class QRangeModelImpl
14161430
});
14171431
} else {
14181432
// If there's no usable value stored in the row, then we can't
1419-
// do anything with this item.
1433+
// do anything with this item, except perhaps drop data into it
14201434
f &= ~Qt::ItemIsEditable;
14211435
}
14221436
}

tests/auto/corelib/itemmodels/qrangemodel/data.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ struct QRangeModel::ItemAccess<ItemAccessType>
119119
{
120120
static Qt::ItemFlags flags(const ItemAccessType &)
121121
{
122-
return Qt::ItemIsEditable;
122+
return Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
123123
}
124124

125125
static QVariant readRole(const ItemAccessType &item, int role)

tests/auto/corelib/itemmodels/qrangemodel/tst_qrangemodel.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,7 @@ void tst_QRangeModel::flags()
776776
auto model = factory();
777777
QFETCH(const ChangeActions, changeActions);
778778

779+
const bool hasMimeTypes = !model->mimeTypes().isEmpty();
779780
const QModelIndex first = model->index(0, 0);
780781
QVERIFY(first.isValid());
781782
const QModelIndex last = model->index(model->rowCount() - 1, model->columnCount() - 1);
@@ -787,6 +788,9 @@ void tst_QRangeModel::flags()
787788
changeActions.testFlags(ChangeAction::SetData));
788789
if (last.column() != 0)
789790
QVERIFY(last.flags().testFlag(Qt::ItemNeverHasChildren));
791+
QCOMPARE(first.flags().testFlag(Qt::ItemIsDragEnabled), hasMimeTypes);
792+
QCOMPARE(first.flags().testFlag(Qt::ItemIsDropEnabled),
793+
changeActions.testAnyFlags(ChangeAction::SetData | ChangeAction::InsertRows));
790794
}
791795

792796
void tst_QRangeModel::headerData()

tests/manual/corelib/itemmodels/qrangemodel/main.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ struct QRangeModel::RowOptions<Gadget>
6161
static Qt::ItemFlags flags(const Gadget &)
6262
{
6363
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemNeverHasChildren
64-
| Qt::ItemIsEditable
65-
| Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
64+
| Qt::ItemIsEditable;
6665
}
6766

6867
static QVariant headerData(int section, int role)

0 commit comments

Comments
 (0)