QmlDesigner: Add tooltips as data type descriptors to Model Editor

Task-number: QDS-11676
Change-Id: I14132ca8f2285de85532b26d3374b5e442f8c746
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Henning Gründl <henning.gruendl@qt.io>
This commit is contained in:
Ali Kianian
2024-03-11 15:11:18 +02:00
parent 7bdf43e8e1
commit 1e92dd4fe4
13 changed files with 154 additions and 97 deletions

View File

@@ -8,6 +8,7 @@ import Qt.labs.platform as PlatformWidgets
import HelperWidgets 2.0 as HelperWidgets import HelperWidgets 2.0 as HelperWidgets
import StudioControls 1.0 as StudioControls import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme import StudioTheme 1.0 as StudioTheme
import CollectionDetails
import CollectionEditorBackend import CollectionEditorBackend
Rectangle { Rectangle {
@@ -231,7 +232,9 @@ Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
model: root.model.typesList() model: CollectionDataTypeModel{}
textRole: "display"
tooltipRole: "toolTip"
actionIndicatorVisible: false actionIndicatorVisible: false
} }

View File

@@ -11,7 +11,7 @@ ListView {
clip: true clip: true
delegate: CollectionItem { delegate: CollectionItem {
implicitWidth: parent.width implicitWidth: root.width
onDeleteItem: root.model.removeRow(index) onDeleteItem: root.model.removeRow(index)
} }
} }

View File

@@ -6,6 +6,7 @@ import QtQuick.Layouts
import StudioTheme 1.0 as StudioTheme import StudioTheme 1.0 as StudioTheme
import StudioControls 1.0 as StudioControls import StudioControls 1.0 as StudioControls
import HelperWidgets 2.0 as HelperWidgets import HelperWidgets 2.0 as HelperWidgets
import CollectionDetails
StudioControls.Dialog { StudioControls.Dialog {
id: root id: root
@@ -91,7 +92,9 @@ StudioControls.Dialog {
property string initialType property string initialType
model: root.model.typesList() model: CollectionDataTypeModel{}
textRole: "display"
tooltipRole: "toolTip"
actionIndicatorVisible: false actionIndicatorVisible: false
} }
} }

View File

@@ -36,6 +36,8 @@ T.ComboBox {
property string preFocusText: "" property string preFocusText: ""
property string tooltipRole: ""
signal compressedActivated(int index, int reason) signal compressedActivated(int index, int reason)
enum ActivatedReason { EditingFinished, Other } enum ActivatedReason { EditingFinished, Other }
@@ -153,6 +155,17 @@ T.ComboBox {
font: control.font font: control.font
elide: Text.ElideRight elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
ToolTipArea {
anchors.fill: parent
text: control.tooltipRole ? (Array.isArray(control.model)
? modelData[control.tooltipRole]
: model[control.tooltipRole])
: ""
enabled: text
onClicked: itemDelegate.clicked()
onDoubleClicked: itemDelegate.doubleClicked()
}
} }
highlighted: control.highlightedIndex === index highlighted: control.highlightedIndex === index

View File

