From c11f5ebd4205ff66559ed625adb620420bb3bea7 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Wed, 17 Mar 2021 15:04:41 +0200 Subject: [PATCH] QmlDesigner: add directory import support to the item library Also: - fix removing used directory imports from possible imports. - query imports from a hash for improved performance. Fixes: QDS-3974 Change-Id: I69d072e24d39d3fa931493ab3cf2f821d5574c85 Reviewed-by: Thomas Hartmann --- .../itemlibrary/itemlibraryaddimportmodel.cpp | 11 ++--- .../itemlibrary/itemlibraryimport.cpp | 11 +++++ .../itemlibrary/itemlibraryimport.h | 1 + .../itemlibrary/itemlibrarymodel.cpp | 41 +++++++++++++------ .../qmldesigner/designercore/include/import.h | 2 +- .../qmldesigner/designercore/model/import.cpp | 4 +- .../designercore/model/texttomodelmerger.cpp | 12 ++++-- 7 files changed, 56 insertions(+), 26 deletions(-) diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.cpp index 4c89d339353..f0a02270b21 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryaddimportmodel.cpp @@ -58,16 +58,15 @@ QVariant ItemLibraryAddImportModel::data(const QModelIndex &index, int role) con if (!index.isValid() || index.row() >= m_importList.count()) return {}; - QString importUrl = m_importList[index.row()].url(); - + Import import = m_importList[index.row()]; if (m_roleNames[role] == "importUrl") - return importUrl; + return m_importList[index.row()].toString(true, true); if (m_roleNames[role] == "importVisible") - return m_searchText.isEmpty() || importUrl.isEmpty() || m_importFilterList.contains(importUrl); + return m_searchText.isEmpty() || import.url().isEmpty() || m_importFilterList.contains(import.url()); if (m_roleNames[role] == "isSeparator") - return importUrl.isEmpty(); + return import.isEmpty(); qWarning() << Q_FUNC_INFO << "invalid role requested"; @@ -132,13 +131,11 @@ void ItemLibraryAddImportModel::update(const QList &possibleImports) // create import sections bool previousIsPriority = false; for (const Import &import : std::as_const(filteredImports)) { - if (import.isLibraryImport()) { bool currentIsPriority = m_priorityImports.contains(import.url()); if (previousIsPriority && !currentIsPriority) m_importList.append(Import::empty()); // empty import acts as a separator m_importList.append(import); previousIsPriority = currentIsPriority; - } } endResetModel(); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.cpp index a2b1073594e..9276ea1fb12 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.cpp @@ -50,6 +50,9 @@ QString ItemLibraryImport::importName() const if (importUrl() == "QtQuick") return tr("Default Components"); + if (m_import.isFileImport()) + return m_import.toString(true, true); + return importUrl().replace('.', ' '); } @@ -64,6 +67,9 @@ QString ItemLibraryImport::importUrl() const if (m_sectionType == SectionType::Unimported) return unimportedComponentsTitle(); + if (m_import.isFileImport()) + return m_import.file(); + return m_import.url(); } @@ -168,6 +174,11 @@ bool ItemLibraryImport::hasCategories() const return m_categoryModel.rowCount() > 0; } +bool ItemLibraryImport::hasSingleCategory() const +{ + return m_categoryModel.rowCount() == 1; +} + void ItemLibraryImport::sortCategorySections() { m_categoryModel.sortCategorySections(); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h index 997ca65c714..10d1ea92807 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryimport.h @@ -65,6 +65,7 @@ public: bool importUsed() const; bool importRemovable() const; bool hasCategories() const; + bool hasSingleCategory() const; ItemLibraryCategory *getCategorySection(const QString &categoryName) const; void addCategory(ItemLibraryCategory *category); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp index 66483939016..c07614ca3b8 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarymodel.cpp @@ -214,10 +214,15 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model) // create import sections QHash importHash; for (const Import &import : model->imports()) { - if (import.isLibraryImport() && import.url() != projectName) { + if (import.url() != projectName) { bool addNew = true; bool isQuick3DAsset = import.url().startsWith("Quick3DAssets."); - QString importUrl = isQuick3DAsset ? ItemLibraryImport::quick3DAssetsTitle() : import.url(); + QString importUrl = import.url(); + if (isQuick3DAsset) + importUrl = ItemLibraryImport::quick3DAssetsTitle(); + else if (import.isFileImport()) + importUrl = import.toString(true, true).remove("\""); + ItemLibraryImport *oldImport = importHash.value(importUrl); if (oldImport && oldImport->sectionType() == ItemLibraryImport::SectionType::Quick3DAssets && isQuick3DAsset) { @@ -280,28 +285,36 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model) QString catName = entry.category(); if (isUsable) { if (catName == ItemLibraryImport::userComponentsTitle()) { - // create an import section for user components - importSection = importByUrl(ItemLibraryImport::userComponentsTitle()); - if (!importSection) { - importSection = new ItemLibraryImport( - {}, this, ItemLibraryImport::SectionType::User); - m_importList.append(importSection); - importSection->setImportExpanded(loadExpandedState(catName)); + if (entry.requiredImport().isEmpty()) { // user components + importSection = importHash[ItemLibraryImport::userComponentsTitle()]; + if (!importSection) { + importSection = new ItemLibraryImport( + {}, this, ItemLibraryImport::SectionType::User); + m_importList.append(importSection); + importHash.insert(ItemLibraryImport::userComponentsTitle(), importSection); + importSection->setImportExpanded(loadExpandedState(catName)); + } + } else { // directory import + importSection = importHash[entry.requiredImport()]; + } } else if (catName == "My Quick3D Components") { - importSection = importByUrl(ItemLibraryImport::quick3DAssetsTitle()); + importSection = importHash[ItemLibraryImport::quick3DAssetsTitle()]; } else { if (catName.startsWith("Qt Quick - ")) catName = catName.mid(11); // remove "Qt Quick - " - importSection = importByUrl(entry.requiredImport()); + + importSection = importHash[entry.requiredImport().isEmpty() ? "QtQuick" + : entry.requiredImport()]; } } else { catName = ItemLibraryImport::unimportedComponentsTitle(); - importSection = importByUrl(catName); + importSection = importHash[catName]; if (!importSection) { importSection = new ItemLibraryImport( {}, this, ItemLibraryImport::SectionType::Unimported); m_importList.append(importSection); + importHash.insert(ItemLibraryImport::unimportedComponentsTitle(), importSection); importSection->setImportExpanded(loadExpandedState(catName)); } } @@ -316,8 +329,10 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model) if (!categorySection) { categorySection = new ItemLibraryCategory(catName, importSection); importSection->addCategory(categorySection); - if (importSection->sectionType() == ItemLibraryImport::SectionType::Default) + if (importSection->sectionType() == ItemLibraryImport::SectionType::Default + && !importSection->hasSingleCategory()) { categorySection->setExpanded(loadExpandedState(categorySection->categoryName())); + } } // create item diff --git a/src/plugins/qmldesigner/designercore/include/import.h b/src/plugins/qmldesigner/designercore/include/import.h index 573e682c0b5..88689722c67 100644 --- a/src/plugins/qmldesigner/designercore/include/import.h +++ b/src/plugins/qmldesigner/designercore/include/import.h @@ -54,7 +54,7 @@ public: QString alias() const { return m_alias; } QStringList importPaths() const { return m_importPathList; } - QString toString(bool skipAlias = false) const; + QString toString(bool skipAlias = false, bool skipVersion = false) const; QString toImportString() const; bool operator==(const Import &other) const; diff --git a/src/plugins/qmldesigner/designercore/model/import.cpp b/src/plugins/qmldesigner/designercore/model/import.cpp index 7b9c2c56c42..16b1c68c241 100644 --- a/src/plugins/qmldesigner/designercore/model/import.cpp +++ b/src/plugins/qmldesigner/designercore/model/import.cpp @@ -64,7 +64,7 @@ Import::Import(const QString &url, const QString &file, const QString &version, { } -QString Import::toString(bool skipAlias) const +QString Import::toString(bool skipAlias, bool skipVersion) const { QString result; @@ -75,7 +75,7 @@ QString Import::toString(bool skipAlias) const else return QString(); - if (hasVersion()) + if (hasVersion() && !skipVersion) result += QLatin1Char(' ') + version(); if (hasAlias() && !skipAlias) diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index 309ab558f23..2a23466e094 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -870,14 +870,20 @@ static void removeUsedImports(QHash &filteredPossibleImportK filteredPossibleImportKeys.remove(import.info.path()); } -static QList generatePossibleFileImports(const QString &path) +static QList generatePossibleFileImports(const QString &path, + const QList &usedImports) { + QSet usedImportsSet; + for (const QmlJS::Import &i : usedImports) + usedImportsSet.insert(i.info.path()); + QList possibleImports; foreach (const QString &subDir, QDir(path).entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot)) { QDir dir(path + "/" + subDir); if (!dir.entryInfoList(QStringList("*.qml"), QDir::Files).isEmpty() - && dir.entryInfoList(QStringList("qmldir"), QDir::Files).isEmpty()) { + && dir.entryInfoList(QStringList("qmldir"), QDir::Files).isEmpty() + && !usedImportsSet.contains(dir.path())) { QmlDesigner::Import import = QmlDesigner::Import::createFileImport(subDir); possibleImports.append(import); } @@ -914,7 +920,7 @@ void TextToModelMerger::setupPossibleImports(const QmlJS::Snapshot &snapshot, co QList possibleImports = generatePossibleLibraryImports(filteredPossibleImportKeys); - possibleImports.append(generatePossibleFileImports(document()->path())); + possibleImports.append(generatePossibleFileImports(document()->path(), imports->all())); if (m_rewriterView->isAttached()) m_rewriterView->model()->setPossibleImports(possibleImports);