diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index 1bf7725b989..81313c43022 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -29,32 +29,38 @@ #include +#include +#include +#include +#include +#include +#include +#include + +#include #include -#include #include +#include +#include #include #include -#include "itemlibrarymodel.h" -#include "itemlibraryimageprovider.h" -#include -#include -#include "rewritingexception.h" +#include #include #include #include -#include #include -#include #include +#include #include #include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include #include #include @@ -69,6 +75,7 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) : m_itemIconSize(24, 24), m_itemViewQuickWidget(new QQuickWidget), m_resourcesView(new ItemLibraryResourceView(this)), + m_importTagsWidget(new QWidget(this)), m_filterFlag(QtBasic) { m_compressionTimer.setInterval(200); @@ -126,7 +133,6 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) : lineEditLayout->addItem(new QSpacerItem(5, 5, QSizePolicy::Fixed, QSizePolicy::Fixed), 1, 2); connect(m_filterLineEdit.data(), &Utils::FancyLineEdit::filterChanged, this, &ItemLibraryWidget::setSearchFilter); - m_stackedWidget = new QStackedWidget(this); m_stackedWidget->addWidget(m_itemViewQuickWidget.data()); m_stackedWidget->addWidget(m_resourcesView.data()); @@ -141,7 +147,8 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) : layout->addWidget(tabBar, 0, 0, 1, 1); layout->addWidget(spacer, 1, 0); layout->addWidget(lineEditFrame, 2, 0, 1, 1); - layout->addWidget(m_stackedWidget.data(), 3, 0, 1, 1); + layout->addWidget(m_importTagsWidget.data(), 3, 0, 1, 1); + layout->addWidget(m_stackedWidget.data(), 4, 0, 1, 1); setSearchFilter(QString()); @@ -154,6 +161,9 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) : connect(&m_compressionTimer, &QTimer::timeout, this, &ItemLibraryWidget::updateModel); + auto *flowLayout = new Utils::FlowLayout(m_importTagsWidget.data()); + flowLayout->setMargin(4); + // init the first load of the QML UI elements reloadQmlSource(); } @@ -175,12 +185,8 @@ void ItemLibraryWidget::setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo) void ItemLibraryWidget::updateImports() { - if (m_model) { - QStringList imports; - foreach (const Import &import, m_model->imports()) - if (import.isLibraryImport()) - imports << import.url(); - } + if (m_model) + setupImportTagWidget(); } void ItemLibraryWidget::setImportsWidget(QWidget *importsWidget) @@ -223,10 +229,16 @@ void ItemLibraryWidget::setModel(Model *model) void ItemLibraryWidget::setCurrentIndexOfStackedWidget(int index) { - if (index == 2) + if (index == 2) { m_filterLineEdit->setVisible(false); - else + m_importTagsWidget->setVisible(true); + } if (index == 1) { m_filterLineEdit->setVisible(true); + m_importTagsWidget->setVisible(false); + } else { + m_filterLineEdit->setVisible(true); + m_importTagsWidget->setVisible(true); + } m_stackedWidget->setCurrentIndex(index); } @@ -249,6 +261,38 @@ void ItemLibraryWidget::reloadQmlSource() m_itemViewQuickWidget->setSource(QUrl::fromLocalFile(itemLibraryQmlFilePath)); } +void ItemLibraryWidget::setupImportTagWidget() +{ + QTC_ASSERT(m_model, return); + + const QStringList imports = m_model->metaInfo().itemLibraryInfo()->showTagsForImports(); + + qDeleteAll(m_importTagsWidget->findChildren("", Qt::FindDirectChildrenOnly)); + + auto *flowLayout = m_importTagsWidget->layout(); + + auto createButton = [this](const QString &import) { + auto button = new QToolButton(m_importTagsWidget.data()); + auto font = button->font(); + font.setPixelSize(9); + button->setFont(font); + button->setIcon(Utils::Icons::PLUS.icon()); + button->setText(import); + button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + connect(button, &QToolButton::clicked, this, [this, import]() { + addPossibleImport(import); + }); + return button; + }; + + for (const QString &importPath : imports) { + const Import import = Import::createLibraryImport(importPath); + if (!m_model->hasImport(import, true, true) + && m_model->isImportPossible(import, true, true)) + flowLayout->addWidget(createButton(importPath)); + } +} + void ItemLibraryWidget::updateModel() { m_itemLibraryModel->update(m_itemLibraryInfo.data(), m_model.data()); @@ -293,8 +337,7 @@ void ItemLibraryWidget::startDragAndDrop(QQuickItem *mouseArea, QVariant itemLib void ItemLibraryWidget::removeImport(const QString &name) { - if (!m_model) - return; + QTC_ASSERT(m_model, return); QList toBeRemovedImportList; foreach (const Import &import, m_model->imports()) @@ -306,9 +349,21 @@ void ItemLibraryWidget::removeImport(const QString &name) void ItemLibraryWidget::addImport(const QString &name, const QString &version) { - if (!m_model) - return; + QTC_ASSERT(m_model, return); m_model->changeImports({Import::createLibraryImport(name, version)}, {}); } +void ItemLibraryWidget::addPossibleImport(const QString &name) +{ + QTC_ASSERT(m_model, return); + const Import import = m_model->highestPossibleImport(name); + try { + m_model->changeImports({Import::createLibraryImport(name, import.version())}, {}); + } + catch (const RewritingException &e) { + e.showException(); + } + QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager(); +} + } diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h index a831b4c5fd1..8ca7467bfee 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h @@ -86,18 +86,17 @@ public: Q_INVOKABLE void startDragAndDrop(QQuickItem *mouseArea, QVariant itemLibId); -protected: - void removeImport(const QString &name); - void addImport(const QString &name, const QString &version); - signals: void itemActivated(const QString& itemName); private: void setCurrentIndexOfStackedWidget(int index); void reloadQmlSource(); + void setupImportTagWidget(); + void removeImport(const QString &name); + void addImport(const QString &name, const QString &version); + void addPossibleImport(const QString &name); -private: QTimer m_compressionTimer; QSize m_itemIconSize; @@ -111,6 +110,8 @@ private: QPointer m_filterLineEdit; QScopedPointer m_itemViewQuickWidget; QScopedPointer m_resourcesView; + QScopedPointer m_importTagsWidget; + QShortcut *m_qmlSourceUpdateShortcut; QPointer m_model; diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h index d5f16be0ed4..d959f4eb0fc 100644 --- a/src/plugins/qmldesigner/designercore/include/model.h +++ b/src/plugins/qmldesigner/designercore/include/model.h @@ -99,8 +99,10 @@ public: void setPossibleImports(const QList &possibleImports); void setUsedImports(const QList &usedImports); bool hasImport(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false); + bool isImportPossible(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false); QString pathForImport(const Import &import); QStringList importPaths() const; + Import highestPossibleImport(const QString &importPath); RewriterView *rewriterView() const; void setRewriterView(RewriterView *rewriterView); diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index 70dd0f4fd43..8c79fee4c71 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -1874,6 +1874,8 @@ void Model::setUsedImports(const QList &usedImports) static bool compareVersions(const QString &version1, const QString &version2, bool allowHigherVersion) { + if (version2.isEmpty()) + return true; if (version1 == version2) return true; if (!allowHigherVersion) @@ -1921,6 +1923,26 @@ bool Model::hasImport(const Import &import, bool ignoreAlias, bool allowHigherVe return false; } +bool Model::isImportPossible(const Import &import, bool ignoreAlias, bool allowHigherVersion) +{ + if (imports().contains(import)) + return true; + if (!ignoreAlias) + return false; + + const auto importList = possibleImports(); + + for (const Import &possibleImport : importList) { + if (possibleImport.isFileImport() && import.isFileImport()) + if (possibleImport.file() == import.file()) + return true; + if (possibleImport.isLibraryImport() && import.isLibraryImport()) + if (possibleImport.url() == import.url() && compareVersions(possibleImport.version(), import.version(), allowHigherVersion)) + return true; + } + return false; +} + QString Model::pathForImport(const Import &import) { if (!rewriterView()) @@ -1944,6 +1966,20 @@ QStringList Model::importPaths() const return importPathList; } +Import Model::highestPossibleImport(const QString &importPath) +{ + Import candidate; + + for (const Import &import : possibleImports()) { + if (import.url() == importPath) { + if (candidate.isEmpty() || compareVersions(import.version(), candidate.version(), true)) + candidate = import; + } + } + + return candidate; +} + RewriterView *Model::rewriterView() const { return d->rewriterView();