diff --git a/apps/opencs/view/world/dragdroputils.cpp b/apps/opencs/view/world/dragdroputils.cpp index 808125a60..bb4d97273 100644 --- a/apps/opencs/view/world/dragdroputils.cpp +++ b/apps/opencs/view/world/dragdroputils.cpp @@ -15,7 +15,15 @@ bool CSVWorld::DragDropUtils::canAcceptData(const QDropEvent &event, CSMWorld::C return data != nullptr && data->holdsType(type); } -CSMWorld::UniversalId CSVWorld::DragDropUtils::getAcceptedData(const QDropEvent &event, +bool CSVWorld::DragDropUtils::isInfo(const QDropEvent &event, CSMWorld::ColumnBase::Display type) +{ + const CSMWorld::TableMimeData *data = getTableMimeData(event); + return data != nullptr && ( + data->holdsType(CSMWorld::UniversalId::Type_TopicInfo) || + data->holdsType(CSMWorld::UniversalId::Type_JournalInfo) ); +} + +CSMWorld::UniversalId CSVWorld::DragDropUtils::getAcceptedData(const QDropEvent &event, CSMWorld::ColumnBase::Display type) { if (canAcceptData(event, type)) diff --git a/apps/opencs/view/world/dragdroputils.hpp b/apps/opencs/view/world/dragdroputils.hpp index d1d780708..2181e7606 100644 --- a/apps/opencs/view/world/dragdroputils.hpp +++ b/apps/opencs/view/world/dragdroputils.hpp @@ -20,6 +20,9 @@ namespace CSVWorld bool canAcceptData(const QDropEvent &event, CSMWorld::ColumnBase::Display type); ///< Checks whether the \a event contains a valid CSMWorld::TableMimeData that holds the \a type + bool isInfo(const QDropEvent &event, CSMWorld::ColumnBase::Display type); + ///< Info types can be dragged to sort the info table + CSMWorld::UniversalId getAcceptedData(const QDropEvent &event, CSMWorld::ColumnBase::Display type); ///< Gets the accepted data from the \a event using the \a type ///< \return Type_None if the \a event data doesn't holds the \a type diff --git a/apps/opencs/view/world/dragrecordtable.cpp b/apps/opencs/view/world/dragrecordtable.cpp index f84bf639d..58041af9f 100644 --- a/apps/opencs/view/world/dragrecordtable.cpp +++ b/apps/opencs/view/world/dragrecordtable.cpp @@ -46,7 +46,8 @@ void CSVWorld::DragRecordTable::dragEnterEvent(QDragEnterEvent *event) void CSVWorld::DragRecordTable::dragMoveEvent(QDragMoveEvent *event) { QModelIndex index = indexAt(event->pos()); - if (CSVWorld::DragDropUtils::canAcceptData(*event, getIndexDisplayType(index))) + if (CSVWorld::DragDropUtils::canAcceptData(*event, getIndexDisplayType(index)) || + CSVWorld::DragDropUtils::isInfo(*event, getIndexDisplayType(index)) ) { if (index.flags() & Qt::ItemIsEditable) { @@ -75,6 +76,10 @@ void CSVWorld::DragRecordTable::dropEvent(QDropEvent *event) } } } + else if (CSVWorld::DragDropUtils::isInfo(*event, display) && event->source() == this) + { + emit moveRecordsFromSameTable(event); + } } CSMWorld::ColumnBase::Display CSVWorld::DragRecordTable::getIndexDisplayType(const QModelIndex &index) const diff --git a/apps/opencs/view/world/dragrecordtable.hpp b/apps/opencs/view/world/dragrecordtable.hpp index a6b6756aa..f6c3fa890 100644 --- a/apps/opencs/view/world/dragrecordtable.hpp +++ b/apps/opencs/view/world/dragrecordtable.hpp @@ -23,6 +23,8 @@ namespace CSVWorld { class DragRecordTable : public QTableView { + Q_OBJECT + protected: CSMDoc::Document& mDocument; bool mEditLock; @@ -45,6 +47,9 @@ namespace CSVWorld private: CSMWorld::ColumnBase::Display getIndexDisplayType(const QModelIndex &index) const; + + signals: + void moveRecordsFromSameTable(QDropEvent *event); }; } diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index e5f4e36c5..03d7dbbfa 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -248,6 +249,7 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, if (isInfoTable) { mProxyModel = new CSMWorld::InfoTableProxyModel(id.getType(), this); + connect (this, &CSVWorld::DragRecordTable::moveRecordsFromSameTable, this, &CSVWorld::Table::moveRecords); } else if (isLtexTable) { @@ -563,6 +565,74 @@ void CSVWorld::Table::moveDownRecord() } } +void CSVWorld::Table::moveRecords(QDropEvent *event) +{ + if (mEditLock || (mModel->getFeatures() & CSMWorld::IdTableBase::Feature_Constant)) + return; + + QModelIndex targedIndex = indexAt(event->pos()); + + QModelIndexList selectedRows = selectionModel()->selectedRows(); + int targetRow = targedIndex.row(); + int baseRow = targedIndex.row() - 1; + int highestDifference = 0; + + for (const auto& thisRowData : selectedRows) + { + if (std::abs(targetRow - thisRowData.row()) > highestDifference) highestDifference = std::abs(targetRow - thisRowData.row()); + if (thisRowData.row() - 1 < baseRow) baseRow = thisRowData.row() - 1; + } + + std::vector newOrder (highestDifference + 1); + + for (long unsigned int i = 0; i < newOrder.size(); ++i) + { + newOrder[i] = i; + } + + if (selectedRows.size() > 1) + { + Log(Debug::Warning) << "Move operation failed: Moving multiple selections isn't implemented."; + return; + } + + for (const auto& thisRowData : selectedRows) + { + /* + Moving algorithm description + a) Remove the (ORIGIN + 1)th list member. + b) Add (ORIGIN+1)th list member with value TARGET + c) If ORIGIN > TARGET,d_INC; ELSE d_DEC + d_INC) increase all members after (and including) the TARGET by one, stop before hitting ORIGINth address + d_DEC) decrease all members after the ORIGIN by one, stop after hitting address TARGET + */ + + int originRow = thisRowData.row(); + //int sourceMappedOriginRow = mProxyModel->mapToSource (mProxyModel->index (originRow, 0)).row(); + + newOrder.erase(newOrder.begin() + originRow - baseRow - 1); + newOrder.emplace(newOrder.begin() + originRow - baseRow - 1, targetRow - baseRow - 1); + + if (originRow > targetRow) + { + for (int i = targetRow - baseRow - 1; i < originRow - baseRow - 1; ++i) + { + ++newOrder[i]; + } + } + else + { + for (int i = originRow - baseRow; i <= targetRow - baseRow - 1; ++i) + { + --newOrder[i]; + } + } + + } + mDocument.getUndoStack().push (new CSMWorld::ReorderRowsCommand ( + dynamic_cast (*mModel), baseRow + 1, newOrder)); +} + void CSVWorld::Table::editCell() { emit editRequest(mEditIdAction->getCurrentId(), ""); diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 61dd57c06..9c4b9b5e5 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -141,6 +141,8 @@ namespace CSVWorld void moveDownRecord(); + void moveRecords(QDropEvent *event); + void viewRecord(); void previewRecord();