xybrid/xybrid/ui/patternlistmodel.cpp

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();
}