summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@qt.io>2018-10-17 14:47:21 +0300
committerMiikka Heikkinen <miikka.heikkinen@qt.io>2018-10-19 10:19:09 +0000
commit3cbc990590ac915d73454addc1be06dbefe7e109 (patch)
tree5b2e732baaa0a41921d1bc99e24de090bc379792
parent745c7eb9e734d9e9670b4c25c97f04749c83180a (diff)
Use QSaveFile when writing various files
Using QSaveFile ensures existing content is not lost if something goes wrong between clearing the file and writing to it. Task-number: QT3DS-2471 Change-Id: I7065416b311753785b7498eb56f828105182fc09 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Jere Tuliniemi <jere.tuliniemi@qt.io> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
-rw-r--r--src/Authoring/Common/Code/_Win32/Preferences.cpp6
-rw-r--r--src/Authoring/Common/Common.pro1
-rw-r--r--src/Authoring/Studio/Application/PresentationFile.cpp39
-rw-r--r--src/Authoring/Studio/Application/ProjectFile.cpp134
-rw-r--r--src/Authoring/Studio/Application/StudioApp.cpp15
-rw-r--r--src/Authoring/Studio/Utils/StudioUtils.cpp45
-rw-r--r--src/Authoring/Studio/Utils/StudioUtils.h11
7 files changed, 131 insertions, 120 deletions
diff --git a/src/Authoring/Common/Code/_Win32/Preferences.cpp b/src/Authoring/Common/Code/_Win32/Preferences.cpp
index 2dc0159f..0adb1268 100644
--- a/src/Authoring/Common/Code/_Win32/Preferences.cpp
+++ b/src/Authoring/Common/Code/_Win32/Preferences.cpp
@@ -27,6 +27,7 @@
****************************************************************************/
#include "Preferences.h"
+#include "StudioUtils.h"
#include <QtCore/qdir.h>
#include <QtCore/qsavefile.h>
@@ -42,9 +43,8 @@ void CPreferences::save()
{
if (!m_PreferencesFile.isEmpty() && !m_domDoc.isNull()) {
QSaveFile file(m_PreferencesFile);
- file.open(QIODevice::WriteOnly);
- if (file.write(m_domDoc.toByteArray(4)) != -1)
- file.commit();
+ if (StudioUtils::openTextSave(file))
+ StudioUtils::commitDomDocumentSave(file, m_domDoc);
}
}
diff --git a/src/Authoring/Common/Common.pro b/src/Authoring/Common/Common.pro
index c3ce78f7..805329ed 100644
--- a/src/Authoring/Common/Common.pro
+++ b/src/Authoring/Common/Common.pro
@@ -26,6 +26,7 @@ INCLUDEPATH += \
../Client/Code/Core/Utility \
../QT3DSDM \
../QT3DSDM/Systems \
+ ../Studio/Utils \
../../Runtime/Source/Qt3DSFoundation/Include \
../../Runtime/Source/Qt3DSFoundation/Include/foundation \
../../3rdparty/EASTL/UnknownVersion/include \
diff --git a/src/Authoring/Studio/Application/PresentationFile.cpp b/src/Authoring/Studio/Application/PresentationFile.cpp
index 86abae83..41fff72a 100644
--- a/src/Authoring/Studio/Application/PresentationFile.cpp
+++ b/src/Authoring/Studio/Application/PresentationFile.cpp
@@ -32,12 +32,14 @@
#include "StudioApp.h"
#include "Core.h"
#include "Doc.h"
+#include "StudioUtils.h"
#include "IDocumentReader.h"
#include <QtCore/qfile.h>
+#include <QtCore/qsavefile.h>
#include <QtXml/qdom.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qdiriterator.h>
-#include <qxmlstream.h>
+#include <QtCore/qxmlstream.h>
#include <QtCore/qlist.h>
// This class provides utility static methods for working with presentation files (.uip). Old uip
@@ -78,13 +80,10 @@ QSize PresentationFile::readSize(const QString &uipPath)
void PresentationFile::updatePresentationId(const QString &uipPath, const QString &oldId,
const QString &newId)
{
- QFile file(uipPath);
- if (!file.open(QFile::Text | QIODevice::ReadWrite)) {
- qWarning() << file.errorString();
- return;
- }
QDomDocument domDoc;
- domDoc.setContent(&file);
+ QSaveFile file(uipPath);
+ if (!StudioUtils::openDomDocumentSave(file, domDoc))
+ return;
QDomElement rootElem = domDoc.documentElement();
QDomNodeList addNodes = rootElem.elementsByTagName(QStringLiteral("Add"));
@@ -104,10 +103,8 @@ void PresentationFile::updatePresentationId(const QString &uipPath, const QStrin
}
}
- if (updated) {
- file.resize(0);
- file.write(domDoc.toByteArray(4));
- }
+ if (updated)
+ StudioUtils::commitDomDocumentSave(file, domDoc);
}
/**
@@ -151,15 +148,9 @@ void PresentationFile::getSourcePaths(const QFileInfo &uipSrc, const QFileInfo &
QString &outProjPathSrc,
QHash<QString, QString> &outPresentationNodes)
{
- QFile file(uipTarget.filePath());
- file.open(QFile::Text | QFile::ReadOnly);
- if (!file.isOpen()) {
- qWarning() << file.errorString();
- return;
- }
-
QDomDocument domDoc;
- domDoc.setContent(&file);
+ if (!StudioUtils::readFileToDomDocument(uipTarget.filePath(), domDoc))
+ return;
QVector<SubPresentationRecord> subpresentations;
QString uiaPath = findProjectFile(uipSrc.filePath());
@@ -306,16 +297,10 @@ bool PresentationFile::getDataInputBindings(const SubPresentationRecord &subpres
QList<QString> ctrldPropList;
QString spPath(g_StudioApp.getRenderableAbsolutePath(subpresentation.m_id));
- QFile file(spPath);
-
- file.open(QFile::Text | QFile::ReadOnly);
- if (!file.isOpen()) {
- qWarning() << file.errorString();
- return false;
- }
QDomDocument domDoc;
- domDoc.setContent(&file);
+ if (!StudioUtils::readFileToDomDocument(spPath, domDoc))
+ return false;
// search <Graph>
QDomElement graphElem = domDoc.documentElement().firstChild()
diff --git a/src/Authoring/Studio/Application/ProjectFile.cpp b/src/Authoring/Studio/Application/ProjectFile.cpp
index 101f3c75..397d9376 100644
--- a/src/Authoring/Studio/Application/ProjectFile.cpp
+++ b/src/Authoring/Studio/Application/ProjectFile.cpp
@@ -37,8 +37,10 @@
#include "Doc.h"
#include "PresentationFile.h"
#include "IStudioRenderer.h"
+#include "StudioUtils.h"
#include <QtCore/qdiriterator.h>
#include <QtXml/qdom.h>
+#include <QtCore/qsavefile.h>
ProjectFile::ProjectFile()
{
@@ -96,11 +98,10 @@ void ProjectFile::addPresentationNodes(const QHash<QString, QString> &nodeList)
{
ensureProjectFile();
- // open the uia file
- QFile file(getProjectFilePath());
- file.open(QIODevice::ReadWrite);
QDomDocument doc;
- doc.setContent(&file);
+ QSaveFile file(getProjectFilePath());
+ if (!StudioUtils::openDomDocumentSave(file, doc))
+ return;
QDomElement rootElem = doc.documentElement();
QDomElement assetsElem = rootElem.firstChildElement(QStringLiteral("assets"));
@@ -164,11 +165,8 @@ void ProjectFile::addPresentationNodes(const QHash<QString, QString> &nodeList)
}
}
- if (initial || changesList.size() > 0) {
- file.resize(0);
- file.write(doc.toByteArray(4));
- }
- file.close();
+ if (initial || changesList.size() > 0)
+ StudioUtils::commitDomDocumentSave(file, doc);
if (changesList.size() > 0) {
g_StudioApp.getRenderer().RegisterSubpresentations(g_StudioApp.m_subpresentations);
@@ -182,14 +180,12 @@ void ProjectFile::addPresentationNodes(const QHash<QString, QString> &nodeList)
}
// Get the src attribute (relative path) to the initial presentation in a uia file, if no initial
-// presentation exists, the first one is returned.
+// presentation exists, the first one is returned. Returns empty string if file cannot be read.
QString ProjectFile::getInitialPresentationSrc(const QString &uiaPath)
{
- QFile file(uiaPath);
- file.open(QIODevice::ReadOnly);
QDomDocument domDoc;
- domDoc.setContent(&file);
- file.close();
+ if (!StudioUtils::readFileToDomDocument(uiaPath, domDoc))
+ return {};
QString firstPresentationSrc;
QDomElement assetsElem = domDoc.documentElement().firstChildElement(QStringLiteral("assets"));
@@ -233,10 +229,10 @@ void ProjectFile::writePresentationId(const QString &id, const QString &src)
if (theSrc == doc->getRelativePath())
doc->setPresentationId(id);
- QFile file(getProjectFilePath());
- file.open(QIODevice::ReadWrite);
QDomDocument domDoc;
- domDoc.setContent(&file);
+ QSaveFile file(getProjectFilePath());
+ if (!StudioUtils::openDomDocumentSave(file, domDoc))
+ return;
QDomElement assetsElem = domDoc.documentElement().firstChildElement(QStringLiteral("assets"));
QDomNodeList pqNodes = isQml ? assetsElem.elementsByTagName(QStringLiteral("presentation-qml"))
@@ -262,16 +258,11 @@ void ProjectFile::writePresentationId(const QString &id, const QString &src)
}
if (!src.isEmpty() && oldId.isEmpty()) { // new presentation, add it
- // overwrite the uia file
- file.resize(0);
- file.write(domDoc.toByteArray(4));
- file.close();
+ StudioUtils::commitDomDocumentSave(file, domDoc);
QDir projectDir(getProjectPath());
addPresentationNode(QDir::cleanPath(projectDir.absoluteFilePath(theSrc)), theId);
} else if (!oldId.isEmpty()) { // the presentation id changed
- // overwrite the uia file
- file.resize(0);
- file.write(domDoc.toByteArray(4));
+ StudioUtils::commitDomDocumentSave(file, domDoc);
// update m_subpresentations
auto *sp = std::find_if(g_StudioApp.m_subpresentations.begin(),
@@ -332,8 +323,7 @@ void ProjectFile::updateDocPresentationId()
return;
QFile file(getProjectFilePath());
- file.open(QFile::Text | QFile::ReadOnly);
- if (!file.isOpen()) {
+ if (!file.open(QFile::Text | QFile::ReadOnly)) {
qWarning() << file.errorString();
return;
}
@@ -377,8 +367,8 @@ QString ProjectFile::getPresentationId(const QString &src) const
// create the project .uia file
void ProjectFile::create(const QString &uiaPath)
{
- QDomDocument doc;
- doc.setContent(QStringLiteral("<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+ QDomDocument domDoc;
+ domDoc.setContent(QStringLiteral("<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<application xmlns=\"http://qt.io/qt3dstudio/uia\">"
"<statemachine ref=\"#logic\">"
"<visual-states>"
@@ -391,13 +381,11 @@ void ProjectFile::create(const QString &uiaPath)
"</statemachine>"
"</application>"));
- QFile file(uiaPath);
- file.open(QIODevice::WriteOnly);
- file.resize(0);
- file.write(doc.toByteArray(4));
- file.close();
-
- m_fileInfo.setFile(uiaPath);
+ QSaveFile file(uiaPath);
+ if (StudioUtils::openTextSave(file)) {
+ StudioUtils::commitDomDocumentSave(file, domDoc);
+ m_fileInfo.setFile(uiaPath);
+ }
}
/**
@@ -429,31 +417,28 @@ QString ProjectFile::createPreview()
QFile::remove(prvPath);
if (QFile::copy(getProjectFilePath(), prvPath)) {
- QFile file(prvPath);
- file.open(QIODevice::ReadWrite);
QDomDocument domDoc;
- domDoc.setContent(&file);
-
- QDomElement assetsElem = domDoc.documentElement()
- .firstChildElement(QStringLiteral("assets"));
- assetsElem.setAttribute(QStringLiteral("initial"), doc->getPresentationId());
-
- if (doc->IsModified()) {
- // Set the preview uip path in the uia file
- QDomNodeList pNodes = assetsElem.elementsByTagName(QStringLiteral("presentation"));
- for (int i = 0; i < pNodes.count(); ++i) {
- QDomElement pElem = pNodes.at(i).toElement();
- if (pElem.attribute(QStringLiteral("id")) == doc->getPresentationId()) {
- QString src = QDir(getProjectPath()).relativeFilePath(uipPrvPath);
- pElem.setAttribute(QStringLiteral("src"), src);
- break;
+ QSaveFile file(prvPath);
+ if (StudioUtils::openDomDocumentSave(file, domDoc)) {
+ QDomElement assetsElem = domDoc.documentElement()
+ .firstChildElement(QStringLiteral("assets"));
+ assetsElem.setAttribute(QStringLiteral("initial"), doc->getPresentationId());
+
+ if (doc->IsModified()) {
+ // Set the preview uip path in the uia file
+ QDomNodeList pNodes = assetsElem.elementsByTagName(QStringLiteral("presentation"));
+ for (int i = 0; i < pNodes.count(); ++i) {
+ QDomElement pElem = pNodes.at(i).toElement();
+ if (pElem.attribute(QStringLiteral("id")) == doc->getPresentationId()) {
+ QString src = QDir(getProjectPath()).relativeFilePath(uipPrvPath);
+ pElem.setAttribute(QStringLiteral("src"), src);
+ break;
+ }
}
}
+ StudioUtils::commitDomDocumentSave(file, domDoc);
}
- file.resize(0);
- file.write(domDoc.toByteArray(4));
-
return prvPath;
} else {
qWarning() << "Couldn't clone project file";
@@ -472,14 +457,12 @@ void ProjectFile::loadSubpresentationsAndDatainputs(
subpresentations.clear();
datainputs.clear();
- QFile file(getProjectFilePath());
- file.open(QIODevice::ReadOnly);
- QDomDocument doc;
- doc.setContent(&file);
- file.close();
-
m_initialPresentation = g_StudioApp.GetCore()->GetDoc()->getPresentationId();
+ QDomDocument doc;
+ if (!StudioUtils::readFileToDomDocument(getProjectFilePath(), doc))
+ return;
+
QDomElement assetsElem = doc.documentElement().firstChildElement(QStringLiteral("assets"));
if (!assetsElem.isNull()) {
QString initial = assetsElem.attribute(QStringLiteral("initial"));
@@ -560,11 +543,10 @@ QString ProjectFile::ensureUniquePresentationId(const QString &id) const
if (!m_fileInfo.exists())
return id;
- QFile file(m_fileInfo.filePath());
- file.open(QIODevice::ReadOnly);
QDomDocument doc;
- doc.setContent(&file);
- file.close();
+ if (!StudioUtils::readFileToDomDocument(m_fileInfo.filePath(), doc))
+ return id;
+
QString newId = id;
QDomElement assetsElem = doc.documentElement().firstChildElement(QStringLiteral("assets"));
if (!assetsElem.isNull()) {
@@ -628,8 +610,7 @@ void ProjectFile::getPresentations(const QString &inUiaPath,
const QString &excludePresentationSrc)
{
QFile file(inUiaPath);
- file.open(QFile::Text | QFile::ReadOnly);
- if (!file.isOpen()) {
+ if (!file.open(QFile::Text | QFile::ReadOnly)) {
qWarning() << file.errorString();
return;
}
@@ -665,10 +646,10 @@ void ProjectFile::setInitialPresentation(const QString &initialId)
ensureProjectFile();
- QFile file(getProjectFilePath());
- file.open(QIODevice::ReadWrite);
QDomDocument domDoc;
- domDoc.setContent(&file);
+ QSaveFile file(getProjectFilePath());
+ if (!StudioUtils::openDomDocumentSave(file, domDoc))
+ return;
QDomElement assetsElem
= domDoc.documentElement().firstChildElement(QStringLiteral("assets"));
@@ -676,9 +657,7 @@ void ProjectFile::setInitialPresentation(const QString &initialId)
!= m_initialPresentation) {
assetsElem.setAttribute(QStringLiteral("initial"), m_initialPresentation);
- // Rewrite project file
- file.resize(0);
- file.write(domDoc.toByteArray(4));
+ StudioUtils::commitDomDocumentSave(file, domDoc);
}
}
}
@@ -703,10 +682,10 @@ bool ProjectFile::renamePresentationFile(const QString &oldName, const QString &
g_StudioApp.m_qmlStreamMap.insert(fullNewPath, true);
}
- QFile file(getProjectFilePath());
- file.open(QIODevice::ReadWrite);
QDomDocument domDoc;
- domDoc.setContent(&file);
+ QSaveFile file(getProjectFilePath());
+ if (!StudioUtils::openDomDocumentSave(file, domDoc))
+ return false;
QDomElement assetsElem
= domDoc.documentElement().firstChildElement(QStringLiteral("assets"));
@@ -738,8 +717,7 @@ bool ProjectFile::renamePresentationFile(const QString &oldName, const QString &
doc->SetDocumentPath(fullNewPath);
}
- file.resize(0);
- file.write(domDoc.toByteArray(4));
+ StudioUtils::commitDomDocumentSave(file, domDoc);
Q_EMIT assetNameChanged();
break;
diff --git a/src/Authoring/Studio/Application/StudioApp.cpp b/src/Authoring/Studio/Application/StudioApp.cpp
index 1d1c1fad..416d54be 100644
--- a/src/Authoring/Studio/Application/StudioApp.cpp
+++ b/src/Authoring/Studio/Application/StudioApp.cpp
@@ -46,6 +46,7 @@
#include <QtGui/qsurfaceformat.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qurl.h>
+#include <QtCore/qsavefile.h>
#include <QtGui/qopenglcontext.h>
#include <QtWidgets/qaction.h>
#include <QtCore/qstandardpaths.h>
@@ -1705,12 +1706,12 @@ bool CStudioApp::OnLoadDocument(const QString &inDocument, bool inShowStartupDia
void CStudioApp::saveDataInputsToProjectFile()
{
- // open the uia file
m_core->getProjectFile().ensureProjectFile();
- QFile file(m_core->getProjectFile().getProjectFilePath());
- file.open(QIODevice::ReadWrite);
+
QDomDocument doc;
- doc.setContent(&file);
+ QSaveFile file(m_core->getProjectFile().getProjectFilePath());
+ if (!StudioUtils::openDomDocumentSave(file, doc))
+ return;
QDomElement assetsNode = doc.documentElement().firstChildElement(QStringLiteral("assets"));
@@ -1753,11 +1754,7 @@ void CStudioApp::saveDataInputsToProjectFile()
#endif
assetsNode.appendChild(diNode);
}
-
- // write the uia file
- file.resize(0);
- file.write(doc.toByteArray(4));
- file.close();
+ StudioUtils::commitDomDocumentSave(file, doc);
}
}
diff --git a/src/Authoring/Studio/Utils/StudioUtils.cpp b/src/Authoring/Studio/Utils/StudioUtils.cpp
index b2c35963..7553d0b2 100644
--- a/src/Authoring/Studio/Utils/StudioUtils.cpp
+++ b/src/Authoring/Studio/Utils/StudioUtils.cpp
@@ -73,3 +73,48 @@ qreal StudioUtils::devicePixelRatio()
return pixelRatio;
}
+
+// Reads the contents of a text file into QDomDocument
+bool StudioUtils::readFileToDomDocument(const QString &filePath, QDomDocument &domDoc)
+{
+ QFile file(filePath);
+ if (!file.open(QFile::Text | QIODevice::ReadOnly)) {
+ qWarning() << __FUNCTION__ << file.errorString();
+ return false;
+ }
+
+ return domDoc.setContent(&file);
+}
+
+// Opens a text file for saving and reads its contents into QDomDocument
+bool StudioUtils::openDomDocumentSave(QSaveFile &file, QDomDocument &domDoc)
+{
+ if (!readFileToDomDocument(file.fileName(), domDoc))
+ return false;
+ if (!file.open(QFile::Text | QIODevice::WriteOnly)) {
+ qWarning() << __FUNCTION__ << file.errorString();
+ return false;
+ }
+ return true;
+}
+
+// Saves contents of a QDomDocument into a previously opened text file
+bool StudioUtils::commitDomDocumentSave(QSaveFile &file, const QDomDocument &domDoc)
+{
+ // Overwrites entire file
+ if (file.resize(0) && file.write(domDoc.toByteArray(4)) != -1 && file.commit())
+ return true;
+
+ qWarning() << __FUNCTION__ << file.errorString();
+ return false;
+}
+
+// Opens text file for saving without reading its contents
+bool StudioUtils::openTextSave(QSaveFile &file)
+{
+ if (!file.open(QFile::Text | QIODevice::WriteOnly)) {
+ qWarning() << __FUNCTION__ << file.errorString();
+ return false;
+ }
+ return true;
+}
diff --git a/src/Authoring/Studio/Utils/StudioUtils.h b/src/Authoring/Studio/Utils/StudioUtils.h
index 9874ecf9..27922878 100644
--- a/src/Authoring/Studio/Utils/StudioUtils.h
+++ b/src/Authoring/Studio/Utils/StudioUtils.h
@@ -30,18 +30,23 @@
#ifndef INCLUDED_STUDIO_UTILS_H
#define INCLUDED_STUDIO_UTILS_H
-#include <QtCore/qstring.h>
+#include <QtXml/qdom.h>
+#include <QtCore/qsavefile.h>
+#include <QtCore/qxmlstream.h>
class StudioUtils {
public:
static QString resourceImagePath();
static QString resourceImageUrl();
-
static QString resourcePath();
-
static QString qmlImportPath();
static qreal devicePixelRatio();
+
+ static bool readFileToDomDocument(const QString &filePath, QDomDocument &domDoc);
+ static bool openDomDocumentSave(QSaveFile &file, QDomDocument &domDoc);
+ static bool commitDomDocumentSave(QSaveFile &file, const QDomDocument &domDoc);
+ static bool openTextSave(QSaveFile &file);
};
#endif // INCLUDED_STUDIO_UTILS_H