From 0f24d95eeec2c5303b017ce1f79e49eeb7c467d1 Mon Sep 17 00:00:00 2001 From: luocai Date: Wed, 14 Aug 2024 20:01:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0=E7=94=BB?= =?UTF-8?q?=E7=82=B9=E5=8F=8A=E4=B8=8B=E5=8F=91=E9=80=BB=E8=BE=91=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Application.cpp | 105 +++++++++++++- Application.h | 43 +++++- DeviceConnection.cpp | 197 ++++++++++++++++++++++++-- DeviceConnection.h | 27 +++- DeviceView.qml | 327 +++++++++++++++++++++++++++++++++---------- Main.qml | 49 +++++-- 6 files changed, 644 insertions(+), 104 deletions(-) diff --git a/Application.cpp b/Application.cpp index a01c6f0..fbb9cbe 100644 --- a/Application.cpp +++ b/Application.cpp @@ -4,17 +4,36 @@ #include "DeviceConnection.h" #include "H264Palyer.h" #include "VideoFrameProvider.h" +#include #include #include Application::Application(int &argc, char **argv) : m_app(std::make_shared(argc, argv)), m_videoFrameProvider(new VideoFrameProvider()), m_player(std::make_shared()) { + QFont font; + font.setPointSize(16); + m_app->setFont(font); m_app->setApplicationName(APPLICATION_NAME); m_app->setApplicationVersion(QString("v%1_%2 build: %3 %4").arg(APP_VERSION, GIT_COMMIT_ID, __DATE__, __TIME__)); m_player->open(); } +bool Application::currentOpenDoorAreaEnabled() const { + return m_currentOpenDoorAreaEnabled; +} + +void Application::setCurrentOpenDoorAreaEnabled(bool enabled) { + if (m_currentOpenDoorAreaEnabled != enabled) { + m_currentOpenDoorAreaEnabled = enabled; + emit currentOpenDoorAreaEnabledChanged(); + if (m_device != nullptr) { + m_device->updateOpenDoorAreaPoints(m_currentOpenDoorAreaEnabled, m_currentOpenDoorAreaPoints); + } + } + LOG(info) << "setCurrentOpenDoorAreaEnabled " << enabled; +} + QList Application::currentOpenDoorAreaPoints() const { return m_currentOpenDoorAreaPoints; } @@ -26,11 +45,86 @@ void Application::setCurrentOpenDoorAreaPoints(const QList &points) { } } -void Application::onDeviceOpenDoorAreaPoints(const QList &points) { +bool Application::currentShieldedAreaEnabled() const { + return m_currentShieldedAreaEnabled; +} + +void Application::setCurrentShieldedAreaEnabled(bool enabled) { + if (m_currentShieldedAreaEnabled != enabled) { + m_currentShieldedAreaEnabled = enabled; + emit currentShieldedAreaEnabledChanged(); + if (m_device != nullptr) { + m_device->updateShieldedAreaPoints(m_currentShieldedAreaEnabled, m_currentShieldedAreaPoints); + } + } +} + +QList Application::currentShieldedAreaPoints() const { + return m_currentShieldedAreaPoints; +} + +void Application::setCurrentShieldedAreaPoints(const QList &points) { + if (m_currentShieldedAreaPoints != points) { + m_currentShieldedAreaPoints = points; + emit currentShieldedAreaPointsChanged(); + } +} + +bool Application::currentAntiClipAreaEnabled() const { + return m_currentAntiClipAreaEnabled; +} + +void Application::setCurrentAntiClipAreaEnabled(bool enabled) { + if (m_currentAntiClipAreaEnabled != enabled) { + m_currentAntiClipAreaEnabled = enabled; + emit currentAntiClipAreaEnabledChanged(); + if (m_device != nullptr) { + m_device->updateAntiClipAreaPoints(m_currentAntiClipAreaEnabled, m_currentAntiClipAreaPoints); + } + } +} + +QList Application::currentAntiClipAreaPoints() const { + return m_currentAntiClipAreaPoints; +} + +void Application::setCurrentAntiClipAreaPoints(const QList &points) { + if (m_currentAntiClipAreaPoints != points) { + m_currentAntiClipAreaPoints = points; + emit currentAntiClipAreaPointsChanged(); + } +} + +void Application::updateOpenDoorAreaPoints(const QList &points) { + LOG(info) << "updateOpenDoorAreaPoints: " << points.size(); + m_device->updateOpenDoorAreaPoints(m_currentOpenDoorAreaEnabled, points); +} + +void Application::updateAntiClipAreaPoints(const QList &points) { + m_device->updateAntiClipAreaPoints(m_currentAntiClipAreaEnabled, points); +} + +void Application::updateShieldedAreaPoints(const QList &points) { + m_device->updateShieldedAreaPoints(m_currentShieldedAreaEnabled, points); +} + +void Application::onDeviceOpenDoorArea(bool enabled, const QList &points) { + setCurrentOpenDoorAreaEnabled(enabled); setCurrentOpenDoorAreaPoints(points); LOG(info) << "onDeviceOpenDoorAreaPoints: " << points.size(); } +void Application::onDeviceShieldedArea(bool enabled, const QList &points) { + LOG(info) << "onDeviceShieldedArea: " << points.size(); + setCurrentShieldedAreaEnabled(enabled); + setCurrentShieldedAreaPoints(points); +} + +void Application::onDeviceAntiClipArea(bool enabled, const QList &points) { + setCurrentAntiClipAreaEnabled(enabled); + setCurrentAntiClipAreaPoints(points); +} + int Application::exec() { QQmlApplicationEngine engine; engine.addImageProvider("videoframe", m_videoFrameProvider); @@ -44,8 +138,9 @@ int Application::exec() { void Application::open() { LOG(info) << "Application::start"; m_device = new DeviceConnection(); - connect(m_device, &DeviceConnection::currentOpenDoorAreaPointsChanged, this, - &Application::onDeviceOpenDoorAreaPoints); + connect(m_device, &DeviceConnection::currentOpenDoorAreaChanged, this, &Application::onDeviceOpenDoorArea); + connect(m_device, &DeviceConnection::currentShieldedAreaChanged, this, &Application::onDeviceShieldedArea); + connect(m_device, &DeviceConnection::currentAntiClipAreaChanged, this, &Application::onDeviceAntiClipArea); m_device->connect(); m_device->setH264FrameCallback([this](const char *data, uint32_t size) { auto image = m_player->decode((const uint8_t *)data, size); @@ -57,7 +152,9 @@ void Application::open() { } void Application::start() { - m_device->start(); + if (m_device != nullptr) { + m_device->start(); + } } Application *Application::create(QQmlEngine *qmlEngine, QJSEngine *jsEngine) { diff --git a/Application.h b/Application.h index b3f0f9a..2ff3a04 100644 --- a/Application.h +++ b/Application.h @@ -15,13 +15,42 @@ class Application : public QObject { Q_OBJECT QML_NAMED_ELEMENT(App) QML_SINGLETON + Q_PROPERTY(int DeviceWidth MEMBER DeviceWidth CONSTANT FINAL) + Q_PROPERTY(bool currentOpenDoorAreaEnabled READ currentOpenDoorAreaEnabled WRITE setCurrentOpenDoorAreaEnabled + NOTIFY currentOpenDoorAreaEnabledChanged) Q_PROPERTY(QList currentOpenDoorAreaPoints READ currentOpenDoorAreaPoints WRITE setCurrentOpenDoorAreaPoints NOTIFY currentOpenDoorAreaPointsChanged) + Q_PROPERTY(bool currentShieldedAreaEnabled READ currentShieldedAreaEnabled WRITE setCurrentShieldedAreaEnabled + NOTIFY currentShieldedAreaEnabledChanged) + Q_PROPERTY(QList currentShieldedAreaPoints READ currentShieldedAreaPoints WRITE + setCurrentShieldedAreaPoints NOTIFY currentShieldedAreaPointsChanged) + Q_PROPERTY(bool currentAntiClipAreaEnabled READ currentAntiClipAreaEnabled WRITE setCurrentAntiClipAreaEnabled + NOTIFY currentAntiClipAreaEnabledChanged) + Q_PROPERTY(QList currentAntiClipAreaPoints READ currentAntiClipAreaPoints WRITE + setCurrentAntiClipAreaPoints NOTIFY currentAntiClipAreaPointsChanged) friend class Amass::Singleton; public: + constexpr static int DeviceWidth = 640; + bool currentOpenDoorAreaEnabled() const; + void setCurrentOpenDoorAreaEnabled(bool enabled); QList currentOpenDoorAreaPoints() const; void setCurrentOpenDoorAreaPoints(const QList &points); + + bool currentShieldedAreaEnabled() const; + void setCurrentShieldedAreaEnabled(bool enabled); + QList currentShieldedAreaPoints() const; + void setCurrentShieldedAreaPoints(const QList &points); + + bool currentAntiClipAreaEnabled() const; + void setCurrentAntiClipAreaEnabled(bool enabled); + QList currentAntiClipAreaPoints() const; + void setCurrentAntiClipAreaPoints(const QList &points); + + Q_INVOKABLE void updateOpenDoorAreaPoints(const QList &points); + Q_INVOKABLE void updateAntiClipAreaPoints(const QList &points); + Q_INVOKABLE void updateShieldedAreaPoints(const QList &points); + int exec(); Q_INVOKABLE void open(); Q_INVOKABLE void start(); @@ -30,10 +59,17 @@ public: signals: void newVideoFrame(); void currentOpenDoorAreaPointsChanged(); + void currentShieldedAreaPointsChanged(); + void currentAntiClipAreaPointsChanged(); + void currentOpenDoorAreaEnabledChanged(); + void currentShieldedAreaEnabledChanged(); + void currentAntiClipAreaEnabledChanged(); protected: Application(int &argc, char **argv); - void onDeviceOpenDoorAreaPoints(const QList &points); + void onDeviceOpenDoorArea(bool enabled, const QList &points); + void onDeviceShieldedArea(bool enabled, const QList &points); + void onDeviceAntiClipArea(bool enabled, const QList &points); private: std::shared_ptr m_app; @@ -41,7 +77,12 @@ private: std::shared_ptr m_player; DeviceConnection *m_device = nullptr; + bool m_currentOpenDoorAreaEnabled = false; QList m_currentOpenDoorAreaPoints; + bool m_currentShieldedAreaEnabled = false; + QList m_currentShieldedAreaPoints; + bool m_currentAntiClipAreaEnabled = false; + QList m_currentAntiClipAreaPoints; }; #endif // APPLICATION_H diff --git a/DeviceConnection.cpp b/DeviceConnection.cpp index e2f25d5..33b6a8c 100644 --- a/DeviceConnection.cpp +++ b/DeviceConnection.cpp @@ -37,22 +37,167 @@ void DeviceConnection::start() { } void DeviceConnection::requestOpenDoorArea() { - boost::json::object request; - request["func"] = "a03opendoor1_getdata"; - request["deviceid"] = "0"; - boost::json::object data; - request["data"] = std::move(data); - auto text = boost::json::serialize(request); - m_commandSocket->write(text.data(), text.size()); - LOG(info) << "requestOpenDoorArea"; + auto task = [this]() { + boost::json::object request; + request["func"] = "a03opendoor1_getdata"; + request["deviceid"] = "0"; + boost::json::object data; + request["data"] = std::move(data); + auto text = boost::json::serialize(request); + m_commandSocket->write(text.data(), text.size()); + LOG(info) << "requestOpenDoorArea"; + }; + if (m_requests.empty()) { + task(); + } + m_requests.push(task); +} + +void DeviceConnection::updateOpenDoorAreaPoints(bool enabled, const QList &points) { + auto task = [this, enabled, points]() { + boost::json::object request; + request["func"] = "a03opendoor1_setdata"; + request["deviceid"] = "0"; + boost::json::object data; + data["value"] = enabled ? "1" : "0"; + boost::json::array pointArray; + for (auto &p : points) { + boost::json::object point; + point["x"] = p.x(); + point["y"] = p.y(); + pointArray.push_back(std::move(point)); + } + data["points"] = std::move(pointArray); + request["data"] = std::move(data); + + auto text = boost::json::serialize(request); + m_commandSocket->write(text.data(), text.size()); + LOG(info) << "updateOpenDoorAreaPoints"; + }; + if (m_requests.empty()) { + task(); + } + m_requests.push(task); +} + +void DeviceConnection::requestShieldedArea() { + auto task = [this]() { + boost::json::object request; + request["func"] = "a03opendoor4_getdata"; + request["deviceid"] = "0"; + boost::json::object data; + request["data"] = std::move(data); + auto text = boost::json::serialize(request); + m_commandSocket->write(text.data(), text.size()); + LOG(info) << "requestShieldedArea"; + }; + if (m_requests.empty()) { + task(); + } + m_requests.push(task); +} + +void DeviceConnection::updateShieldedAreaPoints(bool enabled, const QList &points) { + auto task = [this, enabled, points]() { + boost::json::object request; + request["func"] = "a03opendoor4_setdata"; + request["deviceid"] = "0"; + boost::json::object data; + data["value"] = enabled ? "1" : "0"; + boost::json::array pointArray; + for (auto &p : points) { + boost::json::object point; + point["x"] = p.x(); + point["y"] = p.y(); + pointArray.push_back(std::move(point)); + } + data["points"] = std::move(pointArray); + request["data"] = std::move(data); + + auto text = boost::json::serialize(request); + m_commandSocket->write(text.data(), text.size()); + LOG(info) << "updateShieldedAreaPoints"; + }; + if (m_requests.empty()) { + task(); + } + m_requests.push(task); +} + +void DeviceConnection::requestAntiClipArea() { + auto task = [this]() { + boost::json::object request; + request["func"] = "a03opendoor5_getdata"; + request["deviceid"] = "0"; + boost::json::object data; + request["data"] = std::move(data); + auto text = boost::json::serialize(request); + m_commandSocket->write(text.data(), text.size()); + LOG(info) << "requestAntiClipArea"; + }; + if (m_requests.empty()) { + task(); + } + m_requests.push(task); +} + +void DeviceConnection::updateAntiClipAreaPoints(bool enabled, const QList &points) { + auto task = [this, enabled, points]() { + boost::json::object request; + request["func"] = "a03opendoor5_setdata"; + request["deviceid"] = "0"; + boost::json::object data; + data["value"] = enabled ? "1" : "0"; + boost::json::array pointArray; + for (auto &p : points) { + boost::json::object point; + point["x"] = p.x(); + point["y"] = p.y(); + pointArray.push_back(std::move(point)); + } + data["points"] = std::move(pointArray); + request["data"] = std::move(data); + + auto text = boost::json::serialize(request); + m_commandSocket->write(text.data(), text.size()); + LOG(info) << "updateAntiClipAreaPoints"; + }; + if (m_requests.empty()) { + task(); + } + m_requests.push(task); +} + +void DeviceConnection::requestResolution(Resolution resolution) { + auto task = [this, resolution]() { + boost::json::object request; + request["func"] = "quality_setdata"; + request["deviceid"] = "0"; + boost::json::object data; + data["value"] = static_cast(resolution); + request["data"] = std::move(data); + auto text = boost::json::serialize(request); + m_commandSocket->write(text.data(), text.size()); + LOG(info) << "requestShieldedArea"; + }; + if (m_requests.empty()) { + task(); + } + m_requests.push(task); } void DeviceConnection::handleCommand(const std::string_view &replyText) { - auto replyValue = boost::json::parse(replyText); + boost::system::error_code error; + auto replyValue = boost::json::parse(replyText, error); + if (error) { + LOG(error) << "prase [" << replyText << "] failed, message: " << error.message(); + return; + } auto &reply = replyValue.as_object(); auto &function = reply.at("func").as_string(); if (function == "a03opendoor1_getdata") { auto &data = reply.at("data").as_object(); + auto &value = data.at("value").as_string(); auto &pointArray = data.at("points").as_array(); QList points; for (auto &p : pointArray) { @@ -62,7 +207,33 @@ void DeviceConnection::handleCommand(const std::string_view &replyText) { point.setY(obj.at("y").as_double()); points.push_back(point); } - emit currentOpenDoorAreaPointsChanged(points); + emit currentOpenDoorAreaChanged(value == "1", points); + } else if (function == "a03opendoor4_getdata") { + auto &data = reply.at("data").as_object(); + auto &value = data.at("value").as_string(); + auto &pointArray = data.at("points").as_array(); + QList points; + for (auto &p : pointArray) { + QPointF point; + auto &obj = p.as_object(); + point.setX(obj.at("x").as_double()); + point.setY(obj.at("y").as_double()); + points.push_back(point); + } + emit currentShieldedAreaChanged(value == "1", points); + } else if (function == "a03opendoor5_getdata") { + auto &data = reply.at("data").as_object(); + auto &value = data.at("value").as_string(); + auto &pointArray = data.at("points").as_array(); + QList points; + for (auto &p : pointArray) { + QPointF point; + auto &obj = p.as_object(); + point.setX(obj.at("x").as_double()); + point.setY(obj.at("y").as_double()); + points.push_back(point); + } + emit currentAntiClipAreaChanged(value == "1", points); } } @@ -71,6 +242,8 @@ void DeviceConnection::onConnected() { auto socket = dynamic_cast(sender()); if (socket == m_commandSocket) { requestOpenDoorArea(); + requestShieldedArea(); + requestAntiClipArea(); } } @@ -109,5 +282,9 @@ void DeviceConnection::onCommandReadyRead() { LOG(info) << "h264 reply: " << m_commandBuffer.data() + sizeof(uint32_t); handleCommand(std::string_view(m_commandBuffer.data() + sizeof(uint32_t), packageSize)); m_commandBuffer.remove(0, packageSize + sizeof(uint32_t)); + m_requests.pop(); + if (!m_requests.empty()) { + m_requests.front()(); + } } } diff --git a/DeviceConnection.h b/DeviceConnection.h index 0b0c1ce..8161407 100644 --- a/DeviceConnection.h +++ b/DeviceConnection.h @@ -2,22 +2,44 @@ #define DEVICECONNECTION_H #include +#include +#include #include - class QTcpSocket; class DeviceConnection : public QObject { Q_OBJECT + QML_ELEMENT + QML_UNCREATABLE("Only used in C++...") + public: + enum Resolution { + Video_360P = 0, + Video_720P, + }; + enum AreaWay { + Diabled = 0, + FullScreen, + Quadrangle, // 四边形 + }; + Q_ENUM(AreaWay) using H264FrameCallback = std::function; explicit DeviceConnection(QObject *parent = nullptr); void setH264FrameCallback(H264FrameCallback &&callback); void connect(); void start(); void requestOpenDoorArea(); + void updateOpenDoorAreaPoints(bool enabled, const QList &points); + void requestShieldedArea(); + void updateShieldedAreaPoints(bool enabled, const QList &points); + void requestAntiClipArea(); + void updateAntiClipAreaPoints(bool enabled, const QList &points); + void requestResolution(Resolution resolution); signals: - void currentOpenDoorAreaPointsChanged(const QList &points); + void currentOpenDoorAreaChanged(bool enabled, const QList &points); + void currentShieldedAreaChanged(bool enabled, const QList &points); + void currentAntiClipAreaChanged(bool enabled, const QList &points); protected: void onConnected(); @@ -34,6 +56,7 @@ private: QByteArray m_commandBuffer; QByteArray m_h264Buffer; H264FrameCallback m_frameCallback; + std::queue> m_requests; }; #endif // DEVICECONNECTION_H diff --git a/DeviceView.qml b/DeviceView.qml index d433cb7..ab1df1f 100644 --- a/DeviceView.qml +++ b/DeviceView.qml @@ -1,94 +1,252 @@ import QtQuick +import QtQuick.Controls import AntiClipSettings Item { id: root - property int dargWidth: 10 + property int dargWidth: 12 + property color openDoorAreaColor: "green" property var openDoorAreaPoints: [] - Image { - id: image - anchors.centerIn: parent - cache: false - fillMode: Image.PreserveAspectFit - source: "image://videoframe/" - property real aspectRatio: 16 / 9 - width: Math.min(root.width, root.height * aspectRatio) - height: width / aspectRatio + property bool openDoorAreaEnabled: false + property var shieldedAreaPoints: [] + property bool shieldedAreaEnabled: false + property color antiClipAreaColor: "blue" + property var antiClipAreaPoints: [] + property bool antiClipAreaEnabled: false + property var defaultShieldedAreaPoints: [Qt.point(6, 6), Qt.point(40, 60), + Qt.point(598, 6), Qt.point(633, 60)] + Item { + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: controlBar.top + Image { + id: image + anchors.centerIn: parent + cache: false + fillMode: Image.PreserveAspectFit + source: "image://videoframe/" + property real aspectRatio: 16 / 9 + width: Math.min(parent.width, parent.height * aspectRatio) + height: width / aspectRatio - Canvas { - id: canvas - anchors.fill: parent - onPaint: { - var ctx = canvas.getContext("2d") - ctx.clearRect(0, 0, canvas.width, canvas.height) - if (openDoorAreaPoints.length > 0) { - ctx.strokeStyle = "red" - ctx.lineWidth = 2 + Canvas { + id: canvas + anchors.fill: parent + onPaint: { + var ctx = canvas.getContext("2d") + ctx.clearRect(0, 0, canvas.width, canvas.height) + if (openDoorAreaEnabled &&(openDoorAreaPoints.length > 0)) { + ctx.strokeStyle = openDoorAreaColor + ctx.lineWidth = 2 - ctx.beginPath() - let point = scaledPoint(openDoorAreaPoints[0], - width, height) - ctx.moveTo(point.x, point.y) - for (var i = 1; i < openDoorAreaPoints.length; i++) { - point = scaledPoint(openDoorAreaPoints[i], - width, height) - ctx.lineTo(point.x, point.y) + ctx.beginPath() + let point = scaledPoint(openDoorAreaPoints[0], + width, height) + ctx.moveTo(point.x, point.y) + for (var i = 1; i < openDoorAreaPoints.length; i++) { + point = scaledPoint(openDoorAreaPoints[i], + width, height) + ctx.lineTo(point.x, point.y) + } + ctx.closePath() + ctx.stroke() } - ctx.closePath() - ctx.stroke() + if (antiClipAreaEnabled && (antiClipAreaPoints.length > 0)) { + ctx.strokeStyle = antiClipAreaColor + ctx.lineWidth = 2 + + ctx.beginPath() + let point = scaledPoint(antiClipAreaPoints[0], + width, height) + ctx.moveTo(point.x, point.y) + for (var i = 1; i < antiClipAreaPoints.length; i++) { + point = scaledPoint(antiClipAreaPoints[i], + width, height) + ctx.lineTo(point.x, point.y) + } + ctx.closePath() + ctx.stroke() + } + if (shieldedAreaEnabled &&(shieldedAreaPoints.length > 0)) { + ctx.strokeStyle = "green" + let point0 = scaledPoint(shieldedAreaPoints[0], + width, height) + let point1 = scaledPoint(shieldedAreaPoints[1], + width, height) + let point2 = scaledPoint(shieldedAreaPoints[2], + width, height) + let point3 = scaledPoint(shieldedAreaPoints[3], + width, height) + ctx.strokeRect(point0.x, point0.y, point1.x - point0.x, + point1.y - point0.y) + ctx.strokeRect(point2.x, point2.y, point3.x - point2.x, + point3.y - point2.y) + } + } + } + + Repeater { + id: repeater + visible: openDoorAreaEnabled + model: openDoorAreaPoints + delegate: Rectangle { + width: dargWidth + height: dargWidth + visible: openDoorAreaEnabled + color: openDoorAreaColor + x: scaledPoint(modelData, canvas.width, + canvas.height).x - width / 2 + y: scaledPoint(modelData, canvas.width, + canvas.height).y - height / 2 + } + } + + Repeater { + id: shieldedAreaRepeater + model: shieldedAreaPoints + visible: shieldedAreaEnabled + delegate: Rectangle { + width: dargWidth + height: dargWidth + visible: shieldedAreaEnabled + color: "green" + x: scaledPoint(modelData, canvas.width, + canvas.height).x - width / 2 + y: scaledPoint(modelData, canvas.width, + canvas.height).y - height / 2 + } + } + + Repeater { + id: antiAreaRepeater + visible: antiClipAreaEnabled + model: antiClipAreaPoints + delegate: Rectangle { + visible: antiClipAreaEnabled + width: dargWidth + height: dargWidth + color: antiClipAreaColor + x: scaledPoint(modelData, canvas.width, + canvas.height).x - width / 2 + y: scaledPoint(modelData, canvas.width, + canvas.height).y - height / 2 + } + } + + MouseArea { + anchors.fill: parent + property int draggedOpenDoorAreaPointIndex: -1 + property int draggedShieldedAreaPointIndex: -1 + property int draggedAntiAreaPointIndex: -1 + onPressed: mouse => { + if(openDoorAreaEnabled){ + for (var i = 0; i < openDoorAreaPoints.length; i++) { + let point = scaledPoint( + openDoorAreaPoints[i], canvas.width, + canvas.height) + if (isInside(mouse.x, mouse.y, point)) { + draggedOpenDoorAreaPointIndex = i + break + } + } + } + if (draggedOpenDoorAreaPointIndex >= 0) + return + if(shieldedAreaEnabled){ + for (let i = 0; i < shieldedAreaPoints.length; i++) { + let point = scaledPoint( + shieldedAreaPoints[i], canvas.width, + canvas.height) + if (isInside(mouse.x, mouse.y, point)) { + draggedShieldedAreaPointIndex = i + break + } + } + } + if (draggedShieldedAreaPointIndex >= 0) + return + if(antiClipAreaEnabled){ + for (let i = 0; i < antiClipAreaPoints.length; i++) { + let point = scaledPoint( + antiClipAreaPoints[i], canvas.width, + canvas.height) + if (isInside(mouse.x, mouse.y, point)) { + draggedAntiAreaPointIndex = i + break + } + } + } + } + onReleased: { + if (draggedOpenDoorAreaPointIndex >= 0) { + App.updateOpenDoorAreaPoints(openDoorAreaPoints) + draggedOpenDoorAreaPointIndex = -1 + } + if (draggedShieldedAreaPointIndex >= 0) { + App.updateShieldedAreaPoints(shieldedAreaPoints) + draggedShieldedAreaPointIndex = -1 + } + if (draggedAntiAreaPointIndex >= 0) { + App.updateAntiClipAreaPoints(antiClipAreaPoints) + draggedAntiAreaPointIndex = -1 + } + } + onPositionChanged: mouse => { + if ((mouse.x < 0) || (mouse.x > canvas.width) || (mouse.y < 0) || (mouse.y > canvas.height)) return + if (draggedOpenDoorAreaPointIndex >= 0) { + openDoorAreaPoints[draggedOpenDoorAreaPointIndex] + = standardPoint(Qt.point(mouse.x, mouse.y), canvas.width, canvas.height) + canvas.requestPaint() + repeater.model = openDoorAreaPoints + } else if (draggedShieldedAreaPointIndex >= 0) { + shieldedAreaPoints[draggedShieldedAreaPointIndex] + = standardPoint(Qt.point(mouse.x, + mouse.y), + canvas.width, + canvas.height) + canvas.requestPaint() + shieldedAreaRepeater.model = shieldedAreaPoints + } else if (draggedAntiAreaPointIndex >= 0) { + antiClipAreaPoints[draggedAntiAreaPointIndex] + = standardPoint(Qt.point(mouse.x, + mouse.y), + canvas.width, + canvas.height) + canvas.requestPaint() + antiAreaRepeater.model = antiClipAreaPoints + } + } + + function isInside(x, y, point) { + let edge = dargWidth / 2 + return x >= point.x - edge && x <= point.x + edge + && y >= point.y - edge && y <= point.y + edge } } } - - Repeater { - id: repeater - model: openDoorAreaPoints - delegate: Rectangle { - width: dargWidth - height: dargWidth - color: "red" - x: scaledPoint(modelData, canvas.width, - canvas.height).x - width / 2 - y: scaledPoint(modelData, canvas.width, - canvas.height).y - height / 2 - } + } + Row { + id: controlBar + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + Switch { + text: "开门区域" + checked: openDoorAreaEnabled + onToggled: App.currentOpenDoorAreaEnabled = checked } - - MouseArea { - anchors.fill: parent - property int draggedPointIndex: -1 - onPressed: mouse => { - for (var i = 0; i < openDoorAreaPoints.length; i++) { - let point = scaledPoint(openDoorAreaPoints[i], - canvas.width, - canvas.height) - if (isInside(mouse.x, mouse.y, point)) { - draggedPointIndex = i - break - } - } - } - onReleased: { - draggedPointIndex = -1 - } - onPositionChanged: mouse => { - if (draggedPointIndex >= 0) { - openDoorAreaPoints[draggedPointIndex] = standardPoint( - Qt.point(mouse.x, mouse.y), - canvas.width, canvas.height) - canvas.requestPaint() - repeater.model = openDoorAreaPoints - } - } - - function isInside(x, y, point) { - let edge = dargWidth / 2 - return x >= point.x - edge && x <= point.x + edge - && y >= point.y - edge && y <= point.y + edge - } + Switch { + text: "防夹区域" + checked: antiClipAreaEnabled + onToggled: App.currentAntiClipAreaEnabled = checked + } + Switch { + text: "屏蔽区域" + checked: shieldedAreaEnabled + onToggled: App.currentShieldedAreaEnabled = checked } } - // 转换为显示画点 function scaledPoint(point, width, height) { let x = point.x * width / 640 @@ -96,8 +254,8 @@ Item { return Qt.point(x, y) } + // 转换为设备画点(640x360) function standardPoint(point, width, height) { - // 转换为设备画点(640x360) let x = point.x * 640 / width let y = point.y * 360 / height return Qt.point(x, y) @@ -112,5 +270,20 @@ Item { function onCurrentOpenDoorAreaPointsChanged() { canvas.requestPaint() } + function onCurrentShieldedAreaPointsChanged() { + canvas.requestPaint() + } + function onCurrentAntiClipAreaPointsChanged() { + canvas.requestPaint() + } + function onCurrentOpenDoorAreaEnabledChanged(){ + canvas.requestPaint() + } + function onCurrentShieldedAreaEnabledChanged(){ + canvas.requestPaint() + } + function onCurrentAntiClipAreaEnabledChanged(){ + canvas.requestPaint() + } } } diff --git a/Main.qml b/Main.qml index ef6032d..f43bc5d 100644 --- a/Main.qml +++ b/Main.qml @@ -1,22 +1,32 @@ import QtQuick import QtQuick.Controls +import QtQuick.Layouts import AntiClipSettings ApplicationWindow { - width: 640 + width: 680 height: 480 visible: true title: qsTr("Hello World") - header: Row { - Button { - text: "连接" - onClicked: App.open() - } - - Button { - text: "开始" - onClicked: App.start() + header: ToolBar { + RowLayout { + anchors.fill: parent + Button { + text: "搜索设备" + } + Button { + text: "连接" + onClicked: App.open() + } + Button { + text: "开始" + onClicked: App.start() + } + Text { + Layout.alignment: Qt.AlignRight + text: qsTr("当前设备版本号: RD_T009_V02R001B001") + } } } @@ -34,6 +44,25 @@ ApplicationWindow { anchors.bottom: parent.bottom anchors.left: deviceList.right anchors.right: parent.right + openDoorAreaEnabled: App.currentOpenDoorAreaEnabled openDoorAreaPoints: App.currentOpenDoorAreaPoints + shieldedAreaEnabled: App.currentShieldedAreaEnabled + shieldedAreaPoints: App.currentShieldedAreaPoints + antiClipAreaEnabled: App.currentAntiClipAreaEnabled + antiClipAreaPoints: App.currentAntiClipAreaPoints + } + + footer: RowLayout { + width: parent.width + Item {} + Button { + text: "数据采集" + } + Item {} + Button { + text: "升级" + } + Item {} + spacing: (parent.width - (2 * 100)) / 3 } }