QmlDesigner: Cleanup PropertyTreeModel

* Some cleanup
* Add cache
* Strip full qualified name from PropertyNameRole
* Hide nodes without children if filtering

Change-Id: Ibd368174f5a56d6be33b6e55dc7a8099bbe2d119
Reviewed-by: Henning Gründl <henning.gruendl@qt.io>
This commit is contained in:
Thomas Hartmann
2023-09-08 16:14:06 +02:00
parent 618797a80a
commit 5f0556536e
2 changed files with 41 additions and 50 deletions

View File

@@ -141,10 +141,23 @@ void PropertyTreeModel::resetModel()
m_indexCount = 0; m_indexCount = 0;
m_nodeList = allModelNodesWithIdsSortedByDisplayName(); m_nodeList = allModelNodesWithIdsSortedByDisplayName();
if (!m_filter.isEmpty()) { //This could be a bit slow for large projects, but we have to check everynode to "hide" it.
m_nodeList = Utils::filtered(m_nodeList, [this](const ModelNode &node) {
return node.displayName().contains(m_filter)
|| !sortedAndFilteredPropertyNamesSignalsSlots(node).empty();
});
}
m_sortedAndFilteredPropertyNamesSignalsSlots.clear();
endResetModel(); endResetModel();
testModel(); testModel();
} }
QString stripQualification(const QString &string)
{
return string.split(".").last();
}
QVariant PropertyTreeModel::data(const QModelIndex &index, int role) const QVariant PropertyTreeModel::data(const QModelIndex &index, int role) const
{ {
int internalId = index.internalId(); int internalId = index.internalId();
@@ -161,7 +174,7 @@ QVariant PropertyTreeModel::data(const QModelIndex &index, int role) const
return {}; return {};
if (internalId < 0) if (internalId < 0)
return {}; return "--root item--";
QTC_ASSERT(internalId < m_indexCount, return {"assert"}); QTC_ASSERT(internalId < m_indexCount, return {"assert"});
@@ -175,7 +188,7 @@ QVariant PropertyTreeModel::data(const QModelIndex &index, int role) const
if (role == PropertyNameRole) { if (role == PropertyNameRole) {
if (!item.propertyName.isEmpty()) if (!item.propertyName.isEmpty())
return QString::fromUtf8(item.propertyName); return stripQualification(QString::fromUtf8(item.propertyName));
else else
return item.modelNode.displayName(); return item.modelNode.displayName();
} }
@@ -188,53 +201,14 @@ QVariant PropertyTreeModel::data(const QModelIndex &index, int role) const
if (std::find(dynamic.begin(), dynamic.end(), item.propertyName) != dynamic.end()) if (std::find(dynamic.begin(), dynamic.end(), item.propertyName) != dynamic.end())
return true; // dynamic properties have priority return true; // dynamic properties have priority
if (item.propertyName.isEmpty()) { //node if (item.propertyName.isEmpty()) {
//if (role == PropertyNameRole)
// return item.modelNode.displayName();
return true; // nodes are always shown return true; // nodes are always shown
} }
return false; return false;
} }
// can be removed later since we only use the two roles above in QML return {};
// just for testing
if (!(role == Qt::DisplayRole || role == Qt::FontRole))
return {};
if (!index.isValid())
return {};
if (internalId < 0)
return {};
QTC_ASSERT(internalId < m_indexCount, return {"assert"});
DataCacheItem item = m_indexHash[index.internalId()];
if (item.propertyName.isEmpty()) {
const QString name = item.modelNode.displayName();
if (role == Qt::DisplayRole)
return name;
QFont f;
f.setBold(true);
return f;
}
if (role == Qt::DisplayRole)
return QString::fromUtf8(item.propertyName);
QFont f;
auto priority = properityLists();
if (std::find(priority.begin(), priority.end(), item.propertyName) != priority.end())
f.setBold(true);
auto dynamic = getDynamicProperties(item.modelNode);
if (std::find(dynamic.begin(), dynamic.end(), item.propertyName) != dynamic.end())
f.setBold(true);
return f;
} }
Qt::ItemFlags PropertyTreeModel::flags(const QModelIndex &) const Qt::ItemFlags PropertyTreeModel::flags(const QModelIndex &) const
@@ -248,14 +222,14 @@ QModelIndex PropertyTreeModel::index(int row, int column, const QModelIndex &par
if (!m_connectionView->isAttached()) if (!m_connectionView->isAttached())
return {}; return {};
if (!hasIndex(row, column, parent))
return {};
const int rootId = -1; const int rootId = -1;
if (!parent.isValid()) if (!parent.isValid())
return createIndex(0, 0, rootId); return createIndex(0, 0, rootId);
if (!hasIndex(row, column, parent))
return {};
if (internalId == rootId) { //root level model node if (internalId == rootId) { //root level model node
const ModelNode modelNode = m_nodeList[row]; const ModelNode modelNode = m_nodeList[row];
return ensureModelIndex(modelNode, row); return ensureModelIndex(modelNode, row);
@@ -290,7 +264,7 @@ QModelIndex PropertyTreeModel::parent(const QModelIndex &index) const
int internalId = index.internalId(); int internalId = index.internalId();
if (internalId == -1) if (internalId == m_internalRootIndex)
return {}; return {};
QTC_ASSERT(internalId < m_indexCount, return {}); QTC_ASSERT(internalId < m_indexCount, return {});
@@ -471,6 +445,12 @@ const std::vector<PropertyName> PropertyTreeModel::sortedAndFilteredPropertyName
const ModelNode &modelNode) const const ModelNode &modelNode) const
{ {
std::vector<PropertyName> returnValue; std::vector<PropertyName> returnValue;
returnValue = m_sortedAndFilteredPropertyNamesSignalsSlots.value(modelNode);
if (!returnValue.empty())
return returnValue;
if (m_type == SignalType) { if (m_type == SignalType) {
returnValue = sortedAndFilteredSignalNames(modelNode.metaInfo()); returnValue = sortedAndFilteredSignalNames(modelNode.metaInfo());
} else if (m_type == SlotType) { } else if (m_type == SlotType) {
@@ -484,9 +464,13 @@ const std::vector<PropertyName> PropertyTreeModel::sortedAndFilteredPropertyName
if (m_filter.isEmpty() || modelNode.displayName().contains(m_filter)) if (m_filter.isEmpty() || modelNode.displayName().contains(m_filter))
return returnValue; return returnValue;
return Utils::filtered(returnValue, [this](const PropertyName &name) { const auto filtered = Utils::filtered(returnValue, [this](const PropertyName &name) {
return name.contains(m_filter.toUtf8()) || name == m_filter.toUtf8(); return name.contains(m_filter.toUtf8()) || name == m_filter.toUtf8();
}); });
m_sortedAndFilteredPropertyNamesSignalsSlots.insert(modelNode, filtered);
return filtered;
} }
const std::vector<PropertyName> PropertyTreeModel::getDynamicProperties( const std::vector<PropertyName> PropertyTreeModel::getDynamicProperties(
@@ -852,6 +836,10 @@ void PropertyListProxyModel::goInto(int row)
void PropertyListProxyModel::goUp() void PropertyListProxyModel::goUp()
{ {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
if (m_parentIndex.internalId() == -1)
return;
m_parentIndex = m_treeModel->parent(m_parentIndex); m_parentIndex = m_treeModel->parent(m_parentIndex);
resetModel(); resetModel();

View File

@@ -28,8 +28,8 @@ class PropertyTreeModel : public QAbstractItemModel
Q_OBJECT Q_OBJECT
public: public:
enum UserRoles { enum UserRoles {
PropertyNameRole = Qt::UserRole + 1, PropertyNameRole = Qt::DisplayRole,
PropertyPriorityRole, PropertyPriorityRole = Qt::UserRole + 1,
ExpressionRole, ExpressionRole,
ChildCountRole, ChildCountRole,
RowRole, RowRole,
@@ -122,6 +122,8 @@ private:
QList<ModelNode> m_nodeList; QList<ModelNode> m_nodeList;
PropertyTypes m_type = AllTypes; PropertyTypes m_type = AllTypes;
QString m_filter; QString m_filter;
mutable QHash<ModelNode, std::vector<PropertyName>> m_sortedAndFilteredPropertyNamesSignalsSlots;
int m_internalRootIndex = -1;
}; };
class PropertyListProxyModel : public QAbstractListModel class PropertyListProxyModel : public QAbstractListModel
@@ -158,6 +160,7 @@ private:
PropertyTreeModel *m_treeModel = nullptr; PropertyTreeModel *m_treeModel = nullptr;
}; };
inline bool operator==(const PropertyTreeModel::DataCacheItem &lhs, inline bool operator==(const PropertyTreeModel::DataCacheItem &lhs,
const PropertyTreeModel::DataCacheItem &rhs) const PropertyTreeModel::DataCacheItem &rhs)
{ {