Michael Vincent
Michael Vincent

Reputation: 1660

Dragging from an inherited QTableView

I have in my app a table view called "partsview" which is descended from a QTableView, this is on the main form. The relevant header code looks like:

class partsiew : public QTableView
{
    Q_OBJECT
public:
    explicit partsview(QWidget *parent = 0);
public:
    QStringList mimeTypes() const;
    QMimeData *mimeData(const QModelIndexList &indexes) const;
};

I have also added the following into the constructor of "partsview":

this->setSelectionMode(QAbstractItemView::ExtendedSelection);
this->setDragEnabled(true);
this->setAcceptDrops(true);
this->setDropIndicatorShown(true);

though the last two are probably not needed.

When dragging, I can pick up a row and drag it to a target - a QTreeView - and I get the appropriate cursor and even a dropMimeData event is fired on the treeview.

However, the row and column values in the dropMimeData() method are always -1 and the two methods in the "partsview" are not called.

I'm guessing that the first error may have something to do with the second. Have I declared the mimeType() and mimeData() methods correctly for them to be called during a drag operation.

I have been following this page in the documentation QT4.6 - Using Model/View Classes

Upvotes: 0

Views: 1389

Answers (1)

phyatt
phyatt

Reputation: 19102

Here is the link for the most recent documentation on it:

http://doc.qt.io/qt-5/model-view-programming.html#using-drag-and-drop-with-item-views

I recently worked on some code for doing an internal move of cells on a single table, but while I was researching it, I found some other useful links.

http://qt-project.org/forums/viewthread/14197

I used the code in the above link and translated it to use QTableView instead of QTableWidget:

void MyTableView::dropEvent(QDropEvent *event)
{
    // TODO: switch to using EyeTrackerModel::dropMimeData instead
    QPoint old_coordinates = QPoint(-1,-1);
    int dropAction = event->dropAction();
    if(currentIndex().isValid()) //Check if user is not accessing empty cell
    {
        old_coordinates = QPoint( currentIndex().row(), currentIndex().column() );
    }

    QTableView::dropEvent(event);
    qDebug() << "Detected drop event...";
    event->acceptProposedAction();
    if( this->indexAt(event->pos()).isValid() && old_coordinates != QPoint(-1, -1))
    {
        qDebug() << "Drop Event Accepted.";
        qDebug() << "Source: " << old_coordinates.x() << old_coordinates.y()
                 << "Destination: " << this->indexAt(event->pos()).row()
                 << this->indexAt(event->pos()).column()
                 << "Type: " << dropAction;

        emit itemDropped( old_coordinates.x(), old_coordinates.y(),
                          this->indexAt(event->pos()).row(),
                          this->indexAt(event->pos()).column(),
                          dropAction);
    }
    // resize rows and columns right after a move!
    this->doAdjustSize();
}

Even though the following answer is for Python, it still helped me when checking for what I could be missing.

QT: internal drag and drop of rows in QTableView, that changes order of rows in QTableModel

Here are some code snippets from my recent project related to drag and drop. I think you have most of them already, but I included them below for completeness.

QAbstractTableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)

Qt::ItemFlags QAbstractTableModel::flags(const QModelIndex &index) const
{
    Q_UNUSED(index)
//    if(index.isValid())
        return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
//    else
//        return Qt::ItemIsDropEnabled | Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}

QAbstractTableView(QWidget *parent) :
    QTableView(parent)
{
    setAcceptDrops(true);
    setDefaultDropAction(Qt::MoveAction);
}

Hope that helps.

Upvotes: 2

Related Questions