summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMahmoud Badri <mahmoud.badri@qt.io>2019-02-14 11:42:37 +0200
committerMahmoud Badri <mahmoud.badri@qt.io>2019-02-18 17:58:33 +0000
commit6acfb03a5a3bcc8e49b24ba1611b78df2ba4981a (patch)
treedecf1b42e26d881f1a600afb3110fd789255db96
parent33764aa97c0f176d54c2e02817e533c0c0be6903 (diff)
implement variants import and export features
Task-number: QT3DS-3047 Change-Id: Ifa7986c4a7ca7934cf903c005b9df19d9fb75924 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io> Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
-rw-r--r--src/Authoring/Studio/Application/ProjectFile.cpp146
-rw-r--r--src/Authoring/Studio/Application/ProjectFile.h2
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/InspectorControlView.qml4
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/VariantsGroupModel.cpp52
-rw-r--r--src/Authoring/Studio/Palettes/Inspector/VariantsGroupModel.h2
-rw-r--r--src/Authoring/Studio/Workspace/Dialogs.cpp36
-rw-r--r--src/Authoring/Studio/Workspace/Dialogs.h2
7 files changed, 190 insertions, 54 deletions
diff --git a/src/Authoring/Studio/Application/ProjectFile.cpp b/src/Authoring/Studio/Application/ProjectFile.cpp
index dd8c8fa5..c4a09b8e 100644
--- a/src/Authoring/Studio/Application/ProjectFile.cpp
+++ b/src/Authoring/Studio/Application/ProjectFile.cpp
@@ -931,38 +931,94 @@ ProjectFile::getDiBindingtypesFromSubpresentations() const
return map;
}
-// load variant data from uia to m_variantsDef
-void ProjectFile::loadVariants()
+/**
+ * Load variants data to m_variantsDef
+ *
+ * @param filePath the file path to load the variants from. If empty, variants are loaded from the
+ * project file and replace m_variantsDef. If a filePath is specified, the loaded
+ * variants are merged with m_variantsDef
+ */
+void ProjectFile::loadVariants(const QString &filePath)
{
if (!m_fileInfo.exists())
return;
- QFile file(getProjectFilePath());
+ bool isProj = filePath.isEmpty() || filePath == getProjectFilePath();
+ QFile file(isProj ? getProjectFilePath() : filePath);
if (!file.open(QFile::Text | QFile::ReadOnly)) {
qWarning() << file.errorString();
return;
}
- m_variantsDef.clear();
+ if (isProj)
+ m_variantsDef.clear();
QXmlStreamReader reader(&file);
reader.setNamespaceProcessing(false);
+ VariantGroup *currentGroup = nullptr;
while (!reader.atEnd()) {
if (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("variantgroup")) {
- VariantGroup g;
- g.m_title = reader.attributes().value(QLatin1String("id")).toString();
- g.m_color = reader.attributes().value(QLatin1String("color")).toString();
- m_variantsDef.append(g);
+ QString groupId = reader.attributes().value(QLatin1String("id")).toString();
+ QString groupColor = reader.attributes().value(QLatin1String("color")).toString();
+ auto it = std::find_if(m_variantsDef.begin(), m_variantsDef.end(),
+ [&](const VariantGroup &vg) -> bool {
+ return vg.m_title == groupId;
+ });
+
+ if (it != m_variantsDef.end()) { // group exists, override it
+ currentGroup = it;
+ } else {
+ VariantGroup g;
+ m_variantsDef.append(g);
+ currentGroup = &m_variantsDef.last();
+ }
+ currentGroup->m_title = groupId;
+ currentGroup->m_color = groupColor;
} else if (reader.name() == QLatin1String("variant")) {
- m_variantsDef.last().m_tags.append(reader.attributes().value(
- QLatin1String("id")).toString());
- } else if (m_variantsDef.length() > 0) {
+ if (currentGroup) {
+ QString tagId = reader.attributes().value(QLatin1String("id")).toString();
+ if (!currentGroup->m_tags.contains(tagId))
+ currentGroup->m_tags.append(tagId);
+ } else {
+ qWarning() << "Error parsing variant tags.";
+ }
+ } else if (currentGroup) {
break;
}
}
}
+
+ if (!isProj) {
+ // if loading variants from a file, update the uia
+ QDomDocument domDoc;
+ QSaveFile fileProj(getProjectFilePath());
+ if (!StudioUtils::openDomDocumentSave(fileProj, domDoc))
+ return;
+
+ QDomElement vElem = domDoc.documentElement().firstChildElement(QStringLiteral("variants"));
+ if (!vElem.isNull())
+ domDoc.documentElement().removeChild(vElem);
+
+ vElem = domDoc.createElement(QStringLiteral("variants"));
+ domDoc.documentElement().appendChild(vElem);
+
+ for (auto &g : qAsConst(m_variantsDef)) {
+ QDomElement gElem = domDoc.createElement(QStringLiteral("variantgroup"));
+ gElem.setAttribute(QStringLiteral("id"), g.m_title);
+ gElem.setAttribute(QStringLiteral("color"), g.m_color);
+ vElem.appendChild(gElem);
+
+ for (auto &t : qAsConst(g.m_tags)) {
+ QDomElement tElem = domDoc.createElement(QStringLiteral("variant"));
+ tElem.setAttribute(QStringLiteral("id"), t);
+ gElem.appendChild(tElem);
+ }
+ }
+
+ StudioUtils::commitDomDocumentSave(fileProj, domDoc);
+ }
}
// Add a new tag to a variants group
@@ -991,9 +1047,9 @@ void ProjectFile::addVariantTag(const QString &group, const QString &newTag)
}
// update m_variantsDef
- for (auto &v : m_variantsDef) {
- if (v.m_title == group) {
- v.m_tags.append(newTag);
+ for (auto &g : m_variantsDef) {
+ if (g.m_title == group) {
+ g.m_tags.append(newTag);
break;
}
}
@@ -1192,33 +1248,12 @@ void ProjectFile::deleteVariantGroup(const QString &group)
for (int i = 0; i < presElems.count(); ++i) {
QString pPath = m_fileInfo.path() + QLatin1Char('/')
+ presElems.at(i).toElement().attribute(QStringLiteral("src"));
- if (groupExistsInUip(pPath, group)) {
+ if (pPath != doc->GetDocumentPath() && groupExistsInUip(pPath, group)) {
inUseIdx = i;
break;
}
}
- // check that the group is in use in the current doc (could be set in the property but not saved)
- auto propertySystem = doc->GetStudioSystem()->GetPropertySystem();
- auto bridge = doc->GetStudioSystem()->GetClientDataModelBridge();
- int instance = doc->GetSelectedInstance();
- int property = propertySystem->GetAggregateInstancePropertyByName(instance, L"variants");
- QString propVal;
- if (inUseIdx == -1) {
- if (instance != 0 && bridge->IsLayerInstance(instance)) {
- qt3dsdm::SValue sValue;
- if (propertySystem->GetInstancePropertyValue(instance, property, sValue)) {
- propVal = QString::fromWCharArray(qt3dsdm::get<qt3dsdm::TDataStrPtr>(sValue)
- ->GetData());
- if (propVal.contains(group + QLatin1Char(':'))) {
- // this big value will trigger the in-use warning, but will skip updating the
- // uips which is not needed.
- inUseIdx = 9999;
- }
- }
- }
- }
-
if (inUseIdx != -1) {
QMessageBox box;
box.setWindowTitle(tr("Group tags in use"));
@@ -1236,15 +1271,6 @@ void ProjectFile::deleteVariantGroup(const QString &group)
if (pPath != doc->GetDocumentPath())
deleteGroupFromUip(pPath, group);
}
- if (inUseIdx == 9999) {
- // property has the deleted group, need to update it, else the deleted group
- // will be saved the uip if the user saves the presentation.
- QRegExp rgx(group + ":\\w*,|," + group + ":\\w*");
- propVal.replace(rgx, {});
- qt3dsdm::SValue sVal = std::make_shared<qt3dsdm::CDataStr>(
- Q3DStudio::CString::fromQString(propVal));
- propertySystem->SetInstancePropertyValue(instance, property, sVal);
- }
break;
default:
@@ -1253,13 +1279,37 @@ void ProjectFile::deleteVariantGroup(const QString &group)
}
}
- // delete the group from current doc, if exists
+ // delete the group from current uip, if exists
deleteGroupFromUip(doc->GetDocumentPath(), group);
+ // delete the group from the property (if set)
+ auto propertySystem = doc->GetStudioSystem()->GetPropertySystem();
+ auto bridge = doc->GetStudioSystem()->GetClientDataModelBridge();
+ int instance = doc->GetSelectedInstance();
+ int property = propertySystem->GetAggregateInstancePropertyByName(instance, L"variants");
+ QString propVal;
+ if (instance != 0 && bridge->IsLayerInstance(instance)) {
+ qt3dsdm::SValue sValue;
+ if (propertySystem->GetInstancePropertyValue(instance, property, sValue)) {
+ propVal = QString::fromWCharArray(qt3dsdm::get<qt3dsdm::TDataStrPtr>(sValue)
+ ->GetData());
+ if (propVal.contains(group + QLatin1Char(':'))) {
+ // property has the deleted group, need to update it, else the deleted group
+ // will be saved the uip if the user saves the presentation.
+ QRegExp rgx(group + ":\\w*,*|," + group + ":\\w*");
+ propVal.replace(rgx, {});
+ qt3dsdm::SValue sVal = std::make_shared<qt3dsdm::CDataStr>(
+ Q3DStudio::CString::fromQString(propVal));
+ propertySystem->SetInstancePropertyValue(instance, property, sVal);
+ }
+ }
+ }
+
+ // update and save the uia
QDomElement variantsElem = domDoc.documentElement()
.firstChildElement(QStringLiteral("variants"));
QDomNodeList groupsElems = variantsElem.elementsByTagName(QStringLiteral("variantgroup"));
- // update and save the uia
+
bool deleted = false;
for (int i = 0; i < groupsElems.count(); ++i) {
QDomElement gElem = groupsElems.at(i).toElement();
@@ -1462,7 +1512,7 @@ void ProjectFile::deleteGroupFromUip(const QString &src, const QString &group)
QDomNodeList layerElems = domDoc.documentElement()
.elementsByTagName(QStringLiteral("Layer"));
bool needSave = false;
- QRegExp rgx(group + ":\\w*,|," + group + ":\\w*");
+ QRegExp rgx(group + ":\\w*,*|," + group + ":\\w*");
for (int i = 0; i < layerElems.count(); ++i) {
QDomElement lElem = layerElems.at(i).toElement();
if (lElem.hasAttribute(QStringLiteral("variants"))) {
diff --git a/src/Authoring/Studio/Application/ProjectFile.h b/src/Authoring/Studio/Application/ProjectFile.h
index 390ccb4c..6b138666 100644
--- a/src/Authoring/Studio/Application/ProjectFile.h
+++ b/src/Authoring/Studio/Application/ProjectFile.h
@@ -87,7 +87,7 @@ public:
void deletePresentationFile(const QString &filePath);
void renameMaterial(const QString &oldName, const QString &newName);
bool duplicatePresentation(const QString &oldPres, const QString &newPres);
- void loadVariants();
+ void loadVariants(const QString &filePath = {});
void addVariantTag(const QString &group, const QString &newTag);
void renameVariantTag(const QString &group, const QString &oldTag, const QString &newTag);
void deleteVariantTag(const QString &group, const QString &tag);
diff --git a/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.qml b/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.qml
index 623af241..4ccff8ee 100644
--- a/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.qml
+++ b/src/Authoring/Studio/Palettes/Inspector/InspectorControlView.qml
@@ -1124,7 +1124,7 @@ Rectangle {
height: 20
onClicked: {
- // TODO: implement
+ _variantsGroupModel.importVariants()
}
}
@@ -1136,7 +1136,7 @@ Rectangle {
enabled: !_variantsGroupModel.variantsEmpty
onClicked: {
- // TODO: implement
+ _variantsGroupModel.exportVariants()
}
}
}
diff --git a/src/Authoring/Studio/Palettes/Inspector/VariantsGroupModel.cpp b/src/Authoring/Studio/Palettes/Inspector/VariantsGroupModel.cpp
index ac0cc2b5..87219554 100644
--- a/src/Authoring/Studio/Palettes/Inspector/VariantsGroupModel.cpp
+++ b/src/Authoring/Studio/Palettes/Inspector/VariantsGroupModel.cpp
@@ -35,6 +35,9 @@
#include "ClientDataModelBridge.h"
#include "IDocumentEditor.h"
#include "VariantTagDialog.h"
+#include "StudioUtils.h"
+#include "Dialogs.h"
+#include <QtCore/qsavefile.h>
VariantsGroupModel::VariantsGroupModel(QObject *parent)
: QAbstractListModel(parent)
@@ -65,9 +68,9 @@ void VariantsGroupModel::refresh()
QString val = QString::fromWCharArray(
qt3dsdm::get<qt3dsdm::TDataStrPtr>(sValue)->GetData());
// TODO: remove qDebug when the variants work is fully done.
- qDebug() << "\x1b[42m \x1b[1m" << __FUNCTION__
- << ", val=" << val
- << "\x1b[m";
+// qDebug() << "\x1b[42m \x1b[1m" << __FUNCTION__
+// << ", val=" << val
+// << "\x1b[m";
QHash<QString, QStringList> propTags;
if (!val.isEmpty()) {
const QStringList propTagsList = val.split(QChar(','));
@@ -161,6 +164,49 @@ void VariantsGroupModel::addNewTag(const QString &group)
g_StudioApp.GetCore()->getProjectFile().addVariantTag(group, dlg.getNames().second);
}
+void VariantsGroupModel::importVariants()
+{
+ QString importFilePath = g_StudioApp.GetDialogs()->getImportVariantsDlg();
+
+ if (!importFilePath.isEmpty()) {
+ g_StudioApp.GetCore()->getProjectFile().loadVariants(importFilePath);
+ refresh();
+ }
+}
+
+void VariantsGroupModel::exportVariants()
+{
+ QString exportFilePath = g_StudioApp.GetDialogs()->getExportVariantsDlg();
+
+ if (exportFilePath.isEmpty())
+ return;
+
+ QDomDocument domDoc;
+ domDoc.appendChild(domDoc.createProcessingInstruction(QStringLiteral("xml"),
+ QStringLiteral("version=\"1.0\""
+ " encoding=\"utf-8\"")));
+
+ const auto variantsDef = g_StudioApp.GetCore()->getProjectFile().variantsDef();
+ QDomElement vElem = domDoc.createElement(QStringLiteral("variants"));
+ domDoc.appendChild(vElem);
+ for (auto &g : variantsDef) {
+ QDomElement gElem = domDoc.createElement(QStringLiteral("variantgroup"));
+ gElem.setAttribute(QStringLiteral("id"), g.m_title);
+ gElem.setAttribute(QStringLiteral("color"), g.m_color);
+ vElem.appendChild(gElem);
+
+ for (auto &t : qAsConst(g.m_tags)) {
+ QDomElement tElem = domDoc.createElement(QStringLiteral("variant"));;
+ tElem.setAttribute(QStringLiteral("id"), t);
+ gElem.appendChild(tElem);
+ }
+ }
+
+ QSaveFile file(exportFilePath);
+ if (StudioUtils::openTextSave(file))
+ StudioUtils::commitDomDocumentSave(file, domDoc);
+}
+
void VariantsGroupModel::addNewGroup()
{
VariantTagDialog dlg(VariantTagDialog::AddGroup);
diff --git a/src/Authoring/Studio/Palettes/Inspector/VariantsGroupModel.h b/src/Authoring/Studio/Palettes/Inspector/VariantsGroupModel.h
index fdebebfc..75a218f7 100644
--- a/src/Authoring/Studio/Palettes/Inspector/VariantsGroupModel.h
+++ b/src/Authoring/Studio/Palettes/Inspector/VariantsGroupModel.h
@@ -68,6 +68,8 @@ public:
Q_INVOKABLE void setTagState(const QString &group, const QString &tag, bool selected);
Q_INVOKABLE void addNewTag(const QString &group);
Q_INVOKABLE void addNewGroup();
+ Q_INVOKABLE void importVariants();
+ Q_INVOKABLE void exportVariants();
protected:
diff --git a/src/Authoring/Studio/Workspace/Dialogs.cpp b/src/Authoring/Studio/Workspace/Dialogs.cpp
index 093f154d..96a6680a 100644
--- a/src/Authoring/Studio/Workspace/Dialogs.cpp
+++ b/src/Authoring/Studio/Workspace/Dialogs.cpp
@@ -1151,6 +1151,42 @@ QString CDialogs::GetSaveAsChoice(const QString &inDialogTitle, bool isProject,
return theFile;
}
+QString CDialogs::getImportVariantsDlg()
+{
+ QString docDir = QFileInfo(g_StudioApp.GetCore()->GetDoc()->GetDocumentPath()).absolutePath();
+
+ QFileDialog dlg;
+ dlg.setDirectory(docDir);
+ dlg.setWindowTitle(tr("Import variants"));
+ dlg.setDefaultSuffix(QStringLiteral(".variants"));
+ dlg.setNameFilters({tr("All supported files (*.variants *.uia)"),
+ tr("Variants files (*.variants)"), tr("Project files (*.uia)")});
+ dlg.exec();
+
+ if (!dlg.selectedFiles().empty())
+ return dlg.selectedFiles().front();
+
+ return {};
+}
+
+QString CDialogs::getExportVariantsDlg()
+{
+ QString docDir = QFileInfo(g_StudioApp.GetCore()->GetDoc()->GetDocumentPath()).absolutePath();
+
+ QFileDialog dlg;
+ dlg.setDirectory(docDir);
+ dlg.setAcceptMode(QFileDialog::AcceptSave);
+ dlg.setWindowTitle(tr("Export variants"));
+ dlg.setDefaultSuffix(QStringLiteral(".variants"));
+ dlg.setNameFilters({QObject::tr("Variants files (*.variants)")});
+ dlg.exec();
+
+ if (!dlg.selectedFiles().empty())
+ return dlg.selectedFiles().front();
+
+ return {};
+}
+
//==============================================================================
/**
* Prompt the user for a file to create.
diff --git a/src/Authoring/Studio/Workspace/Dialogs.h b/src/Authoring/Studio/Workspace/Dialogs.h
index 2579e61f..3f40bc50 100644
--- a/src/Authoring/Studio/Workspace/Dialogs.h
+++ b/src/Authoring/Studio/Workspace/Dialogs.h
@@ -137,6 +137,8 @@ public:
bool isCopy = false);
QString GetNewDocumentChoice(const QString &inInitialDirectory = {}, bool isProject = true);
QString GetFileOpenChoice(const QString &inInitialDirectory = {});
+ QString getExportVariantsDlg();
+ QString getImportVariantsDlg();
void DisplayImportFailed(const QUrl &inURL, const QString &inDescription, bool inWarningsOnly);
void DisplayLoadingPresentationFailed(const QFileInfo &loadFileInfo,