I guess no one knows about it. I've been asking the same question for 2 days, and no one answers.
I find a toDoList project about drag&drop. And I wonder Can I get the item that dragging or dropped. I'm reading the documentation for 2 days. I implement the methods.
protected:
void dragEnterEvent( QDragEnterEvent *anEvent ) override;
void dragMoveEvent( QDragMoveEvent *anEvent ) override;
void dragLeaveEvent( QDragLeaveEvent *anEvent ) override;
void dropEvent( QDropEvent *anEvent ) override;
There are 2 listviews and toolbar. I add add and remove to the toolbar.
I can drag or drop but, I can't get text of the the items dragging. This is the main code.
And I really wonder, we override the methods right. But we do not connect the methods to something. How does the method works ?
todolist::todolist(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::todolist)
{
QWidget* pWidget = new QWidget(this);
pWidget->setStyleSheet("background-color: #ECF0F1");
setCentralWidget(pWidget);
QVBoxLayout* pMainLayout = new QVBoxLayout();
pWidget->setLayout(pMainLayout);
QLabel* pwTitle = new QLabel("To Do List", this);
pMainLayout->addWidget(pwTitle);
pwTitle->setAlignment(Qt::AlignCenter);
pwTitle->setStyleSheet("font-size: 30pt; margin: 10%;");
QHBoxLayout* pHLayoutLabels = new QHBoxLayout();
pMainLayout->addLayout(pHLayoutLabels);
QLabel* plblPending = new QLabel("Pending", this);
plblPending->setStyleSheet("font-size: 15pt;");
pHLayoutLabels->addWidget(plblPending);
QLabel* plblCompleted = new QLabel("Completed", this);
plblCompleted->setStyleSheet("font-size: 15pt;");
pHLayoutLabels->addWidget(plblCompleted);
QHBoxLayout* pHLayout = new QHBoxLayout();
pMainLayout->addLayout(pHLayout);
m_pwPending = new QListView(this);
m_pwPending->setDragEnabled(true);
m_pwPending->setAcceptDrops(true);
m_pwPending->setDropIndicatorShown(true);
m_pwPending->setDefaultDropAction(Qt::MoveAction);
pHLayout->addWidget(m_pwPending);
m_pwCompleted = new QListView(this);
m_pwCompleted->setDragEnabled(true);
m_pwCompleted->setAcceptDrops(true);
m_pwCompleted->setDropIndicatorShown(true);
m_pwCompleted->setDefaultDropAction(Qt::MoveAction);
pHLayout->addWidget(m_pwCompleted);
m_pwPending->setModel(new QStringListModel());
m_pwCompleted->setModel(new QStringListModel());
m_pwPending->setStyleSheet
("QListView { font-size: 20pt; font-weight: bold; }"
"QListView::item { background-color: #E74C3C; padding: 10%;"
"border: 1px solid #C0392B; }"
"QListView::item::hover { background-color: #C0392B }");
m_pwCompleted->setStyleSheet
("QListView { font-size: 20pt; font-weight: bold; }"
"QListView::item { background-color: #2ECC71; padding: 10%;"
"border: 1px solid #27AE60; }"
"QListView::item::hover { background-color: #27AE60 }");
QToolBar* pToolBar = new QToolBar(this);
addToolBar(pToolBar);
m_pActAdd = new QAction(this);
m_pActAdd->setIcon(QIcon(":/resources/add.png"));
connect(m_pActAdd, &QAction::triggered, this, &todolist::onAdd);
m_pActRemove = new QAction(this);
m_pActRemove->setIcon(QIcon(":/resources/remove.png"));
connect(m_pActRemove, &QAction::triggered, this, &todolist::onRemove);
pToolBar->addAction(m_pActAdd);
pToolBar->addAction(m_pActRemove);
setAcceptDrops(true);
}
void todolist::onAdd()
{
m_pwPending->model()->insertRow(m_pwPending->model()->rowCount());
QModelIndex oIndex = m_pwPending->model()->index(
m_pwPending->model()->rowCount() - 1, 0);
m_pwPending->edit(oIndex);
}
void todolist::onRemove()
{
QModelIndex oIndex = m_pwPending->currentIndex();
m_pwPending->model()->removeRow(oIndex.row());
}
void todolist::dropEvent(QDropEvent* event) {
const QMimeData* mimeData = event->mimeData();
QString temp;
if(mimeData->hasText()) {
temp = mimeData->text();
}
QMessageBox::information(this,"x",temp);
}
void todolist::dragEnterEvent(QDragEnterEvent *anEvent)
{
anEvent->setAccepted(true);
}
void todolist::dragMoveEvent(QDragMoveEvent *anEvent)
{
}
void todolist::dragLeaveEvent(QDragLeaveEvent *anEvent)
{
}
todolist::~todolist()
{
delete ui;
}
QMimeData* ListModel::mimeData(const QModelIndexList& qMIndices) const {
QMimeData* const pQMimeData = new QMimeData;
QString qText;
for (const QModelIndex& qMIndex : qMIndices) {
qText += data(qMIndex, Qt::DisplayRole).toString() + "\n";
}
pQMimeData->setText(qText);
std::cout << "1" << std::endl;
draggedData = qText;
return pQMimeData;
}
draggedData = qText; this line throws an error.
I used the recommended site Qt Doc. - Model/View Programming - Using Drag and Drop with Item Views to knit a small sample application for what OP asked.
My MCVE testQListViewDragNDrop.cc
:
#include <QtWidgets>
class ListModel: public QStringListModel {
public:
using QStringListModel::QStringListModel;
protected:
// for drag site
// encodes dragged items (different from default).
virtual QMimeData* mimeData(const QModelIndexList& qMIndices) const override;
// for drop site
// returns which kind of drop actions are supported.
virtual Qt::DropActions supportedDropActions() const override
{
return Qt::MoveAction;
}
// checks whether certain dragged MIME data is droppable.
virtual bool canDropMimeData(
const QMimeData* pQMimeData, // dragged data
Qt::DropAction action, // not evaluated
int row, // not evaluated
int column, // uninteresting for lists (but relevant for tables and trees)
const QModelIndex& qMIndex) // uninteresting for lists (but relevant for trees)
const override
{
return pQMimeData->hasText();
}
// drops dragged MIME data into model.
virtual bool dropMimeData(
const QMimeData* pQMimeData, // dropped data
Qt::DropAction action, // not evaluated
int row, // where to insert
int column, // uninteresting for lists (but relevant for tables and trees)
const QModelIndex& qMIndex) // uninteresting for lists (but relevant for trees)
override;
};
QMimeData* ListModel::mimeData(const QModelIndexList& qMIndices) const
{
QMimeData* const pQMimeData = new QMimeData;
QString qText;
for (const QModelIndex& qMIndex : qMIndices) {
qText += data(qMIndex, Qt::DisplayRole).toString() + "\n";
}
pQMimeData->setText(qText);
return pQMimeData;
}
bool ListModel::dropMimeData(
const QMimeData* pQMimeData, Qt::DropAction action,
int row, int, const QModelIndex& qMIndex)
{
// get text from mime data
const QString qText = pQMimeData->text().trimmed();
if (qText.isEmpty()) return true;
// split text into lines
const QStringList qLines = qText.split(QChar('\n'));
const int n = qLines.size();
// fix row
if (qMIndex.isValid()) row = qMIndex.row(); // dropped on row
if (row < 0 || row > rowCount()) row = rowCount();
// insert list into list model
if (insertRows(row, n)) {
for (const QString& qLine : qLines) {
setData(index(row, 0), qLine);
}
}
// done
return true;
}
QStringList makeSampleData()
{
QStringList qList;
qList
<< "Read the Qt doc."
<< "Write CMakeLists.txt"
<< "Write testQListViewDragNDrop.cc"
<< "Test and Debug"
<< "Fix bugs"
<< "Test and Debug"
<< "Fix bugs"
<< "Test and Debug"
<< "Fix bugs"
<< "Test and Debug"
<< "Fix bugs"
<< "Test and Debug"
<< "Fix bugs"
<< "Write SO answer";
return qList;
}
int main(int argc, char** argv)
{
QApplication app(argc, argv);
// setup GUI
QWidget qWinMain;
qWinMain.setWindowTitle("Test QListView Drag & Drop");
qWinMain.resize(640, 480);
QGridLayout qGrid;
qGrid.addWidget(new QLabel("<b>To Do</b>"), 0, 0);
qGrid.addWidget(new QLabel("<b>Done</b>"), 0, 1);
qGrid.setRowStretch(1, 1);
QListView qListToDo; // drag site
ListModel qListModelToDo;
qListModelToDo.setStringList(makeSampleData());
qListToDo.setModel(&qListModelToDo);
qListToDo.setDragEnabled(true); // allow drag in ToDo list
qGrid.addWidget(&qListToDo, 1, 0);
QListView qListDone; // drop site
ListModel qListModelDone;
qListDone.setModel(&qListModelDone);
qListDone.viewport()->setAcceptDrops(true); // allow drops
qListDone.setDropIndicatorShown(true); // adjust drop indicator
qGrid.addWidget(&qListDone, 1, 1);
qWinMain.setLayout(&qGrid);
qWinMain.show();
// run-time loop
return app.exec();
}
Demo Session:
Notes:
QListView
can be used but Drag as well as Drop have to be configured. Thereby, a QListView
can be configured for drag and drop in contrast to my sample code.dragEnterEvent()
(or company). These events are already overridden in QListView
and consult the corresponding model for drag & drop support.QStringListModel
as well. I derived QStringListModel
to demonstrate how to customize drag & drop.mimeData()
, canDropMimeData()
, and dropMimeData()
are not necessary as well. Drag & drop will work even without them. (I tested this before I added them.) I don't know what MIME data is used to communicate the dragged contents. As drag site and drop site are the same widget class in my sample, it's not surprising that the dragged data can be dropped (however it's stored internally).