QmlDesigner: Implement keyboard commands in AssetsLibrary

Up and Down now change selection--they work only for files, they skip
directories.

The Delete key will (ask confirmation to) delete the selected files,
just as it happens when clicking Delete from the Context menu.

Also, did a small fix in the AssetDelegate, where, on mouse release,
you could have a directory added to the selection list.

Task-number: QDS-8710
Change-Id: I05e232ed0ce94709df41a5150a49300ad65c0a86
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Samuel Ghinet
2023-02-02 21:03:17 +02:00
parent 0c7ae672a2
commit 339ebeab8e
13 changed files with 174 additions and 17 deletions

View File

@@ -171,11 +171,16 @@ TreeViewDelegate {
onReleased: (mouse) => {
mouseArea.allowTooltip = true
if (root.__isDirectory)
return
if (mouse.button === Qt.LeftButton) {
if (!(mouse.modifiers & Qt.ControlModifier))
root.assetsView.selectedAssets = {}
root.assetsView.selectedAssets[root.__itemPath] = root.currFileSelected
root.assetsView.selectedAssetsChanged()
root.assetsView.currentFilePath = root.__itemPath
}
}

View File

@@ -24,6 +24,8 @@ TreeView {
property alias verticalScrollBar: verticalScrollBar
property var selectedAssets: ({})
// the latest file that was clicked, or changed to via Up or Down keys
property string currentFilePath: ""
// used to see if the op requested is to expand or to collapse.
property int lastRowCount: -1
@@ -34,6 +36,7 @@ TreeView {
property int rootPathRow: 0
// i.e. first child of the root path
readonly property int firstRow: root.rootPathRow + 1
readonly property int lastRow: root.rows - 1
property var __createdDirectories: []
rowHeightProvider: (row) => {
@@ -78,6 +81,19 @@ TreeView {
updateRowsTimer.restart()
}
function onDeleteSelectedAssetsRequested()
{
let selectedPaths = root.selectedPathsAsList()
if (!selectedPaths.length)
return
let deleted = assetsModel.requestDeleteFiles(selectedPaths)
if (!deleted) {
confirmDeleteFiles.files = selectedPaths
confirmDeleteFiles.open()
}
}
}
Connections {
@@ -319,6 +335,73 @@ TreeView {
return root.modelIndex(row, 0)
}
function __selectRow(row: int)
{
let index = root.__modelIndex(row)
if (assetsModel.isDirectory(index))
return
let filePath = assetsModel.filePath(index)
root.clearSelectedAssets()
root.setAssetSelected(filePath, true)
root.currentFilePath = filePath
}
Keys.enabled: true
Keys.onUpPressed: {
if (!root.currentFilePath)
return
let index = assetsModel.indexForPath(root.currentFilePath)
let row = root.rowAtIndex(index)
let nextRow = row
let nextIndex = index
do {
if (nextRow <= root.firstRow)
return // don't select hidden rows
nextRow--
nextIndex = root.__modelIndex(nextRow)
} while (assetsModel.isDirectory(nextIndex))
root.__selectRow(nextRow)
root.positionViewAtRow(nextRow, TableView.Contain)
}
Keys.onDownPressed: {
if (!root.currentFilePath)
return
let index = assetsModel.indexForPath(root.currentFilePath)
let row = root.rowAtIndex(index)
let nextRow = row
let nextIndex = index
do {
if (nextRow >= root.lastRow)
return // don't select hidden rows
nextRow++
nextIndex = root.__modelIndex(nextRow)
} while (assetsModel.isDirectory(nextIndex))
root.__selectRow(nextRow)
root.positionViewAtRow(nextRow, TableView.Contain)
}
ConfirmDeleteFilesDialog {
id: confirmDeleteFiles
parent: root
files: []
onAccepted: root.clearSelectedAssets()
onClosed: confirmDeleteFiles.files = []
}
DropArea {
id: dropArea
enabled: true

View File

@@ -5,6 +5,7 @@
#include "assetslibrarywidget.h"
#include "createtexture.h"
#include "designmodecontext.h"
#include "qmldesignerplugin.h"
#include <asynchronousimagecache.h>
@@ -61,7 +62,11 @@ WidgetInfo AssetsLibraryView::widgetInfo()
{
if (m_widget.isNull()) {
m_widget = new AssetsLibraryWidget{imageCacheData()->asynchronousFontImageCache,
imageCacheData()->synchronousFontImageCache};
imageCacheData()->synchronousFontImageCache,
this};
auto context = new Internal::AssetsLibraryContext(m_widget.data());
Core::ICore::addContextObject(context);
connect(m_widget, &AssetsLibraryWidget::addTexturesRequested, this,
[&] (const QStringList &filePaths, AddTextureMode mode) {
@@ -84,6 +89,15 @@ WidgetInfo AssetsLibraryView::widgetInfo()
return createWidgetInfo(m_widget.data(), "Assets", WidgetInfo::LeftPane, 0, tr("Assets"));
}
void AssetsLibraryView::customNotification(const AbstractView *view,
const QString &identifier,
const QList<ModelNode> &nodeList,
const QList<QVariant> &data)
{
if (identifier == "delete_selected_assets")
m_widget->deleteSelectedAssets();
}
void AssetsLibraryView::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
@@ -113,7 +127,8 @@ void AssetsLibraryView::setResourcePath(const QString &resourcePath)
if (m_widget.isNull()) {
m_widget = new AssetsLibraryWidget{imageCacheData()->asynchronousFontImageCache,
imageCacheData()->synchronousFontImageCache};
imageCacheData()->synchronousFontImageCache,
this};
}
m_widget->setResourcePath(resourcePath);

View File

@@ -37,6 +37,9 @@ private:
class ImageCacheData;
ImageCacheData *imageCacheData();
void customNotification(const AbstractView *view, const QString &identifier,
const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
std::once_flag imageCacheFlag;
std::unique_ptr<ImageCacheData> m_imageCacheData;
QPointer<AssetsLibraryWidget> m_widget;

View File

@@ -7,7 +7,8 @@
#include "assetslibraryiconprovider.h"
#include "assetslibrarymodel.h"
#include "designeractionmanager.h"
#include "model.h"
#include "assetslibraryview.h"
#include "modelnodeoperations.h"
#include "qmldesignerconstants.h"
#include "qmldesignerplugin.h"
@@ -84,11 +85,13 @@ bool AssetsLibraryWidget::eventFilter(QObject *obj, QEvent *event)
}
AssetsLibraryWidget::AssetsLibraryWidget(AsynchronousImageCache &asynchronousFontImageCache,
SynchronousImageCache &synchronousFontImageCache)
SynchronousImageCache &synchronousFontImageCache,
AssetsLibraryView *view)
: m_itemIconSize{24, 24}
, m_fontImageCache{synchronousFontImageCache}
, m_assetsIconProvider{new AssetsLibraryIconProvider(synchronousFontImageCache)}
, m_assetsModel{new AssetsLibraryModel(this)}
, m_assetsView{view}
, m_assetsWidget{new StudioQuickWidget(this)}
{
setWindowTitle(tr("Assets Library", "Title of assets library widget"));
@@ -150,6 +153,19 @@ AssetsLibraryWidget::AssetsLibraryWidget(AsynchronousImageCache &asynchronousFon
reloadQmlSource();
}
void AssetsLibraryWidget::contextHelp(const Core::IContext::HelpCallback &callback) const
{
if (m_assetsView)
QmlDesignerPlugin::contextHelp(callback, m_assetsView->contextHelpId());
else
callback({});
}
void AssetsLibraryWidget::deleteSelectedAssets()
{
emit deleteSelectedAssetsRequested();
}
QString AssetsLibraryWidget::getUniqueEffectPath(const QString &parentFolder, const QString &effectName)
{
auto genEffectPath = [&parentFolder](const QString &name) {

View File

@@ -3,8 +3,10 @@
#pragma once
#include <coreplugin/icontext.h>
#include <previewtooltip/previewtooltipbackend.h>
#include "createtexture.h"
#include "previewtooltipbackend.h"
#include <QFrame>
#include <QQmlPropertyMap>
@@ -31,6 +33,7 @@ class Model;
class AssetsLibraryIconProvider;
class AssetsLibraryModel;
class AssetsLibraryView;
class SynchronousImageCache;
class AsynchronousImageCache;
class ImageCacheCollector;
@@ -46,10 +49,11 @@ class AssetsLibraryWidget : public QFrame
public:
AssetsLibraryWidget(AsynchronousImageCache &asynchronousFontImageCache,
SynchronousImageCache &synchronousFontImageCache);
SynchronousImageCache &synchronousFontImageCache, AssetsLibraryView *view);
~AssetsLibraryWidget() = default;
QList<QToolButton *> createToolBarWidgets();
void contextHelp(const Core::IContext::HelpCallback &callback) const;
static QString qmlSourcesPath();
void clearSearchFilter();
@@ -64,6 +68,8 @@ public:
bool hasMaterialLibrary() const;
void setHasMaterialLibrary(bool enable);
void deleteSelectedAssets();
Q_INVOKABLE void startDragAsset(const QStringList &assetPaths, const QPointF &mousePos);
Q_INVOKABLE void handleAddAsset();
Q_INVOKABLE void handleSearchFilterChanged(const QString &filterText);
@@ -107,6 +113,7 @@ signals:
void hasMaterialLibraryChanged();
void isDraggingChanged();
void endDrag();
void deleteSelectedAssetsRequested();
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
@@ -124,6 +131,7 @@ private:
AssetsLibraryIconProvider *m_assetsIconProvider = nullptr;
AssetsLibraryModel *m_assetsModel = nullptr;
AssetsLibraryView *m_assetsView = nullptr;
QScopedPointer<StudioQuickWidget> m_assetsWidget;
std::unique_ptr<PreviewTooltipBackend> m_fontPreviewTooltipBackend;

View File

@@ -114,12 +114,14 @@ void DesignerActionManager::polishActions() const
Core::Context qmlDesignerEditor3DContext(Constants::C_QMLEDITOR3D);
Core::Context qmlDesignerNavigatorContext(Constants::C_QMLNAVIGATOR);
Core::Context qmlDesignerMaterialBrowserContext(Constants::C_QMLMATERIALBROWSER);
Core::Context qmlDesignerAssetsLibraryContext(Constants::C_QMLASSETSLIBRARY);
Core::Context qmlDesignerUIContext;
qmlDesignerUIContext.add(qmlDesignerFormEditorContext);
qmlDesignerUIContext.add(qmlDesignerEditor3DContext);
qmlDesignerUIContext.add(qmlDesignerNavigatorContext);
qmlDesignerUIContext.add(qmlDesignerMaterialBrowserContext);
qmlDesignerUIContext.add(qmlDesignerAssetsLibraryContext);
for (auto *action : actions) {
if (!action->menuId().isEmpty()) {

View File

@@ -2,12 +2,13 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "designmodecontext.h"
#include "qmldesignerconstants.h"
#include "assetslibrarywidget.h"
#include "designmodewidget.h"
#include "formeditorwidget.h"
#include "edit3dwidget.h"
#include "formeditorwidget.h"
#include "materialbrowserwidget.h"
#include "navigatorwidget.h"
#include "qmldesignerconstants.h"
#include "texteditorwidget.h"
namespace QmlDesigner {
@@ -61,6 +62,18 @@ void MaterialBrowserContext::contextHelp(const HelpCallback &callback) const
qobject_cast<MaterialBrowserWidget *>(m_widget)->contextHelp(callback);
}
AssetsLibraryContext::AssetsLibraryContext(QWidget *widget)
: IContext(widget)
{
setWidget(widget);
setContext(Core::Context(Constants::C_QMLASSETSLIBRARY, Constants::C_QT_QUICK_TOOLS_MENU));
}
void AssetsLibraryContext::contextHelp(const HelpCallback &callback) const
{
qobject_cast<AssetsLibraryWidget *>(m_widget)->contextHelp(callback);
}
NavigatorContext::NavigatorContext(QWidget *widget)
: IContext(widget)
{

View File

@@ -47,6 +47,15 @@ public:
void contextHelp(const Core::IContext::HelpCallback &callback) const override;
};
class AssetsLibraryContext : public Core::IContext
{
Q_OBJECT
public:
AssetsLibraryContext(QWidget *widget);
void contextHelp(const Core::IContext::HelpCallback &callback) const override;
};
class NavigatorContext : public Core::IContext
{
Q_OBJECT

View File

@@ -17,6 +17,7 @@ const char C_QMLEDITOR3D[] = "QmlDesigner::Editor3D";
const char C_QMLNAVIGATOR[] = "QmlDesigner::Navigator";
const char C_QMLTEXTEDITOR[] = "QmlDesigner::TextEditor";
const char C_QMLMATERIALBROWSER[] = "QmlDesigner::MaterialBrowser";
const char C_QMLASSETSLIBRARY[] = "QmlDesigner::AssetsLibrary";
// Special context for preview menu, shared b/w designer and text editor
const char C_QT_QUICK_TOOLS_MENU[] = "QmlDesigner::ToolsMenu";

View File

@@ -398,17 +398,18 @@ void QmlDesignerPlugin::integrateIntoQtCreator(QWidget *modeWidget)
Core::Context qmlDesignerEditor3dContext(Constants::C_QMLEDITOR3D);
Core::Context qmlDesignerNavigatorContext(Constants::C_QMLNAVIGATOR);
Core::Context qmlDesignerMaterialBrowserContext(Constants::C_QMLMATERIALBROWSER);
Core::Context qmlDesignerAssetsLibraryContext(Constants::C_QMLASSETSLIBRARY);
context->context().add(qmlDesignerMainContext);
context->context().add(qmlDesignerFormEditorContext);
context->context().add(qmlDesignerEditor3dContext);
context->context().add(qmlDesignerNavigatorContext);
context->context().add(qmlDesignerMaterialBrowserContext);
context->context().add(qmlDesignerAssetsLibraryContext);
context->context().add(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID);
d->shortCutManager.registerActions(qmlDesignerMainContext, qmlDesignerFormEditorContext,
qmlDesignerEditor3dContext, qmlDesignerNavigatorContext,
qmlDesignerMaterialBrowserContext);
qmlDesignerEditor3dContext, qmlDesignerNavigatorContext);
const QStringList mimeTypes = { QmlJSTools::Constants::QML_MIMETYPE,
QmlJSTools::Constants::QMLUI_MIMETYPE };

View File

@@ -61,11 +61,8 @@ ShortCutManager::ShortCutManager()
void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContext,
const Core::Context &qmlDesignerFormEditorContext,
const Core::Context &qmlDesignerEditor3DContext,
const Core::Context &qmlDesignerNavigatorContext,
const Core::Context &qmlDesignerMaterialBrowserContext)
const Core::Context &qmlDesignerNavigatorContext)
{
Q_UNUSED(qmlDesignerMaterialBrowserContext)
Core::ActionContainer *editMenu = Core::ActionManager::actionContainer(Core::Constants::M_EDIT);
connect(&m_undoAction, &QAction::triggered, this, &ShortCutManager::undo);
@@ -205,10 +202,11 @@ void ShortCutManager::registerActions(const Core::Context &qmlDesignerMainContex
connect(Core::ICore::instance(), &Core::ICore::contextChanged, this, [&](const Core::Context &context) {
isMatBrowserActive = context.contains(Constants::C_QMLMATERIALBROWSER);
isAssetsLibraryActive = context.contains(Constants::C_QMLASSETSLIBRARY);
if (!context.contains(Constants::C_QMLFORMEDITOR) && !context.contains(Constants::C_QMLEDITOR3D)
&& !context.contains(Constants::C_QMLNAVIGATOR)) {
m_deleteAction.setEnabled(isMatBrowserActive);
m_deleteAction.setEnabled(isMatBrowserActive || isAssetsLibraryActive);
m_cutAction.setEnabled(false);
m_copyAction.setEnabled(false);
m_pasteAction.setEnabled(false);
@@ -263,6 +261,9 @@ void ShortCutManager::deleteSelected()
if (isMatBrowserActive) {
DesignerActionManager &designerActionManager = QmlDesignerPlugin::instance()->viewManager().designerActionManager();
designerActionManager.view()->emitCustomNotification("delete_selected_material");
} else if (isAssetsLibraryActive) {
DesignerActionManager &designerActionManager = QmlDesignerPlugin::instance()->viewManager().designerActionManager();
designerActionManager.view()->emitCustomNotification("delete_selected_assets");
} else if (currentDesignDocument()) {
currentDesignDocument()->deleteSelected();
}

View File

@@ -25,8 +25,7 @@ public:
void registerActions(const Core::Context &qmlDesignerMainContext,
const Core::Context &qmlDesignerFormEditorContext,
const Core::Context &qmlDesignerEditor3DContext,
const Core::Context &qmlDesignerNavigatorContext,
const Core::Context &qmlDesignerMaterialBrowserContext);
const Core::Context &qmlDesignerNavigatorContext);
void connectUndoActions(DesignDocument *designDocument);
void disconnectUndoActions(DesignDocument *designDocument);
@@ -67,6 +66,7 @@ private:
QAction m_escapeAction;
bool isMatBrowserActive = false;
bool isAssetsLibraryActive = false;
};
} // namespace QmlDesigner