正确复制QTableView中的选择(模型索引问题) [英] Copying a selection in a QTableView properly (model index issues)

查看:1053
本文介绍了正确复制QTableView中的选择(模型索引问题)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a QTableView that displays parsed data from a file. I open the file, parse it into different columns based on its delimiter for each line in the file, and then output it to the view. I am using a QStandardItemModel for this.

设置模型的相关代码:

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);

注意,我有它,所以我可以拖动列标题来重新排序表中的列。

Note that I have it so that I can drag the column headers around to reorder the columns in the table. This will be important later.

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

I also have the view set up so that I can select an entire row (or individual cells), hit Ctrl+C, and have the contents of the selection copy to the clipboard. I made a separate model for the selected items/rows:

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

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

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

I then have some code to handle what happens if the selection spans multiple rows. I set up a QModelIndex for this. The implementation for this is simple. I use a for loop to iterate through the indices of the selected cells. If the next index (column) is on the same row as the current one, I add that data to the variable I will eventually write to the clipboard and append a tab (\t) to it (since I want the copied cells to be delimited by tabs so I can easily copy to the clipboard and paste into Excel if I want). If the next index (column) is on a DIFFERENT row, then I append a line break (\n). Here is the code:

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);

这里是我遇到的问题。如果我重新排列我的视图中的列,索引检查断开。我的未经修改的视图如下所示:

Here's where I have a problem. If I rearrange the columns in my view, the index check breaks. My untouched view looks like this:

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

选择表中的任意值,我可以按Ctrl + C并按预期粘贴。没问题。在选择整个表格后进行复制和粘贴将产生以下输出:

If I select any of the values in the table, I can Ctrl+C and paste as expected. No problem. A copy and paste after selecting this entire table would result in this output:

A   B
W   X

但是,如果我将 Col1 拖到 Col2 是有效地将它们切换为如下所示:

However, if I drag Col1 over to where Col2 is, effectively switching them to look like this:

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

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

...and select the entire thing and paste it, I get this output:

B
X
A
W

这显然不是我想要的, ( \\\
)。

This is obviously not what I want and it seems to be adding a line break (\n) after every selected cell.

我的 qDebug()第一个未修改表格的输出是:

My qDebug() outputs for the first, unmodified table are:

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

对于第二个重新排列的表,我的 qDebug()输出是:

My qDebug() outputs for the second, rearranged table are:

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

我在这里做什么?为什么重要的是视图中的列重新排列?

What am I doing wrong here? Why would it matter that the columns in the view are rearranged?

推荐答案

以下似乎有效...

std::map<int/* row */, std::map<int/* col */, QString> > stuff;
int minCol = std::numeric_limits<int>::max();
int maxCol = std::numeric_limits<int>::min();
for (int i = 0; i < selectedIndexes.count(); ++i) {
  QModelIndex current = selectedIndexes[i];
  int col = horizontalHeader()->visualIndex(current.column());
  stuff[current.row()][col] = current.data(Qt::DisplayRole).toString();
  minCol = std::min(minCol, current.column());
  maxCol = std::max(maxCol, current.column());
}

QString displayText;
for (const auto &byRow: stuff) {
  for (int col = minCol; col <= maxCol; ++col) {
    auto i = byRow.second.find(col);
    if (i != byRow.second.end())
      displayText += i->second;
    displayText += col == maxCol ? "\n" : "\t";
  }
}

请注意如何使用...映射索引列

Note how the index columns are mapped using...

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

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

Anyway, see if that's any closer to what you need.

这篇关于正确复制QTableView中的选择(模型索引问题)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