From d7127c343774d8ae316f1c66e308f6dd0cd4c017 Mon Sep 17 00:00:00 2001 From: Ali Kianian Date: Wed, 17 Jan 2024 15:31:38 +0200 Subject: [PATCH] QmlDesigner: Fix the bug for crash on saving Model Editor content Export and write method are available in two different methods Fixes: QDS-11660 Change-Id: I21658f9ed0d29d95de7ff2f9d940ea69c9f072ad Reviewed-by: Miikka Heikkinen Reviewed-by: Qt CI Patch Build Bot --- .../CollectionDetailsToolbar.qml | 2 +- .../collectiondetailsmodel.cpp | 122 +++++++++++------- .../collectioneditor/collectiondetailsmodel.h | 5 +- 3 files changed, 76 insertions(+), 53 deletions(-) diff --git a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsToolbar.qml b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsToolbar.qml index a79a2d5c5d7..da13f62db0b 100644 --- a/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsToolbar.qml +++ b/share/qtcreator/qmldesigner/collectionEditorQmlSource/CollectionDetailsToolbar.qml @@ -102,7 +102,7 @@ Item { icon: StudioTheme.Constants.save_medium tooltip: qsTr("Save changes") enabled: root.model.collectionName !== "" - onClicked: root.model.saveCurrentCollection() + onClicked: root.model.saveDataStoreCollections() } IconButton { diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.cpp index 557868b907a..52d5a6e2bab 100644 --- a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.cpp +++ b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.cpp @@ -7,7 +7,11 @@ #include "collectioneditorutils.h" #include "modelnode.h" +#include + +#include #include +#include #include #include @@ -423,14 +427,76 @@ void CollectionDetailsModel::loadCollection(const ModelNode &sourceNode, const Q } } -bool CollectionDetailsModel::saveCurrentCollection() +bool CollectionDetailsModel::saveDataStoreCollections() { - return saveCollection({}); + const ModelNode node = m_currentCollection.reference().node; + const Utils::FilePath path = CollectionEditorUtils::dataStoreJsonFilePath(); + Utils::FileReader fileData; + Utils::FileSaver sourceFile(path); + + if (!fileData.fetch(path)) { + qWarning() << Q_FUNC_INFO << "Cannot read the json file:" << fileData.errorString(); + return false; + } + + QJsonParseError jpe; + QJsonDocument document = QJsonDocument::fromJson(fileData.data(), &jpe); + + if (jpe.error == QJsonParseError::NoError) { + QJsonObject obj = document.object(); + + QList collectionsToBeSaved; + for (CollectionDetails &openedCollection : m_openedCollections) { + const CollectionReference reference = openedCollection.reference(); + if (reference.node == node) { + obj.insert(reference.name, openedCollection.getCollectionAsJsonArray()); + collectionsToBeSaved << openedCollection; + } + } + + document.setObject(obj); + bool saved = sourceFile.write(document.toJson()); + saved &= sourceFile.finalize(); + + if (saved) { + const CollectionReference currentReference = m_currentCollection.reference(); + for (CollectionDetails &collection : collectionsToBeSaved) { + collection.markSaved(); + const CollectionReference reference = collection.reference(); + if (reference != currentReference) + closeCollectionIfSaved(reference); + } + return true; + } + } + return false; } -bool CollectionDetailsModel::exportCollection(const QString &filePath) +bool CollectionDetailsModel::exportCollection(const QUrl &url) { - return saveCollection(filePath, &m_currentCollection); + using Core::EditorManager; + using Utils::FilePath; + using Utils::TextFileFormat; + + QTC_ASSERT(m_currentCollection.isValid(), return false); + + bool saved = false; + const FilePath filePath = FilePath::fromUserInput(url.isLocalFile() ? url.toLocalFile() + : url.toString()); + const QString saveFormat = filePath.toFileInfo().suffix().toLower(); + const QString content = saveFormat == "csv" ? m_currentCollection.getCollectionAsCsvString() + : m_currentCollection.getCollectionAsJsonString(); + + TextFileFormat textFileFormat; + textFileFormat.codec = EditorManager::defaultTextCodec(); + textFileFormat.lineTerminationMode = EditorManager::defaultLineEnding(); + QString errorMessage; + saved = textFileFormat.writeFile(filePath, content, &errorMessage); + + if (!saved) + qWarning() << Q_FUNC_INFO << "Unable to write file" << errorMessage; + + return saved; } void CollectionDetailsModel::updateEmpty() @@ -466,14 +532,14 @@ void CollectionDetailsModel::closeCollectionIfSaved(const CollectionReference &c if (!collectionDetails.isChanged()) m_openedCollections.remove(collection); - - m_currentCollection = CollectionDetails{}; } void CollectionDetailsModel::closeCurrentCollectionIfSaved() { - if (m_currentCollection.isValid()) + if (m_currentCollection.isValid()) { closeCollectionIfSaved(m_currentCollection.reference()); + m_currentCollection = CollectionDetails{}; + } } void CollectionDetailsModel::loadJsonCollection(const QString &source, const QString &collection) @@ -607,48 +673,6 @@ void CollectionDetailsModel::setCollectionName(const QString &newCollectionName) } } -bool CollectionDetailsModel::saveCollection(const QString &filePath, CollectionDetails *collection) -{ - bool saved = false; - - const ModelNode node = m_currentCollection.reference().node; - QString path = CollectionEditorUtils::getSourceCollectionPath(node); - QString saveFormat = CollectionEditorUtils::getSourceCollectionType(node); - - QFile sourceFile(path); - - if (!filePath.isEmpty()) { - QUrl url(filePath); - path = url.isLocalFile() ? QFileInfo(url.toLocalFile()).absoluteFilePath() : url.toString(); - saveFormat = url.isLocalFile() ? QFileInfo(url.toLocalFile()).suffix().toLower() : saveFormat; - QString content = saveFormat == "json" ? collection->getCollectionAsJsonString() - : saveFormat == "csv" ? collection->getCollectionAsCsvString() : QString(); - - sourceFile.setFileName(path); - - if (sourceFile.open(QFile::WriteOnly)) - saved = sourceFile.write(content.toUtf8()); - } else if (filePath.isEmpty() && sourceFile.open(QFile::ReadWrite)) { - QJsonParseError jpe; - QJsonDocument document = QJsonDocument::fromJson(sourceFile.readAll(), &jpe); - - if (jpe.error == QJsonParseError::NoError) { - QJsonObject obj = document.object(); - - for (const CollectionDetails &openedCollection : std::as_const(m_openedCollections)) - obj[openedCollection.reference().name] = openedCollection.getCollectionAsJsonArray(); - - document.setObject(obj); - saved = sourceFile.write(document.toJson()); - - if (saved) - collection->markSaved(); - } - } - - return saved; -} - QString CollectionDetailsModel::warningToString(DataTypeWarning::Warning warning) const { return DataTypeWarning::getDataTypeWarningString(warning); diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.h b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.h index 9e1fada31af..4fef84a3df3 100644 --- a/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.h +++ b/src/plugins/qmldesigner/components/collectioneditor/collectiondetailsmodel.h @@ -62,8 +62,8 @@ public: void loadCollection(const ModelNode &sourceNode, const QString &collection); - Q_INVOKABLE bool saveCurrentCollection(); - Q_INVOKABLE bool exportCollection(const QString &filePath); + Q_INVOKABLE bool saveDataStoreCollections(); + Q_INVOKABLE bool exportCollection(const QUrl &url); signals: void collectionNameChanged(const QString &collectionName); @@ -81,7 +81,6 @@ private: void setCollectionName(const QString &newCollectionName); void loadJsonCollection(const QString &source, const QString &collection); void loadCsvCollection(const QString &source, const QString &collectionName); - bool saveCollection(const QString &filePath = {}, CollectionDetails *collection = nullptr); QVariant variantFromString(const QString &value); QHash m_openedCollections;