forked from qt-creator/qt-creator
QmlDesigner: Add tags for important imports
This makes the relevant imports a lot more discoverable. Change-Id: Ide0396cf844c071aaee050a8993eb06a9c544daf Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -29,32 +29,38 @@
|
|||||||
|
|
||||||
#include <theme.h>
|
#include <theme.h>
|
||||||
|
|
||||||
|
#include <itemlibrarymodel.h>
|
||||||
|
#include <itemlibraryimageprovider.h>
|
||||||
|
#include <itemlibraryinfo.h>
|
||||||
|
#include <metainfo.h>
|
||||||
|
#include <model.h>
|
||||||
|
#include <rewritingexception.h>
|
||||||
|
#include <qmldesignerplugin.h>
|
||||||
|
|
||||||
|
#include <utils/flowlayout.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/qtcassert.h>
|
|
||||||
#include <utils/stylehelper.h>
|
#include <utils/stylehelper.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
#include <coreplugin/coreconstants.h>
|
#include <coreplugin/coreconstants.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include "itemlibrarymodel.h"
|
|
||||||
#include "itemlibraryimageprovider.h"
|
|
||||||
#include <model.h>
|
|
||||||
#include <metainfo.h>
|
|
||||||
#include "rewritingexception.h"
|
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
#include <QDrag>
|
#include <QDrag>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QFileSystemModel>
|
#include <QFileSystemModel>
|
||||||
#include <QStackedWidget>
|
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QTabBar>
|
|
||||||
#include <QImageReader>
|
#include <QImageReader>
|
||||||
|
#include <QMenu>
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QWheelEvent>
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QShortcut>
|
#include <QShortcut>
|
||||||
|
#include <QStackedWidget>
|
||||||
|
#include <QTabBar>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QToolButton>
|
||||||
|
#include <QWheelEvent>
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
#include <QQuickItem>
|
#include <QQuickItem>
|
||||||
|
|
||||||
@@ -69,6 +75,7 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
|
|||||||
m_itemIconSize(24, 24),
|
m_itemIconSize(24, 24),
|
||||||
m_itemViewQuickWidget(new QQuickWidget),
|
m_itemViewQuickWidget(new QQuickWidget),
|
||||||
m_resourcesView(new ItemLibraryResourceView(this)),
|
m_resourcesView(new ItemLibraryResourceView(this)),
|
||||||
|
m_importTagsWidget(new QWidget(this)),
|
||||||
m_filterFlag(QtBasic)
|
m_filterFlag(QtBasic)
|
||||||
{
|
{
|
||||||
m_compressionTimer.setInterval(200);
|
m_compressionTimer.setInterval(200);
|
||||||
@@ -126,7 +133,6 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
|
|||||||
lineEditLayout->addItem(new QSpacerItem(5, 5, QSizePolicy::Fixed, QSizePolicy::Fixed), 1, 2);
|
lineEditLayout->addItem(new QSpacerItem(5, 5, QSizePolicy::Fixed, QSizePolicy::Fixed), 1, 2);
|
||||||
connect(m_filterLineEdit.data(), &Utils::FancyLineEdit::filterChanged, this, &ItemLibraryWidget::setSearchFilter);
|
connect(m_filterLineEdit.data(), &Utils::FancyLineEdit::filterChanged, this, &ItemLibraryWidget::setSearchFilter);
|
||||||
|
|
||||||
|
|
||||||
m_stackedWidget = new QStackedWidget(this);
|
m_stackedWidget = new QStackedWidget(this);
|
||||||
m_stackedWidget->addWidget(m_itemViewQuickWidget.data());
|
m_stackedWidget->addWidget(m_itemViewQuickWidget.data());
|
||||||
m_stackedWidget->addWidget(m_resourcesView.data());
|
m_stackedWidget->addWidget(m_resourcesView.data());
|
||||||
@@ -141,7 +147,8 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
|
|||||||
layout->addWidget(tabBar, 0, 0, 1, 1);
|
layout->addWidget(tabBar, 0, 0, 1, 1);
|
||||||
layout->addWidget(spacer, 1, 0);
|
layout->addWidget(spacer, 1, 0);
|
||||||
layout->addWidget(lineEditFrame, 2, 0, 1, 1);
|
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());
|
setSearchFilter(QString());
|
||||||
|
|
||||||
@@ -154,6 +161,9 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
|
|||||||
|
|
||||||
connect(&m_compressionTimer, &QTimer::timeout, this, &ItemLibraryWidget::updateModel);
|
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
|
// init the first load of the QML UI elements
|
||||||
reloadQmlSource();
|
reloadQmlSource();
|
||||||
}
|
}
|
||||||
@@ -175,12 +185,8 @@ void ItemLibraryWidget::setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo)
|
|||||||
|
|
||||||
void ItemLibraryWidget::updateImports()
|
void ItemLibraryWidget::updateImports()
|
||||||
{
|
{
|
||||||
if (m_model) {
|
if (m_model)
|
||||||
QStringList imports;
|
setupImportTagWidget();
|
||||||
foreach (const Import &import, m_model->imports())
|
|
||||||
if (import.isLibraryImport())
|
|
||||||
imports << import.url();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemLibraryWidget::setImportsWidget(QWidget *importsWidget)
|
void ItemLibraryWidget::setImportsWidget(QWidget *importsWidget)
|
||||||
@@ -223,10 +229,16 @@ void ItemLibraryWidget::setModel(Model *model)
|
|||||||
|
|
||||||
void ItemLibraryWidget::setCurrentIndexOfStackedWidget(int index)
|
void ItemLibraryWidget::setCurrentIndexOfStackedWidget(int index)
|
||||||
{
|
{
|
||||||
if (index == 2)
|
if (index == 2) {
|
||||||
m_filterLineEdit->setVisible(false);
|
m_filterLineEdit->setVisible(false);
|
||||||
else
|
m_importTagsWidget->setVisible(true);
|
||||||
|
} if (index == 1) {
|
||||||
m_filterLineEdit->setVisible(true);
|
m_filterLineEdit->setVisible(true);
|
||||||
|
m_importTagsWidget->setVisible(false);
|
||||||
|
} else {
|
||||||
|
m_filterLineEdit->setVisible(true);
|
||||||
|
m_importTagsWidget->setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
m_stackedWidget->setCurrentIndex(index);
|
m_stackedWidget->setCurrentIndex(index);
|
||||||
}
|
}
|
||||||
@@ -249,6 +261,38 @@ void ItemLibraryWidget::reloadQmlSource()
|
|||||||
m_itemViewQuickWidget->setSource(QUrl::fromLocalFile(itemLibraryQmlFilePath));
|
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<QWidget*>("", 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()
|
void ItemLibraryWidget::updateModel()
|
||||||
{
|
{
|
||||||
m_itemLibraryModel->update(m_itemLibraryInfo.data(), m_model.data());
|
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)
|
void ItemLibraryWidget::removeImport(const QString &name)
|
||||||
{
|
{
|
||||||
if (!m_model)
|
QTC_ASSERT(m_model, return);
|
||||||
return;
|
|
||||||
|
|
||||||
QList<Import> toBeRemovedImportList;
|
QList<Import> toBeRemovedImportList;
|
||||||
foreach (const Import &import, m_model->imports())
|
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)
|
void ItemLibraryWidget::addImport(const QString &name, const QString &version)
|
||||||
{
|
{
|
||||||
if (!m_model)
|
QTC_ASSERT(m_model, return);
|
||||||
return;
|
|
||||||
m_model->changeImports({Import::createLibraryImport(name, version)}, {});
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -86,18 +86,17 @@ public:
|
|||||||
|
|
||||||
Q_INVOKABLE void startDragAndDrop(QQuickItem *mouseArea, QVariant itemLibId);
|
Q_INVOKABLE void startDragAndDrop(QQuickItem *mouseArea, QVariant itemLibId);
|
||||||
|
|
||||||
protected:
|
|
||||||
void removeImport(const QString &name);
|
|
||||||
void addImport(const QString &name, const QString &version);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void itemActivated(const QString& itemName);
|
void itemActivated(const QString& itemName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setCurrentIndexOfStackedWidget(int index);
|
void setCurrentIndexOfStackedWidget(int index);
|
||||||
void reloadQmlSource();
|
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;
|
QTimer m_compressionTimer;
|
||||||
QSize m_itemIconSize;
|
QSize m_itemIconSize;
|
||||||
|
|
||||||
@@ -111,6 +110,8 @@ private:
|
|||||||
QPointer<Utils::FancyLineEdit> m_filterLineEdit;
|
QPointer<Utils::FancyLineEdit> m_filterLineEdit;
|
||||||
QScopedPointer<QQuickWidget> m_itemViewQuickWidget;
|
QScopedPointer<QQuickWidget> m_itemViewQuickWidget;
|
||||||
QScopedPointer<ItemLibraryResourceView> m_resourcesView;
|
QScopedPointer<ItemLibraryResourceView> m_resourcesView;
|
||||||
|
QScopedPointer<QWidget> m_importTagsWidget;
|
||||||
|
|
||||||
QShortcut *m_qmlSourceUpdateShortcut;
|
QShortcut *m_qmlSourceUpdateShortcut;
|
||||||
|
|
||||||
QPointer<Model> m_model;
|
QPointer<Model> m_model;
|
||||||
|
@@ -99,8 +99,10 @@ public:
|
|||||||
void setPossibleImports(const QList<Import> &possibleImports);
|
void setPossibleImports(const QList<Import> &possibleImports);
|
||||||
void setUsedImports(const QList<Import> &usedImports);
|
void setUsedImports(const QList<Import> &usedImports);
|
||||||
bool hasImport(const Import &import, bool ignoreAlias = true, bool allowHigherVersion = false);
|
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);
|
QString pathForImport(const Import &import);
|
||||||
QStringList importPaths() const;
|
QStringList importPaths() const;
|
||||||
|
Import highestPossibleImport(const QString &importPath);
|
||||||
|
|
||||||
RewriterView *rewriterView() const;
|
RewriterView *rewriterView() const;
|
||||||
void setRewriterView(RewriterView *rewriterView);
|
void setRewriterView(RewriterView *rewriterView);
|
||||||
|
@@ -1874,6 +1874,8 @@ void Model::setUsedImports(const QList<Import> &usedImports)
|
|||||||
|
|
||||||
static bool compareVersions(const QString &version1, const QString &version2, bool allowHigherVersion)
|
static bool compareVersions(const QString &version1, const QString &version2, bool allowHigherVersion)
|
||||||
{
|
{
|
||||||
|
if (version2.isEmpty())
|
||||||
|
return true;
|
||||||
if (version1 == version2)
|
if (version1 == version2)
|
||||||
return true;
|
return true;
|
||||||
if (!allowHigherVersion)
|
if (!allowHigherVersion)
|
||||||
@@ -1921,6 +1923,26 @@ bool Model::hasImport(const Import &import, bool ignoreAlias, bool allowHigherVe
|
|||||||
return false;
|
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)
|
QString Model::pathForImport(const Import &import)
|
||||||
{
|
{
|
||||||
if (!rewriterView())
|
if (!rewriterView())
|
||||||
@@ -1944,6 +1966,20 @@ QStringList Model::importPaths() const
|
|||||||
return importPathList;
|
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
|
RewriterView *Model::rewriterView() const
|
||||||
{
|
{
|
||||||
return d->rewriterView();
|
return d->rewriterView();
|
||||||
|
Reference in New Issue
Block a user