forked from qt-creator/qt-creator
QmlDesigner: Allow dropping external assets
External assets can be dropped to Form Editor, 3D Editor, Text Editor, and Navigator. Fixes: QDS-5045 Change-Id: I2de06ab118350a8d0809b286c16d06e7edea92e4 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -58,6 +58,7 @@
|
|||||||
#include <QGraphicsLinearLayout>
|
#include <QGraphicsLinearLayout>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QMimeData>
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
@@ -241,6 +242,56 @@ ModelNodePreviewImageOperation DesignerActionManager::modelNodePreviewOperation(
|
|||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DesignerActionManager::externalDragHasSupportedAssets(const QMimeData *mimeData) const
|
||||||
|
{
|
||||||
|
if (!mimeData->hasUrls())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QSet<QString> filtersSet;
|
||||||
|
const QList<AddResourceHandler> handlers = addResourceHandler();
|
||||||
|
for (const AddResourceHandler &handler : handlers)
|
||||||
|
filtersSet.insert(handler.filter);
|
||||||
|
|
||||||
|
const QList<QUrl> urls = mimeData->urls();
|
||||||
|
for (const QUrl &url : urls) {
|
||||||
|
QString suffix = "*." + url.fileName().split('.').last().toLower();
|
||||||
|
if (filtersSet.contains(suffix)) // accept drop if it contains a valid file
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DesignerActionManager::handleExternalAssetsDrop(const QMimeData *mimeData) const
|
||||||
|
{
|
||||||
|
const QList<AddResourceHandler> handlers = addResourceHandler();
|
||||||
|
// create suffix to categry and category to operation hashes
|
||||||
|
QHash<QString, QString> suffixCategory;
|
||||||
|
QHash<QString, AddResourceOperation> categoryOperation;
|
||||||
|
for (const AddResourceHandler &handler : handlers) {
|
||||||
|
suffixCategory.insert(handler.filter, handler.category);
|
||||||
|
categoryOperation.insert(handler.category, handler.operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add files grouped by categories (so that files under same category run under 1 operation)
|
||||||
|
QHash<QString, QStringList> categoryFiles;
|
||||||
|
const QList<QUrl> urls = mimeData->urls();
|
||||||
|
for (const QUrl &url : urls) {
|
||||||
|
QString suffix = "*." + url.fileName().split('.').last().toLower();
|
||||||
|
QString category = suffixCategory.value(suffix);
|
||||||
|
if (!category.isEmpty())
|
||||||
|
categoryFiles[category].append(url.toLocalFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
// run operations
|
||||||
|
const QStringList categories = categoryFiles.keys();
|
||||||
|
for (const QString &category : categories) {
|
||||||
|
AddResourceOperation operation = categoryOperation.value(category);
|
||||||
|
QStringList files = categoryFiles.value(category);
|
||||||
|
operation(files, {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class VisiblityModelNodeAction : public ModelNodeContextMenuAction
|
class VisiblityModelNodeAction : public ModelNodeContextMenuAction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@@ -38,6 +38,7 @@
|
|||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QGraphicsItem;
|
class QGraphicsItem;
|
||||||
class QGraphicsWidget;
|
class QGraphicsWidget;
|
||||||
|
class QMimeData;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
@@ -135,6 +136,8 @@ public:
|
|||||||
void registerModelNodePreviewHandler(const ModelNodePreviewImageHandler &handler);
|
void registerModelNodePreviewHandler(const ModelNodePreviewImageHandler &handler);
|
||||||
bool hasModelNodePreviewHandler(const ModelNode &node) const;
|
bool hasModelNodePreviewHandler(const ModelNode &node) const;
|
||||||
ModelNodePreviewImageOperation modelNodePreviewOperation(const ModelNode &node) const;
|
ModelNodePreviewImageOperation modelNodePreviewOperation(const ModelNode &node) const;
|
||||||
|
bool externalDragHasSupportedAssets(const QMimeData *data) const;
|
||||||
|
void handleExternalAssetsDrop(const QMimeData *data) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addTransitionEffectAction(const TypeName &typeName);
|
void addTransitionEffectAction(const TypeName &typeName);
|
||||||
|
@@ -40,6 +40,7 @@
|
|||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
#include <QActionGroup>
|
#include <QActionGroup>
|
||||||
|
#include <QMimeData>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
@@ -47,6 +48,8 @@ namespace QmlDesigner {
|
|||||||
Edit3DWidget::Edit3DWidget(Edit3DView *view) :
|
Edit3DWidget::Edit3DWidget(Edit3DView *view) :
|
||||||
m_view(view)
|
m_view(view)
|
||||||
{
|
{
|
||||||
|
setAcceptDrops(true);
|
||||||
|
|
||||||
Core::Context context(Constants::C_QMLEDITOR3D);
|
Core::Context context(Constants::C_QMLEDITOR3D);
|
||||||
m_context = new Core::IContext(this);
|
m_context = new Core::IContext(this);
|
||||||
m_context->setContext(context);
|
m_context->setContext(context);
|
||||||
@@ -159,4 +162,19 @@ Edit3DView *Edit3DWidget::view() const
|
|||||||
return m_view.data();
|
return m_view.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Edit3DWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
|
||||||
|
{
|
||||||
|
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
|
||||||
|
->viewManager().designerActionManager();
|
||||||
|
if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData()))
|
||||||
|
dragEnterEvent->acceptProposedAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Edit3DWidget::dropEvent(QDropEvent *dropEvent)
|
||||||
|
{
|
||||||
|
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
|
||||||
|
->viewManager().designerActionManager();
|
||||||
|
actionManager.handleExternalAssetsDrop(dropEvent->mimeData());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
||||||
|
@@ -48,6 +48,10 @@ public:
|
|||||||
|
|
||||||
void showCanvas(bool show);
|
void showCanvas(bool show);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void dragEnterEvent(QDragEnterEvent *dragEnterEvent) override;
|
||||||
|
void dropEvent(QDropEvent *dropEvent) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void linkActivated(const QString &link);
|
void linkActivated(const QString &link);
|
||||||
|
|
||||||
|
@@ -53,6 +53,7 @@
|
|||||||
|
|
||||||
#include <QActionGroup>
|
#include <QActionGroup>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
#include <QMimeData>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPicture>
|
#include <QPicture>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
@@ -63,6 +64,8 @@ namespace QmlDesigner {
|
|||||||
FormEditorWidget::FormEditorWidget(FormEditorView *view)
|
FormEditorWidget::FormEditorWidget(FormEditorView *view)
|
||||||
: m_formEditorView(view)
|
: m_formEditorView(view)
|
||||||
{
|
{
|
||||||
|
setAcceptDrops(true);
|
||||||
|
|
||||||
Core::Context context(Constants::C_QMLFORMEDITOR);
|
Core::Context context(Constants::C_QMLFORMEDITOR);
|
||||||
m_context = new Core::IContext(this);
|
m_context = new Core::IContext(this);
|
||||||
m_context->setContext(context);
|
m_context->setContext(context);
|
||||||
@@ -582,4 +585,19 @@ void FormEditorWidget::showEvent(QShowEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FormEditorWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
|
||||||
|
{
|
||||||
|
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
|
||||||
|
->viewManager().designerActionManager();
|
||||||
|
if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData()))
|
||||||
|
dragEnterEvent->acceptProposedAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FormEditorWidget::dropEvent(QDropEvent *dropEvent)
|
||||||
|
{
|
||||||
|
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
|
||||||
|
->viewManager().designerActionManager();
|
||||||
|
actionManager.handleExternalAssetsDrop(dropEvent->mimeData());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -49,6 +49,7 @@ class QmlItemNode;
|
|||||||
class FormEditorWidget : public QWidget
|
class FormEditorWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FormEditorWidget(FormEditorView *view);
|
FormEditorWidget(FormEditorView *view);
|
||||||
|
|
||||||
@@ -93,6 +94,8 @@ protected:
|
|||||||
DocumentWarningWidget *errorWidget();
|
DocumentWarningWidget *errorWidget();
|
||||||
void hideEvent(QHideEvent *event) override;
|
void hideEvent(QHideEvent *event) override;
|
||||||
void showEvent(QShowEvent *event) override;
|
void showEvent(QShowEvent *event) override;
|
||||||
|
void dragEnterEvent(QDragEnterEvent *dragEnterEvent) override;
|
||||||
|
void dropEvent(QDropEvent *dropEvent) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void changeTransformTool(bool checked);
|
void changeTransformTool(bool checked);
|
||||||
|
@@ -49,6 +49,8 @@ NavigatorWidget::NavigatorWidget(NavigatorView *view)
|
|||||||
: m_treeView(new NavigatorTreeView)
|
: m_treeView(new NavigatorTreeView)
|
||||||
, m_navigatorView(view)
|
, m_navigatorView(view)
|
||||||
{
|
{
|
||||||
|
setAcceptDrops(true);
|
||||||
|
|
||||||
m_treeView->setDragEnabled(true);
|
m_treeView->setDragEnabled(true);
|
||||||
m_treeView->setAcceptDrops(true);
|
m_treeView->setAcceptDrops(true);
|
||||||
m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
@@ -184,4 +186,19 @@ NavigatorView *NavigatorWidget::navigatorView() const
|
|||||||
return m_navigatorView.data();
|
return m_navigatorView.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NavigatorWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
|
||||||
|
{
|
||||||
|
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
|
||||||
|
->viewManager().designerActionManager();
|
||||||
|
if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData()))
|
||||||
|
dragEnterEvent->acceptProposedAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NavigatorWidget::dropEvent(QDropEvent *dropEvent)
|
||||||
|
{
|
||||||
|
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
|
||||||
|
->viewManager().designerActionManager();
|
||||||
|
actionManager.handleExternalAssetsDrop(dropEvent->mimeData());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -43,6 +43,7 @@ class NavigatorView;
|
|||||||
class NavigatorWidget: public QFrame
|
class NavigatorWidget: public QFrame
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NavigatorWidget(NavigatorView *view);
|
NavigatorWidget(NavigatorView *view);
|
||||||
|
|
||||||
@@ -63,10 +64,13 @@ signals:
|
|||||||
void filterToggled(bool);
|
void filterToggled(bool);
|
||||||
void reverseOrderToggled(bool);
|
void reverseOrderToggled(bool);
|
||||||
|
|
||||||
private: // functions
|
protected:
|
||||||
|
void dragEnterEvent(QDragEnterEvent *dragEnterEvent) override;
|
||||||
|
void dropEvent(QDropEvent *dropEvent) override;
|
||||||
|
|
||||||
|
private:
|
||||||
NavigatorView *navigatorView() const;
|
NavigatorView *navigatorView() const;
|
||||||
|
|
||||||
private: // variables
|
|
||||||
NavigatorTreeView *m_treeView;
|
NavigatorTreeView *m_treeView;
|
||||||
QPointer<NavigatorView> m_navigatorView;
|
QPointer<NavigatorView> m_navigatorView;
|
||||||
};
|
};
|
||||||
|
@@ -53,6 +53,8 @@ TextEditorWidget::TextEditorWidget(TextEditorView *textEditorView)
|
|||||||
, m_textEditorView(textEditorView)
|
, m_textEditorView(textEditorView)
|
||||||
, m_statusBar(new TextEditorStatusBar(this))
|
, m_statusBar(new TextEditorStatusBar(this))
|
||||||
{
|
{
|
||||||
|
setAcceptDrops(true);
|
||||||
|
|
||||||
QBoxLayout *layout = new QVBoxLayout(this);
|
QBoxLayout *layout = new QVBoxLayout(this);
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
layout->setSpacing(0);
|
layout->setSpacing(0);
|
||||||
@@ -179,7 +181,7 @@ void TextEditorWidget::setBlockCursorSelectionSynchronisation(bool b)
|
|||||||
m_blockCursorSelectionSynchronisation = b;
|
m_blockCursorSelectionSynchronisation = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextEditorWidget::eventFilter( QObject *, QEvent *event)
|
bool TextEditorWidget::eventFilter(QObject *, QEvent *event)
|
||||||
{
|
{
|
||||||
static std::vector<int> overrideKeys = { Qt::Key_Delete, Qt::Key_Backspace, Qt::Key_Insert,
|
static std::vector<int> overrideKeys = { Qt::Key_Delete, Qt::Key_Backspace, Qt::Key_Insert,
|
||||||
Qt::Key_Escape };
|
Qt::Key_Escape };
|
||||||
@@ -216,5 +218,19 @@ bool TextEditorWidget::eventFilter( QObject *, QEvent *event)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextEditorWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
|
||||||
|
{
|
||||||
|
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
|
||||||
|
->viewManager().designerActionManager();
|
||||||
|
if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData()))
|
||||||
|
dragEnterEvent->acceptProposedAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextEditorWidget::dropEvent(QDropEvent *dropEvent)
|
||||||
|
{
|
||||||
|
const DesignerActionManager &actionManager = QmlDesignerPlugin::instance()
|
||||||
|
->viewManager().designerActionManager();
|
||||||
|
actionManager.handleExternalAssetsDrop(dropEvent->mimeData());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -63,6 +63,8 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool eventFilter(QObject *object, QEvent *event) override;
|
bool eventFilter(QObject *object, QEvent *event) override;
|
||||||
|
void dragEnterEvent(QDragEnterEvent *dragEnterEvent) override;
|
||||||
|
void dropEvent(QDropEvent *dropEvent) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateSelectionByCursorPosition();
|
void updateSelectionByCursorPosition();
|
||||||
|
Reference in New Issue
Block a user