feat: drag-and-drop support for explorer

This commit is contained in:
maelstrom 2025-01-26 17:14:55 +01:00
parent f316b26a83
commit 10999be3b6
5 changed files with 77 additions and 5 deletions

16
.vscode/launch.json vendored Normal file
View 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}",
}
]
}

View file

@ -5,11 +5,14 @@
#include "qimage.h"
#include "qnamespace.h"
#include "qobject.h"
#include "qstringview.h"
#include "qwidget.h"
#include "qmimedata.h"
#include "common.h"
#include <algorithm>
#include <cstdio>
#include <optional>
#include <vector>
#include "objects/base/instance.h"
// 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) {
if (oldParent.has_value()) {
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);
}
@ -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;
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");
}

View file

@ -35,9 +35,12 @@ public:
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 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 supportedDropActions() const override;
InstanceRef fromIndex(const QModelIndex index);
InstanceRef fromIndex(const QModelIndex index) const;
private:
InstanceRef rootItem;
QModelIndex toIndex(InstanceRef item);

View file

@ -1,6 +1,7 @@
#include "explorerview.h"
#include "explorermodel.h"
#include "common.h"
#include "qabstractitemmodel.h"
#include "qaction.h"
#include "qnamespace.h"
@ -9,7 +10,11 @@ ExplorerView::ExplorerView(QWidget* parent):
model(ExplorerModel(std::dynamic_pointer_cast<Instance>(workspace))) {
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->setSelectionMode(QAbstractItemView::ExtendedSelection);
this->setDragEnabled(true);

View file

@ -17,7 +17,9 @@ class ExplorerView : public QTreeView {
public:
ExplorerView(QWidget* parent = nullptr);
~ExplorerView() override;
void keyPressEvent(QKeyEvent* evt) override;
void keyPressEvent(QKeyEvent*) override;
// void dropEvent(QDropEvent*) override;
private:
ExplorerModel model;
QMenu contextMenu;