QTableView: endMoveRows в модели сбрасывает размеры горизонтального заголовка - PullRequest
0 голосов
/ 01 ноября 2018

Я пытаюсь реализовать переупорядочение строк с помощью drag'n'drop в QTableView.

Операция должна фактически переупорядочить базовые данные, поэтому переупорядочивание строк вертикального заголовка не кажется хорошим решением.

Вместо этого я выбрал базовую модель для обработки этого, предоставив индексы строк в ее функции mimeData и приняв этот список в dropMimeData. В функции dropMimeData я использую beginMoveRows и endMoveRows для визуального перемещения отдельных строк в дополнение к перемещению базовых данных. Кажется, что этот подход работает, только с одним недостатком: как только я вызываю endMoveRows, горизонтальный заголовок QTableView сбрасывает все размеры его разделов по умолчанию.

Я что-то упускаю, что мне нужно сделать, или это ошибка в Qt (или даже предполагаемое поведение)? Есть ли другой способ переупорядочить drag'n'drop?

Вот упрощенный фрагмент кода, демонстрирующий то же поведение:

class Model: public QAbstractTableModel
{
public:
    Model():
        m_Items({"A", "B", "C", "D", "E"})
    {
    }

    virtual QVariant data(const QModelIndex & a_Parent, int a_Role) const override
    {
        return QString("%1 - %2").arg(m_Items[a_Parent.row()]).arg(a_Parent.column());
    }

    virtual int rowCount(const QModelIndex & a_Parent) const override
    {
        return m_Items.count();
    }

    virtual int columnCount(const QModelIndex & a_Parent) const override
    {
        return 4;
    }

    void moveNow()
    {
        // Moves the last row as the 3rd row:
        auto count = m_Items.count();
        beginMoveRows(QModelIndex(), count, count, QModelIndex(), 2);
        m_Items.insert(2, m_Items.last());
        m_Items.pop_back();
        endMoveRows();
    }

protected:
    QStringList m_Items;
};

static Model g_Model;

MainWindow::MainWindow(QWidget * parent):
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    // "ui" created by QtCreator, has a "tableView" and a "pushButton"
    ui->setupUi(this);
    ui->tableView->setModel(&g_Model);
    ui->tableView->horizontalHeader()->resizeSection(0, 200);
    ui->tableView->horizontalHeader()->resizeSection(1, 100);
    ui->tableView->horizontalHeader()->resizeSection(2, 50);
    ui->tableView->horizontalHeader()->resizeSection(3, 80);

    connect(ui->pushButton, &QPushButton::clicked,
        [this]()
        {
            // Outputs 200 on first click
            qDebug() << ui->tableView->horizontalHeader()->sectionSize(0);

            g_Model.moveNow();

            // Outputs 100
            qDebug() << ui->tableView->horizontalHeader()->sectionSize(0);
        }
    );
}

1 Ответ

0 голосов
/ 02 ноября 2018

Я обнаружил, что вызов emit layoutAboutToBeChanged() непосредственно перед операцией перемещения решает проблему:

void moveNow()
{
    emit layoutAboutToBeChanged();
    auto count = m_Items.count();
    beginMoveRows(QModelIndex(), count, count, QModelIndex(), 2);
    m_Items.insert(2, m_Items.last());
    m_Items.pop_back();
    endMoveRows();
}

Это, кажется, противоречит документации для beginMoveRows, которая указывает, что это замена для вызова этой функции. Кроме того, не должно соответствовать emit layoutChanged() после endMoveRows, в противном случае столбцы снова сбрасываются.

Все это заставляет меня поверить, что это настоящая ошибка в Qt.

...