forked from qt-creator/qt-creator
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:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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) {
|
||||
|
@@ -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;
|
||||
|
@@ -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()) {
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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
|
||||
|
@@ -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";
|
||||
|
@@ -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 };
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user