正确复制QTableView中的选择(模型索引问题)

时间:2016-06-14 02:34:47

标签: c++ qt

我有QTableView显示文件中已解析的数据。我打开文件,根据文件中每一行的分隔符将其解析到不同的列,然后将其输出到视图。我正在使用QStandardItemModel

设置模型的相关代码:

QStandardItemModel* model = new QStandardItemModel(this);

int lineIndex = 0;
QStringList headers;
headers << "Col1" << "Col2";
model->setHorizontalHeaderLabels(headers);
file.seek(0);
QTextStream inData(&file);
while (!inData.atEnd()){
  QString line = inData.readLine();
  QStringList lineToken = line.split(":"/*, QString::SkipEmptyParts*/);
  for (int j = 0; j < lineToken.size(); j++) {
    QString value = lineToken.at(j);
    QStandardItem* item = new QStandardItem(value);
    model->setItem(lineIndex, j, item);
  }
lineIndex++;

}
ui->tableView->setModel(model);
ui->tableView->horizontalHeader()->setSectionsMovable(true);

请注意,我有它,以便我可以拖动列标题来重新排序表中的列。这在以后很重要。

我也设置了视图,以便我可以选择整行(或单个单元格),按Ctrl + C,然后将选择副本的内容复制到剪贴板。我为所选项目/行创建了一个单独的模型:

QApplication::clipboard()->clear();
QItemSelectionModel* selection = ui->tableView->selectionModel();
QModelIndexList indexes = selection->selectedIndexes();

QString clipboardString;
QModelIndexList selectedIndexes = ui->tableView->selectionModel()->selectedIndexes();

然后我有一些代码来处理选择跨越多行时会发生什么。我为此设置了QModelIndex。这个实现很简单。我使用for循环遍历所选单元格的索引。如果下一个索引(列)与当前索引位于同一行,我将该数据添加到变量中,我将最终写入剪贴板并向其附加一个选项卡(\t)(因为我想要复制)要通过制表符分隔的单元格,以便我可以轻松复制到剪贴板并粘贴到Excel中(如果需要)。如果下一个索引(列)位于不同的行上,那么我附加一个换行符(\n)。这是代码:

for (int i = 0; i < selectedIndexes.count(); ++i)
{
  QModelIndex current = selectedIndexes[i];
  QString displayText = current.data(Qt::DisplayRole).toString();
  // If there exists another column beyond this one.
  if (i + 1 < selectedIndexes.count()) {
    QModelIndex next = selectedIndexes[i+1];
    // If the column is on different row, the clipboard should take note.
    qDebug() << "next.row()" << next.row();
    qDebug() << "current.row()" << current.row();
    if (next.row() != current.row()){
      displayText.append("\n");
    } else {
      // Otherwise append a column separator.
      displayText.append("\t");
    }
  }
    clipboardString.append(displayText);
}
QApplication::clipboard()->setText(clipboardString);

这是我遇到问题的地方。如果我在视图中重新排列列,则索引检查会中断。我未触动过的视图看起来像这样:

+------+------+
| Col1 | Col2 |
+------+------+
| A    | B    |
| W    | X    |
+------+------+

如果我选择表格中的任何值,我可以按Ctrl + C并按预期粘贴。没问题。选择此整个表后复制和粘贴将导致此输出:

A   B
W   X

但是,如果我将Col1拖到Col2所在的位置,请将它们切换为如下所示:

+------+------+
| Col2 | Col1 |
+------+------+
| B    | A    |
| X    | W    |
+------+------+

...然后选择整个并粘贴它,我得到这个输出:

B
X
A
W

这显然不是我想要的,似乎是在每个选定的单元格之后添加换行符(\n)。

第一个未经修改的表的qDebug()输出为:

next.row() 0
current.row() 0
next.row() 1
current.row() 0
next.row() 1
current.row() 1

第二个重新排列的表的qDebug()输出为:

next.row() 1
current.row() 0
next.row() 0
current.row() 1
next.row() 1
current.row() 0

我在这里做错了什么?为什么重新排列视图中的列会有什么影响?

2 个答案:

答案 0 :(得分:2)

以下似乎有用......

int col = horizontalHeader()->visualIndex(current.column());

注意索引列是如何使用...

映射的
phpQuyer.php

无论如何,看看它是否更接近你需要的东西。

答案 1 :(得分:0)

出于您的目的,最好使用选择范围

// If your selection is continuous, there should be just one range.
QItemSelectionRange range = selection->selection().front();

int row, col;
for (int i = 0; i < range.height(); i++)
{
    QStringList rowStrList;
    for (int j = 0; j < range.width(); j++)
    {
        row = range.top() + i;
        col = range.left() + j;
        rowStrList << model->index(row, col).data(Qt::DisplayRole).toString();
    }

    clipboardString += rowStrList.join("\t");
    clipboardString += "\n";
}

基本思想是逐行处理选择。

QItemSelectionModel::selection()重新设定QItemSelection,这是选择范围的列表。 选择范围是一组连续的选定索引。