@@ -836,6 +836,7 @@ extend_qtc_plugin(QmlDesigner
extend_qtc_plugin(QmlDesigner extend_qtc_plugin(QmlDesigner
SOURCES_PREFIX components/collectioneditor SOURCES_PREFIX components/collectioneditor
SOURCES SOURCES
collectiondatatypemodel.cpp collectiondatatypemodel.h
collectiondetails.cpp collectiondetails.h collectiondetails.cpp collectiondetails.h
collectiondetailsmodel.cpp collectiondetailsmodel.h collectiondetailsmodel.cpp collectiondetailsmodel.h
collectiondetailssortfiltermodel.cpp collectiondetailssortfiltermodel.h collectiondetailssortfiltermodel.cpp collectiondetailssortfiltermodel.h

View File

@@ -0,0 +1,87 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "collectiondatatypemodel.h"
#include <QHash>
#include <QtQml/QmlTypeAndRevisionsRegistration>
namespace QmlDesigner {
struct CollectionDataTypeModel::Details
{
CollectionDetails::DataType type;
QString name;
QString description;
};
const QList<CollectionDataTypeModel::Details> CollectionDataTypeModel::m_orderedDetails{
{DataType::String, "String", "Text"},
{DataType::Integer, "Integer", "Whole number"},
{DataType::Real, "Real", "Number with a decimal"},
{DataType::Image, "Image", "Image resource"},
{DataType::Color, "Color", "HEX value"},
{DataType::Url, "Url", "Resource locator"},
{DataType::Boolean, "Boolean", "True/False"},
{DataType::Unknown, "Unknown", "Unknown Data Type"},
};
CollectionDataTypeModel::CollectionDataTypeModel(QObject *parent)
: QAbstractListModel(parent)
{
}
int CollectionDataTypeModel::rowCount([[maybe_unused]] const QModelIndex &parent) const
{
return m_orderedDetails.size();
}
QVariant CollectionDataTypeModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return {};
if (role == Qt::DisplayRole)
return m_orderedDetails.at(index.row()).name;
if (role == Qt::ToolTipRole)
return m_orderedDetails.at(index.row()).description;
return {};
}
QString CollectionDataTypeModel::dataTypeToString(DataType dataType)
{
static const QHash<DataType, QString> dataTypeHash = []() -> QHash<DataType, QString> {
QHash<DataType, QString> result;
for (const Details &details : m_orderedDetails)
result.insert(details.type, details.name);
return result;
}();
if (dataTypeHash.contains(dataType))
return dataTypeHash.value(dataType);
return "Unknown";
}
CollectionDetails::DataType CollectionDataTypeModel::dataTypeFromString(const QString &dataType)
{
static const QHash<QString, DataType> stringTypeHash = []() -> QHash<QString, DataType> {
QHash<QString, DataType> result;
for (const Details &details : m_orderedDetails)
result.insert(details.name, details.type);
return result;
}();
if (stringTypeHash.contains(dataType))
return stringTypeHash.value(dataType);
return DataType::Unknown;
}
void CollectionDataTypeModel::registerDeclarativeType()
{
qmlRegisterType<CollectionDataTypeModel>("CollectionDetails", 1, 0, "CollectionDataTypeModel");
}
} // namespace QmlDesigner

View File

@@ -0,0 +1,34 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include "collectiondetails.h"
#include <QAbstractListModel>
#include <QList>
namespace QmlDesigner {
class CollectionDataTypeModel : public QAbstractListModel
{
Q_OBJECT
public:
using DataType = CollectionDetails::DataType;
CollectionDataTypeModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
static Q_INVOKABLE QString dataTypeToString(DataType dataType);
static Q_INVOKABLE DataType dataTypeFromString(const QString &dataType);
static void registerDeclarativeType();
private:
struct Details;
static const QList<Details> m_orderedDetails;
};
} // namespace QmlDesigner

View File

@@ -3,6 +3,7 @@
#include "collectiondetails.h" #include "collectiondetails.h"
#include "collectiondatatypemodel.h"
#include "collectioneditorutils.h" #include "collectioneditorutils.h"
#include <utils/span.h> #include <utils/span.h>
@@ -706,7 +707,7 @@ QJsonObject CollectionDetails::toLocalJson() const
for (const CollectionProperty &property : std::as_const(d->properties)) { for (const CollectionProperty &property : std::as_const(d->properties)) {
QJsonObject columnObject; QJsonObject columnObject;
columnObject.insert("name", property.name); columnObject.insert("name", property.name);
columnObject.insert("type", CollectionEditorUtils::dataTypeToString(property.type)); columnObject.insert("type", CollectionDataTypeModel::dataTypeToString(property.type));
columnsArray.append(columnObject); columnsArray.append(columnObject);
} }
@@ -941,7 +942,7 @@ CollectionDetails CollectionDetails::fromLocalCollection(const QJsonObject &loca
result.insertColumn(columnName, result.insertColumn(columnName,
-1, -1,
{}, {},
CollectionEditorUtils::dataTypeFromString( CollectionDataTypeModel::dataTypeFromString(
column.value("type").toString())); column.value("type").toString()));
} }
} }

View File

