diff --git a/src/plugins/qmldesigner/components/integration/componentaction.cpp b/src/plugins/qmldesigner/components/integration/componentaction.cpp index fb09d10a983..cc7d30b4415 100644 --- a/src/plugins/qmldesigner/components/integration/componentaction.cpp +++ b/src/plugins/qmldesigner/components/integration/componentaction.cpp @@ -39,30 +39,17 @@ namespace QmlDesigner { -ComponentAction::ComponentAction(QObject *parent) - : QWidgetAction(parent), - m_componentView(new ComponentView(this)) +ComponentAction::ComponentAction(ComponentView *componentView) + : QWidgetAction(componentView), + m_componentView(componentView) { } -void ComponentAction::setModel(Model* model) -{ - if (model == m_componentView->model()) - return; - - blockSignals(true); - - if (model) - model->attachView(m_componentView.data()); - else if (m_componentView->model()) - m_componentView->model()->detachView(m_componentView.data()); - - blockSignals(false); -} - QWidget *ComponentAction::createWidget(QWidget *parent) { QComboBox *comboBox = new QComboBox(parent); + comboBox->setMinimumWidth(120); + comboBox->setToolTip(tr("Edit sub components defined in this file")); comboBox->setModel(m_componentView->standardItemModel()); connect(comboBox, SIGNAL(currentIndexChanged(int)), SLOT(emitCurrentComponentChanged(int))); diff --git a/src/plugins/qmldesigner/components/integration/componentaction.h b/src/plugins/qmldesigner/components/integration/componentaction.h index f1a142eab09..acae3e75f3a 100644 --- a/src/plugins/qmldesigner/components/integration/componentaction.h +++ b/src/plugins/qmldesigner/components/integration/componentaction.h @@ -50,8 +50,7 @@ class ComponentAction : public QWidgetAction { Q_OBJECT public: - ComponentAction(QObject *parent); - void setModel(Model* model); + ComponentAction(ComponentView *componentView); protected: QWidget *createWidget(QWidget *parent); diff --git a/src/plugins/qmldesigner/components/integration/componentview.cpp b/src/plugins/qmldesigner/components/integration/componentview.cpp index af7d430b516..bfc0a1cffb9 100644 --- a/src/plugins/qmldesigner/components/integration/componentview.cpp +++ b/src/plugins/qmldesigner/components/integration/componentview.cpp @@ -31,9 +31,11 @@ **************************************************************************/ #include "componentview.h" +#include "componentaction.h" #include #include +#include #include // silence gcc warnings about unused parameters @@ -43,7 +45,8 @@ namespace QmlDesigner { ComponentView::ComponentView(QObject *parent) : AbstractView(parent), m_standardItemModel(new QStandardItemModel(this)), - m_listChanged(false) + m_listChanged(false), + m_componentAction(new ComponentAction(this)) { } @@ -56,6 +59,7 @@ void ComponentView::nodeAboutToBeRemoved(const ModelNode &removedNode) if (item->data(ModelNodeRole).value() == removedNode) m_standardItemModel->removeRow(index); } + searchForComponentAndRemoveFromList(removedNode); } QStandardItemModel *ComponentView::standardItemModel() const @@ -86,17 +90,29 @@ void ComponentView::modelAttached(Model *model) if (AbstractView::model() == model) return; + bool block = m_componentAction->blockSignals(true); + m_standardItemModel->clear(); + AbstractView::modelAttached(model); Q_ASSERT(model->masterModel()); appendWholeDocumentAsComponent(); searchForComponentAndAddToList(rootModelNode()); + + m_componentAction->blockSignals(block); } void ComponentView::modelAboutToBeDetached(Model *model) { + bool block = m_componentAction->blockSignals(true); m_standardItemModel->clear(); AbstractView::modelAboutToBeDetached(model); + m_componentAction->blockSignals(block); +} + +ComponentAction *ComponentView::action() +{ + return m_componentAction; } void ComponentView::nodeCreated(const ModelNode &createdNode) @@ -112,48 +128,59 @@ void ComponentView::searchForComponentAndAddToList(const ModelNode &node) foreach (const ModelNode &childNode, nodeList) { - if (childNode.type() == "Qt/Component") { + if (childNode.type() == "QtQuick.Component") { if (!childNode.id().isEmpty()) { QStandardItem *item = new QStandardItem(childNode.id()); item->setData(QVariant::fromValue(childNode), ModelNodeRole); item->setEditable(false); m_standardItemModel->appendRow(item); + } else { + QString description; + if (!childNode.parentProperty().parentModelNode().id().isEmpty()) + description = childNode.parentProperty().parentModelNode().id() + QLatin1Char(' '); + else + description = childNode.parentProperty().parentModelNode().simplifiedTypeName() + QLatin1Char(' '); + description += childNode.parentProperty().name(); + QStandardItem *item = new QStandardItem(description); + item->setData(QVariant::fromValue(childNode), ModelNodeRole); + item->setEditable(false); + m_standardItemModel->appendRow(item); } } else if (node.metaInfo().isValid() && node.metaInfo().isComponent() && !m_componentList.contains(node.type())) { m_componentList.append(node.type()); m_componentList.sort(); m_listChanged = true; - } + } } } -void ComponentView::nodeRemoved(const ModelNode & /*removedNode*/, const NodeAbstractProperty & /*parentProperty*/, PropertyChangeFlags /*propertyChange*/) +void ComponentView::nodeRemoved(const ModelNode & /* removedNode */, const NodeAbstractProperty & /*parentProperty*/, PropertyChangeFlags /*propertyChange*/) { - } -//void ComponentView::searchForComponentAndRemoveFromList(const ModelNode &node) -//{ -// QList nodeList; -// nodeList.append(node); -// nodeList.append(node.allSubModelNodes()); -// -// -// foreach (const ModelNode &childNode, nodeList) { -// if (node.type() == "Qt/Component") { -// if (!node.id().isEmpty()) { -// for(int row = 0; row < m_standardItemModel->rowCount(); row++) { -// if (m_standardItemModel->item(row)->text() == node.id()) -// m_standardItemModel->removeRow(row); -// } -// } -// } else if (node.metaInfo().isComponent() && !m_componentList.contains(node.type())) { -// m_componentList.append(node.type()); -// m_componentList.sort(); -// m_listChanged = true; -// } -// } -//} +void ComponentView::searchForComponentAndRemoveFromList(const ModelNode &node) +{ + QList nodeList; + nodeList.append(node); + nodeList.append(node.allSubModelNodes()); + + + foreach (const ModelNode &childNode, nodeList) { + if (childNode.type() == "QtQuick.Component") { + if (!childNode.id().isEmpty()) { + for (int row = 0; row < m_standardItemModel->rowCount(); row++) { + if (m_standardItemModel->item(row)->text() == childNode.id()) + m_standardItemModel->removeRow(row); + } + } + } else if (node.metaInfo().isComponent() && !m_componentList.contains(childNode.type())) { + m_componentList.append(childNode.type()); + m_componentList.sort(); + m_listChanged = true; + } + } +} + void ComponentView::nodeAboutToBeReparented(const ModelNode &/*node*/, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {} void ComponentView::nodeReparented(const ModelNode &/*node*/, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {} void ComponentView::nodeIdChanged(const ModelNode& /*node*/, const QString& /*newId*/, const QString& /*oldId*/) {} diff --git a/src/plugins/qmldesigner/components/integration/componentview.h b/src/plugins/qmldesigner/components/integration/componentview.h index 8798e624daf..63c80f12ad9 100644 --- a/src/plugins/qmldesigner/components/integration/componentview.h +++ b/src/plugins/qmldesigner/components/integration/componentview.h @@ -44,6 +44,8 @@ QT_END_NAMESPACE namespace QmlDesigner { +class ComponentAction; + class ComponentView : public AbstractView { Q_OBJECT @@ -59,6 +61,8 @@ public: void modelAttached(Model *model); void modelAboutToBeDetached(Model *model); + ComponentAction *action(); + void nodeCreated(const ModelNode &createdNode); void nodeAboutToBeRemoved(const ModelNode &removedNode); void nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange); @@ -107,13 +111,14 @@ signals: private: //functions void updateModel(); void searchForComponentAndAddToList(const ModelNode &node); -// void searchForComponentAndRemoveFromList(const ModelNode &node); + void searchForComponentAndRemoveFromList(const ModelNode &node); void appendWholeDocumentAsComponent(); private: QStringList m_componentList; QStandardItemModel *m_standardItemModel; bool m_listChanged; + ComponentAction *m_componentAction; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp b/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp index 617fc3363da..11f4ddee1b4 100644 --- a/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp @@ -48,12 +48,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include @@ -97,6 +97,7 @@ public: QWeakPointer statesEditorView; QWeakPointer stackedWidget; QWeakPointer nodeInstanceView; + QWeakPointer componentView; QWeakPointer model; QWeakPointer subComponentModel; @@ -112,7 +113,6 @@ public: QUrl searchPath; bool documentLoaded; bool syncBlocked; - QWeakPointer componentAction; }; @@ -256,6 +256,12 @@ void DesignDocumentController::setNodeInstanceView(NodeInstanceView *nodeInstanc m_d->nodeInstanceView = nodeInstanceView; } +void DesignDocumentController::setComponentView(ComponentView *componentView) +{ + m_d->componentView = componentView; + connect(m_d->componentView->action(), SIGNAL(currentComponentChanged(ModelNode)), SLOT(changeCurrentModelTo(ModelNode))); +} + QString DesignDocumentController::displayName() const { if (fileName().isEmpty()) @@ -331,6 +337,8 @@ QList DesignDocumentController::loadMaster(QPlainTextEdit * loadCurrentModel(); + m_d->masterModel->attachView(m_d->componentView.data()); + return m_d->rewriterView->errors(); } @@ -340,6 +348,17 @@ void DesignDocumentController::changeCurrentModelTo(const ModelNode &componentNo QWeakPointer oldModel = m_d->model; Q_ASSERT(oldModel.data()); + QString componentText = m_d->rewriterView->extractText(QList() << componentNode).value(componentNode); + + if (componentText.isEmpty()) + return; + + + bool explicitComponent = false; + if (componentText.contains("Component")) { //explicit component + explicitComponent = true; + } + if (m_d->model == m_d->subComponentModel) { //change back to master model m_d->model->detachView(m_d->rewriterView.data()); @@ -356,10 +375,20 @@ void DesignDocumentController::changeCurrentModelTo(const ModelNode &componentNo if (m_d->componentTextModifier) delete m_d->componentTextModifier; - int componentStartOffset = m_d->rewriterView->firstDefinitionInsideOffset(componentNode); - int componentEndOffset = componentStartOffset + m_d->rewriterView->firstDefinitionInsideLength(componentNode); + + int componentStartOffset; + int componentEndOffset; + int rootStartOffset = m_d->rewriterView->nodeOffset(rootModelNode); + if (explicitComponent) { //the component is explciit we have to find the first definition inside + componentStartOffset = m_d->rewriterView->firstDefinitionInsideOffset(componentNode); + componentEndOffset = componentStartOffset + m_d->rewriterView->firstDefinitionInsideLength(componentNode); + } else { //the component is implicit + componentStartOffset = m_d->rewriterView->nodeOffset(componentNode); + componentEndOffset = componentStartOffset + m_d->rewriterView->nodeLength(componentNode); + } + m_d->componentTextModifier = new ComponentTextModifier (m_d->textModifier, componentStartOffset, componentEndOffset, rootStartOffset); @@ -392,21 +421,11 @@ void DesignDocumentController::loadCurrentModel() m_d->model->attachView(m_d->navigator.data()); m_d->itemLibraryView->widget()->setResourcePath(QFileInfo(m_d->fileName).absolutePath()); - if (!m_d->componentAction) { - m_d->componentAction = new ComponentAction(m_d->formEditorView->widget()); - m_d->componentAction->setModel(m_d->model.data()); - connect(m_d->componentAction.data(), SIGNAL(currentComponentChanged(ModelNode)), SLOT(changeCurrentModelTo(ModelNode))); - m_d->formEditorView->widget()->toolBox()->addAction(m_d->componentAction.data()); - } - // Disable switching between in file components for the time being - m_d->componentAction->setVisible(false); - connect(m_d->itemLibraryView->widget(), SIGNAL(itemActivated(const QString&)), m_d->formEditorView.data(), SLOT(activateItemCreator(const QString&))); m_d->model->attachView(m_d->formEditorView.data()); m_d->model->attachView(m_d->itemLibraryView.data()); - if (!m_d->textEdit->parent()) // hack to prevent changing owner of external text edit m_d->stackedWidget->addWidget(m_d->textEdit.data()); diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontroller.h b/src/plugins/qmldesigner/components/integration/designdocumentcontroller.h index 047bdb63263..15601b56d71 100644 --- a/src/plugins/qmldesigner/components/integration/designdocumentcontroller.h +++ b/src/plugins/qmldesigner/components/integration/designdocumentcontroller.h @@ -56,6 +56,7 @@ class QmlObjectNode; class RewriterView; class ItemLibraryView; class NavigatorView; +class ComponentView; class PropertyEditor; class StatesEditorView; class FormEditorView; @@ -98,6 +99,7 @@ public: void setStatesEditorView(StatesEditorView* statesEditorView); void setFormEditorView(FormEditorView *formEditorView); void setNodeInstanceView(NodeInstanceView *nodeInstanceView); + void setComponentView(ComponentView *componentView); signals: void displayNameChanged(const QString &newFileName); diff --git a/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp b/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp index 454f9e9198d..71e6a89dc15 100644 --- a/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp +++ b/src/plugins/qmldesigner/designercore/model/componenttextmodifier.cpp @@ -39,7 +39,7 @@ ComponentTextModifier::ComponentTextModifier(TextModifier *originalModifier, int m_componentEndOffset(componentEndOffset), m_rootStartOffset(rootStartOffset) { - connect(m_originalModifier->textDocument(), SIGNAL(contentsChange(int,int,int)), this, SLOT(contentsChange(int,int,int))); + connect(m_originalModifier, SIGNAL(replaced(int, int, int)), this, SLOT(contentsChange(int,int,int))); connect(m_originalModifier, SIGNAL(textChanged()), this, SIGNAL(textChanged())); connect(m_originalModifier, SIGNAL(replaced(int, int, int)), this, SIGNAL(replaced(int, int, int))); diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp index 572ca373e1b..cf4b90221e2 100644 --- a/src/plugins/qmldesigner/designmodewidget.cpp +++ b/src/plugins/qmldesigner/designmodewidget.cpp @@ -40,7 +40,8 @@ #include #include #include - +#include +#include #include #include @@ -312,6 +313,7 @@ void DesignModeWidget::showEditor(Core::IEditor *editor) newDocument->setStatesEditorView(m_statesEditorView.data()); newDocument->setItemLibraryView(m_itemLibraryView.data()); newDocument->setFormEditorView(m_formEditorView.data()); + newDocument->setComponentView(m_componentView.data()); newDocument->setFileName(fileName); @@ -674,6 +676,8 @@ void DesignModeWidget::setup() m_formEditorView = new FormEditorView(this); + m_componentView = new ComponentView(this); + m_formEditorView->widget()->toolBox()->addLeftSideAction(m_componentView->action()); m_fakeToolBar = Core::EditorManager::createToolBar(this); m_mainSplitter = new MiniSplitter(this); diff --git a/src/plugins/qmldesigner/designmodewidget.h b/src/plugins/qmldesigner/designmodewidget.h index a7743cf56b4..e0b0aec3724 100644 --- a/src/plugins/qmldesigner/designmodewidget.h +++ b/src/plugins/qmldesigner/designmodewidget.h @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -185,6 +186,7 @@ private: QWeakPointer m_propertyEditorView; QWeakPointer m_statesEditorView; QWeakPointer m_formEditorView; + QWeakPointer m_componentView; QWeakPointer m_nodeInstanceView; bool m_syncWithTextEdit;