forked from qt-creator/qt-creator
QmlDesigner: Integrate Model::singletonMetaInfos()
THe backend model is removed because it is not anymore used. Task-number: QDS-13603 Change-Id: I9e9857e8698d450e81246009d6f463c50d4ae392 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -558,7 +558,6 @@ extend_qtc_plugin(QmlDesigner
|
||||
SOURCES_PREFIX components/connectioneditor
|
||||
SOURCES
|
||||
addnewbackenddialog.cpp addnewbackenddialog.h addnewbackenddialog.ui
|
||||
backendmodel.cpp backendmodel.h
|
||||
bindingmodel.cpp bindingmodel.h
|
||||
bindingmodelitem.cpp bindingmodelitem.h
|
||||
connectioneditor.qrc
|
||||
|
@@ -305,6 +305,31 @@ void ActionEditor::prepareConnections()
|
||||
}
|
||||
|
||||
// Singletons
|
||||
#ifdef QDS_USE_PROJECTSTORAGE
|
||||
if (auto model = m_modelNode.model()) {
|
||||
for (const auto &metaInfo : model->singletonMetaInfos()) {
|
||||
if (metaInfo.isValid()) {
|
||||
ActionEditorDialog::SingletonOption singelton;
|
||||
for (const auto &property : metaInfo.properties()) {
|
||||
if (isSkippedType(property.propertyType()))
|
||||
continue;
|
||||
auto exportedTypeName = model
|
||||
->exportedTypeNameForMetaInfo(property.propertyType())
|
||||
.name.toQByteArray();
|
||||
singelton.properties.append(
|
||||
ActionEditorDialog::PropertyOption(QString::fromUtf8(property.name()),
|
||||
exportedTypeName,
|
||||
property.isWritable()));
|
||||
}
|
||||
|
||||
if (!singelton.properties.isEmpty()) {
|
||||
singelton.item = metaInfo.displayName();
|
||||
singletons.append(singelton);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (RewriterView *rv = m_modelNode.view()->rewriterView()) {
|
||||
for (const QmlTypeData &data : rv->getQMLTypes()) {
|
||||
if (!data.typeName.isEmpty()) {
|
||||
@@ -314,21 +339,10 @@ void ActionEditor::prepareConnections()
|
||||
for (const auto &property : metaInfo.properties()) {
|
||||
if (isSkippedType(property.propertyType()))
|
||||
continue;
|
||||
#ifdef QDS_USE_PROJECTSTORAGE
|
||||
auto exportedTypeName = model
|
||||
->exportedTypeNameForMetaInfo(
|
||||
property.propertyType())
|
||||
.name.toQByteArray();
|
||||
singelton.properties.append(
|
||||
ActionEditorDialog::PropertyOption(QString::fromUtf8(property.name()),
|
||||
exportedTypeName,
|
||||
property.isWritable()));
|
||||
#else
|
||||
singelton.properties.append(ActionEditorDialog::PropertyOption(
|
||||
QString::fromUtf8(property.name()),
|
||||
skipCpp(property.propertyType().typeName()),
|
||||
property.isWritable()));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!singelton.properties.isEmpty()) {
|
||||
@@ -339,6 +353,7 @@ void ActionEditor::prepareConnections()
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// States
|
||||
for (const QmlModelState &state : QmlItemNode(m_modelNode.view()->rootModelNode()).states().allStates())
|
||||
|
@@ -246,6 +246,26 @@ void BindingEditor::prepareBindings()
|
||||
}
|
||||
|
||||
//singletons:
|
||||
#ifdef QDS_USE_PROJECTSTORAGE
|
||||
if (auto model = m_modelNode.view()->model()) {
|
||||
for (const auto &metaInfo : model->singletonMetaInfos()) {
|
||||
BindingEditorDialog::BindingOption binding;
|
||||
|
||||
for (const auto &property : metaInfo.properties()) {
|
||||
const auto propertyType = property.propertyType();
|
||||
|
||||
if (compareTypes(m_backendValueType, propertyType)) {
|
||||
binding.properties.append(QString::fromUtf8(property.name()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!binding.properties.isEmpty()) {
|
||||
binding.item = metaInfo.displayName();
|
||||
bindings.append(binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (RewriterView *rv = m_modelNode.view()->rewriterView()) {
|
||||
for (const QmlTypeData &data : rv->getQMLTypes()) {
|
||||
if (!data.typeName.isEmpty()) {
|
||||
@@ -270,7 +290,7 @@ void BindingEditor::prepareBindings()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
if (!bindings.isEmpty() && m_dialog)
|
||||
m_dialog->setAllBindings(bindings, m_backendValueType);
|
||||
}
|
||||
@@ -289,7 +309,7 @@ void BindingEditor::updateWindowName()
|
||||
} else {
|
||||
#ifdef QDS_USE_PROJECTSTORAGE
|
||||
targetString = " [" + (m_targetName.isEmpty() ? QString() : (m_targetName + ": "))
|
||||
+ QString::fromUtf8(m_backendValueType.displayName()) + "]";
|
||||
+ m_backendValueType.displayName() + "]";
|
||||
#else
|
||||
targetString = " [" + (m_targetName.isEmpty() ? QString() : (m_targetName + ": "))
|
||||
+ QString::fromUtf8(m_backendValueType.simplifiedTypeName()) + "]";
|
||||
|
@@ -1,318 +0,0 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
|
||||
#include "backendmodel.h"
|
||||
|
||||
#include "bindingproperty.h"
|
||||
#include "connectioneditorutils.h"
|
||||
#include "connectionview.h"
|
||||
#include "exception.h"
|
||||
#include "nodemetainfo.h"
|
||||
#include "nodeproperty.h"
|
||||
#include "rewriterview.h"
|
||||
|
||||
#include "addnewbackenddialog.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
BackendModel::BackendModel(ConnectionView *view)
|
||||
: m_connectionView(view)
|
||||
{
|
||||
connect(this, &QStandardItemModel::dataChanged, this, &BackendModel::handleDataChanged);
|
||||
}
|
||||
|
||||
ConnectionView *BackendModel::connectionView() const
|
||||
{
|
||||
return m_connectionView;
|
||||
}
|
||||
|
||||
void BackendModel::resetModel()
|
||||
{
|
||||
if (!m_connectionView->model())
|
||||
return;
|
||||
|
||||
RewriterView *rewriterView = m_connectionView->model()->rewriterView();
|
||||
|
||||
m_lock = true;
|
||||
|
||||
beginResetModel();
|
||||
clear();
|
||||
|
||||
setHorizontalHeaderLabels(QStringList({ tr("Type"), tr("Name"), tr("Singleton"), tr("Local") }));
|
||||
|
||||
ModelNode rootNode = connectionView()->rootModelNode();
|
||||
|
||||
static const PropertyTypeList simpleTypes = {"int", "real", "color", "string"};
|
||||
|
||||
if (rewriterView)
|
||||
for (const QmlTypeData &cppTypeData : rewriterView->getQMLTypes())
|
||||
if (cppTypeData.isSingleton) {
|
||||
NodeMetaInfo metaInfo = m_connectionView->model()->metaInfo(
|
||||
cppTypeData.typeName.toUtf8());
|
||||
if (metaInfo.isValid() && !metaInfo.isQtQuickItem()) {
|
||||
auto type = new QStandardItem(cppTypeData.typeName);
|
||||
type->setData(cppTypeData.typeName, Qt::UserRole + 1);
|
||||
type->setData(true, Qt::UserRole + 2);
|
||||
type->setEditable(false);
|
||||
|
||||
auto name = new QStandardItem(cppTypeData.typeName);
|
||||
name->setEditable(false);
|
||||
|
||||
QStandardItem *singletonItem = new QStandardItem("");
|
||||
singletonItem->setCheckState(Qt::Checked);
|
||||
|
||||
singletonItem->setCheckable(true);
|
||||
singletonItem->setEnabled(false);
|
||||
|
||||
QStandardItem *inlineItem = new QStandardItem("");
|
||||
|
||||
inlineItem->setCheckState(Qt::Unchecked);
|
||||
|
||||
inlineItem->setCheckable(true);
|
||||
inlineItem->setEnabled(false);
|
||||
|
||||
appendRow({type, name, singletonItem, inlineItem});
|
||||
}
|
||||
}
|
||||
|
||||
if (rootNode.isValid()) {
|
||||
const QList<AbstractProperty> properties = rootNode.properties();
|
||||
for (const AbstractProperty &property : properties)
|
||||
if (property.isDynamic() && !simpleTypes.contains(property.dynamicTypeName())) {
|
||||
|
||||
NodeMetaInfo metaInfo = m_connectionView->model()->metaInfo(property.dynamicTypeName());
|
||||
if (metaInfo.isValid() && !metaInfo.isQtQuickItem()) {
|
||||
QStandardItem *type = new QStandardItem(QString::fromUtf8(property.dynamicTypeName()));
|
||||
type->setEditable(false);
|
||||
|
||||
type->setData(QString::fromUtf8(property.name()), Qt::UserRole + 1);
|
||||
type->setData(false, Qt::UserRole + 2);
|
||||
QStandardItem *name = new QStandardItem(QString::fromUtf8(property.name()));
|
||||
|
||||
QStandardItem *singletonItem = new QStandardItem("");
|
||||
singletonItem->setCheckState(Qt::Unchecked);
|
||||
|
||||
singletonItem->setCheckable(true);
|
||||
singletonItem->setEnabled(false);
|
||||
|
||||
QStandardItem *inlineItem = new QStandardItem("");
|
||||
|
||||
inlineItem->setCheckState(property.isNodeProperty() ? Qt::Checked : Qt::Unchecked);
|
||||
|
||||
inlineItem->setCheckable(true);
|
||||
inlineItem->setEnabled(false);
|
||||
|
||||
appendRow({ type, name, singletonItem, inlineItem });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_lock = false;
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QStringList BackendModel::possibleCppTypes() const
|
||||
{
|
||||
RewriterView *rewriterView = m_connectionView->model()->rewriterView();
|
||||
|
||||
QStringList list;
|
||||
|
||||
if (rewriterView) {
|
||||
const QList<QmlTypeData> cppTypes = rewriterView->getQMLTypes();
|
||||
for (const QmlTypeData &cppTypeData : cppTypes)
|
||||
list.append(cppTypeData.typeName);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
QmlTypeData BackendModel::cppTypeDataForType(const QString &typeName) const
|
||||
{
|
||||
RewriterView *rewriterView = m_connectionView->model()->rewriterView();
|
||||
|
||||
if (!rewriterView)
|
||||
return QmlTypeData();
|
||||
|
||||
return Utils::findOr(rewriterView->getQMLTypes(), QmlTypeData(), [&typeName](const QmlTypeData &data) {
|
||||
return typeName == data.typeName;
|
||||
});
|
||||
}
|
||||
|
||||
void BackendModel::deletePropertyByRow(int rowNumber)
|
||||
{
|
||||
Model *model = m_connectionView->model();
|
||||
if (!model)
|
||||
return;
|
||||
|
||||
/* singleton case remove the import */
|
||||
if (data(index(rowNumber, 0), Qt::UserRole + 1).toBool()) {
|
||||
const QString typeName = data(index(rowNumber, 0), Qt::UserRole + 1).toString();
|
||||
QmlTypeData cppTypeData = cppTypeDataForType(typeName);
|
||||
|
||||
if (cppTypeData.isSingleton) {
|
||||
|
||||
Import import = Import::createLibraryImport(cppTypeData.importUrl, cppTypeData.versionString);
|
||||
|
||||
try {
|
||||
if (model->hasImport(import))
|
||||
model->changeImports({}, {import});
|
||||
} catch (const Exception &e) {
|
||||
e.showException();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const QString propertyName = data(index(rowNumber, 0), Qt::UserRole + 1).toString();
|
||||
|
||||
ModelNode modelNode = connectionView()->rootModelNode();
|
||||
|
||||
try {
|
||||
modelNode.removeProperty(propertyName.toUtf8());
|
||||
} catch (const Exception &e) {
|
||||
e.showException();
|
||||
}
|
||||
}
|
||||
|
||||
resetModel();
|
||||
}
|
||||
|
||||
void BackendModel::addNewBackend()
|
||||
{
|
||||
Model *model = m_connectionView->model();
|
||||
if (!model)
|
||||
return;
|
||||
|
||||
AddNewBackendDialog dialog(Core::ICore::dialogParent());
|
||||
|
||||
RewriterView *rewriterView = model->rewriterView();
|
||||
|
||||
QStringList availableTypes;
|
||||
|
||||
if (rewriterView)
|
||||
dialog.setupPossibleTypes(Utils::filtered(rewriterView->getQMLTypes(), [model](const QmlTypeData &cppTypeData) {
|
||||
return !cppTypeData.isSingleton || !model->metaInfo(cppTypeData.typeName.toUtf8()).isValid();
|
||||
/* Only show singletons if the import is missing */
|
||||
}));
|
||||
|
||||
dialog.exec();
|
||||
|
||||
if (dialog.applied()) {
|
||||
QStringList importSplit = dialog.importString().split(" ");
|
||||
if (importSplit.size() != 2) {
|
||||
qCWarning(ConnectionEditorLog) << __FUNCTION__ << "invalid import" << importSplit;
|
||||
QTC_ASSERT(false, return);
|
||||
}
|
||||
|
||||
QString typeName = dialog.type();
|
||||
|
||||
Import import = Import::createLibraryImport(importSplit.constFirst(), importSplit.constLast());
|
||||
|
||||
/* We cannot add an import and add a node from that import in a single transaction.
|
||||
* We need the import to have the meta info available.
|
||||
*/
|
||||
|
||||
if (!model->hasImport(import))
|
||||
model->changeImports({import}, {});
|
||||
|
||||
QString propertyName = m_connectionView->model()->generateNewId(typeName);
|
||||
|
||||
NodeMetaInfo metaInfo = model->metaInfo(typeName.toUtf8());
|
||||
|
||||
QTC_ASSERT(metaInfo.isValid(), return);
|
||||
|
||||
/* Add a property for non singleton types. For singletons just adding the import is enough. */
|
||||
if (!dialog.isSingleton()) {
|
||||
m_connectionView->executeInTransaction("BackendModel::addNewBackend",
|
||||
[this, metaInfo, typeName, propertyName, &dialog] {
|
||||
|
||||
if (dialog.localDefinition()) {
|
||||
#ifdef QDS_USE_PROJECTSTORAGE
|
||||
ModelNode newNode = m_connectionView->createModelNode(typeName.toUtf8());
|
||||
#else
|
||||
int minorVersion = metaInfo.minorVersion();
|
||||
int majorVersion = metaInfo.majorVersion();
|
||||
ModelNode newNode = m_connectionView->createModelNode(metaInfo.typeName(),
|
||||
majorVersion,
|
||||
minorVersion);
|
||||
#endif
|
||||
m_connectionView->rootModelNode().nodeProperty(propertyName.toUtf8()).setDynamicTypeNameAndsetModelNode(
|
||||
typeName.toUtf8(), newNode);
|
||||
} else {
|
||||
m_connectionView->rootModelNode().bindingProperty(
|
||||
propertyName.toUtf8()).setDynamicTypeNameAndExpression(typeName.toUtf8(), "null");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
resetModel();
|
||||
}
|
||||
|
||||
void BackendModel::updatePropertyName(int rowNumber)
|
||||
{
|
||||
const PropertyName newName = data(index(rowNumber, 1)).toString().toUtf8();
|
||||
const PropertyName oldName = data(index(rowNumber, 0), Qt::UserRole + 1).toString().toUtf8();
|
||||
|
||||
m_connectionView->executeInTransaction("BackendModel::updatePropertyName", [this, newName, oldName](){
|
||||
|
||||
ModelNode rootModelNode = m_connectionView->rootModelNode();
|
||||
if (rootModelNode.property(oldName).isNodeProperty()) {
|
||||
|
||||
const TypeName typeName = rootModelNode.nodeProperty(oldName).dynamicTypeName();
|
||||
const ModelNode targetModelNode = rootModelNode.nodeProperty(oldName).modelNode();
|
||||
const TypeName fullTypeName = targetModelNode.type();
|
||||
const int majorVersion = targetModelNode.majorVersion();
|
||||
const int minorVersion = targetModelNode.minorVersion();
|
||||
|
||||
rootModelNode.removeProperty(oldName);
|
||||
ModelNode newNode = m_connectionView->createModelNode(fullTypeName, majorVersion, minorVersion);
|
||||
m_connectionView->rootModelNode().nodeProperty(newName).setDynamicTypeNameAndsetModelNode(typeName, newNode);
|
||||
|
||||
} else if (rootModelNode.property(oldName).isBindingProperty()) {
|
||||
const QString expression = rootModelNode.bindingProperty(oldName).expression();
|
||||
const TypeName typeName = rootModelNode.bindingProperty(oldName).dynamicTypeName();
|
||||
|
||||
rootModelNode.removeProperty(oldName);
|
||||
rootModelNode.bindingProperty(newName).setDynamicTypeNameAndExpression(typeName, expression);
|
||||
} else {
|
||||
qCWarning(ConnectionEditorLog) << __FUNCTION__ << oldName << newName << "failed...";
|
||||
QTC_ASSERT(false, return);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void BackendModel::handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
|
||||
{
|
||||
if (m_lock)
|
||||
return;
|
||||
|
||||
if (topLeft != bottomRight) {
|
||||
qCWarning(ConnectionEditorLog) << __FUNCTION__ << "multi edit?";
|
||||
return;
|
||||
}
|
||||
|
||||
m_lock = true;
|
||||
|
||||
int currentColumn = topLeft.column();
|
||||
int currentRow = topLeft.row();
|
||||
|
||||
switch (currentColumn) {
|
||||
case 0: {
|
||||
//updating user data
|
||||
} break;
|
||||
case 1: {
|
||||
updatePropertyName(currentRow);
|
||||
} break;
|
||||
|
||||
default:
|
||||
qCWarning(ConnectionEditorLog) << __FUNCTION__ << "column" << currentColumn;
|
||||
}
|
||||
|
||||
m_lock = false;
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
@@ -1,48 +0,0 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#pragma once
|
||||
#include <QStandardItemModel>
|
||||
|
||||
#include "rewriterview.h"
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class ConnectionView;
|
||||
|
||||
class BackendModel : public QStandardItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum ColumnRoles {
|
||||
TypeNameColumn = 0,
|
||||
PropertyNameColumn = 1,
|
||||
IsSingletonColumn = 2,
|
||||
IsLocalColumn = 3,
|
||||
};
|
||||
|
||||
BackendModel(ConnectionView *view);
|
||||
|
||||
ConnectionView *connectionView() const;
|
||||
|
||||
void resetModel();
|
||||
|
||||
QStringList possibleCppTypes() const;
|
||||
QmlTypeData cppTypeDataForType(const QString &typeName) const;
|
||||
|
||||
void deletePropertyByRow(int rowNumber);
|
||||
|
||||
void addNewBackend();
|
||||
|
||||
protected:
|
||||
void updatePropertyName(int rowNumber);
|
||||
|
||||
private:
|
||||
void handleDataChanged(const QModelIndex &topLeft, const QModelIndex& bottomRight);
|
||||
|
||||
private:
|
||||
ConnectionView *m_connectionView;
|
||||
bool m_lock = false;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
@@ -277,12 +277,12 @@ std::pair<QString, QString> splitExpression(const QString &expression)
|
||||
return {sourceNode, propertyName};
|
||||
}
|
||||
|
||||
#ifndef QDS_USE_PROJECTSTORAGE
|
||||
QStringList singletonsFromView(AbstractView *view)
|
||||
{
|
||||
RewriterView *rv = view->rewriterView();
|
||||
if (!rv)
|
||||
return {};
|
||||
|
||||
QStringList out;
|
||||
for (const QmlTypeData &data : rv->getQMLTypes()) {
|
||||
if (data.isSingleton && !data.typeName.isEmpty())
|
||||
@@ -301,6 +301,7 @@ std::vector<PropertyMetaInfo> propertiesFromSingleton(const QString &name, Abstr
|
||||
|
||||
return {};
|
||||
}
|
||||
#endif
|
||||
|
||||
QList<AbstractProperty> dynamicPropertiesFromNode(const ModelNode &node)
|
||||
{
|
||||
@@ -317,9 +318,30 @@ QList<AbstractProperty> dynamicPropertiesFromNode(const ModelNode &node)
|
||||
return dynamicProperties;
|
||||
}
|
||||
|
||||
#ifdef QDS_USE_PROJECTSTORAGE
|
||||
QStringList availableSources(AbstractView *view)
|
||||
{
|
||||
if (!view->isAttached())
|
||||
return {};
|
||||
|
||||
QStringList sourceNodes;
|
||||
|
||||
for (const auto &metaInfo : view->model()->singletonMetaInfos())
|
||||
sourceNodes.push_back(metaInfo.displayName());
|
||||
|
||||
for (const ModelNode &modelNode : view->allModelNodes()) {
|
||||
if (auto id = modelNode.id(); !id.isEmpty())
|
||||
sourceNodes.append(id);
|
||||
}
|
||||
|
||||
std::sort(sourceNodes.begin(), sourceNodes.end());
|
||||
return sourceNodes;
|
||||
}
|
||||
#else
|
||||
QStringList availableSources(AbstractView *view)
|
||||
{
|
||||
QStringList sourceNodes;
|
||||
|
||||
for (const ModelNode &modelNode : view->allModelNodes()) {
|
||||
if (!modelNode.id().isEmpty())
|
||||
sourceNodes.append(modelNode.id());
|
||||
@@ -327,6 +349,7 @@ QStringList availableSources(AbstractView *view)
|
||||
std::sort(sourceNodes.begin(), sourceNodes.end());
|
||||
return singletonsFromView(view) + sourceNodes;
|
||||
}
|
||||
#endif
|
||||
|
||||
QStringList availableTargetProperties(const BindingProperty &bindingProperty)
|
||||
{
|
||||
@@ -351,6 +374,8 @@ QStringList availableTargetProperties(const BindingProperty &bindingProperty)
|
||||
return {};
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
ModelNode getNodeByIdOrParent(AbstractView *view, const QString &id, const ModelNode &targetNode)
|
||||
{
|
||||
if (id != QLatin1String("parent"))
|
||||
@@ -362,6 +387,35 @@ ModelNode getNodeByIdOrParent(AbstractView *view, const QString &id, const Model
|
||||
return {};
|
||||
}
|
||||
|
||||
#ifdef QDS_USE_PROJECTSTORAGE
|
||||
NodeMetaInfo singletonMetaInfoForId(const QString &id, AbstractView *view)
|
||||
{
|
||||
using Storage::Info::ExportedTypeName;
|
||||
const auto model = view->model();
|
||||
|
||||
if (!model)
|
||||
return {};
|
||||
|
||||
const Utils::SmallString name = id;
|
||||
|
||||
const auto singletonMetaInfos = model->singletonMetaInfos();
|
||||
|
||||
const auto sourceId = model->fileUrlSourceId();
|
||||
|
||||
auto found = std::ranges::find_if(singletonMetaInfos, [&](const auto &metaInfo) {
|
||||
auto exportedTypeNames = metaInfo.exportedTypeNamesForSourceId(sourceId);
|
||||
return std::ranges::find(exportedTypeNames, name, &ExportedTypeName::name)
|
||||
!= exportedTypeNames.end();
|
||||
});
|
||||
|
||||
if (found == singletonMetaInfos.end())
|
||||
return {};
|
||||
|
||||
return *found;
|
||||
}
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
QStringList availableSourceProperties(const QString &id,
|
||||
const BindingProperty &targetProperty,
|
||||
AbstractView *view)
|
||||
@@ -378,6 +432,15 @@ QStringList availableSourceProperties(const QString &id,
|
||||
|
||||
QStringList possibleProperties;
|
||||
if (!modelNode.isValid()) {
|
||||
#ifdef QDS_USE_PROJECTSTORAGE
|
||||
if (auto singletonMetaInfo = singletonMetaInfoForId(id, view)) {
|
||||
for (const auto &property : singletonMetaInfo.properties()) {
|
||||
if (metaInfoIsCompatible(targetType, property))
|
||||
possibleProperties.push_back(QString::fromUtf8(property.name()));
|
||||
}
|
||||
return possibleProperties;
|
||||
}
|
||||
#else
|
||||
QStringList singletons = singletonsFromView(view);
|
||||
if (singletons.contains(id)) {
|
||||
for (const auto &property : propertiesFromSingleton(id, view)) {
|
||||
@@ -386,6 +449,7 @@ QStringList availableSourceProperties(const QString &id,
|
||||
}
|
||||
return possibleProperties;
|
||||
}
|
||||
#endif
|
||||
qCWarning(ConnectionEditorLog) << __FUNCTION__ << "invalid model node:" << id;
|
||||
return {};
|
||||
}
|
||||
|
@@ -40,8 +40,10 @@ QVariant defaultValueForType(const TypeName &type);
|
||||
QString defaultExpressionForType(const TypeName &type);
|
||||
std::pair<QString, QString> splitExpression(const QString &expression);
|
||||
|
||||
#ifndef QDS_USE_PROJECTSTORAGE
|
||||
QStringList singletonsFromView(AbstractView *view);
|
||||
std::vector<PropertyMetaInfo> propertiesFromSingleton(const QString &name, AbstractView *view);
|
||||
#endif
|
||||
|
||||
QList<AbstractProperty> dynamicPropertiesFromNode(const ModelNode &node);
|
||||
QStringList availableSources(AbstractView *view);
|
||||
|
@@ -40,10 +40,10 @@ const char defaultCondition[] = "condition";
|
||||
QStringList propertyNameListToStringList(const QmlDesigner::PropertyNameList &propertyNameList)
|
||||
{
|
||||
QStringList stringList;
|
||||
stringList.reserve(propertyNameList.size());
|
||||
for (const QmlDesigner::PropertyName &propertyName : propertyNameList)
|
||||
stringList << QString::fromUtf8(propertyName);
|
||||
stringList.push_back(QString::fromUtf8(propertyName));
|
||||
|
||||
stringList.removeDuplicates();
|
||||
return stringList;
|
||||
}
|
||||
|
||||
@@ -206,6 +206,62 @@ void ConnectionModel::updateSignalName(int rowNumber)
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
#ifdef QDS_USE_PROJECTSTORAGE
|
||||
bool isSingleton(AbstractView *view, bool isAlias, QStringView newTarget)
|
||||
{
|
||||
using Storage::Info::ExportedTypeName;
|
||||
|
||||
auto model = view->model();
|
||||
|
||||
if (!model)
|
||||
return false;
|
||||
|
||||
const auto sourceId = model->fileUrlSourceId();
|
||||
const Utils::SmallString name = newTarget;
|
||||
const Utils::SmallString aliasName = newTarget.split(u'.').front();
|
||||
auto hasTargetExportedTypeName = [&](const auto &metaInfo) {
|
||||
const auto exportedTypeNames = metaInfo.exportedTypeNamesForSourceId(sourceId);
|
||||
if (std::ranges::find(exportedTypeNames, name, &ExportedTypeName::name)
|
||||
!= exportedTypeNames.end())
|
||||
return true;
|
||||
if (isAlias) {
|
||||
if (std::ranges::find(exportedTypeNames, aliasName, &ExportedTypeName::name)
|
||||
!= exportedTypeNames.end())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto singletonMetaInfos = model->singletonMetaInfos();
|
||||
return std::ranges::find_if(singletonMetaInfos, hasTargetExportedTypeName)
|
||||
!= singletonMetaInfos.end();
|
||||
}
|
||||
#else
|
||||
bool isSingleton(AbstractView *view, bool isAlias, const QString &newTarget)
|
||||
{
|
||||
if (RewriterView *rv = view->rewriterView()) {
|
||||
for (const QmlTypeData &data : rv->getQMLTypes()) {
|
||||
if (!data.typeName.isEmpty()) {
|
||||
if (data.typeName == newTarget) {
|
||||
if (view->model()->metaInfo(data.typeName.toUtf8()).isValid())
|
||||
return true;
|
||||
|
||||
} else if (isAlias) {
|
||||
if (data.typeName == newTarget.split(".").constFirst()) {
|
||||
if (view->model()->metaInfo(data.typeName.toUtf8()).isValid())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
void ConnectionModel::updateTargetNode(int rowNumber)
|
||||
{
|
||||
SignalHandlerProperty signalHandlerProperty = signalHandlerPropertyForRow(rowNumber);
|
||||
@@ -213,27 +269,7 @@ void ConnectionModel::updateTargetNode(int rowNumber)
|
||||
ModelNode connectionNode = signalHandlerProperty.parentModelNode();
|
||||
|
||||
const bool isAlias = newTarget.contains(".");
|
||||
bool isSingleton = false;
|
||||
|
||||
if (RewriterView* rv = connectionView()->rewriterView()) {
|
||||
for (const QmlTypeData &data : rv->getQMLTypes()) {
|
||||
if (!data.typeName.isEmpty()) {
|
||||
if (data.typeName == newTarget) {
|
||||
if (connectionView()->model()->metaInfo(data.typeName.toUtf8()).isValid()) {
|
||||
isSingleton = true;
|
||||
break;
|
||||
}
|
||||
} else if (isAlias) {
|
||||
if (data.typeName == newTarget.split(".").constFirst()) {
|
||||
if (connectionView()->model()->metaInfo(data.typeName.toUtf8()).isValid()) {
|
||||
isSingleton = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool isSingleton = QmlDesigner::isSingleton(m_connectionView, isAlias, newTarget);
|
||||
|
||||
if (!newTarget.isEmpty()) {
|
||||
//if it's a singleton, then let's reparent connections to rootNode,
|
||||
@@ -595,78 +631,96 @@ QStringList ConnectionModel::getflowActionTriggerForRow(int row) const
|
||||
return stringList;
|
||||
}
|
||||
|
||||
namespace {}
|
||||
|
||||
QStringList ConnectionModel::getPossibleSignalsForConnection(const ModelNode &connection) const
|
||||
{
|
||||
if (!connection)
|
||||
return {};
|
||||
|
||||
QStringList stringList;
|
||||
|
||||
auto getAliasMetaSignals = [&](QString aliasPart, NodeMetaInfo metaInfo) {
|
||||
if (metaInfo.isValid() && metaInfo.hasProperty(aliasPart.toUtf8())) {
|
||||
NodeMetaInfo propertyMetaInfo = metaInfo.property(aliasPart.toUtf8()).propertyType();
|
||||
if (propertyMetaInfo.isValid()) {
|
||||
return propertyNameListToStringList(propertyMetaInfo.signalNames());
|
||||
}
|
||||
}
|
||||
return QStringList();
|
||||
auto getAliasMetaSignals = [&](PropertyNameView aliasPart, NodeMetaInfo metaInfo) -> QStringList {
|
||||
if (NodeMetaInfo propertyMetaInfo = metaInfo.property(aliasPart).propertyType())
|
||||
return propertyNameListToStringList(propertyMetaInfo.signalNames());
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
if (connection.isValid()) {
|
||||
//separate check for singletons
|
||||
if (connection.hasBindingProperty("target")) {
|
||||
const BindingProperty bp = connection.bindingProperty("target");
|
||||
//separate check for singletons
|
||||
if (const BindingProperty bp = connection.bindingProperty("target")) {
|
||||
#ifdef QDS_USE_PROJECTSTORAGE
|
||||
if (auto model = m_connectionView->model()) {
|
||||
const Utils::SmallString bindExpression = bp.expression();
|
||||
using Storage::Info::ExportedTypeName;
|
||||
const auto sourceId = model->fileUrlSourceId();
|
||||
for (const auto &metaInfo : model->singletonMetaInfos()) {
|
||||
const auto exportedTypeNames = metaInfo.exportedTypeNamesForSourceId(sourceId);
|
||||
if (std::ranges::find(exportedTypeNames, bindExpression, &ExportedTypeName::name)
|
||||
!= exportedTypeNames.end()) {
|
||||
stringList.append(propertyNameListToStringList(metaInfo.signalNames()));
|
||||
} else {
|
||||
std::string_view expression = bindExpression;
|
||||
auto index = expression.find('.');
|
||||
if (index == std::string_view::npos)
|
||||
continue;
|
||||
|
||||
if (bp.isValid()) {
|
||||
const QString bindExpression = bp.expression();
|
||||
expression.remove_prefix(index);
|
||||
|
||||
if (const RewriterView * const rv = connectionView()->rewriterView()) {
|
||||
for (const QmlTypeData &data : rv->getQMLTypes()) {
|
||||
if (!data.typeName.isEmpty()) {
|
||||
if (data.typeName == bindExpression) {
|
||||
NodeMetaInfo metaInfo = connectionView()->model()->metaInfo(data.typeName.toUtf8());
|
||||
if (metaInfo.isValid()) {
|
||||
stringList << propertyNameListToStringList(metaInfo.signalNames());
|
||||
break;
|
||||
}
|
||||
} else if (bindExpression.contains(".")) {
|
||||
//if it doesn't fit the same name, maybe it's an alias?
|
||||
QStringList expression = bindExpression.split(".");
|
||||
if ((expression.size() > 1) && (expression.constFirst() == data.typeName)) {
|
||||
expression.removeFirst();
|
||||
stringList.append(getAliasMetaSignals(expression, metaInfo));
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
const QString bindExpression = bp.expression();
|
||||
|
||||
stringList << getAliasMetaSignals(
|
||||
expression.join("."),
|
||||
connectionView()->model()->metaInfo(data.typeName.toUtf8()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (const RewriterView *const rv = connectionView()->rewriterView()) {
|
||||
for (const QmlTypeData &data : rv->getQMLTypes()) {
|
||||
if (!data.typeName.isEmpty()) {
|
||||
if (data.typeName == bindExpression) {
|
||||
NodeMetaInfo metaInfo = connectionView()->model()->metaInfo(
|
||||
data.typeName.toUtf8());
|
||||
if (metaInfo.isValid()) {
|
||||
stringList << propertyNameListToStringList(metaInfo.signalNames());
|
||||
break;
|
||||
}
|
||||
} else if (bindExpression.contains(".")) {
|
||||
//if it doesn't fit the same name, maybe it's an alias?
|
||||
QStringList expression = bindExpression.split(".");
|
||||
if ((expression.size() > 1) && (expression.constFirst() == data.typeName)) {
|
||||
expression.removeFirst();
|
||||
|
||||
stringList << getAliasMetaSignals(expression.join(".").toUtf8(),
|
||||
connectionView()->model()->metaInfo(
|
||||
data.typeName.toUtf8()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
std::ranges::sort(stringList);
|
||||
stringList.erase(std::ranges::unique(stringList).begin(), stringList.end());
|
||||
}
|
||||
|
||||
ModelNode targetNode = getTargetNodeForConnection(connection);
|
||||
if (targetNode.isValid() && targetNode.metaInfo().isValid()) {
|
||||
stringList.append(propertyNameListToStringList(targetNode.metaInfo().signalNames()));
|
||||
} else {
|
||||
//most likely it's component's internal alias:
|
||||
ModelNode targetNode = getTargetNodeForConnection(connection);
|
||||
if (auto metaInfo = targetNode.metaInfo()) {
|
||||
stringList.append(propertyNameListToStringList(metaInfo.signalNames()));
|
||||
} else {
|
||||
//most likely it's component's internal alias:
|
||||
|
||||
if (connection.hasBindingProperty("target")) {
|
||||
const BindingProperty bp = connection.bindingProperty("target");
|
||||
|
||||
if (bp.isValid()) {
|
||||
QStringList expression = bp.expression().split(".");
|
||||
if (expression.size() > 1) {
|
||||
const QString itemId = expression.constFirst();
|
||||
if (connectionView()->hasId(itemId)) {
|
||||
ModelNode parentItem = connectionView()->modelNodeForId(itemId);
|
||||
if (parentItem.isValid()
|
||||
&& parentItem.hasMetaInfo()
|
||||
&& parentItem.metaInfo().isValid()) {
|
||||
expression.removeFirst();
|
||||
stringList << getAliasMetaSignals(expression.join("."),
|
||||
parentItem.metaInfo());
|
||||
}
|
||||
}
|
||||
if (const BindingProperty bp = connection.bindingProperty("target")) {
|
||||
QStringList expression = bp.expression().split(".");
|
||||
if (expression.size() > 1) {
|
||||
const QString itemId = expression.constFirst();
|
||||
if (connectionView()->hasId(itemId)) {
|
||||
ModelNode parentItem = connectionView()->modelNodeForId(itemId);
|
||||
if (parentItem.isValid() && parentItem.hasMetaInfo()
|
||||
&& parentItem.metaInfo().isValid()) {
|
||||
expression.removeFirst();
|
||||
stringList << getAliasMetaSignals(expression.join(".").toUtf8(),
|
||||
parentItem.metaInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "connectionview.h"
|
||||
|
||||
#include "backendmodel.h"
|
||||
#include "bindingmodel.h"
|
||||
#include "connectionmodel.h"
|
||||
#include "dynamicpropertiesmodel.h"
|
||||
@@ -146,7 +145,6 @@ struct ConnectionView::ConnectionViewData
|
||||
: connectionModel{view}
|
||||
, bindingModel{view}
|
||||
, dynamicPropertiesModel{false, view}
|
||||
, backendModel{view}
|
||||
, propertyTreeModel{view}
|
||||
, connectionViewQuickWidget{Utils::makeUniqueObjectPtr<ConnectionViewQuickWidget>(
|
||||
view, &connectionModel, &bindingModel, &dynamicPropertiesModel)}
|
||||
@@ -155,7 +153,6 @@ struct ConnectionView::ConnectionViewData
|
||||
ConnectionModel connectionModel;
|
||||
BindingModel bindingModel;
|
||||
DynamicPropertiesModel dynamicPropertiesModel;
|
||||
BackendModel backendModel;
|
||||
PropertyTreeModel propertyTreeModel;
|
||||
int currentIndex = 0;
|
||||
|
||||
@@ -177,7 +174,6 @@ void ConnectionView::modelAttached(Model *model)
|
||||
d->bindingModel.reset();
|
||||
d->dynamicPropertiesModel.reset();
|
||||
d->connectionModel.resetModel();
|
||||
d->backendModel.resetModel();
|
||||
}
|
||||
|
||||
void ConnectionView::modelAboutToBeDetached(Model *model)
|
||||
@@ -249,8 +245,6 @@ void ConnectionView::variantPropertiesChanged(const QList<VariantProperty> &prop
|
||||
for (const VariantProperty &variantProperty : propertyList) {
|
||||
if (variantProperty.isDynamic())
|
||||
d->dynamicPropertiesModel.updateItem(variantProperty);
|
||||
if (variantProperty.isDynamic() && variantProperty.parentModelNode().isRootNode())
|
||||
d->backendModel.resetModel();
|
||||
|
||||
d->connectionModel.variantPropertyChanged(variantProperty);
|
||||
|
||||
@@ -265,8 +259,6 @@ void ConnectionView::bindingPropertiesChanged(const QList<BindingProperty> &prop
|
||||
d->bindingModel.updateItem(bindingProperty);
|
||||
if (bindingProperty.isDynamic())
|
||||
d->dynamicPropertiesModel.updateItem(bindingProperty);
|
||||
if (bindingProperty.isDynamic() && bindingProperty.parentModelNode().isRootNode())
|
||||
d->backendModel.resetModel();
|
||||
|
||||
d->connectionModel.bindingPropertyChanged(bindingProperty);
|
||||
|
||||
@@ -288,11 +280,6 @@ void ConnectionView::selectedNodesChanged(const QList<ModelNode> & selectedNodeL
|
||||
d->dynamicPropertiesModel.reset();
|
||||
}
|
||||
|
||||
void ConnectionView::importsChanged(const Imports & /*addedImports*/, const Imports & /*removedImports*/)
|
||||
{
|
||||
d->backendModel.resetModel();
|
||||
}
|
||||
|
||||
void ConnectionView::currentStateChanged(const ModelNode &)
|
||||
{
|
||||
d->dynamicPropertiesModel.reset();
|
||||
@@ -332,11 +319,6 @@ DynamicPropertiesModel *ConnectionView::dynamicPropertiesModel() const
|
||||
return &d->dynamicPropertiesModel;
|
||||
}
|
||||
|
||||
BackendModel *ConnectionView::backendModel() const
|
||||
{
|
||||
return &d->backendModel;
|
||||
}
|
||||
|
||||
int ConnectionView::currentIndex() const
|
||||
{
|
||||
return d->currentIndex;
|
||||
|
@@ -21,7 +21,6 @@ class ConnectionViewWidget;
|
||||
class BindingModel;
|
||||
class ConnectionModel;
|
||||
class DynamicPropertiesModel;
|
||||
class BackendModel;
|
||||
class ConnectionViewQuickWidget;
|
||||
class PropertyTreeModel;
|
||||
class PropertyListProxyModel;
|
||||
@@ -55,8 +54,6 @@ public:
|
||||
void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
|
||||
const QList<ModelNode> &lastSelectedNodeList) override;
|
||||
|
||||
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||
|
||||
void currentStateChanged(const ModelNode &node) override;
|
||||
|
||||
WidgetInfo widgetInfo() override;
|
||||
@@ -67,7 +64,6 @@ public:
|
||||
|
||||
ConnectionModel *connectionModel() const;
|
||||
BindingModel *bindingModel() const;
|
||||
BackendModel *backendModel() const;
|
||||
|
||||
int currentIndex() const;
|
||||
void setCurrentIndex(int i);
|
||||
|
@@ -1208,6 +1208,7 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
|
||||
|
||||
QVector<MockupTypeContainer> mockupTypesVector;
|
||||
|
||||
#ifndef QDS_USE_PROJECTSTORAGE
|
||||
for (const QmlTypeData &cppTypeData : model()->rewriterView()->getQMLTypes()) {
|
||||
const QString versionString = cppTypeData.versionString;
|
||||
int majorVersion = -1;
|
||||
@@ -1242,6 +1243,7 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
|
||||
mockupTypesVector.append(mockupType);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
QString lastUsedLanguage;
|
||||
if (auto multiLanguageAspect = QmlProjectManager::QmlMultiLanguageAspect::current(m_currentTarget))
|
||||
|
@@ -117,7 +117,7 @@ public:
|
||||
|
||||
bool defaultPropertyIsComponent() const;
|
||||
|
||||
TypeName displayName() const;
|
||||
QString displayName() const;
|
||||
DEPRECATED_TYPENAME TypeName typeName() const;
|
||||
DEPRECATED_TYPENAME TypeName simplifiedTypeName() const;
|
||||
DEPRECATED_VERSION_NUMBER int majorVersion() const;
|
||||
|
@@ -143,7 +143,9 @@ public:
|
||||
|
||||
QStringList autoComplete(const QString &text, int pos, bool explicitComplete = true);
|
||||
|
||||
#ifndef QDS_USE_PROJECTSTORAGE
|
||||
QList<QmlTypeData> getQMLTypes() const;
|
||||
#endif
|
||||
|
||||
void setWidgetStatusCallback(std::function<void(bool)> setWidgetStatusCallback);
|
||||
|
||||
|
@@ -2106,7 +2106,7 @@ bool NodeMetaInfo::defaultPropertyIsComponent() const
|
||||
}
|
||||
}
|
||||
|
||||
TypeName NodeMetaInfo::displayName() const
|
||||
QString NodeMetaInfo::displayName() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
@@ -1102,6 +1102,7 @@ QStringList RewriterView::autoComplete(const QString &text, int pos, bool explic
|
||||
return list;
|
||||
}
|
||||
|
||||
#ifndef QDS_USE_PROJECTSTORAGE
|
||||
QList<QmlTypeData> RewriterView::getQMLTypes() const
|
||||
{
|
||||
QList<QmlTypeData> qmlDataList;
|
||||
@@ -1127,6 +1128,7 @@ QList<QmlTypeData> RewriterView::getQMLTypes() const
|
||||
|
||||
return qmlDataList;
|
||||
}
|
||||
#endif
|
||||
|
||||
void RewriterView::setWidgetStatusCallback(std::function<void(bool)> setWidgetStatusCallback)
|
||||
{
|
||||
|
Reference in New Issue
Block a user