From 1f4ade68614d5809f343161bab7214d2298d9efd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Burak=20Han=C3=A7erli?= <burak.hancerli@qt.io>
Date: Mon, 27 Jan 2025 10:48:23 +0000
Subject: [PATCH] Disconnect immediately when the app is put to sleep (or sent
 to background)

---
 README.md                             |  9 ++++-----
 src/Main.qml                          |  1 -
 src/backend/backend.cpp               | 12 ++++++++++++
 src/backend/dsconnector/ds.cpp        | 12 ++++++++++++
 src/backend/dsconnector/ds.h          |  3 +++
 src/backend/dsconnector/dsmanager.cpp | 21 +++++++++++++++++++++
 src/backend/dsconnector/dsmanager.h   |  2 ++
 7 files changed, 54 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index e94f559..7cea86e 100644
--- a/README.md
+++ b/README.md
@@ -3,9 +3,9 @@
 
 ## About
 
-Launch [Qt Design Studio](https://www.qt.io/ui-design-tools) projects in your Android device. The viewer that helps you do with [Qt for Android](https://doc.qt.io/qt-6/android.html).
+Launch [Qt Design Studio](https://www.qt.io/ui-design-tools) projects in your Android device in seconds. Qt UI Viewer is a simple app that allows you to view your Qt Design Studio projects on your Android device. It's a great tool for designers and developers to preview their designs on a real device.
 
-Qt UI Viewer works with minimum Android 11 (API level 30).
+Qt UI Viewer is built with [Qt for Android](https://doc.qt.io/qt-6/android.html).
 
 ## Getting the App
 
@@ -16,15 +16,14 @@ You can get the pre-built app from either [Google Play Store][google-play-link]
 * CMake 3.16 or newer
 * Qt 6.8.0 or newer
 * OpenSSL (<https://github.com/KDAB/android_openssl>)
-* Android SDK and NDK (<https://developer.android.com/studio>)
+* Android (min API 34) SDK and NDK (<https://developer.android.com/studio>)
 
 ## Code Map
 
 * cicd: GitLab pipeline files
 * resources: UI related files
 * android: Files needed for Android build system
-* src: Backend source files
-* ui: UI source files
+* src: All source files
 * 3rdparty: Required 3rd party libraries
     * qtquickdesigner-components: QML components
     * zxing-cpp: QR code decoding/encoding
diff --git a/src/Main.qml b/src/Main.qml
index e53eafe..8273525 100644
--- a/src/Main.qml
+++ b/src/Main.qml
@@ -61,7 +61,6 @@ Rectangle {
             Connections {
                 target: backend
                 function onConnectedChanged(isConnected) {
-                    console.log("Connected changed to", isConnected)
                     root.connected = isConnected
                 }
             }
diff --git a/src/backend/backend.cpp b/src/backend/backend.cpp
index 8952a78..cfebb45 100644
--- a/src/backend/backend.cpp
+++ b/src/backend/backend.cpp
@@ -74,6 +74,18 @@ Backend::Backend(QObject *parent)
         }
     });
 
+    connect(qApp,
+            &QGuiApplication::applicationStateChanged,
+            this,
+            [this](Qt::ApplicationState state) {
+                qDebug() << "Application state changed to" << state;
+                if (state == Qt::ApplicationState::ApplicationSuspended) {
+                    if (m_projectManager && !m_projectManager->sessionId().isEmpty())
+                        QMetaObject::invokeMethod(m_projectManager.get(), "stopProject");
+                    m_dsManager->disconnectAllDesignStudios();
+                }
+            });
+
     const QRect screenGeometry = QGuiApplication::primaryScreen()->geometry();
 
     qDebug() << "Qt Design Viewer";
diff --git a/src/backend/dsconnector/ds.cpp b/src/backend/dsconnector/ds.cpp
index 464ec80..d8ad95b 100644
--- a/src/backend/dsconnector/ds.cpp
+++ b/src/backend/dsconnector/ds.cpp
@@ -67,6 +67,12 @@ void DesignStudio::initPingPong()
             &QWebSocket::pong,
             this,
             [this](quint64 elapsedTime, const QByteArray &) {
+                if (elapsedTime > 1000)
+                    qWarning() << "Design Studio pong is too slow:" << elapsedTime
+                               << "ms. Newtork issue?";
+                else if (elapsedTime > 500)
+                    qWarning() << "Design Studio pong is slow:" << elapsedTime << "ms";
+
                 m_pongTimer.stop();
                 m_pingTimer.start();
             });
@@ -111,6 +117,12 @@ void DesignStudio::initSocket()
             &DesignStudio::processBinaryMessage);
 }
 
+void DesignStudio::disconnect()
+{
+    m_socket->close();
+    m_socket->abort();
+}
+
 QString DesignStudio::ipv4Addr() const
 {
     return m_socket->peerAddress().toString();
diff --git a/src/backend/dsconnector/ds.h b/src/backend/dsconnector/ds.h
index db69e0c..069c988 100644
--- a/src/backend/dsconnector/ds.h
+++ b/src/backend/dsconnector/ds.h
@@ -13,6 +13,9 @@ class DesignStudio : public QObject
 public:
     DesignStudio(QWebSocket *socket, const QString &deviceID, QObject *parent = nullptr);
 
+    // Connection
+    void disconnect();
+
     // Getters
     QString ipv4Addr() const;
     QString id() const;
diff --git a/src/backend/dsconnector/dsmanager.cpp b/src/backend/dsconnector/dsmanager.cpp
index e2c44b3..29d301f 100644
--- a/src/backend/dsconnector/dsmanager.cpp
+++ b/src/backend/dsconnector/dsmanager.cpp
@@ -136,3 +136,24 @@ QString DesignStudioManager::getDesignStudioIp(const QString &id) const
 
     return {};
 }
+
+bool DesignStudioManager::disconnectDesignStudio(const QString &id)
+{
+    for (const auto &designStudio : m_designStudios) {
+        if (designStudio->id() == id) {
+            qDebug() << "Disconnecting Design Studio" << id;
+            designStudio->disconnect();
+            return true;
+        }
+    }
+
+    qWarning() << "Design Studio" << id << "not found for disconnection";
+    return false;
+}
+
+void DesignStudioManager::disconnectAllDesignStudios()
+{
+    qDebug() << "Disconnecting all Design Studios";
+    for (const auto &designStudio : m_designStudios)
+        designStudio->disconnect();
+}
diff --git a/src/backend/dsconnector/dsmanager.h b/src/backend/dsconnector/dsmanager.h
index 708190b..661407a 100644
--- a/src/backend/dsconnector/dsmanager.h
+++ b/src/backend/dsconnector/dsmanager.h
@@ -21,6 +21,8 @@ public slots:
     void sendProjectStopped(const QString &id);
     void sendProjectLogs(const QString &id, const QString &logs);
     QString getDesignStudioIp(const QString &id) const;
+    bool disconnectDesignStudio(const QString &id);
+    void disconnectAllDesignStudios();
 
 private:
     // Network
-- 
GitLab