forked from qt-creator/qt-creator
QmlDesigner: Show the material name in the property editor
The material name for the property editor's material field is presented in the following format: MaterialName [MaterialId] Task-number: QDS-8663 Change-Id: I59fdfcb52ecb2ce9a1079ae20b7e2d748bbc1d61 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io> Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
@@ -146,11 +146,15 @@ StudioControls.ComboBox {
|
||||
if (!comboBox.__isCompleted)
|
||||
return
|
||||
|
||||
let inputValue = comboBox.editText
|
||||
|
||||
let index = comboBox.find(inputValue)
|
||||
if (index !== -1)
|
||||
inputValue = comboBox.textAt(index)
|
||||
let inputText = comboBox.editText
|
||||
let inputValue = inputText;
|
||||
let index = comboBox.find(inputText)
|
||||
if (index !== -1) {
|
||||
let modelIdx = comboBox.model.index(index)
|
||||
inputValue = comboBox.valueRole
|
||||
? comboBox.model.data(modelIdx, comboBox.valueRole)
|
||||
: comboBox.textAt(index)
|
||||
}
|
||||
|
||||
comboBox.backendValue.value = inputValue
|
||||
|
||||
@@ -167,6 +171,18 @@ StudioControls.ComboBox {
|
||||
if (comboBox.manualMapping)
|
||||
return
|
||||
|
||||
if (comboBox.valueRole && comboBox.textRole !== comboBox.valueRole) {
|
||||
let inputText = comboBox.currentText
|
||||
let inputValue = comboBox.currentValue
|
||||
let index = comboBox.find(inputText)
|
||||
if (index !== -1) {
|
||||
let modelIdx = comboBox.model.index(index)
|
||||
inputValue = comboBox.model.data(modelIdx, comboBox.valueRole)
|
||||
}
|
||||
comboBox.backendValue.value = inputValue
|
||||
return
|
||||
}
|
||||
|
||||
switch (comboBox.valueType) {
|
||||
case ComboBox.ValueType.String:
|
||||
comboBox.backendValue.value = comboBox.currentText
|
||||
|
@@ -23,6 +23,8 @@ Item {
|
||||
property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth
|
||||
property real __actionIndicatorHeight: StudioTheme.Values.height
|
||||
property string typeFilter: "QtQuick3D.Material"
|
||||
property string textRole: "IdAndNameRole"
|
||||
property string valueRole: "IdRole"
|
||||
property int activatedReason: ComboBox.ActivatedReason.Other
|
||||
|
||||
property bool delegateHover: false
|
||||
@@ -49,8 +51,9 @@ Item {
|
||||
|
||||
actionIndicatorVisible: false
|
||||
typeFilter: editableListView.typeFilter
|
||||
editText: modelData
|
||||
initialModelData: modelData
|
||||
textRole: editableListView.textRole
|
||||
valueRole: editableListView.valueRole
|
||||
implicitWidth: StudioTheme.Values.singleControlColumnWidth
|
||||
width: implicitWidth
|
||||
|
||||
@@ -58,20 +61,22 @@ Item {
|
||||
if (itemFilterComboBox.focus)
|
||||
myColumn.currentIndex = index
|
||||
|
||||
if (itemFilterComboBox.empty && itemFilterComboBox.editText !== "") {
|
||||
var curValue = itemFilterComboBox.availableValue()
|
||||
if (itemFilterComboBox.empty && curValue !== "") {
|
||||
myRepeater.dirty = false
|
||||
editableListView.add(itemFilterComboBox.editText)
|
||||
editableListView.add(curValue)
|
||||
}
|
||||
}
|
||||
|
||||
onCompressedActivated: {
|
||||
onCompressedActivated: function(index, reason) {
|
||||
editableListView.activatedReason = reason
|
||||
|
||||
if (itemFilterComboBox.empty && itemFilterComboBox.editText !== "") {
|
||||
var curValue = itemFilterComboBox.availableValue()
|
||||
if (itemFilterComboBox.empty && curValue) {
|
||||
myRepeater.dirty = false
|
||||
editableListView.add(itemFilterComboBox.editText)
|
||||
editableListView.add(curValue)
|
||||
} else {
|
||||
editableListView.replace(itemFilterComboBox.myIndex, itemFilterComboBox.editText)
|
||||
editableListView.replace(itemFilterComboBox.myIndex, curValue)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,21 +175,25 @@ Item {
|
||||
validator: RegExpValidator { regExp: /(^[a-z_]\w*|^[A-Z]\w*\.{1}([a-z_]\w*\.?)+)/ }
|
||||
actionIndicatorVisible: false
|
||||
typeFilter: editableListView.typeFilter
|
||||
textRole: editableListView.textRole
|
||||
valueRole: editableListView.valueRole
|
||||
implicitWidth: StudioTheme.Values.singleControlColumnWidth
|
||||
width: implicitWidth
|
||||
|
||||
onFocusChanged: {
|
||||
if (dummyComboBox.editText !== "")
|
||||
editableListView.add(dummyComboBox.editText)
|
||||
var curValue = dummyComboBox.availableValue()
|
||||
if (curValue !== "")
|
||||
editableListView.add(curValue)
|
||||
}
|
||||
|
||||
onCompressedActivated: {
|
||||
editableListView.activatedReason = reason
|
||||
|
||||
if (dummyComboBox.editText !== "")
|
||||
editableListView.add(dummyComboBox.editText)
|
||||
var curValue = dummyComboBox.availableValue()
|
||||
if (curValue !== "")
|
||||
editableListView.add(curValue)
|
||||
else
|
||||
editableListView.replace(dummyComboBox.myIndex, dummyComboBox.editText)
|
||||
editableListView.replace(dummyComboBox.myIndex, curValue)
|
||||
}
|
||||
|
||||
onHoverChanged: editableListView.delegateHover = dummyComboBox.hover
|
||||
|
@@ -14,7 +14,9 @@ StudioControls.ComboBox {
|
||||
property bool __isCompleted: false
|
||||
|
||||
editable: true
|
||||
model: itemFilterModel.itemModel
|
||||
model: itemFilterModel
|
||||
textRole: "IdRole"
|
||||
valueRole: "IdRole"
|
||||
|
||||
HelperWidgets.ItemFilterModel {
|
||||
id: itemFilterModel
|
||||
@@ -23,12 +25,48 @@ StudioControls.ComboBox {
|
||||
|
||||
Component.onCompleted: {
|
||||
comboBox.__isCompleted = true
|
||||
resetInitialIndex()
|
||||
}
|
||||
|
||||
onInitialModelDataChanged: resetInitialIndex()
|
||||
onValueRoleChanged: resetInitialIndex()
|
||||
onModelChanged: resetInitialIndex()
|
||||
onTextRoleChanged: resetInitialIndex()
|
||||
|
||||
function resetInitialIndex() {
|
||||
let currentSelectedDataIndex = -1
|
||||
|
||||
// Workaround for proper initialization. Use the initial modelData value and search for it
|
||||
// in the model. If nothing was found, set the editText to the initial modelData.
|
||||
comboBox.currentIndex = comboBox.find(comboBox.initialModelData)
|
||||
|
||||
if (textRole === valueRole) {
|
||||
currentSelectedDataIndex = comboBox.find(comboBox.initialModelData)
|
||||
} else {
|
||||
for (let i = 0; i < comboBox.count; ++i) {
|
||||
let movingModelIndex = model.index(i)
|
||||
let movingModelValueData = model.data(movingModelIndex, valueRole)
|
||||
if (movingModelValueData === initialModelData) {
|
||||
currentSelectedDataIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
comboBox.currentIndex = currentSelectedDataIndex
|
||||
if (comboBox.currentIndex === -1)
|
||||
comboBox.editText = comboBox.initialModelData
|
||||
}
|
||||
|
||||
function currentData(role = valueRole) {
|
||||
if (comboBox.currentIndex !== -1) {
|
||||
let currentModelIndex = model.index(currentIndex)
|
||||
return model.data(currentModelIndex, role)
|
||||
}
|
||||
return comboBox.editText
|
||||
}
|
||||
|
||||
function availableValue() {
|
||||
if (comboBox.currentIndex !== -1 && currentValue !== "")
|
||||
return currentValue
|
||||
|
||||
return comboBox.editText
|
||||
}
|
||||
}
|
||||
|
@@ -6,14 +6,28 @@
|
||||
#include <abstractview.h>
|
||||
#include <model.h>
|
||||
#include <nodemetainfo.h>
|
||||
#include <qmlmodelnodeproxy.h>
|
||||
#include "variantproperty.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QDirIterator>
|
||||
#include <qmlmodelnodeproxy.h>
|
||||
#include <QMetaEnum>
|
||||
|
||||
ItemFilterModel::ItemFilterModel(QObject *parent) :
|
||||
QObject(parent), m_typeFilter("QtQuick.Item"), m_lock(false), m_selectionOnly(false)
|
||||
using namespace QmlDesigner;
|
||||
|
||||
QHash<int, QByteArray> ItemFilterModel::m_roles;
|
||||
|
||||
ItemFilterModel::ItemFilterModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
, m_typeFilter("QtQuick.Item")
|
||||
, m_selectionOnly(false)
|
||||
{
|
||||
if (m_roles.empty()) {
|
||||
m_roles = QAbstractListModel::roleNames();
|
||||
QMetaEnum roleEnum = QMetaEnum::fromType<Roles>();
|
||||
for (int i = 0; i < roleEnum.keyCount(); i++)
|
||||
m_roles.insert(roleEnum.value(i), roleEnum.key(i));
|
||||
}
|
||||
}
|
||||
|
||||
void ItemFilterModel::setModelNodeBackend(const QVariant &modelNodeBackend)
|
||||
@@ -22,7 +36,7 @@ void ItemFilterModel::setModelNodeBackend(const QVariant &modelNodeBackend)
|
||||
auto modelNodeBackendObject = modelNodeBackend.value<QObject*>();
|
||||
|
||||
const auto backendObjectCasted =
|
||||
qobject_cast<const QmlDesigner::QmlModelNodeProxy *>(modelNodeBackendObject);
|
||||
qobject_cast<const QmlModelNodeProxy *>(modelNodeBackendObject);
|
||||
|
||||
if (backendObjectCasted)
|
||||
m_modelNode = backendObjectCasted->qmlObjectNode().modelNode();
|
||||
@@ -62,19 +76,79 @@ void ItemFilterModel::registerDeclarativeType()
|
||||
qmlRegisterType<ItemFilterModel>("HelperWidgets",2,0,"ItemFilterModel");
|
||||
}
|
||||
|
||||
QVariant ItemFilterModel::modelNodeBackend() const
|
||||
QModelIndex ItemFilterModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
return QVariant();
|
||||
return QAbstractListModel::index(row, column, parent);
|
||||
}
|
||||
|
||||
int ItemFilterModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return m_modelInternalIds.size();
|
||||
}
|
||||
|
||||
QVariant ItemFilterModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return {};
|
||||
|
||||
ModelNode node = modelNodeForRow(index.row());
|
||||
|
||||
QVariant value;
|
||||
switch (role) {
|
||||
case IdRole:
|
||||
value = node.id();
|
||||
break;
|
||||
case NameRole:
|
||||
value = node.variantProperty("objectName").value();
|
||||
break;
|
||||
case IdAndNameRole:
|
||||
value = QString("%1 [%2]").arg(
|
||||
node.variantProperty("objectName").value().toString()
|
||||
,node.id());
|
||||
break;
|
||||
default:
|
||||
value = node.id();
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// TODO: Handle model data manipulation here.
|
||||
bool ItemFilterModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
return QAbstractListModel::setData(index, value, role);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ItemFilterModel::roleNames() const
|
||||
{
|
||||
return m_roles;
|
||||
}
|
||||
|
||||
QVariant ItemFilterModel::modelNodeBackend() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
ModelNode ItemFilterModel::modelNodeForRow(const int &row) const
|
||||
{
|
||||
if (row < 0 || row >= m_modelInternalIds.size())
|
||||
return {};
|
||||
|
||||
AbstractView *view = m_modelNode.view();
|
||||
if (!view || !view->model())
|
||||
return {};
|
||||
|
||||
return view->modelNodeForInternalId(m_modelInternalIds.at(row));
|
||||
}
|
||||
|
||||
void ItemFilterModel::setupModel()
|
||||
{
|
||||
if (!m_modelNode.isValid() || !m_modelNode.view()->isAttached())
|
||||
return;
|
||||
|
||||
m_lock = true;
|
||||
m_model.clear();
|
||||
beginResetModel();
|
||||
m_modelInternalIds.clear();
|
||||
|
||||
const auto nodes = m_selectionOnly ? m_modelNode.view()->selectedModelNodes()
|
||||
: m_modelNode.view()->allModelNodes();
|
||||
@@ -82,15 +156,22 @@ void ItemFilterModel::setupModel()
|
||||
auto base = m_modelNode.model()->metaInfo(m_typeFilter.toUtf8());
|
||||
for (const QmlDesigner::ModelNode &node : nodes) {
|
||||
if (node.hasId() && node.metaInfo().isBasedOn(base))
|
||||
m_model.append(node.id());
|
||||
m_modelInternalIds.append(node.internalId());
|
||||
}
|
||||
|
||||
m_lock = false;
|
||||
|
||||
endResetModel();
|
||||
emit itemModelChanged();
|
||||
}
|
||||
|
||||
QStringList ItemFilterModel::itemModel() const
|
||||
{
|
||||
return m_model;
|
||||
AbstractView *view = m_modelNode.view();
|
||||
if (!view || !view->model())
|
||||
return {};
|
||||
|
||||
QStringList retval;
|
||||
for (const auto &internalId : std::as_const(m_modelInternalIds))
|
||||
retval << view->modelNodeForInternalId(internalId).id();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@@ -6,12 +6,13 @@
|
||||
#include <qmlitemnode.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QUrl>
|
||||
#include <QtQml>
|
||||
|
||||
class ItemFilterModel : public QObject
|
||||
class ItemFilterModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -21,6 +22,13 @@ class ItemFilterModel : public QObject
|
||||
Q_PROPERTY(bool selectionOnly READ selectionOnly WRITE setSelectionOnly NOTIFY selectionOnlyChanged)
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
IdRole = Qt::UserRole + 1,
|
||||
NameRole,
|
||||
IdAndNameRole
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
explicit ItemFilterModel(QObject *parent = nullptr);
|
||||
|
||||
void setModelNodeBackend(const QVariant &modelNodeBackend);
|
||||
@@ -33,6 +41,14 @@ public:
|
||||
|
||||
static void registerDeclarativeType();
|
||||
|
||||
// Make index accessible for Qml side since it's not accessible by default in QAbstractListModel
|
||||
Q_INVOKABLE QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const override;
|
||||
Q_INVOKABLE virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
Q_INVOKABLE virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
Q_INVOKABLE virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
|
||||
virtual QHash<int,QByteArray> roleNames() const override;
|
||||
|
||||
signals:
|
||||
void modelNodeBackendChanged();
|
||||
void itemModelChanged();
|
||||
@@ -40,13 +56,14 @@ signals:
|
||||
|
||||
private:
|
||||
QVariant modelNodeBackend() const;
|
||||
QmlDesigner::ModelNode modelNodeForRow(const int &row) const;
|
||||
|
||||
private:
|
||||
QString m_typeFilter;
|
||||
bool m_lock;
|
||||
QStringList m_model;
|
||||
QList<qint32> m_modelInternalIds;
|
||||
QmlDesigner::ModelNode m_modelNode;
|
||||
bool m_selectionOnly;
|
||||
static QHash<int, QByteArray> m_roles;
|
||||
};
|
||||
|
||||
QML_DECLARE_TYPE(ItemFilterModel)
|
||||
|
Reference in New Issue
Block a user