forked from qt-creator/qt-creator
QmlDesigner: Search also possible imports in item library
Possible imports are now also parsed for items in item library. They are only shown in case the search string is not empty. Starting a drag of unimported item will automatically add the import. Added a small manhattanlength check to the start of the drag to avoid unwanted import additions on clicks. Also fixed the item sorting to alphabetical order within categories. Task-number: QDS-3825 Change-Id: I93366182af3fd7eda38bf94d53807393ecf92a08 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
@@ -29,6 +29,9 @@ import QtQuickDesignerTheme 1.0
|
|||||||
import HelperWidgets 2.0
|
import HelperWidgets 2.0
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
id: delegateRoot
|
||||||
|
signal showContextMenu()
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.rightMargin: 1
|
anchors.rightMargin: 1
|
||||||
anchors.topMargin: 1
|
anchors.topMargin: 1
|
||||||
@@ -71,11 +74,12 @@ Item {
|
|||||||
|
|
||||||
ImagePreviewTooltipArea {
|
ImagePreviewTooltipArea {
|
||||||
id: mouseRegion
|
id: mouseRegion
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
|
onShowContextMenu: delegateRoot.showContextMenu()
|
||||||
onPressed: {
|
onPressed: {
|
||||||
rootView.startDragAndDrop(itemLibraryEntry)
|
if (mouse.button === Qt.LeftButton)
|
||||||
|
rootView.startDragAndDrop(itemLibraryEntry, mapToGlobal(mouse.x, mouse.y))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,11 +77,14 @@ ScrollView {
|
|||||||
id: itemsView
|
id: itemsView
|
||||||
|
|
||||||
property string importToRemove: ""
|
property string importToRemove: ""
|
||||||
|
property string importToAdd: ""
|
||||||
|
property var currentItem: null
|
||||||
|
|
||||||
// called from C++ to close context menu on focus out
|
// called from C++ to close context menu on focus out
|
||||||
function closeContextMenu()
|
function closeContextMenu()
|
||||||
{
|
{
|
||||||
contextMenu.close()
|
importContextMenu.close()
|
||||||
|
itemContextMenu.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
@@ -99,11 +102,11 @@ ScrollView {
|
|||||||
2 * cellVerticalMargin + cellVerticalSpacing
|
2 * cellVerticalMargin + cellVerticalSpacing
|
||||||
|
|
||||||
StudioControls.Menu {
|
StudioControls.Menu {
|
||||||
id: contextMenu
|
id: importContextMenu
|
||||||
|
|
||||||
StudioControls.MenuItem {
|
StudioControls.MenuItem {
|
||||||
text: qsTr("Remove Module")
|
text: qsTr("Remove Module")
|
||||||
enabled: importToRemove !== "" && importToRemove !== "QtQuick"
|
enabled: importToRemove !== ""
|
||||||
onTriggered: rootView.removeImport(importToRemove)
|
onTriggered: rootView.removeImport(importToRemove)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,6 +122,19 @@ ScrollView {
|
|||||||
onTriggered: itemLibraryModel.collapseAll()
|
onTriggered: itemLibraryModel.collapseAll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StudioControls.Menu {
|
||||||
|
id: itemContextMenu
|
||||||
|
// Workaround for menu item implicit width not properly propagating to menu
|
||||||
|
width: importMenuItem.implicitWidth
|
||||||
|
|
||||||
|
StudioControls.MenuItem {
|
||||||
|
id: importMenuItem
|
||||||
|
text: qsTr("Import Module: ") + importToAdd
|
||||||
|
enabled: currentItem
|
||||||
|
onTriggered: rootView.addImportForItem(currentItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
@@ -144,8 +160,8 @@ ScrollView {
|
|||||||
importExpanded = !importExpanded
|
importExpanded = !importExpanded
|
||||||
}
|
}
|
||||||
onShowContextMenu: {
|
onShowContextMenu: {
|
||||||
importToRemove = importUsed ? "" : importUrl
|
importToRemove = importRemovable ? importUrl : ""
|
||||||
contextMenu.popup()
|
importContextMenu.popup()
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
@@ -180,6 +196,15 @@ ScrollView {
|
|||||||
visible: itemVisible
|
visible: itemVisible
|
||||||
width: styleConstants.cellWidth + itemGrid.flexibleWidth
|
width: styleConstants.cellWidth + itemGrid.flexibleWidth
|
||||||
height: styleConstants.cellHeight
|
height: styleConstants.cellHeight
|
||||||
|
onShowContextMenu: {
|
||||||
|
if (!itemUsable) {
|
||||||
|
importToAdd = itemRequiredImport
|
||||||
|
if (importToAdd !== "") {
|
||||||
|
currentItem = itemLibraryEntry
|
||||||
|
itemContextMenu.popup()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,12 +30,19 @@ import QtQuick.Layouts 1.0
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
id: mouseArea
|
id: mouseArea
|
||||||
|
|
||||||
|
signal showContextMenu()
|
||||||
|
|
||||||
onExited: tooltipBackend.hideTooltip()
|
onExited: tooltipBackend.hideTooltip()
|
||||||
onCanceled: tooltipBackend.hideTooltip()
|
onCanceled: tooltipBackend.hideTooltip()
|
||||||
onClicked: forceActiveFocus()
|
|
||||||
onPositionChanged: tooltipBackend.reposition()
|
onPositionChanged: tooltipBackend.reposition()
|
||||||
|
onClicked: {
|
||||||
|
forceActiveFocus()
|
||||||
|
if (mouse.button === Qt.RightButton)
|
||||||
|
showContextMenu()
|
||||||
|
}
|
||||||
|
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
interval: 1000
|
interval: 1000
|
||||||
|
|||||||
@@ -370,7 +370,8 @@ void DesignDocument::close()
|
|||||||
void DesignDocument::updateSubcomponentManager()
|
void DesignDocument::updateSubcomponentManager()
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_subComponentManager);
|
Q_ASSERT(m_subComponentManager);
|
||||||
m_subComponentManager->update(QUrl::fromLocalFile(fileName().toString()), currentModel()->imports());
|
m_subComponentManager->update(QUrl::fromLocalFile(fileName().toString()),
|
||||||
|
currentModel()->imports() + currentModel()->possibleImports());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DesignDocument::deleteSelected()
|
void DesignDocument::deleteSelected()
|
||||||
|
|||||||
@@ -127,6 +127,9 @@ void ItemLibraryCategoriesModel::sortCategorySections()
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::sort(m_categoryList.begin(), m_categoryList.end(), categorySort);
|
std::sort(m_categoryList.begin(), m_categoryList.end(), categorySort);
|
||||||
|
|
||||||
|
for (const auto &category : qAsConst(m_categoryList))
|
||||||
|
category->sortItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemLibraryCategoriesModel::resetModel()
|
void ItemLibraryCategoriesModel::resetModel()
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ bool ItemLibraryCategory::updateItemVisibility(const QString &searchText, bool *
|
|||||||
bool itemVisible = item->itemName().toLower().contains(searchText)
|
bool itemVisible = item->itemName().toLower().contains(searchText)
|
||||||
|| item->typeName().toLower().contains(searchText);
|
|| item->typeName().toLower().contains(searchText);
|
||||||
|
|
||||||
|
if (searchText.isEmpty() && !item->isUsable())
|
||||||
|
itemVisible = false;
|
||||||
bool itemChanged = item->setVisible(itemVisible);
|
bool itemChanged = item->setVisible(itemVisible);
|
||||||
|
|
||||||
*changed |= itemChanged;
|
*changed |= itemChanged;
|
||||||
|
|||||||
@@ -28,18 +28,22 @@
|
|||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
ItemLibraryImport::ItemLibraryImport(const Import &import, QObject *parent, bool isUserSection)
|
ItemLibraryImport::ItemLibraryImport(const Import &import, QObject *parent, SectionType sectionType)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
m_import(import),
|
m_import(import),
|
||||||
m_isUserSection(isUserSection)
|
m_sectionType(sectionType)
|
||||||
{
|
{
|
||||||
|
updateRemovable();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ItemLibraryImport::importName() const
|
QString ItemLibraryImport::importName() const
|
||||||
{
|
{
|
||||||
if (m_isUserSection)
|
if (m_sectionType == SectionType::User)
|
||||||
return userComponentsTitle();
|
return userComponentsTitle();
|
||||||
|
|
||||||
|
if (m_sectionType == SectionType::Unimported)
|
||||||
|
return unimportedComponentsTitle();
|
||||||
|
|
||||||
if (importUrl() == "QtQuick")
|
if (importUrl() == "QtQuick")
|
||||||
return tr("Default Components");
|
return tr("Default Components");
|
||||||
|
|
||||||
@@ -48,9 +52,12 @@ QString ItemLibraryImport::importName() const
|
|||||||
|
|
||||||
QString ItemLibraryImport::importUrl() const
|
QString ItemLibraryImport::importUrl() const
|
||||||
{
|
{
|
||||||
if (m_isUserSection)
|
if (m_sectionType == SectionType::User)
|
||||||
return userComponentsTitle();
|
return userComponentsTitle();
|
||||||
|
|
||||||
|
if (m_sectionType == SectionType::Unimported)
|
||||||
|
return unimportedComponentsTitle();
|
||||||
|
|
||||||
return m_import.url();
|
return m_import.url();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,11 +68,14 @@ bool ItemLibraryImport::importExpanded() const
|
|||||||
|
|
||||||
QString ItemLibraryImport::sortingName() const
|
QString ItemLibraryImport::sortingName() const
|
||||||
{
|
{
|
||||||
if (m_isUserSection) // user components always come first
|
if (m_sectionType == SectionType::User)
|
||||||
return "_";
|
return "_"; // user components always come first
|
||||||
|
|
||||||
|
if (m_sectionType == SectionType::Unimported)
|
||||||
|
return "zzzzzz"; // Unimported components always come last
|
||||||
|
|
||||||
if (!hasCategories()) // imports with no categories are at the bottom of the list
|
if (!hasCategories()) // imports with no categories are at the bottom of the list
|
||||||
return "zzzzz" + importName();
|
return "zzzzz_" + importName();
|
||||||
|
|
||||||
return importName();
|
return importName();
|
||||||
}
|
}
|
||||||
@@ -113,6 +123,7 @@ bool ItemLibraryImport::setVisible(bool isVisible)
|
|||||||
{
|
{
|
||||||
if (isVisible != m_isVisible) {
|
if (isVisible != m_isVisible) {
|
||||||
m_isVisible = isVisible;
|
m_isVisible = isVisible;
|
||||||
|
emit importVisibleChanged();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +137,11 @@ bool ItemLibraryImport::importVisible() const
|
|||||||
|
|
||||||
void ItemLibraryImport::setImportUsed(bool importUsed)
|
void ItemLibraryImport::setImportUsed(bool importUsed)
|
||||||
{
|
{
|
||||||
m_importUsed = importUsed;
|
if (importUsed != m_importUsed) {
|
||||||
|
m_importUsed = importUsed;
|
||||||
|
updateRemovable();
|
||||||
|
emit importUsedChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ItemLibraryImport::importUsed() const
|
bool ItemLibraryImport::importUsed() const
|
||||||
@@ -134,6 +149,11 @@ bool ItemLibraryImport::importUsed() const
|
|||||||
return m_importUsed;
|
return m_importUsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ItemLibraryImport::importRemovable() const
|
||||||
|
{
|
||||||
|
return m_importRemovable;
|
||||||
|
}
|
||||||
|
|
||||||
bool ItemLibraryImport::hasCategories() const
|
bool ItemLibraryImport::hasCategories() const
|
||||||
{
|
{
|
||||||
return m_categoryModel.rowCount() > 0;
|
return m_categoryModel.rowCount() > 0;
|
||||||
@@ -146,7 +166,10 @@ void ItemLibraryImport::sortCategorySections()
|
|||||||
|
|
||||||
void ItemLibraryImport::setImportExpanded(bool expanded)
|
void ItemLibraryImport::setImportExpanded(bool expanded)
|
||||||
{
|
{
|
||||||
m_importExpanded = expanded;
|
if (expanded != m_importExpanded) {
|
||||||
|
m_importExpanded = expanded;
|
||||||
|
emit importExpandChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemLibraryCategory *ItemLibraryImport::getCategorySection(const QString &categoryName) const
|
ItemLibraryCategory *ItemLibraryImport::getCategorySection(const QString &categoryName) const
|
||||||
@@ -159,15 +182,30 @@ ItemLibraryCategory *ItemLibraryImport::getCategorySection(const QString &catego
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ItemLibraryImport::isUserSection() const
|
|
||||||
{
|
|
||||||
return m_isUserSection;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
QString ItemLibraryImport::userComponentsTitle()
|
QString ItemLibraryImport::userComponentsTitle()
|
||||||
{
|
{
|
||||||
return tr("My Components");
|
return tr("My Components");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ItemLibraryImport::unimportedComponentsTitle()
|
||||||
|
{
|
||||||
|
return tr("All Other Components");
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemLibraryImport::SectionType ItemLibraryImport::sectionType() const
|
||||||
|
{
|
||||||
|
return m_sectionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryImport::updateRemovable()
|
||||||
|
{
|
||||||
|
bool importRemovable = !m_importUsed && m_sectionType == SectionType::Default
|
||||||
|
&& m_import.url() != "QtQuick";
|
||||||
|
if (importRemovable != m_importRemovable) {
|
||||||
|
m_importRemovable = importRemovable;
|
||||||
|
emit importRemovableChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
|||||||
@@ -41,10 +41,18 @@ class ItemLibraryImport : public QObject
|
|||||||
Q_PROPERTY(bool importVisible READ importVisible NOTIFY importVisibleChanged FINAL)
|
Q_PROPERTY(bool importVisible READ importVisible NOTIFY importVisibleChanged FINAL)
|
||||||
Q_PROPERTY(bool importUsed READ importUsed NOTIFY importUsedChanged FINAL)
|
Q_PROPERTY(bool importUsed READ importUsed NOTIFY importUsedChanged FINAL)
|
||||||
Q_PROPERTY(bool importExpanded READ importExpanded WRITE setImportExpanded NOTIFY importExpandChanged FINAL)
|
Q_PROPERTY(bool importExpanded READ importExpanded WRITE setImportExpanded NOTIFY importExpandChanged FINAL)
|
||||||
|
Q_PROPERTY(bool importRemovable READ importRemovable NOTIFY importRemovableChanged FINAL)
|
||||||
Q_PROPERTY(QObject *categoryModel READ categoryModel NOTIFY categoryModelChanged FINAL)
|
Q_PROPERTY(QObject *categoryModel READ categoryModel NOTIFY categoryModelChanged FINAL)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ItemLibraryImport(const Import &import, QObject *parent = nullptr, bool isUserSection = false);
|
enum class SectionType {
|
||||||
|
Default,
|
||||||
|
User,
|
||||||
|
Unimported
|
||||||
|
};
|
||||||
|
|
||||||
|
ItemLibraryImport(const Import &import, QObject *parent = nullptr,
|
||||||
|
SectionType sectionType = SectionType::Default);
|
||||||
|
|
||||||
QString importName() const;
|
QString importName() const;
|
||||||
QString importUrl() const;
|
QString importUrl() const;
|
||||||
@@ -53,6 +61,7 @@ public:
|
|||||||
Import importEntry() const;
|
Import importEntry() const;
|
||||||
bool importVisible() const;
|
bool importVisible() const;
|
||||||
bool importUsed() const;
|
bool importUsed() const;
|
||||||
|
bool importRemovable() const;
|
||||||
bool hasCategories() const;
|
bool hasCategories() const;
|
||||||
ItemLibraryCategory *getCategorySection(const QString &categoryName) const;
|
ItemLibraryCategory *getCategorySection(const QString &categoryName) const;
|
||||||
|
|
||||||
@@ -66,21 +75,26 @@ public:
|
|||||||
void expandCategories(bool expand = true);
|
void expandCategories(bool expand = true);
|
||||||
|
|
||||||
static QString userComponentsTitle();
|
static QString userComponentsTitle();
|
||||||
|
static QString unimportedComponentsTitle();
|
||||||
|
|
||||||
bool isUserSection() const;
|
SectionType sectionType() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void categoryModelChanged();
|
void categoryModelChanged();
|
||||||
void importVisibleChanged();
|
void importVisibleChanged();
|
||||||
void importUsedChanged();
|
void importUsedChanged();
|
||||||
void importExpandChanged();
|
void importExpandChanged();
|
||||||
|
void importRemovableChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void updateRemovable();
|
||||||
|
|
||||||
Import m_import;
|
Import m_import;
|
||||||
bool m_importExpanded = true;
|
bool m_importExpanded = true;
|
||||||
bool m_isVisible = true;
|
bool m_isVisible = true;
|
||||||
bool m_importUsed = false;
|
bool m_importUsed = false;
|
||||||
bool m_isUserSection = false; // user components import section
|
bool m_importRemovable = false;
|
||||||
|
SectionType m_sectionType = SectionType::Default;
|
||||||
ItemLibraryCategoriesModel m_categoryModel;
|
ItemLibraryCategoriesModel m_categoryModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -27,9 +27,10 @@
|
|||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
ItemLibraryItem::ItemLibraryItem(const ItemLibraryEntry &itemLibraryEntry, QObject *parent)
|
ItemLibraryItem::ItemLibraryItem(const ItemLibraryEntry &itemLibraryEntry, bool isUsable, QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent)
|
||||||
m_itemLibraryEntry(itemLibraryEntry)
|
, m_itemLibraryEntry(itemLibraryEntry)
|
||||||
|
, m_isUsable(isUsable)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,6 +62,11 @@ QString ItemLibraryItem::componentPath() const
|
|||||||
return m_itemLibraryEntry.customComponentSource();
|
return m_itemLibraryEntry.customComponentSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ItemLibraryItem::requiredImport() const
|
||||||
|
{
|
||||||
|
return m_itemLibraryEntry.requiredImport();
|
||||||
|
}
|
||||||
|
|
||||||
bool ItemLibraryItem::setVisible(bool isVisible)
|
bool ItemLibraryItem::setVisible(bool isVisible)
|
||||||
{
|
{
|
||||||
if (isVisible != m_isVisible) {
|
if (isVisible != m_isVisible) {
|
||||||
@@ -77,6 +83,11 @@ bool ItemLibraryItem::isVisible() const
|
|||||||
return m_isVisible;
|
return m_isVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ItemLibraryItem::isUsable() const
|
||||||
|
{
|
||||||
|
return m_isUsable;
|
||||||
|
}
|
||||||
|
|
||||||
QVariant ItemLibraryItem::itemLibraryEntry() const
|
QVariant ItemLibraryItem::itemLibraryEntry() const
|
||||||
{
|
{
|
||||||
return QVariant::fromValue(m_itemLibraryEntry);
|
return QVariant::fromValue(m_itemLibraryEntry);
|
||||||
|
|||||||
@@ -43,18 +43,22 @@ class ItemLibraryItem: public QObject
|
|||||||
Q_PROPERTY(QString itemLibraryIconPath READ itemLibraryIconPath FINAL)
|
Q_PROPERTY(QString itemLibraryIconPath READ itemLibraryIconPath FINAL)
|
||||||
Q_PROPERTY(bool itemVisible READ isVisible NOTIFY visibilityChanged FINAL)
|
Q_PROPERTY(bool itemVisible READ isVisible NOTIFY visibilityChanged FINAL)
|
||||||
Q_PROPERTY(QString componentPath READ componentPath FINAL)
|
Q_PROPERTY(QString componentPath READ componentPath FINAL)
|
||||||
|
Q_PROPERTY(bool itemUsable READ isUsable FINAL)
|
||||||
|
Q_PROPERTY(QString itemRequiredImport READ requiredImport FINAL)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ItemLibraryItem(const ItemLibraryEntry &itemLibraryEntry, QObject *parent);
|
ItemLibraryItem(const ItemLibraryEntry &itemLibraryEntry, bool isImported, QObject *parent);
|
||||||
~ItemLibraryItem() override;
|
~ItemLibraryItem() override;
|
||||||
|
|
||||||
QString itemName() const;
|
QString itemName() const;
|
||||||
QString typeName() const;
|
QString typeName() const;
|
||||||
QString itemLibraryIconPath() const;
|
QString itemLibraryIconPath() const;
|
||||||
QString componentPath() const;
|
QString componentPath() const;
|
||||||
|
QString requiredImport() const;
|
||||||
|
|
||||||
bool setVisible(bool isVisible);
|
bool setVisible(bool isVisible);
|
||||||
bool isVisible() const;
|
bool isVisible() const;
|
||||||
|
bool isUsable() const;
|
||||||
|
|
||||||
QVariant itemLibraryEntry() const;
|
QVariant itemLibraryEntry() const;
|
||||||
|
|
||||||
@@ -64,6 +68,7 @@ signals:
|
|||||||
private:
|
private:
|
||||||
ItemLibraryEntry m_itemLibraryEntry;
|
ItemLibraryEntry m_itemLibraryEntry;
|
||||||
bool m_isVisible = true;
|
bool m_isVisible = true;
|
||||||
|
bool m_isUsable = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ void ItemLibraryItemsModel::addItem(ItemLibraryItem *element)
|
|||||||
{
|
{
|
||||||
m_itemList.append(element);
|
m_itemList.append(element);
|
||||||
|
|
||||||
element->setVisible(true);
|
element->setVisible(element->isUsable());
|
||||||
}
|
}
|
||||||
|
|
||||||
const QList<QPointer<ItemLibraryItem>> &ItemLibraryItemsModel::items() const
|
const QList<QPointer<ItemLibraryItem>> &ItemLibraryItemsModel::items() const
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ void ItemLibraryModel::setSearchText(const QString &searchText)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Import entryToImport(const ItemLibraryEntry &entry)
|
Import ItemLibraryModel::entryToImport(const ItemLibraryEntry &entry)
|
||||||
{
|
{
|
||||||
if (entry.majorVersion() == -1 && entry.minorVersion() == -1)
|
if (entry.majorVersion() == -1 && entry.minorVersion() == -1)
|
||||||
return Import::createFileImport(entry.requiredImport());
|
return Import::createFileImport(entry.requiredImport());
|
||||||
@@ -204,46 +204,61 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
|
|||||||
|
|
||||||
bool valid = metaInfo.isValid() && metaInfo.majorVersion() == entry.majorVersion();
|
bool valid = metaInfo.isValid() && metaInfo.majorVersion() == entry.majorVersion();
|
||||||
bool isItem = valid && metaInfo.isSubclassOf("QtQuick.Item");
|
bool isItem = valid && metaInfo.isSubclassOf("QtQuick.Item");
|
||||||
bool forceVisiblity = valid && NodeHints::fromItemLibraryEntry(entry).visibleInLibrary();
|
bool forceVisibility = valid && NodeHints::fromItemLibraryEntry(entry).visibleInLibrary();
|
||||||
|
|
||||||
if (m_flowMode && metaInfo.isValid()) {
|
if (m_flowMode && metaInfo.isValid()) {
|
||||||
isItem = metaInfo.isSubclassOf("FlowView.FlowItem")
|
isItem = metaInfo.isSubclassOf("FlowView.FlowItem")
|
||||||
|| metaInfo.isSubclassOf("FlowView.FlowWildcard")
|
|| metaInfo.isSubclassOf("FlowView.FlowWildcard")
|
||||||
|| metaInfo.isSubclassOf("FlowView.FlowDecision");
|
|| metaInfo.isSubclassOf("FlowView.FlowDecision");
|
||||||
forceVisiblity = isItem;
|
forceVisibility = isItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool blocked = false;
|
||||||
const DesignerMcuManager &mcuManager = DesignerMcuManager::instance();
|
const DesignerMcuManager &mcuManager = DesignerMcuManager::instance();
|
||||||
if (mcuManager.isMCUProject()) {
|
if (mcuManager.isMCUProject()) {
|
||||||
const QSet<QString> blockTypes = mcuManager.bannedItems();
|
const QSet<QString> blockTypes = mcuManager.bannedItems();
|
||||||
|
|
||||||
if (blockTypes.contains(QString::fromUtf8(entry.typeName())))
|
if (blockTypes.contains(QString::fromUtf8(entry.typeName())))
|
||||||
valid = false;
|
blocked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid && (isItem || forceVisiblity) // We can change if the navigator does support pure QObjects
|
Import import = entryToImport(entry);
|
||||||
&& (entry.requiredImport().isEmpty()
|
bool hasImport = model->hasImport(import, true, true);
|
||||||
|| model->hasImport(entryToImport(entry), true, true))) {
|
bool isImportPossible = false;
|
||||||
|
if (!hasImport)
|
||||||
|
isImportPossible = model->isImportPossible(import, true, true);
|
||||||
|
bool isUsable = (valid && (isItem || forceVisibility))
|
||||||
|
&& (entry.requiredImport().isEmpty() || hasImport);
|
||||||
|
if (!blocked && (isUsable || isImportPossible)) {
|
||||||
ItemLibraryImport *importSection = nullptr;
|
ItemLibraryImport *importSection = nullptr;
|
||||||
|
|
||||||
QString catName = entry.category();
|
QString catName = entry.category();
|
||||||
if (catName == ItemLibraryImport::userComponentsTitle()) {
|
if (isUsable) {
|
||||||
// create an import section for user components
|
if (catName == ItemLibraryImport::userComponentsTitle()) {
|
||||||
importSection = importByUrl(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));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (catName.startsWith("Qt Quick - "))
|
||||||
|
catName = catName.mid(11); // remove "Qt Quick - "
|
||||||
|
importSection = importByUrl(entry.requiredImport());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
catName = ItemLibraryImport::unimportedComponentsTitle();
|
||||||
|
importSection = importByUrl(catName);
|
||||||
if (!importSection) {
|
if (!importSection) {
|
||||||
importSection = new ItemLibraryImport({}, this, true);
|
importSection = new ItemLibraryImport(
|
||||||
|
{}, this, ItemLibraryImport::SectionType::Unimported);
|
||||||
m_importList.append(importSection);
|
m_importList.append(importSection);
|
||||||
importSection->setImportExpanded(loadExpandedState(catName));
|
importSection->setImportExpanded(loadExpandedState(catName));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (catName.startsWith("Qt Quick - "))
|
|
||||||
catName = catName.mid(11); // remove "Qt Quick - "
|
|
||||||
|
|
||||||
importSection = importByUrl(entry.requiredImport());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!importSection) { // should not happen, but just in case
|
if (!importSection) {
|
||||||
qWarning() << __FUNCTION__ << "No import section found! skipping entry: " << entry.name();
|
qWarning() << __FUNCTION__ << "No import section found! skipping entry: " << entry.name();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -253,12 +268,12 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
|
|||||||
if (!categorySection) {
|
if (!categorySection) {
|
||||||
categorySection = new ItemLibraryCategory(catName, importSection);
|
categorySection = new ItemLibraryCategory(catName, importSection);
|
||||||
importSection->addCategory(categorySection);
|
importSection->addCategory(categorySection);
|
||||||
if (!importSection->isUserSection())
|
if (importSection->sectionType() == ItemLibraryImport::SectionType::Default)
|
||||||
categorySection->setExpanded(loadExpandedState(categorySection->categoryName()));
|
categorySection->setExpanded(loadExpandedState(categorySection->categoryName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// create item
|
// create item
|
||||||
auto item = new ItemLibraryItem(entry, categorySection);
|
auto item = new ItemLibraryItem(entry, isUsable, categorySection);
|
||||||
categorySection->addItem(item);
|
categorySection->addItem(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -300,7 +315,9 @@ ItemLibraryImport *ItemLibraryModel::importByUrl(const QString &importUrl) const
|
|||||||
if (itemLibraryImport->importUrl() == importUrl
|
if (itemLibraryImport->importUrl() == importUrl
|
||||||
|| (importUrl.isEmpty() && itemLibraryImport->importUrl() == "QtQuick")
|
|| (importUrl.isEmpty() && itemLibraryImport->importUrl() == "QtQuick")
|
||||||
|| (importUrl == ItemLibraryImport::userComponentsTitle()
|
|| (importUrl == ItemLibraryImport::userComponentsTitle()
|
||||||
&& itemLibraryImport->isUserSection())) {
|
&& itemLibraryImport->sectionType() == ItemLibraryImport::SectionType::User)
|
||||||
|
|| (importUrl == ItemLibraryImport::unimportedComponentsTitle()
|
||||||
|
&& itemLibraryImport->sectionType() == ItemLibraryImport::SectionType::Unimported)) {
|
||||||
return itemLibraryImport;
|
return itemLibraryImport;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -324,9 +341,11 @@ void ItemLibraryModel::updateVisibility(bool *changed)
|
|||||||
for (ItemLibraryImport *import : std::as_const(m_importList)) {
|
for (ItemLibraryImport *import : std::as_const(m_importList)) {
|
||||||
bool categoryChanged = false;
|
bool categoryChanged = false;
|
||||||
bool hasVisibleItems = import->updateCategoryVisibility(m_searchText, &categoryChanged);
|
bool hasVisibleItems = import->updateCategoryVisibility(m_searchText, &categoryChanged);
|
||||||
|
|
||||||
*changed |= categoryChanged;
|
*changed |= categoryChanged;
|
||||||
|
|
||||||
|
if (import->sectionType() == ItemLibraryImport::SectionType::Unimported)
|
||||||
|
*changed |= import->setVisible(!m_searchText.isEmpty());
|
||||||
|
|
||||||
// expand import if it has an item matching search criteria
|
// expand import if it has an item matching search criteria
|
||||||
if (hasVisibleItems && !import->importExpanded())
|
if (hasVisibleItems && !import->importExpanded())
|
||||||
import->setImportExpanded();
|
import->setImportExpanded();
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ public:
|
|||||||
Q_INVOKABLE void expandAll();
|
Q_INVOKABLE void expandAll();
|
||||||
Q_INVOKABLE void collapseAll();
|
Q_INVOKABLE void collapseAll();
|
||||||
|
|
||||||
|
Import entryToImport(const ItemLibraryEntry &entry);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateVisibility(bool *changed);
|
void updateVisibility(bool *changed);
|
||||||
void addRoleNames();
|
void addRoleNames();
|
||||||
|
|||||||
@@ -86,15 +86,35 @@ bool ItemLibraryWidget::eventFilter(QObject *obj, QEvent *event)
|
|||||||
QMetaObject::invokeMethod(m_itemViewQuickWidget->rootObject(), "closeContextMenu");
|
QMetaObject::invokeMethod(m_itemViewQuickWidget->rootObject(), "closeContextMenu");
|
||||||
} else if (event->type() == QMouseEvent::MouseMove) {
|
} else if (event->type() == QMouseEvent::MouseMove) {
|
||||||
if (m_itemToDrag.isValid()) {
|
if (m_itemToDrag.isValid()) {
|
||||||
ItemLibraryEntry entry = m_itemToDrag.value<ItemLibraryEntry>();
|
QMouseEvent *me = static_cast<QMouseEvent *>(event);
|
||||||
auto drag = new QDrag(this);
|
if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 10) {
|
||||||
drag->setPixmap(Utils::StyleHelper::dpiSpecificImageFile(entry.libraryEntryIconPath()));
|
ItemLibraryEntry entry = m_itemToDrag.value<ItemLibraryEntry>();
|
||||||
drag->setMimeData(m_itemLibraryModel->getMimeData(entry));
|
// For drag to be handled correctly, we must have the component properly imported
|
||||||
drag->exec();
|
// beforehand, so we import the module immediately when the drag starts
|
||||||
drag->deleteLater();
|
if (!entry.requiredImport().isEmpty()) {
|
||||||
|
Import import = Import::createLibraryImport(entry.requiredImport());
|
||||||
|
if (!m_model->hasImport(import, true, true)) {
|
||||||
|
const QList<Import> possImports = m_model->possibleImports();
|
||||||
|
for (const auto &possImport : possImports) {
|
||||||
|
if (possImport.url() == import.url()) {
|
||||||
|
m_model->changeImports({possImport}, {});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_itemToDrag = {};
|
auto drag = new QDrag(this);
|
||||||
|
drag->setPixmap(Utils::StyleHelper::dpiSpecificImageFile(entry.libraryEntryIconPath()));
|
||||||
|
drag->setMimeData(m_itemLibraryModel->getMimeData(entry));
|
||||||
|
drag->exec();
|
||||||
|
drag->deleteLater();
|
||||||
|
|
||||||
|
m_itemToDrag = {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else if (event->type() == QMouseEvent::MouseButtonRelease) {
|
||||||
|
m_itemToDrag = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return QObject::eventFilter(obj, event);
|
return QObject::eventFilter(obj, event);
|
||||||
@@ -349,6 +369,7 @@ void ItemLibraryWidget::updateModel()
|
|||||||
void ItemLibraryWidget::updatePossibleImports(const QList<Import> &possibleImports)
|
void ItemLibraryWidget::updatePossibleImports(const QList<Import> &possibleImports)
|
||||||
{
|
{
|
||||||
m_itemLibraryAddImportModel->update(possibleImports);
|
m_itemLibraryAddImportModel->update(possibleImports);
|
||||||
|
delayedUpdateModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemLibraryWidget::updateUsedImports(const QList<Import> &usedImports)
|
void ItemLibraryWidget::updateUsedImports(const QList<Import> &usedImports)
|
||||||
@@ -387,12 +408,13 @@ void ItemLibraryWidget::setResourcePath(const QString &resourcePath)
|
|||||||
updateSearch();
|
updateSearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemLibraryWidget::startDragAndDrop(const QVariant &itemLibEntry)
|
void ItemLibraryWidget::startDragAndDrop(const QVariant &itemLibEntry, const QPointF &mousePos)
|
||||||
{
|
{
|
||||||
// Actual drag is created after mouse has moved to avoid a QDrag bug that causes drag to stay
|
// Actual drag is created after mouse has moved to avoid a QDrag bug that causes drag to stay
|
||||||
// active (and blocks mouse release) if mouse is released at the same spot of the drag start.
|
// active (and blocks mouse release) if mouse is released at the same spot of the drag start.
|
||||||
// This doesn't completely eliminate the bug but makes it significantly harder to produce.
|
// This doesn't completely eliminate the bug but makes it significantly harder to produce.
|
||||||
m_itemToDrag = itemLibEntry;
|
m_itemToDrag = itemLibEntry;
|
||||||
|
m_dragStartPoint = mousePos.toPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemLibraryWidget::setFlowMode(bool b)
|
void ItemLibraryWidget::setFlowMode(bool b)
|
||||||
@@ -409,6 +431,15 @@ void ItemLibraryWidget::removeImport(const QString &importUrl)
|
|||||||
m_model->changeImports({}, {importSection->importEntry()});
|
m_model->changeImports({}, {importSection->importEntry()});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ItemLibraryWidget::addImportForItem(const QVariant &entry)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_itemLibraryModel, return);
|
||||||
|
QTC_ASSERT(m_model, return);
|
||||||
|
|
||||||
|
Import import = m_itemLibraryModel->entryToImport(entry.value<ItemLibraryEntry>());
|
||||||
|
m_model->changeImports({import}, {});
|
||||||
|
}
|
||||||
|
|
||||||
void ItemLibraryWidget::addResources(const QStringList &files)
|
void ItemLibraryWidget::addResources(const QStringList &files)
|
||||||
{
|
{
|
||||||
auto document = QmlDesignerPlugin::instance()->currentDesignDocument();
|
auto document = QmlDesignerPlugin::instance()->currentDesignDocument();
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include <QQuickWidget>
|
#include <QQuickWidget>
|
||||||
#include <QQmlPropertyMap>
|
#include <QQmlPropertyMap>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QPointF>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -87,8 +88,9 @@ public:
|
|||||||
void setModel(Model *model);
|
void setModel(Model *model);
|
||||||
void setFlowMode(bool b);
|
void setFlowMode(bool b);
|
||||||
|
|
||||||
Q_INVOKABLE void startDragAndDrop(const QVariant &itemLibEntry);
|
Q_INVOKABLE void startDragAndDrop(const QVariant &itemLibEntry, const QPointF &mousePos);
|
||||||
Q_INVOKABLE void removeImport(const QString &importUrl);
|
Q_INVOKABLE void removeImport(const QString &importUrl);
|
||||||
|
Q_INVOKABLE void addImportForItem(const QVariant &entry);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void itemActivated(const QString& itemName);
|
void itemActivated(const QString& itemName);
|
||||||
@@ -127,6 +129,7 @@ private:
|
|||||||
QVariant m_itemToDrag;
|
QVariant m_itemToDrag;
|
||||||
bool m_updateRetry = false;
|
bool m_updateRetry = false;
|
||||||
QString m_filterText;
|
QString m_filterText;
|
||||||
|
QPoint m_dragStartPoint;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleTabChanged(int index);
|
void handleTabChanged(int index);
|
||||||
|
|||||||
Reference in New Issue
Block a user