diff --git a/src/plugins/qmldesigner/core/core.pri b/src/plugins/qmldesigner/core/core.pri index 0768c58fd720967215019517e7fe22ef3bd49c2f..46c1b7387a5d530c6eb75b393ad272a39c4cda76 100644 --- a/src/plugins/qmldesigner/core/core.pri +++ b/src/plugins/qmldesigner/core/core.pri @@ -90,7 +90,8 @@ SOURCES += $$PWD/model/abstractview.cpp \ $$PWD/model/rewriteactioncompressor.cpp \ $$PWD/model/qmltextgenerator.cpp \ $$PWD/model/modelmerger.cpp \ - $$PWD/instances/qmltransitionnodeinstance.cpp + $$PWD/instances/qmltransitionnodeinstance.cpp \ + $$PWD/exceptions/rewritingexception.cpp HEADERS += $$PWD/include/corelib_global.h \ $$PWD/include/abstractview.h \ $$PWD/include/nodeinstanceview.h \ @@ -177,7 +178,8 @@ HEADERS += $$PWD/include/corelib_global.h \ $$PWD/include/modelmerger.h \ $$PWD/include/mathutils.h \ $$PWD/instances/qmltransitionnodeinstance.h \ - $$PWD/include/customnotifications.h + $$PWD/include/customnotifications.h \ + $$PWD/include/rewritingexception.h DISTFILES += $$PWD/metafile/widget.metafile RESOURCES += $$PWD/core.qrc OTHER_FILES += $$PWD/metainfo/gui.metainfo diff --git a/src/plugins/qmldesigner/core/include/rewriterview.h b/src/plugins/qmldesigner/core/include/rewriterview.h index ce335d3c44d81755863a74fbe11978c34a9e3ae3..bbc49df2d6fe5e410cd8644cad57fd9a21711a75 100644 --- a/src/plugins/qmldesigner/core/include/rewriterview.h +++ b/src/plugins/qmldesigner/core/include/rewriterview.h @@ -140,6 +140,8 @@ public: void setErrors(const QList<Error> &errors); void addError(const Error &error); + void resetToLastCorrectQml(); + QMap<ModelNode, QString> extractText(const QList<ModelNode> &nodes) const; int nodeOffset(const ModelNode &node) const; int nodeLength(const ModelNode &node) const; @@ -159,6 +161,7 @@ protected: // functions void setModificationGroupActive(bool active); void applyModificationGroupChanges(); void setupComponent(const ModelNode &node); + void applyChanges(); private: //variables DifferenceHandling m_differenceHandling; @@ -170,6 +173,8 @@ private: //variables QList<Error> m_errors; int transactionLevel; RewriterTransaction m_removeDefaultPropertyTransaction; + bool errorState; + QString lastCorrectQmlSource; }; } //QmlDesigner diff --git a/src/plugins/qmldesigner/core/model/rewriterview.cpp b/src/plugins/qmldesigner/core/model/rewriterview.cpp index 619044e334b26d37c386b01b82c73e5b596ffde3..b04e68c565f082844cd8c9045a60f0b0a709924f 100644 --- a/src/plugins/qmldesigner/core/model/rewriterview.cpp +++ b/src/plugins/qmldesigner/core/model/rewriterview.cpp @@ -33,6 +33,7 @@ #include <customnotifications.h> #include "rewriterview.h" +#include "rewritingexception.h" #include "textmodifier.h" #include "texttomodelmerger.h" #include "modelnodepositionstorage.h" @@ -77,7 +78,7 @@ QString RewriterView::Error::toString() const if (m_type == ParseError) str += tr("Error parsing"); else if (m_type == InternalError) - str += tr("Internal error while parsing"); + str += tr("Internal error"); if (url().isValid()) { if (!str.isEmpty()) @@ -114,7 +115,8 @@ RewriterView::RewriterView(DifferenceHandling differenceHandling, QObject *paren m_modelToTextMerger(new Internal::ModelToTextMerger(this)), m_textToModelMerger(new Internal::TextToModelMerger(this)), m_textModifier(0), - transactionLevel(0) + transactionLevel(0), + errorState(false) { } @@ -138,7 +140,10 @@ void RewriterView::modelAttached(Model *model) AbstractView::modelAttached(model); ModelAmender differenceHandler(m_textToModelMerger.data()); - m_textToModelMerger->load(m_textModifier->text().toUtf8(), differenceHandler); + const QString qmlSource = m_textModifier->text(); + if (m_textToModelMerger->load(qmlSource.toUtf8(), differenceHandler)) { + lastCorrectQmlSource = qmlSource; + } } void RewriterView::modelAboutToBeDetached(Model * /*model*/) @@ -158,7 +163,7 @@ void RewriterView::nodeCreated(const ModelNode &createdNode) modelToTextMerger()->nodeCreated(createdNode); if (!isModificationGroupActive()) - modelToTextMerger()->applyChanges(); + applyChanges(); } void RewriterView::nodeAboutToBeRemoved(const ModelNode &/*removedNode*/) @@ -174,7 +179,7 @@ void RewriterView::nodeRemoved(const ModelNode &removedNode, const NodeAbstractP modelToTextMerger()->nodeRemoved(removedNode, parentProperty, propertyChange); if (!isModificationGroupActive()) - modelToTextMerger()->applyChanges(); + applyChanges(); } void RewriterView::propertiesAdded(const ModelNode &/*node*/, const QList<AbstractProperty>& /*propertyList*/) @@ -212,7 +217,7 @@ void RewriterView::propertiesRemoved(const QList<AbstractProperty>& propertyList m_removeDefaultPropertyTransaction.commit(); if (!isModificationGroupActive()) - modelToTextMerger()->applyChanges(); + applyChanges(); } void RewriterView::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange) @@ -228,7 +233,7 @@ void RewriterView::variantPropertiesChanged(const QList<VariantProperty>& proper modelToTextMerger()->propertiesChanged(usefulPropertyList, propertyChange); if (!isModificationGroupActive()) - modelToTextMerger()->applyChanges(); + applyChanges(); } void RewriterView::bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange) @@ -244,7 +249,7 @@ void RewriterView::bindingPropertiesChanged(const QList<BindingProperty>& proper modelToTextMerger()->propertiesChanged(usefulPropertyList, propertyChange); if (!isModificationGroupActive()) - modelToTextMerger()->applyChanges(); + applyChanges(); } void RewriterView::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange) @@ -259,7 +264,7 @@ void RewriterView::nodeReparented(const ModelNode &node, const NodeAbstractPrope modelToTextMerger()->nodeReparented(node, newPropertyParent, oldPropertyParent, propertyChange); if (!isModificationGroupActive()) - modelToTextMerger()->applyChanges(); + applyChanges(); } void RewriterView::fileUrlChanged(const QUrl &/*oldUrl*/, const QUrl &/*newUrl*/) @@ -275,7 +280,7 @@ void RewriterView::nodeIdChanged(const ModelNode& node, const QString& newId, co modelToTextMerger()->nodeIdChanged(node, newId, oldId); if (!isModificationGroupActive()) - modelToTextMerger()->applyChanges(); + applyChanges(); } void RewriterView::nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &movedNode, int /*oldIndex*/) @@ -293,7 +298,7 @@ void RewriterView::nodeOrderChanged(const NodeListProperty &listProperty, const modelToTextMerger()->nodeSlidAround(movedNode, trailingNode); if (!isModificationGroupActive()) - modelToTextMerger()->applyChanges(); + applyChanges(); } void RewriterView::nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion) @@ -305,7 +310,7 @@ void RewriterView::nodeTypeChanged(const ModelNode &node,const QString &type, in modelToTextMerger()->nodeTypeChanged(node, type, majorVersion, minorVersion); if (!isModificationGroupActive()) - modelToTextMerger()->applyChanges(); + applyChanges(); } void RewriterView::customNotification(const AbstractView * /*view*/, const QString &identifier, const QList<ModelNode> & /* nodeList */, const QList<QVariant> & /*data */) @@ -359,7 +364,7 @@ void RewriterView::setTextModifier(TextModifier *textModifier) void RewriterView::applyModificationGroupChanges() { Q_ASSERT(transactionLevel == 0); - modelToTextMerger()->applyChanges(); + applyChanges(); } void RewriterView::setupComponent(const ModelNode &node) @@ -386,6 +391,30 @@ void RewriterView::setupComponent(const ModelNode &node) node.variantProperty("__component_data") = result; } +void RewriterView::applyChanges() +{ + if (errorState) { + qDebug() << "RewriterView::applyChanges() got called while in error state. Will do a quick-exit now."; + throw RewritingException(__LINE__, __FUNCTION__, __FILE__); + } + + bool success = false; + try { + success = modelToTextMerger()->applyChanges(); + + if (!success) { + errorState = true; + + throw RewritingException(__LINE__, __FUNCTION__, __FILE__); + } + } catch (Exception &e) { + Q_UNUSED(e); + errorState = true; + + throw RewritingException(__LINE__, __FUNCTION__, __FILE__); + } +} + QList<RewriterView::Error> RewriterView::errors() const { return m_errors; @@ -409,6 +438,13 @@ void RewriterView::addError(const RewriterView::Error &error) emit errorsChanged(m_errors); } +void RewriterView::resetToLastCorrectQml() +{ + ModelAmender differenceHandler(m_textToModelMerger.data()); + m_textToModelMerger->load(lastCorrectQmlSource.toUtf8(), differenceHandler); + errorState = false; +} + QMap<ModelNode, QString> RewriterView::extractText(const QList<ModelNode> &nodes) const { QmlDesigner::ASTObjectTextExtractor extract(m_textModifier->text()); @@ -461,7 +497,9 @@ void RewriterView::qmlTextChanged() switch (m_differenceHandling) { case Validate: { ModelValidator differenceHandler(m_textToModelMerger.data()); - m_textToModelMerger->load(newQmlText.toUtf8(), differenceHandler); + if (m_textToModelMerger->load(newQmlText.toUtf8(), differenceHandler)) { + lastCorrectQmlSource = newQmlText; + } break; } @@ -469,7 +507,9 @@ void RewriterView::qmlTextChanged() default: { emitCustomNotification(StartRewriterAmend); ModelAmender differenceHandler(m_textToModelMerger.data()); - m_textToModelMerger->load(newQmlText.toUtf8(), differenceHandler); + if (m_textToModelMerger->load(newQmlText.toUtf8(), differenceHandler)) { + lastCorrectQmlSource = newQmlText; + } emitCustomNotification(EndRewriterAmend); break; } diff --git a/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp index 49dcb0c945b4c27e09c62c91149b4e93c3539249..a39bc546e1a09b11e140629e790c6623e9824f6b 100644 --- a/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp @@ -110,7 +110,10 @@ bool TextToModelMerger::load(const QByteArray &data, DifferenceHandler &differen setActive(false); return success; } catch (Exception &e) { - m_rewriterView->addError(RewriterView::Error(&e)); + RewriterView::Error error(&e); + // Somehow, the error below gets eaten in upper levels, so printing the exception info here for debugging purposes: + qDebug() << "*** An exception occurred while reading the QML file:" << error.toString(); + m_rewriterView->addError(error); setActive(false);