Skip to content

Commit 066b092

Browse files
committed
Added Drag'n'Drop support for ProjectView
1 parent 470d50b commit 066b092

19 files changed

+260
-7
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,4 @@ List of changes of new v0.4 version of ModbusTools:
165165
* Improved MDI window management
166166
* Improved script text editor
167167
* Added 'Import Project' functionality which unites current project with the imported one
168+
* Implemented Drag`n`Drop for ProjectView window

src/client/gui/project/client_projectmodel.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,30 @@ QString mbClientProjectModel::deviceName(const mbClientDevice *device) const
134134
return device->name();
135135
}
136136

137+
bool mbClientProjectModel::dropDevice(Qt::DropAction action, mbCorePort *sourcePort, int srcIndex, mbCorePort *destPort, int dstIndex)
138+
{
139+
mbClientPort *srcPort = static_cast<mbClientPort*>(sourcePort);
140+
mbClientPort *dstPort = static_cast<mbClientPort*>(destPort);
141+
mbClientDevice *device = srcPort->device(srcIndex);
142+
if (dstIndex < 0 || dstIndex > dstPort->deviceCount())
143+
dstIndex = dstPort->deviceCount();
144+
if (action == Qt::MoveAction && srcPort == dstPort && srcPort->deviceIndex(device) == dstIndex)
145+
return false; // No move
146+
if (action == Qt::MoveAction)
147+
{
148+
srcPort->deviceRemove(device);
149+
dstPort->deviceInsert(device, dstIndex);
150+
}
151+
else if (action == Qt::CopyAction)
152+
{
153+
mbClientDevice *newDevice = new mbClientDevice();
154+
newDevice->setSettings(device->settings());
155+
dstPort->deviceInsert(newDevice, dstIndex);
156+
project()->deviceAdd(newDevice);
157+
}
158+
return true;
159+
}
160+
137161
void mbClientProjectModel::portAdd(mbCorePort *port)
138162
{
139163
int i = project()->portIndex(static_cast<mbClientPort*>(port));

src/client/gui/project/client_projectmodel.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,16 @@ class mbClientProjectModel : public mbCoreProjectModel
5757

5858
protected:
5959
QString deviceName(const mbClientDevice *device) const;
60+
bool dropDevice(Qt::DropAction action, mbCorePort *sourcePort, int srcIndex, mbCorePort *destPort, int dstIndex) override;
6061

6162
protected Q_SLOTS:
6263
void portAdd(mbCorePort *port) override;
6364
void portRemove(mbCorePort *port) override;
6465
void deviceAdd(mbClientDevice *device);
6566
void deviceRemove(mbClientDevice *device);
6667
void deviceChanged();
68+
69+
public:
6770
};
6871

6972
#endif // CLIENT_PROJECTMODEL_H

src/client/gui/project/client_projectui.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@
2222
*/
2323
#include "client_projectui.h"
2424

25-
#include <QTreeView>
26-
2725
#include <project/client_project.h>
2826
#include <project/client_port.h>
2927
#include <project/client_device.h>
3028

29+
#include <gui/project/core_projecttreeview.h>
30+
3131
#include "client_projectmodel.h"
3232
#include "client_projectdelegate.h"
3333

src/client/gui/project/client_projectui.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
class mbClientPort;
2929
class mbClientDevice;
30+
class mbClientProjectTreeView;
3031

