forked from qt-creator/qt-creator
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 <miikka.heikkinen@qt.io> Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
This commit is contained in:
@@ -102,7 +102,7 @@ Item {
|
|||||||
icon: StudioTheme.Constants.save_medium
|
icon: StudioTheme.Constants.save_medium
|
||||||
tooltip: qsTr("Save changes")
|
tooltip: qsTr("Save changes")
|
||||||
enabled: root.model.collectionName !== ""
|
enabled: root.model.collectionName !== ""
|
||||||
onClicked: root.model.saveCurrentCollection()
|
onClicked: root.model.saveDataStoreCollections()
|
||||||
}
|
}
|
||||||
|
|
||||||
IconButton {
|
IconButton {
|
||||||
|
@@ -7,7 +7,11 @@
|
|||||||
#include "collectioneditorutils.h"
|
#include "collectioneditorutils.h"
|
||||||
#include "modelnode.h"
|
#include "modelnode.h"
|
||||||
|
|
||||||
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
|
|
||||||
|
#include <utils/fileutils.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/textfileformat.h>
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
@@ -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<CollectionDetails> 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()
|
void CollectionDetailsModel::updateEmpty()
|
||||||
@@ -466,14 +532,14 @@ void CollectionDetailsModel::closeCollectionIfSaved(const CollectionReference &c
|
|||||||
|
|
||||||
if (!collectionDetails.isChanged())
|
if (!collectionDetails.isChanged())
|
||||||
m_openedCollections.remove(collection);
|
m_openedCollections.remove(collection);
|
||||||
|
|
||||||
m_currentCollection = CollectionDetails{};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionDetailsModel::closeCurrentCollectionIfSaved()
|
void CollectionDetailsModel::closeCurrentCollectionIfSaved()
|
||||||
{
|
{
|
||||||
if (m_currentCollection.isValid())
|
if (m_currentCollection.isValid()) {
|
||||||
closeCollectionIfSaved(m_currentCollection.reference());
|
closeCollectionIfSaved(m_currentCollection.reference());
|
||||||
|
m_currentCollection = CollectionDetails{};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionDetailsModel::loadJsonCollection(const QString &source, const QString &collection)
|
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
|
QString CollectionDetailsModel::warningToString(DataTypeWarning::Warning warning) const
|
||||||
{
|
{
|
||||||
return DataTypeWarning::getDataTypeWarningString(warning);
|
return DataTypeWarning::getDataTypeWarningString(warning);
|
||||||
|
@@ -62,8 +62,8 @@ public:
|
|||||||
|
|
||||||
void loadCollection(const ModelNode &sourceNode, const QString &collection);
|
void loadCollection(const ModelNode &sourceNode, const QString &collection);
|
||||||
|
|
||||||
Q_INVOKABLE bool saveCurrentCollection();
|
Q_INVOKABLE bool saveDataStoreCollections();
|
||||||
Q_INVOKABLE bool exportCollection(const QString &filePath);
|
Q_INVOKABLE bool exportCollection(const QUrl &url);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void collectionNameChanged(const QString &collectionName);
|
void collectionNameChanged(const QString &collectionName);
|
||||||
@@ -81,7 +81,6 @@ private:
|
|||||||
void setCollectionName(const QString &newCollectionName);
|
void setCollectionName(const QString &newCollectionName);
|
||||||
void loadJsonCollection(const QString &source, const QString &collection);
|
void loadJsonCollection(const QString &source, const QString &collection);
|
||||||
void loadCsvCollection(const QString &source, const QString &collectionName);
|
void loadCsvCollection(const QString &source, const QString &collectionName);
|
||||||
bool saveCollection(const QString &filePath = {}, CollectionDetails *collection = nullptr);
|
|
||||||
QVariant variantFromString(const QString &value);
|
QVariant variantFromString(const QString &value);
|
||||||
|
|
||||||
QHash<CollectionReference, CollectionDetails> m_openedCollections;
|
QHash<CollectionReference, CollectionDetails> m_openedCollections;
|
||||||
|
Reference in New Issue
Block a user