feat: drag-and-drop support for explorer
This commit is contained in:
parent
f316b26a83
commit
10999be3b6
16
.vscode/launch.json
vendored
Normal file
16
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug",
|
||||||
|
"program": "${workspaceFolder}/bin/editor",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -5,11 +5,14 @@
|
||||||
#include "qimage.h"
|
#include "qimage.h"
|
||||||
#include "qnamespace.h"
|
#include "qnamespace.h"
|
||||||
#include "qobject.h"
|
#include "qobject.h"
|
||||||
|
#include "qstringview.h"
|
||||||
#include "qwidget.h"
|
#include "qwidget.h"
|
||||||
|
#include "qmimedata.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
#include "objects/base/instance.h"
|
#include "objects/base/instance.h"
|
||||||
|
|
||||||
// https://doc.qt.io/qt-6/qtwidgets-itemviews-simpletreemodel-example.html#testing-the-model
|
// https://doc.qt.io/qt-6/qtwidgets-itemviews-simpletreemodel-example.html#testing-the-model
|
||||||
|
@ -23,7 +26,7 @@ ExplorerModel::ExplorerModel(InstanceRef dataRoot, QWidget *parent)
|
||||||
hierarchyPreUpdateHandler = [&](InstanceRef object, std::optional<InstanceRef> oldParent, std::optional<InstanceRef> newParent) {
|
hierarchyPreUpdateHandler = [&](InstanceRef object, std::optional<InstanceRef> oldParent, std::optional<InstanceRef> newParent) {
|
||||||
if (oldParent.has_value()) {
|
if (oldParent.has_value()) {
|
||||||
auto children = oldParent.value()->GetChildren();
|
auto children = oldParent.value()->GetChildren();
|
||||||
size_t idx = std::find(children.begin(), children.end(), object) - children.end();
|
size_t idx = std::find(children.begin(), children.end(), object) - children.begin();
|
||||||
beginRemoveRows(toIndex(oldParent.value()), idx, idx);
|
beginRemoveRows(toIndex(oldParent.value()), idx, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +200,50 @@ Qt::DropActions ExplorerModel::supportedDropActions() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
InstanceRef ExplorerModel::fromIndex(const QModelIndex index) {
|
InstanceRef ExplorerModel::fromIndex(const QModelIndex index) const {
|
||||||
if (!index.isValid()) return workspace;
|
if (!index.isValid()) return workspace;
|
||||||
return static_cast<Instance*>(index.internalPointer())->shared_from_this();
|
return static_cast<Instance*>(index.internalPointer())->shared_from_this();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DragDropSlot {
|
||||||
|
std::vector<InstanceRef> instances;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool ExplorerModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) {
|
||||||
|
// if (action != Qt::InternalMove) return;
|
||||||
|
QByteArray byteData = data->data("application/x-openblocks-instance-pointers");
|
||||||
|
uintptr_t slotPtr = byteData.toULongLong();
|
||||||
|
DragDropSlot* slot = (DragDropSlot*)slotPtr;
|
||||||
|
|
||||||
|
if (!parent.isValid()) {
|
||||||
|
delete slot;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
InstanceRef parentInst = fromIndex(parent);
|
||||||
|
for (InstanceRef instance : slot->instances) {
|
||||||
|
instance->SetParent(parentInst);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete slot;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMimeData* ExplorerModel::mimeData(const QModelIndexList& indexes) const {
|
||||||
|
// application/x-openblocks-instance-pointers
|
||||||
|
DragDropSlot* slot = new DragDropSlot();
|
||||||
|
|
||||||
|
for (const QModelIndex& index : indexes) {
|
||||||
|
slot->instances.push_back(fromIndex(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
// uintptr_t ptr = (uintptr_t)&slot;
|
||||||
|
|
||||||
|
QMimeData* mimeData = new QMimeData();
|
||||||
|
mimeData->setData("application/x-openblocks-instance-pointers", QByteArray::number((qulonglong)slot));
|
||||||
|
return mimeData;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList ExplorerModel::mimeTypes() const {
|
||||||
|
return QStringList("application/x-openblocks-instance-pointers");
|
||||||
|
}
|
|
@ -35,9 +35,12 @@ public:
|
||||||
bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override;
|
bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override;
|
||||||
bool removeRows(int row, int count, const QModelIndex & parent = QModelIndex()) override;
|
bool removeRows(int row, int count, const QModelIndex & parent = QModelIndex()) override;
|
||||||
bool insertRows(int row, int count, const QModelIndex & parent = QModelIndex()) override;
|
bool insertRows(int row, int count, const QModelIndex & parent = QModelIndex()) override;
|
||||||
|
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
||||||
|
QMimeData* mimeData(const QModelIndexList& indexes) const override;
|
||||||
|
QStringList mimeTypes() const override;
|
||||||
Qt::DropActions supportedDragActions() const override;
|
Qt::DropActions supportedDragActions() const override;
|
||||||
Qt::DropActions supportedDropActions() const override;
|
Qt::DropActions supportedDropActions() const override;
|
||||||
InstanceRef fromIndex(const QModelIndex index);
|
InstanceRef fromIndex(const QModelIndex index) const;
|
||||||
private:
|
private:
|
||||||
InstanceRef rootItem;
|
InstanceRef rootItem;
|
||||||
QModelIndex toIndex(InstanceRef item);
|
QModelIndex toIndex(InstanceRef item);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "explorerview.h"
|
#include "explorerview.h"
|
||||||
#include "explorermodel.h"
|
#include "explorermodel.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "qabstractitemmodel.h"
|
||||||
#include "qaction.h"
|
#include "qaction.h"
|
||||||
#include "qnamespace.h"
|
#include "qnamespace.h"
|
||||||
|
|
||||||
|
@ -9,7 +10,11 @@ ExplorerView::ExplorerView(QWidget* parent):
|
||||||
model(ExplorerModel(std::dynamic_pointer_cast<Instance>(workspace))) {
|
model(ExplorerModel(std::dynamic_pointer_cast<Instance>(workspace))) {
|
||||||
|
|
||||||
this->setModel(&model);
|
this->setModel(&model);
|
||||||
this->setRootIsDecorated(false);
|
// Disabling the root decoration will cause the expand/collapse chevrons to be hidden too, we don't want that
|
||||||
|
// https://stackoverflow.com/a/4687016/16255372
|
||||||
|
// this->setRootIsDecorated(false);
|
||||||
|
// The branches can be customized like this if you want:
|
||||||
|
// this->setStyleSheet(QString("QTreeView::branch { border: none; }"));
|
||||||
this->setDragDropMode(QAbstractItemView::InternalMove);
|
this->setDragDropMode(QAbstractItemView::InternalMove);
|
||||||
this->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
this->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
this->setDragEnabled(true);
|
this->setDragEnabled(true);
|
||||||
|
|
|
@ -17,7 +17,9 @@ class ExplorerView : public QTreeView {
|
||||||
public:
|
public:
|
||||||
ExplorerView(QWidget* parent = nullptr);
|
ExplorerView(QWidget* parent = nullptr);
|
||||||
~ExplorerView() override;
|
~ExplorerView() override;
|
||||||
void keyPressEvent(QKeyEvent* evt) override;
|
|
||||||
|
void keyPressEvent(QKeyEvent*) override;
|
||||||
|
// void dropEvent(QDropEvent*) override;
|
||||||
private:
|
private:
|
||||||
ExplorerModel model;
|
ExplorerModel model;
|
||||||
QMenu contextMenu;
|
QMenu contextMenu;
|
||||||
|
|
Loading…
Reference in a new issue