diff --git a/src/common/SignalVectorModel.hpp b/src/common/SignalVectorModel.hpp index adea78843..bacb6c4df 100644 --- a/src/common/SignalVectorModel.hpp +++ b/src/common/SignalVectorModel.hpp @@ -205,7 +205,9 @@ public: assert(row >= 0 && row < this->rows_.size() && column >= 0 && column < this->columnCount_); - return this->rows_[row].items[column]->flags(); + return this->rows_[row].items[column]->flags() | + Qt::ItemFlag::ItemIsDragEnabled | + Qt::ItemFlag::ItemIsDropEnabled; } QStandardItem *getItem(int row, int column) @@ -239,6 +241,66 @@ public: return true; } + QStringList mimeTypes() const override + { + return {"chatterino_row_id"}; + } + + QMimeData *mimeData(const QModelIndexList &list) const + { + if (list.length() == 1) + { + return nullptr; + } + + // Check if all indices are in the same row -> single row selected + for (auto &&x : list) + { + if (x.row() != list.first().row()) + return nullptr; + } + + auto data = new QMimeData; + data->setData("chatterino_row_id", QByteArray::number(list[0].row())); + return data; + } + + bool dropMimeData(const QMimeData *data, Qt::DropAction action, int /*row*/, + int /*column*/, const QModelIndex &parent) override + { + if (data->hasFormat("chatterino_row_id") && + action & (Qt::DropAction::MoveAction | Qt::DropAction::CopyAction)) + { + int from = data->data("chatterino_row_id").toInt(); + int to = parent.row(); + + if (from < 0 || from > this->vector_->getVector().size() || + to < 0 || to > this->vector_->getVector().size()) + { + return false; + } + + if (from != to) + { + auto item = this->vector_->getVector()[from]; + this->vector_->removeItem(from); + this->vector_->insertItem(item, to); + } + + // We return false since we remove items ourselves. + return false; + } + + return false; + } + + Qt::DropActions supportedDropActions() const override + { + return this->vector_->isSorted() + ? Qt::DropActions() + : Qt::DropAction::CopyAction | Qt::DropAction::MoveAction; + } + protected: virtual void afterInit() { diff --git a/src/widgets/helper/EditableModelView.cpp b/src/widgets/helper/EditableModelView.cpp index ff6f92143..62f1e4dcc 100644 --- a/src/widgets/helper/EditableModelView.cpp +++ b/src/widgets/helper/EditableModelView.cpp @@ -15,9 +15,12 @@ EditableModelView::EditableModelView(QAbstractTableModel *model) { this->model_->setParent(this); this->tableView_->setModel(model); - this->tableView_->setSelectionMode(QAbstractItemView::ExtendedSelection); + this->tableView_->setSelectionMode(QAbstractItemView::SingleSelection); this->tableView_->setSelectionBehavior(QAbstractItemView::SelectRows); - this->tableView_->verticalHeader()->hide(); + this->tableView_->setDragDropMode(QTableView::DragDropMode::InternalMove); + this->tableView_->setDragDropOverwriteMode(false); + this->tableView_->setDefaultDropAction(Qt::DropAction::MoveAction); + this->tableView_->verticalHeader()->setVisible(false); // create layout QVBoxLayout *vbox = new QVBoxLayout(this); @@ -38,12 +41,17 @@ EditableModelView::EditableModelView(QAbstractTableModel *model) QPushButton *remove = new QPushButton("Remove"); buttons->addWidget(remove); QObject::connect(remove, &QPushButton::clicked, [this] { - QModelIndexList list; - while ((list = this->getTableView()->selectionModel()->selectedRows(0)) - .length() > 0) - { - model_->removeRow(list[0].row()); - } + auto selected = this->getTableView()->selectionModel()->selectedRows(0); + + // Remove rows backwards so indices don't shift. + std::vector rows; + for (auto &&index : selected) + rows.push_back(index.row()); + + std::sort(rows.begin(), rows.end(), std::greater{}); + + for (auto &&row : rows) + model_->removeRow(row); }); buttons->addStretch();