Selected Rows in QTableView, copy to QClipboard

后端 未结 12 544
别那么骄傲
别那么骄傲 2020-12-25 08:14

I have a SQLite-Database and I did it into a QSqlTableModel. To show the Database, I put that Model into a QTableView.

Now I want to create

相关标签:
12条回答
  • 2020-12-25 08:33

    If anybody is interested, this web page provide a working code project on this topic, it's working pretty well. Copy / paste functionality implementation for QAbstractTableModel / QTableView

    0 讨论(0)
  • 2020-12-25 08:34

    What you'll need to do is access the text data in the model, then pass that text to the QClipboard.

    To access the text data in the model, use QModelIndex::data(). The default argument is Qt::DisplayRole, i.e. the displayed text.

    Once you've retrieved the text, pass that text to the clipboard using QClipboard::setText().

    0 讨论(0)
  • 2020-12-25 08:36

    a pyqt py2.x example:

    selection = self.table.selectionModel() #self.table = QAbstractItemView
    indexes = selection.selectedIndexes()
    
    columns = indexes[-1].column() - indexes[0].column() + 1
    rows = len(indexes) / columns
    textTable = [[""] * columns for i in xrange(rows)]
    
    for i, index in enumerate(indexes):
     textTable[i % rows][i / rows] = unicode(self.model.data(index).toString()) #self.model = QAbstractItemModel 
    
    return "\n".join(("\t".join(i) for i in textTable))
    
    0 讨论(0)
  • 2020-12-25 08:37

    I had a similar problem and ended up adapting QTableWidget (which is an extension of QTableView) to add copy/paste functionality. Here is the code which builds on what was provided by quark above:

    qtablewidgetwithcopypaste.h

    // QTableWidget with support for copy and paste added
    // Here copy and paste can copy/paste the entire grid of cells
    #ifndef QTABLEWIDGETWITHCOPYPASTE_H
    #define QTABLEWIDGETWITHCOPYPASTE_H
    
    #include <QTableWidget>
    #include <QKeyEvent>
    #include <QWidget>
    
    class QTableWidgetWithCopyPaste : public QTableWidget
    {
        Q_OBJECT
    public:
      QTableWidgetWithCopyPaste(int rows, int columns, QWidget *parent = 0) :
          QTableWidget(rows, columns, parent)
      {}
    
      QTableWidgetWithCopyPaste(QWidget *parent = 0) :
      QTableWidget(parent)
      {}
    
    private:
      void copy();
      void paste();
    
    public slots:
      void keyPressEvent(QKeyEvent * event);
    };
    
    #endif // QTABLEWIDGETWITHCOPYPASTE_H
    

    qtablewidgetwithcopypaste.cpp

    #include "qtablewidgetwithcopypaste.h"
    #include <QApplication>
    #include <QMessageBox>
    #include <QClipboard>
    #include <QMimeData>
    
    void QTableWidgetWithCopyPaste::copy()
    {
        QItemSelectionModel * selection = selectionModel();
        QModelIndexList indexes = selection->selectedIndexes();
    
        if(indexes.size() < 1)
            return;
    
        // QModelIndex::operator < sorts first by row, then by column.
        // this is what we need
    //    std::sort(indexes.begin(), indexes.end());
        qSort(indexes);
    
        // You need a pair of indexes to find the row changes
        QModelIndex previous = indexes.first();
        indexes.removeFirst();
        QString selected_text_as_html;
        QString selected_text;
        selected_text_as_html.prepend("<html><style>br{mso-data-placement:same-cell;}</style><table><tr><td>");
        QModelIndex current;
        Q_FOREACH(current, indexes)
        {
            QVariant data = model()->data(previous);
            QString text = data.toString();
            selected_text.append(text);
            text.replace("\n","<br>");
            // At this point `text` contains the text in one cell
            selected_text_as_html.append(text);
    
            // If you are at the start of the row the row number of the previous index
            // isn't the same.  Text is followed by a row separator, which is a newline.
            if (current.row() != previous.row())
            {
                selected_text_as_html.append("</td></tr><tr><td>");
                selected_text.append(QLatin1Char('\n'));
            }
            // Otherwise it's the same row, so append a column separator, which is a tab.
            else
            {
                selected_text_as_html.append("</td><td>");
                selected_text.append(QLatin1Char('\t'));
            }
            previous = current;
        }
    
        // add last element
        selected_text_as_html.append(model()->data(current).toString());
        selected_text.append(model()->data(current).toString());
        selected_text_as_html.append("</td></tr>");
        QMimeData * md = new QMimeData;
        md->setHtml(selected_text_as_html);
    //    qApp->clipboard()->setText(selected_text);
        md->setText(selected_text);
        qApp->clipboard()->setMimeData(md);
    
    //    selected_text.append(QLatin1Char('\n'));
    //    qApp->clipboard()->setText(selected_text);
    }
    
    void QTableWidgetWithCopyPaste::paste()
    {
        if(qApp->clipboard()->mimeData()->hasHtml())
        {
            // TODO, parse the html data
        }
        else
        {
            QString selected_text = qApp->clipboard()->text();
            QStringList cells = selected_text.split(QRegExp(QLatin1String("\\n|\\t")));
            while(!cells.empty() && cells.back().size() == 0)
            {
                cells.pop_back(); // strip empty trailing tokens
            }
            int rows = selected_text.count(QLatin1Char('\n'));
            int cols = cells.size() / rows;
            if(cells.size() % rows != 0)
            {
                // error, uneven number of columns, probably bad data
                QMessageBox::critical(this, tr("Error"),
                                      tr("Invalid clipboard data, unable to perform paste operation."));
                return;
            }
    
            if(cols != columnCount())
            {
                // error, clipboard does not match current number of columns
                QMessageBox::critical(this, tr("Error"),
                                      tr("Invalid clipboard data, incorrect number of columns."));
                return;
            }
    
            // don't clear the grid, we want to keep any existing headers
            setRowCount(rows);
            // setColumnCount(cols);
            int cell = 0;
            for(int row=0; row < rows; ++row)
            {
                for(int col=0; col < cols; ++col, ++cell)
                {
                    QTableWidgetItem *newItem = new QTableWidgetItem(cells[cell]);
                    setItem(row, col, newItem);
                }
            }
        }
    }
    
    void QTableWidgetWithCopyPaste::keyPressEvent(QKeyEvent * event)
    {
        if(event->matches(QKeySequence::Copy) )
        {
            copy();
        }
        else if(event->matches(QKeySequence::Paste) )
        {
            paste();
        }
        else
        {
            QTableWidget::keyPressEvent(event);
        }
    
    }
    
    0 讨论(0)
  • 2020-12-25 08:39

    I can't help but notice that you can simplify your code using a foreach() construct and the QStringList class, which has a convenient join() function.

    void Widget::copy()
    {
       QStringList list ;
       foreach ( const QModelIndex& index, tableView->selectedIndexes() )
       {
          list << index.data() ;
       }
    
       clipboard->setText( list.join( ", " ) ) ;
    }
    
    0 讨论(0)
  • 2020-12-25 08:44

    Careful with the last element. Note below, indexes may become empty after 'removeFirst()'. Thus, 'current' is never valid and should not be used in model()->data(current).

      indexes.removeFirst();
      QString selected_text;
      QModelIndex current;
      Q_FOREACH(current, indexes)
      {
      .
      .
      .
      }
      // add last element
      selected_text.append(model()->data(current).toString());
    

    Consider

      QModelIndex last = indexes.last();
      indexes.removeFirst();
      QString selected_text;
      Q_FOREACH(QModelIndex current, indexes)
      {
      .
      .
      .
      }
      // add last element
      selected_text.append(model()->data(last).toString());
    
    0 讨论(0)
提交回复
热议问题