@@ -3,6 +3,7 @@
#include "collectiondetailsmodel.h" #include "collectiondetailsmodel.h"
#include "collectiondatatypemodel.h"
#include "collectioneditorutils.h" #include "collectioneditorutils.h"
#include "modelnode.h" #include "modelnode.h"
@@ -188,7 +189,7 @@ QVariant CollectionDetailsModel::headerData(int section, Qt::Orientation orienta
{ {
if (orientation == Qt::Horizontal) { if (orientation == Qt::Horizontal) {
if (role == DataTypeRole) if (role == DataTypeRole)
return CollectionEditorUtils::dataTypeToString(m_currentCollection.typeAt(section)); return CollectionDataTypeModel::dataTypeToString(m_currentCollection.typeAt(section));
else else
return m_currentCollection.propertyAt(section); return m_currentCollection.propertyAt(section);
} }
@@ -227,7 +228,7 @@ QString CollectionDetailsModel::propertyType(int column) const
{ {
QTC_ASSERT(m_currentCollection.hasValidReference(), return {}); QTC_ASSERT(m_currentCollection.hasValidReference(), return {});
return CollectionEditorUtils::dataTypeToString(m_currentCollection.typeAt(column)); return CollectionDataTypeModel::dataTypeToString(m_currentCollection.typeAt(column));
} }
bool CollectionDetailsModel::isPropertyAvailable(const QString &name) bool CollectionDetailsModel::isPropertyAvailable(const QString &name)
@@ -251,7 +252,7 @@ bool CollectionDetailsModel::addColumn(int column, const QString &name, const QS
m_currentCollection.insertColumn(name, m_currentCollection.insertColumn(name,
column, column,
{}, {},
CollectionEditorUtils::dataTypeFromString(propertyType)); CollectionDataTypeModel::dataTypeFromString(propertyType));
endInsertColumns(); endInsertColumns();
return m_currentCollection.containsPropertyName(name); return m_currentCollection.containsPropertyName(name);
} }
@@ -298,7 +299,7 @@ bool CollectionDetailsModel::setPropertyType(int column, const QString &newValue
QTC_ASSERT(m_currentCollection.hasValidReference(), return false); QTC_ASSERT(m_currentCollection.hasValidReference(), return false);
bool changed = m_currentCollection.setPropertyType(column, bool changed = m_currentCollection.setPropertyType(column,
CollectionEditorUtils::dataTypeFromString( CollectionDataTypeModel::dataTypeFromString(
newValue)); newValue));
if (changed) { if (changed) {
emit headerDataChanged(Qt::Horizontal, column, column); emit headerDataChanged(Qt::Horizontal, column, column);
@@ -346,11 +347,6 @@ void CollectionDetailsModel::deselectAll()
selectRow(-1); selectRow(-1);
} }
QStringList CollectionDetailsModel::typesList()
{
return CollectionEditorUtils::dataTypesStringList();
}
void CollectionDetailsModel::loadCollection(const ModelNode &sourceNode, const QString &collection) void CollectionDetailsModel::loadCollection(const ModelNode &sourceNode, const QString &collection)
{ {
QString fileName = CollectionEditorUtils::getSourceCollectionPath(sourceNode); QString fileName = CollectionEditorUtils::getSourceCollectionPath(sourceNode);

View File

@@ -58,7 +58,6 @@ public:
Q_INVOKABLE bool selectRow(int row); Q_INVOKABLE bool selectRow(int row);
Q_INVOKABLE void deselectAll(); Q_INVOKABLE void deselectAll();
Q_INVOKABLE QString warningToString(DataTypeWarning::Warning warning) const; Q_INVOKABLE QString warningToString(DataTypeWarning::Warning warning) const;
static Q_INVOKABLE QStringList typesList();
void loadCollection(const ModelNode &sourceNode, const QString &collection); void loadCollection(const ModelNode &sourceNode, const QString &collection);
void removeCollection(const ModelNode &sourceNode, const QString &collection); void removeCollection(const ModelNode &sourceNode, const QString &collection);

View File

@@ -31,64 +31,6 @@ namespace {
using CollectionDataVariant = std::variant<QString, bool, double, int, QUrl, QColor>; using CollectionDataVariant = std::variant<QString, bool, double, int, QUrl, QColor>;
class CollectionDataTypeHelper
{
private:
using DataType = QmlDesigner::CollectionDetails::DataType;
friend QString QmlDesigner::CollectionEditorUtils::dataTypeToString(DataType);
friend DataType QmlDesigner::CollectionEditorUtils::dataTypeFromString(const QString &);
friend QStringList QmlDesigner::CollectionEditorUtils::dataTypesStringList();
CollectionDataTypeHelper() = delete;
static QHash<DataType, QString> typeToStringHash()
{
return {
{DataType::Unknown, "Unknown"},
{DataType::String, "String"},
{DataType::Url, "Url"},
{DataType::Real, "Real"},
{DataType::Integer, "Integer"},
{DataType::Boolean, "Boolean"},
{DataType::Image, "Image"},
{DataType::Color, "Color"},
};
}
static QHash<QString, DataType> stringToTypeHash()
{
QHash<QString, DataType> stringTypeHash;
const QHash<DataType, QString> typeStringHash = typeToStringHash();
for (const auto &transferItem : typeStringHash.asKeyValueRange())
stringTypeHash.insert(transferItem.second, transferItem.first);
return stringTypeHash;
}
static QStringList orderedTypeNames()
{
const QList<DataType> orderedtypes{
DataType::String,
DataType::Integer,
DataType::Real,
DataType::Image,
DataType::Color,
DataType::Url,
DataType::Boolean,
DataType::Unknown,
};
QStringList orderedNames;
QHash<DataType, QString> typeStringHash = typeToStringHash();
for (const DataType &type : orderedtypes)
orderedNames.append(typeStringHash.take(type));
Q_ASSERT(typeStringHash.isEmpty());
return orderedNames;
}
};
inline bool operator<(const QColor &a, const QColor &b) inline bool operator<(const QColor &a, const QColor &b)
{ {
return a.name(QColor::HexArgb) < b.name(QColor::HexArgb); return a.name(QColor::HexArgb) < b.name(QColor::HexArgb);
@@ -383,24 +325,6 @@ QJsonObject defaultColorCollection()
return collection.toLocalJson(); return collection.toLocalJson();
} }
QString dataTypeToString(CollectionDetails::DataType dataType)
{
static const QHash<DataType, QString> typeStringHash = CollectionDataTypeHelper::typeToStringHash();
return typeStringHash.value(dataType);
}
CollectionDetails::DataType dataTypeFromString(const QString &dataType)
{
static const QHash<QString, DataType> stringTypeHash = CollectionDataTypeHelper::stringToTypeHash();
return stringTypeHash.value(dataType, DataType::Unknown);
}
QStringList dataTypesStringList()
{
static const QStringList typesList = CollectionDataTypeHelper::orderedTypeNames();
return typesList;
}
bool writeToJsonDocument(const Utils::FilePath &path, const QJsonDocument &document, QString *errorString) bool writeToJsonDocument(const Utils::FilePath &path, const QJsonDocument &document, QString *errorString)
{ {
Core::FileChangeBlocker fileBlocker(path); Core::FileChangeBlocker fileBlocker(path);

View File

@@ -43,10 +43,4 @@ QJsonObject defaultCollection();
QJsonObject defaultColorCollection(); QJsonObject defaultColorCollection();
QString dataTypeToString(CollectionDetails::DataType dataType);
CollectionDetails::DataType dataTypeFromString(const QString &dataType);
QStringList dataTypesStringList();
} // namespace QmlDesigner::CollectionEditorUtils } // namespace QmlDesigner::CollectionEditorUtils

View File

@@ -3,6 +3,7 @@
#include "collectionview.h" #include "collectionview.h"
#include "collectiondatatypemodel.h"
#include "collectiondetailsmodel.h" #include "collectiondetailsmodel.h"
#include "collectioneditorconstants.h" #include "collectioneditorconstants.h"
#include "collectioneditorutils.h" #include "collectioneditorutils.h"
@@ -290,6 +291,7 @@ void CollectionView::openCollection(const QString &collectionName)
void CollectionView::registerDeclarativeType() void CollectionView::registerDeclarativeType()
{ {
CollectionDetails::registerDeclarativeType(); CollectionDetails::registerDeclarativeType();
CollectionDataTypeModel::registerDeclarativeType();
} }
void CollectionView::resetDataStoreNode() void CollectionView::resetDataStoreNode()