forked from qt-creator/qt-creator
QmlDesigner: Fix issues with Components and Repeaters
- Fixed state preview rendering by deparenting nodes under component wraps. - Ensure state preview image is always clipped to root item. The state preview bounding box broke when Repeater was direct child of root and had delegate with rotation. - Allow dragging items under Repeater to create implicit component. - Allow dragging Components under Repeater. - Do not ask for target property when Component is dragged under any node. - Update nodeSource properly when reparenting implicit component or removing last child of a Component item. - Fixed scene update when last child of a repeater is deleted/moved. Fixes: QDS-5197 Change-Id: Iaaf1745e25db3522ffc1dba7fd1b051da29f5aec Reviewed-by: Samuel Ghinet <samuel.ghinet@qt.io> Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
@@ -397,8 +397,19 @@ void NodeInstanceServer::reparentInstances(const QVector<ReparentContainer> &con
|
|||||||
if (hasInstanceForId(container.instanceId())) {
|
if (hasInstanceForId(container.instanceId())) {
|
||||||
ServerNodeInstance instance = instanceForId(container.instanceId());
|
ServerNodeInstance instance = instanceForId(container.instanceId());
|
||||||
if (instance.isValid()) {
|
if (instance.isValid()) {
|
||||||
instance.reparent(instanceForId(container.oldParentInstanceId()), container.oldParentProperty(),
|
ServerNodeInstance newParent = instanceForId(container.newParentInstanceId());
|
||||||
instanceForId(container.newParentInstanceId()), container.newParentProperty());
|
PropertyName newParentProperty = container.newParentProperty();
|
||||||
|
if (!isInformationServer()) {
|
||||||
|
// Children of the component wraps are left out of the node tree to avoid
|
||||||
|
// incorrectly rendering them
|
||||||
|
if (newParent.isComponentWrap()) {
|
||||||
|
newParent = {};
|
||||||
|
newParentProperty.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
instance.reparent(instanceForId(container.oldParentInstanceId()),
|
||||||
|
container.oldParentProperty(),
|
||||||
|
newParent, newParentProperty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -415,6 +415,16 @@ bool ObjectNodeInstance::isLockedInEditor() const
|
|||||||
return m_isLockedInEditor;
|
return m_isLockedInEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ObjectNodeInstance::isComponentWrap() const
|
||||||
|
{
|
||||||
|
return m_isComponentWrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectNodeInstance::setComponentWrap(bool wrap)
|
||||||
|
{
|
||||||
|
m_isComponentWrap = wrap;
|
||||||
|
}
|
||||||
|
|
||||||
void ObjectNodeInstance::setModifiedFlag(bool b)
|
void ObjectNodeInstance::setModifiedFlag(bool b)
|
||||||
{
|
{
|
||||||
m_isModified = b;
|
m_isModified = b;
|
||||||
@@ -732,6 +742,10 @@ QObject *ObjectNodeInstance::createComponentWrap(const QString &nodeSource, cons
|
|||||||
QQmlComponent *component = new QQmlComponent(context->engine());
|
QQmlComponent *component = new QQmlComponent(context->engine());
|
||||||
|
|
||||||
QByteArray data(nodeSource.toUtf8());
|
QByteArray data(nodeSource.toUtf8());
|
||||||
|
if (data.isEmpty()) {
|
||||||
|
// Add a fake root element as an empty component is not valid and crashes in some cases
|
||||||
|
data.append("QtObject{}");
|
||||||
|
}
|
||||||
data.prepend(importCode);
|
data.prepend(importCode);
|
||||||
component->setData(data, context->baseUrl().resolved(QUrl("createComponent.qml")));
|
component->setData(data, context->baseUrl().resolved(QUrl("createComponent.qml")));
|
||||||
QObject *object = component;
|
QObject *object = component;
|
||||||
|
|||||||
@@ -202,6 +202,9 @@ public:
|
|||||||
virtual void setLockedInEditor(bool b);
|
virtual void setLockedInEditor(bool b);
|
||||||
bool isLockedInEditor() const;
|
bool isLockedInEditor() const;
|
||||||
|
|
||||||
|
bool isComponentWrap() const;
|
||||||
|
void setComponentWrap(bool wrap);
|
||||||
|
|
||||||
void setModifiedFlag(bool b);
|
void setModifiedFlag(bool b);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -234,6 +237,7 @@ private:
|
|||||||
bool m_isModified = false;
|
bool m_isModified = false;
|
||||||
bool m_isLockedInEditor = false;
|
bool m_isLockedInEditor = false;
|
||||||
bool m_isHiddenInEditor = false;
|
bool m_isHiddenInEditor = false;
|
||||||
|
bool m_isComponentWrap = false;
|
||||||
static QHash<EnumerationName, QVariant> m_enumationValueHash;
|
static QHash<EnumerationName, QVariant> m_enumationValueHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -199,11 +199,24 @@ void Qt5NodeInstanceServer::markRepeaterParentDirty(qint32 id) const
|
|||||||
if (!hasInstanceForId(id))
|
if (!hasInstanceForId(id))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If a Repeater instance was moved/removed, the old parent must be marked dirty to rerender it
|
|
||||||
ServerNodeInstance instance = instanceForId(id);
|
ServerNodeInstance instance = instanceForId(id);
|
||||||
if (instance.isValid() && instance.isSubclassOf("QQuickRepeater") && instance.hasParent()) {
|
if (!instance.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
ServerNodeInstance parentInstance = instance.parent();
|
ServerNodeInstance parentInstance = instance.parent();
|
||||||
|
if (!parentInstance.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If a Repeater instance was moved/removed, the old parent must be marked dirty to rerender it
|
||||||
|
const QByteArray type("QQuickRepeater");
|
||||||
|
if (ServerNodeInstance::isSubclassOf(instance.internalObject(), type))
|
||||||
DesignerSupport::addDirty(parentInstance.rootQuickItem(), QQuickDesignerSupport::Content);
|
DesignerSupport::addDirty(parentInstance.rootQuickItem(), QQuickDesignerSupport::Content);
|
||||||
|
|
||||||
|
// Repeater's parent must also be dirtied when a child of a repeater was moved/removed.
|
||||||
|
if (ServerNodeInstance::isSubclassOf(parentInstance.internalObject(), type)) {
|
||||||
|
ServerNodeInstance parentsParent = parentInstance.parent();
|
||||||
|
if (parentsParent.isValid())
|
||||||
|
DesignerSupport::addDirty(parentsParent.rootQuickItem(), QQuickDesignerSupport::Content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -101,6 +101,10 @@ void Qt5PreviewNodeInstanceServer::changeState(const ChangeStateCommand &/*comma
|
|||||||
|
|
||||||
QImage Qt5PreviewNodeInstanceServer::renderPreviewImage()
|
QImage Qt5PreviewNodeInstanceServer::renderPreviewImage()
|
||||||
{
|
{
|
||||||
|
// Ensure the state preview image is always clipped properly to root item dimensions
|
||||||
|
if (auto rootItem = qobject_cast<QQuickItem *>(rootNodeInstance().internalObject()))
|
||||||
|
rootItem->setClip(true);
|
||||||
|
|
||||||
rootNodeInstance().updateDirtyNodeRecursive();
|
rootNodeInstance().updateDirtyNodeRecursive();
|
||||||
|
|
||||||
QRectF boundingRect = rootNodeInstance().boundingRect();
|
QRectF boundingRect = rootNodeInstance().boundingRect();
|
||||||
|
|||||||
@@ -769,6 +769,9 @@ void QuickItemNodeInstance::reparent(const ObjectNodeInstance::Pointer &oldParen
|
|||||||
|
|
||||||
ObjectNodeInstance::reparent(oldParentInstance, oldParentProperty, newParentInstance, newParentProperty);
|
ObjectNodeInstance::reparent(oldParentInstance, oldParentProperty, newParentInstance, newParentProperty);
|
||||||
|
|
||||||
|
if (!newParentInstance)
|
||||||
|
quickItem()->setParentItem(nullptr);
|
||||||
|
|
||||||
if (instanceIsValidLayoutable(newParentInstance, newParentProperty)) {
|
if (instanceIsValidLayoutable(newParentInstance, newParentProperty)) {
|
||||||
setInLayoutable(true);
|
setInLayoutable(true);
|
||||||
setMovable(false);
|
setMovable(false);
|
||||||
|
|||||||
@@ -150,6 +150,11 @@ bool ServerNodeInstance::holdsGraphical() const
|
|||||||
return m_nodeInstance->isQuickItem();
|
return m_nodeInstance->isQuickItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ServerNodeInstance::isComponentWrap() const
|
||||||
|
{
|
||||||
|
return m_nodeInstance->isComponentWrap();
|
||||||
|
}
|
||||||
|
|
||||||
void ServerNodeInstance::updateDirtyNodeRecursive()
|
void ServerNodeInstance::updateDirtyNodeRecursive()
|
||||||
{
|
{
|
||||||
m_nodeInstance->updateAllDirtyNodesRecursive();
|
m_nodeInstance->updateAllDirtyNodesRecursive();
|
||||||
@@ -280,6 +285,8 @@ ServerNodeInstance ServerNodeInstance::create(NodeInstanceServer *nodeInstanceSe
|
|||||||
|
|
||||||
instance.internalInstance()->setInstanceId(instanceContainer.instanceId());
|
instance.internalInstance()->setInstanceId(instanceContainer.instanceId());
|
||||||
|
|
||||||
|
instance.internalInstance()->setComponentWrap(componentWrap == WrapAsComponent);
|
||||||
|
|
||||||
instance.internalInstance()->initialize(instance.m_nodeInstance, instanceContainer.metaFlags());
|
instance.internalInstance()->initialize(instance.m_nodeInstance, instanceContainer.metaFlags());
|
||||||
|
|
||||||
// Handle hidden state to initialize pickable state
|
// Handle hidden state to initialize pickable state
|
||||||
|
|||||||
@@ -178,6 +178,8 @@ public:
|
|||||||
void updateDirtyNodeRecursive();
|
void updateDirtyNodeRecursive();
|
||||||
bool holdsGraphical() const;
|
bool holdsGraphical() const;
|
||||||
|
|
||||||
|
bool isComponentWrap() const;
|
||||||
|
|
||||||
private: // functions
|
private: // functions
|
||||||
ServerNodeInstance(const QSharedPointer<Internal::ObjectNodeInstance> &abstractInstance);
|
ServerNodeInstance(const QSharedPointer<Internal::ObjectNodeInstance> &abstractInstance);
|
||||||
|
|
||||||
|
|||||||
@@ -732,6 +732,10 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
|
|||||||
ModelNode targetNode = targetProperty.parentModelNode();
|
ModelNode targetNode = targetProperty.parentModelNode();
|
||||||
NodeMetaInfo metaInfo = targetNode.metaInfo();
|
NodeMetaInfo metaInfo = targetNode.metaInfo();
|
||||||
TypeName typeName = newModelNode.type();
|
TypeName typeName = newModelNode.type();
|
||||||
|
|
||||||
|
// Empty components are not supported and having one as property value is generally
|
||||||
|
// unstable, so let's not offer user to put a fresh Component into a property
|
||||||
|
if (typeName != "QtQml.Component") {
|
||||||
const PropertyNameList nameList = targetNode.metaInfo().directPropertyNames();
|
const PropertyNameList nameList = targetNode.metaInfo().directPropertyNames();
|
||||||
for (const auto &propertyName : nameList) {
|
for (const auto &propertyName : nameList) {
|
||||||
auto testType = metaInfo.propertyTypeName(propertyName);
|
auto testType = metaInfo.propertyTypeName(propertyName);
|
||||||
@@ -746,6 +750,7 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!validContainer) {
|
if (!validContainer) {
|
||||||
if (!showMatToCompInfo)
|
if (!showMatToCompInfo)
|
||||||
@@ -1087,7 +1092,9 @@ void NavigatorTreeModel::moveNodesInteractive(NodeAbstractProperty &parentProper
|
|||||||
&& !modelNode.isAncestorOf(parentProperty.parentModelNode())
|
&& !modelNode.isAncestorOf(parentProperty.parentModelNode())
|
||||||
&& (modelNode.metaInfo().isSubclassOf(propertyQmlType)
|
&& (modelNode.metaInfo().isSubclassOf(propertyQmlType)
|
||||||
|| propertyQmlType == "alias"
|
|| propertyQmlType == "alias"
|
||||||
|| parentProperty.name() == "data")) {
|
|| parentProperty.name() == "data"
|
||||||
|
|| (parentProperty.parentModelNode().metaInfo().defaultPropertyName() == parentProperty.name()
|
||||||
|
&& propertyQmlType == "<cpp>.QQmlComponent"))) {
|
||||||
//### todo: allowing alias is just a heuristic
|
//### todo: allowing alias is just a heuristic
|
||||||
//once the MetaInfo is part of instances we can do this right
|
//once the MetaInfo is part of instances we can do this right
|
||||||
|
|
||||||
@@ -1097,6 +1104,10 @@ void NavigatorTreeModel::moveNodesInteractive(NodeAbstractProperty &parentProper
|
|||||||
// When the actual reparenting happens, model will create the "data" property if
|
// When the actual reparenting happens, model will create the "data" property if
|
||||||
// it is missing.
|
// it is missing.
|
||||||
|
|
||||||
|
// We allow move even if target property type doesn't match, if the target property
|
||||||
|
// is the default property of the parent and is of Component type.
|
||||||
|
// In that case an implicit component will be created.
|
||||||
|
|
||||||
bool nodeCanBeMovedToParentProperty = removeModelNodeFromNodeProperty(parentProperty, modelNode);
|
bool nodeCanBeMovedToParentProperty = removeModelNodeFromNodeProperty(parentProperty, modelNode);
|
||||||
if (nodeCanBeMovedToParentProperty) {
|
if (nodeCanBeMovedToParentProperty) {
|
||||||
reparentModelNodeToNodeProperty(parentProperty, modelNode);
|
reparentModelNodeToNodeProperty(parentProperty, modelNode);
|
||||||
|
|||||||
@@ -1191,6 +1191,8 @@ void TextToModelMerger::syncNode(ModelNode &modelNode,
|
|||||||
|
|
||||||
if (isComponentType(typeName) || isImplicitComponent)
|
if (isComponentType(typeName) || isImplicitComponent)
|
||||||
setupComponentDelayed(modelNode, differenceHandler.isAmender());
|
setupComponentDelayed(modelNode, differenceHandler.isAmender());
|
||||||
|
else if (!modelNode.nodeSource().isEmpty() || modelNode.nodeSourceType() != ModelNode::NodeWithoutSource)
|
||||||
|
clearImplicitComponentDelayed(modelNode, differenceHandler.isAmender());
|
||||||
|
|
||||||
if (isCustomParserType(typeName))
|
if (isCustomParserType(typeName))
|
||||||
setupCustomParserNodeDelayed(modelNode, differenceHandler.isAmender());
|
setupCustomParserNodeDelayed(modelNode, differenceHandler.isAmender());
|
||||||
@@ -2079,18 +2081,23 @@ void TextToModelMerger::setupComponent(const ModelNode &node)
|
|||||||
|
|
||||||
QString componentText = m_rewriterView->extractText({node}).value(node);
|
QString componentText = m_rewriterView->extractText({node}).value(node);
|
||||||
|
|
||||||
if (componentText.isEmpty())
|
if (componentText.isEmpty() && node.nodeSource().isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QString result = extractComponentFromQml(componentText);
|
QString result = extractComponentFromQml(componentText);
|
||||||
|
|
||||||
if (result.isEmpty())
|
if (result.isEmpty() && node.nodeSource().isEmpty())
|
||||||
return; //No object definition found
|
return; //No object definition found
|
||||||
|
|
||||||
if (node.nodeSource() != result)
|
if (node.nodeSource() != result)
|
||||||
ModelNode(node).setNodeSource(result, ModelNode::NodeWithComponentSource);
|
ModelNode(node).setNodeSource(result, ModelNode::NodeWithComponentSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextToModelMerger::clearImplicitComponent(const ModelNode &node)
|
||||||
|
{
|
||||||
|
ModelNode(node).setNodeSource({}, ModelNode::NodeWithoutSource);
|
||||||
|
}
|
||||||
|
|
||||||
void TextToModelMerger::collectLinkErrors(QList<DocumentMessage> *errors, const ReadingContext &ctxt)
|
void TextToModelMerger::collectLinkErrors(QList<DocumentMessage> *errors, const ReadingContext &ctxt)
|
||||||
{
|
{
|
||||||
foreach (const QmlJS::DiagnosticMessage &diagnosticMessage, ctxt.diagnosticLinkMessages()) {
|
foreach (const QmlJS::DiagnosticMessage &diagnosticMessage, ctxt.diagnosticLinkMessages()) {
|
||||||
@@ -2237,9 +2244,9 @@ void TextToModelMerger::addIsoIconQrcMapping(const QUrl &fileUrl)
|
|||||||
} while (dir.cdUp());
|
} while (dir.cdUp());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextToModelMerger::setupComponentDelayed(const ModelNode &node, bool synchron)
|
void TextToModelMerger::setupComponentDelayed(const ModelNode &node, bool synchronous)
|
||||||
{
|
{
|
||||||
if (synchron) {
|
if (synchronous) {
|
||||||
setupComponent(node);
|
setupComponent(node);
|
||||||
} else {
|
} else {
|
||||||
m_setupComponentList.insert(node);
|
m_setupComponentList.insert(node);
|
||||||
@@ -2254,7 +2261,7 @@ void TextToModelMerger::setupCustomParserNode(const ModelNode &node)
|
|||||||
|
|
||||||
QString modelText = m_rewriterView->extractText({node}).value(node);
|
QString modelText = m_rewriterView->extractText({node}).value(node);
|
||||||
|
|
||||||
if (modelText.isEmpty())
|
if (modelText.isEmpty() && node.nodeSource().isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (node.nodeSource() != modelText)
|
if (node.nodeSource() != modelText)
|
||||||
@@ -2262,11 +2269,11 @@ void TextToModelMerger::setupCustomParserNode(const ModelNode &node)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextToModelMerger::setupCustomParserNodeDelayed(const ModelNode &node, bool synchron)
|
void TextToModelMerger::setupCustomParserNodeDelayed(const ModelNode &node, bool synchronous)
|
||||||
{
|
{
|
||||||
Q_ASSERT(isCustomParserType(node.type()));
|
Q_ASSERT(isCustomParserType(node.type()));
|
||||||
|
|
||||||
if (synchron) {
|
if (synchronous) {
|
||||||
setupCustomParserNode(node);
|
setupCustomParserNode(node);
|
||||||
} else {
|
} else {
|
||||||
m_setupCustomParserList.insert(node);
|
m_setupCustomParserList.insert(node);
|
||||||
@@ -2274,15 +2281,32 @@ void TextToModelMerger::setupCustomParserNodeDelayed(const ModelNode &node, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextToModelMerger::clearImplicitComponentDelayed(const ModelNode &node, bool synchronous)
|
||||||
|
{
|
||||||
|
Q_ASSERT(!isComponentType(node.type()));
|
||||||
|
|
||||||
|
if (synchronous) {
|
||||||
|
clearImplicitComponent(node);
|
||||||
|
} else {
|
||||||
|
m_clearImplicitComponentList.insert(node);
|
||||||
|
m_setupTimer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TextToModelMerger::delayedSetup()
|
void TextToModelMerger::delayedSetup()
|
||||||
{
|
{
|
||||||
foreach (const ModelNode node, m_setupComponentList)
|
for (const ModelNode &node : std::as_const(m_setupComponentList))
|
||||||
setupComponent(node);
|
setupComponent(node);
|
||||||
|
|
||||||
foreach (const ModelNode node, m_setupCustomParserList)
|
for (const ModelNode &node : std::as_const(m_setupCustomParserList))
|
||||||
setupCustomParserNode(node);
|
setupCustomParserNode(node);
|
||||||
|
|
||||||
|
for (const ModelNode &node : std::as_const(m_clearImplicitComponentList))
|
||||||
|
clearImplicitComponent(node);
|
||||||
|
|
||||||
m_setupCustomParserList.clear();
|
m_setupCustomParserList.clear();
|
||||||
m_setupComponentList.clear();
|
m_setupComponentList.clear();
|
||||||
|
m_clearImplicitComponentList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<QPair<QString, QString> > TextToModelMerger::qrcMapping() const
|
QSet<QPair<QString, QString> > TextToModelMerger::qrcMapping() const
|
||||||
|
|||||||
@@ -128,8 +128,9 @@ public:
|
|||||||
ReadingContext *context,
|
ReadingContext *context,
|
||||||
DifferenceHandler &differenceHandler);
|
DifferenceHandler &differenceHandler);
|
||||||
|
|
||||||
void setupComponentDelayed(const ModelNode &node, bool synchron);
|
void setupComponentDelayed(const ModelNode &node, bool synchronous);
|
||||||
void setupCustomParserNodeDelayed(const ModelNode &node, bool synchron);
|
void setupCustomParserNodeDelayed(const ModelNode &node, bool synchronous);
|
||||||
|
void clearImplicitComponentDelayed(const ModelNode &node, bool synchronous);
|
||||||
|
|
||||||
void delayedSetup();
|
void delayedSetup();
|
||||||
|
|
||||||
@@ -140,6 +141,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void setupCustomParserNode(const ModelNode &node);
|
void setupCustomParserNode(const ModelNode &node);
|
||||||
void setupComponent(const ModelNode &node);
|
void setupComponent(const ModelNode &node);
|
||||||
|
void clearImplicitComponent(const ModelNode &node);
|
||||||
void collectLinkErrors(QList<DocumentMessage> *errors, const ReadingContext &ctxt);
|
void collectLinkErrors(QList<DocumentMessage> *errors, const ReadingContext &ctxt);
|
||||||
void collectImportErrors(QList<DocumentMessage> *errors);
|
void collectImportErrors(QList<DocumentMessage> *errors);
|
||||||
void collectSemanticErrorsAndWarnings(QList<DocumentMessage> *errors,
|
void collectSemanticErrorsAndWarnings(QList<DocumentMessage> *errors,
|
||||||
@@ -163,6 +165,7 @@ private:
|
|||||||
QTimer m_setupTimer;
|
QTimer m_setupTimer;
|
||||||
QSet<ModelNode> m_setupComponentList;
|
QSet<ModelNode> m_setupComponentList;
|
||||||
QSet<ModelNode> m_setupCustomParserList;
|
QSet<ModelNode> m_setupCustomParserList;
|
||||||
|
QSet<ModelNode> m_clearImplicitComponentList;
|
||||||
QmlJS::ViewerContext m_vContext;
|
QmlJS::ViewerContext m_vContext;
|
||||||
QSet<QPair<QString, QString> > m_qrcMapping;
|
QSet<QPair<QString, QString> > m_qrcMapping;
|
||||||
QSet<QmlJS::ImportKey> m_possibleImportKeys;
|
QSet<QmlJS::ImportKey> m_possibleImportKeys;
|
||||||
|
|||||||
Reference in New Issue
Block a user