Skip to content

Commit

Permalink
Support for drag and drop (#54)
Browse files Browse the repository at this point in the history
Added support for drag and drop

---------

Co-authored-by: Leonardo Seiji Oyama <oyama@coter.eb.mil.br>
  • Loading branch information
leonardooyama and Leonardo Seiji Oyama authored Jun 4, 2024
1 parent 31b9df4 commit 89afccb
Show file tree
Hide file tree
Showing 11 changed files with 329 additions and 1 deletion.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ if (${BUILD_EXAMPLES})
add_subdirectory(samples/moving-objects)
add_subdirectory(samples/mouse-actions)
add_subdirectory(samples/camera-actions)
add_subdirectory(samples/drag-and-drop)
else ()
message(STATUS "Disabled building of examples")
endif ()
3 changes: 2 additions & 1 deletion QGeoView.pro
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ SUBDIRS = \
samples/custom-tiles \
samples/moving-objects \
samples/mouse-actions \
samples/camera-actions
samples/camera-actions \
samples/drag-and-drop
3 changes: 3 additions & 0 deletions lib/include/QGeoView/QGVMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#pragma once

#include <QMimeData>
#include <QWidget>

#include "QGVCamera.h"
Expand Down Expand Up @@ -104,11 +105,13 @@ class QGV_LIB_DECL QGVMap : public QWidget
void mapMouseMove(QPointF projPos);
void mapMousePress(QPointF projPos);
void mapMouseDoubleClicked(QPointF projPos);
void dropOnMap(QGV::GeoPos pos, const QMimeData* data);

private:
QScopedPointer<QGVProjection> mProjection;
QScopedPointer<QGVMapQGView> mQGView;
QScopedPointer<QGVItem> mRootItem;
QList<QGVWidget*> mWidgets;
QSet<QGVItem*> mSelections;
void handleDropDataOnQGVMapQGView(QPointF position, const QMimeData* dropData);
};
13 changes: 13 additions & 0 deletions lib/include/QGeoView/QGVMapQGView.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,14 @@
#include "QGVMapQGItem.h"
#include "QGVMapRubberBand.h"


#include <QDragEnterEvent>
#include <QDragLeaveEvent>
#include <QDragMoveEvent>
#include <QDropEvent>
#include <QGraphicsView>
#include <QMenu>
#include <QMimeData>

class QGVMap;

Expand All @@ -45,6 +51,9 @@ class QGV_LIB_DECL QGVMapQGView : public QGraphicsView
void setScaleLimits(double minScale, double maxScale);
void cleanState();

Q_SIGNALS:
void dropData(QPointF position, const QMimeData* dropData);

private:
QRectF viewRect() const;
void changeState(QGV::MapState state);
Expand Down Expand Up @@ -83,6 +92,10 @@ class QGV_LIB_DECL QGVMapQGView : public QGraphicsView
void resizeEvent(QResizeEvent* event) override final;
void showEvent(QShowEvent* event) override final;
void keyPressEvent(QKeyEvent* event) override final;
void dragEnterEvent(QDragEnterEvent* event) override final;
void dragMoveEvent(QDragMoveEvent* event) override final;
void dropEvent(QDropEvent* event) override final;
void dragLeaveEvent(QDragLeaveEvent* event) override final;

private:
QGVMap* mGeoMap;
Expand Down
8 changes: 8 additions & 0 deletions lib/src/QGVMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ QGVMap::QGVMap(QWidget* parent)
layout()->addWidget(mQGView.data());
layout()->setContentsMargins(0, 0, 0, 0);
refreshProjection();
connect(mQGView.data(), &QGVMapQGView::dropData, this, &QGVMap::handleDropDataOnQGVMapQGView);
}

QGVMap::~QGVMap()
Expand Down Expand Up @@ -381,6 +382,13 @@ void QGVMap::mousePressEvent(QMouseEvent* event)
QWidget::mousePressEvent(event);
}

void QGVMap::handleDropDataOnQGVMapQGView(QPointF position, const QMimeData* dropData)
{
const auto mapToProjectionPos = mapToProj(QPoint(position.rx(), position.ry()));
auto geoPos = getProjection()->projToGeo(mapToProjectionPos);
Q_EMIT dropOnMap(geoPos, dropData);
}

