aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAli Kianian <ali.kianian@qt.io>2023-11-27 23:50:53 +0200
committerAli Kianian <ali.kianian@qt.io>2023-12-07 14:03:09 +0000
commit3604bde01ab4ebcf8c686855302aee9713804470 (patch)
treec991a2190c34e8f76ab6672b94adce4a62673f1e
parent305fb4cb79822c42619416645aa7b8262e6e9987 (diff)
QmlDesigner: Add DataStore Dynamically to the project
Task-number: QDS-11400 Change-Id: I0ad20a6aad604aa66d4d0f24ca32a19fb9e94a08 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> (cherry picked from commit 4129c7703b0f51ea523b8dda72dc384e4a3cbcf7) Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp144
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h10
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp5
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionview.h1
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp16
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h2
-rw-r--r--src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp22
7 files changed, 166 insertions, 34 deletions
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp
index 6e0328e008..4eeca52964 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.cpp
@@ -11,6 +11,7 @@
#include <variant>
+#include <coreplugin/icore.h>
#include <utils/qtcassert.h>
#include <projectexplorer/project.h>
@@ -66,6 +67,43 @@ struct LessThanVisitor
}
};
+Utils::FilePath findFile(const Utils::FilePath &path, const QString &fileName)
+{
+ QDirIterator it(path.toString(), QDirIterator::Subdirectories);
+
+ while (it.hasNext()) {
+ QFileInfo file(it.next());
+ if (file.isDir())
+ continue;
+
+ if (file.fileName() == fileName)
+ return Utils::FilePath::fromFileInfo(file);
+ }
+ return {};
+}
+
+Utils::FilePath dataStoreDir()
+{
+ using Utils::FilePath;
+ ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectManager::startupProject();
+
+ if (!currentProject)
+ return {};
+
+ return currentProject->projectDirectory().pathAppended("/imports/"
+ + currentProject->displayName());
+}
+
+inline Utils::FilePath collectionPath(const QString &filePath)
+{
+ return dataStoreDir().pathAppended("/" + filePath);
+}
+
+inline Utils::FilePath qmlDirFilePath()
+{
+ return collectionPath("qmldir");
+}
+
} // namespace
namespace QmlDesigner::CollectionEditor {
@@ -126,6 +164,16 @@ void assignCollectionToNode(AbstractView *view,
});
}
+Utils::FilePath dataStoreJsonFilePath()
+{
+ return collectionPath("models.json");
+}
+
+Utils::FilePath dataStoreQmlFilePath()
+{
+ return collectionPath("DataStore.qml");
+}
+
bool canAcceptCollectionAsModel(const ModelNode &node)
{
const NodeMetaInfo nodeMetaInfo = node.metaInfo();
@@ -143,13 +191,10 @@ bool canAcceptCollectionAsModel(const ModelNode &node)
QString getSourceCollectionPath(const ModelNode &dataStoreNode)
{
using Utils::FilePath;
- ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectManager::startupProject();
-
- if (!currentProject || !dataStoreNode.isValid())
+ if (!dataStoreNode.isValid())
return {};
- const FilePath expectedFile = currentProject->projectDirectory().pathAppended(
- "/imports/" + currentProject->displayName() + "/DataStore.json");
+ const FilePath expectedFile = dataStoreJsonFilePath();
if (expectedFile.exists())
return expectedFile.toFSPathString();
@@ -160,13 +205,14 @@ QString getSourceCollectionPath(const ModelNode &dataStoreNode)
bool isDataStoreNode(const ModelNode &dataStoreNode)
{
using Utils::FilePath;
- ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectManager::startupProject();
- if (!currentProject || !dataStoreNode.isValid())
+ if (!dataStoreNode.isValid())
return false;
- const FilePath expectedFile = currentProject->projectDirectory().pathAppended(
- "/imports/" + currentProject->displayName() + "/DataStore.qml");
+ const FilePath expectedFile = dataStoreQmlFilePath();
+
+ if (!expectedFile.exists())
+ return false;
FilePath modelPath = FilePath::fromUserInput(dataStoreNode.model()->fileUrl().toLocalFile());
@@ -183,4 +229,84 @@ QJsonArray defaultCollectionArray()
return initialCollection;
}
+bool ensureDataStoreExists(bool &justCreated)
+{
+ using Utils::FilePath;
+ using Utils::FileReader;
+ using Utils::FileSaver;
+
+ FilePath qmlDestinationPath = dataStoreQmlFilePath();
+ justCreated = false;
+
+ auto extractDependency = [&justCreated](const FilePath &filePath) -> bool {
+ if (filePath.exists())
+ return true;
+
+ const QString templateFileName = filePath.fileName() + u".tpl";
+ const FilePath templatePath = findFile(Core::ICore::resourcePath(), templateFileName);
+ if (!templatePath.exists()) {
+ qWarning() << Q_FUNC_INFO << __LINE__ << templateFileName << "does not exist";
+ return false;
+ }
+
+ templatePath.copyFile(filePath);
+ if (filePath.exists()) {
+ justCreated = true;
+ return true;
+ }
+
+ qWarning() << Q_FUNC_INFO << __LINE__ << "Cannot copy" << templateFileName << "to" << filePath;
+ return false;
+ };
+
+ if (!extractDependency(dataStoreJsonFilePath()))
+ return false;
+
+ if (!extractDependency(collectionPath("data.json")))
+ return false;
+
+ if (!extractDependency(collectionPath("JsonData.qml")))
+ return false;
+
+ if (!qmlDestinationPath.exists()) {
+ if (qmlDestinationPath.ensureExistingFile()) {
+ justCreated = true;
+ } else {
+ qWarning() << Q_FUNC_INFO << __LINE__ << "Can't create DataStore Qml File";
+ return false;
+ }
+ }
+
+ FilePath qmlDirPath = qmlDirFilePath();
+ qmlDirPath.ensureExistingFile();
+
+ FileReader qmlDirReader;
+ if (!qmlDirReader.fetch(qmlDirPath)) {
+ qWarning() << Q_FUNC_INFO << __LINE__ << "Can't read the content of the qmldir";
+ return false;
+ }
+
+ QByteArray qmlDirContent = qmlDirReader.data();
+ const QList<QByteArray> qmlDirLines = qmlDirContent.split('\n');
+ for (const QByteArray &line : qmlDirLines) {
+ if (line.startsWith("singleton DataStore "))
+ return true;
+ }
+
+ if (!qmlDirContent.isEmpty() && qmlDirContent.back() != '\n')
+ qmlDirContent.append("\n");
+ qmlDirContent.append("singleton DataStore 1.0 DataStore.qml\n");
+
+ FileSaver qmlDirSaver(qmlDirPath);
+ qmlDirSaver.write(qmlDirContent);
+
+ if (qmlDirSaver.finalize()) {
+ justCreated = true;
+ return true;
+ }
+
+ qWarning() << Q_FUNC_INFO << __LINE__ << "Can't write to the qmldir file";
+ return false;
+}
+
} // namespace QmlDesigner::CollectionEditor
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h
index 8d226e7a34..835960f671 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectioneditorutils.h
@@ -10,6 +10,10 @@ QT_BEGIN_NAMESPACE
class QJsonArray;
QT_END_NAMESPACE
+namespace Utils {
+class FilePath;
+}
+
namespace QmlDesigner::CollectionEditor {
bool variantIslessThan(const QVariant &a, const QVariant &b, CollectionDetails::DataType type);
@@ -25,8 +29,14 @@ void assignCollectionToNode(AbstractView *view,
const ModelNode &collectionSourceNode,
const QString &collectionName);
+Utils::FilePath dataStoreJsonFilePath();
+
+Utils::FilePath dataStoreQmlFilePath();
+
bool isDataStoreNode(const ModelNode &dataStoreNode);
+bool ensureDataStoreExists(bool &justCreated);
+
bool canAcceptCollectionAsModel(const ModelNode &node);
QJsonArray defaultCollectionArray();
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp
index 8a470c4915..f6a24280d1 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionview.cpp
@@ -211,6 +211,11 @@ void CollectionView::resetDataStoreNode()
refreshModel();
}
+ModelNode CollectionView::dataStoreNode() const
+{
+ return m_dataStore->modelNode();
+}
+
void CollectionView::refreshModel()
{
if (!model())
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionview.h b/src/plugins/qmldesigner/components/collectioneditor/collectionview.h
index bb52f82ac0..dd946776ed 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionview.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionview.h
@@ -46,6 +46,7 @@ public:
static void registerDeclarativeType();
void resetDataStoreNode();
+ ModelNode dataStoreNode() const;
private:
void refreshModel();
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp
index 94edd5da4c..30ae4418ed 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.cpp
@@ -316,6 +316,7 @@ bool CollectionWidget::importCollectionToDataStore(const QString &collectionName
bool CollectionWidget::addCollectionToDataStore(const QString &collectionName)
{
+ ensureDataStoreExists();
const ModelNode node = dataStoreNode();
if (!node.isValid()) {
warn(tr("Can not import to the main model"), tr("The default model node is not available."));
@@ -349,14 +350,17 @@ void CollectionWidget::assignCollectionToSelectedNode(const QString collectionNa
CollectionEditor::assignCollectionToNode(m_view, targetNode, dsNode, collectionName);
}
+void CollectionWidget::ensureDataStoreExists()
+{
+ bool filesJustCreated = false;
+ bool filesExist = CollectionEditor::ensureDataStoreExists(filesJustCreated);
+ if (filesExist && filesJustCreated)
+ m_view->resetDataStoreNode();
+}
+
ModelNode CollectionWidget::dataStoreNode() const
{
- for (int i = 0; i < m_sourceModel->rowCount(); ++i) {
- const ModelNode node = m_sourceModel->sourceNodeAt(i);
- if (CollectionEditor::getSourceCollectionFormat(node) == CollectionEditor::SourceFormat::Json)
- return node;
- }
- return {};
+ return m_view->dataStoreNode();
}
void CollectionWidget::warn(const QString &title, const QString &body)
diff --git a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h
index 6700bf91a4..2be98df190 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h
+++ b/src/plugins/qmldesigner/components/collectioneditor/collectionwidget.h
@@ -54,6 +54,8 @@ public:
Q_INVOKABLE void assignCollectionToSelectedNode(const QString collectionName);
+ Q_INVOKABLE void ensureDataStoreExists();
+
Q_INVOKABLE ModelNode dataStoreNode() const;
void warn(const QString &title, const QString &body);
diff --git a/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp b/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp
index 4b2ab6edbe..446d7ef08f 100644
--- a/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp
+++ b/src/plugins/qmldesigner/components/collectioneditor/datastoremodelnode.cpp
@@ -4,6 +4,7 @@
#include "datastoremodelnode.h"
#include "collectioneditorconstants.h"
+#include "collectioneditorutils.h"
#include "model/qmltextgenerator.h"
#include <model.h>
@@ -23,21 +24,6 @@
namespace {
-Utils::FilePath findFile(const Utils::FilePath &path, const QString &fileName)
-{
- QDirIterator it(path.toString(), QDirIterator::Subdirectories);
-
- while (it.hasNext()) {
- QFileInfo file(it.next());
- if (file.isDir())
- continue;
-
- if (file.fileName() == fileName)
- return Utils::FilePath::fromFileInfo(file);
- }
- return {};
-}
-
QmlDesigner::PropertyNameList createNameList(const QmlDesigner::ModelNode &node)
{
using QmlDesigner::AbstractProperty;
@@ -74,10 +60,8 @@ void DataStoreModelNode::reloadModel()
}
bool forceUpdate = false;
- const FilePath projectFilePath = ProjectExplorer::ProjectManager::startupProject()->projectDirectory();
- const FilePath importsPath = FilePath::fromString(projectFilePath.path() + "/imports");
- FilePath dataStoreQmlPath = findFile(importsPath, "DataStore.qml");
- FilePath dataStoreJsonPath = findFile(importsPath, "DataStore.json");
+ const FilePath dataStoreQmlPath = CollectionEditor::dataStoreQmlFilePath();
+ const FilePath dataStoreJsonPath = CollectionEditor::dataStoreJsonFilePath();
QUrl dataStoreQmlUrl = dataStoreQmlPath.toUrl();
if (dataStoreQmlPath.exists() && dataStoreJsonPath.exists()) {