Перетаскивание строк QTableView не работает должным образом - PullRequest
0 голосов
/ 25 февраля 2019

Я пытаюсь переместить строки QTableView.Я строю маленький MVCE согласно этой статье .Я могу успешно перемещать строки, однако, как только я опускаю строку, происходит странный эффект, см. Ниже экран печати:

dragDrop_error

Создается новая строка5 вместо нажатия twoна Row0 и three на Row1

Таким образом, правильный результат должен быть:

Correct

вместо этого я получаю следующий неверный результат:

Incorrect

Я пытался решить эту проблему, читая этот источник , который был полезен для построения и тестирования модели.В дополнение к этому этот был полезен для понимания параметров, которые должны быть переданы QTableView, но не полностью решил проблему.Также отсюда небольшое описание процесса было полезно прочитать, но моя проблема все еще сохраняется.Наконец, я нашел этот интересный источник , который, кажется, описывает адрес Qt::ItemFlags как возможное решение, но не мог должным образом связать его с возможным решением.

См. Наиболее важную часть кода ниже:

main.cpp

#include <QApplication>
#include <QtGui>
#include <QAbstractItemModel>
#include <QTableView>
#include <QListView>
#include <QAbstractItemView>
#include "newmodel.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QStringList numbers;
    numbers << "one" << "two" << "three" << "four" << "five";
    QAbstractItemModel *model = new NewModel(numbers);
    QTableView *tableView = new QTableView;
    tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);
    tableView->dragDropOverwriteMode();
    tableView->setDragEnabled(true);
    tableView->setAcceptDrops(true);
    tableView->setDropIndicatorShown(true);
    tableView->setModel(model);
    tableView->setDefaultDropAction(Qt::MoveAction);
    tableView->show();

    QListView *listView = new QListView;
    listView->setDragEnabled(true);
    listView->setAcceptDrops(true);
    listView->setModel(model);
    listView->setDefaultDropAction(Qt::MoveAction);
    listView->show();
    return a.exec();
}

newmodel.cpp

#include "newmodel.h"
#include <QStringListModel>
#include <QDebug>

NewModel::NewModel(const QStringList &strings, QObject *parent)
    : QAbstractListModel(parent)
    , stringList(strings)
{}

int NewModel::rowCount(const QModelIndex &parent) const
{
    return stringList.count();
    Q_UNUSED(parent);
}

QVariant NewModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();
    if(index.row() >= stringList.size())
        return QVariant();
    if(role == Qt::DisplayRole || role == Qt::EditRole)
        return stringList.at(index.row());
    else
        return QVariant();
}

QVariant NewModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(role != Qt::DisplayRole)
        return QVariant();
    if(orientation == Qt::Horizontal)
        return QString("Column %1").arg(section);
    else
        return QString("Row %1").arg(section);
}

Qt::ItemFlags NewModel::flags(const QModelIndex &index) const
{
    Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index);

    if(index.isValid())
        return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
    else
        return Qt::ItemIsDropEnabled | defaultFlags;
}

bool NewModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if(index.isValid() && role == Qt::EditRole) {
        stringList.replace(index.row(), value.toString());
        emit dataChanged(index, index);
        return true;
    }
    return false;
}

bool NewModel::insertRows(int position, int rows, const QModelIndex &parent)
{
    beginInsertRows(QModelIndex(), position, position+rows-1);
    for(int row = 0; row < rows; row++) {
        stringList.insert(position, "");
    }
    endInsertRows();
    return true;
    Q_UNUSED(parent);
}

bool NewModel::removeRows(int position, int rows, const QModelIndex &parent)
{
    beginRemoveRows(QModelIndex(), position, position+rows-1);
    for(int row = 0; row < rows; ++row) {
        stringList.removeAt(position);
    }
    endRemoveRows();
    return true;
    Q_UNUSED(parent);
}

Qt::DropActions NewModel::supportedDropActions() const
{
    return Qt::CopyAction | Qt::MoveAction;
}

QStringList NewModel::mimeTypes() const
{
    QStringList types;
    types << "application/vnd.text.list";
    return types;
}

QMimeData *NewModel::mimeData(const QModelIndexList &indexes) const
{
    QMimeData *mimeData = new QMimeData();
    QByteArray encodedData;
    QDataStream stream(&encodedData, QIODevice::WriteOnly);
    foreach(const QModelIndex &index, indexes) {
        if(index.isValid()) {
            QString text = data(index, Qt::DisplayRole).toString();
            stream << text;
        }
    }
    mimeData->setData("application/vnd.text.list", encodedData);
    return mimeData;
}

bool NewModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
                                   int row, int column, const QModelIndex &parent)
{
    qDebug() << action;
    if(action == Qt::IgnoreAction)
        return true;
    if(!data->hasFormat("application/vnd.text.list"))
        return false;
    if(column > 0)
        return false;
    int beginRow;
    if(row != -1)
        beginRow = row;
    else if(parent.isValid())
        beginRow = parent.row();
    else
        beginRow = rowCount(QModelIndex());
    QByteArray encodedData = data->data("application/vnd.text.list");
    QDataStream stream(&encodedData, QIODevice::ReadOnly);
    QStringList newItems;
    int rows = 0;
    while(!stream.atEnd()) {
        QString text;
        stream >> text;
        newItems << text;
        ++rows;
    }
    insertRows(beginRow, rows, QModelIndex());
    foreach(const QString &text, newItems) {
        QModelIndex idx = index(beginRow, 0, QModelIndex());
        setData(idx, text);
        beginRow++;
    }
    return true;
}

bool NewModel::dragDropOverwtiteMode() const
{
    return false;
}

Большое спасибо за то, что указали в правильном направлении и пытаетесь пролить свет на этот вопрос

...