PDA

View Full Version : QTableView Drag and Drop



alenyashka
19th November 2010, 05:09
Hi all,

I try to make DnD in QTableView. I made a sub-class of QAbstractTableModel.



#include "dragdroptableview.h"

DragDropTableView::DragDropTableView(QObject *parent) :
QAbstractTableModel(parent)
{
}

DragDropTableView::DragDropTableView(QList< QPair<QString, QString> > pairs, QObject *parent):
QAbstractTableModel(parent)
{
listOfPairs = pairs;
}

int DragDropTableView::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return listOfPairs.size();
}

int DragDropTableView::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return 2;
}

QVariant DragDropTableView::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();

if (index.row() >= listOfPairs.size() || index.row() < 0)
return QVariant();

if (role == Qt::DisplayRole) {
QPair<QString, QString> pair = listOfPairs.at(index.row());

if (index.column() == 0)
return pair.first;
else if (index.column() == 1)
return pair.second;
}
return QVariant();
}

QVariant DragDropTableView::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();

if (orientation == Qt::Horizontal) {
switch (section) {
case 0:
return tr("Name");

case 1:
return tr("Address");

default:
return QVariant();
}
}
return QVariant();
}

bool DragDropTableView::insertRows(int position, int rows, const QModelIndex &index)
{
Q_UNUSED(index);
beginInsertRows(QModelIndex(), position, position+rows-1);

for (int row=0; row < rows; row++) {
QPair<QString, QString> pair(" ", " ");
listOfPairs.insert(position, pair);
}

endInsertRows();
return true;
}

bool DragDropTableView::removeRows(int position, int rows, const QModelIndex &index)
{
Q_UNUSED(index);
beginRemoveRows(QModelIndex(), position, position+rows-1);

for (int row=0; row < rows; ++row) {
listOfPairs.removeAt(position);
}

endRemoveRows();
return true;
}

Qt::ItemFlags DragDropTableView::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::ItemIsEnabled;

return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
}

QStringList DragDropTableView::mimeTypes() const
{
QStringList types;
types << "application/vnd.text.list";
return types;
}

QMimeData* DragDropTableView::mimeData(const QModelIndexList &indexes) const
{
QMimeData *mimeData = new QMimeData();
QByteArray encodedData;
QDataStream stream(&encodedData, QIODevice::WriteOnly);
QModelIndex index;
foreach (index, indexes)
{
if (index.isValid())
{
QString text;
text = data(index, Qt::DisplayRole).toString();
stream << text;
}
}
mimeData->setData("application/vnd.text.list", encodedData);
return mimeData;
}

Qt::DropAction DragDropTableView::supportedDropActions()
{
return Qt::MoveAction;
}

bool DragDropTableView::dropMimeData(const QMimeData *data,
Qt::DropAction action,
int row, int column,
const QModelIndex &parent)
{
Q_UNUSED(column)
if (!data->hasFormat("application/vnd.text.list"))
{
return false;
}
if (action == Qt::IgnoreAction)
{
return true;
}
int endRow = 0;
if (!parent.isValid() && row < 0)
{
endRow = listOfPairs.count();
}
else if (!parent.isValid())
{
endRow = qMin(row, listOfPairs.count());
}
else
{
endRow = parent.row();
}

QByteArray encodedData = data->data("application/vnd.text.list");
QDataStream stream(&encodedData, QIODevice::ReadOnly);

while (!stream.atEnd())
{
QString first, second;
stream >> first >> second;
QPair <QString, QString> pair(first, second);
beginInsertRows(QModelIndex(), endRow, endRow);
listOfPairs.insert(endRow, pair);
endInsertRows();
endRow ++;
}
return true;
}


When I DnD some item from first table to second the item is copied into second table, but not removed from first table.

Any ideas?

diginikkari
22nd October 2012, 11:30
Did you ever get this solved? I'm struggling with the same problem.

ChiliPalmer
23rd October 2012, 15:06
Did you set the Views defaultDropAction to Qt::MoveAction via setDefaultDropAction (http://qt-project.org/doc/qt-4.8/qabstractitemview.html#defaultDropAction-prop)? If that doesn't work either you might try to create a custom view and reimplement mouseMoveEvent (http://qt-project.org/doc/qt-4.8/qtreeview.html#mouseMoveEvent) to start a drag yourself and delete the row after QDrag::exec (http://qt-project.org/doc/qt-4.8/qdrag.html#exec)