0

Currently, I have a QTableView with an associated model (inheriting QAbstractTableModel). Through QTableView::customContextMenuRequested, I can copy the table like this :

void MyForm::onCopyClicked()
{
    QItemSelectionModel *lpSelection = m_pUI->DATA_TABLE_VIEW->selectionModel();
    QModelIndexList lIndices = lpSelection->selectedIndexes();

    if(lIndices.isEmpty())
        return;

    QMap<int, bool> selectedColumnsMap;
    foreach (QModelIndex current, lIndices) {
        selectedColumnsMap[current.column()] = true;
    }
    QList<int> selectedColumns = selectedColumnsMap.uniqueKeys();
    int minCol = selectedColumns.first();

    // prepend headers for selected columnss
    QString selectedText;

    foreach (int column, selectedColumns) {
        selectedText += m_pUI->DATA_TABLE_VIEW->model()->headerData(column, Qt::Horizontal, Qt::DisplayRole).toString();
        if (column != selectedColumns.last())
            selectedText += QLatin1Char('\t');
    }
    selectedText += QLatin1Char('\n');

    // QModelIndex::operator < sorts first by row, then by column.
    // this is what we need
    std::sort(lIndices.begin(), lIndices.end());

    int lastRow = lIndices.first().row();
    int lastColumn = minCol;

    foreach (QModelIndex current, lIndices) {

        if (current.row() != lastRow) {
            selectedText += QLatin1Char('\n');
            lastColumn = minCol;
            lastRow = current.row();
        }

        if (current.column() != lastColumn) {
            for (int i = 0; i < current.column() - lastColumn; ++i)
                selectedText += QLatin1Char('\t');
            lastColumn = current.column();
        }
        const double lValue = m_pUI->DATA_LIST_VIEW->model()->data(current).toDouble();
        selectedText += QString::number(lValue);
    }

    selectedText += QLatin1Char('\n');

    QApplication::clipboard()->setText(selectedText);
}

The need is to be able to copy the selection to another application like Excel through the clipboard. This code works well in most cases.

But if I have a big table with something like 5 million cells, this code crash, the string becoming too big. I'd like to be able to copy lots of cells like it's possible on excel.

So I wonder what is the good way of doing this ?

Best would be with Qt, but it doesn't look possible, so maybe with another lib or even windows API ...

bobombe
  • 53
  • 1
  • 5
  • I ran into this same QString limitation in an application I wrote to dump a sqlite database into text INSERT statements. I ended up splitting the string at a point although I don't think this is the solution for you. – drescherjm Jan 16 '21 at 16:10
  • Indeed, it's not a solution for me, I need a solution where all the data are accessible from the clipboard in other applications like Excel. – bobombe Jan 16 '21 at 16:15
  • I believe this is the limitation we both are seeing: [https://forum.qt.io/topic/10302/what-is-the-maximum-length-of-string-that-qstring-object-can-hold](https://forum.qt.io/topic/10302/what-is-the-maximum-length-of-string-that-qstring-object-can-hold) – drescherjm Jan 16 '21 at 16:16
  • I think you need to look for a different c++ library for the clipboard or perhaps an OS API if your code is windows only. Related: [https://stackoverflow.com/questions/6436257/how-do-you-copy-paste-from-the-clipboard-in-c](https://stackoverflow.com/questions/6436257/how-do-you-copy-paste-from-the-clipboard-in-c) – drescherjm Jan 16 '21 at 16:24
  • Yes, that what I said in my last sentence, but I'm lost in all these information, and I was hoping for some input from this community :) – bobombe Jan 16 '21 at 16:27
  • https://github.com/Arian8j2/ClipboardXX seems promising to me. I think you can take your code here and append to a std::string as `selectedText` instead of a QString then use that as input to the library. – drescherjm Jan 16 '21 at 16:28
  • Looking at that library it's no good if you need linux because it uses Qt for linux support.. However it does implement the windows API code. [https://github.com/Arian8j2/ClipboardXX/blob/master/include/ClipboardXX.hpp](https://github.com/Arian8j2/ClipboardXX/blob/master/include/ClipboardXX.hpp) – drescherjm Jan 16 '21 at 16:35
  • I only need for Windows, but this API is not what I need as it can only copy one string at a time, like QClipboard. But it's a nice easy example of how to use Windows API for copy/past... – bobombe Jan 16 '21 at 16:40
  • You only need to copy 1 string at a time. Make `selectedText` a std::string and use it the same way as you use `QApplication::clipboard()->setText(selectedText);` `std::string` does not have the 2GB limitation that `QString` has assuming your code is 64 bit. – drescherjm Jan 16 '21 at 16:42
  • Unfortunately, my app is 32 bit ... – bobombe Jan 16 '21 at 16:50
  • I didn't consider that since I have done pretty much only 64 bit applications for over a decade now.. I can't help with that at all. – drescherjm Jan 16 '21 at 16:51
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/227416/discussion-between-bobombe-and-drescherjm). – bobombe Jan 16 '21 at 16:58
  • When you 've only a 32bit OS then you can't create a container with more than 2GB. You don't even have the process memory for it. – chehrlic Jan 17 '21 at 10:25
  • I get that it is the limitation here, but I was wondering if it's possible to find a workaround. Is it not possible to set the data clipboard parts by parts, like first setting 1000000 characters, then another 1000000 characters and so on until I finished setting all the characters I want ? – bobombe Jan 18 '21 at 12:42

0 Answers0