forked from qt-creator/qt-creator
QmlDesigner: Warn the user if the project is not imported
When the project is not importd in the design document, DataStore cannot be found by the project manager. User should add it to make the Model Editor work. So we will warn the user in the Model Editor view. Task-number: QDS-12119 Change-Id: I313e5553e8b0a0ef3b97c50d61db80c0a8d382f8 Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -498,10 +498,38 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: importsProblem
|
||||||
|
|
||||||
|
visible: !topRow.visible && rootView.dataStoreExists && !rootView.projectImportExists
|
||||||
|
width: parent.width
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: qsTr("Import the project to your design document to make the Model Editor enabled.")
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
Layout.maximumWidth: parent.width
|
||||||
|
leftPadding: StudioTheme.Values.collectionItemTextPadding
|
||||||
|
rightPadding: StudioTheme.Values.collectionItemTextPadding
|
||||||
|
color: StudioTheme.Values.themeTextColor
|
||||||
|
font.pixelSize: StudioTheme.Values.mediumFontSize
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
|
||||||
|
HelperWidgets.Button {
|
||||||
|
text: qsTr("Enable DataStore (This will add the required import)")
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
onClicked: rootView.addProjectImport()
|
||||||
|
leftPadding: StudioTheme.Values.collectionItemTextPadding
|
||||||
|
rightPadding: StudioTheme.Values.collectionItemTextPadding
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: qsTr("There are no models in this project.\nAdd or import a model.")
|
text: qsTr("There are no models in this project.\nAdd or import a model.")
|
||||||
visible: !topRow.visible
|
visible: !topRow.visible && !importsProblem.visible
|
||||||
color: StudioTheme.Values.themeTextColor
|
color: StudioTheme.Values.themeTextColor
|
||||||
font.pixelSize: StudioTheme.Values.mediumFontSize
|
font.pixelSize: StudioTheme.Values.mediumFontSize
|
||||||
}
|
}
|
||||||
|
@@ -35,6 +35,12 @@ bool isStudioCollectionModel(const QmlDesigner::ModelNode &node)
|
|||||||
return node.metaInfo().isQtQuickStudioUtilsJsonListModel();
|
return node.metaInfo().isQtQuickStudioUtilsJsonListModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool isProjectImport(const QmlDesigner::Import &import)
|
||||||
|
{
|
||||||
|
ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectManager::startupProject();
|
||||||
|
return currentProject && import.toString() == currentProject->displayName();
|
||||||
|
}
|
||||||
|
|
||||||
inline void setVariantPropertyValue(const QmlDesigner::ModelNode &node,
|
inline void setVariantPropertyValue(const QmlDesigner::ModelNode &node,
|
||||||
const QmlDesigner::PropertyName &propertyName,
|
const QmlDesigner::PropertyName &propertyName,
|
||||||
const QVariant &value)
|
const QVariant &value)
|
||||||
@@ -98,7 +104,7 @@ QmlDesigner::WidgetInfo CollectionView::widgetInfo()
|
|||||||
|
|
||||||
connect(listModel, &CollectionListModel::modelReset, this, [this] {
|
connect(listModel, &CollectionListModel::modelReset, this, [this] {
|
||||||
CollectionListModel *listModel = m_widget->listModel().data();
|
CollectionListModel *listModel = m_widget->listModel().data();
|
||||||
if (listModel->sourceNode() == m_dataStore->modelNode())
|
if (listModel->sourceNode() == dataStoreNode())
|
||||||
m_dataStore->setCollectionNames(listModel->collections());
|
m_dataStore->setCollectionNames(listModel->collections());
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -140,19 +146,14 @@ QmlDesigner::WidgetInfo CollectionView::widgetInfo()
|
|||||||
void CollectionView::modelAttached(Model *model)
|
void CollectionView::modelAttached(Model *model)
|
||||||
{
|
{
|
||||||
AbstractView::modelAttached(model);
|
AbstractView::modelAttached(model);
|
||||||
|
m_widget->setProjectImportExists(Utils::anyOf(model->imports(), isProjectImport));
|
||||||
resetDataStoreNode();
|
resetDataStoreNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionView::modelAboutToBeDetached([[maybe_unused]] Model *model)
|
void CollectionView::modelAboutToBeDetached([[maybe_unused]] Model *model)
|
||||||
{
|
{
|
||||||
m_libraryInfoIsUpdated = false;
|
unloadDataStore();
|
||||||
m_reloadCounter = 0;
|
m_widget->setProjectImportExists(false);
|
||||||
m_rewriterAmended = false;
|
|
||||||
m_dataStoreTypeFound = false;
|
|
||||||
disconnect(m_documentUpdateConnection);
|
|
||||||
QTC_ASSERT(m_delayedTasks.isEmpty(), m_delayedTasks.clear());
|
|
||||||
if (m_widget)
|
|
||||||
m_widget->listModel()->setDataStoreNode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionView::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
|
void CollectionView::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
|
||||||
@@ -177,6 +178,17 @@ void CollectionView::selectedNodesChanged(const QList<ModelNode> &selectedNodeLi
|
|||||||
m_widget->setTargetNodeSelected(singleSelectedHasModelProperty);
|
m_widget->setTargetNodeSelected(singleSelectedHasModelProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CollectionView::importsChanged(const Imports &addedImports, const Imports &removedImports)
|
||||||
|
{
|
||||||
|
if (Utils::anyOf(addedImports, isProjectImport)) {
|
||||||
|
m_widget->setProjectImportExists(true);
|
||||||
|
resetDataStoreNode();
|
||||||
|
} else if (Utils::anyOf(removedImports, isProjectImport)) {
|
||||||
|
m_widget->setProjectImportExists(false);
|
||||||
|
unloadDataStore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CollectionView::customNotification(const AbstractView *,
|
void CollectionView::customNotification(const AbstractView *,
|
||||||
const QString &identifier,
|
const QString &identifier,
|
||||||
const QList<ModelNode> &nodeList,
|
const QList<ModelNode> &nodeList,
|
||||||
@@ -223,6 +235,22 @@ void CollectionView::addResource(const QUrl &url, const QString &name)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CollectionView::addProjectImport()
|
||||||
|
{
|
||||||
|
if (!m_widget)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectManager::startupProject();
|
||||||
|
if (!currentProject)
|
||||||
|
return;
|
||||||
|
|
||||||
|
executeInTransaction(__FUNCTION__, [&] {
|
||||||
|
Import import = Import::createLibraryImport(currentProject->displayName());
|
||||||
|
if (!model()->hasImport(import, true, true))
|
||||||
|
model()->changeImports({import}, {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void CollectionView::assignCollectionToNode(const QString &collectionName, const ModelNode &node)
|
void CollectionView::assignCollectionToNode(const QString &collectionName, const ModelNode &node)
|
||||||
{
|
{
|
||||||
if (!m_widget)
|
if (!m_widget)
|
||||||
@@ -314,7 +342,8 @@ void CollectionView::resetDataStoreNode()
|
|||||||
|
|
||||||
m_dataStore->reloadModel();
|
m_dataStore->reloadModel();
|
||||||
|
|
||||||
ModelNode dataStore = m_dataStore->modelNode();
|
ModelNode dataStore = dataStoreNode();
|
||||||
|
m_widget->setDataStoreExists(dataStore.isValid());
|
||||||
if (!dataStore || m_widget->listModel()->sourceNode() == dataStore)
|
if (!dataStore || m_widget->listModel()->sourceNode() == dataStore)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -355,28 +384,11 @@ void CollectionView::ensureDataStoreExists()
|
|||||||
{
|
{
|
||||||
bool filesJustCreated = false;
|
bool filesJustCreated = false;
|
||||||
bool filesExist = CollectionEditorUtils::ensureDataStoreExists(filesJustCreated);
|
bool filesExist = CollectionEditorUtils::ensureDataStoreExists(filesJustCreated);
|
||||||
if (filesExist) {
|
if (filesExist && filesJustCreated) {
|
||||||
if (filesJustCreated) {
|
|
||||||
// Force code model reset to notice changes to existing module
|
// Force code model reset to notice changes to existing module
|
||||||
auto modelManager = QmlJS::ModelManagerInterface::instance();
|
if (auto modelManager = QmlJS::ModelManagerInterface::instance())
|
||||||
if (modelManager) {
|
|
||||||
m_libraryInfoIsUpdated = false;
|
|
||||||
|
|
||||||
m_expectedDocumentUpdates.clear();
|
|
||||||
m_expectedDocumentUpdates << CollectionEditorUtils::dataStoreQmlFilePath()
|
|
||||||
<< CollectionEditorUtils::dataStoreJsonFilePath();
|
|
||||||
|
|
||||||
m_documentUpdateConnection = connect(modelManager,
|
|
||||||
&QmlJS::ModelManagerInterface::documentUpdated,
|
|
||||||
this,
|
|
||||||
&CollectionView::onDocumentUpdated);
|
|
||||||
|
|
||||||
modelManager->resetCodeModel();
|
modelManager->resetCodeModel();
|
||||||
}
|
|
||||||
resetDataStoreNode();
|
resetDataStoreNode();
|
||||||
} else {
|
|
||||||
m_libraryInfoIsUpdated = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,6 +408,18 @@ NodeMetaInfo CollectionView::jsonCollectionMetaInfo() const
|
|||||||
return model()->metaInfo(CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME);
|
return model()->metaInfo(CollectionEditorConstants::JSONCOLLECTIONMODEL_TYPENAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CollectionView::unloadDataStore()
|
||||||
|
{
|
||||||
|
m_reloadCounter = 0;
|
||||||
|
m_rewriterAmended = false;
|
||||||
|
m_dataStoreTypeFound = false;
|
||||||
|
QTC_ASSERT(m_delayedTasks.isEmpty(), m_delayedTasks.clear());
|
||||||
|
if (m_widget) {
|
||||||
|
m_widget->setDataStoreExists(dataStoreNode().isValid());
|
||||||
|
m_widget->listModel()->setDataStoreNode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CollectionView::ensureStudioModelImport()
|
void CollectionView::ensureStudioModelImport()
|
||||||
{
|
{
|
||||||
executeInTransaction(__FUNCTION__, [&] {
|
executeInTransaction(__FUNCTION__, [&] {
|
||||||
@@ -420,23 +444,12 @@ void CollectionView::onItemLibraryNodeCreated(const ModelNode &node)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionView::onDocumentUpdated(const QSharedPointer<const QmlJS::Document> &doc)
|
|
||||||
{
|
|
||||||
if (m_expectedDocumentUpdates.contains(doc->fileName()))
|
|
||||||
m_expectedDocumentUpdates.remove(doc->fileName());
|
|
||||||
|
|
||||||
if (m_expectedDocumentUpdates.isEmpty()) {
|
|
||||||
disconnect(m_documentUpdateConnection);
|
|
||||||
m_libraryInfoIsUpdated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CollectionView::addTask(QSharedPointer<CollectionTask> task)
|
void CollectionView::addTask(QSharedPointer<CollectionTask> task)
|
||||||
{
|
{
|
||||||
ensureDataStoreExists();
|
ensureDataStoreExists();
|
||||||
if (m_dataStoreTypeFound)
|
if (m_dataStoreTypeFound)
|
||||||
task->process();
|
task->process();
|
||||||
else if (m_dataStore->modelNode())
|
else if (dataStoreNode())
|
||||||
m_delayedTasks << task;
|
m_delayedTasks << task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -41,6 +41,8 @@ public:
|
|||||||
void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
|
void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
|
||||||
const QList<ModelNode> &lastSelectedNodeList) override;
|
const QList<ModelNode> &lastSelectedNodeList) override;
|
||||||
|
|
||||||
|
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||||
|
|
||||||
void customNotification(const AbstractView *view,
|
void customNotification(const AbstractView *view,
|
||||||
const QString &identifier,
|
const QString &identifier,
|
||||||
const QList<ModelNode> &nodeList,
|
const QList<ModelNode> &nodeList,
|
||||||
@@ -48,6 +50,7 @@ public:
|
|||||||
|
|
||||||
void addResource(const QUrl &url, const QString &name);
|
void addResource(const QUrl &url, const QString &name);
|
||||||
|
|
||||||
|
void addProjectImport();
|
||||||
void assignCollectionToNode(const QString &collectionName, const ModelNode &node);
|
void assignCollectionToNode(const QString &collectionName, const ModelNode &node);
|
||||||
void assignCollectionToSelectedNode(const QString &collectionName);
|
void assignCollectionToSelectedNode(const QString &collectionName);
|
||||||
void addNewCollection(const QString &collectionName, const QJsonObject &localCollection);
|
void addNewCollection(const QString &collectionName, const QJsonObject &localCollection);
|
||||||
@@ -65,17 +68,14 @@ private:
|
|||||||
friend class CollectionTask;
|
friend class CollectionTask;
|
||||||
|
|
||||||
NodeMetaInfo jsonCollectionMetaInfo() const;
|
NodeMetaInfo jsonCollectionMetaInfo() const;
|
||||||
|
void unloadDataStore();
|
||||||
void ensureStudioModelImport();
|
void ensureStudioModelImport();
|
||||||
void onItemLibraryNodeCreated(const ModelNode &node);
|
void onItemLibraryNodeCreated(const ModelNode &node);
|
||||||
void onDocumentUpdated(const QSharedPointer<const QmlJS::Document> &doc);
|
|
||||||
void addTask(QSharedPointer<CollectionTask> task);
|
void addTask(QSharedPointer<CollectionTask> task);
|
||||||
|
|
||||||
std::unique_ptr<DataStoreModelNode> m_dataStore;
|
std::unique_ptr<DataStoreModelNode> m_dataStore;
|
||||||
Utils::UniqueObjectPtr<CollectionWidget> m_widget;
|
Utils::UniqueObjectPtr<CollectionWidget> m_widget;
|
||||||
QSet<Utils::FilePath> m_expectedDocumentUpdates;
|
|
||||||
QList<QSharedPointer<CollectionTask>> m_delayedTasks;
|
QList<QSharedPointer<CollectionTask>> m_delayedTasks;
|
||||||
QMetaObject::Connection m_documentUpdateConnection;
|
|
||||||
bool m_libraryInfoIsUpdated = false;
|
|
||||||
bool m_dataStoreTypeFound = false;
|
bool m_dataStoreTypeFound = false;
|
||||||
bool m_rewriterAmended = false;
|
bool m_rewriterAmended = false;
|
||||||
int m_reloadCounter = 0;
|
int m_reloadCounter = 0;
|
||||||
|
@@ -251,6 +251,11 @@ bool CollectionWidget::importFile(const QString &collectionName,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CollectionWidget::addProjectImport()
|
||||||
|
{
|
||||||
|
m_view->addProjectImport();
|
||||||
|
}
|
||||||
|
|
||||||
void CollectionWidget::addCollectionToDataStore(const QString &collectionName)
|
void CollectionWidget::addCollectionToDataStore(const QString &collectionName)
|
||||||
{
|
{
|
||||||
m_view->addNewCollection(collectionName, CollectionEditorUtils::defaultCollection());
|
m_view->addNewCollection(collectionName, CollectionEditorUtils::defaultCollection());
|
||||||
@@ -289,6 +294,24 @@ void CollectionWidget::setTargetNodeSelected(bool selected)
|
|||||||
emit targetNodeSelectedChanged(m_targetNodeSelected);
|
emit targetNodeSelectedChanged(m_targetNodeSelected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CollectionWidget::setProjectImportExists(bool exists)
|
||||||
|
{
|
||||||
|
if (m_projectImportExists == exists)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_projectImportExists = exists;
|
||||||
|
emit projectImportExistsChanged(m_projectImportExists);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CollectionWidget::setDataStoreExists(bool exists)
|
||||||
|
{
|
||||||
|
if (m_dataStoreExists == exists)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_dataStoreExists = exists;
|
||||||
|
emit dataStoreExistsChanged(m_dataStoreExists);
|
||||||
|
}
|
||||||
|
|
||||||
void CollectionWidget::deleteSelectedCollection()
|
void CollectionWidget::deleteSelectedCollection()
|
||||||
{
|
{
|
||||||
QMetaObject::invokeMethod(m_quickWidget->quickWidget()->rootObject(), "deleteSelectedCollection");
|
QMetaObject::invokeMethod(m_quickWidget->quickWidget()->rootObject(), "deleteSelectedCollection");
|
||||||
|
@@ -22,6 +22,8 @@ class CollectionWidget : public QFrame
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PROPERTY(bool targetNodeSelected MEMBER m_targetNodeSelected NOTIFY targetNodeSelectedChanged)
|
Q_PROPERTY(bool targetNodeSelected MEMBER m_targetNodeSelected NOTIFY targetNodeSelectedChanged)
|
||||||
|
Q_PROPERTY(bool projectImportExists MEMBER m_projectImportExists NOTIFY projectImportExistsChanged)
|
||||||
|
Q_PROPERTY(bool dataStoreExists MEMBER m_dataStoreExists NOTIFY dataStoreExistsChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CollectionWidget(CollectionView *view);
|
CollectionWidget(CollectionView *view);
|
||||||
@@ -33,7 +35,7 @@ public:
|
|||||||
|
|
||||||
void reloadQmlSource();
|
void reloadQmlSource();
|
||||||
|
|
||||||
virtual QSize minimumSizeHint() const;
|
QSize minimumSizeHint() const override;
|
||||||
|
|
||||||
Q_INVOKABLE bool loadJsonFile(const QUrl &url, const QString &collectionName = {});
|
Q_INVOKABLE bool loadJsonFile(const QUrl &url, const QString &collectionName = {});
|
||||||
Q_INVOKABLE bool loadCsvFile(const QUrl &url, const QString &collectionName = {});
|
Q_INVOKABLE bool loadCsvFile(const QUrl &url, const QString &collectionName = {});
|
||||||
@@ -45,6 +47,7 @@ public:
|
|||||||
const QUrl &url,
|
const QUrl &url,
|
||||||
const bool &firstRowIsHeader = true);
|
const bool &firstRowIsHeader = true);
|
||||||
|
|
||||||
|
Q_INVOKABLE void addProjectImport();
|
||||||
Q_INVOKABLE void addCollectionToDataStore(const QString &collectionName);
|
Q_INVOKABLE void addCollectionToDataStore(const QString &collectionName);
|
||||||
Q_INVOKABLE void assignCollectionToSelectedNode(const QString collectionName);
|
Q_INVOKABLE void assignCollectionToSelectedNode(const QString collectionName);
|
||||||
Q_INVOKABLE void openCollection(const QString &collectionName);
|
Q_INVOKABLE void openCollection(const QString &collectionName);
|
||||||
@@ -52,11 +55,15 @@ public:
|
|||||||
|
|
||||||
void warn(const QString &title, const QString &body);
|
void warn(const QString &title, const QString &body);
|
||||||
void setTargetNodeSelected(bool selected);
|
void setTargetNodeSelected(bool selected);
|
||||||
|
void setProjectImportExists(bool exists);
|
||||||
|
void setDataStoreExists(bool exists);
|
||||||
|
|
||||||
void deleteSelectedCollection();
|
void deleteSelectedCollection();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void targetNodeSelectedChanged(bool);
|
void targetNodeSelectedChanged(bool);
|
||||||
|
void projectImportExistsChanged(bool);
|
||||||
|
void dataStoreExistsChanged(bool);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString generateUniqueCollectionName(const ModelNode &node, const QString &name);
|
QString generateUniqueCollectionName(const ModelNode &node, const QString &name);
|
||||||
@@ -67,6 +74,8 @@ private:
|
|||||||
std::unique_ptr<CollectionDetailsSortFilterModel> m_collectionDetailsSortFilterModel;
|
std::unique_ptr<CollectionDetailsSortFilterModel> m_collectionDetailsSortFilterModel;
|
||||||
QScopedPointer<StudioQuickWidget> m_quickWidget;
|
QScopedPointer<StudioQuickWidget> m_quickWidget;
|
||||||
bool m_targetNodeSelected = false;
|
bool m_targetNodeSelected = false;
|
||||||
|
bool m_projectImportExists = false;
|
||||||
|
bool m_dataStoreExists = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
Reference in New Issue
Block a user