summaryrefslogtreecommitdiffstats
path: root/examples/sensors
diff options
context:
space:
mode:
authorJuha Vuolle <juha.vuolle@qt.io>2023-02-17 13:40:13 +0200
committerJuha Vuolle <juha.vuolle@qt.io>2023-02-22 08:37:59 +0200
commitf5426ddda0c8e022d55290de70f96cb4db1801bb (patch)
treead5cf038654f1a69ad1e86aea12bc1513a699202 /examples/sensors
parent20373cfd4019c66884fb63a4316b1c60ede089ca (diff)
Move sensor_explorer QML example to manual tests
The example is useful as a sensor testing tool, but less necessary as an example. The primary demonstrative element of the example was how to iterate the available sensors, which is covered in a documentation snippet (followup commit). This commit also renames the pre-existing widget-based sensor_explorer manual test to avoid name conflicts, as well as removes the qdoc and qmake support from the now-a-manual-test application. Task-number: QTBUG-110939 Pick-to: 6.5 Change-Id: I422f62f852d0a7e40a76f555ec8aa98404164f7a Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
Diffstat (limited to 'examples/sensors')
-rw-r--r--examples/sensors/CMakeLists.txt7
-rw-r--r--examples/sensors/sensor_explorer/CMakeLists.txt44
-rw-r--r--examples/sensors/sensor_explorer/doc/images/qtsensors-examples-sensor-explorer.pngbin47605 -> 0 bytes
-rw-r--r--examples/sensors/sensor_explorer/doc/src/sensor_explorer.qdoc118
-rw-r--r--examples/sensors/sensor_explorer/main.cpp20
-rw-r--r--examples/sensors/sensor_explorer/qml.qrc5
-rw-r--r--examples/sensors/sensor_explorer/sensor_explorer.pro22
-rw-r--r--examples/sensors/sensor_explorer/sensor_explorer.qml127
-rw-r--r--examples/sensors/sensor_explorer/sensormodels.cpp191
-rw-r--r--examples/sensors/sensor_explorer/sensormodels.h63
-rw-r--r--examples/sensors/sensors.pro4
11 files changed, 2 insertions, 599 deletions
diff --git a/examples/sensors/CMakeLists.txt b/examples/sensors/CMakeLists.txt
index ef323eff..ecbd35fb 100644
--- a/examples/sensors/CMakeLists.txt
+++ b/examples/sensors/CMakeLists.txt
@@ -1,9 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-if(TARGET Qt::Quick)
- qt_internal_add_example(sensor_explorer)
- if(TARGET Qt::Svg)
- qt_internal_add_example(sensorsshowcase)
- endif()
+if(TARGET Qt::Quick AND TARGET Qt::Svg)
+ qt_internal_add_example(sensorsshowcase)
endif()
diff --git a/examples/sensors/sensor_explorer/CMakeLists.txt b/examples/sensors/sensor_explorer/CMakeLists.txt
deleted file mode 100644
index 33fc7ea8..00000000
--- a/examples/sensors/sensor_explorer/CMakeLists.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: BSD-3-Clause
-
-cmake_minimum_required(VERSION 3.16)
-project(sensor_explorer LANGUAGES CXX)
-
-set(CMAKE_AUTOMOC ON)
-
-if(NOT DEFINED INSTALL_EXAMPLESDIR)
- set(INSTALL_EXAMPLESDIR "examples")
-endif()
-
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/sensors/sensor_explorer")
-
-find_package(Qt6 REQUIRED COMPONENTS Qml Quick Sensors)
-
-qt_add_executable(sensor_explorer
- main.cpp
- sensormodels.cpp sensormodels.h
-)
-
-set_target_properties(sensor_explorer PROPERTIES
- WIN32_EXECUTABLE TRUE
- MACOSX_BUNDLE TRUE
-)
-
-target_link_libraries(sensor_explorer PUBLIC
- Qt::Qml
- Qt::Quick
- Qt::Sensors
-)
-
-qt_add_qml_module(sensor_explorer
- URI SensorModels
- VERSION 1.0
- QML_FILES sensor_explorer.qml
- NO_RESOURCE_TARGET_PATH
-)
-
-install(TARGETS sensor_explorer
- RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
- BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
- LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
-)
diff --git a/examples/sensors/sensor_explorer/doc/images/qtsensors-examples-sensor-explorer.png b/examples/sensors/sensor_explorer/doc/images/qtsensors-examples-sensor-explorer.png
deleted file mode 100644
index 830f9597..00000000
--- a/examples/sensors/sensor_explorer/doc/images/qtsensors-examples-sensor-explorer.png
+++ /dev/null
Binary files differ
diff --git a/examples/sensors/sensor_explorer/doc/src/sensor_explorer.qdoc b/examples/sensors/sensor_explorer/doc/src/sensor_explorer.qdoc
deleted file mode 100644
index f4d7c6bc..00000000
--- a/examples/sensors/sensor_explorer/doc/src/sensor_explorer.qdoc
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
-
-/*!
- \example sensor_explorer
- \title Qt Sensors - Explorer QML Example
- \ingroup qtsensors-examples
- \brief Demonstrates how to read the meta-data of available sensors.
-
- \image qtsensors-examples-sensor-explorer.png
-
- The example is implemented as a typical model-view application. The
- models are written with C++ and exposed to QML, and the views are
- implemented as QML types in the QML application.
-
- \section1 Exposing and Importing the Models
-
- The QML models written in C++ are exposed in the project build files
- as a \c SensorModels QML module.
-
- \e CMake:
- \code
- qt_add_qml_module(sensor_explorer
- URI SensorModels
- VERSION 1.0
- )
- \endcode
-
- \e qmake:
- \code
- CONFIG += qmltypes
- QML_IMPORT_NAME = SensorModels
- QML_IMPORT_MAJOR_VERSION = 1
- \endcode
-
- The individual model elements are exposed as part of the model
- code by using the \c QML_ELEMENT macro as illustrated here:
- \snippet sensor_explorer/sensormodels.h 0
-
- To access the models in the QML application, the module is imported
- by the application QML:
- \snippet sensor_explorer/sensor_explorer.qml 0
-
- \section1 Populating the Model of Available Sensors
-
- The \c AvailableSensorsModel is a list model that provides information on
- available sensors on the device. The model is populated once at the
- element's construction time:
-
- \snippet sensor_explorer/sensormodels.cpp 0
-
- The model's \c data() function returns a pointer to the requested sensor
- object.
-
- \snippet sensor_explorer/sensormodels.cpp 1
-
- Since the sensor (QSensor) is a QObject, the QML is then able to directly
- access all metaproperties and -functions directly.
-
- \note It would be possible to refresh the sensor list later at will, but for
- the simplicity of the example such functionality is not exposed to QML.
-
- \section1 Populating the Model of Sensor Properties
-
- The \c SensorPropertyModel is a table model that provides individual
- sensor's property-value pairs as columns. The column \c 0 provides the
- property's name and the column \c 1 provides the property's value. The
- population of the properties is done by reading the metadata of the sensors.
- The model reads both the sensor's metadata as well as the sensor's reading's
- metadata. The code below illustrates the reading of the \c reading metadata:
-
- \snippet sensor_explorer/sensormodels.cpp 2
-
- This metadata access allows providing the model data for all sensors
- without prior compile-time understanding of their properties.
-
- Once the metadata is set, the code then subscribes to the
- QSensor::readingChanged() signal to detect sensor reading changes.
- Upon such changes (for example a rotation value changes), the model data
- is updated accordingly.
-
- \section1 Viewing the Models
-
- The QML application is based on two views. The first view shows the available
- sensors as a selectable list. The second view shows the selected sensor's
- properties and their values. The delegates for viewing the individual items
- are simplistic \e {rectangle and text} items.
-
- Binding the two views functionally together is done by binding the property
- model's \c sensor property to the current selection of the available sensors
- model:
-
- \snippet sensor_explorer/sensor_explorer.qml 1
-
- When the selected sensor changes, the \c sensor of the property model changes
- accordingly.
-
- The following snippet illustrates how the property view is implemented. For
- more details about QML models and views, please see
- \l{Models and Views in Qt Quick}.
-
- \snippet sensor_explorer/sensor_explorer.qml 3
-
- For clarity it should be mentioned that the \c display attribute used by
- the text element refers to the Qt::DisplayRole role of the model, which is
- provided by default by Qt models.
-
- \section1 Activating the Sensors
-
- The example has a button for activating and deactivating the currently
- selected sensor. The button is enabled only if a sensor is currently
- selected, as illustrated below.
-
- \snippet sensor_explorer/sensor_explorer.qml 2
-
- On clicking the button, the sensor's active property is toggled on/off.
-
-*/
diff --git a/examples/sensors/sensor_explorer/main.cpp b/examples/sensors/sensor_explorer/main.cpp
deleted file mode 100644
index 4eeaa147..00000000
--- a/examples/sensors/sensor_explorer/main.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#include <QtQml>
-#include <QtQuick/QQuickWindow>
-#include <QtGui/QGuiApplication>
-
-int main(int argc, char *argv[])
-{
- QGuiApplication app(argc, argv);
- QQmlApplicationEngine engine(QUrl("qrc:///sensor_explorer.qml"));
- QObject *topLevel = engine.rootObjects().value(0);
- QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
- if (!window) {
- qWarning("Error: Your root item has to be a Window.");
- return -1;
- }
- window->show();
- return app.exec();
-}
diff --git a/examples/sensors/sensor_explorer/qml.qrc b/examples/sensors/sensor_explorer/qml.qrc
deleted file mode 100644
index df6160ae..00000000
--- a/examples/sensors/sensor_explorer/qml.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>sensor_explorer.qml</file>
- </qresource>
-</RCC>
diff --git a/examples/sensors/sensor_explorer/sensor_explorer.pro b/examples/sensors/sensor_explorer/sensor_explorer.pro
deleted file mode 100644
index a27681e2..00000000
--- a/examples/sensors/sensor_explorer/sensor_explorer.pro
+++ /dev/null
@@ -1,22 +0,0 @@
-TEMPLATE = app
-TARGET = sensor_explorer
-QT += qml quick sensors
-
-# Avoid going to release/debug subdirectory
-win32: DESTDIR = ./
-
-SOURCES = main.cpp sensormodels.cpp
-HEADERS = sensormodels.h
-
-CONFIG += qmltypes
-QML_IMPORT_NAME = SensorModels
-QML_IMPORT_MAJOR_VERSION = 1
-
-OTHER_FILES = \
- sensor_explorer.qml
-
-target.path = $$[QT_INSTALL_EXAMPLES]/sensors/sensor_explorer
-INSTALLS += target
-
-RESOURCES += \
- qml.qrc
diff --git a/examples/sensors/sensor_explorer/sensor_explorer.qml b/examples/sensors/sensor_explorer/sensor_explorer.qml
deleted file mode 100644
index 9fe59baa..00000000
--- a/examples/sensors/sensor_explorer/sensor_explorer.qml
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-import QtQuick
-import QtQuick.Window
-import QtQuick.Controls
-import QtQuick.Layouts
-
-//! [0]
-import SensorModels
-//! [0]
-
-Window {
- id: window
- width: 400
- height: 600
-
- AvailableSensorsModel {
- id: availableSensorsModel
- }
-
- ColumnLayout {
-
- GroupBox {
- id: availableSensorsModelGroup
- title: qsTr("Available Sensors")
- Layout.preferredWidth: window.width - 4 // 4 = 2x2 margins
- Layout.preferredHeight: window.height * 0.4
- Layout.margins: 2
-
- ListView {
- id: sensorsView
- anchors.fill: parent
- currentIndex: -1 // no initial selection
- spacing: 1
- clip: true
- model: availableSensorsModel
- delegate: Item {
- id: sensorRow
- width: sensorsView.width
- height: 30
- property color rowColor: {
- if (sensorsView.currentIndex == index)
- return "lightsteelblue" // highlight
- return (index % 2 == 0) ? "#CCCCCC" : "#AAAAAA"
- }
- RowLayout {
- spacing: 1
- anchors.fill: parent
- Rectangle {
- color: sensorRow.rowColor
- Layout.preferredWidth: sensorRow.width * 0.8
- Layout.preferredHeight: sensorRow.height
- Text {
- anchors.centerIn: parent
- text: display.type + "::" + display.identifier
- }
- }
- Rectangle {
- color: sensorRow.rowColor
- Layout.preferredWidth: sensorRow.width * 0.2
- Layout.preferredHeight: sensorRow.height
- Text {
- anchors.centerIn: parent
- text: display.active ? qsTr("Active") : qsTr("Inactive")
- }
- }
- }
- MouseArea {
- anchors.fill: parent
- onClicked: sensorsView.currentIndex = index
- }
- }
- }
- }
-
- //! [1]
- SensorPropertyModel {
- id: propertyModel
- sensor: availableSensorsModel.get(sensorsView.currentIndex)
- }
- //! [1]
-
- //! [2]
- Button {
- id: activateButton
- Layout.preferredHeight: 30
- Layout.alignment: Qt.AlignCenter
- enabled: propertyModel.sensor
- text: !propertyModel.sensor ? qsTr("Select sensor")
- : (propertyModel.sensor.active ? qsTr("Deactivate sensor")
- : qsTr("Activate sensor"))
- onClicked: propertyModel.sensor.active = !propertyModel.sensor.active
- }
- //! [2]
-
- GroupBox {
- title: qsTr("Selected sensor's properties")
- Layout.preferredWidth: window.width - 4 // 4 = 2x2 margins
- Layout.preferredHeight: window.height * 0.55 - activateButton.height
- Layout.margins: 2
- enabled: sensorsView.currentIndex != -1
-
- //! [3]
- TableView {
- id: propertyView
- anchors.fill: parent
- model: propertyModel
- columnSpacing: 1
- rowSpacing: 1
- boundsMovement: Flickable.StopAtBounds
- clip: true
-
- delegate: Rectangle {
- implicitHeight: 30
- implicitWidth: propertyView.width * 0.5
- color: (model.row % 2 == 0) ? "#CCCCCC" : "#AAAAAA"
- Text {
- anchors.centerIn: parent
- text: display
- }
- }
- }
- //! [3]
- }
- }
-}
diff --git a/examples/sensors/sensor_explorer/sensormodels.cpp b/examples/sensors/sensor_explorer/sensormodels.cpp
deleted file mode 100644
index f9ed4d90..00000000
--- a/examples/sensors/sensor_explorer/sensormodels.cpp
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#include "sensormodels.h"
-#include "qsensor.h"
-#include "qorientationsensor.h"
-#include <QtCore/QDebug>
-#include <qsensor.h>
-#include <QMetaObject>
-#include <QMetaProperty>
-
-QT_BEGIN_NAMESPACE
-
-QByteArray rangelistToByteArray(const qrangelist& list)
-{
- QStringList ranges;
- for (const qrange &r : list) {
- if (r.first == r.second)
- ranges << QString("%1 Hz").arg(r.first);
- else
- ranges << QString("%1-%2 Hz").arg(r.first).arg(r.second);
- }
- if (ranges.size() > 0)
- return ranges.join(", ").toLatin1();
- return "-";
-}
-
-QByteArray outputrangelistToByteArray(const qoutputrangelist& list)
-{
- QStringList ranges;
- for (const qoutputrange &r : list) {
- ranges << QString("(%1, %2) += %3").arg(r.minimum).arg(r.maximum).arg(r.accuracy);
- }
- if (ranges.size() > 0)
- return ranges.join(", ").toLatin1();
- return "-";
-}
-
-AvailableSensorsModel::AvailableSensorsModel(QObject* parent) : QAbstractListModel(parent)
-{
- // Some valuetypes do not convert nicely to presentable strings, add converters for them
- QMetaType::registerConverter<qrangelist, QByteArray>(rangelistToByteArray);
- QMetaType::registerConverter<qoutputrangelist, QByteArray>(outputrangelistToByteArray);
-
- // Populate the available sensors list
- loadSensors();
-}
-
-/*
- Load all available sensors and store them in a list.
-*/
-void AvailableSensorsModel::loadSensors()
-{
- //! [0]
- beginResetModel();
- m_availableSensors.clear();
-
- for (const QByteArray &type : QSensor::sensorTypes()) {
- for (const QByteArray &identifier : QSensor::sensorsForType(type)) {
- QSensor* sensor = new QSensor(type, this);
- sensor->setIdentifier(identifier);
- // Don't put in sensors we can't connect to
- if (!sensor->connectToBackend())
- continue;
- m_availableSensors.append(sensor);
- }
- }
- endResetModel();
- //! [0]
-}
-
-int AvailableSensorsModel::rowCount(const QModelIndex&) const
-{
- return m_availableSensors.size();
-}
-
-//! [1]
-QVariant AvailableSensorsModel::data(const QModelIndex &index, int role) const
-{
- if (role != Qt::DisplayRole)
- return QVariant();
- return QVariant::fromValue<QSensor*>(m_availableSensors.at(index.row()));
-}
-//! [1]
-
-QSensor* AvailableSensorsModel::get(int index) const
-{
- if (index < 0 || index >= m_availableSensors.size())
- return nullptr;
- return m_availableSensors[index];
-}
-
-// -- SensorPropertyModel
-
-static QSet<QByteArray> ignoredProperties = {"reading", "identifier", "active",
- "connectedToBackend", "busy"};
-
-SensorPropertyModel::SensorPropertyModel(QObject* parent) : QAbstractTableModel(parent)
-{
-}
-
-int SensorPropertyModel::rowCount(const QModelIndex&) const
-{
- if (!m_sensor)
- return 0;
- return m_values.size();
-}
-
-int SensorPropertyModel::columnCount(const QModelIndex&) const
-{
- return 2; // 2 = property name + value columns
-}
-
-QVariant SensorPropertyModel::data(const QModelIndex &index, int role) const
-{
- if (role != Qt::DisplayRole)
- return QVariant();
- return (index.column() == 0) ? std::get<0>(m_values.at(index.row()))
- : std::get<1>(m_values.at(index.row()));
-}
-
-void SensorPropertyModel::setSensor(QSensor *sensor)
-{
- if (m_sensor == sensor)
- return;
- if (m_sensor)
- m_sensor->disconnect(this);
- m_sensor = sensor;
-
- beginResetModel();
- m_values.clear();
- if (m_sensor) {
- // Use metobject to read the available properties. This allows the model to support all
- // available sensors without knowing their properties in advance / compile-time.
-
- // 1. Read properties of the 'reading' object if available
- //! [2]
- int firstProperty = QSensorReading::staticMetaObject.propertyOffset();
- QSensorReading *reading = m_sensor->reading();
- if (reading) {
- const QMetaObject *mo = reading->metaObject();
- for (int i = firstProperty; i < mo->propertyCount(); ++i) {
- QByteArray name = mo->property(i).name();
- m_values.append(std::tuple<QByteArray, QByteArray>
- (name, reading->property(name).toByteArray()));
- }
- }
- //! [2]
-
- // 2. Read properties of the 'sensor' object
- const QMetaObject *mo1 = m_sensor->metaObject();
- firstProperty = QSensorReading::staticMetaObject.propertyOffset();
- for (int i = firstProperty; i < mo1->propertyCount(); ++i) {
- QByteArray name = mo1->property(i).name();
- if (ignoredProperties.contains(name))
- continue;
- m_values.append(std::tuple<QByteArray, QByteArray>
- (name, m_sensor->property(name).toByteArray()));
- }
- QObject::connect(m_sensor, &QSensor::readingChanged,
- this, &SensorPropertyModel::onReadingChanged);
- }
- endResetModel();
- emit sensorChanged();
-}
-
-QSensor* SensorPropertyModel::sensor() const
-{
- return m_sensor;
-}
-
-void SensorPropertyModel::onReadingChanged()
-{
- QSensorReading *reading = m_sensor->reading();
- const QMetaObject *mo = reading->metaObject();
- int firstProperty = QSensorReading::staticMetaObject.propertyOffset();
-
- int valueMapIndex = 0;
- for (int i = firstProperty; i < mo->propertyCount(); ++i) {
- QByteArray name = mo->property(i).name();
- // Update the value and signal the change. Note: here we rely that the "reading"
- // properties are first on the m_values, and in same order as after the initial
- // population. This should be true as we access the static metabobject (dynamic
- // property changes shouldn't impact)
- m_values[valueMapIndex++] = std::tuple<QByteArray, QByteArray>
- (name, reading->property(name).toByteArray());
- }
- emit dataChanged(createIndex(0,1), createIndex(valueMapIndex,1), {Qt::DisplayRole});
-}
-
-QT_END_NAMESPACE
diff --git a/examples/sensors/sensor_explorer/sensormodels.h b/examples/sensors/sensor_explorer/sensormodels.h
deleted file mode 100644
index 02de2a8e..00000000
--- a/examples/sensors/sensor_explorer/sensormodels.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-
-#ifndef QSEONSOREXPLORER_H
-#define QSEONSOREXPLORER_H
-
-#include <QtSensors/qsensor.h>
-
-#include <QtQml/qqml.h>
-#include <QtCore/QAbstractListModel>
-#include <QtCore/QAbstractTableModel>
-
-QT_BEGIN_NAMESPACE
-
-//! [0]
-class AvailableSensorsModel: public QAbstractListModel
-{
- Q_OBJECT
- QML_ELEMENT
-//! [0]
-public:
- explicit AvailableSensorsModel(QObject* parent = nullptr);
- int rowCount(const QModelIndex & = QModelIndex()) const override;
- QVariant data(const QModelIndex &index, int role) const override;
- Q_INVOKABLE QSensor* get(int index) const;
-
-private:
- void loadSensors();
- QList<QSensor*> m_availableSensors;
-};
-
-class SensorPropertyModel: public QAbstractTableModel
-{
- Q_OBJECT
- Q_PROPERTY(QSensor* sensor READ sensor WRITE setSensor NOTIFY sensorChanged)
- QML_ELEMENT
-
-public:
- explicit SensorPropertyModel(QObject* parent = nullptr);
-
- int rowCount(const QModelIndex & = QModelIndex()) const override;
- int columnCount(const QModelIndex & = QModelIndex()) const override;
- QVariant data(const QModelIndex &index, int role) const override;
-
- void setSensor(QSensor* sensor);
- QSensor* sensor() const;
-
-signals:
- void sensorChanged();
-
-private slots:
- void onReadingChanged();
-
-private:
- QSensor* m_sensor = nullptr;
- // m_values is used to cache sensor property values to avoid
- // full metaobject iteration on every sensor reading change
- QList<std::tuple<QByteArray, QByteArray>> m_values;
-};
-
-QT_END_NAMESPACE
-
-#endif // QSEONSOREXPLORER_H
diff --git a/examples/sensors/sensors.pro b/examples/sensors/sensors.pro
index 984d7619..566e1725 100644
--- a/examples/sensors/sensors.pro
+++ b/examples/sensors/sensors.pro
@@ -1,6 +1,2 @@
TEMPLATE = subdirs
-qtHaveModule(quick) {
- SUBDIRS += \
- sensor_explorer
-}