3132
class mbClientProjectUi : public mbCoreProjectUi
3233
{

src/core/gui/core_rsc.qrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@
2222
<file>icons/arrow_down.png</file>
2323
<file>icons/arrow_up.png</file>
2424
<file>icons/logexport.png</file>
25+
<file>icons/device_small.png</file>
2526
</qresource>
2627
</RCC>
1.6 KB
Loading

src/core/gui/project/core_projectmodel.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,26 @@
2222
*/
2323
#include "core_projectmodel.h"
2424

25+
#include <QMimeData>
26+
2527
#include <project/core_project.h>
2628
#include <project/core_port.h>
29+
#include <project/core_device.h>
2730

2831
#include <gui/core_ui.h>
2932

33+
mbCoreProjectModel::Strings::Strings() :
34+
mimeTypeDevice(QStringLiteral("application/x-modbustools-device"))
35+
36+
{
37+
}
38+
39+
const mbCoreProjectModel::Strings &mbCoreProjectModel::Strings::instance()
40+
{
41+
static const Strings s;
42+
return s;
43+
}
44+
3045
mbCoreProjectModel::mbCoreProjectModel(QObject* parent) :
3146
QAbstractItemModel (parent)
3247
{
@@ -69,6 +84,63 @@ Qt::ItemFlags mbCoreProjectModel::flags(const QModelIndex &index) const
6984
return f;
7085
}
7186

87+
Qt::DropActions mbCoreProjectModel::supportedDropActions() const
88+
{
89+
return Qt::MoveAction | Qt::CopyAction;
90+
}
91+
92+
QStringList mbCoreProjectModel::mimeTypes() const
93+
{
94+
return {mbCoreProjectModel::Strings::instance().mimeTypeDevice};
95+
}
96+
97+
QMimeData *mbCoreProjectModel::mimeData(const QModelIndexList &indexes) const
98+
{
99+
QMimeData *mimeData = new QMimeData();
100+
if (indexes.size() == 1)
101+
{
102+
QModelIndex index = indexes.first();
103+
if (mbCoreDevice *dev = this->getDeviceByIndex(index))
104+
{
105+
QByteArray encoded;
106+
QDataStream stream(&encoded, QIODevice::WriteOnly);
107+
mbCorePort *port = getPortByIndex(indexes.first());
108+
stream << port->name() << index.row();
109+
mimeData->setData(mbCoreProjectModel::Strings::instance().mimeTypeDevice, encoded);
110+
}
111+
}
112+
return mimeData;
113+
}
114+
115+
bool mbCoreProjectModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
116+
{
117+
if (!data->hasFormat(mbCoreProjectModel::Strings::instance().mimeTypeDevice))
118+
return false;
119+
QByteArray encoded = data->data(mbCoreProjectModel::Strings::instance().mimeTypeDevice);
120+
QDataStream stream(&encoded, QIODevice::ReadOnly);
121+
QString srcPortName;
122+
int srcIndex;
123+
stream >> srcPortName >> srcIndex;
124+
mbCoreProject *prj = projectCore();
125+
if (!prj)
126+
return false;
127+
mbCorePort *srcPort = prj->portCore(srcPortName);
128+
mbCoreDevice *device = prj->deviceCore(srcIndex);
129+
if (!srcPort || !device)
130+
return false;
131+
QModelIndex portIndex = parent;
132+
if (!portIndex.isValid())
133+
portIndex = index(row, column);
134+
mbCorePort *dstPort = portCore(portIndex);
135+
if (!dstPort)
136+
{
137+
dstPort = prj->portCore(prj->portCount()-1);
138+
if (!dstPort)
139+
return false;
140+
}
141+
return dropDevice(action, srcPort, srcIndex, dstPort, row);
142+
}
143+
72144
void mbCoreProjectModel::setUseNameWithSettings(bool use)
73145
{
74146
if (m_settings.useNameWithSettings != use)

src/core/gui/project/core_projectmodel.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ class MB_EXPORT mbCoreProjectModel : public QAbstractItemModel
3636
{
3737
Q_OBJECT
3838

39+
public:
40+
struct MB_EXPORT Strings
41+
{
42+
const QString mimeTypeDevice;
43+
44+
Strings();
45+
static const Strings &instance();
46+
};
47+
3948
public:
4049
mbCoreProjectModel(QObject* parent = nullptr);
4150

@@ -48,6 +57,10 @@ class MB_EXPORT mbCoreProjectModel : public QAbstractItemModel
4857
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
4958
bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
5059
Qt::ItemFlags flags(const QModelIndex &index) const override;
60+
Qt::DropActions supportedDropActions() const override;
61+
QStringList mimeTypes() const override;
62+
QMimeData *mimeData(const QModelIndexList &indexes) const override;
63+
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
5164

5265
public: // settings
5366
inline bool useNameWithSettings() const { return m_settings.useNameWithSettings; }
@@ -67,6 +80,7 @@ class MB_EXPORT mbCoreProjectModel : public QAbstractItemModel
6780

6881
protected:
6982
QString portName(const mbCorePort *port) const;
83+
virtual bool dropDevice(Qt::DropAction action, mbCorePort *srcPort, int srcIndex, mbCorePort *dstPort, int dstIndex) = 0;
7084

7185
protected Q_SLOTS:
7286
virtual void portChanged();
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#include "core_projecttreeview.h"
2+
3+
#include <QApplication>
4+
#include <QTreeView>
5+
#include <QMouseEvent>
6+
#include <QDrag>
7+
8+
mbCoreProjectTreeView::mbCoreProjectTreeView(QWidget *parent) : QTreeView(parent)
9+
{
10+
11+
}
12+
13+
void mbCoreProjectTreeView::mousePressEvent(QMouseEvent *event)
14+
{
15+
if (event->button() == Qt::LeftButton)
16+
m_dragStartPosition = event->pos();
17+
QTreeView::mousePressEvent(event);
18+
}
19+
20+
void mbCoreProjectTreeView::mouseMoveEvent(QMouseEvent *event)
21+
{
22+
if (!(event->buttons() & Qt::LeftButton))
23+
return;
24+
if ((event->pos() - m_dragStartPosition).manhattanLength() < QApplication::startDragDistance())
25+
return;
26+
QModelIndex index = this->indexAt(m_dragStartPosition);
27+
if (!index.isValid())
28+
return;
29+
if (!index.parent().isValid()) // Note: invalid parent index means that is port
30+
return;
31+
m_dragInProgress = true;
32+
QDrag *drag = new QDrag(this);
33+
QMimeData *mimeData = model()->mimeData({index});
34+
drag->setMimeData(mimeData);
35+
drag->setPixmap(QPixmap(":/core/icons/device_small.png"));
36+
drag->exec(Qt::MoveAction | Qt::CopyAction);
37+
m_dragInProgress = false;
38+
}
39+
40+
void mbCoreProjectTreeView::dropEvent(QDropEvent *event)
41+
{
42+
QModelIndex index = indexAt(event->pos());
43+
if (index.isValid())
44+
model()->dropMimeData(event->mimeData(), event->dropAction(), index.row(), index.column(), index.parent());
45+
}
46+
47+
void mbCoreProjectTreeView::dragEnterEvent(QDragEnterEvent *event)
48+
{
49+
event->acceptProposedAction();
50+
}
51+
52+
void mbCoreProjectTreeView::dragMoveEvent(QDragMoveEvent *event)
53+
{
54+
event->acceptProposedAction();
55+
}
56+
57+
void mbCoreProjectTreeView::dragLeaveEvent(QDragLeaveEvent *event)
58+
{
59+
event->accept();
60+
}

0 commit comments

Comments
 (0)