diff --git a/doc/qgsquick.dox b/doc/qgsquick.dox index 5276a7f45052..6a5e7acbd3de 100644 --- a/doc/qgsquick.dox +++ b/doc/qgsquick.dox @@ -13,6 +13,15 @@ QGIS Quick consists of a Qt plugin that provides the QML components and of a sha \subsection qgsquick_overview_widgets QML Classes \subsubsection qgsquick_overview_widgets_mapcanvas MapCanvas +Similarly to QgsMapCanvas, this component can be used for displaying GIS data on a canvas. See also QgsQuickMapCanvasMap. +\subsubsection qgsquick_overview_widgets_scalebar ScaleBar +A QML component that shows the scale ratio between its length and distance on the MapCanvas. There are predefined rounded values +for several zooming levels with 'm' or 'km' postfixes. After any zoom in/out event on canvas recalculates its properties and updates +text. See also QgsQuickScaleBarKit. + +\subsubsection qgsquick_overview_widgets_messagelog MessageLog +A simple panel which can be used for publishing logs messages to a user such as basic information about the application or its status. +See also QgsQuickMessageLogModel. \section qgsquick_styling Styling diff --git a/src/quickgui/CMakeLists.txt b/src/quickgui/CMakeLists.txt index 041e8a7b25c1..e433c08f8713 100644 --- a/src/quickgui/CMakeLists.txt +++ b/src/quickgui/CMakeLists.txt @@ -3,6 +3,8 @@ SET(QGIS_QUICK_GUI_MOC_HDRS qgsquickmapcanvasmap.h qgsquickmapsettings.h + qgsquickmessagelogmodel.h + qgsquickscalebarkit.h qgsquickutils.h ) @@ -12,6 +14,8 @@ SET(QGIS_QUICK_GUI_HDRS SET(QGIS_QUICK_GUI_SRC qgsquickmapcanvasmap.cpp qgsquickmapsettings.cpp + qgsquickmessagelogmodel.cpp + qgsquickscalebarkit.cpp qgsquickutils.cpp ) diff --git a/src/quickgui/plugin/CMakeLists.txt b/src/quickgui/plugin/CMakeLists.txt index 691a2b84f724..4513599577a1 100644 --- a/src/quickgui/plugin/CMakeLists.txt +++ b/src/quickgui/plugin/CMakeLists.txt @@ -11,6 +11,8 @@ SET(QGIS_QUICK_PLUGIN_SRC SET(QGIS_QUICK_PLUGIN_RESOURCES qgsquickmapcanvas.qml + qgsquickmessagelog.qml + qgsquickscalebar.qml qmldir ) @@ -37,7 +39,7 @@ INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/src/core/metadata ${CMAKE_SOURCE_DIR}/src/core/expression ${CMAKE_SOURCE_DIR}/src/quickgui - + ${CMAKE_BINARY_DIR}/src/core ${CMAKE_BINARY_DIR}/src/quickgui ) @@ -98,13 +100,14 @@ IF(QMLPLUGINDUMP_FOUND) # Extract QML Types Info from our QML plugin. This is useful for development with Qt Creator as it allows # Qt Creator understand also the C++ classes registered in the plugin and thus available in QML code SET(QGIS_QUICK_PLUGIN_TYPEINFO ${QGIS_QUICK_PLUGIN_RUNTIME_DIR}/qgsquick.qmltypes) + SET(QGIS_QUICK_VERSION 0.1) ADD_CUSTOM_COMMAND( TARGET qgis_quick_plugin COMMAND ${CMAKE_COMMAND} -E make_directory ${QGIS_QUICK_TYPEINFO_GENERATE_DIR} COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/qmldir ${QGIS_QUICK_TYPEINFO_GENERATE_DIR} COMMAND ${CMAKE_COMMAND} -E copy $ ${QGIS_QUICK_TYPEINFO_GENERATE_DIR} COMMAND ${QMLPLUGINDUMP_EXECUTABLE} - ARGS QgsQuick 0.1 . -v --output ${QGIS_QUICK_PLUGIN_TYPEINFO} + ARGS QgsQuick ${QGIS_QUICK_VERSION} . -v --output ${QGIS_QUICK_PLUGIN_TYPEINFO} WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" POST_BUILD ) diff --git a/src/quickgui/plugin/qgsquickmessagelog.qml b/src/quickgui/plugin/qgsquickmessagelog.qml new file mode 100644 index 000000000000..536550897d24 --- /dev/null +++ b/src/quickgui/plugin/qgsquickmessagelog.qml @@ -0,0 +1,98 @@ +/*************************************************************************** + qgsquickmessagelog.qml + -------------------------------------- + Date : January 2018 + Copyright : (C) 2018 by Peter Petrik + Email : zilolv at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +import QtQuick.Controls 2.0 +import QtQuick 2.5 +import QgsQuick 0.1 as QgsQuick + + +/** + * \brief A component that shows all log messages. The component shows + * the items from QgsQuickMessageLogModel. + */ +Item { + /** + * Input for messages. Must be connected before usage from QgsQuick.MessageLog. + * + * See also QgsQuickMessageLogModel + */ + property alias model: table.model + /** + * Background color + */ + property color bgColor: "white" + /** + * Separator color + */ + property color separatorColor: "gray" + + /** + * Separator width + */ + property int separatorSize: 1 * QgsQuick.Utils.dp + /** + * True if there are unread messages in the list. All messages + * are marked read when the widget receives visibility. + */ + property bool unreadMessages: false + + id: item + + /** + * List containing message logs + */ + ListView { + id: table + anchors.fill: parent + + delegate: Column { + Text { + text: MessageTag + font.bold: true + } + + Text { + text: Message + width: table.width + wrapMode: Text.WordWrap + } + + /** + * Message separator. + */ + Rectangle { + color: item.separatorColor + height: item.separatorSize + width: table.width + } + } + } + + /** + * Handles adding new messages to the list. + */ + Connections { + target: model + + onRowsInserted: { + if (!visible) + unreadMessages = true + } + } + + onVisibleChanged: { + if (visible) + unreadMessages = false + } +} diff --git a/src/quickgui/plugin/qgsquickplugin.cpp b/src/quickgui/plugin/qgsquickplugin.cpp index 22b1fe10c158..4e38ee1125e1 100644 --- a/src/quickgui/plugin/qgsquickplugin.cpp +++ b/src/quickgui/plugin/qgsquickplugin.cpp @@ -31,7 +31,9 @@ #include "qgsquickmapcanvasmap.h" #include "qgsquickmapsettings.h" +#include "qgsquickmessagelogmodel.h" #include "qgsquickplugin.h" +#include "qgsquickscalebarkit.h" #include "qgsquickutils.h" static QObject *_utilsProvider( QQmlEngine *engine, QJSEngine *scriptEngine ) @@ -55,11 +57,13 @@ void QgsQuickPlugin::registerTypes( const char *uri ) qmlRegisterType< QgsProject >( uri, 0, 1, "Project" ); qmlRegisterType< QgsQuickMapCanvasMap >( uri, 0, 1, "MapCanvasMap" ); qmlRegisterType< QgsQuickMapSettings >( uri, 0, 1, "MapSettings" ); + qmlRegisterType< QgsQuickMessageLogModel >( uri, 0, 1, "MessageLogModel" ); + qmlRegisterType< QgsQuickScaleBarKit >( uri, 0, 1, "ScaleBarKit" ); qmlRegisterType< QgsVectorLayer >( uri, 0, 1, "VectorLayer" ); qmlRegisterSingletonType< QgsQuickUtils >( uri, 0, 1, "Utils", _utilsProvider ); - qmlRegisterUncreatableType< QgsRelationManager >( uri, 0, 1, "RelationManager", "The relation manager is available from the Project. Try `qgisProject.relationManager`" ); - qmlRegisterUncreatableType< QgsMessageLog >( uri, 0, 1, "QgsMessageLog", "Expose MessageLevel" ); + //qmlRegisterUncreatableType< QgsRelationManager >( uri, 0, 1, "RelationManager", "The relation manager is available from the Project. Try `qgisProject.relationManager`" ); + //qmlRegisterUncreatableType< QgsMessageLog >( uri, 0, 1, "QgsMessageLog", "Expose MessageLevel" ); } diff --git a/src/quickgui/plugin/qgsquickscalebar.qml b/src/quickgui/plugin/qgsquickscalebar.qml new file mode 100644 index 000000000000..f5468e538d86 --- /dev/null +++ b/src/quickgui/plugin/qgsquickscalebar.qml @@ -0,0 +1,141 @@ +/*************************************************************************** + qgsquickscalebar.qml + -------------------------------------- + Date : Nov 2017 + Copyright : (C) 2017 by Peter Petrik + Email : zilolv at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +import QtQuick 2.7 +import QtQuick.Controls 2.2 +import QgsQuick 0.1 as QgsQuick + +Item { + id: scaleBar + + /** + * The mapSettings property contains configuration for rendering of the map. + * + * Must be connected before usage from QgsQuick.MapCanvas::mapSettings + */ + property alias mapSettings: scaleBarKit.mapSettings + /** + * Preferred width of scalebar in pixels on the screen. Defaults set to 300. + * + * barWidth is calculated to be close to preferred width, but has "nice" textual + * representation + */ + property alias preferredWidth: scaleBarKit.preferredWidth + /** + * Kit for all calculation of width and text of the scalebar + * + * See also QgsQuickMapCanvasMap::mapSettings + */ + property QgsQuick.ScaleBarKit scaleBarKit: QgsQuick.ScaleBarKit { + id: scaleBarKit + } + /** + * Reserved text width. + */ + property int textWidth: fontMetrics.averageCharacterWidth * 8 + /** + * Text color + */ + property color barColor: "white" + /** + * Background color + */ + property color barBackgroundColor: "grey" + /** + * Opacity + */ + property double barOpacity: 0.8 + /** + * Textual representation of the bar length (e.g 800 m) + */ + property string barText: scaleBarKit.distance + " " + scaleBarKit.units + /** + * Calculated width of bar in pixels + */ + property int barWidth: scaleBarKit.width + /** + * Size of scalebar line (height of bar) + */ + property int lineWidth: 5 * QgsQuick.Utils.dp + + width: textWidth + barWidth + + MouseArea { + anchors.fill: background + onClicked: { + animation.restart() + } + } + + NumberAnimation { + id: animation + target: scaleBar + property: "barWidth" + to: 200 + duration: 1000 + } + + Rectangle { + id: background + color: scaleBar.barBackgroundColor + opacity: scaleBar.barOpacity + width: parent.width + height: parent.height + } + + FontMetrics { + id: fontMetrics + font: text.font + } + + Row { + opacity: 1 + spacing: 0 + + Text { + id: text + width: textWidth + height: scaleBar.height + text: barText + color: barColor + font.pixelSize: scaleBar.height - 2 * scaleBar.lineWidth + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + Rectangle { + id: leftBar + width: scaleBar.lineWidth + height: scaleBar.height - 20 * QgsQuick.Utils.dp + y: (scaleBar.height - leftBar.height) / 2 + color: barColor + opacity: 1 + } + + Rectangle { + width: scaleBar.width - text.width - 15 * QgsQuick.Utils.dp + height: scaleBar.lineWidth + y: (scaleBar.height - scaleBar.lineWidth) / 2 + color: barColor + } + + Rectangle { + id: rightBar + width: scaleBar.lineWidth + height: scaleBar.height - 20 * QgsQuick.Utils.dp + y: (scaleBar.height - leftBar.height) / 2 + color: barColor + } + } +} diff --git a/src/quickgui/plugin/qmldir b/src/quickgui/plugin/qmldir index ac0dc7a73637..567a64feb59e 100644 --- a/src/quickgui/plugin/qmldir +++ b/src/quickgui/plugin/qmldir @@ -14,5 +14,7 @@ module QgsQuick plugin qgis_quick_plugin MapCanvas 0.1 qgsquickmapcanvas.qml +ScaleBar 0.1 qgsquickscalebar.qml +MessageLog 0.1 qgsquickmessagelog.qml typeinfo qgsquick.qmltypes diff --git a/src/quickgui/qgsquickmessagelogmodel.cpp b/src/quickgui/qgsquickmessagelogmodel.cpp new file mode 100644 index 000000000000..dc168ab1383f --- /dev/null +++ b/src/quickgui/qgsquickmessagelogmodel.cpp @@ -0,0 +1,76 @@ +/*************************************************************************** + qgsquickmessagelogmodel.cpp + -------------------------------------- + date : 13.7.2016 + copyright : (C) 2016 by Matthias Kuhn + email : matthias (at) opengis.ch + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgis.h" +#include "qgslogger.h" +#include "qgsmessagelog.h" +#include "qgsapplication.h" + +#include "qgsquickmessagelogmodel.h" + +QgsQuickMessageLogModel::QgsQuickMessageLogModel( QObject *parent ) + : QAbstractListModel( parent ) +{ + connect( QgsApplication::messageLog(), static_cast( &QgsMessageLog::messageReceived ), this, &QgsQuickMessageLogModel::onMessageReceived ); +} + +QgsQuickMessageLogModel::LogMessage QgsQuickMessageLogModel::logMessage( const QString &tag, const QString &message, Qgis::MessageLevel level ) +{ + LogMessage msg; + msg.tag = tag; + msg.message = message; + msg.level = level; + + return msg; +} + +QHash QgsQuickMessageLogModel::roleNames() const +{ + QHash roles = QAbstractListModel::roleNames(); + roles[MessageRole] = QByteArrayLiteral( "Message" ); + roles[MessageTagRole] = QByteArrayLiteral( "MessageTag" ); + roles[MessageLevelRole] = QByteArrayLiteral( "MessageLevel" ); + + return roles; +} + +int QgsQuickMessageLogModel::rowCount( const QModelIndex &parent ) const +{ + Q_UNUSED( parent ) + return mMessages.size(); +} + +QVariant QgsQuickMessageLogModel::data( const QModelIndex &index, int role ) const +{ + if ( index.row() >= mMessages.size() ) + return QVariant(); + + if ( role == MessageRole ) + return mMessages.at( index.row() ).message; + else if ( role == MessageTagRole ) + return mMessages.at( index.row() ).tag; + else if ( role == MessageLevelRole ) + return mMessages.at( index.row() ).level; + + return QVariant(); +} + +void QgsQuickMessageLogModel::onMessageReceived( const QString &message, const QString &tag, Qgis::MessageLevel level ) +{ + beginInsertRows( QModelIndex(), 0, 0 ); + mMessages.prepend( logMessage( tag, message, level ) ); + QgsDebugMsg( QStringLiteral( "Next message %1 : %2" ).arg( tag, message ) ); + endInsertRows(); +} diff --git a/src/quickgui/qgsquickmessagelogmodel.h b/src/quickgui/qgsquickmessagelogmodel.h new file mode 100644 index 000000000000..4b684568455f --- /dev/null +++ b/src/quickgui/qgsquickmessagelogmodel.h @@ -0,0 +1,80 @@ +/*************************************************************************** + qgsquickmessagelogmodel.h + -------------------------------------- + date : 13.7.2016 + copyright : (C) 2016 by Matthias Kuhn + email : matthias (at) opengis.ch + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSQUICKMESSAGELOGMODEL_H +#define QGSQUICKMESSAGELOGMODEL_H + +#include +#include +#include + +#include "qgis.h" +#include "qgsmessagelog.h" + +#include "qgis_quick.h" + +/** + * \ingroup quick + * + * This model will connect to the QgsMessageLog singleton and store any + * messages received. Can be used as a model for QListView, + * for example QgsQuick.MessageLog (QML only) + * + * \note QML Type: MessageLogModel + * + * \sa QgsMessageLog + * + * \since QGIS 3.2 + */ +class QUICK_EXPORT QgsQuickMessageLogModel : public QAbstractListModel +{ + Q_OBJECT + + struct LogMessage + { + LogMessage() = default; + + QString tag; + QString message; + Qgis::MessageLevel level; + }; + + enum Roles + { + MessageRole = Qt::UserRole, + MessageTagRole, + MessageLevelRole + }; + + public: + //! Create new message log model + QgsQuickMessageLogModel( QObject *parent = nullptr ); + + QHash roleNames() const override; + int rowCount( const QModelIndex &parent ) const override; + QVariant data( const QModelIndex &index, int role ) const override; + + private slots: + void onMessageReceived( const QString &message, const QString &tag, Qgis::MessageLevel level ); + + private: + //! LogMessage factory + LogMessage logMessage( const QString &tag, const QString &message, Qgis::MessageLevel level ); + + //! Storage of all messages. + QVector mMessages; +}; + +#endif // QGSQUICKMESSAGELOGMODEL_H diff --git a/src/quickgui/qgsquickscalebarkit.cpp b/src/quickgui/qgsquickscalebarkit.cpp new file mode 100644 index 000000000000..4d646c94bbe2 --- /dev/null +++ b/src/quickgui/qgsquickscalebarkit.cpp @@ -0,0 +1,114 @@ +/*************************************************************************** + qgsquickscalebarkit.cpp + -------------------------------------- + Date : Nov 2017 + Copyright : (C) 2017 by Peter Petrik + Email : zilolv at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include +#include + +#include "qgsdistancearea.h" +#include "qgspointxy.h" + +#include "qgsquickmapsettings.h" +#include "qgsquickscalebarkit.h" +#include "qgsquickutils.h" +#include "qgsunittypes.h" + +QgsQuickScaleBarKit::QgsQuickScaleBarKit( QObject *parent ) + : QObject( parent ) + , mPreferredWidth( 300 ) + , mWidth( mPreferredWidth ) + , mDistance( 0 ) + , mUnits( "" ) +{ + connect( this, &QgsQuickScaleBarKit::mapSettingsChanged, this, &QgsQuickScaleBarKit::updateScaleBar ); + connect( this, &QgsQuickScaleBarKit::preferredWidthChanged, this, &QgsQuickScaleBarKit::updateScaleBar ); +} + +void QgsQuickScaleBarKit::setMapSettings( QgsQuickMapSettings *mapSettings ) +{ + if ( mMapSettings == mapSettings ) + return; + + // If we have already something connected, disconnect it! + if ( mMapSettings ) + { + disconnect( mMapSettings, nullptr, this, nullptr ); + } + + mMapSettings = mapSettings; + + // Connect all signals to change scale bar when needed! + if ( mMapSettings ) + { + connect( mMapSettings, &QgsQuickMapSettings::extentChanged, this, &QgsQuickScaleBarKit::updateScaleBar ); + connect( mMapSettings, &QgsQuickMapSettings::destinationCrsChanged, this, &QgsQuickScaleBarKit::updateScaleBar ); + connect( mMapSettings, &QgsQuickMapSettings::mapUnitsPerPixelChanged, this, &QgsQuickScaleBarKit::updateScaleBar ); + connect( mMapSettings, &QgsQuickMapSettings::visibleExtentChanged, this, &QgsQuickScaleBarKit::updateScaleBar ); + connect( mMapSettings, &QgsQuickMapSettings::outputSizeChanged, this, &QgsQuickScaleBarKit::updateScaleBar ); + connect( mMapSettings, &QgsQuickMapSettings::outputDpiChanged, this, &QgsQuickScaleBarKit::updateScaleBar ); + } + + emit mapSettingsChanged(); +} + +int QgsQuickScaleBarKit::width() const +{ + return mWidth; +} + +QString QgsQuickScaleBarKit::units() const +{ + return mUnits; +} + +int QgsQuickScaleBarKit::distance() const +{ + return mDistance; +} + +void QgsQuickScaleBarKit::updateScaleBar() +{ + if ( !mMapSettings ) + return; + + double dist = QgsQuickUtils().screenUnitsToMeters( mMapSettings, mPreferredWidth ); // meters + if ( dist > 1000.0 ) + { + dist = dist / 1000.0; // meters to kilometers + mUnits = QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::DistanceKilometers ); + } + else + { + mUnits = QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::DistanceMeters ); + } + + // we want to show nice round distances e.g. 200 km instead of e.g. 273 km + // so we determine which "nice" number to use and also update the scale bar + // length accordingly. First digit will be 1, 2 or 5, the rest will be zeroes. + int digits = int( floor( log10( ( dist ) ) ) ); // number of digits after first one + double base = pow( 10, digits ); // e.g. for 1234 this will be 1000 + double first_digit = dist / base; // get the first digit + int round_digit; + if ( first_digit < 2 ) + round_digit = 1; + else if ( first_digit < 5 ) + round_digit = 2; + else + round_digit = 5; + + mDistance = int( round_digit * base ); + mWidth = int( mPreferredWidth * mDistance / dist ); + + emit scaleBarChanged(); +} diff --git a/src/quickgui/qgsquickscalebarkit.h b/src/quickgui/qgsquickscalebarkit.h new file mode 100644 index 000000000000..6fd6751b62ac --- /dev/null +++ b/src/quickgui/qgsquickscalebarkit.h @@ -0,0 +1,123 @@ +/*************************************************************************** + qgsquickscalebarkit.h + -------------------------------------- + Date : Nov 2017 + Copyright : (C) 2017 by Peter Petrik + Email : zilolv at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSQUICKSCALEBARKIT_H +#define QGSQUICKSCALEBARKIT_H + +#include +#include + +#include "qgis_quick.h" +#include "qgsquickutils.h" + +class QgsQuickMapSettings; + +/** + * \ingroup quick + * + * The class QgsQuickScaleBarKit encapsulates the utilies to calculate + * scale bar properties + * + * It requires connection to mapSettings of the active canvas to automatically + * update text and width + * + * From preferred width in pixel, it calculates the width (pixel) of scalebar + * distance in meters or kilometers (int) rounded to "nice" number (e.g. 72.4 to 100) + * and units text (e.g. km) + * + * \note QML Type: ScaleBarKit + * + * \since QGIS 3.2 + */ +class QUICK_EXPORT QgsQuickScaleBarKit : public QObject +{ + Q_OBJECT + + /** + * Associated map settings. Should be initialized before the first use from mapcanvas map settings. + */ + Q_PROPERTY( QgsQuickMapSettings *mapSettings MEMBER mMapSettings WRITE setMapSettings NOTIFY mapSettingsChanged ) + + /** + * Preferred width of scalebar in pixels. Default set to 300. + */ + Q_PROPERTY( int preferredWidth MEMBER mPreferredWidth NOTIFY preferredWidthChanged ) + + /** + * Units of distance (e.g. km or m) Read-only (result). + */ + Q_PROPERTY( QString units READ units NOTIFY scaleBarChanged ) + + /** + * Distance rounded to "nice" number (e.g. 100, 20) corresponding to width. To be used with units property for labels. Read-only (result). + */ + Q_PROPERTY( int distance READ distance NOTIFY scaleBarChanged ) + + /** + * Calculated width of scalebar in pixels representing distance + units. Differs minimum possible from preferredWidth to + * get "nice" distance number. + */ + Q_PROPERTY( int width READ width NOTIFY scaleBarChanged ) + + public: + //! create new scale bar kit + explicit QgsQuickScaleBarKit( QObject *parent = nullptr ); + ~QgsQuickScaleBarKit() = default; + + //! \copydoc QgsQuickScaleBarKit::mapSettings + void setMapSettings( QgsQuickMapSettings *mapSettings ); + + //! \copydoc QgsQuickScaleBarKit::width + int width() const; + + /** + * \copydoc QgsQuickScaleBarKit::units + * \see QgsQuickScaleBarKit::units() + */ + int distance() const; + + /** + * \copydoc QgsQuickScaleBarKit::units + * \see QgsQuickScaleBarKit::distance() + */ + QString units() const; + + signals: + + /** + * width, distance and/or units changed + */ + void scaleBarChanged(); + + //! \copydoc QgsQuickScaleBarKit::mapSettings + void mapSettingsChanged(); + + //! \copydoc QgsQuickScaleBarKit::preferredWidth + void preferredWidthChanged(); + + public slots: + //! recalculate width, distance and units. + void updateScaleBar(); + + private: + QgsQuickMapSettings *mMapSettings = nullptr; // not owned + int mPreferredWidth; // pixels + int mWidth; // pixels + int mDistance; // in meters or kilometers, rounded + QString mUnits; // km or m +}; + + +#endif // QGSQUICKSCALEBARKIT_H diff --git a/src/quickgui/qgsquickutils.cpp b/src/quickgui/qgsquickutils.cpp index bd559520fbd2..7ad60f6d4783 100644 --- a/src/quickgui/qgsquickutils.cpp +++ b/src/quickgui/qgsquickutils.cpp @@ -16,11 +16,8 @@ #include #include "qgis.h" -#include "qgscoordinatereferencesystem.h" -#include "qgscoordinatetransform.h" #include "qgsdistancearea.h" #include "qgslogger.h" -#include "qgsvectorlayer.h" #include "qgsquickmapsettings.h" #include "qgsquickutils.h" @@ -33,6 +30,28 @@ QgsQuickUtils::QgsQuickUtils( QObject *parent ) { } +double QgsQuickUtils::screenUnitsToMeters( QgsQuickMapSettings *mapSettings, int baseLengthPixels ) const +{ + if ( mapSettings == nullptr ) return 0.0; + + QgsDistanceArea mDistanceArea; + mDistanceArea.setEllipsoid( QStringLiteral( "WGS84" ) ); + mDistanceArea.setSourceCrs( mapSettings->destinationCrs(), mapSettings->transformContext() ); + + // calculate the geographic distance from the central point of extent + // to the specified number of points on the right side + QSize s = mapSettings->outputSize(); + QPoint pointCenter( s.width() / 2, s.height() / 2 ); + QgsPointXY p1 = mapSettings->screenToCoordinate( pointCenter ); + QgsPointXY p2 = mapSettings->screenToCoordinate( pointCenter + QPoint( baseLengthPixels, 0 ) ); + return mDistanceArea.measureLine( p1, p2 ); +} + +void QgsQuickUtils::logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level ) +{ + QgsMessageLog::logMessage( message, tag, level ); +} + QString QgsQuickUtils::dumpScreenInfo() const { QRect rec = QApplication::desktop()->screenGeometry(); diff --git a/src/quickgui/qgsquickutils.h b/src/quickgui/qgsquickutils.h index 53499ab849fd..b17b162a2ef1 100644 --- a/src/quickgui/qgsquickutils.h +++ b/src/quickgui/qgsquickutils.h @@ -21,8 +21,13 @@ #include #include "qgis.h" +#include "qgsmessagelog.h" + +#include "qgsquickmapsettings.h" #include "qgis_quick.h" +class QgsCoordinateReferenceSystem; + /** * \ingroup quick * @@ -58,6 +63,16 @@ class QUICK_EXPORT QgsQuickUtils: public QObject //! \copydoc QgsQuickUtils::dp qreal screenDensity() const; + /** + * Calculate the distance in meter representing baseLengthPixels pixels on the screen based on the current map settings. + */ + Q_INVOKABLE double screenUnitsToMeters( QgsQuickMapSettings *mapSettings, int baseLengthPixels ) const; + + //! Log message in QgsMessageLog + Q_INVOKABLE void logMessage( const QString &message, + const QString &tag = QString( "QgsQuick" ), + Qgis::MessageLevel level = Qgis::Warning ); + /** * Returns a string with information about screen size and resolution * diff --git a/tests/src/quickgui/CMakeLists.txt b/tests/src/quickgui/CMakeLists.txt index af99c766567b..4658b776f7a0 100644 --- a/tests/src/quickgui/CMakeLists.txt +++ b/tests/src/quickgui/CMakeLists.txt @@ -79,6 +79,7 @@ ENDMACRO (ADD_QGIS_TEST) # Tests: ADD_QGIS_TEST(qgsquickutils testqgsquickutils.cpp) +ADD_QGIS_TEST(qgsquickscalebarkit testqgsquickscalebarkit.cpp) ############################################################# diff --git a/tests/src/quickgui/app/main.qml b/tests/src/quickgui/app/main.qml index 7e6cf8bd9121..c29f5a320975 100644 --- a/tests/src/quickgui/app/main.qml +++ b/tests/src/quickgui/app/main.qml @@ -37,4 +37,36 @@ ApplicationWindow { console.log("clicked:" + screenPoint) } } + + Drawer { + id: logPanel + visible: true + modal: true + interactive: true + height: window.height + width: QgsQuick.Utils.dp * 700 + edge: Qt.RightEdge + z: 2 // make sure items from here are on top of the Z-order + + background: Rectangle { + color: "white" + } + + QgsQuick.MessageLog { + id: messageLog + width: parent.width + height: parent.height + model: QgsQuick.MessageLogModel {} + visible: true + } + } + + QgsQuick.ScaleBar { + id: scaleBar + y: window.height - height + height: 50 + mapSettings: mapCanvas.mapSettings + preferredWidth: 115 * QgsQuick.Utils.dp + z: 1 + } } diff --git a/tests/src/quickgui/testqgsquickscalebarkit.cpp b/tests/src/quickgui/testqgsquickscalebarkit.cpp new file mode 100644 index 000000000000..5c7ac8cd5829 --- /dev/null +++ b/tests/src/quickgui/testqgsquickscalebarkit.cpp @@ -0,0 +1,63 @@ +/*************************************************************************** + testqgsquickscalebarkit.cpp.cpp + -------------------------------------- + Date : May 2018 + Copyright : (C) 2018 by Viktor Sklencar + Email : vsklencar at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +#include +#include +#include + +#include "qgsapplication.h" +#include "qgstest.h" +#include "qgis.h" + +#include "qgsquickutils.h" +#include "qgsquickmapcanvasmap.h" +#include "qgsquickscalebarkit.h" + + +class TestQgsQuickScaleBarKit: public QObject +{ + Q_OBJECT + private slots: + void init() {} // will be called before each testfunction is executed. + void cleanup() {} // will be called after every testfunction. + + void updateScaleBar(); // test text of scalebar after update. +}; + +void TestQgsQuickScaleBarKit::updateScaleBar() +{ + QgsCoordinateReferenceSystem crsGPS = QgsCoordinateReferenceSystem::fromEpsgId( 4326 ); + QVERIFY( crsGPS.authid() == "EPSG:4326" ); + + QgsRectangle extent = QgsRectangle( 49, 16, 50, 17 ); + QgsQuickMapCanvasMap canvas; + + QgsQuickMapSettings *ms = canvas.mapSettings(); + ms->setDestinationCrs( crsGPS ); + ms->setExtent( extent ); + ms->setOutputSize( QSize( 1000, 500 ) ); + + QgsQuickScaleBarKit kit; + kit.setMapSettings( ms ); + QVERIFY( kit.units() == QString( "km" ) ); + QVERIFY( kit.distance() == 50 ); + + qreal scale = 0.005; + canvas.zoom( extent.center().toQPointF(), scale ); + QVERIFY( kit.units() == QString( "m" ) ); + QVERIFY( kit.distance() == 200 ); +} + +QGSTEST_MAIN( TestQgsQuickScaleBarKit ) +#include "testqgsquickscalebarkit.moc" diff --git a/tests/src/quickgui/testqgsquickutils.cpp b/tests/src/quickgui/testqgsquickutils.cpp index a83f7a9e5c58..425545ea0dc0 100644 --- a/tests/src/quickgui/testqgsquickutils.cpp +++ b/tests/src/quickgui/testqgsquickutils.cpp @@ -30,8 +30,8 @@ class TestQgsQuickUtils: public QObject void cleanup() {} // will be called after every testfunction. void screen_density(); - void dump_screen_info(); + void screenUnitsToMeters(); private: QgsQuickUtils utils; @@ -49,5 +49,18 @@ void TestQgsQuickUtils::dump_screen_info() QVERIFY( utils.dumpScreenInfo().contains( QStringLiteral( "%1" ).arg( dp ) ) ); } +void TestQgsQuickUtils::screenUnitsToMeters() +{ + QgsCoordinateReferenceSystem crsGPS = QgsCoordinateReferenceSystem::fromEpsgId( 4326 ); + QVERIFY( crsGPS.authid() == "EPSG:4326" ); + + QgsQuickMapSettings ms; + ms.setDestinationCrs( crsGPS ); + ms.setExtent( QgsRectangle( 49, 16, 50, 17 ) ); + ms.setOutputSize( QSize( 1000, 500 ) ); + double sutm = utils.screenUnitsToMeters( &ms, 1 ); + QVERIFY( fabs( sutm - 213 ) < 1.0 ); +} + QGSTEST_MAIN( TestQgsQuickUtils ) #include "testqgsquickutils.moc"