void QGVMap::mouseDoubleClickEvent(QMouseEvent* event)
{
if (hasMouseTracking()) {
Expand Down
27 changes: 27 additions & 0 deletions lib/src/QGVMapQGView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ QGVMapQGView::QGVMapQGView(QGVMap* geoMap)
setCacheMode(QGraphicsView::CacheBackground);
setMouseTracking(true);
setBackgroundBrush(QBrush(Qt::lightGray));
setAcceptDrops(true);
}

void QGVMapQGView::setMouseActions(QGV::MouseActions actions)
Expand Down Expand Up @@ -599,3 +600,29 @@ void QGVMapQGView::keyPressEvent(QKeyEvent* event)
{
QWidget::keyPressEvent(event);
}

void QGVMapQGView::dragEnterEvent(QDragEnterEvent* event)
{
event->accept();
}

void QGVMapQGView::dragMoveEvent(QDragMoveEvent* event)
{
event->accept();
}

void QGVMapQGView::dropEvent(QDropEvent* event)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
Q_EMIT dropData(event->position(), event->mimeData());
#else
QPointF dropPoint = event->posF();
Q_EMIT dropData(dropPoint, event->mimeData());
#endif
event->accept();
}

void QGVMapQGView::dragLeaveEvent(QDragLeaveEvent* event)
{
event->accept();
}
37 changes: 37 additions & 0 deletions samples/drag-and-drop/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
set(CMAKE_CXX_STANDARD 11)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

# Set the QT version
find_package(Qt6 COMPONENTS Core QUIET)
if (NOT Qt6_FOUND)
set(QT_VERSION 5 CACHE STRING "Qt version for QGeoView")
else()
set(QT_VERSION 6 CACHE STRING "Qt version for QGeoView")
endif()

find_package(Qt${QT_VERSION} REQUIRED COMPONENTS
Core
Gui
Widgets
Network
)

add_executable(qgeoview-samples-drag-and-drop
main.cpp
mainwindow.h
mainwindow.cpp
)

target_link_libraries(qgeoview-samples-drag-and-drop
PRIVATE
Qt${QT_VERSION}::Core
Qt${QT_VERSION}::Network
Qt${QT_VERSION}::Gui
Qt${QT_VERSION}::Widgets
QGeoView
qgeoview-samples-shared
)
15 changes: 15 additions & 0 deletions samples/drag-and-drop/drag-and-drop.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
TARGET = qgeoview-samples-drag-and-drop
TEMPLATE = app
CONFIG-= console

QT += gui widgets network

include(../lib.pri)
include(../shared.pri)

SOURCES += \
main.cpp \
mainwindow.cpp

HEADERS += \
mainwindow.h
37 changes: 37 additions & 0 deletions samples/drag-and-drop/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/***************************************************************************
* QGeoView is a Qt / C ++ widget for visualizing geographic data.
* Copyright (C) 2018-2023 Andrey Yaroshenko.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see https://www.gnu.org/licenses.
****************************************************************************/

#include <QApplication>
#include <QCommandLineParser>

#include "mainwindow.h"

int main(int argc, char* argv[])
{
QApplication app(argc, argv);
app.setApplicationName("QGeoView Samples");

QCommandLineParser parser;
parser.addHelpOption();
parser.addVersionOption();
parser.process(app);

MainWindow window;
window.show();
return app.exec();
}
143 changes: 143 additions & 0 deletions samples/drag-and-drop/mainwindow.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/***************************************************************************
* QGeoView is a Qt / C ++ widget for visualizing geographic data.
* Copyright (C) 2018-2023 Andrey Yaroshenko.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see https://www.gnu.org/licenses.
****************************************************************************/

#include "mainwindow.h"

#include <QApplication>
#include <QGuiApplication>
#include <QHBoxLayout>
#include <QIcon>
#include <QTimer>
#include <QTreeWidgetItem>

//#include <QGeoView/QGVLayerBDGEx.h>
#include <QGeoView/QGVLayerGoogle.h>
#include <QGeoView/Raster/QGVIcon.h>
#include <helpers.h>

MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent)
{
setWindowTitle("QGeoView Samples - drag and drop");
setCentralWidget(new QWidget());
centralWidget()->setLayout(new QHBoxLayout());

// setup tree widget
sampleTree = new QTreeWidget(this);
sampleTree->setDragEnabled(true); // enable dragging items from the tree
sampleTree->setMinimumWidth(200);
sampleTree->setMaximumWidth(250);

// setup data into the tree widget
sampleTree->setColumnCount(1);
sampleTree->setHeaderLabel("Sample Tree Items with Icons");

QTreeWidgetItem* itemArrowUp = new QTreeWidgetItem;
QIcon arrowUp_icon = QApplication::style()->standardIcon(QStyle::SP_ArrowUp);
itemArrowUp->setData(0, Qt::DisplayRole, "Arrow Up");
itemArrowUp->setData(0, Qt::DecorationRole, arrowUp_icon);
sampleTree->addTopLevelItem(itemArrowUp);

QTreeWidgetItem* itemArrowDown = new QTreeWidgetItem;
QIcon arrowDown_icon = QApplication::style()->standardIcon(QStyle::SP_ArrowDown);
itemArrowDown->setData(0, Qt::DisplayRole, "Arrow Down");
itemArrowDown->setData(0, Qt::DecorationRole, arrowDown_icon);
sampleTree->addTopLevelItem(itemArrowDown);

QTreeWidgetItem* itemArrowRight = new QTreeWidgetItem;
QIcon arrowRight_icon = QApplication::style()->standardIcon(QStyle::SP_ArrowRight);
itemArrowRight->setData(0, Qt::DisplayRole, "Arrow Right");
itemArrowRight->setData(0, Qt::DecorationRole, arrowRight_icon);
sampleTree->addTopLevelItem(itemArrowRight);

QTreeWidgetItem* itemArrowLeft = new QTreeWidgetItem;
QIcon arrowLeft_icon = QApplication::style()->standardIcon(QStyle::SP_ArrowLeft);
itemArrowLeft->setData(0, Qt::DisplayRole, "Arrow Left");
itemArrowLeft->setData(0, Qt::DecorationRole, arrowLeft_icon);
sampleTree->addTopLevelItem(itemArrowLeft);

centralWidget()->layout()->addWidget(sampleTree);

// QGeoView setup
Helpers::setupCachedNetworkAccessManager(this);
mMap = new QGVMap(this);

// Background layer
// QGVLayer * layerBDGExCTM250 = new QGVLayerBDGEx(QGV::BDGExLayer::ctm250);
// layerBDGExCTM250->setName("BDGEx CTM250");
// mMap->addItem(layerBDGExCTM250);

QGVLayer* layerGoogleSchema = new QGVLayerGoogle(QGV::TilesType::Schema);
layerGoogleSchema->setName("Google Schema");
mMap->addItem(layerGoogleSchema);

// initial area to show
QTimer::singleShot(500, this, &MainWindow::targetArea);
centralWidget()->layout()->addWidget(mMap); // add map to central widget

// handle drop of itens on map
connect(mMap, &QGVMap::dropOnMap, this, &MainWindow::handleDropOnMap);
iconsLayer = new QGVLayer();
mMap->addItem(iconsLayer);
}

MainWindow::~MainWindow()
{
}

void MainWindow::targetArea()
{
QGV::GeoPos geoPos(-23.55651916354534, -46.61844717963553);
auto scaleRect = QGV::GeoRect{
geoPos.latitude() - 0.33, geoPos.longitude() - 0.33, geoPos.latitude() + 0.33, geoPos.longitude() + 0.33
};
mMap->cameraTo(QGVCameraActions(mMap).scaleTo(scaleRect));
return;
}

void MainWindow::handleDropOnMap(QGV::GeoPos pos, const QMimeData* data)
{
QByteArray encoded = data->data("application/x-qabstractitemmodeldatalist");
QDataStream stream(&encoded, QIODevice::ReadOnly);
QIcon iconDropped;
QString strDropped;
while (!stream.atEnd()) {
int row, col;
QMap<int, QVariant> roleDataMap;
stream >> row >> col >> roleDataMap;
for (auto i = 0; i < roleDataMap.size(); i++) {
std::string typeName = roleDataMap[i].typeName();
auto variant = roleDataMap[i];
if (typeName == "QString") {
strDropped = qvariant_cast<QString>(variant);
}
if (typeName == "QIcon") {
iconDropped = qvariant_cast<QIcon>(variant);
}
}
}
qDebug() << strDropped << "(lat, lon):" << pos.latToString() << pos.lonToString();
if (!iconDropped.isNull() && !strDropped.isEmpty()) {
auto* mIcon = new QGVIcon();
auto pixmap = iconDropped.pixmap(QSize(32, 32));
auto image = pixmap.toImage();
mIcon->loadImage(image);
mIcon->setGeometry(pos, QSizeF(32, 32));
iconsLayer->addItem(mIcon);
}
}
Loading

0 comments on commit 89afccb

Please sign in to comment.