Bonjour,
J'essaye en vain d'implémenter la réorganisation des éléments d'une QListView par glisser déposer. Mais il semble que quelque chose m'échappe. En effet lorsque je veux déplacer un éléments dans la liste en le glissant dans ma liste, j'obtiens toujours un icône d'interdiction qui s'affiche (voir image plus bas).
Pour le modèle de la liste, j'ai crée une classe "DeviceListModel" qui dérive de QAbstractListModel et j'ai réimplémenté les fonctions nécessaires (certaines renvoi simplement true et ne font rien, je n'ai pas pris le temps de les implémenter et ce n'est pas nécessaire car elle ne sont jamais appelées dans ce cas précis).
Pourtant d'après la doc ainsi que les dizaines de forums que j'ai consulté, je pense avoir tout configuré correctement.
Voici mon code :
MainWindow.cpp:
DeviceListModel.h:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); ui->listView->setSelectionMode(QAbstractItemView::SingleSelection); ui->listView->setMovement(QListView::Free); ui->listView->setDragEnabled(true); ui->listView->viewport()->setAcceptDrops(true); ui->listView->setDropIndicatorShown(true); //on accepte que les déplacements en interne ui->listView->setDragDropMode(QAbstractItemView::InternalMove); DeviceListModel *model = new DeviceListModel(this); model->setList(QString("Value1|Value2|Value3|Value4|Value5|Value6|Value7|Value8|Value9").split("|")); ui->listView->setModel(model); } MainWindow::~MainWindow() { delete ui; }
DeviceListModel.cpp:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 class DeviceListModel : public QAbstractListModel { Q_OBJECT public: explicit DeviceListModel(QObject *parent = 0); void setList(const QList<QString> &list); //Reimplement needed functions int rowCount(const QModelIndex &parent) const; QVariant data(const QModelIndex &index, int role) const; virtual Qt::DropActions supportedDragActions(); virtual Qt::DropActions supportedDropActions(); Qt::ItemFlags flags(const QModelIndex &index) const; bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); bool insertRows(int row, int count, const QModelIndex &parent); bool removeRows(int row, int count, const QModelIndex &parent); bool setData(const QModelIndex &index, const QVariant &value, int role); protected: QList<QString> m_list; };
Si je modifie la ligne :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 DeviceListModel::DeviceListModel(QObject *parent) : QAbstractListModel(parent) { } int DeviceListModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return m_list.count(); } QVariant DeviceListModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= m_list.size()) return QVariant(); if (role == Qt::DisplayRole || role == Qt::EditRole) return m_list.value(index.row()); return QVariant(); } Qt::DropActions DeviceListModel::supportedDragActions() { qDebug() << "supportedDragActions " << QAbstractListModel::supportedDragActions(); return Qt::CopyAction | Qt::MoveAction; } Qt::DropActions DeviceListModel::supportedDropActions() { return Qt::CopyAction | Qt::MoveAction; } Qt::ItemFlags DeviceListModel::flags(const QModelIndex &index) const { Qt::ItemFlags defaultFlags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; if (index.isValid()) return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags; else return Qt::ItemIsDropEnabled | defaultFlags; } bool DeviceListModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { qDebug() << "dropMimeData: " << data->formats().join(", ") << " action: " << action; return false; } bool DeviceListModel::insertRows(int row, int count, const QModelIndex &parent) { qDebug() << "insertRows: " << row << " count: " << count; if(parent.isValid()) return false; return true; } bool DeviceListModel::removeRows(int row, int count, const QModelIndex &parent) { qDebug() << "removeRows: " << row << " count: " << count; if(parent.isValid()) return false; return true; } bool DeviceListModel::setData(const QModelIndex &index, const QVariant &value, int role) { if(!index.isValid()) return false; return true; } void DeviceListModel::setList(const QList<QString> &list) { beginResetModel(); m_list = list; endResetModel(); }
par
Code : Sélectionner tout - Visualiser dans une fenêtre à part ui->listView->setDragDropMode(QAbstractItemView::InternalMove);
j'obtiens un icône + et la fonction dropMimeData est bien appelée avec le type d'action "CopyAction". Mais ce n'est pas ce que je veux car il faudrait alors implémenter cette fonction pour que cela fonctionne. Deplus ils s'agit d'une copie et non d'un déplacement. Ou peut être n'ai-je pas bien compris le principe...
Code : Sélectionner tout - Visualiser dans une fenêtre à part ui->listView->setDragDropMode(QAbstractItemView::DragDrop);
D'après ce que j'ai cru comprendre seules le fonctions removeRows(), rowCount(), flags() et supportedDropActions() doivent être réimplémentées pour supporter les "déplacements internes".
A noter que cela fonctionne très bien avec un QListWidget. On peut le tester très facilement depuis Qt Designer. Il suffit de définir l'option dragDropMode à InternalMove.
Partager