diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a2924e..22510a1 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ if (${BUILD_EXAMPLES}) add_subdirectory(samples/widgets) add_subdirectory(samples/flags) add_subdirectory(samples/layers) + add_subdirectory(samples/raster) add_subdirectory(samples/fun) add_subdirectory(samples/10000) add_subdirectory(samples/debug) diff --git a/QGeoView.pro b/QGeoView.pro index 79ffcbb..b311b6c 100644 --- a/QGeoView.pro +++ b/QGeoView.pro @@ -8,6 +8,7 @@ SUBDIRS = \ samples/widgets \ samples/flags \ samples/layers \ + samples/raster \ samples/fun \ samples/10000 \ samples/debug \ diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index ee98dfa..72c99ef 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -36,7 +36,6 @@ add_library(qgeoview SHARED include/QGeoView/QGVItem.h include/QGeoView/QGVDrawItem.h include/QGeoView/QGVLayer.h - include/QGeoView/QGVImage.h include/QGeoView/QGVLayerTiles.h include/QGeoView/QGVLayerTilesOnline.h include/QGeoView/QGVLayerGoogle.h @@ -48,6 +47,8 @@ add_library(qgeoview SHARED include/QGeoView/QGVWidgetScale.h include/QGeoView/QGVWidgetZoom.h include/QGeoView/QGVWidgetText.h + include/QGeoView/Raster/QGVImage.h + include/QGeoView/Raster/QGVIcon.h src/QGVUtils.cpp src/QGVGlobal.cpp src/QGVProjection.cpp @@ -60,7 +61,6 @@ add_library(qgeoview SHARED src/QGVItem.cpp src/QGVDrawItem.cpp src/QGVLayer.cpp - src/QGVImage.cpp src/QGVLayerTiles.cpp src/QGVLayerTilesOnline.cpp src/QGVLayerGoogle.cpp @@ -72,6 +72,8 @@ add_library(qgeoview SHARED src/QGVWidgetScale.cpp src/QGVWidgetZoom.cpp src/QGVWidgetText.cpp + src/Raster/QGVImage.cpp + src/Raster/QGVIcon.cpp ) target_include_directories(qgeoview diff --git a/lib/include/QGeoView/Raster/QGVIcon.h b/lib/include/QGeoView/Raster/QGVIcon.h new file mode 100644 index 0000000..f98ebc2 --- /dev/null +++ b/lib/include/QGeoView/Raster/QGVIcon.h @@ -0,0 +1,55 @@ +/*************************************************************************** + * 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. + ****************************************************************************/ + +#pragma once + +#include + +class QGV_LIB_DECL QGVIcon : public QGVDrawItem +{ + Q_OBJECT + +public: + QGVIcon(); + + void setGeometry(const QGV::GeoPos& geoPos, const QSizeF& imageSize = QSizeF()); + void setGeometry(const QPointF& projPos, const QSizeF& imageSize = QSizeF()); + + QImage getImage() const; + bool isImage() const; + + void loadImage(const QByteArray& rawData); + void loadImage(const QImage& image); + +protected: + void onProjection(QGVMap* geoMap) override; + QPainterPath projShape() const override; + void projPaint(QPainter* painter) override; + +private: + void calculateGeometry(); + +private: + QGV::GeoPos mGeoPos; + QPointF mProjPos; + QSizeF mImageSize; + QRectF mProjRect; + + QString mUrl; + QImage mImage; +}; diff --git a/lib/include/QGeoView/QGVImage.h b/lib/include/QGeoView/Raster/QGVImage.h similarity index 74% rename from lib/include/QGeoView/QGVImage.h rename to lib/include/QGeoView/Raster/QGVImage.h index d681f32..be8de02 100644 --- a/lib/include/QGeoView/QGVImage.h +++ b/lib/include/QGeoView/Raster/QGVImage.h @@ -18,8 +18,7 @@ #pragma once -#include "QGVDrawItem.h" -#include +#include class QGV_LIB_DECL QGVImage : public QGVDrawItem { @@ -29,39 +28,29 @@ class QGV_LIB_DECL QGVImage : public QGVDrawItem QGVImage(); void setGeometry(const QGV::GeoRect& geoRect); - void setGeometry(const QGV::GeoPos& geoPos, const QSize& imageSize = QSize(), const QPoint& imageAnchor = QPoint()); + void setGeometry(const QRectF& projRect); QImage getImage() const; bool isImage() const; - void load(const QString& url); void loadImage(const QByteArray& rawData); void loadImage(const QImage& image); + void setCeilingOnScale(bool enabled); + protected: void onProjection(QGVMap* geoMap) override; QPainterPath projShape() const override; - QPointF projAnchor() const override; void projPaint(QPainter* painter) override; private: - void onReplyFinished(); void calculateGeometry(); private: - enum class GeometryType - { - None, - ByRect, - ByPos, - } mGeometryType; QGV::GeoRect mGeoRect; - QGV::GeoPos mGeoPos; - QSize mImageSize; - QPoint mImageAnchor; QRectF mProjRect; - QPointF mProjAnchor; + QString mUrl; QImage mImage; - QScopedPointer mReply; + bool mCeilingOnScale; }; diff --git a/lib/lib.pro b/lib/lib.pro index 47df2cb..fb0e465 100644 --- a/lib/lib.pro +++ b/lib/lib.pro @@ -10,7 +10,6 @@ HEADERS += \ $$PWD/include/QGeoView/QGVDrawItem.h \ $$PWD/include/QGeoView/QGVGlobal.h \ $$PWD/include/QGeoView/QGVUtils.h \ - $$PWD/include/QGeoView/QGVImage.h \ $$PWD/include/QGeoView/QGVItem.h \ $$PWD/include/QGeoView/QGVLayer.h \ $$PWD/include/QGeoView/QGVLayerBing.h \ @@ -29,14 +28,15 @@ HEADERS += \ $$PWD/include/QGeoView/QGVWidgetCompass.h \ $$PWD/include/QGeoView/QGVWidgetScale.h \ $$PWD/include/QGeoView/QGVWidgetText.h \ - $$PWD/include/QGeoView/QGVWidgetZoom.h + $$PWD/include/QGeoView/QGVWidgetZoom.h \ + $$PWD/include/QGeoView/Raster/QGVImage.h \ + $$PWD/include/QGeoView/Raster/QGVIcon.h \ SOURCES += \ $$PWD/src/QGVCamera.cpp \ $$PWD/src/QGVDrawItem.cpp \ $$PWD/src/QGVGlobal.cpp \ $$PWD/src/QGVUtils.cpp \ - $$PWD/src/QGVImage.cpp \ $$PWD/src/QGVItem.cpp \ $$PWD/src/QGVLayer.cpp \ $$PWD/src/QGVLayerBing.cpp \ @@ -55,7 +55,9 @@ SOURCES += \ $$PWD/src/QGVWidgetCompass.cpp \ $$PWD/src/QGVWidgetScale.cpp \ $$PWD/src/QGVWidgetText.cpp \ - $$PWD/src/QGVWidgetZoom.cpp + $$PWD/src/QGVWidgetZoom.cpp \ + $$PWD/src/Raster/QGVImage.cpp \ + $$PWD/src/Raster/QGVIcon.cpp INCLUDEPATH += \ $$PWD/include/ \ diff --git a/lib/src/QGVLayerTilesOnline.cpp b/lib/src/QGVLayerTilesOnline.cpp index b6b9a96..271bce5 100644 --- a/lib/src/QGVLayerTilesOnline.cpp +++ b/lib/src/QGVLayerTilesOnline.cpp @@ -17,7 +17,7 @@ ****************************************************************************/ #include "QGVLayerTilesOnline.h" -#include "QGVImage.h" +#include "Raster/QGVImage.h" QGVLayerTilesOnline::~QGVLayerTilesOnline() { diff --git a/lib/src/Raster/QGVIcon.cpp b/lib/src/Raster/QGVIcon.cpp new file mode 100644 index 0000000..7e82b30 --- /dev/null +++ b/lib/src/Raster/QGVIcon.cpp @@ -0,0 +1,113 @@ +/*************************************************************************** + * 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 "Raster/QGVIcon.h" +#include "QGVMap.h" + +#include + +QGVIcon::QGVIcon() +{ + setFlag(QGV::ItemFlag::IgnoreScale); + setFlag(QGV::ItemFlag::IgnoreAzimuth); +} + +void QGVIcon::setGeometry(const QGV::GeoPos& geoPos, const QSizeF& imageSize) +{ + mGeoPos = geoPos; + mProjPos = {}; + mImageSize = imageSize; + mProjRect = {}; + calculateGeometry(); +} + +void QGVIcon::setGeometry(const QPointF& projPos, const QSizeF& imageSize) +{ + mGeoPos = {}; + mProjPos = projPos; + mImageSize = imageSize; + mProjRect = {}; + calculateGeometry(); +} + +QImage QGVIcon::getImage() const +{ + return mImage; +} + +bool QGVIcon::isImage() const +{ + return !mImage.isNull(); +} + +void QGVIcon::loadImage(const QByteArray& rawData) +{ + QImage image; + image.loadFromData(rawData); + loadImage(image); +} + +void QGVIcon::loadImage(const QImage& image) +{ + mImage = image; + calculateGeometry(); +} + +void QGVIcon::onProjection(QGVMap* geoMap) +{ + QGVDrawItem::onProjection(geoMap); + calculateGeometry(); +} + +QPainterPath QGVIcon::projShape() const +{ + QPainterPath path; + path.addRect(mProjRect); + return path; +} + +void QGVIcon::projPaint(QPainter* painter) +{ + if (mImage.isNull() || mProjRect.isEmpty()) { + return; + } + + QRectF paintRect = mProjRect; + + painter->setRenderHint(QPainter::SmoothPixmapTransform); + painter->drawImage(paintRect, getImage()); +} + +void QGVIcon::calculateGeometry() +{ + if (getMap() == nullptr) { + return; + } + + if (!mGeoPos.isEmpty()) { + mProjPos = getMap()->getProjection()->geoToProj(mGeoPos); + } + + const QSizeF baseSize = !mImageSize.isEmpty() ? mImageSize : mImage.size(); + const QPointF baseAnchor = QPointF(baseSize.width() / 2, baseSize.height() / 2); + + mProjRect = QRectF(mProjPos - baseAnchor, baseSize); + + resetBoundary(); + refresh(); +} diff --git a/lib/src/QGVImage.cpp b/lib/src/Raster/QGVImage.cpp similarity index 50% rename from lib/src/QGVImage.cpp rename to lib/src/Raster/QGVImage.cpp index c2ec95d..7a0bded 100644 --- a/lib/src/QGVImage.cpp +++ b/lib/src/Raster/QGVImage.cpp @@ -16,31 +16,27 @@ * along with this program; if not, see https://www.gnu.org/licenses. ****************************************************************************/ -#include "QGVImage.h" +#include "Raster/QGVImage.h" #include "QGVMap.h" -#include -#include #include QGVImage::QGVImage() - : mGeometryType(GeometryType::ByRect) + : mCeilingOnScale{ true } { } void QGVImage::setGeometry(const QGV::GeoRect& geoRect) { - mGeometryType = GeometryType::ByRect; mGeoRect = geoRect; + mProjRect = {}; calculateGeometry(); } -void QGVImage::setGeometry(const QGV::GeoPos& geoPos, const QSize& imageSize, const QPoint& imageAnchor) +void QGVImage::setGeometry(const QRectF& projRect) { - mGeometryType = GeometryType::ByPos; - mGeoPos = geoPos; - mImageSize = imageSize; - mImageAnchor = imageAnchor; + mGeoRect = {}; + mProjRect = projRect; calculateGeometry(); } @@ -54,21 +50,6 @@ bool QGVImage::isImage() const return !mImage.isNull(); } -void QGVImage::load(const QString& url) -{ - Q_ASSERT(QGV::getNetworkManager()); - QNetworkRequest request(url); - request.setRawHeader("User-Agent", - "Mozilla/5.0 (Windows; U; MSIE " - "6.0; Windows NT 5.1; SV1; .NET " - "CLR 2.0.50727)"); - request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); - request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); - mReply.reset(QGV::getNetworkManager()->get(request)); - connect(mReply.data(), &QNetworkReply::finished, this, &QGVImage::onReplyFinished); - qgvDebug() << "request" << url; -} - void QGVImage::loadImage(const QByteArray& rawData) { QImage image; @@ -79,6 +60,12 @@ void QGVImage::loadImage(const QByteArray& rawData) void QGVImage::loadImage(const QImage& image) { mImage = image; + calculateGeometry(); +} + +void QGVImage::setCeilingOnScale(bool enabled) +{ + mCeilingOnScale = enabled; } void QGVImage::onProjection(QGVMap* geoMap) @@ -94,63 +81,33 @@ QPainterPath QGVImage::projShape() const return path; } -QPointF QGVImage::projAnchor() const -{ - if (mProjAnchor.isNull()) { - return QGVDrawItem::projAnchor(); - } - return mProjAnchor; -} - void QGVImage::projPaint(QPainter* painter) { if (mImage.isNull() || mProjRect.isEmpty()) { return; } + QRectF paintRect = mProjRect; - if (!isFlag(QGV::ItemFlag::IgnoreScale)) { + + if (mCeilingOnScale && !isFlag(QGV::ItemFlag::IgnoreScale)) { const double pixelFactor = 1.0 / getMap()->getCamera().scale(); paintRect.setSize(paintRect.size() + QSizeF(pixelFactor, pixelFactor)); } + painter->setRenderHint(QPainter::SmoothPixmapTransform); painter->drawImage(paintRect, getImage()); } -void QGVImage::onReplyFinished() -{ - if (mReply.isNull()) { - return; - } - if (mReply->error() != QNetworkReply::NoError) { - qgvCritical() << "ERROR" << mReply->errorString(); - mReply.reset(nullptr); - return; - } - loadImage(mReply->readAll()); - mReply.reset(nullptr); -} - void QGVImage::calculateGeometry() { - mProjRect = {}; - mProjAnchor = {}; - if (mGeometryType == GeometryType::None || getMap() == nullptr) { + if (getMap() == nullptr) { return; } - if (mGeometryType == GeometryType::ByRect) { + + if (!mGeoRect.isEmpty()) { mProjRect = getMap()->getProjection()->geoToProj(mGeoRect); - resetBoundary(); - refresh(); - } else if (mGeometryType == GeometryType::ByPos) { - if (mImageSize.isEmpty() && mImage.isNull()) { - return; - } - const QPointF anchor = - (mImageAnchor.isNull()) ? QPointF(mImageSize.width() / 2, mImageSize.height() / 2) : mImageAnchor; - const QPointF basePos = getMap()->getProjection()->geoToProj(mGeoPos); - mProjRect = QRectF(basePos - anchor, mImageSize); - mProjAnchor = basePos; - resetBoundary(); - refresh(); } + + resetBoundary(); + refresh(); } diff --git a/samples/fun/placemark.cpp b/samples/fun/placemark.cpp index 5d8b258..00d8fd7 100644 --- a/samples/fun/placemark.cpp +++ b/samples/fun/placemark.cpp @@ -18,17 +18,39 @@ #include "placemark.h" +#include + Placemark::Placemark(const QGV::GeoPos& geoPos) { - setFlag(QGV::ItemFlag::IgnoreScale); - setFlag(QGV::ItemFlag::IgnoreAzimuth); - setFlag(QGV::ItemFlag::Highlightable); - setFlag(QGV::ItemFlag::HighlightCustom); setFlag(QGV::ItemFlag::Highlightable); setFlag(QGV::ItemFlag::Transformed); - setGeometry(geoPos, QSize(32, 32), QPoint(16, 32)); - const QString url = "http://maps.google.com/mapfiles/kml/paddle/blu-circle.png"; - load(url); + setGeometry(geoPos, QSize(32, 32)); + + load(QUrl{ "http://maps.google.com/mapfiles/kml/paddle/blu-circle.png" }); +} + +void Placemark::load(const QUrl& url) +{ + QNetworkRequest request(url); + request.setRawHeader("User-Agent", + "Mozilla/5.0 (Windows; U; MSIE " + "6.0; Windows NT 5.1; SV1; .NET " + "CLR 2.0.50727)"); + request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); + request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); + + QNetworkReply* reply = QGV::getNetworkManager()->get(request); + connect(reply, &QNetworkReply::finished, reply, [reply, this]() { + if (reply->error() != QNetworkReply::NoError) { + qgvCritical() << "ERROR" << reply->errorString(); + reply->deleteLater(); + return; + } + loadImage(reply->readAll()); + reply->deleteLater(); + }); + + qgvDebug() << "request" << url; } QTransform Placemark::projTransform() const diff --git a/samples/fun/placemark.h b/samples/fun/placemark.h index 3c59509..6342b28 100644 --- a/samples/fun/placemark.h +++ b/samples/fun/placemark.h @@ -18,15 +18,17 @@ #pragma once -#include +#include -class Placemark : public QGVImage +class Placemark : public QGVIcon { Q_OBJECT public: explicit Placemark(const QGV::GeoPos& geoPos); + void load(const QUrl& url); + private: QTransform projTransform() const override; void projOnFlags() override; diff --git a/samples/raster/CMakeLists.txt b/samples/raster/CMakeLists.txt new file mode 100644 index 0000000..42a1674 --- /dev/null +++ b/samples/raster/CMakeLists.txt @@ -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-raster + main.cpp + mainwindow.h + mainwindow.cpp +) + +target_link_libraries(qgeoview-samples-raster + PRIVATE + Qt${QT_VERSION}::Core + Qt${QT_VERSION}::Network + Qt${QT_VERSION}::Gui + Qt${QT_VERSION}::Widgets + QGeoView + qgeoview-samples-shared +) diff --git a/samples/raster/main.cpp b/samples/raster/main.cpp new file mode 100644 index 0000000..6c72f24 --- /dev/null +++ b/samples/raster/main.cpp @@ -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 +#include + +#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(); +} diff --git a/samples/raster/mainwindow.cpp b/samples/raster/mainwindow.cpp new file mode 100644 index 0000000..9aaa399 --- /dev/null +++ b/samples/raster/mainwindow.cpp @@ -0,0 +1,204 @@ +/*************************************************************************** + * 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 +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +MainWindow::MainWindow() +{ + setWindowTitle("QGeoView Samples - raster"); + + setCentralWidget(new QWidget()); + centralWidget()->setLayout(new QVBoxLayout()); + + Helpers::setupCachedNetworkAccessManager(this); + + mMap = new QGVMap(this); + centralWidget()->layout()->addWidget(mMap); + + // Widgets + mMap->addWidget(new QGVWidgetCompass()); + mMap->addWidget(new QGVWidgetZoom()); + mMap->addWidget(new QGVWidgetScale()); + + // Background layer + auto osmLayer = new QGVLayerOSM(); + mMap->addItem(osmLayer); + + // Raster layer + mLayer = new QGVLayer(); + mMap->addItem(mLayer); + + // Options list + QWidget* widget = new QWidget(); + widget->setLayout(new QHBoxLayout()); + widget->layout()->addWidget(createOptionsList()); + widget->layout()->addWidget(createItemsList()); + centralWidget()->layout()->addWidget(widget); + + // Show target area + QTimer::singleShot(100, this, [this]() { mMap->cameraTo(QGVCameraActions(mMap).scaleTo(targetArea())); }); + + // Pre-load image sources + preloadImages(); +} + +MainWindow::~MainWindow() +{ +} + +QGV::GeoRect MainWindow::targetArea() const +{ + return QGV::GeoRect(QGV::GeoPos(50, 14), QGV::GeoPos(52, 15)); +} + +QGroupBox* MainWindow::createOptionsList() +{ + QGroupBox* groupBox = new QGroupBox(tr("Raster")); + groupBox->setLayout(new QVBoxLayout); + + { + QPushButton* button = new QPushButton("Add image"); + groupBox->layout()->addWidget(button); + + connect(button, &QPushButton::clicked, this, &MainWindow::addImage); + } + + { + QPushButton* button = new QPushButton("Add icon"); + groupBox->layout()->addWidget(button); + + connect(button, &QPushButton::clicked, this, &MainWindow::addIcon); + } + + { + QPushButton* button = new QPushButton("Remove last"); + groupBox->layout()->addWidget(button); + + connect(button, &QPushButton::clicked, this, &MainWindow::removeLast); + } + + return groupBox; +} + +QGroupBox* MainWindow::createItemsList() +{ + QGroupBox* groupBox = new QGroupBox(tr("List of items")); + groupBox->setLayout(new QVBoxLayout); + + mList = new QListWidget(); + groupBox->layout()->addWidget(mList); + updateListOfItems(); + + return groupBox; +} + +void MainWindow::preloadImages() +{ + loadImage(mImage, + QUrl{ "https://upload.wikimedia.org/wikipedia/commons/thumb/7/79/Face-smile.svg/" + "1024px-Face-smile.svg.png" }); + loadImage(mIcon, QUrl{ "http://maps.google.com/mapfiles/kml/paddle/red-circle.png" }); +} + +void MainWindow::loadImage(QImage& dest, QUrl url) +{ + QNetworkRequest request(url); + request.setRawHeader("User-Agent", + "Mozilla/5.0 (Windows; U; MSIE " + "6.0; Windows NT 5.1; SV1; .NET " + "CLR 2.0.50727)"); + request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); + request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); + + QNetworkReply* reply = QGV::getNetworkManager()->get(request); + connect(reply, &QNetworkReply::finished, reply, [reply, &dest]() { + if (reply->error() != QNetworkReply::NoError) { + qgvCritical() << "ERROR" << reply->errorString(); + reply->deleteLater(); + return; + } + dest.loadFromData(reply->readAll()); + reply->deleteLater(); + }); + + qgvDebug() << "request" << url; +} + +void MainWindow::addImage() +{ + const QGV::GeoRect itemTargetArea = mMap->getProjection()->projToGeo(mMap->getCamera().projRect()); + + auto* item = new QGVImage(); + item->setGeometry(Helpers::randRect(mMap, itemTargetArea)); + item->loadImage(mImage); + + mLayer->addItem(item); + + updateListOfItems(); +} + +void MainWindow::addIcon() +{ + const QGV::GeoRect itemTargetArea = mMap->getProjection()->projToGeo(mMap->getCamera().projRect()); + + auto* item = new QGVIcon(); + item->setGeometry(Helpers::randPos(itemTargetArea)); + item->loadImage(mIcon); + + mLayer->addItem(item); + + updateListOfItems(); +} + +void MainWindow::removeLast() +{ + if (mLayer->countItems() == 0) { + return; + } + + mLayer->removeItem(mLayer->getItem(mLayer->countItems() - 1)); + + updateListOfItems(); +} + +void MainWindow::updateListOfItems() +{ + mList->clear(); + + for (int i = 0; i < mLayer->countItems(); i++) { + QGVItem* item = mLayer->getItem(i); + mList->addItem(item->metaObject()->className()); + } +} diff --git a/samples/raster/mainwindow.h b/samples/raster/mainwindow.h new file mode 100644 index 0000000..3cdd74e --- /dev/null +++ b/samples/raster/mainwindow.h @@ -0,0 +1,56 @@ +/*************************************************************************** + * 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. + ****************************************************************************/ + +#pragma once + +#include +#include +#include + +#include +#include + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(); + ~MainWindow(); + + QGV::GeoRect targetArea() const; + + QGroupBox* createOptionsList(); + QGroupBox* createItemsList(); + + void preloadImages(); + void loadImage(QImage& dest, QUrl url); + + void addImage(); + void addIcon(); + void removeLast(); + void updateListOfItems(); + +private: + QGVMap* mMap; + QGVLayer* mLayer; + QListWidget* mList; + + QImage mImage; + QImage mIcon; +}; diff --git a/samples/raster/raster.pro b/samples/raster/raster.pro new file mode 100644 index 0000000..84634ed --- /dev/null +++ b/samples/raster/raster.pro @@ -0,0 +1,15 @@ +TARGET = qgeoview-samples-raster +TEMPLATE = app +CONFIG-= console + +QT += gui widgets network + +include(../lib.pri) +include(../shared.pri) + +SOURCES += \ + main.cpp \ + mainwindow.cpp + +HEADERS += \ + mainwindow.h diff --git a/samples/shared/helpers.cpp b/samples/shared/helpers.cpp index 1b40f2e..2359658 100644 --- a/samples/shared/helpers.cpp +++ b/samples/shared/helpers.cpp @@ -41,6 +41,13 @@ QGV::GeoRect Helpers::randRect(QGVMap* geoMap, const QGV::GeoRect& targetArea, i return randRect(geoMap, targetArea, size); } +QGV::GeoRect Helpers::randRect(QGVMap* geoMap, const QGV::GeoRect& targetArea) +{ + const auto baseGeo1 = randPos(targetArea); + const auto baseGeo2 = randPos(targetArea); + return QGV::GeoRect{ baseGeo1.latitude(), baseGeo1.longitude(), baseGeo2.latitude(), baseGeo2.longitude() }; +} + QGV::GeoPos Helpers::randPos(const QGV::GeoRect& targetArea) { const double latRange = targetArea.latTop() - targetArea.latBottom(); diff --git a/samples/shared/helpers.h b/samples/shared/helpers.h index 286c6b3..641aaac 100644 --- a/samples/shared/helpers.h +++ b/samples/shared/helpers.h @@ -26,6 +26,7 @@ void setupCachedNetworkAccessManager(QObject* parent); int randomInt(int lowest, int highest); QGV::GeoRect randRect(QGVMap* geoMap, const QGV::GeoRect& targetArea, const QSizeF& size); QGV::GeoRect randRect(QGVMap* geoMap, const QGV::GeoRect& targetArea, int baseSize); +QGV::GeoRect randRect(QGVMap* geoMap, const QGV::GeoRect& targetArea); QGV::GeoPos randPos(const QGV::GeoRect& targetArea); QSizeF randSize(int baseSize); }