I modified the program I posted above to add slots for various model methods (dataChanged, rowsInserted, rowsRemoved):
// ListViewDragDrop.h
#ifndef LISTVIEWDRAGDROP_H
#define LISTVIEWDRAGDROP_H
#include <QtWidgets/QMainWindow>
{
Q_OBJECT
public:
ListViewDragDrop
(QWidget *parent
= 0);
~ListViewDragDrop();
protected slots:
void onModelARowsInserted
( const QModelIndex & parent,
int first,
int last
);
void onModelARowsRemoved
( const QModelIndex & parent,
int first,
int last
);
void onModelBRowsInserted
( const QModelIndex & parent,
int first,
int last
);
void onModelBRowsRemoved
( const QModelIndex & parent,
int first,
int last
);
private:
private:
};
#endif // LISTVIEWDRAGDROP_H
// ListViewDragDrop.h
#ifndef LISTVIEWDRAGDROP_H
#define LISTVIEWDRAGDROP_H
#include <QtWidgets/QMainWindow>
class QListView;
class QStringListModel;
class QModelIndex;
class ListViewDragDrop : public QMainWindow
{
Q_OBJECT
public:
ListViewDragDrop(QWidget *parent = 0);
~ListViewDragDrop();
protected slots:
void onModelADataChanged( const QModelIndex & topLeft, const QModelIndex & bottomRight );
void onModelARowsInserted( const QModelIndex & parent, int first, int last );
void onModelARowsRemoved( const QModelIndex & parent, int first, int last );
void onModelBDataChanged( const QModelIndex & topLeft, const QModelIndex & bottomRight );
void onModelBRowsInserted( const QModelIndex & parent, int first, int last );
void onModelBRowsRemoved( const QModelIndex & parent, int first, int last );
private:
void dumpStringList( const QString & where, const QString & modelName, QStringListModel * pModel );
private:
QStringListModel * mpModelA;
QStringListModel * mpModelB;
QListView * mpViewA;
QListView * mpViewB;
};
#endif // LISTVIEWDRAGDROP_H
To copy to clipboard, switch view to plain text mode
// ListViewDragDrop.cpp
#include "ListViewDragDrop.h"
#include "MoveListModel.h"
#include <QListView>
#include <QStringListModel>
#include <QSplitter>
#include <QDebug>
ListViewDragDrop
::ListViewDragDrop(QWidget *parent
){
listA << "String A1" << "String A2" << "String A3" << "String A4";
mpModelA = new MoveListModel( this );
connect( mpModelA, &QAbstractItemModel::dataChanged, this, &ListViewDragDrop::onModelADataChanged );
connect( mpModelA, &QAbstractItemModel::rowsInserted, this, &ListViewDragDrop::onModelARowsInserted );
connect( mpModelA, &QAbstractItemModel::rowsRemoved, this, &ListViewDragDrop::onModelARowsRemoved );
mpModelA->setStringList( listA );
listB << "String B1" << "String B2" << "String B3" << "String B4";
connect( mpModelB, &QAbstractItemModel::dataChanged, this, &ListViewDragDrop::onModelBDataChanged );
connect( mpModelB, &QAbstractItemModel::rowsInserted, this, &ListViewDragDrop::onModelBRowsInserted );
connect( mpModelB, &QAbstractItemModel::rowsRemoved, this, &ListViewDragDrop::onModelBRowsRemoved );
mpModelB->setStringList( listB );
mpViewA->setModel( mpModelA );
mpViewA->setDragEnabled( true );
mpViewA->setAcceptDrops( true );
mpViewB->setModel( mpModelB );
mpViewB->setDragEnabled( true );
mpViewB->setAcceptDrops( true );
pSplitter->addWidget( mpViewA );
pSplitter->addWidget( mpViewB );
setCentralWidget( pSplitter );
}
ListViewDragDrop::~ListViewDragDrop()
{
}
{
dumpStringList( "onModelADataChanged", "Model A", mpModelA );
}
void ListViewDragDrop
::onModelARowsInserted( const QModelIndex & parent,
int first,
int last
) {
dumpStringList( "onModelARowsInserted", "Model A", mpModelA );
}
void ListViewDragDrop
::onModelARowsRemoved( const QModelIndex & parent,
int first,
int last
) {
dumpStringList( "onModelARowsRemoved", "Model A", mpModelA );
}
{
dumpStringList( "onModelBDataChanged", "Model B", mpModelB );
}
void ListViewDragDrop
::onModelBRowsInserted( const QModelIndex & parent,
int first,
int last
) {
dumpStringList( "onModelBRowsInserted", "Model B", mpModelB );
}
void ListViewDragDrop
::onModelBRowsRemoved( const QModelIndex & parent,
int first,
int last
) {
dumpStringList( "onModelBRowsRemoved", "Model B", mpModelB );
}
{
if ( pModel )
qDebug() << "From " << where << " - Current string list for " << modelName << ":" << pModel->stringList();
}
// ListViewDragDrop.cpp
#include "ListViewDragDrop.h"
#include "MoveListModel.h"
#include <QListView>
#include <QStringListModel>
#include <QSplitter>
#include <QDebug>
ListViewDragDrop::ListViewDragDrop(QWidget *parent)
: QMainWindow(parent)
{
QStringList listA;
listA << "String A1" << "String A2" << "String A3" << "String A4";
mpModelA = new MoveListModel( this );
connect( mpModelA, &QAbstractItemModel::dataChanged, this, &ListViewDragDrop::onModelADataChanged );
connect( mpModelA, &QAbstractItemModel::rowsInserted, this, &ListViewDragDrop::onModelARowsInserted );
connect( mpModelA, &QAbstractItemModel::rowsRemoved, this, &ListViewDragDrop::onModelARowsRemoved );
mpModelA->setStringList( listA );
QStringList listB;
listB << "String B1" << "String B2" << "String B3" << "String B4";
mpModelB = new QStringListModel( this );
connect( mpModelB, &QAbstractItemModel::dataChanged, this, &ListViewDragDrop::onModelBDataChanged );
connect( mpModelB, &QAbstractItemModel::rowsInserted, this, &ListViewDragDrop::onModelBRowsInserted );
connect( mpModelB, &QAbstractItemModel::rowsRemoved, this, &ListViewDragDrop::onModelBRowsRemoved );
mpModelB->setStringList( listB );
QSplitter * pSplitter = new QSplitter( Qt::Horizontal );
mpViewA = new QListView();
mpViewA->setModel( mpModelA );
mpViewA->setDragEnabled( true );
mpViewA->setAcceptDrops( true );
mpViewB = new QListView();
mpViewB->setModel( mpModelB );
mpViewB->setDragEnabled( true );
mpViewB->setAcceptDrops( true );
pSplitter->addWidget( mpViewA );
pSplitter->addWidget( mpViewB );
setCentralWidget( pSplitter );
}
ListViewDragDrop::~ListViewDragDrop()
{
}
void ListViewDragDrop::onModelADataChanged( const QModelIndex & topLeft, const QModelIndex & bottomRight )
{
dumpStringList( "onModelADataChanged", "Model A", mpModelA );
}
void ListViewDragDrop::onModelARowsInserted( const QModelIndex & parent, int first, int last )
{
dumpStringList( "onModelARowsInserted", "Model A", mpModelA );
}
void ListViewDragDrop::onModelARowsRemoved( const QModelIndex & parent, int first, int last )
{
dumpStringList( "onModelARowsRemoved", "Model A", mpModelA );
}
void ListViewDragDrop::onModelBDataChanged( const QModelIndex & topLeft, const QModelIndex & bottomRight )
{
dumpStringList( "onModelBDataChanged", "Model B", mpModelB );
}
void ListViewDragDrop::onModelBRowsInserted( const QModelIndex & parent, int first, int last )
{
dumpStringList( "onModelBRowsInserted", "Model B", mpModelB );
}
void ListViewDragDrop::onModelBRowsRemoved( const QModelIndex & parent, int first, int last )
{
dumpStringList( "onModelBRowsRemoved", "Model B", mpModelB );
}
void ListViewDragDrop::dumpStringList( const QString & where, const QString & modelName, QStringListModel * pModel )
{
if ( pModel )
qDebug() << "From " << where << " - Current string list for " << modelName << ":" << pModel->stringList();
}
To copy to clipboard, switch view to plain text mode
Run this code in the debugger.
No debug output for the initial setStringList calls. But when I added slots for the modelReset() signals, I get this on startup:
From "onModelAReset" - Current string list for "Model A" : ("String A1", "String A2", "String A3", "String A4")
From "onModelBReset" - Current string list for "Model B" : ("String B1", "String B2", "String B3", "String B4")
From "onModelAReset" - Current string list for "Model A" : ("String A1", "String A2", "String A3", "String A4")
From "onModelBReset" - Current string list for "Model B" : ("String B1", "String B2", "String B3", "String B4")
To copy to clipboard, switch view to plain text mode
if I click and drag "String A4" from model A to model B (making a copy of the item from A), I see this output:
From "onModelBRowsInserted" - Current string list for "Model B" : ("String B1", "String B2", "String B3", "String B4", "")
From "onModelBDataChanged" - Current string list for "Model B" : ("String B1", "String B2", "String B3", "String B4", "String A4")
From "onModelBRowsInserted" - Current string list for "Model B" : ("String B1", "String B2", "String B3", "String B4", "")
From "onModelBDataChanged" - Current string list for "Model B" : ("String B1", "String B2", "String B3", "String B4", "String A4")
To copy to clipboard, switch view to plain text mode
Likewise, if I CLICK-DRAG "String B4" from model B to model A (again making a copy), I see this:
From "onModelARowsInserted" - Current string list for "Model A" : ("String A1", "String A2", "String A3", "String A4", "")
From "onModelADataChanged" - Current string list for "Model A" : ("String A1", "String A2", "String A3", "String A4", "String B4")
From "onModelARowsInserted" - Current string list for "Model A" : ("String A1", "String A2", "String A3", "String A4", "")
From "onModelADataChanged" - Current string list for "Model A" : ("String A1", "String A2", "String A3", "String A4", "String B4")
To copy to clipboard, switch view to plain text mode
If I SHIFT-CLICK-DRAG "String A1" from model A to model B (moving it), I see this output:
From "onModelBRowsInserted" - Current string list for "Model B" : ("String B1", "String B2", "String B3", "String B4", "String A4", "")
From "onModelBDataChanged" - Current string list for "Model B" : ("String B1", "String B2", "String B3", "String B4", "String A4", "String A1")
From "onModelARowsRemoved" - Current string list for "Model A" : ("String A2", "String A3", "String A4", "String B4")
From "onModelBRowsInserted" - Current string list for "Model B" : ("String B1", "String B2", "String B3", "String B4", "String A4", "")
From "onModelBDataChanged" - Current string list for "Model B" : ("String B1", "String B2", "String B3", "String B4", "String A4", "String A1")
From "onModelARowsRemoved" - Current string list for "Model A" : ("String A2", "String A3", "String A4", "String B4")
To copy to clipboard, switch view to plain text mode
So, it looks like the following is happening:
- rowsInserted is called when the item is dropped, and the strin list shows that there is an entry added to the model, but it is not complete
- dataChanged is called after rowsInserted, and now the model is complete
- rowsRemoved is called when an item is moved out of the source model, but dataChanged is not called for that model
This makes sense, because the dataChanged signal contains indexes for items that are presently in the model. If you remove one, it no longer has a valid index in the model.
Bookmarks