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
mapview.h
+ + ObjectBrowser + QTreeView +
objectbrowser.h
+
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); +};