How can I drag from e.g a QListWidget and drop in an editable QTableView?

In order to enable dragging from the QListWidget, you need to reimplement dragEnterEvent() [qt.nokia.com] and dragMoveEvent() [qt.nokia.com] to accept the event. In addition you need to set setDragEnabled() [qt.nokia.com] to true to enable dragging of the view’s items.

For the QTableView you need to set setAcceptDrops() [qt.nokia.com] to true in order to allow drops and then set a model on the view that has reimplemented setData() [qt.nokia.com] and flags() [qt.nokia.com] to allow editing of the model.

The example below illustrates how this can be implemented:

  1. #include <QtCore>
  2.  
  3. class ListWidget : public QListWidget
  4. {
  5. public:
  6.     ListWidget(QWidget *parent);
  7. protected:
  8.     void dragEnterEvent(QDragEnterEvent *e)
  9.     {
  10.         e->accept();
  11.     }
  12.  
  13.     void dragMoveEvent(QDragMoveEvent *e)
  14.     {
  15.         e->accept();
  16.     }
  17. };
  18.  
  19. ListWidget::ListWidget(QWidget *parent) : QListWidget(parent)
  20. {
  21.     addItem("Zero");
  22.     addItem("First");
  23.     addItem("Second");
  24.     addItem("Third");
  25.     addItem("Fourth");
  26.     // The tree supports dragging of its own items
  27.     setDragEnabled(true);
  28. }
  29.  
  30. class DragModel : public QAbstractTableModel
  31. {
  32. public:
  33.     DragModel(QObject *parent)
  34.     {
  35.         QStringList firstRow;
  36.         QStringList secondRow;
  37.         for (int i = 0; i < 5; i++ ) {
  38.             firstRow.insert(i,"Row " + QString::number(i+1));
  39.             secondRow.insert(i,"Row " + QString::number(i+1));
  40.         }
  41.         stringList << firstRow << secondRow;
  42.     }
  43.  
  44.     // Returns the number of rows
  45.     int rowCount (const QModelIndex &parent = QModelIndex()) const
  46.     {
  47.         return 2;
  48.     }
  49.  
  50.     // Returns the number of columns
  51.     int columnCount(const QModelIndex &parent = QModelIndex()) const
  52.     {
  53.         return 5;
  54.     }
  55.  
  56.     // Returns an appropriate value for the requested data.
  57.     // If the view requests an invalid index or if the role is not
  58.     // Qt::DisplayRole, an invalid variant is returned.
  59.     // Any valid index that corresponds to a string for the index's column and row in
  60.     // the stringlist is returned
  61.     QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const
  62.     {
  63.         if (!index.isValid())
  64.             return QVariant();
  65.         if (role != Qt::DisplayRole)
  66.             return QVariant();
  67.         QStringList list = (QStringList)stringList.at(index.row());
  68.         return list.at(index.column());
  69.     }
  70.  
  71.     // Changes an item in the string list, but only if the following conditions
  72.     // are met:
  73.     // * The index supplied is valid.
  74.     // * The index corresponds to an item to be shown in a view.
  75.     // * The role associated with rendering data is specified.
  76.     // The dataChanged() signal is emitted if the item is changed.
  77.     bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)
  78.     {
  79.         if (index.isValid() && role == Qt::EditRole) {
  80.             // Set the data in the current cell to be value
  81.             stringList[index.row()].replace(index.column(), value.toString());
  82.             // We only want to change the data for the current cell
  83.             emit dataChanged(index, index);
  84.             return true;
  85.         }
  86.         return true;
  87.     }
  88.  
  89.     // Return the default flags for this index in addition to flags
  90.     // that will accept drops and editing
  91.     Qt::ItemFlags flags(const QModelIndex & index) const
  92.     {
  93.         return QAbstractItemModel::flags(index) | Qt::ItemIsDropEnabled | Qt::ItemIsEditable;
  94.     }
  95.  
  96. private:
  97.     // Each row will consist of a list of strings
  98.     QList<QStringList> stringList;
  99. };
  100.  
  101. int main(int argc, char **argv)
  102. {
  103.     QApplication app(argc, argv);
  104.     QWidget widget;
  105.     QHBoxLayout *layout = new QHBoxLayout(&widget);
  106.     ListWidget *listWidget = new ListWidget(&widget);
  107.     QTableView *tableView = new QTableView(&widget);
  108.     DragModel *model = new DragModel(tableView);
  109.     tableView->setModel(model);
  110.     // The table view can accept drops
  111.     tableView->setAcceptDrops(true);
  112.     layout->addWidget(listWidget);
  113.     layout->addWidget(tableView);
  114.     widget.show();
  115.     return app.exec();
  116. }  

1 comment

May 8, 2014

Picture of facontidavide facontidavide

Lab Rat

The example doesn’t work out of the box,

Apparently, when DragModel::setData is called, the role is Qt:DisplayRole instead of Qt::EditRole, therefore the value in the table is never modified.

How do you think that this code should be modified, then?

Write a comment

Sorry, you must be logged in to post a comment.