add assembly to gcompose, not working yet
This commit is contained in:
@@ -4,6 +4,11 @@
|
||||
#include <cxxabi.h>
|
||||
#include <functional>
|
||||
#include "Core/Object.h"
|
||||
#include <QMimeData>
|
||||
#include <QDataStream>
|
||||
#include <QIODevice>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
ContextModel::ContextModel(QObject* parent)
|
||||
: QAbstractItemModel(parent), m_rootContext(nullptr) {}
|
||||
@@ -11,12 +16,16 @@ ContextModel::ContextModel(QObject* parent)
|
||||
ContextModel::~ContextModel() {}
|
||||
|
||||
void ContextModel::setContext(uLib::ObjectsContext* context) {
|
||||
m_isReseting = true;
|
||||
beginResetModel();
|
||||
m_rootContext = context;
|
||||
if (m_rootContext) {
|
||||
auto refresh = [this]() {
|
||||
if (this->m_isReseting) return;
|
||||
this->m_isReseting = true;
|
||||
this->beginResetModel();
|
||||
this->endResetModel();
|
||||
this->m_isReseting = false;
|
||||
};
|
||||
|
||||
uLib::Object::connect(m_rootContext, &uLib::Object::Updated, refresh);
|
||||
@@ -25,7 +34,6 @@ void ContextModel::setContext(uLib::ObjectsContext* context) {
|
||||
refresh();
|
||||
});
|
||||
uLib::Object::connect(m_rootContext, &uLib::ObjectsContext::ObjectRemoved, [this, refresh](uLib::Object* obj) {
|
||||
// Disconnect would be good here but not strictly required if refresh handles it
|
||||
refresh();
|
||||
});
|
||||
|
||||
@@ -35,6 +43,7 @@ void ContextModel::setContext(uLib::ObjectsContext* context) {
|
||||
}
|
||||
}
|
||||
endResetModel();
|
||||
m_isReseting = false;
|
||||
}
|
||||
|
||||
QModelIndex ContextModel::index(int row, int column, const QModelIndex& parent) const {
|
||||
@@ -48,8 +57,8 @@ QModelIndex ContextModel::index(int row, int column, const QModelIndex& parent)
|
||||
}
|
||||
} else {
|
||||
uLib::Object* parentObj = static_cast<uLib::Object*>(parent.internalPointer());
|
||||
uLib::ObjectsContext* parentCtx = dynamic_cast<uLib::ObjectsContext*>(parentObj);
|
||||
if (parentCtx && row < parentCtx->GetCount()) {
|
||||
uLib::ObjectsContext* parentCtx = parentObj->GetChildren();
|
||||
if (parentCtx && row < (int)parentCtx->GetCount()) {
|
||||
return createIndex(row, column, parentCtx->GetObject(row));
|
||||
}
|
||||
}
|
||||
@@ -65,36 +74,37 @@ QModelIndex ContextModel::parent(const QModelIndex& child) const {
|
||||
|
||||
// Finding the parent of childObj is O(N) since there is no parent pointer.
|
||||
// We just do a recursive search starting from root context.
|
||||
std::function<uLib::ObjectsContext*(uLib::ObjectsContext*, uLib::Object*)> findParent =
|
||||
[&findParent](uLib::ObjectsContext* ctx, uLib::Object* target) -> uLib::ObjectsContext* {
|
||||
for (const auto& obj : ctx->GetObjects()) {
|
||||
if (obj == target) return ctx;
|
||||
if (auto subCtx = dynamic_cast<uLib::ObjectsContext*>(obj)) {
|
||||
if (auto p = findParent(subCtx, target)) return p;
|
||||
std::function<uLib::Object*(uLib::Object*, uLib::Object*)> findParent =
|
||||
[&findParent](uLib::Object* current, uLib::Object* target) -> uLib::Object* {
|
||||
uLib::ObjectsContext* ctx = current->GetChildren();
|
||||
if (ctx) {
|
||||
for (const auto& obj : ctx->GetObjects()) {
|
||||
if (obj == target) return current;
|
||||
if (auto p = findParent(obj, target)) return p;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
uLib::ObjectsContext* parentCtx = findParent(m_rootContext, childObj);
|
||||
if (!parentCtx || parentCtx == m_rootContext) {
|
||||
uLib::Object* parentObj = findParent(m_rootContext, childObj);
|
||||
if (!parentObj || parentObj == m_rootContext) {
|
||||
return QModelIndex(); // Root items have invalid parent index
|
||||
}
|
||||
|
||||
// Now need to find the row of parentCtx in its own parent Context.
|
||||
uLib::ObjectsContext* grandParentCtx = findParent(m_rootContext, parentCtx);
|
||||
if (!grandParentCtx) grandParentCtx = m_rootContext;
|
||||
// Now need to find the row of parentObj in its own parent Context.
|
||||
uLib::Object* grandParentObj = findParent(m_rootContext, parentObj);
|
||||
uLib::ObjectsContext* grandParentCtx = grandParentObj ? grandParentObj->GetChildren() : m_rootContext;
|
||||
|
||||
int row = -1;
|
||||
for (size_t i = 0; i < grandParentCtx->GetCount(); ++i) {
|
||||
if (grandParentCtx->GetObject(i) == parentCtx) {
|
||||
if (grandParentCtx->GetObject(i) == parentObj) {
|
||||
row = (int)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (row != -1) {
|
||||
return createIndex(row, 0, parentCtx);
|
||||
return createIndex(row, 0, parentObj);
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
@@ -107,8 +117,8 @@ int ContextModel::rowCount(const QModelIndex& parent) const {
|
||||
}
|
||||
|
||||
uLib::Object* parentObj = static_cast<uLib::Object*>(parent.internalPointer());
|
||||
if (auto parentCtx = dynamic_cast<uLib::ObjectsContext*>(parentObj)) {
|
||||
return parentCtx->GetCount();
|
||||
if (auto parentCtx = parentObj->GetChildren()) {
|
||||
return (int)parentCtx->GetCount();
|
||||
}
|
||||
return 0; // leaf node
|
||||
}
|
||||
@@ -161,8 +171,98 @@ QVariant ContextModel::headerData(int section, Qt::Orientation orientation, int
|
||||
}
|
||||
|
||||
Qt::ItemFlags ContextModel::flags(const QModelIndex& index) const {
|
||||
if (!index.isValid()) return Qt::NoItemFlags;
|
||||
return Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||
if (!index.isValid()) return m_rootContext ? Qt::ItemIsDropEnabled : Qt::NoItemFlags;
|
||||
|
||||
Qt::ItemFlags f = Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled;
|
||||
uLib::Object* obj = static_cast<uLib::Object*>(index.internalPointer());
|
||||
if (dynamic_cast<uLib::ObjectsContext*>(obj)) {
|
||||
f |= Qt::ItemIsDropEnabled;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
Qt::DropActions ContextModel::supportedDropActions() const {
|
||||
return Qt::MoveAction;
|
||||
}
|
||||
|
||||
QStringList ContextModel::mimeTypes() const {
|
||||
return {"application/x-ulib-object-ptr"};
|
||||
}
|
||||
|
||||
QMimeData* ContextModel::mimeData(const QModelIndexList& indexes) const {
|
||||
QMimeData* mimeData = new QMimeData();
|
||||
QByteArray encodedData;
|
||||
QDataStream stream(&encodedData, QIODevice::WriteOnly);
|
||||
for (const auto& idx : indexes) {
|
||||
if (idx.isValid() && idx.column() == 0) {
|
||||
void* ptr = idx.internalPointer();
|
||||
stream << reinterpret_cast<qlonglong>(ptr);
|
||||
}
|
||||
}
|
||||
mimeData->setData("application/x-ulib-object-ptr", encodedData);
|
||||
return mimeData;
|
||||
}
|
||||
|
||||
bool ContextModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) {
|
||||
if (action != Qt::MoveAction || !data->hasFormat("application/x-ulib-object-ptr")) return false;
|
||||
|
||||
uLib::ObjectsContext* targetCtx = m_rootContext;
|
||||
if (parent.isValid()) {
|
||||
uLib::Object* parentObj = static_cast<uLib::Object*>(parent.internalPointer());
|
||||
targetCtx = dynamic_cast<uLib::ObjectsContext*>(parentObj);
|
||||
}
|
||||
if (!targetCtx) return false;
|
||||
|
||||
QByteArray encodedData = data->data("application/x-ulib-object-ptr");
|
||||
QDataStream stream(&encodedData, QIODevice::ReadOnly);
|
||||
std::vector<uLib::Object*> objectsToMove;
|
||||
while (!stream.atEnd()) {
|
||||
qlonglong ptrVal;
|
||||
stream >> ptrVal;
|
||||
objectsToMove.push_back(reinterpret_cast<uLib::Object*>(ptrVal));
|
||||
}
|
||||
|
||||
if (objectsToMove.empty()) return false;
|
||||
|
||||
// Helper to find and remove from current parent
|
||||
std::function<void(uLib::Object*, uLib::Object*)> findAndRemoveRecursive =
|
||||
[&findAndRemoveRecursive](uLib::Object* current, uLib::Object* target) {
|
||||
if (auto ctx = current->GetChildren()) {
|
||||
ctx->RemoveObject(target);
|
||||
for (auto* obj : ctx->GetObjects()) {
|
||||
findAndRemoveRecursive(obj, target);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
m_isReseting = true;
|
||||
beginResetModel();
|
||||
for (auto* obj : objectsToMove) {
|
||||
// Don't drop onto itself or its descendants
|
||||
bool invalid = (obj == targetCtx || obj == (uLib::Object*)targetCtx);
|
||||
if (!invalid) {
|
||||
// check if targetCtx is descendant of obj
|
||||
std::function<bool(uLib::Object*, uLib::Object*)> isDescendant =
|
||||
[&isDescendant](uLib::Object* root, uLib::Object* target) -> bool {
|
||||
if (auto ctx = root->GetChildren()) {
|
||||
for (auto* child : ctx->GetObjects()) {
|
||||
if (child == target) return true;
|
||||
if (isDescendant(child, target)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
if (isDescendant(obj, (uLib::Object*)targetCtx)) invalid = true;
|
||||
}
|
||||
|
||||
if (!invalid) {
|
||||
findAndRemoveRecursive(m_rootContext, obj);
|
||||
targetCtx->AddObject(obj);
|
||||
}
|
||||
}
|
||||
endResetModel();
|
||||
m_isReseting = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ContextModel::setData(const QModelIndex& index, const QVariant& value, int role) {
|
||||
|
||||
Reference in New Issue
Block a user