108 lines
4.1 KiB
C++
108 lines
4.1 KiB
C++
#include "patternlistmodel.h"
|
|
using Xybrid::UI::PatternListModel;
|
|
|
|
using Xybrid::Data::Project;
|
|
using Xybrid::Data::Pattern;
|
|
|
|
#include "editing/projectcommands.h"
|
|
#include "editing/patterncommands.h"
|
|
using namespace Xybrid::Editing;
|
|
|
|
#include <QDebug>
|
|
#include <QMimeData>
|
|
#include <QIODevice>
|
|
|
|
#include "mainwindow.h"
|
|
|
|
PatternListModel::PatternListModel(QObject *parent, MainWindow* window) : QAbstractListModel (parent) {
|
|
this->window = window;
|
|
}
|
|
|
|
int PatternListModel::rowCount(const QModelIndex &parent [[maybe_unused]]) const {
|
|
auto* project = window->getProject().get();
|
|
if (!project) return 0;
|
|
return static_cast<int>(project->patterns.size());
|
|
}
|
|
|
|
int PatternListModel::columnCount(const QModelIndex &parent [[maybe_unused]]) const {
|
|
return 1;
|
|
}
|
|
|
|
QVariant PatternListModel::data(const QModelIndex &index, int role) const {
|
|
auto* project = window->getProject().get();
|
|
if (!project) return QVariant();
|
|
if (role == Qt::DisplayRole) {
|
|
auto pattern = project->patterns[static_cast<size_t>(index.row())];
|
|
return QString("%1: %2").arg(pattern->index, 1, 10, QChar('0')).arg(pattern->name.isEmpty() ? "(unnamed)" : pattern->name);
|
|
}
|
|
if (role == Qt::EditRole) {
|
|
return project->patterns[static_cast<size_t>(index.row())]->name;
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
bool PatternListModel::setData(const QModelIndex &index, const QVariant &value, int role) {
|
|
if (role == Qt::EditRole) {
|
|
auto* project = window->getProject().get();
|
|
if (!project) return true;
|
|
auto pattern = project->patterns[static_cast<size_t>(index.row())];
|
|
//pattern->name = value.toString().toStdString();
|
|
return (new PatternRenameCommand(pattern, value.toString()))->commit();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
Qt::ItemFlags PatternListModel::flags(const QModelIndex &index) const {
|
|
return Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | QAbstractListModel::flags(index);
|
|
}
|
|
|
|
Qt::DropActions PatternListModel::supportedDropActions() const {
|
|
return Qt::CopyAction | Qt::MoveAction;
|
|
}
|
|
|
|
QStringList PatternListModel::mimeTypes() const {
|
|
QStringList types;
|
|
types << "xybrid-internal/x-pattern-index";
|
|
return types;
|
|
}
|
|
|
|
QMimeData *PatternListModel::mimeData(const QModelIndexList &indexes) const {
|
|
auto d = new QMimeData();
|
|
QByteArray dd;
|
|
QDataStream stream(&dd, QIODevice::WriteOnly);
|
|
size_t idx = static_cast<size_t>(indexes[0].row());
|
|
Project* prj = window->getProject().get();
|
|
if (!prj) return d; // if somehow nullptr, just return a blank
|
|
stream.writeRawData(reinterpret_cast<char*>(&idx), sizeof(size_t));
|
|
stream.writeRawData(reinterpret_cast<char*>(&prj), sizeof(void*));
|
|
d->setData("xybrid-internal/x-pattern-index", dd);
|
|
return d;
|
|
}
|
|
|
|
bool PatternListModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column [[maybe_unused]], const QModelIndex &parent [[maybe_unused]]) {
|
|
if (!data->hasFormat("xybrid-internal/x-pattern-index")) return false;
|
|
if (action == Qt::IgnoreAction) return true; // can accept type
|
|
|
|
std::shared_ptr<Pattern> p;
|
|
{
|
|
QByteArray dd = data->data("xybrid-internal/x-pattern-index");
|
|
QDataStream stream(&dd, QIODevice::ReadOnly);
|
|
size_t idx;
|
|
Project* prj;
|
|
stream.readRawData(reinterpret_cast<char*>(&idx), sizeof(size_t));
|
|
stream.readRawData(reinterpret_cast<char*>(&prj), sizeof(void*));
|
|
if (prj != window->getProject().get()) return false; // wrong or invalid project
|
|
if (idx >= prj->patterns.size()) return false; // index out of range
|
|
p = prj->patterns[idx];
|
|
}
|
|
|
|
if (parent.isValid()) { // if dropped onto an item and not between, place on opposite side
|
|
row = parent.row();
|
|
if (row > static_cast<int>(p->index)) row += 1;
|
|
}
|
|
if (row < 0) row = static_cast<int>(p->project->patterns.size()); // if dropped on empty space, snap to end
|
|
if (row > static_cast<int>(p->index)) row -= 1; // compensate ahead of time for snap-out
|
|
|
|
return (new ProjectPatternMoveCommand(window->getProject(), static_cast<int>(p->index), row))->commit();
|
|
}
|