diff --git a/mapeditor/mainwindow.cpp b/mapeditor/mainwindow.cpp
index 3acf2d678..7dba97e27 100644
--- a/mapeditor/mainwindow.cpp
+++ b/mapeditor/mainwindow.cpp
@@ -550,7 +550,7 @@ void MainWindow::loadObjectsTree()
//model
objectsModel.setHorizontalHeaderLabels(QStringList() << tr("Type"));
- objectBrowser = new ObjectBrowser(this);
+ objectBrowser = new ObjectBrowserProxyModel(this);
objectBrowser->setSourceModel(&objectsModel);
objectBrowser->setDynamicSortFilter(false);
objectBrowser->setRecursiveFilteringEnabled(true);
diff --git a/mapeditor/mainwindow.h b/mapeditor/mainwindow.h
index 3028c6b25..fb312ac70 100644
--- a/mapeditor/mainwindow.h
+++ b/mapeditor/mainwindow.h
@@ -8,7 +8,7 @@
#include "resourceExtractor/ResourceConverter.h"
class CMap;
-class ObjectBrowser;
+class ObjectBrowserProxyModel;
class CGObjectInstance;
namespace Ui
@@ -133,7 +133,7 @@ private:
private:
Ui::MainWindow * ui;
- ObjectBrowser * objectBrowser = nullptr;
+ ObjectBrowserProxyModel * objectBrowser = nullptr;
QGraphicsScene * scenePreview;
QString filename;
diff --git a/mapeditor/mainwindow.ui b/mapeditor/mainwindow.ui
index 1b266eaec..6da92787e 100644
--- a/mapeditor/mainwindow.ui
+++ b/mapeditor/mainwindow.ui
@@ -303,7 +303,7 @@
-
-
+
0
@@ -319,8 +319,11 @@
QAbstractItemView::NoEditTriggers
+
+ false
+
- QAbstractItemView::NoDragDrop
+ QAbstractItemView::DragOnly
QAbstractItemView::SelectItems
@@ -1206,6 +1209,11 @@
QGraphicsView
+
+ ObjectBrowser
+ QTreeView
+
+
diff --git a/mapeditor/mapview.cpp b/mapeditor/mapview.cpp
index d9460d7a4..d3bc84f9d 100644
--- a/mapeditor/mapview.cpp
+++ b/mapeditor/mapview.cpp
@@ -13,6 +13,7 @@
#include "mainwindow.h"
#include
#include "mapcontroller.h"
+#include "../lib/mapObjects/CObjectClassesHandler.h"
MinimapView::MinimapView(QWidget * parent):
QGraphicsView(parent)
@@ -161,13 +162,7 @@ void MapView::mouseMoveEvent(QMouseEvent *mouseEvent)
if(sh.x || sh.y)
{
- if(sc->selectionObjectsView.newObject)
- {
- sc->selectionObjectsView.shift = QPoint(tile.x, tile.y);
- sc->selectionObjectsView.selectObject(sc->selectionObjectsView.newObject);
- sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::MOVEMENT;
- }
- else if(mouseEvent->buttons() & Qt::LeftButton)
+ if(sc->selectionObjectsView.newObject && (mouseEvent->buttons() & Qt::LeftButton))
{
if(sc->selectionObjectsView.selectionMode == SelectionObjectsLayer::SELECTION)
{
@@ -324,7 +319,7 @@ void MapView::mouseReleaseEvent(QMouseEvent *event)
bool tab = false;
if(sc->selectionObjectsView.selectionMode == SelectionObjectsLayer::MOVEMENT)
{
- if(sc->selectionObjectsView.newObject)
+ /*if(sc->selectionObjectsView.newObject)
{
QString errorMsg;
if(controller->canPlaceObject(sc->level, sc->selectionObjectsView.newObject, errorMsg))
@@ -335,8 +330,8 @@ void MapView::mouseReleaseEvent(QMouseEvent *event)
break;
}
}
- else
- controller->commitObjectShift(sc->level);
+ else*/
+ controller->commitObjectShift(sc->level);
}
else
{
@@ -355,6 +350,100 @@ void MapView::mouseReleaseEvent(QMouseEvent *event)
}
}
+void MapView::dragEnterEvent(QDragEnterEvent * event)
+{
+ if(!controller || !controller->map())
+ return;
+
+ auto * sc = static_cast(scene());
+ if(!sc)
+ return;
+
+ if(event->mimeData()->hasFormat("application/vcmi.object"))
+ {
+ auto encodedData = event->mimeData()->data("application/vcmi.object");
+ QDataStream stream(&encodedData, QIODevice::ReadOnly);
+ QJsonObject data;
+ stream >> data;
+ if(!data.empty())
+ {
+ auto preview = data["preview"];
+ if(preview != QJsonValue::Undefined)
+ {
+ auto objId = data["id"].toInt();
+ auto objSubId = data["subid"].toInt();
+ auto templateId = data["template"].toInt();
+ auto factory = VLC->objtypeh->getHandlerFor(objId, objSubId);
+ auto templ = factory->getTemplates()[templateId];
+ controller->discardObject(sc->level);
+ controller->createObject(sc->level, factory->create(templ));
+ }
+ }
+
+ event->acceptProposedAction();
+ }
+}
+
+void MapView::dropEvent(QDropEvent * event)
+{
+ if(!controller || !controller->map())
+ return;
+
+ auto * sc = static_cast(scene());
+ if(!sc)
+ return;
+
+ if(sc->selectionObjectsView.newObject)
+ {
+ QString errorMsg;
+ if(controller->canPlaceObject(sc->level, sc->selectionObjectsView.newObject, errorMsg))
+ {
+ controller->commitObjectCreate(sc->level);
+ }
+ else
+ {
+ controller->discardObject(sc->level);
+ QMessageBox::information(this, "Can't place object", errorMsg);
+ }
+ }
+
+ event->acceptProposedAction();
+}
+
+void MapView::dragMoveEvent(QDragMoveEvent * event)
+{
+ auto * sc = static_cast(scene());
+ if(!sc)
+ return;
+
+ auto rect = event->answerRect();
+ auto pos = mapToScene(rect.bottomRight()); //TODO: do we need to check size?
+ int3 tile(pos.x() / 32 + 1, pos.y() / 32 + 1, sc->level);
+
+ if(sc->selectionObjectsView.newObject)
+ {
+ sc->selectionObjectsView.shift = QPoint(tile.x, tile.y);
+ sc->selectionObjectsView.selectObject(sc->selectionObjectsView.newObject);
+ sc->selectionObjectsView.selectionMode = SelectionObjectsLayer::MOVEMENT;
+ sc->selectionObjectsView.draw();
+ }
+
+ event->acceptProposedAction();
+}
+
+void MapView::dragLeaveEvent(QDragLeaveEvent * event)
+{
+ if(!controller || !controller->map())
+ return;
+
+ auto * sc = static_cast(scene());
+ if(!sc)
+ return;
+
+ controller->discardObject(sc->level);
+}
+
+
bool MapView::viewportEvent(QEvent *event)
{
if(auto * sc = static_cast(scene()))
diff --git a/mapeditor/mapview.h b/mapeditor/mapview.h
index 13caabb97..703a68399 100644
--- a/mapeditor/mapview.h
+++ b/mapeditor/mapview.h
@@ -98,6 +98,10 @@ public slots:
void mouseMoveEvent(QMouseEvent * mouseEvent) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
+ void dragEnterEvent(QDragEnterEvent * event) override;
+ void dragMoveEvent(QDragMoveEvent *event) override;
+ void dragLeaveEvent(QDragLeaveEvent *event) override;
+ void dropEvent(QDropEvent * event) override;
void cameraChanged(const QPointF & pos);
@@ -127,7 +131,7 @@ public:
public slots:
void mouseMoveEvent(QMouseEvent * mouseEvent) override;
- void mousePressEvent(QMouseEvent* event) override;
+ void mousePressEvent(QMouseEvent * event) override;
signals:
void cameraPositionChanged(const QPointF & newPosition);
diff --git a/mapeditor/objectbrowser.cpp b/mapeditor/objectbrowser.cpp
index 416b8abfa..809b10eed 100644
--- a/mapeditor/objectbrowser.cpp
+++ b/mapeditor/objectbrowser.cpp
@@ -12,12 +12,12 @@
#include "objectbrowser.h"
#include "../lib/mapObjects/CObjectClassesHandler.h"
-ObjectBrowser::ObjectBrowser(QObject *parent)
+ObjectBrowserProxyModel::ObjectBrowserProxyModel(QObject *parent)
: QSortFilterProxyModel{parent}, terrain(Terrain::ANY_TERRAIN)
{
}
-bool ObjectBrowser::filterAcceptsRow(int source_row, const QModelIndex & source_parent) const
+bool ObjectBrowserProxyModel::filterAcceptsRow(int source_row, const QModelIndex & source_parent) const
{
bool result = QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
@@ -57,7 +57,7 @@ bool ObjectBrowser::filterAcceptsRow(int source_row, const QModelIndex & source_
return result;
}
-bool ObjectBrowser::filterAcceptsRowText(int source_row, const QModelIndex &source_parent) const
+bool ObjectBrowserProxyModel::filterAcceptsRowText(int source_row, const QModelIndex &source_parent) const
{
if(source_parent.isValid())
{
@@ -76,3 +76,48 @@ bool ObjectBrowser::filterAcceptsRowText(int source_row, const QModelIndex &sour
return (filter.isNull() || filter.isEmpty() || item->text().contains(filter, Qt::CaseInsensitive));
}
+Qt::ItemFlags ObjectBrowserProxyModel::flags(const QModelIndex & index) const
+{
+ Qt::ItemFlags defaultFlags = QSortFilterProxyModel::flags(index);
+
+ if (index.isValid())
+ return Qt::ItemIsDragEnabled | defaultFlags;
+
+ return defaultFlags;
+}
+
+QStringList ObjectBrowserProxyModel::mimeTypes() const
+{
+ QStringList types;
+ types << "application/vcmi.object";
+ return types;
+}
+
+QMimeData * ObjectBrowserProxyModel::mimeData(const QModelIndexList & indexes) const
+{
+ assert(indexes.size() == 1);
+
+ auto * standardModel = qobject_cast(sourceModel());
+ assert(standardModel);
+
+ QModelIndex index = indexes.front();
+ QMimeData * mimeData = new QMimeData;
+ QByteArray encodedData;
+
+ QDataStream stream(&encodedData, QIODevice::WriteOnly);
+
+ if(index.isValid())
+ {
+ auto text = standardModel->itemFromIndex(mapToSource(index))->data().toJsonObject();
+ stream << text;
+ }
+
+ mimeData->setData("application/vcmi.object", encodedData);
+ return mimeData;
+}
+
+ObjectBrowser::ObjectBrowser(QWidget * parent):
+ QTreeView(parent)
+{
+
+}
diff --git a/mapeditor/objectbrowser.h b/mapeditor/objectbrowser.h
index 6c700ae62..d62ee7fce 100644
--- a/mapeditor/objectbrowser.h
+++ b/mapeditor/objectbrowser.h
@@ -13,10 +13,16 @@
#include
#include "../lib/Terrain.h"
-class ObjectBrowser : public QSortFilterProxyModel
+class ObjectBrowserProxyModel : public QSortFilterProxyModel
{
public:
- explicit ObjectBrowser(QObject *parent = nullptr);
+ explicit ObjectBrowserProxyModel(QObject *parent = nullptr);
+
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
+
+ QStringList mimeTypes() const override;
+
+ QMimeData * mimeData(const QModelIndexList & indexes) const override;
TerrainId terrain;
QString filter;
@@ -25,3 +31,9 @@ protected:
bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const override;
bool filterAcceptsRowText(int source_row, const QModelIndex &source_parent) const;
};
+
+class ObjectBrowser : public QTreeView
+{
+public:
+ ObjectBrowser(QWidget * parent);
+};