From 6ae4c71032e6b15dedd631dfff0c0c4cc4a8522a Mon Sep 17 00:00:00 2001 From: Daniel Teichmann Date: Tue, 10 Aug 2021 14:56:44 +0200 Subject: Complete restructure of current code tree --- images/clipboard.png.url | 1 - images/into-clipboard.svg | 1 - locales/de_DE.qm | Bin 17771 -> 0 bytes locales/de_DE.ts | 407 ---------------- locales/es_ES.qm | Bin 723 -> 0 bytes locales/es_ES.ts | 405 ---------------- locales/main_en.qm | Bin 1078 -> 0 bytes locales/main_en.ts | 405 ---------------- qml.qrc | 39 -- qtquickcontrols2.conf | 30 -- rwa-support-desktop.pro | 3 + rwa-support-desktopapp.pro | 87 ---- rwa-support-desktopapp/images/clipboard.png.url | 1 + rwa-support-desktopapp/images/into-clipboard.svg | 1 + rwa-support-desktopapp/locales/de_DE.qm | Bin 0 -> 17771 bytes rwa-support-desktopapp/locales/de_DE.ts | 407 ++++++++++++++++ rwa-support-desktopapp/locales/es_ES.qm | Bin 0 -> 723 bytes rwa-support-desktopapp/locales/es_ES.ts | 405 ++++++++++++++++ rwa-support-desktopapp/locales/main_en.qm | Bin 0 -> 1078 bytes rwa-support-desktopapp/locales/main_en.ts | 405 ++++++++++++++++ rwa-support-desktopapp/qml.qrc | 39 ++ rwa-support-desktopapp/qtquickcontrols2.conf | 30 ++ rwa-support-desktopapp/rwa-support-desktopapp.pro | 101 ++++ rwa-support-desktopapp/src/DBusAPI.cpp | 423 +++++++++++++++++ rwa-support-desktopapp/src/DBusAPI.h | 87 ++++ rwa-support-desktopapp/src/ListItem.qml | 45 ++ rwa-support-desktopapp/src/RWADBusAdaptor.cpp | 64 +++ rwa-support-desktopapp/src/RWADBusAdaptor.h | 151 ++++++ rwa-support-desktopapp/src/RWAHost.cpp | 68 +++ rwa-support-desktopapp/src/RWAHost.h | 63 +++ rwa-support-desktopapp/src/RWAHostModel.cpp | 37 ++ rwa-support-desktopapp/src/RWAHostModel.h | 23 + rwa-support-desktopapp/src/Toast.qml | 158 +++++++ rwa-support-desktopapp/src/ToastManager.qml | 89 ++++ rwa-support-desktopapp/src/main.cpp | 141 ++++++ rwa-support-desktopapp/src/main.qml | 418 +++++++++++++++++ rwa-support-desktopapp/src/main_qmladaptor.cpp | 344 ++++++++++++++ rwa-support-desktopapp/src/main_qmladaptor.h | 144 ++++++ .../src/scenes/Scene_no_server_available.qml | 71 +++ .../src/scenes/Scene_placeholder.qml | 56 +++ .../src/scenes/Scene_remote_view.qml | 371 +++++++++++++++ .../src/scenes/Scene_settings.qml | 34 ++ .../src/scenes/add_rwahost_wizard/Scene_step_1.qml | 282 ++++++++++++ .../add_rwahost_wizard/add_rwahost_wizard.cpp | 124 +++++ .../scenes/add_rwahost_wizard/add_rwahost_wizard.h | 61 +++ .../scenes/remote_control/Scene_remote_control.qml | 382 +++++++++++++++ .../remote_control/remote_control_manager.cpp | 511 +++++++++++++++++++++ .../scenes/remote_control/remote_control_manager.h | 78 ++++ rwa-support-desktopapp/src/session.cpp | 271 +++++++++++ rwa-support-desktopapp/src/session.h | 104 +++++ rwa-support-desktopapp/update_locales.sh | 29 ++ src/DBusAPI.cpp | 423 ----------------- src/DBusAPI.h | 87 ---- src/ListItem.qml | 45 -- src/RWADBusAdaptor.cpp | 64 --- src/RWADBusAdaptor.h | 151 ------ src/RWAHost.cpp | 68 --- src/RWAHost.h | 63 --- src/RWAHostModel.cpp | 37 -- src/RWAHostModel.h | 23 - src/Toast.qml | 158 ------- src/ToastManager.qml | 89 ---- src/main.cpp | 141 ------ src/main.qml | 418 ----------------- src/main_qmladaptor.cpp | 344 -------------- src/main_qmladaptor.h | 144 ------ src/scenes/Scene_no_server_available.qml | 71 --- src/scenes/Scene_placeholder.qml | 56 --- src/scenes/Scene_remote_view.qml | 371 --------------- src/scenes/Scene_settings.qml | 34 -- src/scenes/add_rwahost_wizard/Scene_step_1.qml | 282 ------------ .../add_rwahost_wizard/add_rwahost_wizard.cpp | 124 ----- src/scenes/add_rwahost_wizard/add_rwahost_wizard.h | 61 --- src/scenes/remote_control/Scene_remote_control.qml | 382 --------------- .../remote_control/remote_control_manager.cpp | 511 --------------------- src/scenes/remote_control/remote_control_manager.h | 78 ---- src/session.cpp | 271 ----------- src/session.h | 104 ----- tests/testqstring.cpp | 15 + tests/tests.pro | 4 + update_locales.sh | 29 -- 81 files changed, 6040 insertions(+), 6004 deletions(-) delete mode 100644 images/clipboard.png.url delete mode 100644 images/into-clipboard.svg delete mode 100644 locales/de_DE.qm delete mode 100644 locales/de_DE.ts delete mode 100644 locales/es_ES.qm delete mode 100644 locales/es_ES.ts delete mode 100644 locales/main_en.qm delete mode 100644 locales/main_en.ts delete mode 100644 qml.qrc delete mode 100644 qtquickcontrols2.conf create mode 100644 rwa-support-desktop.pro delete mode 100644 rwa-support-desktopapp.pro create mode 100644 rwa-support-desktopapp/images/clipboard.png.url create mode 100644 rwa-support-desktopapp/images/into-clipboard.svg create mode 100644 rwa-support-desktopapp/locales/de_DE.qm create mode 100644 rwa-support-desktopapp/locales/de_DE.ts create mode 100644 rwa-support-desktopapp/locales/es_ES.qm create mode 100644 rwa-support-desktopapp/locales/es_ES.ts create mode 100644 rwa-support-desktopapp/locales/main_en.qm create mode 100644 rwa-support-desktopapp/locales/main_en.ts create mode 100644 rwa-support-desktopapp/qml.qrc create mode 100644 rwa-support-desktopapp/qtquickcontrols2.conf create mode 100644 rwa-support-desktopapp/rwa-support-desktopapp.pro create mode 100644 rwa-support-desktopapp/src/DBusAPI.cpp create mode 100644 rwa-support-desktopapp/src/DBusAPI.h create mode 100644 rwa-support-desktopapp/src/ListItem.qml create mode 100644 rwa-support-desktopapp/src/RWADBusAdaptor.cpp create mode 100644 rwa-support-desktopapp/src/RWADBusAdaptor.h create mode 100644 rwa-support-desktopapp/src/RWAHost.cpp create mode 100644 rwa-support-desktopapp/src/RWAHost.h create mode 100644 rwa-support-desktopapp/src/RWAHostModel.cpp create mode 100644 rwa-support-desktopapp/src/RWAHostModel.h create mode 100644 rwa-support-desktopapp/src/Toast.qml create mode 100644 rwa-support-desktopapp/src/ToastManager.qml create mode 100644 rwa-support-desktopapp/src/main.cpp create mode 100644 rwa-support-desktopapp/src/main.qml create mode 100644 rwa-support-desktopapp/src/main_qmladaptor.cpp create mode 100644 rwa-support-desktopapp/src/main_qmladaptor.h create mode 100644 rwa-support-desktopapp/src/scenes/Scene_no_server_available.qml create mode 100644 rwa-support-desktopapp/src/scenes/Scene_placeholder.qml create mode 100644 rwa-support-desktopapp/src/scenes/Scene_remote_view.qml create mode 100644 rwa-support-desktopapp/src/scenes/Scene_settings.qml create mode 100644 rwa-support-desktopapp/src/scenes/add_rwahost_wizard/Scene_step_1.qml create mode 100644 rwa-support-desktopapp/src/scenes/add_rwahost_wizard/add_rwahost_wizard.cpp create mode 100644 rwa-support-desktopapp/src/scenes/add_rwahost_wizard/add_rwahost_wizard.h create mode 100644 rwa-support-desktopapp/src/scenes/remote_control/Scene_remote_control.qml create mode 100644 rwa-support-desktopapp/src/scenes/remote_control/remote_control_manager.cpp create mode 100644 rwa-support-desktopapp/src/scenes/remote_control/remote_control_manager.h create mode 100644 rwa-support-desktopapp/src/session.cpp create mode 100644 rwa-support-desktopapp/src/session.h create mode 100755 rwa-support-desktopapp/update_locales.sh delete mode 100644 src/DBusAPI.cpp delete mode 100644 src/DBusAPI.h delete mode 100644 src/ListItem.qml delete mode 100644 src/RWADBusAdaptor.cpp delete mode 100644 src/RWADBusAdaptor.h delete mode 100644 src/RWAHost.cpp delete mode 100644 src/RWAHost.h delete mode 100644 src/RWAHostModel.cpp delete mode 100644 src/RWAHostModel.h delete mode 100644 src/Toast.qml delete mode 100644 src/ToastManager.qml delete mode 100644 src/main.cpp delete mode 100644 src/main.qml delete mode 100644 src/main_qmladaptor.cpp delete mode 100644 src/main_qmladaptor.h delete mode 100644 src/scenes/Scene_no_server_available.qml delete mode 100644 src/scenes/Scene_placeholder.qml delete mode 100644 src/scenes/Scene_remote_view.qml delete mode 100644 src/scenes/Scene_settings.qml delete mode 100644 src/scenes/add_rwahost_wizard/Scene_step_1.qml delete mode 100644 src/scenes/add_rwahost_wizard/add_rwahost_wizard.cpp delete mode 100644 src/scenes/add_rwahost_wizard/add_rwahost_wizard.h delete mode 100644 src/scenes/remote_control/Scene_remote_control.qml delete mode 100644 src/scenes/remote_control/remote_control_manager.cpp delete mode 100644 src/scenes/remote_control/remote_control_manager.h delete mode 100644 src/session.cpp delete mode 100644 src/session.h create mode 100644 tests/testqstring.cpp create mode 100644 tests/tests.pro delete mode 100755 update_locales.sh diff --git a/images/clipboard.png.url b/images/clipboard.png.url deleted file mode 100644 index a023a15..0000000 --- a/images/clipboard.png.url +++ /dev/null @@ -1 +0,0 @@ -https://iconmonstr.com/clipboard-13-svg/ diff --git a/images/into-clipboard.svg b/images/into-clipboard.svg deleted file mode 100644 index ca9020e..0000000 --- a/images/into-clipboard.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/locales/de_DE.qm b/locales/de_DE.qm deleted file mode 100644 index 453dcd4..0000000 Binary files a/locales/de_DE.qm and /dev/null differ diff --git a/locales/de_DE.ts b/locales/de_DE.ts deleted file mode 100644 index 1582fcc..0000000 --- a/locales/de_DE.ts +++ /dev/null @@ -1,407 +0,0 @@ - - - - - AddRWAHostWizard - - Couldn't connect to the specified host! - Konnte nicht zum Server verbinden! - - - The specified host was already added! - Der angegebene RWA-Server wurde bereits hinzugefügt! - - - The specified host address is not valid! - Die angegebene Serveradresse enthält einen Fehler! - - - The features you expected here are not yet implemented. - Die Features die Sie erwartet hatten, sind noch nicht implementiert worden. - - - An error occured while adding a new host! - Ein Fehler trat auf beim Hinzufügen eines RWA-Servers! - - - Both textfields can't be empty! - Beide Felder müssen ausgefüllt werden! - - - The specified host address does not grant access! - Der angegebene Server gewährt keinen Zugang! - - - The specified host address is not supported! - Der angegebene Server wird nicht unterstützt! - - - Can't connect to underlying session service! - Es kann keine Verbindung zur Sitzungsverwaltung hergestellt werden! - - - - MainQMLAdaptor - - A host object in the response of D-Bus service lacks a necessary value. (host_url or host_uuid) - Ein Serverobject in der D-Bus Serviceantwort beeinhaltet nicht alle erforderlichen werte. (host_url oder host_uuid) - - - An error occured while adding a new host: - Ein Fehler trat auf beim Hinzufügen eines RWA-Servers: - - - Successfully added new RWAHost '%0' - Erfolgreich RWA-Server '%0' hinzugefügt - - - The error is not clear. The session service responded with status type '%0' - Der Fehler ist nicht klar. Der Sessionservice hat mit Statustype '%0' geantwortet - - - The error is not clear. The session service responded with no status type! - Der Fehler ist nicht klar. Der Sessionservice hat mit keinem Statustypen geantwortet! - - - No RWA host available! - Kein RWA-Server verfügbar! - - - Can't connect to underlying session service! - Es kann keine Verbindung zur Sitzungsverwaltung hergestellt werden! - - - Removed RWAHost '%0' - RWA-Server '%0' entfernt - - - - RemoteControlManager - - Stop remote support session - Stoppe Fernwartungssitzung - - - Start remote support session - Starte Fernwartungssitzung - - - Not available yet - Noch nicht verfügbar - - - Unknown state of service - Unbekannter Status des Dienstes - - - Remote Support session was stopped ungracefully - Fernwartungssitzung wurde unerwartet beendet - - - Remote Support session was stopped - Fernwartungssitzung wurde beendet - - - Your partner is connected to the Remote Support session - Fernwartungspartner ist mit dieser Sitzung verbunden - - - Remote Support session couldn't be started! - Fernwartungssitzung konnte nicht gestartet werden! - - - Session was started on '%0' successfully - Sitzung wurde erfolgreich auf '%0' gestartet - - - remote support partner could still be connected! - Es ist möglich, dass Ihr Fernwartungspartner noch verbunden ist! - - - Session could not be stopped! - Sitzung konnte nicht gestoppt werden! - - - Session status could not be refreshed! Your remote support partner could still be connected! - Sitzungstatus konnte nicht erneuert werden! Es ist möglich, dass der Fernwartungspartner noch verbunden ist! - - - Couldn't remove current session out of '_sessions' list. - Konnte aktuelle Sitzung nicht aus der Liste '_sessions' löschen. - - - currentSessionStartSucceeded(): Current Session is nullptr! - currentSessionStartSucceeded(): Aktuelle Sitzung ist nullptr! - - - Remote support session was stopped. - Fernwartungssitzung wurde beendet. - - - Remote Support session successfully started! Waiting for your remote support partner to connect. - Fernwartungssitzung wurde erfolgreich gestartet! Warte auf auf Verbindung vom Fernwartungspartner. - - - Session stopped successfully. - Fernwartungssitzung wurde erfolgreich beendet. - - - Creating a new session object. - Erstelle neues Sitzungsobjekt. - - - Can't start a remote support session. There is no RWA host is selected! - Kann keine Fernwartungssitzung starten. Es ist kein RWA-Server ausgewählt! - - - RemoteControlManager::handleConnectButtonClick(): Current Session is nullptr! - RemoteControlManager::handleConnectButtonClick(): Aktuelle Sitzung ist nullptr! - - - Starting a remote support session on host '%0' using the new session object. - Starte eine Fernwartungssitzung auf Server '%0' mithilfe des neuen Sitzungsobjektes. - - - - Scene_no_server_available - - Welcome! - Willkommen! - - - You need to add and select the remote web app server to which you want to connect. You can see a button to the left in the menu which says 'Add RWA-Server'. Follow the steps listed there and you can start your remote support session afterwards using the buttons above 'Add RWA-Server'. - Sie müssen zuerst einen RWA-Server hinzufügen und dann auswählen, um sich mit diesen zu verbinden. Auf der linken Seite befindet sich ein Knopf mit der Aufschrift 'RWA-Server hinzufügen'. Folgen Sie den Anweisungen dort und Sie können Ihre Fernwartungssitzung rasch starten. - - - - Scene_placeholder - - This is the placeholder scene! - Das hier ist eine Platzhalter Szene! - - - The features you expected here are not yet implemented. - Die Features die Sie erwartet hatten, sind noch nicht implementiert worden. - - - - Scene_remote_control - - Please tell your remote support partner your access address and your access-PIN to let your partner connect to this computer. - Bitte teile Ihrem Fernwartungspartner Ihre Zugangsadresse und Ihre Zugangs-PIN mit, damit sich dieser mit diesem Computer verbinden kann. - - - Remote Support Address - Zugangsadresse für Fernwartung - - - Copied access address into clipboard! - Zugangsadresse wurde in die Zwischenablage kopiert! - - - Copy the access address into the clipboard - Kopiere Zugangsadresse in die Zwischenablage - - - Session-ID - Sitzungs-ID - - - Copied session-ID into clipboard! - Sitzungs-ID wurde in die Zwischenablage kopiert! - - - Copy the session-ID into the clipboard - Kopiere Sitzungs-ID in die Zwischenablage - - - Access-PIN - Zugangs-PIN - - - Copied PIN into clipboard! - Zugangs-PIN wurde in die Zwischenablage kopiert! - - - Copy the pin into the clipboard - Kopiere Zugangspin in die Zwischenablage - - - Start remote support session - Starte Fernwartungssitzung - - - Stop remote support session - Stoppe Fernwartungssitzung - - - Unknown state of session service. - Unbekannter Status der Sitzungverwaltung. - - - - Scene_remote_view - - Please tell your remote support partner your access address and your access-PIN to let your partner connect to this computer. - Bitte teile Ihrem Fernwartungspartner Ihre Zugangsadresse und Ihre Zugangs-PIN mit, damit sich dieser mit diesem Computer verbinden kann. - - - Remote viewing Address - Zugangsadresse für Zuschauer - - - Copied access address into clipboard! - Zugangsadresse wurde in die Zwischenablage kopiert! - - - Copy the access address into the clipboard - Kopiere Zugangsadresse in die Zwischenablage - - - Session-ID - Sitzungs-ID - - - Copied session-ID into clipboard! - Sitzungs-ID wurde in die Zwischenablage kopiert! - - - Copy the session-ID into the clipboard - Kopiere Sitzungs-ID in die Zwischenablage - - - Access-PIN - Zugangs-PIN - - - Copied PIN into clipboard! - Zugangspin wurde in die Zwischenablage kopiert! - - - Copy the pin into the clipboard - Kopiere Zugangspin in die Zwischenablage - - - Start remote viewing session - Starte Zuschauersitzung - - - - Scene_step_1 - - Next Step - Nächster Schritt - - - Please input the address for the remote web app server which you want to connect to. -If you don't know what this means, ask your local administrator about it please. -Before you can start any remote sessions you will have to be approved for remote support. - Bitte gebe hier die Adresse für den RWA-Server ein, zudem Sie sich verbinden wollen. -Kontaktieren Sie bitte ihren lokalen Administrator bei Fragen. -Bevor Sie eine Fernwartungssitzung starten können, müssen Sie zuerst für das Fernwarten angenommen werden. - - - http://example.com:8000 - - - - Successfully added remote web app host. - Erfolgreich Fernwartungsserver hinzugefügt. - - - RWA host address - RWA-Server Adressse - - - My example host - Mein Beispiel Server - - - RWA host alias - RWA-Server Alias - - - - Session - - Not available yet - Noch nicht verfügbar - - - An error occured while creating a new session! - Ein Fehler trat auf bei dem Versuch eine Sitzung zu erstellen! - - - The session service is configured to not support multiple sessions and there is already a session running. - Die Sitzungsverwaltung ist so konfiguriert, dass nur eine Sitzung erlaubt ist und es ist bereits eine Sitzung am laufen. - - - Couldn't connect to host '%0'. - Konnte nicht zu RWA-Server '%0' verbinden. - - - The RWA host '%0' couldn't be found. - Konnte RWA-Server '%0' nicht finden. - - - The RWA host '%0' doesn't grant access. - Der RWA-Server '%0' gewährt keinen Zugang. - - - The RWA host '%0' is not supported. - Der RWA-Server '%0' wird nicht unterstützt. - - - Can't connect to underlying session service! Is the session service started? - Es kann keine Verbindung zur Sitzungsverwaltung hergestellt werden! Ist die Sitzungsverwaltung eingeschaltet? - - - - main - - Remote Support for your Desktop - Fernwartung für den Desktop - - - Allow Remote Control - Fernwartungssitzung erlauben - - - Remote Control - Fernwartung - - - Remote View - Fernbeobachtung - - - Settings - Einstellungen - - - You are not supposed to see this message. -This is a bug. - Diese Nachricht sollte nie gesehen werden. Das ist ein Bug. - - - Dark theme - Dunkelmodus - - - Allow remote control - Fernwartungssitzung erlauben - - - Allow remote view - Zuschauersitzung erlauben - - - Add RWA-Server - RWA-Server hinzufügen - - - Server addition wizard - Server hinzufügen - - - diff --git a/locales/es_ES.qm b/locales/es_ES.qm deleted file mode 100644 index 2d4045c..0000000 Binary files a/locales/es_ES.qm and /dev/null differ diff --git a/locales/es_ES.ts b/locales/es_ES.ts deleted file mode 100644 index f69359e..0000000 --- a/locales/es_ES.ts +++ /dev/null @@ -1,405 +0,0 @@ - - - - - AddRWAHostWizard - - Couldn't connect to the specified host! - - - - The specified host was already added! - - - - The specified host address is not valid! - - - - The features you expected here are not yet implemented. - - - - An error occured while adding a new host! - - - - Both textfields can't be empty! - - - - The specified host address does not grant access! - - - - The specified host address is not supported! - - - - Can't connect to underlying session service! - - - - - MainQMLAdaptor - - A host object in the response of D-Bus service lacks a necessary value. (host_url or host_uuid) - - - - An error occured while adding a new host: - - - - Successfully added new RWAHost '%0' - - - - The error is not clear. The session service responded with status type '%0' - - - - The error is not clear. The session service responded with no status type! - - - - No RWA host available! - - - - Can't connect to underlying session service! - - - - Removed RWAHost '%0' - - - - - RemoteControlManager - - Stop remote support session - - - - Start remote support session - - - - Not available yet - - - - Unknown state of service - Estado de servicio desconocido - - - Remote Support session was stopped ungracefully - - - - Remote Support session was stopped - - - - Your partner is connected to the Remote Support session - - - - Remote Support session couldn't be started! - - - - Session was started on '%0' successfully - - - - remote support partner could still be connected! - - - - Session could not be stopped! - - - - Session status could not be refreshed! Your remote support partner could still be connected! - - - - Couldn't remove current session out of '_sessions' list. - - - - currentSessionStartSucceeded(): Current Session is nullptr! - - - - Remote support session was stopped. - - - - Remote Support session successfully started! Waiting for your remote support partner to connect. - - - - Session stopped successfully. - - - - Creating a new session object. - - - - Can't start a remote support session. There is no RWA host is selected! - - - - RemoteControlManager::handleConnectButtonClick(): Current Session is nullptr! - - - - Starting a remote support session on host '%0' using the new session object. - - - - - Scene_no_server_available - - Welcome! - - - - You need to add and select the remote web app server to which you want to connect. You can see a button to the left in the menu which says 'Add RWA-Server'. Follow the steps listed there and you can start your remote support session afterwards using the buttons above 'Add RWA-Server'. - - - - - Scene_placeholder - - This is the placeholder scene! - - - - The features you expected here are not yet implemented. - - - - - Scene_remote_control - - Remote Support Address - - - - Copied access address into clipboard! - - - - Copy the access address into the clipboard - - - - Session-ID - - - - Copied session-ID into clipboard! - - - - Copy the session-ID into the clipboard - - - - Access-PIN - - - - Copied PIN into clipboard! - - - - Copy the pin into the clipboard - - - - Start remote support session - - - - Stop remote support session - - - - Please tell your remote support partner your access address and your access-PIN to let your partner connect to this computer. - - - - Unknown state of session service. - - - - - Scene_remote_view - - Please tell your remote support partner your access address and your access-PIN to let your partner connect to this computer. - - - - Remote viewing Address - - - - Copied access address into clipboard! - - - - Copy the access address into the clipboard - - - - Session-ID - - - - Copied session-ID into clipboard! - - - - Copy the session-ID into the clipboard - - - - Access-PIN - - - - Copied PIN into clipboard! - - - - Copy the pin into the clipboard - - - - Start remote viewing session - - - - - Scene_step_1 - - Next Step - - - - Please input the address for the remote web app server which you want to connect to. -If you don't know what this means, ask your local administrator about it please. -Before you can start any remote sessions you will have to be approved for remote support. - - - - http://example.com:8000 - - - - Successfully added remote web app host. - - - - RWA host address - - - - My example host - - - - RWA host alias - - - - - Session - - Not available yet - - - - An error occured while creating a new session! - - - - The session service is configured to not support multiple sessions and there is already a session running. - - - - Couldn't connect to host '%0'. - - - - The RWA host '%0' couldn't be found. - - - - The RWA host '%0' doesn't grant access. - - - - The RWA host '%0' is not supported. - - - - Can't connect to underlying session service! Is the session service started? - - - - - main - - Remote Support for your Desktop - Soporte remoto para su escritorio - - - You are not supposed to see this message. -This is a bug. - - - - Allow Remote Control - - - - Settings - - - - Dark theme - - - - Allow remote control - - - - Allow remote view - - - - Remote Control - - - - Remote View - - - - Add RWA-Server - - - - Server addition wizard - - - - diff --git a/locales/main_en.qm b/locales/main_en.qm deleted file mode 100644 index a0de2c8..0000000 Binary files a/locales/main_en.qm and /dev/null differ diff --git a/locales/main_en.ts b/locales/main_en.ts deleted file mode 100644 index 7e033d1..0000000 --- a/locales/main_en.ts +++ /dev/null @@ -1,405 +0,0 @@ - - - - - AddRWAHostWizard - - Couldn't connect to the specified host! - - - - The specified host was already added! - - - - The specified host address is not valid! - - - - The features you expected here are not yet implemented. - - - - An error occured while adding a new host! - - - - Both textfields can't be empty! - - - - The specified host address does not grant access! - - - - The specified host address is not supported! - - - - Can't connect to underlying session service! - - - - - MainQMLAdaptor - - A host object in the response of D-Bus service lacks a necessary value. (host_url or host_uuid) - - - - An error occured while adding a new host: - - - - Successfully added new RWAHost '%0' - - - - The error is not clear. The session service responded with status type '%0' - - - - The error is not clear. The session service responded with no status type! - - - - No RWA host available! - - - - Can't connect to underlying session service! - - - - Removed RWAHost '%0' - - - - - RemoteControlManager - - Stop remote support session - - - - Start remote support session - - - - Not available yet - - - - Unknown state of service - - - - Remote Support session was stopped ungracefully - - - - Remote Support session was stopped - - - - Your partner is connected to the Remote Support session - - - - Remote Support session couldn't be started! - - - - Session was started on '%0' successfully - - - - remote support partner could still be connected! - - - - Session could not be stopped! - - - - Session status could not be refreshed! Your remote support partner could still be connected! - - - - Couldn't remove current session out of '_sessions' list. - - - - currentSessionStartSucceeded(): Current Session is nullptr! - - - - Remote support session was stopped. - - - - Remote Support session successfully started! Waiting for your remote support partner to connect. - - - - Session stopped successfully. - - - - Creating a new session object. - - - - Can't start a remote support session. There is no RWA host is selected! - - - - RemoteControlManager::handleConnectButtonClick(): Current Session is nullptr! - - - - Starting a remote support session on host '%0' using the new session object. - - - - - Scene_no_server_available - - Welcome! - - - - You need to add and select the remote web app server to which you want to connect. You can see a button to the left in the menu which says 'Add RWA-Server'. Follow the steps listed there and you can start your remote support session afterwards using the buttons above 'Add RWA-Server'. - - - - - Scene_placeholder - - This is the placeholder scene! - - - - The features you expected here are not yet implemented. - - - - - Scene_remote_control - - Remote Support Address - - - - Copied access address into clipboard! - - - - Copy the access address into the clipboard - - - - Session-ID - - - - Copied session-ID into clipboard! - - - - Copy the session-ID into the clipboard - - - - Access-PIN - - - - Copied PIN into clipboard! - - - - Copy the pin into the clipboard - - - - Start remote support session - - - - Stop remote support session - - - - Please tell your remote support partner your access address and your access-PIN to let your partner connect to this computer. - - - - Unknown state of session service. - - - - - Scene_remote_view - - Please tell your remote support partner your access address and your access-PIN to let your partner connect to this computer. - - - - Remote viewing Address - - - - Copied access address into clipboard! - - - - Copy the access address into the clipboard - - - - Session-ID - - - - Copied session-ID into clipboard! - - - - Copy the session-ID into the clipboard - - - - Access-PIN - - - - Copied PIN into clipboard! - - - - Copy the pin into the clipboard - - - - Start remote viewing session - - - - - Scene_step_1 - - Next Step - - - - Please input the address for the remote web app server which you want to connect to. -If you don't know what this means, ask your local administrator about it please. -Before you can start any remote sessions you will have to be approved for remote support. - - - - http://example.com:8000 - - - - Successfully added remote web app host. - - - - RWA host address - - - - My example host - - - - RWA host alias - - - - - Session - - Not available yet - - - - An error occured while creating a new session! - - - - The session service is configured to not support multiple sessions and there is already a session running. - - - - Couldn't connect to host '%0'. - - - - The RWA host '%0' couldn't be found. - - - - The RWA host '%0' doesn't grant access. - - - - The RWA host '%0' is not supported. - - - - Can't connect to underlying session service! Is the session service started? - - - - - main - - Remote Support for your Desktop - - - - You are not supposed to see this message. -This is a bug. - - - - Allow Remote Control - - - - Settings - - - - Dark theme - - - - Allow remote control - - - - Allow remote view - - - - Remote Control - - - - Remote View - - - - Add RWA-Server - - - - Server addition wizard - - - - diff --git a/qml.qrc b/qml.qrc deleted file mode 100644 index 04ee201..0000000 --- a/qml.qrc +++ /dev/null @@ -1,39 +0,0 @@ - - - qtquickcontrols2.conf - images/into-clipboard.svg - locales/de_DE.ts - locales/de_DE.qm - locales/main_en.ts - locales/main_en.qm - locales/es_ES.ts - locales/es_ES.qm - src/main.qml - src/ListItem.qml - src/ToastManager.qml - src/Toast.qml - src/main.cpp - src/main_qmladaptor.cpp - src/main_qmladaptor.h - src/RWADBusAdaptor.cpp - src/RWADBusAdaptor.h - src/session.cpp - src/session.h - src/RWAHost.h - src/RWAHost.cpp - src/RWAHostModel.h - src/RWAHostModel.cpp - src/DBusAPI.h - src/DBusAPI.cpp - src/scenes/Scene_remote_view.qml - src/scenes/Scene_settings.qml - src/scenes/Scene_placeholder.qml - src/scenes/Scene_no_server_available.qml - src/scenes/add_rwahost_wizard/add_rwahost_wizard.cpp - src/scenes/add_rwahost_wizard/add_rwahost_wizard.h - src/scenes/add_rwahost_wizard/Scene_step_1.qml - src/scenes/remote_control/remote_control_manager.cpp - src/scenes/remote_control/remote_control_manager.h - src/scenes/remote_control/Scene_remote_control.qml - - diff --git a/qtquickcontrols2.conf b/qtquickcontrols2.conf deleted file mode 100644 index 8bcc85b..0000000 --- a/qtquickcontrols2.conf +++ /dev/null @@ -1,30 +0,0 @@ -# This file is part of Remote Support Desktop -# https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp -# Copyright 2020, 2021 Daniel Teichmann -# Copyright 2020, 2021 Mike Gabriel -# SPDX-License-Identifier: GPL-2.0-or-later -# -# 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. -# -# 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 General Public License -# along with this program; if not, write to the -# Free Software Foundation, Inc., -# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -[Controls] -Style=Material - -[Material] -Primary=Blue -Accent=Blue diff --git a/rwa-support-desktop.pro b/rwa-support-desktop.pro new file mode 100644 index 0000000..1ecb64f --- /dev/null +++ b/rwa-support-desktop.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs + +SUBDIRS = rwa-support-desktopapp tests diff --git a/rwa-support-desktopapp.pro b/rwa-support-desktopapp.pro deleted file mode 100644 index 96ecec3..0000000 --- a/rwa-support-desktopapp.pro +++ /dev/null @@ -1,87 +0,0 @@ -# This file is part of Remote Support Desktop -# https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp -# Copyright 2021 Daniel Teichmann -# Copyright 2021 Mike Gabriel -# SPDX-License-Identifier: GPL-2.0-or-later -# -# 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. -# -# 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 General Public License -# along with this program; if not, write to the -# Free Software Foundation, Inc., -# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -QT += quick -QT += quickcontrols2 -QT += widgets - -message(Building with DBUS (Freedesktop notifications) support) -DEFINES += USE_DBUS -QT += dbus - -CONFIG += c++11 - -# The following define makes your compiler emit warnings if you use -# any Qt feature that has been marked deprecated (the exact warnings -# depend on your compiler). Refer to the documentation for the -# deprecated API to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if it uses deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 -# disables all the APIs deprecated before Qt 6.0.0 - -SOURCES += src/main.cpp \ - src/main_qmladaptor.cpp \ - src/RWADBusAdaptor.cpp \ - src/session.cpp \ - src/RWAHostModel.cpp \ - src/RWAHost.cpp \ - src/DBusAPI.cpp \ - src/scenes/remote_control/remote_control_manager.cpp \ - src/scenes/add_rwahost_wizard/add_rwahost_wizard.cpp - -HEADERS += src/RWADBusAdaptor.h \ - src/main_qmladaptor.h \ - src/RWADBusAdaptor.h \ - src/scenes/remote_control/remote_control_manager.h \ - src/session.h \ - src/RWAHostModel.h \ - src/RWAHost.h \ - src/DBusAPI.h \ - src/scenes/remote_control/remote_control_manager.h \ - src/scenes/add_rwahost_wizard/add_rwahost_wizard.h - -TRANSLATIONS += locales/main_en.ts \ - locales/de_DE.ts \ - locales/es_ES.ts - -RESOURCES += qml.qrc - -# Additional import path used to resolve QML modules in Qt Creator's code model -QML_IMPORT_PATH = src/scenes - -# Additional import path used to resolve QML modules just for Qt Quick Designer -QML_DESIGNER_IMPORT_PATH = - -# Default rules for deployment. -qnx: target.path = /tmp/$${TARGET}/bin -else: unix:!android: target.path = /opt/$${TARGET}/bin -!isEmpty(target.path): INSTALLS += target - -#DISTFILES += - -CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT diff --git a/rwa-support-desktopapp/images/clipboard.png.url b/rwa-support-desktopapp/images/clipboard.png.url new file mode 100644 index 0000000..a023a15 --- /dev/null +++ b/rwa-support-desktopapp/images/clipboard.png.url @@ -0,0 +1 @@ +https://iconmonstr.com/clipboard-13-svg/ diff --git a/rwa-support-desktopapp/images/into-clipboard.svg b/rwa-support-desktopapp/images/into-clipboard.svg new file mode 100644 index 0000000..ca9020e --- /dev/null +++ b/rwa-support-desktopapp/images/into-clipboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/rwa-support-desktopapp/locales/de_DE.qm b/rwa-support-desktopapp/locales/de_DE.qm new file mode 100644 index 0000000..453dcd4 Binary files /dev/null and b/rwa-support-desktopapp/locales/de_DE.qm differ diff --git a/rwa-support-desktopapp/locales/de_DE.ts b/rwa-support-desktopapp/locales/de_DE.ts new file mode 100644 index 0000000..1582fcc --- /dev/null +++ b/rwa-support-desktopapp/locales/de_DE.ts @@ -0,0 +1,407 @@ + + + + + AddRWAHostWizard + + Couldn't connect to the specified host! + Konnte nicht zum Server verbinden! + + + The specified host was already added! + Der angegebene RWA-Server wurde bereits hinzugefügt! + + + The specified host address is not valid! + Die angegebene Serveradresse enthält einen Fehler! + + + The features you expected here are not yet implemented. + Die Features die Sie erwartet hatten, sind noch nicht implementiert worden. + + + An error occured while adding a new host! + Ein Fehler trat auf beim Hinzufügen eines RWA-Servers! + + + Both textfields can't be empty! + Beide Felder müssen ausgefüllt werden! + + + The specified host address does not grant access! + Der angegebene Server gewährt keinen Zugang! + + + The specified host address is not supported! + Der angegebene Server wird nicht unterstützt! + + + Can't connect to underlying session service! + Es kann keine Verbindung zur Sitzungsverwaltung hergestellt werden! + + + + MainQMLAdaptor + + A host object in the response of D-Bus service lacks a necessary value. (host_url or host_uuid) + Ein Serverobject in der D-Bus Serviceantwort beeinhaltet nicht alle erforderlichen werte. (host_url oder host_uuid) + + + An error occured while adding a new host: + Ein Fehler trat auf beim Hinzufügen eines RWA-Servers: + + + Successfully added new RWAHost '%0' + Erfolgreich RWA-Server '%0' hinzugefügt + + + The error is not clear. The session service responded with status type '%0' + Der Fehler ist nicht klar. Der Sessionservice hat mit Statustype '%0' geantwortet + + + The error is not clear. The session service responded with no status type! + Der Fehler ist nicht klar. Der Sessionservice hat mit keinem Statustypen geantwortet! + + + No RWA host available! + Kein RWA-Server verfügbar! + + + Can't connect to underlying session service! + Es kann keine Verbindung zur Sitzungsverwaltung hergestellt werden! + + + Removed RWAHost '%0' + RWA-Server '%0' entfernt + + + + RemoteControlManager + + Stop remote support session + Stoppe Fernwartungssitzung + + + Start remote support session + Starte Fernwartungssitzung + + + Not available yet + Noch nicht verfügbar + + + Unknown state of service + Unbekannter Status des Dienstes + + + Remote Support session was stopped ungracefully + Fernwartungssitzung wurde unerwartet beendet + + + Remote Support session was stopped + Fernwartungssitzung wurde beendet + + + Your partner is connected to the Remote Support session + Fernwartungspartner ist mit dieser Sitzung verbunden + + + Remote Support session couldn't be started! + Fernwartungssitzung konnte nicht gestartet werden! + + + Session was started on '%0' successfully + Sitzung wurde erfolgreich auf '%0' gestartet + + + remote support partner could still be connected! + Es ist möglich, dass Ihr Fernwartungspartner noch verbunden ist! + + + Session could not be stopped! + Sitzung konnte nicht gestoppt werden! + + + Session status could not be refreshed! Your remote support partner could still be connected! + Sitzungstatus konnte nicht erneuert werden! Es ist möglich, dass der Fernwartungspartner noch verbunden ist! + + + Couldn't remove current session out of '_sessions' list. + Konnte aktuelle Sitzung nicht aus der Liste '_sessions' löschen. + + + currentSessionStartSucceeded(): Current Session is nullptr! + currentSessionStartSucceeded(): Aktuelle Sitzung ist nullptr! + + + Remote support session was stopped. + Fernwartungssitzung wurde beendet. + + + Remote Support session successfully started! Waiting for your remote support partner to connect. + Fernwartungssitzung wurde erfolgreich gestartet! Warte auf auf Verbindung vom Fernwartungspartner. + + + Session stopped successfully. + Fernwartungssitzung wurde erfolgreich beendet. + + + Creating a new session object. + Erstelle neues Sitzungsobjekt. + + + Can't start a remote support session. There is no RWA host is selected! + Kann keine Fernwartungssitzung starten. Es ist kein RWA-Server ausgewählt! + + + RemoteControlManager::handleConnectButtonClick(): Current Session is nullptr! + RemoteControlManager::handleConnectButtonClick(): Aktuelle Sitzung ist nullptr! + + + Starting a remote support session on host '%0' using the new session object. + Starte eine Fernwartungssitzung auf Server '%0' mithilfe des neuen Sitzungsobjektes. + + + + Scene_no_server_available + + Welcome! + Willkommen! + + + You need to add and select the remote web app server to which you want to connect. You can see a button to the left in the menu which says 'Add RWA-Server'. Follow the steps listed there and you can start your remote support session afterwards using the buttons above 'Add RWA-Server'. + Sie müssen zuerst einen RWA-Server hinzufügen und dann auswählen, um sich mit diesen zu verbinden. Auf der linken Seite befindet sich ein Knopf mit der Aufschrift 'RWA-Server hinzufügen'. Folgen Sie den Anweisungen dort und Sie können Ihre Fernwartungssitzung rasch starten. + + + + Scene_placeholder + + This is the placeholder scene! + Das hier ist eine Platzhalter Szene! + + + The features you expected here are not yet implemented. + Die Features die Sie erwartet hatten, sind noch nicht implementiert worden. + + + + Scene_remote_control + + Please tell your remote support partner your access address and your access-PIN to let your partner connect to this computer. + Bitte teile Ihrem Fernwartungspartner Ihre Zugangsadresse und Ihre Zugangs-PIN mit, damit sich dieser mit diesem Computer verbinden kann. + + + Remote Support Address + Zugangsadresse für Fernwartung + + + Copied access address into clipboard! + Zugangsadresse wurde in die Zwischenablage kopiert! + + + Copy the access address into the clipboard + Kopiere Zugangsadresse in die Zwischenablage + + + Session-ID + Sitzungs-ID + + + Copied session-ID into clipboard! + Sitzungs-ID wurde in die Zwischenablage kopiert! + + + Copy the session-ID into the clipboard + Kopiere Sitzungs-ID in die Zwischenablage + + + Access-PIN + Zugangs-PIN + + + Copied PIN into clipboard! + Zugangs-PIN wurde in die Zwischenablage kopiert! + + + Copy the pin into the clipboard + Kopiere Zugangspin in die Zwischenablage + + + Start remote support session + Starte Fernwartungssitzung + + + Stop remote support session + Stoppe Fernwartungssitzung + + + Unknown state of session service. + Unbekannter Status der Sitzungverwaltung. + + + + Scene_remote_view + + Please tell your remote support partner your access address and your access-PIN to let your partner connect to this computer. + Bitte teile Ihrem Fernwartungspartner Ihre Zugangsadresse und Ihre Zugangs-PIN mit, damit sich dieser mit diesem Computer verbinden kann. + + + Remote viewing Address + Zugangsadresse für Zuschauer + + + Copied access address into clipboard! + Zugangsadresse wurde in die Zwischenablage kopiert! + + + Copy the access address into the clipboard + Kopiere Zugangsadresse in die Zwischenablage + + + Session-ID + Sitzungs-ID + + + Copied session-ID into clipboard! + Sitzungs-ID wurde in die Zwischenablage kopiert! + + + Copy the session-ID into the clipboard + Kopiere Sitzungs-ID in die Zwischenablage + + + Access-PIN + Zugangs-PIN + + + Copied PIN into clipboard! + Zugangspin wurde in die Zwischenablage kopiert! + + + Copy the pin into the clipboard + Kopiere Zugangspin in die Zwischenablage + + + Start remote viewing session + Starte Zuschauersitzung + + + + Scene_step_1 + + Next Step + Nächster Schritt + + + Please input the address for the remote web app server which you want to connect to. +If you don't know what this means, ask your local administrator about it please. +Before you can start any remote sessions you will have to be approved for remote support. + Bitte gebe hier die Adresse für den RWA-Server ein, zudem Sie sich verbinden wollen. +Kontaktieren Sie bitte ihren lokalen Administrator bei Fragen. +Bevor Sie eine Fernwartungssitzung starten können, müssen Sie zuerst für das Fernwarten angenommen werden. + + + http://example.com:8000 + + + + Successfully added remote web app host. + Erfolgreich Fernwartungsserver hinzugefügt. + + + RWA host address + RWA-Server Adressse + + + My example host + Mein Beispiel Server + + + RWA host alias + RWA-Server Alias + + + + Session + + Not available yet + Noch nicht verfügbar + + + An error occured while creating a new session! + Ein Fehler trat auf bei dem Versuch eine Sitzung zu erstellen! + + + The session service is configured to not support multiple sessions and there is already a session running. + Die Sitzungsverwaltung ist so konfiguriert, dass nur eine Sitzung erlaubt ist und es ist bereits eine Sitzung am laufen. + + + Couldn't connect to host '%0'. + Konnte nicht zu RWA-Server '%0' verbinden. + + + The RWA host '%0' couldn't be found. + Konnte RWA-Server '%0' nicht finden. + + + The RWA host '%0' doesn't grant access. + Der RWA-Server '%0' gewährt keinen Zugang. + + + The RWA host '%0' is not supported. + Der RWA-Server '%0' wird nicht unterstützt. + + + Can't connect to underlying session service! Is the session service started? + Es kann keine Verbindung zur Sitzungsverwaltung hergestellt werden! Ist die Sitzungsverwaltung eingeschaltet? + + + + main + + Remote Support for your Desktop + Fernwartung für den Desktop + + + Allow Remote Control + Fernwartungssitzung erlauben + + + Remote Control + Fernwartung + + + Remote View + Fernbeobachtung + + + Settings + Einstellungen + + + You are not supposed to see this message. +This is a bug. + Diese Nachricht sollte nie gesehen werden. Das ist ein Bug. + + + Dark theme + Dunkelmodus + + + Allow remote control + Fernwartungssitzung erlauben + + + Allow remote view + Zuschauersitzung erlauben + + + Add RWA-Server + RWA-Server hinzufügen + + + Server addition wizard + Server hinzufügen + + + diff --git a/rwa-support-desktopapp/locales/es_ES.qm b/rwa-support-desktopapp/locales/es_ES.qm new file mode 100644 index 0000000..2d4045c Binary files /dev/null and b/rwa-support-desktopapp/locales/es_ES.qm differ diff --git a/rwa-support-desktopapp/locales/es_ES.ts b/rwa-support-desktopapp/locales/es_ES.ts new file mode 100644 index 0000000..f69359e --- /dev/null +++ b/rwa-support-desktopapp/locales/es_ES.ts @@ -0,0 +1,405 @@ + + + + + AddRWAHostWizard + + Couldn't connect to the specified host! + + + + The specified host was already added! + + + + The specified host address is not valid! + + + + The features you expected here are not yet implemented. + + + + An error occured while adding a new host! + + + + Both textfields can't be empty! + + + + The specified host address does not grant access! + + + + The specified host address is not supported! + + + + Can't connect to underlying session service! + + + + + MainQMLAdaptor + + A host object in the response of D-Bus service lacks a necessary value. (host_url or host_uuid) + + + + An error occured while adding a new host: + + + + Successfully added new RWAHost '%0' + + + + The error is not clear. The session service responded with status type '%0' + + + + The error is not clear. The session service responded with no status type! + + + + No RWA host available! + + + + Can't connect to underlying session service! + + + + Removed RWAHost '%0' + + + + + RemoteControlManager + + Stop remote support session + + + + Start remote support session + + + + Not available yet + + + + Unknown state of service + Estado de servicio desconocido + + + Remote Support session was stopped ungracefully + + + + Remote Support session was stopped + + + + Your partner is connected to the Remote Support session + + + + Remote Support session couldn't be started! + + + + Session was started on '%0' successfully + + + + remote support partner could still be connected! + + + + Session could not be stopped! + + + + Session status could not be refreshed! Your remote support partner could still be connected! + + + + Couldn't remove current session out of '_sessions' list. + + + + currentSessionStartSucceeded(): Current Session is nullptr! + + + + Remote support session was stopped. + + + + Remote Support session successfully started! Waiting for your remote support partner to connect. + + + + Session stopped successfully. + + + + Creating a new session object. + + + + Can't start a remote support session. There is no RWA host is selected! + + + + RemoteControlManager::handleConnectButtonClick(): Current Session is nullptr! + + + + Starting a remote support session on host '%0' using the new session object. + + + + + Scene_no_server_available + + Welcome! + + + + You need to add and select the remote web app server to which you want to connect. You can see a button to the left in the menu which says 'Add RWA-Server'. Follow the steps listed there and you can start your remote support session afterwards using the buttons above 'Add RWA-Server'. + + + + + Scene_placeholder + + This is the placeholder scene! + + + + The features you expected here are not yet implemented. + + + + + Scene_remote_control + + Remote Support Address + + + + Copied access address into clipboard! + + + + Copy the access address into the clipboard + + + + Session-ID + + + + Copied session-ID into clipboard! + + + + Copy the session-ID into the clipboard + + + + Access-PIN + + + + Copied PIN into clipboard! + + + + Copy the pin into the clipboard + + + + Start remote support session + + + + Stop remote support session + + + + Please tell your remote support partner your access address and your access-PIN to let your partner connect to this computer. + + + + Unknown state of session service. + + + + + Scene_remote_view + + Please tell your remote support partner your access address and your access-PIN to let your partner connect to this computer. + + + + Remote viewing Address + + + + Copied access address into clipboard! + + + + Copy the access address into the clipboard + + + + Session-ID + + + + Copied session-ID into clipboard! + + + + Copy the session-ID into the clipboard + + + + Access-PIN + + + + Copied PIN into clipboard! + + + + Copy the pin into the clipboard + + + + Start remote viewing session + + + + + Scene_step_1 + + Next Step + + + + Please input the address for the remote web app server which you want to connect to. +If you don't know what this means, ask your local administrator about it please. +Before you can start any remote sessions you will have to be approved for remote support. + + + + http://example.com:8000 + + + + Successfully added remote web app host. + + + + RWA host address + + + + My example host + + + + RWA host alias + + + + + Session + + Not available yet + + + + An error occured while creating a new session! + + + + The session service is configured to not support multiple sessions and there is already a session running. + + + + Couldn't connect to host '%0'. + + + + The RWA host '%0' couldn't be found. + + + + The RWA host '%0' doesn't grant access. + + + + The RWA host '%0' is not supported. + + + + Can't connect to underlying session service! Is the session service started? + + + + + main + + Remote Support for your Desktop + Soporte remoto para su escritorio + + + You are not supposed to see this message. +This is a bug. + + + + Allow Remote Control + + + + Settings + + + + Dark theme + + + + Allow remote control + + + + Allow remote view + + + + Remote Control + + + + Remote View + + + + Add RWA-Server + + + + Server addition wizard + + + + diff --git a/rwa-support-desktopapp/locales/main_en.qm b/rwa-support-desktopapp/locales/main_en.qm new file mode 100644 index 0000000..a0de2c8 Binary files /dev/null and b/rwa-support-desktopapp/locales/main_en.qm differ diff --git a/rwa-support-desktopapp/locales/main_en.ts b/rwa-support-desktopapp/locales/main_en.ts new file mode 100644 index 0000000..7e033d1 --- /dev/null +++ b/rwa-support-desktopapp/locales/main_en.ts @@ -0,0 +1,405 @@ + + + + + AddRWAHostWizard + + Couldn't connect to the specified host! + + + + The specified host was already added! + + + + The specified host address is not valid! + + + + The features you expected here are not yet implemented. + + + + An error occured while adding a new host! + + + + Both textfields can't be empty! + + + + The specified host address does not grant access! + + + + The specified host address is not supported! + + + + Can't connect to underlying session service! + + + + + MainQMLAdaptor + + A host object in the response of D-Bus service lacks a necessary value. (host_url or host_uuid) + + + + An error occured while adding a new host: + + + + Successfully added new RWAHost '%0' + + + + The error is not clear. The session service responded with status type '%0' + + + + The error is not clear. The session service responded with no status type! + + + + No RWA host available! + + + + Can't connect to underlying session service! + + + + Removed RWAHost '%0' + + + + + RemoteControlManager + + Stop remote support session + + + + Start remote support session + + + + Not available yet + + + + Unknown state of service + + + + Remote Support session was stopped ungracefully + + + + Remote Support session was stopped + + + + Your partner is connected to the Remote Support session + + + + Remote Support session couldn't be started! + + + + Session was started on '%0' successfully + + + + remote support partner could still be connected! + + + + Session could not be stopped! + + + + Session status could not be refreshed! Your remote support partner could still be connected! + + + + Couldn't remove current session out of '_sessions' list. + + + + currentSessionStartSucceeded(): Current Session is nullptr! + + + + Remote support session was stopped. + + + + Remote Support session successfully started! Waiting for your remote support partner to connect. + + + + Session stopped successfully. + + + + Creating a new session object. + + + + Can't start a remote support session. There is no RWA host is selected! + + + + RemoteControlManager::handleConnectButtonClick(): Current Session is nullptr! + + + + Starting a remote support session on host '%0' using the new session object. + + + + + Scene_no_server_available + + Welcome! + + + + You need to add and select the remote web app server to which you want to connect. You can see a button to the left in the menu which says 'Add RWA-Server'. Follow the steps listed there and you can start your remote support session afterwards using the buttons above 'Add RWA-Server'. + + + + + Scene_placeholder + + This is the placeholder scene! + + + + The features you expected here are not yet implemented. + + + + + Scene_remote_control + + Remote Support Address + + + + Copied access address into clipboard! + + + + Copy the access address into the clipboard + + + + Session-ID + + + + Copied session-ID into clipboard! + + + + Copy the session-ID into the clipboard + + + + Access-PIN + + + + Copied PIN into clipboard! + + + + Copy the pin into the clipboard + + + + Start remote support session + + + + Stop remote support session + + + + Please tell your remote support partner your access address and your access-PIN to let your partner connect to this computer. + + + + Unknown state of session service. + + + + + Scene_remote_view + + Please tell your remote support partner your access address and your access-PIN to let your partner connect to this computer. + + + + Remote viewing Address + + + + Copied access address into clipboard! + + + + Copy the access address into the clipboard + + + + Session-ID + + + + Copied session-ID into clipboard! + + + + Copy the session-ID into the clipboard + + + + Access-PIN + + + + Copied PIN into clipboard! + + + + Copy the pin into the clipboard + + + + Start remote viewing session + + + + + Scene_step_1 + + Next Step + + + + Please input the address for the remote web app server which you want to connect to. +If you don't know what this means, ask your local administrator about it please. +Before you can start any remote sessions you will have to be approved for remote support. + + + + http://example.com:8000 + + + + Successfully added remote web app host. + + + + RWA host address + + + + My example host + + + + RWA host alias + + + + + Session + + Not available yet + + + + An error occured while creating a new session! + + + + The session service is configured to not support multiple sessions and there is already a session running. + + + + Couldn't connect to host '%0'. + + + + The RWA host '%0' couldn't be found. + + + + The RWA host '%0' doesn't grant access. + + + + The RWA host '%0' is not supported. + + + + Can't connect to underlying session service! Is the session service started? + + + + + main + + Remote Support for your Desktop + + + + You are not supposed to see this message. +This is a bug. + + + + Allow Remote Control + + + + Settings + + + + Dark theme + + + + Allow remote control + + + + Allow remote view + + + + Remote Control + + + + Remote View + + + + Add RWA-Server + + + + Server addition wizard + + + + diff --git a/rwa-support-desktopapp/qml.qrc b/rwa-support-desktopapp/qml.qrc new file mode 100644 index 0000000..04ee201 --- /dev/null +++ b/rwa-support-desktopapp/qml.qrc @@ -0,0 +1,39 @@ + + + qtquickcontrols2.conf + images/into-clipboard.svg + locales/de_DE.ts + locales/de_DE.qm + locales/main_en.ts + locales/main_en.qm + locales/es_ES.ts + locales/es_ES.qm + src/main.qml + src/ListItem.qml + src/ToastManager.qml + src/Toast.qml + src/main.cpp + src/main_qmladaptor.cpp + src/main_qmladaptor.h + src/RWADBusAdaptor.cpp + src/RWADBusAdaptor.h + src/session.cpp + src/session.h + src/RWAHost.h + src/RWAHost.cpp + src/RWAHostModel.h + src/RWAHostModel.cpp + src/DBusAPI.h + src/DBusAPI.cpp + src/scenes/Scene_remote_view.qml + src/scenes/Scene_settings.qml + src/scenes/Scene_placeholder.qml + src/scenes/Scene_no_server_available.qml + src/scenes/add_rwahost_wizard/add_rwahost_wizard.cpp + src/scenes/add_rwahost_wizard/add_rwahost_wizard.h + src/scenes/add_rwahost_wizard/Scene_step_1.qml + src/scenes/remote_control/remote_control_manager.cpp + src/scenes/remote_control/remote_control_manager.h + src/scenes/remote_control/Scene_remote_control.qml + + diff --git a/rwa-support-desktopapp/qtquickcontrols2.conf b/rwa-support-desktopapp/qtquickcontrols2.conf new file mode 100644 index 0000000..8bcc85b --- /dev/null +++ b/rwa-support-desktopapp/qtquickcontrols2.conf @@ -0,0 +1,30 @@ +# This file is part of Remote Support Desktop +# https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp +# Copyright 2020, 2021 Daniel Teichmann +# Copyright 2020, 2021 Mike Gabriel +# SPDX-License-Identifier: GPL-2.0-or-later +# +# 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. +# +# 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 General Public License +# along with this program; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +[Controls] +Style=Material + +[Material] +Primary=Blue +Accent=Blue diff --git a/rwa-support-desktopapp/rwa-support-desktopapp.pro b/rwa-support-desktopapp/rwa-support-desktopapp.pro new file mode 100644 index 0000000..a013742 --- /dev/null +++ b/rwa-support-desktopapp/rwa-support-desktopapp.pro @@ -0,0 +1,101 @@ +# This file is part of Remote Support Desktop +# https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp +# Copyright 2021 Daniel Teichmann +# Copyright 2021 Mike Gabriel +# SPDX-License-Identifier: GPL-2.0-or-later +# +# 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. +# +# 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 General Public License +# along with this program; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +QT += quick +QT += quickcontrols2 +QT += widgets + + +QT += testlib +CONFIG += testcase +CONFIG += no_testcase_installs + +#test_conf { +# TARGET = rwa-support-desktop-tests +# QT += testlib +# SOURCES += testqstring.cpp +# HEADERS += +#} else { +# SOURCES += src/main.cpp +#} + +message(Building with DBUS (Freedesktop notifications) support) +DEFINES += USE_DBUS +QT += dbus + +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Refer to the documentation for the +# deprecated API to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 +# disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += src/main.cpp \ + src/main_qmladaptor.cpp \ + src/RWADBusAdaptor.cpp \ + src/session.cpp \ + src/RWAHostModel.cpp \ + src/RWAHost.cpp \ + src/DBusAPI.cpp \ + src/scenes/remote_control/remote_control_manager.cpp \ + src/scenes/add_rwahost_wizard/add_rwahost_wizard.cpp \ + +HEADERS += src/RWADBusAdaptor.h \ + src/main_qmladaptor.h \ + src/RWADBusAdaptor.h \ + src/scenes/remote_control/remote_control_manager.h \ + src/session.h \ + src/RWAHostModel.h \ + src/RWAHost.h \ + src/DBusAPI.h \ + src/scenes/remote_control/remote_control_manager.h \ + src/scenes/add_rwahost_wizard/add_rwahost_wizard.h + +TRANSLATIONS += locales/main_en.ts \ + locales/de_DE.ts \ + locales/es_ES.ts + +RESOURCES += qml.qrc + +# Additional import path used to resolve QML modules in Qt Creator's code model +QML_IMPORT_PATH = src/scenes + +# Additional import path used to resolve QML modules just for Qt Quick Designer +QML_DESIGNER_IMPORT_PATH = + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +#DISTFILES += + +CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT diff --git a/rwa-support-desktopapp/src/DBusAPI.cpp b/rwa-support-desktopapp/src/DBusAPI.cpp new file mode 100644 index 0000000..9a0f8de --- /dev/null +++ b/rwa-support-desktopapp/src/DBusAPI.cpp @@ -0,0 +1,423 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2021 Daniel Teichmann + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "DBusAPI.h" + +/*! + * \class DBusAPI + * \brief The DBusAPI class provides all necessary D-Bus methods and distributes the response via signals. + */ +DBusAPI::DBusAPI() { + _initDBus(); +} + +/*! + * \brief Initializes private _dbus_rwa object. + */ +void DBusAPI::_initDBus() { + if (!QDBusConnection::sessionBus().isConnected()) { + qCritical() << "Cannot connect to the D-Bus session bus."; + } + + // Create DBus object + _dbus_rwa = new OrgArcticaProjectRWASupportSessionServiceInterface("org.ArcticaProject.RWASupportSessionService", + "/RWASupportSessionService", + QDBusConnection::sessionBus(), + this->parent()); + + qDebug("Initialized DBus object!"); +} + +/*! + * \brief Ask the session service to start a session. + * + * \a host RWAHost object which includes all necessary information about a RWA host. + */ +void DBusAPI::start_request(RWAHost *host) { + Q_ASSERT(host != nullptr); + + qDebug() << "Requesting D-Bus service to start a new session on host:" << host->alias(); + + // Make an asynchronous 'start' call (Response will be sent to 'start_reply') + QDBusPendingCall async = _dbus_rwa->asyncCall("start", host->uuid()); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); + + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(start_reply(QDBusPendingCallWatcher*))); +} + +/*! + * \brief Method gets called when a D-Bus response is ready. + * + * \a call contains the D-Bus response (session service or for example maybe just a error message). + * + * TODO: Example of json input + */ +void DBusAPI::start_reply(QDBusPendingCallWatcher *call) { + QString result = ""; + QDBusPendingReply reply = *call; + if (reply.isError()) { + qCritical() << "D-Bus 'start' request failed, this was the reply:"; + qCritical() << reply.error(); + + if (QDBusError::ServiceUnknown == reply.error().type()) { + qCritical() << "The session service was probably just not started!"; + } + + emit serviceStartResponse(nullptr); + + return; + } else { + result = reply.argumentAt<0>(); + } + call->deleteLater(); + + qDebug() << "Raw JSON from starting session is:" << result.toUtf8().replace('"', ""); + QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); + + emit serviceStartResponse(&doc); +} + +/*! + * \brief Ask the session service to stop session #. + * + * \a host RWAHost object which includes all necessary information about a RWA host. + * + * \a session_id Unique identifier for a session in a specific host. + */ +void DBusAPI::stop_request(RWAHost *host, QString session_id) { + Q_ASSERT(host != nullptr); + Q_ASSERT(session_id != ""); + + bool ok; + long long session_id_number = session_id.toLongLong(&ok); + + // Sanity Check + if(ok == false){ + qWarning().noquote() << QString("Unable to parse session_id '%0' as long long!").arg(session_id); + return; + } + + qDebug().noquote() << QString("Requesting D-Bus service to stop " + "session #'%0' on host '%1'") + .arg(session_id) + .arg(host->alias()); + + // Make an asynchronous 'stop' call (Response will be sent to 'stop_reply') + QDBusPendingCall async = _dbus_rwa->asyncCall("stop", host->uuid(), session_id_number); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); + + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(stop_reply(QDBusPendingCallWatcher*))); +} + +/*! + * \brief Method gets called when a D-Bus response is ready. + * + * \a call contains the D-Bus response (session service or for example maybe just a error message). + * + * TODO: Example of json input + */ +void DBusAPI::stop_reply(QDBusPendingCallWatcher *call) { + QString result = ""; + + QDBusPendingReply reply = *call; + if (reply.isError()) { + qCritical() << "D-Bus 'stop' request failed, this was the reply:"; + qCritical() << reply.error(); + + if (QDBusError::ServiceUnknown == reply.error().type()) { + qCritical() << "The session service was probably just not started!"; + } + + emit serviceStopResponse(nullptr); + + return; + } else { + result = reply.argumentAt<0>(); + } + call->deleteLater(); + + qDebug() << "Raw JSON from stopping a session is:" << result.toUtf8().replace('"', ""); + QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); + + emit serviceStopResponse(&doc); +} + +/*! + * \brief Ask the session service for status of . + * + * \a host RWAHost object which includes all necessary information about a RWA host. + * + * \a session_id Unique identifier for a session in a specific host. + */ +void DBusAPI::status_request(RWAHost *host, QString session_id) { + Q_ASSERT(host != nullptr); + Q_ASSERT(session_id != ""); + + bool ok; + long long session_id_number = session_id.toLongLong(&ok); + + // Sanity Check + if(ok == false){ + qWarning().noquote() << QString("Unable to parse session_id '%0' as long long!").arg(session_id); + return; + } + + qDebug().noquote() << QString("Requesting D-Bus service for status of session " + "#'%0' on host '%1'").arg(session_id).arg(host->alias()); + + // Make an asynchronous 'start' call (Response will be sent to 'status_reply') + QDBusPendingCall async = _dbus_rwa->asyncCall("status", host->uuid(), session_id_number); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); + + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(status_reply(QDBusPendingCallWatcher*))); +} + +/*! + * \brief Forces the session service to refresh it's status of and tell us about it then. + * + * \a host RWAHost object which includes all necessary information about a RWA host. + * + * \a session_id Unique identifier for a session in a specific host. + */ +void DBusAPI::refresh_status_request(RWAHost *host, QString session_id) { + Q_ASSERT(host != nullptr); + Q_ASSERT(session_id != ""); + + bool ok; + long long session_id_number = session_id.toLongLong(&ok); + + // Sanity Check + if(ok == false){ + qWarning().noquote() << QString("Unable to parse session_id '%0' as long long!").arg(session_id); + return; + } + + qDebug().noquote() << QString("Requesting D-Bus service for refresh_status of session " + "#'%0' on host '%1'").arg(session_id).arg(host->alias()); + + // Make an asynchronous 'start' call (Response will be sent to 'status_reply') + QDBusPendingCall async = _dbus_rwa->asyncCall("refresh_status", host->uuid(), session_id_number); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); + + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(status_reply(QDBusPendingCallWatcher*))); +} + +/*! + * \brief Method gets called when a D-Bus response is ready. + * + * \a call contains the D-Bus response (session service or for example maybe just a error message). + * + * TODO: Example of json input + */ +void DBusAPI::status_reply(QDBusPendingCallWatcher *call){ + QString result = ""; + + QDBusPendingReply reply = *call; + if (reply.isError()) { + qCritical() << "D-Bus '(refresh_)status' request failed, this was the reply:"; + qCritical() << reply.error(); + + if (QDBusError::ServiceUnknown == reply.error().type()) { + qCritical() << "The session service was probably just not started!"; + } + + emit serviceStatusResponse(nullptr); + + return; + } else { + result = reply.argumentAt<0>(); + } + call->deleteLater(); + + // Get the QJsonObject + qDebug() << "Raw JSON from a status request for a session is:" << result.toUtf8().replace('"', ""); + QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); + + emit serviceStatusResponse(&doc); +} + +/*! + * \brief This method requests the session service to list all RWAHosts. + */ +void DBusAPI::get_web_app_hosts_request() { + qDebug().noquote() << QString("Requesting D-Bus service to list " + "all remote web app hosts"); + + // Make an asynchronous 'get_web_app_hosts' call + // Response will be sent to 'get_web_app_hosts_reply' + QDBusPendingCall async = _dbus_rwa->asyncCall("get_web_app_hosts"); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); + + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(get_web_app_hosts_reply(QDBusPendingCallWatcher*))); +} + +/*! + * \brief This method requests the session service to add a RWAHost to its configuration files. + * + * \a host_url is the remote web app adress which will be used by the session service to coordinate + * sessions, connections, settings and such. + */ +void DBusAPI::add_web_app_host_request(QString host_url, QString host_alias) { + Q_ASSERT(host_url != ""); + Q_ASSERT(host_alias != ""); + + qDebug().noquote() << QString("Requesting D-Bus service to register new " + "remote web app host '%0' with url '%1'").arg(host_alias).arg(host_url); + + // Make an asynchronous 'add_web_app_host' call + // Response will be sent to 'add_web_app_host_reply' + QDBusPendingCall async = _dbus_rwa->asyncCall("add_web_app_host", host_url, host_alias); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); + + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(add_web_app_host_reply(QDBusPendingCallWatcher*))); +} + +/*! + * \brief This method requests the session service to remove a RWAHost from its configuration files. + * + * \a host_uuid Unique identifier which all hosts have. + */ +void DBusAPI::remove_web_app_host_request(QString host_uuid) { + Q_ASSERT(host_uuid != ""); + + qDebug().noquote() << QString("Requesting D-Bus service to list " + "all remote web app hosts"); + + // Make an asynchronous 'remove_web_app_host' call + // Response will be sent to 'remove_web_app_host_reply' + QDBusPendingCall async = _dbus_rwa->asyncCall("remove_web_app_host", host_uuid); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); + + QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SLOT(remove_web_app_host_reply(QDBusPendingCallWatcher*))); +} + +/*! + * \brief Method gets called when a D-Bus response is ready. + * + * \a call contains the D-Bus response (session service or for example maybe just a error message). + * + * TODO: Example of json input + */ +void DBusAPI::get_web_app_hosts_reply(QDBusPendingCallWatcher *call){ + QString result = ""; + + QDBusPendingReply reply = *call; + if (reply.isError()) { + qCritical() << "D-Bus 'get_web_app_hosts' request failed, this was the reply:"; + qCritical() << reply.error(); + + if (QDBusError::ServiceUnknown == reply.error().type()) { + qCritical() << "The session service was probably just not started!"; + } + + emit serviceGetWebAppHostsResponse(nullptr); + + return; + } else { + result = reply.argumentAt<0>(); + } + call->deleteLater(); + + // Get the QJsonObject + qDebug() << "Raw JSON from the remote web app host listing request:" << result.toUtf8().replace('"', ""); + QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); + + emit serviceGetWebAppHostsResponse(&doc); +} + +/*! + * \brief Method gets called when a D-Bus response is ready. + * + * \a call contains the D-Bus response (session service or for example maybe just a error message). + * + * TODO: Example of json input + */ +void DBusAPI::add_web_app_host_reply(QDBusPendingCallWatcher *call){ + QString result = ""; + + QDBusPendingReply reply = *call; + if (reply.isError()) { + qCritical() << "D-Bus 'add_web_app_host' request failed, this was the reply:"; + qCritical() << reply.error(); + + if (QDBusError::ServiceUnknown == reply.error().type()) { + qCritical() << "The session service was probably just not started!"; + } + + emit serviceAddWebAppHostResponse(nullptr); + + return; + } else { + result = reply.argumentAt<0>(); + } + call->deleteLater(); + + // Get the QJsonObject + qDebug() << "Raw JSON from the remote web app host register request:" << result.toUtf8().replace('"', ""); + QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); + + emit serviceAddWebAppHostResponse(&doc); +} + +/*! + * \brief Method gets called when a D-Bus response is ready. + * + * \a call contains the D-Bus response (session service or for example maybe just a error message). + * + * TODO: Example of json input + */ +void DBusAPI::remove_web_app_host_reply(QDBusPendingCallWatcher *call){ + QString result = ""; + + QDBusPendingReply reply = *call; + if (reply.isError()) { + qCritical() << "D-Bus 'remove_web_app_host' request failed, this was the reply:"; + qCritical() << reply.error(); + + if (QDBusError::ServiceUnknown == reply.error().type()) { + qCritical() << "The session service was probably just not started!"; + } + + emit serviceRemoveWebAppHostResponse(nullptr); + + return; + } else { + result = reply.argumentAt<0>(); + } + call->deleteLater(); + + // Get the QJsonObject + qDebug() << "Raw JSON from the remote web app host deletion request:" << result.toUtf8().replace('"', ""); + QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); + + emit serviceRemoveWebAppHostResponse(&doc); +} diff --git a/rwa-support-desktopapp/src/DBusAPI.h b/rwa-support-desktopapp/src/DBusAPI.h new file mode 100644 index 0000000..63dbe68 --- /dev/null +++ b/rwa-support-desktopapp/src/DBusAPI.h @@ -0,0 +1,87 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2021 Daniel Teichmann + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef DBUSAPI_H +#define DBUSAPI_H + +#include +#include + +#include "RWAHost.h" +#include "RWADBusAdaptor.h" + +class DBusAPI : public QObject { + Q_OBJECT +public: + explicit DBusAPI(); + +signals: + void serviceStartResponse(QJsonDocument*); + void serviceStopResponse(QJsonDocument*); + void serviceStatusResponse(QJsonDocument*); + + void serviceGetWebAppHostsResponse(QJsonDocument*); + void serviceAddWebAppHostResponse(QJsonDocument*); + void serviceRemoveWebAppHostResponse(QJsonDocument*); + +public slots: + void start_reply(QDBusPendingCallWatcher *call); + void stop_reply(QDBusPendingCallWatcher *call); + void status_reply(QDBusPendingCallWatcher *call); + + void get_web_app_hosts_reply(QDBusPendingCallWatcher *call); + void add_web_app_host_reply(QDBusPendingCallWatcher *call); + void remove_web_app_host_reply(QDBusPendingCallWatcher *call); + + + // Starts a remote web app session + void start_request(RWAHost *host); + + // Stop a remote web app session + void stop_request(RWAHost *host, QString session_id); + + // Refreshes a remote web app session's status + void refresh_status_request(RWAHost *host, QString session_id); + + // Gets a remote web app session's status + void status_request(RWAHost *host, QString session_id); + + // Gets all remote web app hosts deposited in the session server + void get_web_app_hosts_request(); + + // Add a specific remote web app host using a url to make sure its contactable + void add_web_app_host_request(QString host_url, QString host_alias); + + // Removes a specific remote web app host using the uuid of a host + void remove_web_app_host_request(QString host_uuid); + +private: + OrgArcticaProjectRWASupportSessionServiceInterface* _dbus_rwa; + + void _initDBus(); + +}; + +#endif // DBUSAPI_H diff --git a/rwa-support-desktopapp/src/ListItem.qml b/rwa-support-desktopapp/src/ListItem.qml new file mode 100644 index 0000000..fa83f4b --- /dev/null +++ b/rwa-support-desktopapp/src/ListItem.qml @@ -0,0 +1,45 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2021 Daniel Teichmann + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import QtQuick 2.0 +import QtQuick.Controls.Material 2.3 +import QtQuick.Controls 2.2 + +ItemDelegate { + id: root + width: parent.width + height: 50 + + property string scene_url + + signal listItemClick() + + text: "" + + MouseArea { + anchors.fill: parent + onClicked: listItemClick(); + } +} diff --git a/rwa-support-desktopapp/src/RWADBusAdaptor.cpp b/rwa-support-desktopapp/src/RWADBusAdaptor.cpp new file mode 100644 index 0000000..6c1504e --- /dev/null +++ b/rwa-support-desktopapp/src/RWADBusAdaptor.cpp @@ -0,0 +1,64 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2020, 2021 Daniel Teichmann + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -i src/RWADBusAdaptor.h -p :src/RWADBusAdaptor.cpp rwa.xml + * rwa.xml is the xml output of the Introspect D-Bus method + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "src/RWADBusAdaptor.h" +/* + * Implementation of interface class OrgArcticaProjectRWASupportSessionServiceInterface + */ + +OrgArcticaProjectRWASupportSessionServiceInterface::OrgArcticaProjectRWASupportSessionServiceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgArcticaProjectRWASupportSessionServiceInterface::~OrgArcticaProjectRWASupportSessionServiceInterface() +{ +} + +/* + * Implementation of interface class OrgFreedesktopDBusIntrospectableInterface + */ + +OrgFreedesktopDBusIntrospectableInterface::OrgFreedesktopDBusIntrospectableInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgFreedesktopDBusIntrospectableInterface::~OrgFreedesktopDBusIntrospectableInterface() +{ +} + diff --git a/rwa-support-desktopapp/src/RWADBusAdaptor.h b/rwa-support-desktopapp/src/RWADBusAdaptor.h new file mode 100644 index 0000000..77f4b6c --- /dev/null +++ b/rwa-support-desktopapp/src/RWADBusAdaptor.h @@ -0,0 +1,151 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2020, 2021 Daniel Teichmann + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -p src/RWADBusAdaptor.h: rwa.xml + * rwa.xml is the xml output of the Introspect D-Bus method + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef RWADBUSADAPTOR_H +#define RWADBUSADAPTOR_H + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Proxy class for interface org.ArcticaProject.RWASupportSessionService + */ +class OrgArcticaProjectRWASupportSessionServiceInterface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.ArcticaProject.RWASupportSessionService"; } + +public: + OrgArcticaProjectRWASupportSessionServiceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgArcticaProjectRWASupportSessionServiceInterface(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply add_web_app_host(const QString &host) + { + QList argumentList; + argumentList << QVariant::fromValue(host); + return asyncCallWithArgumentList(QStringLiteral("add_web_app_host"), argumentList); + } + + inline QDBusPendingReply get_web_app_hosts() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("get_web_app_hosts"), argumentList); + } + + inline QDBusPendingReply refresh_status(int pid) + { + QList argumentList; + argumentList << QVariant::fromValue(pid); + return asyncCallWithArgumentList(QStringLiteral("refresh_status"), argumentList); + } + + inline QDBusPendingReply remove_web_app_host(int host_idx) + { + QList argumentList; + argumentList << QVariant::fromValue(host_idx); + return asyncCallWithArgumentList(QStringLiteral("remove_web_app_host"), argumentList); + } + + inline QDBusPendingReply start(int host_idx) + { + QList argumentList; + argumentList << QVariant::fromValue(host_idx); + return asyncCallWithArgumentList(QStringLiteral("start"), argumentList); + } + + inline QDBusPendingReply status(int pid) + { + QList argumentList; + argumentList << QVariant::fromValue(pid); + return asyncCallWithArgumentList(QStringLiteral("status"), argumentList); + } + + inline QDBusPendingReply stop(int pid) + { + QList argumentList; + argumentList << QVariant::fromValue(pid); + return asyncCallWithArgumentList(QStringLiteral("stop"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +/* + * Proxy class for interface org.freedesktop.DBus.Introspectable + */ +class OrgFreedesktopDBusIntrospectableInterface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.freedesktop.DBus.Introspectable"; } + +public: + OrgFreedesktopDBusIntrospectableInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgFreedesktopDBusIntrospectableInterface(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply Introspect() + { + QList argumentList; + return asyncCallWithArgumentList(QStringLiteral("Introspect"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace ArcticaProject { + typedef ::OrgArcticaProjectRWASupportSessionServiceInterface RWASupportSessionService; + } + namespace freedesktop { + namespace DBus { + typedef ::OrgFreedesktopDBusIntrospectableInterface Introspectable; + } + } +} +#endif diff --git a/rwa-support-desktopapp/src/RWAHost.cpp b/rwa-support-desktopapp/src/RWAHost.cpp new file mode 100644 index 0000000..f31dc60 --- /dev/null +++ b/rwa-support-desktopapp/src/RWAHost.cpp @@ -0,0 +1,68 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2021 Daniel Teichmann + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "RWAHost.h" + +RWAHost::RWAHost(QString uuid, QString alias, QString url) { + assert(uuid != ""); + assert(alias != ""); + assert(url != ""); + + /*qDebug() << "Created new RWAHost object.\n\t" + << QString("uuid: '%0'").arg(uuid) << "\n\t" + << QString("alias: '%0'").arg(alias) << "\n\t" + << QString("url: '%0'").arg(url);*/ + + _url = url; + _alias = alias; + _uuid = uuid; +} + +QString RWAHost::uuid() const { + return _uuid; +} + +QString RWAHost::alias() const { + return _alias; +} + +QString RWAHost::url() const { + return _url; +} + +void RWAHost::setUuid(const QString &uuid) { + _uuid = uuid; + emit uuidChanged(uuid); +} + +void RWAHost::setAlias(const QString &alias) { + _alias = alias; + emit aliasChanged(alias); +} + +void RWAHost::setUrl(const QString &url) { + _url = url; + emit urlChanged(url); +} diff --git a/rwa-support-desktopapp/src/RWAHost.h b/rwa-support-desktopapp/src/RWAHost.h new file mode 100644 index 0000000..cd3b1ce --- /dev/null +++ b/rwa-support-desktopapp/src/RWAHost.h @@ -0,0 +1,63 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2021 Daniel Teichmann + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef RWAHOST_H +#define RWAHOST_H + +#include +#include + +class RWAHost : public QObject { + Q_OBJECT + Q_PROPERTY(QString uuid READ uuid WRITE setUuid NOTIFY uuidChanged) + Q_PROPERTY(QString alias READ alias WRITE setAlias NOTIFY aliasChanged) + Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged) + +public: + RWAHost(QString uuid = "", QString alias = "", QString url = ""); + RWAHost(const RWAHost&); + +private: + QString _uuid; + QString _alias; + QString _url; + +signals: + void uuidChanged(QString uuid); + void aliasChanged(QString alias); + void urlChanged(QString url); + +public slots: + QString uuid() const; + QString alias() const; + QString url() const; + + void setUuid(const QString &uuid); + void setAlias(const QString &alias); + void setUrl(const QString &url); + +}; + +#endif // RWAHOST_H diff --git a/rwa-support-desktopapp/src/RWAHostModel.cpp b/rwa-support-desktopapp/src/RWAHostModel.cpp new file mode 100644 index 0000000..5f62adc --- /dev/null +++ b/rwa-support-desktopapp/src/RWAHostModel.cpp @@ -0,0 +1,37 @@ +#include "RWAHostModel.h" + +RWAHostModel::RWAHostModel(QObject *parent) { + Q_UNUSED(parent) +} + +int RWAHostModel::rowCount(const QModelIndex& parent) const { + Q_UNUSED(parent); + return mDatas.size(); +} + +int RWAHostModel::columnCount(const QModelIndex& parent) const { + Q_UNUSED(parent); + return 1; +} + +QVariant RWAHostModel::data(const QModelIndex &index, int role) const + { + if (!index.isValid()) + return QVariant(); + if ( role == Qt::DisplayRole) { + return mDatas[index.row()]; + } + return QVariant(); +} + +void RWAHostModel::populate() { + beginResetModel(); + mDatas.clear(); + RWAHost *host1 = new RWAHost("uuid-1", "Erster Server", "url1"); + RWAHost *host2 = new RWAHost("uuid-2", "Zweiter Server", "url2"); + RWAHost *host3 = new RWAHost("uuid-3", "Dritter Server", "url3"); + mDatas.append(host1->alias()); + mDatas.append(host2->alias()); + mDatas.append(host3->alias()); + endResetModel(); +} diff --git a/rwa-support-desktopapp/src/RWAHostModel.h b/rwa-support-desktopapp/src/RWAHostModel.h new file mode 100644 index 0000000..8697df2 --- /dev/null +++ b/rwa-support-desktopapp/src/RWAHostModel.h @@ -0,0 +1,23 @@ +#ifndef RWAHOSTMODEL_H +#define RWAHOSTMODEL_H + +#include +#include + +#include "RWAHost.h" + +class RWAHostModel : public QAbstractListModel { + Q_OBJECT + +public: + explicit RWAHostModel(QObject * parent = nullptr); + int rowCount(const QModelIndex& parent = QModelIndex()) const; + int columnCount(const QModelIndex& parent = QModelIndex()) const; + QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; + void populate(); + +private: + QStringList mDatas; +}; + +#endif // RWAHOSTMODEL_H diff --git a/rwa-support-desktopapp/src/Toast.qml b/rwa-support-desktopapp/src/Toast.qml new file mode 100644 index 0000000..7a18dc8 --- /dev/null +++ b/rwa-support-desktopapp/src/Toast.qml @@ -0,0 +1,158 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/remote-support-desktop + * Copyright 2020, 2021 Daniel Teichmann + * Copyright 2020, 2021 Mike Gabriel + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import QtQuick 2.0 +import QtQuick.Controls 2.0 +import QtQuick.Controls.Material 2.3 +import rwa.toast.type 1.0 + +/** + * adapted from StackOverflow: + * http://stackoverflow.com/questions/26879266/make-toast-in-android-by-qml + * GitHub Gist: https://gist.github.com/jonmcclung/bae669101d17b103e94790341301c129 + * Adapted to work with dark/light theming + */ + +/** + * @brief An Android-like timed message text in + * a box that self-destroys when finished if desired + */ +Control { + + /** + * Public + */ + + /** + * @brief Shows this Toast + * + * @param {string} text Text to show + * @param {real} duration Duration to show in milliseconds, defaults to 3000 + * @param {enum} type Type of toast. Available is: + * ToastType.Standard, ToastType.Info, ToastType.Warning + * ToastType.Success, ToastType.Error + */ + function show(text, duration, type) { + message.text = text; + + // checks if parameter was passed + if (typeof duration !== "undefined") { + time = Math.max(duration, 2 * fadeTime); + } else { + time = defaultTime; + } + + if (typeof type !== "undefined" ) { + if (type === ToastType.ToastStandard) { + selectedColor = "#dcdedc"; + } else if (type === ToastType.ToastInfo) { + selectedColor = "#0d5eaf"; + } else if (type === ToastType.ToastSuccess) { + selectedColor = "#0daf36"; + } else if (type === ToastType.ToastWarning) { + selectedColor = "#efef2a"; + } else if (type === ToastType.ToastError) { + selectedColor = "#ed1212"; + } + } else { + selectedColor = "#dcdedc"; + } + + animation.start(); + } + + // whether this Toast will self-destroy when it is finished + property bool selfDestroying: false + + /** + * Private + */ + + id: root + + property color selectedColor: "#dcdedc" + readonly property real defaultTime: 3000 + property real time: defaultTime + readonly property real fadeTime: 300 + + property real margin: 10 + + anchors { + left: parent.left + right: parent.right + margins: margin + } + + height: message.height + margin + + background: Rectangle { + color: (Material.theme == Material.Dark) ? "#212121" : "#dcdedc" + border.color: selectedColor + border.width: 1.5 + radius: margin + } + + opacity: 0 + + Text { + id: message + color: (Material.theme == Material.Dark) ? "#f1f1f1" : "#010101" + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignHCenter + anchors { + top: parent.top + left: parent.left + right: parent.right + margins: margin / 2 + } + } + + SequentialAnimation on opacity { + id: animation + running: false + + + NumberAnimation { + to: .9 + duration: fadeTime + } + + PauseAnimation { + duration: time - 2 * fadeTime + } + + NumberAnimation { + to: 0 + duration: fadeTime + } + + onRunningChanged: { + if (!running && selfDestroying) { + root.destroy(); + } + } + } +} diff --git a/rwa-support-desktopapp/src/ToastManager.qml b/rwa-support-desktopapp/src/ToastManager.qml new file mode 100644 index 0000000..2f1600f --- /dev/null +++ b/rwa-support-desktopapp/src/ToastManager.qml @@ -0,0 +1,89 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/remote-support-desktop + * Copyright 2020, 2021 Daniel Teichmann + * Copyright 2020, 2021 Mike Gabriel + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import QtQuick 2.0 + +/** + * adapted from StackOverflow: + * http://stackoverflow.com/questions/26879266/make-toast-in-android-by-qml + * GitHub Gist: https://gist.github.com/jonmcclung/bae669101d17b103e94790341301c129 + * @brief Manager that creates Toasts dynamically + */ +ListView { + /** + * Public + */ + + /** + * @brief Shows a Toast + * + * @param {string} text Text to show + * @param {real} duration Duration to show in milliseconds, defaults to 3000 + * @param {enum} type Type of toast. Available is: + * ToastType.Standard, ToastType.Info, ToastType.Warning + * ToastType.Success, ToastType.Error + */ + function show(text, duration, type) { + model.insert(0, {text: text, duration: duration, type: type}); + } + + /** + * Private + */ + + id: root + + z: Infinity + spacing: 5 + anchors.fill: parent + // parent.height * 0.1 = height of blue header rectangle on main + anchors.topMargin: parent.height * 0.1 + 5 + verticalLayoutDirection: ListView.TopToBottom + + interactive: false + + displaced: Transition { + NumberAnimation { + properties: "y" + easing.type: Easing.InOutQuad + } + } + + delegate: Toast { + Component.onCompleted: { + if (typeof duration === "undefined" && typeof type === "undefined") { + show(text, ToastType.ToastStandard); + } else if (typeof duration === "undefined" && + typeof type !== "undefined") { + show(text, type); + } else { + show(text, duration, type); + } + } + } + + model: ListModel {id: model} +} diff --git a/rwa-support-desktopapp/src/main.cpp b/rwa-support-desktopapp/src/main.cpp new file mode 100644 index 0000000..e29c8db --- /dev/null +++ b/rwa-support-desktopapp/src/main.cpp @@ -0,0 +1,141 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2020, 2021 Daniel Teichmann + * Copyright 2020, 2021 Mike Gabriel + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DBusAPI.h" +#include "RWADBusAdaptor.cpp" +#include "session.h" +#include "scenes/add_rwahost_wizard/add_rwahost_wizard.h" +#include "scenes/remote_control/remote_control_manager.h" +#include "RWAHostModel.h" +#include "RWAHost.h" + +int main(int argc, char *argv[]) { + qDebug() << "This app was built on: " << __DATE__ << __TIME__; + + // We don't want users to have multiple instances of this app running + QString tmpDirPath = QDir::tempPath() + "/rwa.support.desktopapp"; + QString tmpFilePath = tmpDirPath + "/prevent-multiple-instances.lock"; + QDir tmpDir(tmpDirPath); + if (!tmpDir.exists()) { + // Ensure that the path exists + tmpDir.mkpath("."); + } + QLockFile lockFile(tmpFilePath); + qDebug().noquote() << QString("Checking for a lockfile at: '%0'").arg(tmpFilePath); + + if(!lockFile.tryLock(100)){ + qCritical().noquote() << "You already have this app running.\n" + << "Only one instance is allowed.\n" + << "Closing application now with an error."; + + return 1; + } + + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QApplication app(argc, argv); + + QQuickStyle::setStyle("Material"); + + QTranslator translator; + qDebug().noquote() << QString("Locales: Loading locale: qrc:/locales/%0") + .arg(QLocale::system().name()); + if(translator.load(":/locales/" + QLocale::system().name())) { + app.installTranslator(&translator); + qDebug().noquote() << "Locales: Loaded: " + QLocale::system().name() + " locale!"; + } else { + qWarning() << "Locales: Unable to load translation!"; + } + + QQmlApplicationEngine engine(&app); + + QScopedPointer dbus_api (new DBusAPI()); + + // Make 'mainqmladaptor' available to QML + QScopedPointer main_gui ( + new MainQMLAdaptor(&app, &engine, dbus_api.data()) + ); + + engine.rootContext()->setContextProperty("mainqmladaptor", main_gui.data()); + + QObject::connect(dbus_api.data(), + SIGNAL(serviceGetWebAppHostsResponse(QJsonDocument*)), + main_gui.data(), + SLOT(get_web_app_hosts_response(QJsonDocument*))); + dbus_api.data()->get_web_app_hosts_request(); + + + engine.load(QUrl(QStringLiteral("qrc:/src/main.qml"))); + if (engine.rootObjects().isEmpty()) + return -1; + + QObject::connect(main_gui.data(), + SIGNAL(minimizeWindow()), + engine.rootObjects().takeFirst(), + SLOT(minimizeWindow())); + + QObject::connect(main_gui.data(), + SIGNAL(showWindow()), + engine.rootObjects().takeFirst(), + SLOT(showWindow())); + + QObject::connect(engine.rootObjects().takeFirst()-> + findChild("sidebar_drawer"), + SIGNAL(rwaHostSelected(QString)), + main_gui.data(), + SLOT(onRwaHostSelected(QString))); + + // Make 'AddRWAHostWizard' available to QML + QScopedPointer wizard ( + new AddRWAHostWizard(&app, + main_gui.data(), + dbus_api.data()) + ); + engine.rootContext()-> + setContextProperty("add_rwahost_wizard", wizard.data()); + + // Make 'remote_control_manager' available to QML + QScopedPointer remote_mngr ( + new RemoteControlManager(&engine, + main_gui.data(), + dbus_api.data()) + ); + engine.rootContext()-> + setContextProperty("remote_control_manager", remote_mngr.data()); + + return app.exec(); +} diff --git a/rwa-support-desktopapp/src/main.qml b/rwa-support-desktopapp/src/main.qml new file mode 100644 index 0000000..a622c18 --- /dev/null +++ b/rwa-support-desktopapp/src/main.qml @@ -0,0 +1,418 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/remote-support-desktop + * Copyright 2020, 2021 Daniel Teichmann + * Copyright 2020, 2021 Mike Gabriel + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import QtQuick 2.9 +import QtQuick.Window 2.2 +import QtQuick.Extras 1.4 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Material 2.3 +import "scenes" as Scenes + +/*! + The main.qml file contains the window, with its header, sidebar, toast and main_content. + */ + +ApplicationWindow { + readonly property int normal_width: 650 + readonly property int normal_height: 500 + readonly property bool inPortrait: window.width < window.height + + minimumWidth: 400 + minimumHeight: 460 + + width: normal_width + height: normal_height + + id: window + visible: true + title: qsTr("Remote Support for your Desktop") + + onClosing: { + mainqmladaptor.onCloseHandler(); + } + + function minimizeWindow() { + showMinimized(); + console.log("Minimizing window now..."); + } + + function showWindow() { + showNormal(); + console.log("Opening window now..."); + } + + function main_content_pop(item) { + if(item) { + if(item.search(main_content.currentItem.objectName) >= 0) return + } + return main_content.pop(item) + } + + function main_content_push(item) { + if(item) { + if(item.search(main_content.currentItem.objectName) >= 0) return + } + return main_content.push(item) + } + + function main_content_replace(item) { + if(item) { + if(item.search(main_content.currentItem.objectName) >= 0) return + } + return main_content.replace(item) + } + + MessageDialog { + id: message_dialog + objectName: "message_dialog" + title: qsTr("Remote Support for your Desktop") + text: qsTr("You are not supposed to see this message.\nThis is a bug.") + icon: StandardIcon.Critical + } + + ToastManager { + id: toast + + anchors.leftMargin: inPortrait ? 0 : sidebar_drawer.width + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.top: parent.top + } + + Connections { + target: mainqmladaptor + function onShowToastSignal(text, durationMs, type) { + toast.show(text, durationMs, type) + } + } + + Connections { + target: mainqmladaptor + function onShowMessageDialogChanged(show) { + message_dialog.visible = show + } + } + + StackView { + id: main_content + objectName: "main_content" + + anchors.top: top_menu_bar_frame.bottom + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.leftMargin: !inPortrait ? sidebar_drawer.width : 0 + anchors.topMargin: 0 + + // Our Application will start with the following content: + initialItem: "scenes/Scene_placeholder.qml" + + replaceEnter: Transition { + PropertyAnimation { + property: "opacity" + from: 0 + to:1 + duration: 100 + } + } + replaceExit: Transition { + PropertyAnimation { + property: "opacity" + from: 1 + to:0 + duration: 100 + } + } + } + + Connections { + target: mainqmladaptor + function onMessageDialogTextChanged(text) { + message_dialog.text = text + } + } + + Connections { + target: mainqmladaptor + function onMessageDialogTitleChanged(title) { + message_dialog.title = title + } + } + + Connections { + target: mainqmladaptor + function onMessageDialogIconChanged(iconindex) { + message_dialog.icon = iconindex + } + } + + /*! + This is our sidebar (sidemenu) for navigation purposes. + It will collapse if the window gets resized to a portrait format. + Then it can be opened using the now visible button in the header + or by swiping from left to right. + main_content's leftMargin depends on sidebar_drawers's width + We don't want them to overlap on different window heights und widths. + */ + Drawer { + id: sidebar_drawer + objectName: "sidebar_drawer" + + y: top_menu_bar_frame.height + width: !inPortrait ? + Math.min(300, Math.max(200, window.width * 0.333)) : + (window.width * 0.5) + height: window.height - top_menu_bar_frame.height + + modal: inPortrait + interactive: inPortrait + position: inPortrait ? 0 : 1 + dragMargin: 1 + margins: -2 + visible: !inPortrait + + signal rwaHostSelected(string host_uuid) + property bool rwaHostIsSelected: false + + ListView { + id: sidebar_listview + boundsBehavior: Flickable.StopAtBounds + interactive: true + clip: true + anchors.fill: parent + model: mainModel + + header: Rectangle { + height: 50 + width: parent.width + color: Material.background + + ComboBox { + id: server_chooser + objectName: "server_chooser" + + padding: 0 + width: parent.width + height: 56 - y + y: -6 + + model: mainqmladaptor.rwaHostModel + textRole: "alias" + + onCurrentIndexChanged: { + var rwa_host = mainqmladaptor.rwaHostModel + if (rwa_host[currentIndex] !== undefined) { + sidebar_drawer.rwaHostSelected(rwa_host[currentIndex].uuid) + displayText = rwa_host[currentIndex].alias + } + } + + + } + } + + footer: ItemDelegate { + id: footer + text: " " + qsTr("Settings") + width: parent.width + enabled: false + + onClicked: { + var scene_url = "scenes/Scene_placeholder.qml" + header_text.text = qsTr("Settings") + if (inPortrait) sidebar_drawer.close() + + if (scene_url.search(main_content.currentItem.objectName) >= 0) return + main_content.replace(scene_url, StackView.Transition) + } + + MenuSeparator { + parent: footer + width: parent.width + anchors.verticalCenter: parent.top + } + } + + VisualItemModel { + id: mainModel + + ListItem { + text: " " + qsTr("Remote Control") + scene_url: "scenes/remote_control/Scene_remote_control.qml" + onListItemClick: { + header_text.text = qsTr("Allow remote control") + if (inPortrait) sidebar_drawer.close() + + if (scene_url.search(main_content.currentItem.objectName) >= 0) return + main_content.replace(scene_url, StackView.Transition) + } + + // Disabled till a RWAHost object is selected. + enabled: sidebar_drawer.rwaHostIsSelected + } + ListItem { + text: " " + qsTr("Remote View") + scene_url: "scenes/Scene_remote_view.qml" + onListItemClick: { + header_text.text = qsTr("Allow remote view") + if (inPortrait) sidebar_drawer.close() + + if (scene_url.search(main_content.currentItem.objectName) >= 0) return + main_content.replace(scene_url, StackView.Transition) + } + + // Disabled till a RWAHost object is selected. + //enabled: sidebar_drawer.rwaHostIsSelected + + // But remote view is not implemented yet + enabled: false + } + ListItem { + text: " " + qsTr("Add RWA-Server") + scene_url: "scenes/add_rwahost_wizard/Scene_step_1.qml" + onListItemClick: { + header_text.text = qsTr("Server addition wizard") + if (inPortrait) sidebar_drawer.close() + + if (scene_url.search(main_content.currentItem.objectName) >= 0) return + main_content.push(scene_url, StackView.ReplaceTransition) + } + } + } + + ScrollIndicator.vertical: ScrollIndicator { } + } + } + + // Set dark/light theme based on the slider setting + Material.theme: inPortrait ? (theme_portrait.position < 1 ? Material.Light : Material.Dark) + : (theme_landscape.position < 1 ? Material.Light : Material.Dark) + + ToolBar { + id: top_menu_bar_frame + width: parent.width + height: parent.height * 0.10 + + background: Rectangle { + color: parent.Material.background + border.color: parent.Material.background + } + Material.background: "#0d5eaf" + Material.foreground: "#ffffff" + + anchors.margins: 0 + anchors.left: parent.left + anchors.top: parent.top + + Switch { + id: theme_landscape + width: 150 + implicitWidth: 100 + visible: !inPortrait + parent: inPortrait ? sidebar_listview : top_menu_bar_frame + + height: parent.height + anchors.margins: 10 + text: qsTr("Dark theme") + anchors.left: parent.left + anchors.verticalCenterOffset: 0 + anchors.leftMargin: 0 + anchors.verticalCenter: parent.verticalCenter + + /*! + Here is the default setting for dark/light mode + */ + checked: true + + onCheckedChanged: { + theme_portrait.checked = checked + } + } + + Switch { + id: theme_portrait + visible: inPortrait + parent: sidebar_listview + + height: 50 + width: parent.width + + anchors.bottom: parent.bottom + text: qsTr("Dark theme") + + checked: theme_landscape.checked + onCheckedChanged: { + theme_landscape.checked = checked + } + } + + Label { + id: header_text + height: parent.height + color: "white" + text: qsTr("Allow Remote Control") + font.pointSize: 20 + fontSizeMode: Text.Fit + horizontalAlignment: Text.AlignRight + verticalAlignment: Text.AlignVCenter + anchors.left: inPortrait ? burger_button.right : parent.left + anchors.leftMargin: inPortrait ? 5 : theme_landscape.width + anchors.right: parent.right + anchors.rightMargin: 5 + anchors.verticalCenter: parent.verticalCenter + padding: 5 + } + + Button { + id: burger_button + width: 50 + height: parent.height + 10 + visible: inPortrait + + text: "≡" + checkable: false + font.pointSize: 24 + flat: true + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.verticalCenter: parent.verticalCenter + enabled: !sidebar_drawer.opened + + onClicked: { + sidebar_drawer.open() + enabled: false + } + } + } +} + +/*##^## Designer { + D{i:14;anchors_width:650} +} + ##^##*/ diff --git a/rwa-support-desktopapp/src/main_qmladaptor.cpp b/rwa-support-desktopapp/src/main_qmladaptor.cpp new file mode 100644 index 0000000..688b993 --- /dev/null +++ b/rwa-support-desktopapp/src/main_qmladaptor.cpp @@ -0,0 +1,344 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2020, 2021 Daniel Teichmann + * Copyright 2020, 2021 Mike Gabriel + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "main_qmladaptor.h" + +MainQMLAdaptor::MainQMLAdaptor(QObject *parent, QQmlApplicationEngine* engine, + DBusAPI *dbus_api) : QObject(parent) { + Q_ASSERT(engine != nullptr); + Q_ASSERT(dbus_api != nullptr); + + _engine = engine; + _dbus_api = dbus_api; + _selected_rwa_host = nullptr; + _rwaHostModel = new QList; + + QTimer *timer = new QTimer(this); + connect(timer, &QTimer::timeout, _dbus_api, + QOverload<>::of(&DBusAPI::get_web_app_hosts_request)); + timer->start(10000); + + qmlRegisterUncreatableMetaObject( + Toast::staticMetaObject, // meta object created by Q_NAMESPACE macro + "rwa.toast.type", // import statement (can be any string) + 1, 0, // major and minor version of the import + "ToastType", // name in QML (does not have to match C++ name) + "Error: only enums" // error if someone tries to create a ToastType object + ); + +} + +void MainQMLAdaptor::onRwaHostSelected(QString host_uuid) { + Q_ASSERT(host_uuid != ""); + + RWAHost *_host = nullptr; + for (int i = 0; i < getRWAHostModel().size(); i++) { + QObject *obj = _rwaHostModel->value(i); + RWAHost *host = qobject_cast(obj); + Q_ASSERT(host != nullptr); + + if (host->uuid() == host_uuid) { + _host = host; + } + } + Q_ASSERT(_host != nullptr); + + _selected_rwa_host = _host; + qDebug() << "RWAHost was selected!" << + _selected_rwa_host->uuid() << + "aka" << + _selected_rwa_host->alias(); + + setRWAHostSelected(true); +} + +RWAHost* MainQMLAdaptor::getSelectedRWAHost() { + return _selected_rwa_host; +} + +void MainQMLAdaptor::setRWAHostModel(QList *rwa_hosts) { + _rwaHostModel = rwa_hosts; + emit rwaHostModelChanged(*rwa_hosts); +} + +void MainQMLAdaptor::addRWAHost(RWAHost *rwa_host) { + _rwaHostModel->append(rwa_host); + emit rwaHostModelChanged(*_rwaHostModel); +} + +void MainQMLAdaptor::removeRWAHost(RWAHost *rwa_host) { + _rwaHostModel->removeOne(rwa_host); + emit rwaHostModelChanged(*_rwaHostModel); +} + +QList MainQMLAdaptor::getRWAHostModel() { + return *_rwaHostModel; +} + +void MainQMLAdaptor::setRWAHostSelected(bool value) { + // Find item via 'objectName' + QObject *sidebar_drawer = _engine->rootObjects().takeFirst()-> + findChild("sidebar_drawer"); + if (sidebar_drawer) { + sidebar_drawer->setProperty("rwaHostIsSelected", value); + } else { + qWarning() << "Unable to find 'sidebar_drawer' Item!"; + } + + QObject *server_chooser = _engine->rootObjects().takeFirst()-> + findChild("server_chooser"); + if (server_chooser) { + server_chooser->setProperty("displayText", value ? + server_chooser->property("currentText") : + tr("No RWA host available!")); + server_chooser->setProperty("enabled", value); + } else { + qWarning() << "Unable to find 'server_chooser' Item!"; + } +} + +void MainQMLAdaptor::get_web_app_hosts_response(QJsonDocument *doc) { + // Q_ASSERT lets the program crash immediatly at startup, + // when the session service is not started. + // Don't use Q_ASSERT(doc != nullptr); instead use: + if (doc == nullptr) { + setRWAHostSelected(false); + + showToast(tr("Can't connect to underlying session service!"), + 9800, + Toast::ToastError); + + // Go to the first page on the stack. + main_content_pop(nullptr); + + return; + } + + + bool atLeastOneHostAvailable = false; + + // Get the QJsonObject + QJsonObject jObject = doc->object(); + QVariantMap mainMap = jObject.toVariantMap(); + + // Status of request + QString request_status = mainMap["status"].toString(); + if (request_status == "success") { + // Building host_objects + QJsonArray host_objects = jObject.value("hosts").toArray(); + + QList *all_rwa_hosts = new QList; + foreach (const QJsonValue &host_object, host_objects) { + QString host_uuid = host_object["uuid"].toString(); + QString host_alias = host_object["alias"].toString(); + QString host_url = host_object["url"].toString(); + + if (host_url == "" || host_uuid == "") { + // This two values are required and can't be omitted. + QString reason = tr("A host object in the response of D-Bus service lacks" + " a necessary value. (host_url or host_uuid)"); + qCritical().noquote() << tr("An error occured while adding a new host:") + << reason; + + return; + } + + if (host_alias == "") { + qDebug().noquote() << QString("An alias for the host wasn't delivered " + "so just use '%0' as alias.").arg(host_url); + host_alias = host_url; + } + + + // Now built RWAHost object. + RWAHost *rwa_host = new RWAHost(host_uuid, host_alias, host_url); + all_rwa_hosts->append(rwa_host); + + bool found = false; + for (int i = 0; i < this->_rwaHostModel->size(); i++) { + RWAHost* old_host = qobject_cast(_rwaHostModel->value(i)); + Q_ASSERT(old_host != nullptr); + + if (rwa_host->uuid() == old_host->uuid()) { + found = true; + break; + } + } + + atLeastOneHostAvailable = true; + + if (!found) { + qInfo().noquote() << QString(tr("Successfully added new RWAHost '%0'")) + .arg(rwa_host->alias()); + addRWAHost(rwa_host); + } + } + + for (int i = 0; i < this->_rwaHostModel->size(); i++) { + RWAHost* old_host = qobject_cast(_rwaHostModel->value(i)); + Q_ASSERT(old_host != nullptr); + + bool found = false; + for (RWAHost *host : *all_rwa_hosts) { + if (host->uuid() == old_host->uuid()) { + found = true; + break; + } + } + + if (!found) { + removeRWAHost(old_host); + qInfo().noquote() << QString(tr("Removed RWAHost '%0'")).arg(old_host->alias()); + } + } + } else { + QString reason = tr("An error occured while adding a new host:"); + qCritical().noquote() << reason; + + QString type = mainMap["type"].toString(); + if (type != "") { + reason = QString(tr("The error is not clear. The session service " + "responded with status type '%0'")).arg(type); + qCritical().noquote() << reason; + } else { + reason = QString(tr("The error is not clear. The session service " + "responded with no status type!")); + qCritical().noquote() << reason; + } + + return; + } + + if (!atLeastOneHostAvailable) { + main_content_replace("scenes/Scene_no_server_available.qml"); + } + + setRWAHostSelected(atLeastOneHostAvailable); +} + +void MainQMLAdaptor::main_content_push(QString scene) { + // Find item via 'objectName' + QObject *window = _engine->rootObjects().takeFirst(); + Q_ASSERT(window != nullptr); + + QObject *main_content = _engine->rootObjects().takeFirst()->findChild("main_content"); + Q_ASSERT(main_content != nullptr); + + QVariant to_cast = main_content->property("currentItem"); + QObject *obj = qvariant_cast(to_cast); + if (obj) { + if (!(scene.contains(obj->objectName()))) { + QVariant arg = QVariant::fromValue(scene); + if(!QMetaObject::invokeMethod(window, "main_content_push", Q_ARG(QVariant, arg))) + qDebug() << "Failed to invoke push"; + } + } +} + +void MainQMLAdaptor::main_content_pop(QString scene) { + // Find item via 'objectName' + QObject *window = _engine->rootObjects().takeFirst(); + Q_ASSERT(window != nullptr); + + QObject *main_content = _engine->rootObjects().takeFirst()-> + findChild("main_content"); + Q_ASSERT(main_content != nullptr); + + QVariant to_cast = main_content->property("currentItem"); + QObject *obj = qvariant_cast(to_cast); + if (obj) { + if (!(scene.contains(obj->objectName()))) { + QVariant arg = QVariant::fromValue(scene); + if(!QMetaObject::invokeMethod(window, "main_content_pop", Q_ARG(QVariant, arg))) + qDebug() << "Failed to invoke pop"; + } + } +} + +void MainQMLAdaptor::main_content_replace(QString scene) { + // Find item via 'objectName' + QObject *window = _engine->rootObjects().takeFirst(); + Q_ASSERT(window != nullptr); + + QObject *main_content = _engine->rootObjects().takeFirst()-> + findChild("main_content"); + Q_ASSERT(main_content != nullptr); + + QVariant to_cast = main_content->property("currentItem"); + QObject *obj = qvariant_cast(to_cast); + if (obj) { + QString scene_add_rwahost_wizard = "Scene_step_1"; + if (!(scene.contains(obj->objectName()) || + scene_add_rwahost_wizard.contains(obj->objectName()))) { + QVariant arg = QVariant::fromValue(scene); + if (!QMetaObject::invokeMethod(window, "main_content_replace", + Q_ARG(QVariant, arg))) { + qDebug() << "Failed to invoke replace"; + } + } + } +} + +bool MainQMLAdaptor::openMessageDialog(QString title, QString text, QMessageBox::Icon icon) { + _messageDialogText = text; + _messageDialogTitle = title; + _messageDialogIcon = icon; + _showMessageDialog = true; + emit messageDialogIconChanged(_messageDialogIcon); + emit messageDialogTitleChanged(_messageDialogTitle); + emit messageDialogTextChanged(_messageDialogText); + + emit showMessageDialogChanged(_showMessageDialog); + + qDebug() << "Opening MessageDialog!"; + return true; +} + +QString MainQMLAdaptor::getMessageDialogTitle() { + return _messageDialogTitle; +} + +QString MainQMLAdaptor::getMessageDialogText() { + return _messageDialogText; +} + +QMessageBox::Icon MainQMLAdaptor::getMessageDialogIcon() { + return _messageDialogIcon; +} + +bool MainQMLAdaptor::getShowMessageDialog() { + return _showMessageDialog; +} + +void MainQMLAdaptor::onCloseHandler() { + // Do cleanup things here... + emit onCloseSignal(); +} + +void MainQMLAdaptor::showToast(QString text, uint durationMs, uint type) { + // type is actually Toast::ToastType + emit showToastSignal(text, QString::number(durationMs), type); +} diff --git a/rwa-support-desktopapp/src/main_qmladaptor.h b/rwa-support-desktopapp/src/main_qmladaptor.h new file mode 100644 index 0000000..70c075b --- /dev/null +++ b/rwa-support-desktopapp/src/main_qmladaptor.h @@ -0,0 +1,144 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2020, 2021 Daniel Teichmann + * Copyright 2020, 2021 Mike Gabriel + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "RWAHost.h" +#include "DBusAPI.h" + +namespace Toast { + Q_NAMESPACE + enum ToastType { + ToastStandard, + ToastInfo, + ToastSuccess, + ToastWarning, + ToastError + }; + Q_ENUM_NS(ToastType) +} + +/*#include +namespace MyNamespace +{ + Q_NAMESPACE // required for meta object creation + enum EnStyle { + STYLE_RADIAL, + STYLE_ENVELOPE, + STYLE_FILLED + }; + Q_ENUM_NS(EnStyle) // register the enum in meta object data +}*/ + +class MainQMLAdaptor : public QObject { + Q_OBJECT + // this makes rwaHostModel available as a QML property + Q_PROPERTY(QList rwaHostModel READ getRWAHostModel NOTIFY rwaHostModelChanged) + // this makes showMessageDialog available as a QML property + Q_PROPERTY(bool showMessageDialog READ getShowMessageDialog NOTIFY showMessageDialogChanged) + // this makes showMessageDialogTitle available as a QML property + Q_PROPERTY(QString _messageDialogTitle READ getMessageDialogTitle NOTIFY messageDialogTitleChanged) + // this makes showMessageDialogText available as a QML property + Q_PROPERTY(QString _messageDialogText READ getMessageDialogText NOTIFY messageDialogTextChanged) + // this makes showMessageDialogIcon available as a QML property + Q_PROPERTY(QMessageBox::Icon _messageDialogIcon READ getMessageDialogIcon NOTIFY messageDialogIconChanged) + + +public: + explicit MainQMLAdaptor(QObject *parent, QQmlApplicationEngine *engine = nullptr, + DBusAPI *dbus_api = nullptr); + + void setRWAHostModel(QList *rwa_hosts); + + void main_content_push(QString); + void main_content_pop(QString); + void main_content_replace(QString); + + bool openMessageDialog(QString title, QString text, QMessageBox::Icon); + QString getMessageDialogTitle(); + QString getMessageDialogText(); + QMessageBox::Icon getMessageDialogIcon(); + bool getShowMessageDialog(); + +signals: + void showMessageDialogChanged(bool show); + void messageDialogTextChanged(QString text); + void messageDialogTitleChanged(QString title); + void messageDialogIconChanged(int iconindex); + + void minimizeWindow(); + void showWindow(); + + void rwaHostModelChanged(QList); + + void onCloseSignal(); + + void showToastSignal(QString text, QString durationMs, int type); + +protected: + DBusAPI *_dbus_api; + QList *_rwaHostModel; + +private: + QQmlApplicationEngine *_engine; + RWAHost *_selected_rwa_host; + + bool _showMessageDialog; + QString _messageDialogTitle; + QString _messageDialogText; + QMessageBox::Icon _messageDialogIcon; + +public slots: + void get_web_app_hosts_response(QJsonDocument *doc); + + void addRWAHost(RWAHost *rwa_host); + void removeRWAHost(RWAHost *rwa_host); + void setRWAHostSelected(bool value); + + // No pointer because QML doesn't + // like this type much with pointer + QList getRWAHostModel(); + + RWAHost *getSelectedRWAHost(); + + void onRwaHostSelected(QString host_uuid); + void onCloseHandler(); + + // arg type is actually Toast::ToastType + void showToast(QString text, + uint durationMs = 3000, + uint type = 0); +}; diff --git a/rwa-support-desktopapp/src/scenes/Scene_no_server_available.qml b/rwa-support-desktopapp/src/scenes/Scene_no_server_available.qml new file mode 100644 index 0000000..7b99b55 --- /dev/null +++ b/rwa-support-desktopapp/src/scenes/Scene_no_server_available.qml @@ -0,0 +1,71 @@ +import QtQuick 2.9 +import QtQuick.Window 2.2 +import QtQuick.Extras 1.4 +import QtQuick.Controls 2.2 +import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Material 2.3 + +/*! + * This .qml file is a Scene which can be loaded through for + * example a StackView (main_content in main.qml). + */ + +Item { + id: scene_no_server_available + objectName: "Scene_no_server_available" + + Rectangle { + id: rectangle + anchors.fill: parent + color: Material.background + + Text { + color: Material.foreground + id: title + + text: qsTr("Welcome!") + font.pointSize: 20 + font.bold: true + wrapMode: Text.WordWrap + + horizontalAlignment: Text.AlignLeft + + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: 15 + } + + Text { + color: Material.foreground + anchors.top: title.bottom + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: 15 + + horizontalAlignment: Text.AlignLeft + wrapMode: Text.WordWrap + /*: 'Add RWA-Server' has to be replaced with the correct translation in file main.qml .*/ + font.pointSize: 13 + text: qsTr("You need to add and select the remote \ +web app server to which you want to connect. \ +You can see a button to the left in the menu \ +which says 'Add RWA-Server'. Follow the steps \ +listed there and you can start your remote \ +support session afterwards using the buttons \ +above 'Add RWA-Server'.") + } + } +} + + + + + + + +/*##^## Designer { + D{i:0;autoSize:true;height:480;width:640} +} + ##^##*/ diff --git a/rwa-support-desktopapp/src/scenes/Scene_placeholder.qml b/rwa-support-desktopapp/src/scenes/Scene_placeholder.qml new file mode 100644 index 0000000..f492e00 --- /dev/null +++ b/rwa-support-desktopapp/src/scenes/Scene_placeholder.qml @@ -0,0 +1,56 @@ +import QtQuick 2.9 +import QtQuick.Window 2.2 +import QtQuick.Extras 1.4 +import QtQuick.Controls 2.2 +import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Material 2.3 + +/*! + * This .qml file is a Scene which can be loaded through for + * example a StackView (main_content in main.qml). + */ + +Item { + id: scene_placeholder + objectName: "Scene_placeholder" + + Rectangle { + id: rectangle + anchors.fill: parent + color: Material.background + + Text { + color: Material.foreground + id: title + + text: qsTr("This is the placeholder scene!") + font.pointSize: 18 + wrapMode: Text.WordWrap + + font.bold: true + horizontalAlignment: Text.AlignHCenter + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: 5 + } + + Text { + color: Material.foreground + anchors.top: title.bottom + anchors.margins: 5 + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + + wrapMode: Text.WordWrap + text: qsTr("The features you expected here are not yet implemented.") + horizontalAlignment: Text.AlignHCenter + } + } +} + +/*##^## Designer { + D{i:0;autoSize:true;height:480;width:640} +} + ##^##*/ diff --git a/rwa-support-desktopapp/src/scenes/Scene_remote_view.qml b/rwa-support-desktopapp/src/scenes/Scene_remote_view.qml new file mode 100644 index 0000000..436d8aa --- /dev/null +++ b/rwa-support-desktopapp/src/scenes/Scene_remote_view.qml @@ -0,0 +1,371 @@ +import QtQuick 2.9 +import QtQuick.Window 2.2 +import QtQuick.Extras 1.4 +import QtQuick.Controls 2.2 +import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Material 2.3 + +/*! + * This .qml file is a Scene which can be loaded through for + * example a StackView (main_content in main.qml). + */ + +Item { + id: scene_remote_view + objectName: "Scene_remote_view" + + Label { + id: dbus_api_status_text + text: "Unknown state of Service" + anchors.leftMargin: 10 + 5 + dbus_api_status_indicator.width + anchors.bottom: parent.bottom + anchors.bottomMargin: 10 + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + verticalAlignment: Text.AlignVCenter + font.pointSize: 11 + fontSizeMode: Text.Fit + objectName: "dbus_api_status_text" + anchors.left: parent.left + + StatusIndicator { + id: dbus_api_status_indicator + width: height + height: parent.height + objectName: "dbus_api_status_indicator" + color: "#73d216" + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.left + anchors.rightMargin: 5 + active: false + } + } + + Label { + id: explain_function_label + text: qsTr("Please tell your remote support partner your access address and your access-PIN to let your partner connect to this computer.") + font.pixelSize: 18 + fontSizeMode: Text.VerticalFit + wrapMode: Text.WordWrap + anchors.left: parent.left + anchors.leftMargin: 10 + anchors.top: parent.top + anchors.topMargin: 10 + anchors.right: parent.right + anchors.rightMargin: 10 + horizontalAlignment: Text.AlignLeft + enabled: false + + color: Material.theme == Material.Light ? "#000000" : "#FFFFFF" + } + + Rectangle { + id: dbus_api_status_line + y: 379 + height: 1 + radius: 1 + anchors.right: parent.right + anchors.rightMargin: 10 + anchors.bottom: dbus_api_status_text.top + anchors.bottomMargin: 10 + opacity: 0.3 + gradient: Gradient { + GradientStop { + position: 0.391 + color: "#ffffff" + } + + GradientStop { + position: 0.975 + color: "#8b8b8b" + } + } + border.width: 1 + border.color: "#00000000" + anchors.left: parent.left + anchors.leftMargin: 10 + } + + Column { + id: column + spacing: 6 + anchors.right: parent.right + anchors.rightMargin: 10 + anchors.left: parent.left + anchors.leftMargin: 10 + anchors.bottom: dbus_api_status_line.top + anchors.bottomMargin: 10 + anchors.top: explain_function_label.bottom + anchors.topMargin: 10 + + Column { + id: url_group + width: parent.width + height: parent.height * 0.25 + spacing: 5 + + Label { + id: your_url_text + height: parent.height/2 + text: qsTr("Remote viewing Address") + font.weight: Font.Bold + font.bold: true + verticalAlignment: Text.AlignBottom + horizontalAlignment: Text.AlignLeft + font.pointSize: 14 + fontSizeMode: Text.Fit + } + + TextEdit { + id: url_text + height: parent.height/2 + text: mainqmladaptor.url + anchors.rightMargin: 10 + copy_url_to_clipboard_button.width + anchors.right: parent.right + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + anchors.leftMargin: 10 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + font.pointSize: 15 + + readOnly: true + color: Material.foreground + selectByMouse: true + anchors.left: parent.left + + leftPadding: 5 + Rectangle { + radius: 5 + color: Material.theme == Material.Light ? "#F0F0F0" : "#383838" + height: url_text.height + // whole line + copy-into-clipboard button + some margin + width: url_text.width + copy_url_to_clipboard_button.width + 5 + 5 + x: 0; y: 0 + z: -1 + } + + Button { + id: copy_url_to_clipboard_button + width: copy_url_to_clipboard_image.width + 6 + height: copy_url_to_clipboard_image.height + 6 + 10 + anchors.verticalCenter: parent.verticalCenter + display: AbstractButton.IconOnly + anchors.leftMargin: 5 + anchors.left: url_text.right + highlighted: false + flat: true + + Image { + id: copy_url_to_clipboard_image + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + source: "../../images/into-clipboard.svg" + opacity: 0.65 + } + + onClicked: { + mainqmladaptor.handleCopyToClipboardButtonClick(url_text.text); + toast.show(qsTr("Copied access address into clipboard!"), "1000"); + } + + ToolTip.text: qsTr("Copy the access address into the clipboard") + hoverEnabled: true + + ToolTip.delay: 1000 + ToolTip.timeout: 5000 + ToolTip.visible: hovered + } + } + } + + Column { + id: session_id_group + width: parent.width + height: parent.height * 0.25 + spacing: 5 + + Label { + id: your_session_id_text + height: parent.height/2 + text: qsTr("Session-ID") + font.weight: Font.Bold + font.bold: true + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + font.pointSize: 14 + verticalAlignment: Text.AlignBottom + horizontalAlignment: Text.AlignLeft + fontSizeMode: Text.Fit + } + + TextEdit { + objectName: "session_id_text" + id: session_id_text + height: parent.height/2 + text: mainqmladaptor.session_id + font.letterSpacing: 10 + anchors.rightMargin: 10 + copy_session_id_to_clipboard_button.width + anchors.right: parent.right + font.pointSize: 15 + anchors.left: parent.left + anchors.leftMargin: 10 + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + leftPadding: 5 + Rectangle { + radius: 5 + color: Material.theme == Material.Light ? "#F0F0F0" : "#383838" + height: url_text.height + // whole line + copy-into-clipboard button + some margin + width: url_text.width + copy_url_to_clipboard_button.width + 5 + 5 + x: 0; y: 0 + z: -1 + } + + readOnly: true + color: Material.foreground + wrapMode: Text.WordWrap + selectByMouse: true + + Button { + id: copy_session_id_to_clipboard_button + width: copy_session_id_to_clipboard_image.width + 6 + height: copy_session_id_to_clipboard_image.height + 6 + 10 + anchors.verticalCenter: parent.verticalCenter + flat: true + display: AbstractButton.IconOnly + anchors.left: session_id_text.right + anchors.leftMargin: 5 + + Image { + id: copy_session_id_to_clipboard_image + anchors.horizontalCenter: parent.horizontalCenter + opacity: 0.65 + anchors.verticalCenter: parent.verticalCenter + source: "../../images/into-clipboard.svg" + fillMode: Image.PreserveAspectFit + } + + onClicked: { + mainqmladaptor.handleCopyToClipboardButtonClick(pin_text.text); + toast.show(qsTr("Copied session-ID into clipboard!"), "1000"); + } + + ToolTip.text: qsTr("Copy the session-ID into the clipboard") + hoverEnabled: true + + ToolTip.delay: 1000 + ToolTip.timeout: 5000 + ToolTip.visible: hovered + } + } + } + + Column { + id: pin_group + width: parent.width + height: parent.height * 0.25 + spacing: 5 + + Label { + id: your_pin_text + height: parent.height/2 + text: qsTr("Access-PIN") + font.weight: Font.Bold + font.bold: true + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + font.pointSize: 14 + verticalAlignment: Text.AlignBottom + horizontalAlignment: Text.AlignLeft + } + + TextEdit { + objectName: "pin_text" + id: pin_text + height: parent.height/2 + text: mainqmladaptor.pin + anchors.rightMargin: 10 + copy_pin_to_clipboard_button.width + anchors.right: parent.right + font.pointSize: 15 + anchors.left: parent.left + anchors.leftMargin: 10 + font.letterSpacing: 10 + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + leftPadding: 5 + Rectangle { + radius: 5 + color: Material.theme == Material.Light ? "#F0F0F0" : "#383838" + height: url_text.height + // whole line + copy-into-clipboard button + some margin + width: url_text.width + copy_url_to_clipboard_button.width + 5 + 5 + x: 0; y: 0 + z: -1 + } + + readOnly: true + color: Material.foreground + wrapMode: Text.WordWrap + selectByMouse: true + + Button { + id: copy_pin_to_clipboard_button + width: copy_pin_to_clipboard_image.width + 6 + height: copy_pin_to_clipboard_image.height + 6 + 10 + anchors.verticalCenter: parent.verticalCenter + flat: true + display: AbstractButton.IconOnly + anchors.left: pin_text.right + anchors.leftMargin: 5 + + Image { + id: copy_pin_to_clipboard_image + anchors.verticalCenter: parent.verticalCenter + opacity: 0.65 + anchors.horizontalCenter: parent.horizontalCenter + source: "../../images/into-clipboard.svg" + fillMode: Image.PreserveAspectFit + } + + onClicked: { + mainqmladaptor.handleCopyToClipboardButtonClick(pin_text.text); + toast.show(qsTr("Copied PIN into clipboard!"), "1000"); + } + + ToolTip.text: qsTr("Copy the pin into the clipboard") + hoverEnabled: true + + ToolTip.delay: 1000 + ToolTip.timeout: 5000 + ToolTip.visible: hovered + } + } + } + + } + + Button { + id: start_support_button + height: Math.min(50) + objectName: "start_support_button" + text: qsTr("Start remote viewing session") + anchors.rightMargin: column.anchors.leftMargin + anchors.bottom: dbus_api_status_line.top + anchors.bottomMargin: 10 + anchors.right: parent.right + checkable: true + + onClicked: mainqmladaptor.handleConnectButtonClick(checked); + } +} + +/*##^## Designer { + D{i:0;autoSize:true;height:480;width:640} +} + ##^##*/ diff --git a/rwa-support-desktopapp/src/scenes/Scene_settings.qml b/rwa-support-desktopapp/src/scenes/Scene_settings.qml new file mode 100644 index 0000000..e2f89da --- /dev/null +++ b/rwa-support-desktopapp/src/scenes/Scene_settings.qml @@ -0,0 +1,34 @@ +import QtQuick 2.9 +import QtQuick.Window 2.2 +import QtQuick.Extras 1.4 +import QtQuick.Controls 2.2 +import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Material 2.3 + +/*! + * This .qml file is a Scene which can be loaded through for + * example a StackView (main_content in main.qml). + */ + +Item { + id: scene_settings + objectName: "Scene_settings" + + Rectangle { + id: rectangle + anchors.fill: parent + color: Material.background + + Text { + color: Material.foreground + text: "Settings tab!" + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + } + } +} + +/*##^## Designer { + D{i:0;autoSize:true;height:480;width:640} +} + ##^##*/ diff --git a/rwa-support-desktopapp/src/scenes/add_rwahost_wizard/Scene_step_1.qml b/rwa-support-desktopapp/src/scenes/add_rwahost_wizard/Scene_step_1.qml new file mode 100644 index 0000000..873e0fd --- /dev/null +++ b/rwa-support-desktopapp/src/scenes/add_rwahost_wizard/Scene_step_1.qml @@ -0,0 +1,282 @@ +import QtQuick 2.9 +import QtQuick.Window 2.2 +import QtQuick.Extras 1.4 +import QtQuick.Controls 2.2 +import QtQuick.Controls.Material 2.3 +import rwa.toast.type 1.0 + +/*! + * This .qml file is a Scene which can be loaded through for + * example a StackView (main_content in main.qml). + */ + +Item { + id: scene_server_wizard_step_1 + objectName: "Scene_step_1" + + Connections { + target: add_rwahost_wizard + function onStep1Success() { + // Go onto the first page of the stack. + main_content_pop(null) + mainqmladaptor.showToast(qsTr("Successfully added remote web app host."), + 5000, + ToastType.ToastSuccess); + } + } + + Connections { + target: add_rwahost_wizard + function onStep1Failed(reason, toast_type) { + mainqmladaptor.showToast(reason, + 5000, + toast_type) + } + } + + Rectangle { + id: rectangle + anchors.fill: parent + color: Material.background + + Button { + id: next_step1_button + text: qsTr("Next Step") + anchors.bottom: parent.bottom + anchors.bottomMargin: 15 + anchors.right: parent.right + anchors.rightMargin: 15 + + onClicked: { + add_rwahost_wizard.processStep1(host_url.text, host_alias.text) + } + } + + /*Text { + color: Material.foreground + id: step_indicator + + text: qsTr("Step 1") + anchors.leftMargin: 15 + anchors.top: parent.top + anchors.topMargin: 15 + font.pointSize: 21 + wrapMode: Text.WordWrap + + font.bold: true + horizontalAlignment: Text.AlignHCenter + anchors.left: parent.left + anchors.margins: 5 + }*/ + + Text { + color: Material.foreground + id: explaining_text + + text: qsTr("Please input the address for the "+ + "remote web app server which you want "+ + "to connect to.\nIf you don't know "+ + "what this means, ask your local "+ + "administrator about it please.\nBefore you can "+ + "start any remote sessions you will have to "+ + "be approved for remote support.") + font.pointSize: 12 + anchors.right: parent.right + anchors.rightMargin: 15 + anchors.leftMargin: 15 + anchors.top: parent.top //step_indicator.bottom + anchors.topMargin: 15 + wrapMode: Text.WordWrap + + anchors.left: parent.left + anchors.margins: 5 + } + + TextField { + id: host_url + selectByMouse: true + placeholderText: qsTr("http://example.com:8000") + + font.pixelSize: 16 + color: Material.foreground + anchors.topMargin: 30 + + padding: 15 + topPadding: 15 + + anchors.top: explaining_text.bottom + anchors.left: parent.left + anchors.leftMargin: 15 + anchors.right: parent.right + anchors.margins: 30 + + MouseArea { + anchors.fill: parent + hoverEnabled: true + onHoveredChanged: { + if (containsMouse) { + host_url_background.state = "hovered" + } else if (!host_url.focus) { + host_url_background.state = "unhovered" + } + } + onClicked: { + host_url.forceActiveFocus(); + } + } + + onFocusChanged: { + host_url_background.state = host_url.focus ? "hovered" : "unhovered" + } + + background: Rectangle { + id: host_url_background + color: Material.background + border.color: Material.foreground + border.width: 1 + radius: 4 + + states: [ + State { + name: "hovered" + PropertyChanges { + target: host_url_background + border.color: "#0178EF" + } + }, + State { + name: "unhovered" + PropertyChanges { + target: host_url_background + border.color: Material.foreground + } + } + ] + transitions: [ + Transition { + from: "*" + to: "*" + PropertyAnimation { + property: "border.color" + duration: 100 + easing.type: Easing.Linear + } + } + ] + + Text { + color: Material.foreground + text: qsTr("RWA host address") + anchors.left: parent.left + anchors.leftMargin: 15 + anchors.verticalCenterOffset: - host_url.height / 2 + anchors.verticalCenter: parent.verticalCenter + leftPadding: 5 + + Rectangle { + color: Material.background + width: parent.width + 5 + 3 + height: parent.height + z: -1 + } + } + } + } + + TextField { + id: host_alias + selectByMouse: true + placeholderText: qsTr("My example host") + + font.pixelSize: 16 + color: Material.foreground + + padding: 15 + topPadding: 15 + + anchors.top: host_url.bottom + anchors.topMargin: 30 + anchors.left: parent.left + anchors.leftMargin: 15 + anchors.right: parent.right + anchors.margins: 30 + + MouseArea { + anchors.fill: parent + hoverEnabled: true + onHoveredChanged: { + if (containsMouse) { + host_alias_background.state = "hovered" + } else if (!host_alias.focus) { + host_alias_background.state = "unhovered" + } + } + onClicked: { + host_alias.forceActiveFocus(); + } + } + + onFocusChanged: { + host_alias_background.state = host_alias.focus ? "hovered" : "unhovered" + } + + background: Rectangle { + id: host_alias_background + color: Material.background + border.color: Material.foreground + border.width: 1 + radius: 4 + + states: [ + State { + name: "hovered" + PropertyChanges { + target: host_alias_background + border.color: "#0178EF" + } + }, + State { + name: "unhovered" + PropertyChanges { + target: host_alias_background + border.color: Material.foreground + } + } + ] + transitions: [ + Transition { + from: "*" + to: "*" + PropertyAnimation { + property: "border.color" + duration: 100 + easing.type: Easing.Linear + } + } + ] + + Text { + color: Material.foreground + text: qsTr("RWA host alias") + anchors.left: parent.left + anchors.leftMargin: 15 + anchors.verticalCenterOffset: - host_alias.height / 2 + anchors.verticalCenter: parent.verticalCenter + leftPadding: 5 + + Rectangle { + color: Material.background + width: parent.width + 5 + 3 + height: parent.height + z: -1 + } + } + } + } + } +} + +/*##^## Designer { + D{i:0;autoSize:true;height:480;width:640}D{i:4;anchors_width:351;anchors_x:279} +} + ##^##*/ diff --git a/rwa-support-desktopapp/src/scenes/add_rwahost_wizard/add_rwahost_wizard.cpp b/rwa-support-desktopapp/src/scenes/add_rwahost_wizard/add_rwahost_wizard.cpp new file mode 100644 index 0000000..7adbdf9 --- /dev/null +++ b/rwa-support-desktopapp/src/scenes/add_rwahost_wizard/add_rwahost_wizard.cpp @@ -0,0 +1,124 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2021 Daniel Teichmann + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "add_rwahost_wizard.h" +#include "../../RWADBusAdaptor.h" +#include "../../RWAHost.h" + +AddRWAHostWizard::AddRWAHostWizard(QObject *parent, + MainQMLAdaptor *main_gui, DBusAPI *dbus_api) : QObject(parent) { + Q_ASSERT(main_gui != nullptr); + Q_ASSERT(dbus_api != nullptr); + + _dbus_api = dbus_api; + _main_gui = main_gui; + + // _dbus_api --serviceAddWebAppHostResponse-> this.add_web_app_host_response() + QObject::connect(_dbus_api, + SIGNAL(serviceAddWebAppHostResponse(QJsonDocument*)), + this, + SLOT(add_web_app_host_response(QJsonDocument*))); +} + +void AddRWAHostWizard::processStep1(QString host_url, QString host_alias) { + qDebug() << "Processing Step 1 with args: " << host_url << host_alias; + + if(host_alias == "" || host_url == "") { + QString reason = tr("Both textfields can't be empty!"); + emit step1Failed(reason, Toast::ToastType::ToastWarning); + qDebug().noquote() << reason; + return; + } + + return add_server(host_url, host_alias); +} + +void AddRWAHostWizard::processStep2() { + qDebug() << "Processing Step 2 with args: No Args."; + emit step2Failed(tr("The features you expected here are not yet implemented."), Toast::ToastType::ToastWarning); + // Just show placeholder scene now. + emit step2Success(); +} + +void AddRWAHostWizard::add_server(QString host_url, QString host_alias) { + _dbus_api->add_web_app_host_request(host_url, host_alias); +} + +void AddRWAHostWizard::add_web_app_host_response(QJsonDocument *doc) { + // Q_ASSERT lets the program crash immediatly at startup, + // when the session service is not started. + // Don't use Q_ASSERT(doc != nullptr); instead use: + if (doc == nullptr) { + _main_gui->setRWAHostSelected(false); + _main_gui->showToast(tr("Can't connect to underlying session service!"), + 9800, + Toast::ToastType::ToastError); + return; + } + + // Get the QJsonObject + QJsonObject jObject = doc->object(); + QVariantMap mainMap = jObject.toVariantMap(); + + // Status of request + QString request_status = mainMap["status"].toString(); + if (request_status == "success") { + _dbus_api->get_web_app_hosts_request(); + + qInfo() << "Successfully added a new RWAHost."; + emit step1Success(); + } else { + qCritical().noquote() << tr("An error occured while adding a new host!"); + + uint toast_type = Toast::ToastType::ToastStandard; + QString reason = tr("An error occured while adding a new host!"); + QString type = mainMap["type"].toString(); + + if(type == "connection"){ + reason = tr("Couldn't connect to the specified host!"); + toast_type = Toast::ToastType::ToastError; + qCritical().noquote() << reason; + } else if (type == "duplicate") { + reason = tr("The specified host was already added!"); + toast_type = Toast::ToastType::ToastWarning; + qCritical().noquote() << reason; + } else if (type == "invalid_url") { + reason = tr("The specified host address is not valid!"); + toast_type = Toast::ToastType::ToastWarning; + qCritical().noquote() << reason; + } else if (type == "permission_denied") { + reason = tr("The specified host address does not grant access!"); + toast_type = Toast::ToastType::ToastError; + qCritical().noquote() << reason; + } else if (type == "unsupported_server") { + reason = tr("The specified host address is not supported!"); + toast_type = Toast::ToastType::ToastError; + qCritical().noquote() << reason; + } + emit step1Failed(reason, toast_type); + + return; + } +} diff --git a/rwa-support-desktopapp/src/scenes/add_rwahost_wizard/add_rwahost_wizard.h b/rwa-support-desktopapp/src/scenes/add_rwahost_wizard/add_rwahost_wizard.h new file mode 100644 index 0000000..f019be1 --- /dev/null +++ b/rwa-support-desktopapp/src/scenes/add_rwahost_wizard/add_rwahost_wizard.h @@ -0,0 +1,61 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2021 Daniel Teichmann + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef ADD_RWAHOST_WIZARD_H +#define ADD_RWAHOST_WIZARD_H + +#include + +#include "../../RWADBusAdaptor.h" +#include "../../DBusAPI.h" +#include "../../main_qmladaptor.h" + +class AddRWAHostWizard : public QObject +{ + Q_OBJECT +public: + explicit AddRWAHostWizard(QObject *parent = nullptr, + MainQMLAdaptor *main_gui = nullptr, + DBusAPI *dbus_api = nullptr); + void add_server(QString host_url, QString host_alias); + +private: + DBusAPI *_dbus_api; + MainQMLAdaptor *_main_gui; + +signals: + void step1Success(); + void step1Failed(QString reason, uint toast_type); + void step2Success(); + void step2Failed(QString reason, uint toast_type); + +public slots: + void processStep1(QString host_url, QString host_alias); + void processStep2(); + + void add_web_app_host_response(QJsonDocument *doc); +}; + +#endif // ADD_SERVER_WIZARD_H diff --git a/rwa-support-desktopapp/src/scenes/remote_control/Scene_remote_control.qml b/rwa-support-desktopapp/src/scenes/remote_control/Scene_remote_control.qml new file mode 100644 index 0000000..dc152ef --- /dev/null +++ b/rwa-support-desktopapp/src/scenes/remote_control/Scene_remote_control.qml @@ -0,0 +1,382 @@ +import QtQuick 2.9 +import QtQuick.Window 2.2 +import QtQuick.Extras 1.4 +import QtQuick.Controls 2.2 +import QtQuick.Dialogs 1.2 +import QtQuick.Controls.Material 2.3 + +/*! + * This .qml file is a Scene which can be loaded through for + * example a StackView (main_content in main.qml). + */ + +Item { + id: scene_remote_control + objectName: "Scene_remote_control" + + Label { + id: dbus_api_status_text + text: qsTr("Unknown state of session service.") + anchors.leftMargin: 10 + 5 + dbus_api_status_indicator.width + anchors.bottom: parent.bottom + anchors.bottomMargin: 10 + wrapMode: Text.WordWrap + anchors.rightMargin: 10 + verticalAlignment: Text.AlignVCenter + font.pointSize: 11 + fontSizeMode: Text.Fit + objectName: "dbus_api_status_text" + anchors.left: parent.left + anchors.right: parent.right + + StatusIndicator { + id: dbus_api_status_indicator + width: height + height: 20 + objectName: "dbus_api_status_indicator" + color: "#73d216" + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.left + anchors.rightMargin: 5 + active: false + } + } + + Label { + id: explain_function_label + text: qsTr("Please tell your remote support \ +partner your access address and \ +your access-PIN to let your partner \ +connect to this computer.") + wrapMode: Text.WordWrap + font.pixelSize: 18 + anchors.topMargin: 10 + anchors.leftMargin: 10 + anchors.rightMargin: 10 + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + horizontalAlignment: Text.AlignLeft + + color: Material.theme == Material.Light ? "#000000" : "#FFFFFF" + } + + Rectangle { + id: dbus_api_status_line + height: 1 + radius: 1 + anchors.right: parent.right + anchors.rightMargin: 10 + anchors.bottom: dbus_api_status_text.top + anchors.bottomMargin: 10 + opacity: 0.3 + gradient: Gradient { + GradientStop { + position: 0.391 + color: "#ffffff" + } + + GradientStop { + position: 0.975 + color: "#8b8b8b" + } + } + border.width: 1 + border.color: "#00000000" + anchors.left: parent.left + anchors.leftMargin: 10 + } + + Column { + id: column + spacing: 6 + anchors.right: parent.right + anchors.rightMargin: 10 + anchors.left: parent.left + anchors.leftMargin: 10 + anchors.bottom: dbus_api_status_line.top + anchors.bottomMargin: 10 + anchors.top: explain_function_label.bottom + anchors.topMargin: 10 + + Column { + id: url_group + width: parent.width + height: parent.height * 0.25 + spacing: 5 + + Label { + id: your_url_text + height: parent.height/2 + text: qsTr("Remote Support Address") + font.weight: Font.Bold + font.bold: true + verticalAlignment: Text.AlignBottom + horizontalAlignment: Text.AlignLeft + font.pointSize: 14 + fontSizeMode: Text.Fit + } + + TextEdit { + id: url_text + height: parent.height/2 + text: remote_control_manager.url + anchors.rightMargin: 10 + copy_url_to_clipboard_button.width + anchors.right: parent.right + wrapMode: Text.WrapAtWordBoundaryOrAnywhere + anchors.leftMargin: 10 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + font.pointSize: 15 + + readOnly: true + color: Material.foreground + selectByMouse: true + anchors.left: parent.left + + leftPadding: 5 + Rectangle { + radius: 5 + color: Material.theme == Material.Light ? "#F0F0F0" : "#383838" + height: url_text.height + // whole line + copy-into-clipboard button + some margin + width: url_text.width + copy_url_to_clipboard_button.width + 5 + 5 + x: 0; y: 0 + z: -1 + } + + Button { + id: copy_url_to_clipboard_button + width: copy_url_to_clipboard_image.width + 6 + height: copy_url_to_clipboard_image.height + 6 + 10 + anchors.verticalCenter: parent.verticalCenter + display: AbstractButton.IconOnly + anchors.leftMargin: 5 + anchors.left: url_text.right + highlighted: false + flat: true + + Image { + id: copy_url_to_clipboard_image + x: 0 + y: -26 + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + source: "../../../images/into-clipboard.svg" + opacity: 0.65 + } + + onClicked: { + remote_control_manager.handleCopyToClipboardButtonClick(url_text.text); + toast.show(qsTr("Copied access address into clipboard!"), + "5000", + mainqmladaptor.ToastInfo); + } + + ToolTip.text: qsTr("Copy the access address into the clipboard") + hoverEnabled: true + + ToolTip.delay: 600 + ToolTip.timeout: 5000 + ToolTip.visible: hovered + } + } + } + + Column { + id: session_id_group + width: parent.width + height: parent.height * 0.25 + spacing: 5 + + Label { + id: your_session_id_text + height: parent.height/2 + text: qsTr("Session-ID") + font.weight: Font.Bold + font.bold: true + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + font.pointSize: 14 + verticalAlignment: Text.AlignBottom + horizontalAlignment: Text.AlignLeft + fontSizeMode: Text.Fit + } + + TextEdit { + objectName: "session_id_text" + id: session_id_text + height: parent.height/2 + text: remote_control_manager.session_id + font.letterSpacing: 10 + anchors.rightMargin: 10 + copy_session_id_to_clipboard_button.width + anchors.right: parent.right + font.pointSize: 15 + anchors.left: parent.left + anchors.leftMargin: 10 + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + leftPadding: 5 + Rectangle { + radius: 5 + color: Material.theme == Material.Light ? "#F0F0F0" : "#383838" + height: session_id_text.height + // whole line + copy-into-clipboard button + some margin + width: session_id_text.width + copy_session_id_to_clipboard_button.width + 5 + 5 + x: 0; y: 0 + z: -1 + } + + readOnly: true + color: Material.foreground + wrapMode: Text.WordWrap + selectByMouse: true + + Button { + id: copy_session_id_to_clipboard_button + width: copy_session_id_to_clipboard_image.width + 6 + height: copy_session_id_to_clipboard_image.height + 6 + 10 + anchors.verticalCenter: parent.verticalCenter + flat: true + display: AbstractButton.IconOnly + anchors.left: session_id_text.right + anchors.leftMargin: 5 + + Image { + id: copy_session_id_to_clipboard_image + anchors.horizontalCenter: parent.horizontalCenter + opacity: 0.65 + anchors.verticalCenter: parent.verticalCenter + source: "../../../images/into-clipboard.svg" + fillMode: Image.PreserveAspectFit + } + + onClicked: { + remote_control_manager.handleCopyToClipboardButtonClick(session_id_text.text); + toast.show(qsTr("Copied session-ID into clipboard!"), + "5000", + mainqmladaptor.ToastInfo); + } + + ToolTip.text: qsTr("Copy the session-ID into the clipboard") + hoverEnabled: true + + ToolTip.delay: 600 + ToolTip.timeout: 5000 + ToolTip.visible: hovered + } + } + } + + Column { + id: pin_group + width: parent.width + height: parent.height * 0.25 + spacing: 5 + + Label { + id: your_pin_text + height: parent.height/2 + text: qsTr("Access-PIN") + font.weight: Font.Bold + font.bold: true + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + font.pointSize: 14 + verticalAlignment: Text.AlignBottom + horizontalAlignment: Text.AlignLeft + } + + TextEdit { + objectName: "pin_text" + id: pin_text + height: parent.height/2 + text: remote_control_manager.pin + anchors.rightMargin: 10 + copy_pin_to_clipboard_button.width + anchors.right: parent.right + font.pointSize: 15 + anchors.left: parent.left + anchors.leftMargin: 10 + font.letterSpacing: 10 + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + leftPadding: 5 + Rectangle { + radius: 5 + color: Material.theme == Material.Light ? "#F0F0F0" : "#383838" + height: url_text.height + // whole line + copy-into-clipboard button + some margin + width: url_text.width + copy_url_to_clipboard_button.width + 5 + 5 + x: 0; y: 0 + z: -1 + } + + readOnly: true + color: Material.foreground + wrapMode: Text.WordWrap + selectByMouse: true + + Button { + id: copy_pin_to_clipboard_button + width: copy_pin_to_clipboard_image.width + 6 + height: copy_pin_to_clipboard_image.height + 6 + 10 + anchors.verticalCenter: parent.verticalCenter + flat: true + display: AbstractButton.IconOnly + anchors.left: pin_text.right + anchors.leftMargin: 5 + + Image { + id: copy_pin_to_clipboard_image + anchors.verticalCenter: parent.verticalCenter + opacity: 0.65 + anchors.horizontalCenter: parent.horizontalCenter + source: "../../../images/into-clipboard.svg" + fillMode: Image.PreserveAspectFit + } + + onClicked: { + remote_control_manager.handleCopyToClipboardButtonClick(pin_text.text); + toast.show(qsTr("Copied PIN into clipboard!"), + "5000", + mainqmladaptor.ToastInfo); + } + + ToolTip.text: qsTr("Copy the pin into the clipboard") + hoverEnabled: true + + ToolTip.delay: 600 + ToolTip.timeout: 5000 + ToolTip.visible: hovered + } + } + } + + } + + Button { + id: start_support_button + height: Math.min(50) + objectName: "start_support_button" + text: checked ? qsTr("Stop remote support session") : qsTr("Start remote support session") + anchors.rightMargin: column.anchors.leftMargin + anchors.bottom: dbus_api_status_line.top + anchors.bottomMargin: 10 + anchors.right: parent.right + checkable: true + + onClicked: remote_control_manager.handleConnectButtonClick(checked); + } +} + +/*##^## +Designer { + D{i:0;autoSize:true;height:480;width:640} +} +##^##*/ diff --git a/rwa-support-desktopapp/src/scenes/remote_control/remote_control_manager.cpp b/rwa-support-desktopapp/src/scenes/remote_control/remote_control_manager.cpp new file mode 100644 index 0000000..b76ea2a --- /dev/null +++ b/rwa-support-desktopapp/src/scenes/remote_control/remote_control_manager.cpp @@ -0,0 +1,511 @@ +#include "remote_control_manager.h" + +#ifndef QT_NO_DEBUG +#define CHECK_TRUE(instruction) Q_ASSERT(instruction) +#else +#define CHECK_TRUE(instruction) (instruction) +#endif + +RemoteControlManager::RemoteControlManager(QQmlApplicationEngine *engine, + MainQMLAdaptor *main_gui, + DBusAPI *dbus_api) : QObject() { + Q_ASSERT(dbus_api != nullptr); + Q_ASSERT(main_gui != nullptr); + Q_ASSERT(engine != nullptr); + + _current_session = nullptr; + _sessions = new QSet; + _dbus_api = dbus_api; + _main_gui = main_gui; + _engine = engine; +} + +bool RemoteControlManager::setConnectButtonEnabled(bool enabled) { + // Find item via 'objectName' + QQuickItem *scene_remote_control = _engine->rootObjects().takeFirst()-> + findChild("Scene_remote_control"); + QQuickItem *item = scene_remote_control-> + findChild("start_support_button"); + if (item) { + item->setProperty("enabled", enabled); + if (item->property("checked").toBool()) { + item->setProperty("text", tr("Stop remote support session")); + } else { + item->setProperty("text", tr("Start remote support session")); + } + } else { + qWarning() << "Unable to find 'start_support_button' Item!"; + return false; + } + + return true; +} + +bool RemoteControlManager::setConnectButtonChecked(bool checked) { + // Find item via 'objectName' + QQuickItem *scene_remote_control = _engine->rootObjects().takeFirst()-> + findChild("Scene_remote_control"); + QQuickItem *item = scene_remote_control-> + findChild("start_support_button"); + if (item) { + item->setProperty("checked", checked); + } else { + qWarning() << "Unable to find 'start_support_button' Item!"; + return false; + } + + return true; +} + +bool RemoteControlManager::setStatusIndicatorText(QString status_text) { + // Find item via 'objectName' + QQuickItem *scene_remote_control = _engine->rootObjects().takeFirst()-> + findChild("Scene_remote_control"); + QQuickItem *item = scene_remote_control-> + findChild("dbus_api_status_text"); + if (item) { + item->setProperty("text", status_text); + } else { + qWarning() << "Unable to find 'dbus_api_status_text' Item!"; + return false; + } + + return true; +} + +bool RemoteControlManager::setStatusIndicatorColor(bool active, QColor color) { + // Find item via 'objectName' + QQuickItem *scene_remote_control = _engine->rootObjects().takeFirst()-> + findChild("Scene_remote_control"); + QQuickItem *item = scene_remote_control-> + findChild("dbus_api_status_indicator"); + if (item) { + item->setProperty("active", active); + item->setProperty("color", color); + } else { + qWarning() << "Unable to find 'dbus_api_status_indicator' Item!"; + return false; + } + + return true; +} + +void RemoteControlManager::handleCopyToClipboardButtonClick(QString copy_data) { + QClipboard *clipboard = QApplication::clipboard(); + QString originalText = clipboard->text(); + clipboard->setText(copy_data); + qDebug() << "Copied into clipboard:" << copy_data; +} + +QString RemoteControlManager::getURL() { + if (getCurrentSession() == nullptr) { + return tr("Not available yet"); + } + return getCurrentSession()->getURL(); +} + +QString RemoteControlManager::getPin() { + if (getCurrentSession() == nullptr) { + return "-----"; + } + return getCurrentSession()->getPin(); +} + +QString RemoteControlManager::getSessionID() { + if (getCurrentSession() == nullptr) { + return "-----"; + } + return getCurrentSession()->getSessionID(); +} + +Session* RemoteControlManager::getCurrentSession() { + return _current_session; +} + +void RemoteControlManager::addSession(Session *session) { + _sessions->insert(session); +} + +bool RemoteControlManager::removeSession(Session *session) { + if (getCurrentSession() == session) { + setCurrentSession(nullptr); + } + + bool ok = _sessions->remove(session); + + if (session != nullptr) { + session->disconnect(); + session->deleteLater(); + } + + setConnectButtonChecked(false); + setConnectButtonEnabled(true); + + currentSessionUrlChanged(tr("Not available yet")); + currentSessionPinChanged("-----"); + currentSessionSessionIDChanged("-----"); + + return ok; +} + +void RemoteControlManager::setCurrentSession(Session *session) { + if (session == nullptr) { + qDebug() << "Deselecting currentSession."; + _current_session = nullptr; + + return; + } + + if (_sessions->contains(session)) { + qDebug() << "Set currentSession to new session."; + _current_session = session; + + connectSession(_current_session); + } else { + qDebug() << "Given session was not in _sessions!"; + } +} + +void RemoteControlManager::connectSession(Session *session) { + // session --statusChanged-> this.currentSessionStatusChanged() + CHECK_TRUE(QObject::connect(session, + &Session::statusChanged, + this, + &RemoteControlManager::currentSessionStatusChanged)); + + // session --pinChanged-> this.currentSessionPinChanged() + CHECK_TRUE(QObject::connect(session, + &Session::pinChanged, + this, + &RemoteControlManager::currentSessionPinChanged)); + + // session --urlChanged-> this.currentSessionUrlChanged() + CHECK_TRUE(QObject::connect(session, + &Session::urlChanged, + this, + &RemoteControlManager::currentSessionUrlChanged)); + + // session --sessionIDChanged-> this.currentSessionSessionIDChanged() + CHECK_TRUE(QObject::connect(session, + &Session::sessionIDChanged, + this, + &RemoteControlManager::currentSessionSessionIDChanged)); + + + // session --startSucceeded -> this.currentSessionStartSucceeded() + CHECK_TRUE(QObject::connect(session, + &Session::startSucceeded, + this, + &RemoteControlManager::currentSessionStartSucceeded)); + + // session --startFailed-> this.currentSessionStartFailed() + CHECK_TRUE(QObject::connect(session, + &Session::startFailed, + this, + &RemoteControlManager::currentSessionStartFailed)); + + + // session --stopSucceeded-> this.currentSessionStopSucceeded() + CHECK_TRUE(QObject::connect(session, + &Session::stopSucceeded, + this, + &RemoteControlManager::currentSessionStopSucceeded)); + + // session --stopFailed-> this.currentSessionStopFailed() + CHECK_TRUE(QObject::connect(session, + &Session::stopFailed, + this, + &RemoteControlManager::currentSessionStopFailed)); + + + // session --statusSucceeded-> this.currentSessionStatusSucceeded() + CHECK_TRUE(QObject::connect(session, + &Session::statusSucceeded, + this, + &RemoteControlManager::currentSessionStatusSucceeded)); + + // session --statusFailed-> this.currentSessionStatusFailed() + CHECK_TRUE(QObject::connect(session, + &Session::statusFailed, + this, + &RemoteControlManager::currentSessionStatusFailed)); +} + +void RemoteControlManager::currentSessionStartFailed(QString error_message) { + _main_gui->showToast(error_message, 6000, Toast::ToastType::ToastError); + + // Start failed. No need to stop session, so remove it directly. + removeSession(getCurrentSession()); + + setConnectButtonChecked(false); + setConnectButtonEnabled(true); + + emit _main_gui->showWindow(); +} + +void RemoteControlManager::currentSessionStopFailed(QString error_message) { + _main_gui->showToast(error_message, 6000, Toast::ToastType::ToastError); + + // Stop failed, so don't do anything! The user should try again. + + // Set status indicator to the corresponding error message. + QString translated = translateStatusIndicatorText("stop_session_error"); + setStatusIndicatorText(translated); + + setConnectButtonChecked(true); + setConnectButtonEnabled(true); + + emit _main_gui->showWindow(); +} + +void RemoteControlManager::currentSessionStatusFailed(QString error_message) { + _main_gui->showToast(error_message, 6000, Toast::ToastType::ToastError); + + // Set status indicator to the corresponding error message. + QString translated = translateStatusIndicatorText("status_session_error"); + setStatusIndicatorText(translated); + + setConnectButtonChecked(false); + setConnectButtonEnabled(true); + + currentSessionUrlChanged(tr("Not available yet")); + currentSessionPinChanged("-----"); + currentSessionSessionIDChanged("-----"); + + emit _main_gui->showWindow(); +} + +void RemoteControlManager::currentSessionStartSucceeded() { + Session *current_session = getCurrentSession(); + if (current_session != nullptr) { + _main_gui->showToast( + tr("Session was started on '%0' successfully") + .arg(current_session->getHost()->alias()), + 6000, + Toast::ToastType::ToastSuccess + ); + } else { + qCritical().noquote() << tr("currentSessionStartSucceeded(): " + "Current Session is nullptr!"); + _engine->exit(1); + } + + // Set status indicator to the corresponding error message. + QString translated = translateStatusIndicatorText("start_session_success"); + setStatusIndicatorText(translated); + + setConnectButtonChecked(true); + setConnectButtonEnabled(true); +} + +void RemoteControlManager::currentSessionStopSucceeded() { + qDebug() << "Session stop succeeded: Delete current session object now."; + bool ok = removeSession(getCurrentSession()); + if (!ok) { + qWarning() << tr("Couldn't remove current session out of '_sessions' list."); + } + + _main_gui->showToast(tr("Remote support session was stopped."), + 6000, + Toast::ToastType::ToastSuccess); + + // Set status indicator to the corresponding error message. + QString translated = translateStatusIndicatorText("stop_session_success"); + setStatusIndicatorText(translated); + + setConnectButtonChecked(false); + setConnectButtonEnabled(true); +} + +void RemoteControlManager::currentSessionUnexpectedStop(QString error_message) { + _main_gui->showToast(error_message, 6000, Toast::ToastType::ToastError); + + setConnectButtonChecked(false); + setConnectButtonEnabled(true); + + qDebug() << "Delete current session object now."; + bool ok = removeSession(getCurrentSession()); + if (!ok) { + qWarning() << tr("Couldn't remove current session out of '_sessions' list."); + } +} + +void RemoteControlManager::currentSessionStatusSucceeded() { + // Nothing to do. +} + +void RemoteControlManager::currentSessionStatusChanged(QString new_status_code) { + Session *current_session = getCurrentSession(); + if (current_session == nullptr || !current_session->started) { + qDebug() << "RemoteControlManager::currentSessionStatusChanged(QString): " + "got called even though the session isn't even started."; + return; + } + QString translated = translateStatusIndicatorText(new_status_code); + setStatusIndicatorText(translated); +} + +QString RemoteControlManager::translateStatusIndicatorText(QString status_code) { + QString guiString = tr("Unknown state of service"); + setStatusIndicatorColor(false); + + if (status_code == "dead") { + + /* Session died */ + guiString = tr("Remote Support session was stopped ungracefully"); + + // Red color + setStatusIndicatorColor(true, QColor(255, 0, 0, 127)); + + currentSessionUnexpectedStop(guiString); + + } else if (status_code == "stopped") { + + /* Session was stopped normally somehow other than the users request. + * Remote support partner could have clicked exit for example */ + guiString = tr("Remote Support session was stopped"); + + // Green color + setStatusIndicatorColor(true, QColor(0, 255, 0, 127)); + + currentSessionUnexpectedStop(guiString); + + } else if (status_code == "active") { + + /* Partner is connected */ + guiString = tr("Your partner is connected to the Remote Support session"); + + // Green color + setStatusIndicatorColor(true, QColor(0, 255, 0, 127)); + + } else if (status_code == "start_session_success" || status_code == "running") { + + /* Session successfully started */ + guiString = tr("Remote Support session successfully started! " + "Waiting for your remote support partner to connect."); + + // yellow color (will be green when partner is connected) + setStatusIndicatorColor(true, QColor(255, 255, 0, 127)); + + } else if (status_code == "start_session_error") { + + /* Session couldn't be started */ + guiString = tr("Remote Support session couldn't be started!"); + + // Red color + setStatusIndicatorColor(true, QColor(255, 0, 0, 127)); + + } else if (status_code == "stop_session_success") { + + /* Session was successfully stopped by the users request */ + guiString = tr("Session stopped successfully."); + + // Green color + setStatusIndicatorColor(true, QColor(0, 255, 0, 127)); + + } else if (status_code == "stop_session_error") { + + /* Session couldn't be stopped */ + guiString = tr("Session could not be stopped!") + "\n" + + tr("remote support partner could still be connected!"); + + // Red color + setStatusIndicatorColor(true, QColor(255, 0, 0, 127)); + + } else if (status_code == "status_session_error") { + + /* Session's status couldn't be refreshed */ + guiString = tr("Session status could not be refreshed! " + "Your remote support partner could still be connected!"); + + // Red color + setStatusIndicatorColor(true, QColor(255, 0, 0, 127)); + + } + + qDebug().noquote() << QString("Translating status code '%0' to '%1'") + .arg(status_code) + .arg(guiString); + return guiString; +} + +void RemoteControlManager::currentSessionPinChanged(QString pin) { + emit pinChanged(pin); +} + +void RemoteControlManager::currentSessionUrlChanged(QString url) { + emit urlChanged(url); +} + +void RemoteControlManager::currentSessionSessionIDChanged(QString session_id) { + emit sessionIDChanged(session_id); +} + +void RemoteControlManager::connectToDBusAPI(Session *session) { + // _dbus_api --sessionStartResponse-> this.start_response() + CHECK_TRUE(QObject::connect(_dbus_api, + &DBusAPI::serviceStartResponse, + session, + &Session::start_response)); + + // _dbus_api --serviceStopResponse-> this.stop_response() + CHECK_TRUE(QObject::connect(_dbus_api, + &DBusAPI::serviceStopResponse, + session, + &Session::stop_response, + Qt::DirectConnection)); + + // _dbus_api --sessionStatusResponse-> this.status_response() + CHECK_TRUE(QObject::connect(_dbus_api, + &DBusAPI::serviceStatusResponse, + session, + &Session::status_response)); +} + +void RemoteControlManager::handleConnectButtonClick(bool checked) { + if (checked) { + // Create a Session object and start it. + qDebug() << "Creating and starting a new session object now."; + RWAHost *selected_host = _main_gui->getSelectedRWAHost(); + if (selected_host) { + qInfo() << tr("Creating a new session object."); + Session *new_session = new Session(_dbus_api, selected_host); + + connectToDBusAPI(new_session); + + qDebug() << "Adding session to QSet"; + addSession(new_session); + + qDebug() << "Setting session as current session."; + setCurrentSession(new_session); + + qInfo().noquote() << tr("Starting a remote support session on host '%0' " + "using the new session object.") + .arg(selected_host->uuid()); + new_session->start(); + } else { + qCritical().noquote() << tr("Can't start a remote support session. " + "There is no RWA host is selected!"); + } + + setConnectButtonChecked(false); + setConnectButtonEnabled(false); + } else { + Session *current_session = getCurrentSession(); + if (current_session != nullptr) { + emit current_session->stop(); + } else { + qCritical().noquote() << tr("RemoteControlManager::" + "handleConnectButtonClick(): Current Session " + "is nullptr!"); + setConnectButtonChecked(false); + setConnectButtonEnabled(true); + } + } +} + +/*void RemoteControlManager::onCloseHandler() { + // To cleanup things here + // check current session nullptr + getCurrentSession()->stop(); +}*/ diff --git a/rwa-support-desktopapp/src/scenes/remote_control/remote_control_manager.h b/rwa-support-desktopapp/src/scenes/remote_control/remote_control_manager.h new file mode 100644 index 0000000..4554724 --- /dev/null +++ b/rwa-support-desktopapp/src/scenes/remote_control/remote_control_manager.h @@ -0,0 +1,78 @@ +#ifndef REMOTE_CONTROL_MANAGER_H +#define REMOTE_CONTROL_MANAGER_H + +#include + +#include "../../main_qmladaptor.h" +#include "../../DBusAPI.h" +#include "../../session.h" + +class RemoteControlManager : public QObject { + + Q_OBJECT + // this makes url available as a QML property + Q_PROPERTY(QString url READ getURL NOTIFY urlChanged) + // this makes pin available as a QML property + Q_PROPERTY(QString pin READ getPin NOTIFY pinChanged) + // this makes session_id available as a QML property + Q_PROPERTY(QString session_id READ getSessionID NOTIFY sessionIDChanged) + +public: + explicit RemoteControlManager(QQmlApplicationEngine *engine = nullptr, + MainQMLAdaptor *main_gui = nullptr, + DBusAPI *dbus_api = nullptr); + + bool setConnectButtonEnabled(bool enabled); + bool setConnectButtonChecked(bool checked); + bool setStatusIndicatorColor(bool active, QColor color = QColor(255,255,255)); + + QString translateStatusIndicatorText(QString status_code); + bool setStatusIndicatorText(QString status_text); + +private: + DBusAPI *_dbus_api; + MainQMLAdaptor *_main_gui; + QQmlApplicationEngine *_engine; + Session *_current_session; + QSet *_sessions; + + void connectSession(Session *session); + void connectToDBusAPI(Session *session); + + bool refreshTimerIsRunning; + +signals: + void onConnectButtonClick(bool checked); + void pinChanged(QString pin); + void urlChanged(QString URL); + void sessionIDChanged(QString session_id); + +public slots: + void handleCopyToClipboardButtonClick(QString copy_data); + void handleConnectButtonClick(bool checked); + + void setCurrentSession(Session *session); + void addSession(Session *session); + bool removeSession(Session *session); + + void currentSessionStatusChanged(QString); + void currentSessionPinChanged(QString); + void currentSessionSessionIDChanged(QString); + void currentSessionUrlChanged(QString); + + QString getURL(); + QString getPin(); + QString getSessionID(); + Session* getCurrentSession(); + + void currentSessionStartFailed(QString error_message); + void currentSessionStopFailed(QString error_message); + void currentSessionStatusFailed(QString error_message); + void currentSessionUnexpectedStop(QString error_message); + + void currentSessionStartSucceeded(); + void currentSessionStopSucceeded(); + void currentSessionStatusSucceeded(); +}; + +#endif // REMOTECONTROLMANAGER_H diff --git a/rwa-support-desktopapp/src/session.cpp b/rwa-support-desktopapp/src/session.cpp new file mode 100644 index 0000000..25a8512 --- /dev/null +++ b/rwa-support-desktopapp/src/session.cpp @@ -0,0 +1,271 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2020, 2021 Daniel Teichmann + * Copyright 2020, 2021 Mike Gabriel + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "session.h" + +Session::Session(DBusAPI *dbus_api, RWAHost *host) : QObject() { + Q_ASSERT(host != nullptr); + Q_ASSERT(dbus_api != nullptr); + + _dbus_api = dbus_api; + _host = host; + + setPin("-----"); + setSessionID("-----"); + setURL(tr("Not available yet")); + setStatus("unknown"); + started = false; +} + +Session::~Session() { + qDebug().noquote() << QString("Session #'%0' on host '%1' will be deconstructed.") + .arg(getSessionID()) + .arg(getHost()->alias()); + stop(); + disconnect(); +} + +void Session::statusTimerEvent() { + qDebug() << "Status timer event triggered"; + + refresh_status(); +} + +bool Session::isSessionAliveOrRunning() { + if (getStatus() == "running" || getStatus() == "active") { + return true; + } else { + return false; + } +} + +RWAHost* Session::getHost() { + return _host; +} + +QString Session::getStatus() { + return _status; +} + +QString Session::getURL() { + return _url; +} + +QString Session::getSessionID() { + return _session_id; +} + +QString Session::getPin() { + return _pin; +} + +void Session::setURL(QString url) { + _url = url; + emit urlChanged(url); +} + +void Session::setSessionID(QString session_id) { + _session_id = session_id; + emit sessionIDChanged(session_id); +} + +void Session::setPin(QString pin) { + _pin = pin; + emit pinChanged(pin); +} + +void Session::setHost(RWAHost *host) { + _host = host; + emit hostChanged(host); +} + +void Session::setStatus(QString status) { + _status = status; + emit statusChanged(status); +} + +void Session::start() { + _dbus_api->start_request(_host); +} + +void Session::start_response(QJsonDocument *doc) { + // Q_ASSERT lets the program crash immediatly after method call + // when the session service is not started. + // Don't use Q_ASSERT(doc != nullptr); instead use: + if (doc == nullptr) { + emit startFailed(tr("Can't connect to underlying session service! " + "Is the session service started?")); + return; + } + + // Get the QJsonObject + QJsonObject jObject = doc->object(); + QVariantMap mainMap = jObject.toVariantMap(); + + // Status of request + QString status = mainMap["status"].toString(); + if (status != "success") { + QString type = mainMap["type"].toString(); + QString error_message = tr("An error occured while creating a new session!"); + + if (type == "multiple") { + // TODO: Ask to stop other session via a message dialog. + error_message = tr("The session service is configured " + "to not support multiple sessions " + "and there is already a session running."); + } else if (type == "connection") { + error_message = tr("Couldn't connect to host '%0'.") + .arg(getHost()->alias()); + } else if (type == "host_not_found") { + error_message = tr("The RWA host '%0' couldn't be found.") + .arg(getHost()->alias()); + } else if (type == "permission_denid") { + error_message = tr("The RWA host '%0' doesn't grant access.") + .arg(getHost()->alias()); + } else if (type == "unsupported_server") { + error_message = tr("The RWA host '%0' is not supported.") + .arg(getHost()->alias()); + } + + setStatus("start_session_error"); + qCritical().noquote() << error_message; + emit startFailed(error_message); + return; + } + + bool ok; + + // URL of remote web app frontend + QString url = mainMap["url"].toString(); + this->setURL(url); + + // PIN + long long pin = mainMap["pin"].toLongLong(&ok); + // Sanity Check + if(ok == false){ + QString error_message = "Unable to parse into longo long out of dbus answer!"; + qCritical().noquote() << error_message; + emit startFailed(error_message); + return; + } + this->setPin(QString::number(pin)); + + // session_id = remote support id from the rwa-server + long long session_id = mainMap["session_id"].toLongLong(); + // Sanity Check + if(ok == false){ + QString error_message = "Unable to parse into long long out of dbus answer!"; + qCritical().noquote() << error_message; + emit startFailed(error_message); + return; + } + this->setSessionID(QString::number(session_id)); + + qDebug() << "Got session_id:" << session_id << + "\nGot url:" << url << + "\nGot pin:" << pin; + + emit pinChanged(QString::number(pin)); + emit urlChanged(url); + emit sessionIDChanged(QString::number(session_id)); + + started = true; + + // Ask status every 1000 millisecond + + QTimer *timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, + QOverload<>::of(&Session::statusTimerEvent)); + timer->start(1000); + + qDebug() << "Successfully started a session."; + this->setStatus("start_session_success"); + + emit startSucceeded(); +} + +void Session::stop() { + if (started) + _dbus_api->stop_request(getHost(), getSessionID()); +} + +void Session::stop_response(QJsonDocument *doc) { + // Q_ASSERT lets the program crash immediatly after method call + // when the session service is not started. + // Don't use Q_ASSERT(doc != nullptr); instead use: + if (doc == nullptr) { + emit stopFailed(tr("Can't connect to underlying session service! " + "Is the session service started?")); + return; + } + + QJsonObject jObject = doc->object(); + QVariantMap mainMap = jObject.toVariantMap(); + + QString new_status = mainMap["status"].toString(); + qDebug() << "stop_response() retrieved json. Status now:" << new_status; + + started = false; + + this->setStatus(new_status); + + emit stopSucceeded(); +} + +void Session::status() { + _dbus_api->status_request(getHost(), this->getSessionID()); +} + +void Session::refresh_status() { + _dbus_api->refresh_status_request(getHost(), this->getSessionID()); +} + +void Session::status_response(QJsonDocument *doc) { + // Q_ASSERT lets the program crash immediatly after method call, + // when the session service is not started. + // Don't use Q_ASSERT(doc != nullptr); instead use: + if (doc == nullptr) { + if (!_emitted_status_error_already) { + emit statusFailed(tr("Can't connect to underlying session service! " + "Is the session service started?")); + + _emitted_status_error_already = true; + } + + return; + } + + _emitted_status_error_already = false; + + QJsonObject jObject = doc->object(); + QVariantMap mainMap = jObject.toVariantMap(); + QString new_status = mainMap["status"].toString(); + qDebug() << "status_response() retrieved json. Status:" << new_status; + + setStatus(new_status); + + emit statusSucceeded(); +} diff --git a/rwa-support-desktopapp/src/session.h b/rwa-support-desktopapp/src/session.h new file mode 100644 index 0000000..e1c924f --- /dev/null +++ b/rwa-support-desktopapp/src/session.h @@ -0,0 +1,104 @@ +/* + * This file is part of Remote Support Desktop + * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp + * Copyright 2020, 2021 Daniel Teichmann + * Copyright 2020, 2021 Mike Gabriel + * SPDX-License-Identifier: GPL-2.0-or-later + * + * 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. + * + * 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 General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SESSION_H +#define SESSION_H + +#include +#include +#include +#include +#include + +#include "RWAHost.h" +#include "DBusAPI.h" + +class Session : public QObject { + Q_OBJECT + +public: + explicit Session(DBusAPI *dbus_api = nullptr, + RWAHost *host = nullptr); + ~Session(); + + QString getStatus(); + QString getURL(); + QString getSessionID(); + QString getPin(); + RWAHost* getHost(); + + void setStatus(QString status); + void setURL(QString url); + void setSessionID(QString session_id); + void setPin(QString pin); + void setHost(RWAHost *host); + + void start(); + void stop(); + void status(); + void refresh_status(); + + bool started; + +private: + void statusTimerEvent(); + + bool _emitted_status_error_already; + QString _status; + RWAHost *_host; + DBusAPI *_dbus_api; + + QString _session_id; + QString _url; + QString _pin; + + bool _minimizedBefore = false; + +signals: + void statusChanged(QString); + void sessionIDChanged(QString); + void urlChanged(QString); + void pinChanged(QString); + void hostChanged(RWAHost*); + + void startFailed(QString error_message); + void stopFailed(QString error_message); + void statusFailed(QString error_message); + + void startSucceeded(); + void stopSucceeded(); + void statusSucceeded(); + +public slots: + // Returns true if a session is somewhat usable (Running, Alive, etc..) + bool isSessionAliveOrRunning(); + + void start_response(QJsonDocument*); + void stop_response(QJsonDocument*); + void status_response(QJsonDocument*); +}; + +#endif // SESSION_H diff --git a/rwa-support-desktopapp/update_locales.sh b/rwa-support-desktopapp/update_locales.sh new file mode 100755 index 0000000..8c05ece --- /dev/null +++ b/rwa-support-desktopapp/update_locales.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# This file is part of Remote Support Desktop +# https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp +# Copyright 2020-2021 Daniel Teichmann +# Copyright 2020-2021 Mike Gabriel +# SPDX-License-Identifier: GPL-2.0-or-later +# +# 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. +# +# 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 General Public License +# along with this program; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +lupdate rwa-support-desktopapp.pro -no-obsolete +linguist locales/*.ts +lrelease rwa-support-desktopapp.pro -compress -removeidentical diff --git a/src/DBusAPI.cpp b/src/DBusAPI.cpp deleted file mode 100644 index 9a0f8de..0000000 --- a/src/DBusAPI.cpp +++ /dev/null @@ -1,423 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp - * Copyright 2021 Daniel Teichmann - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "DBusAPI.h" - -/*! - * \class DBusAPI - * \brief The DBusAPI class provides all necessary D-Bus methods and distributes the response via signals. - */ -DBusAPI::DBusAPI() { - _initDBus(); -} - -/*! - * \brief Initializes private _dbus_rwa object. - */ -void DBusAPI::_initDBus() { - if (!QDBusConnection::sessionBus().isConnected()) { - qCritical() << "Cannot connect to the D-Bus session bus."; - } - - // Create DBus object - _dbus_rwa = new OrgArcticaProjectRWASupportSessionServiceInterface("org.ArcticaProject.RWASupportSessionService", - "/RWASupportSessionService", - QDBusConnection::sessionBus(), - this->parent()); - - qDebug("Initialized DBus object!"); -} - -/*! - * \brief Ask the session service to start a session. - * - * \a host RWAHost object which includes all necessary information about a RWA host. - */ -void DBusAPI::start_request(RWAHost *host) { - Q_ASSERT(host != nullptr); - - qDebug() << "Requesting D-Bus service to start a new session on host:" << host->alias(); - - // Make an asynchronous 'start' call (Response will be sent to 'start_reply') - QDBusPendingCall async = _dbus_rwa->asyncCall("start", host->uuid()); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); - - QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(start_reply(QDBusPendingCallWatcher*))); -} - -/*! - * \brief Method gets called when a D-Bus response is ready. - * - * \a call contains the D-Bus response (session service or for example maybe just a error message). - * - * TODO: Example of json input - */ -void DBusAPI::start_reply(QDBusPendingCallWatcher *call) { - QString result = ""; - QDBusPendingReply reply = *call; - if (reply.isError()) { - qCritical() << "D-Bus 'start' request failed, this was the reply:"; - qCritical() << reply.error(); - - if (QDBusError::ServiceUnknown == reply.error().type()) { - qCritical() << "The session service was probably just not started!"; - } - - emit serviceStartResponse(nullptr); - - return; - } else { - result = reply.argumentAt<0>(); - } - call->deleteLater(); - - qDebug() << "Raw JSON from starting session is:" << result.toUtf8().replace('"', ""); - QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); - - emit serviceStartResponse(&doc); -} - -/*! - * \brief Ask the session service to stop session #. - * - * \a host RWAHost object which includes all necessary information about a RWA host. - * - * \a session_id Unique identifier for a session in a specific host. - */ -void DBusAPI::stop_request(RWAHost *host, QString session_id) { - Q_ASSERT(host != nullptr); - Q_ASSERT(session_id != ""); - - bool ok; - long long session_id_number = session_id.toLongLong(&ok); - - // Sanity Check - if(ok == false){ - qWarning().noquote() << QString("Unable to parse session_id '%0' as long long!").arg(session_id); - return; - } - - qDebug().noquote() << QString("Requesting D-Bus service to stop " - "session #'%0' on host '%1'") - .arg(session_id) - .arg(host->alias()); - - // Make an asynchronous 'stop' call (Response will be sent to 'stop_reply') - QDBusPendingCall async = _dbus_rwa->asyncCall("stop", host->uuid(), session_id_number); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); - - QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(stop_reply(QDBusPendingCallWatcher*))); -} - -/*! - * \brief Method gets called when a D-Bus response is ready. - * - * \a call contains the D-Bus response (session service or for example maybe just a error message). - * - * TODO: Example of json input - */ -void DBusAPI::stop_reply(QDBusPendingCallWatcher *call) { - QString result = ""; - - QDBusPendingReply reply = *call; - if (reply.isError()) { - qCritical() << "D-Bus 'stop' request failed, this was the reply:"; - qCritical() << reply.error(); - - if (QDBusError::ServiceUnknown == reply.error().type()) { - qCritical() << "The session service was probably just not started!"; - } - - emit serviceStopResponse(nullptr); - - return; - } else { - result = reply.argumentAt<0>(); - } - call->deleteLater(); - - qDebug() << "Raw JSON from stopping a session is:" << result.toUtf8().replace('"', ""); - QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); - - emit serviceStopResponse(&doc); -} - -/*! - * \brief Ask the session service for status of . - * - * \a host RWAHost object which includes all necessary information about a RWA host. - * - * \a session_id Unique identifier for a session in a specific host. - */ -void DBusAPI::status_request(RWAHost *host, QString session_id) { - Q_ASSERT(host != nullptr); - Q_ASSERT(session_id != ""); - - bool ok; - long long session_id_number = session_id.toLongLong(&ok); - - // Sanity Check - if(ok == false){ - qWarning().noquote() << QString("Unable to parse session_id '%0' as long long!").arg(session_id); - return; - } - - qDebug().noquote() << QString("Requesting D-Bus service for status of session " - "#'%0' on host '%1'").arg(session_id).arg(host->alias()); - - // Make an asynchronous 'start' call (Response will be sent to 'status_reply') - QDBusPendingCall async = _dbus_rwa->asyncCall("status", host->uuid(), session_id_number); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); - - QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(status_reply(QDBusPendingCallWatcher*))); -} - -/*! - * \brief Forces the session service to refresh it's status of and tell us about it then. - * - * \a host RWAHost object which includes all necessary information about a RWA host. - * - * \a session_id Unique identifier for a session in a specific host. - */ -void DBusAPI::refresh_status_request(RWAHost *host, QString session_id) { - Q_ASSERT(host != nullptr); - Q_ASSERT(session_id != ""); - - bool ok; - long long session_id_number = session_id.toLongLong(&ok); - - // Sanity Check - if(ok == false){ - qWarning().noquote() << QString("Unable to parse session_id '%0' as long long!").arg(session_id); - return; - } - - qDebug().noquote() << QString("Requesting D-Bus service for refresh_status of session " - "#'%0' on host '%1'").arg(session_id).arg(host->alias()); - - // Make an asynchronous 'start' call (Response will be sent to 'status_reply') - QDBusPendingCall async = _dbus_rwa->asyncCall("refresh_status", host->uuid(), session_id_number); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); - - QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(status_reply(QDBusPendingCallWatcher*))); -} - -/*! - * \brief Method gets called when a D-Bus response is ready. - * - * \a call contains the D-Bus response (session service or for example maybe just a error message). - * - * TODO: Example of json input - */ -void DBusAPI::status_reply(QDBusPendingCallWatcher *call){ - QString result = ""; - - QDBusPendingReply reply = *call; - if (reply.isError()) { - qCritical() << "D-Bus '(refresh_)status' request failed, this was the reply:"; - qCritical() << reply.error(); - - if (QDBusError::ServiceUnknown == reply.error().type()) { - qCritical() << "The session service was probably just not started!"; - } - - emit serviceStatusResponse(nullptr); - - return; - } else { - result = reply.argumentAt<0>(); - } - call->deleteLater(); - - // Get the QJsonObject - qDebug() << "Raw JSON from a status request for a session is:" << result.toUtf8().replace('"', ""); - QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); - - emit serviceStatusResponse(&doc); -} - -/*! - * \brief This method requests the session service to list all RWAHosts. - */ -void DBusAPI::get_web_app_hosts_request() { - qDebug().noquote() << QString("Requesting D-Bus service to list " - "all remote web app hosts"); - - // Make an asynchronous 'get_web_app_hosts' call - // Response will be sent to 'get_web_app_hosts_reply' - QDBusPendingCall async = _dbus_rwa->asyncCall("get_web_app_hosts"); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); - - QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(get_web_app_hosts_reply(QDBusPendingCallWatcher*))); -} - -/*! - * \brief This method requests the session service to add a RWAHost to its configuration files. - * - * \a host_url is the remote web app adress which will be used by the session service to coordinate - * sessions, connections, settings and such. - */ -void DBusAPI::add_web_app_host_request(QString host_url, QString host_alias) { - Q_ASSERT(host_url != ""); - Q_ASSERT(host_alias != ""); - - qDebug().noquote() << QString("Requesting D-Bus service to register new " - "remote web app host '%0' with url '%1'").arg(host_alias).arg(host_url); - - // Make an asynchronous 'add_web_app_host' call - // Response will be sent to 'add_web_app_host_reply' - QDBusPendingCall async = _dbus_rwa->asyncCall("add_web_app_host", host_url, host_alias); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); - - QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(add_web_app_host_reply(QDBusPendingCallWatcher*))); -} - -/*! - * \brief This method requests the session service to remove a RWAHost from its configuration files. - * - * \a host_uuid Unique identifier which all hosts have. - */ -void DBusAPI::remove_web_app_host_request(QString host_uuid) { - Q_ASSERT(host_uuid != ""); - - qDebug().noquote() << QString("Requesting D-Bus service to list " - "all remote web app hosts"); - - // Make an asynchronous 'remove_web_app_host' call - // Response will be sent to 'remove_web_app_host_reply' - QDBusPendingCall async = _dbus_rwa->asyncCall("remove_web_app_host", host_uuid); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); - - QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(remove_web_app_host_reply(QDBusPendingCallWatcher*))); -} - -/*! - * \brief Method gets called when a D-Bus response is ready. - * - * \a call contains the D-Bus response (session service or for example maybe just a error message). - * - * TODO: Example of json input - */ -void DBusAPI::get_web_app_hosts_reply(QDBusPendingCallWatcher *call){ - QString result = ""; - - QDBusPendingReply reply = *call; - if (reply.isError()) { - qCritical() << "D-Bus 'get_web_app_hosts' request failed, this was the reply:"; - qCritical() << reply.error(); - - if (QDBusError::ServiceUnknown == reply.error().type()) { - qCritical() << "The session service was probably just not started!"; - } - - emit serviceGetWebAppHostsResponse(nullptr); - - return; - } else { - result = reply.argumentAt<0>(); - } - call->deleteLater(); - - // Get the QJsonObject - qDebug() << "Raw JSON from the remote web app host listing request:" << result.toUtf8().replace('"', ""); - QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); - - emit serviceGetWebAppHostsResponse(&doc); -} - -/*! - * \brief Method gets called when a D-Bus response is ready. - * - * \a call contains the D-Bus response (session service or for example maybe just a error message). - * - * TODO: Example of json input - */ -void DBusAPI::add_web_app_host_reply(QDBusPendingCallWatcher *call){ - QString result = ""; - - QDBusPendingReply reply = *call; - if (reply.isError()) { - qCritical() << "D-Bus 'add_web_app_host' request failed, this was the reply:"; - qCritical() << reply.error(); - - if (QDBusError::ServiceUnknown == reply.error().type()) { - qCritical() << "The session service was probably just not started!"; - } - - emit serviceAddWebAppHostResponse(nullptr); - - return; - } else { - result = reply.argumentAt<0>(); - } - call->deleteLater(); - - // Get the QJsonObject - qDebug() << "Raw JSON from the remote web app host register request:" << result.toUtf8().replace('"', ""); - QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); - - emit serviceAddWebAppHostResponse(&doc); -} - -/*! - * \brief Method gets called when a D-Bus response is ready. - * - * \a call contains the D-Bus response (session service or for example maybe just a error message). - * - * TODO: Example of json input - */ -void DBusAPI::remove_web_app_host_reply(QDBusPendingCallWatcher *call){ - QString result = ""; - - QDBusPendingReply reply = *call; - if (reply.isError()) { - qCritical() << "D-Bus 'remove_web_app_host' request failed, this was the reply:"; - qCritical() << reply.error(); - - if (QDBusError::ServiceUnknown == reply.error().type()) { - qCritical() << "The session service was probably just not started!"; - } - - emit serviceRemoveWebAppHostResponse(nullptr); - - return; - } else { - result = reply.argumentAt<0>(); - } - call->deleteLater(); - - // Get the QJsonObject - qDebug() << "Raw JSON from the remote web app host deletion request:" << result.toUtf8().replace('"', ""); - QJsonDocument doc = QJsonDocument::fromJson(result.toUtf8()); - - emit serviceRemoveWebAppHostResponse(&doc); -} diff --git a/src/DBusAPI.h b/src/DBusAPI.h deleted file mode 100644 index 63dbe68..0000000 --- a/src/DBusAPI.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp - * Copyright 2021 Daniel Teichmann - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef DBUSAPI_H -#define DBUSAPI_H - -#include -#include - -#include "RWAHost.h" -#include "RWADBusAdaptor.h" - -class DBusAPI : public QObject { - Q_OBJECT -public: - explicit DBusAPI(); - -signals: - void serviceStartResponse(QJsonDocument*); - void serviceStopResponse(QJsonDocument*); - void serviceStatusResponse(QJsonDocument*); - - void serviceGetWebAppHostsResponse(QJsonDocument*); - void serviceAddWebAppHostResponse(QJsonDocument*); - void serviceRemoveWebAppHostResponse(QJsonDocument*); - -public slots: - void start_reply(QDBusPendingCallWatcher *call); - void stop_reply(QDBusPendingCallWatcher *call); - void status_reply(QDBusPendingCallWatcher *call); - - void get_web_app_hosts_reply(QDBusPendingCallWatcher *call); - void add_web_app_host_reply(QDBusPendingCallWatcher *call); - void remove_web_app_host_reply(QDBusPendingCallWatcher *call); - - - // Starts a remote web app session - void start_request(RWAHost *host); - - // Stop a remote web app session - void stop_request(RWAHost *host, QString session_id); - - // Refreshes a remote web app session's status - void refresh_status_request(RWAHost *host, QString session_id); - - // Gets a remote web app session's status - void status_request(RWAHost *host, QString session_id); - - // Gets all remote web app hosts deposited in the session server - void get_web_app_hosts_request(); - - // Add a specific remote web app host using a url to make sure its contactable - void add_web_app_host_request(QString host_url, QString host_alias); - - // Removes a specific remote web app host using the uuid of a host - void remove_web_app_host_request(QString host_uuid); - -private: - OrgArcticaProjectRWASupportSessionServiceInterface* _dbus_rwa; - - void _initDBus(); - -}; - -#endif // DBUSAPI_H diff --git a/src/ListItem.qml b/src/ListItem.qml deleted file mode 100644 index fa83f4b..0000000 --- a/src/ListItem.qml +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp - * Copyright 2021 Daniel Teichmann - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import QtQuick 2.0 -import QtQuick.Controls.Material 2.3 -import QtQuick.Controls 2.2 - -ItemDelegate { - id: root - width: parent.width - height: 50 - - property string scene_url - - signal listItemClick() - - text: "" - - MouseArea { - anchors.fill: parent - onClicked: listItemClick(); - } -} diff --git a/src/RWADBusAdaptor.cpp b/src/RWADBusAdaptor.cpp deleted file mode 100644 index 6c1504e..0000000 --- a/src/RWADBusAdaptor.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp - * Copyright 2020, 2021 Daniel Teichmann - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -i src/RWADBusAdaptor.h -p :src/RWADBusAdaptor.cpp rwa.xml - * rwa.xml is the xml output of the Introspect D-Bus method - * - * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. - * - * This is an auto-generated file. - * This file may have been hand-edited. Look for HAND-EDIT comments - * before re-generating it. - */ - -#include "src/RWADBusAdaptor.h" -/* - * Implementation of interface class OrgArcticaProjectRWASupportSessionServiceInterface - */ - -OrgArcticaProjectRWASupportSessionServiceInterface::OrgArcticaProjectRWASupportSessionServiceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) - : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) -{ -} - -OrgArcticaProjectRWASupportSessionServiceInterface::~OrgArcticaProjectRWASupportSessionServiceInterface() -{ -} - -/* - * Implementation of interface class OrgFreedesktopDBusIntrospectableInterface - */ - -OrgFreedesktopDBusIntrospectableInterface::OrgFreedesktopDBusIntrospectableInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) - : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) -{ -} - -OrgFreedesktopDBusIntrospectableInterface::~OrgFreedesktopDBusIntrospectableInterface() -{ -} - diff --git a/src/RWADBusAdaptor.h b/src/RWADBusAdaptor.h deleted file mode 100644 index 77f4b6c..0000000 --- a/src/RWADBusAdaptor.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp - * Copyright 2020, 2021 Daniel Teichmann - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -p src/RWADBusAdaptor.h: rwa.xml - * rwa.xml is the xml output of the Introspect D-Bus method - * - * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. - * - * This is an auto-generated file. - * Do not edit! All changes made to it will be lost. - */ - -#ifndef RWADBUSADAPTOR_H -#define RWADBUSADAPTOR_H - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Proxy class for interface org.ArcticaProject.RWASupportSessionService - */ -class OrgArcticaProjectRWASupportSessionServiceInterface: public QDBusAbstractInterface -{ - Q_OBJECT -public: - static inline const char *staticInterfaceName() - { return "org.ArcticaProject.RWASupportSessionService"; } - -public: - OrgArcticaProjectRWASupportSessionServiceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); - - ~OrgArcticaProjectRWASupportSessionServiceInterface(); - -public Q_SLOTS: // METHODS - inline QDBusPendingReply add_web_app_host(const QString &host) - { - QList argumentList; - argumentList << QVariant::fromValue(host); - return asyncCallWithArgumentList(QStringLiteral("add_web_app_host"), argumentList); - } - - inline QDBusPendingReply get_web_app_hosts() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("get_web_app_hosts"), argumentList); - } - - inline QDBusPendingReply refresh_status(int pid) - { - QList argumentList; - argumentList << QVariant::fromValue(pid); - return asyncCallWithArgumentList(QStringLiteral("refresh_status"), argumentList); - } - - inline QDBusPendingReply remove_web_app_host(int host_idx) - { - QList argumentList; - argumentList << QVariant::fromValue(host_idx); - return asyncCallWithArgumentList(QStringLiteral("remove_web_app_host"), argumentList); - } - - inline QDBusPendingReply start(int host_idx) - { - QList argumentList; - argumentList << QVariant::fromValue(host_idx); - return asyncCallWithArgumentList(QStringLiteral("start"), argumentList); - } - - inline QDBusPendingReply status(int pid) - { - QList argumentList; - argumentList << QVariant::fromValue(pid); - return asyncCallWithArgumentList(QStringLiteral("status"), argumentList); - } - - inline QDBusPendingReply stop(int pid) - { - QList argumentList; - argumentList << QVariant::fromValue(pid); - return asyncCallWithArgumentList(QStringLiteral("stop"), argumentList); - } - -Q_SIGNALS: // SIGNALS -}; - -/* - * Proxy class for interface org.freedesktop.DBus.Introspectable - */ -class OrgFreedesktopDBusIntrospectableInterface: public QDBusAbstractInterface -{ - Q_OBJECT -public: - static inline const char *staticInterfaceName() - { return "org.freedesktop.DBus.Introspectable"; } - -public: - OrgFreedesktopDBusIntrospectableInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); - - ~OrgFreedesktopDBusIntrospectableInterface(); - -public Q_SLOTS: // METHODS - inline QDBusPendingReply Introspect() - { - QList argumentList; - return asyncCallWithArgumentList(QStringLiteral("Introspect"), argumentList); - } - -Q_SIGNALS: // SIGNALS -}; - -namespace org { - namespace ArcticaProject { - typedef ::OrgArcticaProjectRWASupportSessionServiceInterface RWASupportSessionService; - } - namespace freedesktop { - namespace DBus { - typedef ::OrgFreedesktopDBusIntrospectableInterface Introspectable; - } - } -} -#endif diff --git a/src/RWAHost.cpp b/src/RWAHost.cpp deleted file mode 100644 index f31dc60..0000000 --- a/src/RWAHost.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp - * Copyright 2021 Daniel Teichmann - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "RWAHost.h" - -RWAHost::RWAHost(QString uuid, QString alias, QString url) { - assert(uuid != ""); - assert(alias != ""); - assert(url != ""); - - /*qDebug() << "Created new RWAHost object.\n\t" - << QString("uuid: '%0'").arg(uuid) << "\n\t" - << QString("alias: '%0'").arg(alias) << "\n\t" - << QString("url: '%0'").arg(url);*/ - - _url = url; - _alias = alias; - _uuid = uuid; -} - -QString RWAHost::uuid() const { - return _uuid; -} - -QString RWAHost::alias() const { - return _alias; -} - -QString RWAHost::url() const { - return _url; -} - -void RWAHost::setUuid(const QString &uuid) { - _uuid = uuid; - emit uuidChanged(uuid); -} - -void RWAHost::setAlias(const QString &alias) { - _alias = alias; - emit aliasChanged(alias); -} - -void RWAHost::setUrl(const QString &url) { - _url = url; - emit urlChanged(url); -} diff --git a/src/RWAHost.h b/src/RWAHost.h deleted file mode 100644 index cd3b1ce..0000000 --- a/src/RWAHost.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp - * Copyright 2021 Daniel Teichmann - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef RWAHOST_H -#define RWAHOST_H - -#include -#include - -class RWAHost : public QObject { - Q_OBJECT - Q_PROPERTY(QString uuid READ uuid WRITE setUuid NOTIFY uuidChanged) - Q_PROPERTY(QString alias READ alias WRITE setAlias NOTIFY aliasChanged) - Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged) - -public: - RWAHost(QString uuid = "", QString alias = "", QString url = ""); - RWAHost(const RWAHost&); - -private: - QString _uuid; - QString _alias; - QString _url; - -signals: - void uuidChanged(QString uuid); - void aliasChanged(QString alias); - void urlChanged(QString url); - -public slots: - QString uuid() const; - QString alias() const; - QString url() const; - - void setUuid(const QString &uuid); - void setAlias(const QString &alias); - void setUrl(const QString &url); - -}; - -#endif // RWAHOST_H diff --git a/src/RWAHostModel.cpp b/src/RWAHostModel.cpp deleted file mode 100644 index 5f62adc..0000000 --- a/src/RWAHostModel.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "RWAHostModel.h" - -RWAHostModel::RWAHostModel(QObject *parent) { - Q_UNUSED(parent) -} - -int RWAHostModel::rowCount(const QModelIndex& parent) const { - Q_UNUSED(parent); - return mDatas.size(); -} - -int RWAHostModel::columnCount(const QModelIndex& parent) const { - Q_UNUSED(parent); - return 1; -} - -QVariant RWAHostModel::data(const QModelIndex &index, int role) const - { - if (!index.isValid()) - return QVariant(); - if ( role == Qt::DisplayRole) { - return mDatas[index.row()]; - } - return QVariant(); -} - -void RWAHostModel::populate() { - beginResetModel(); - mDatas.clear(); - RWAHost *host1 = new RWAHost("uuid-1", "Erster Server", "url1"); - RWAHost *host2 = new RWAHost("uuid-2", "Zweiter Server", "url2"); - RWAHost *host3 = new RWAHost("uuid-3", "Dritter Server", "url3"); - mDatas.append(host1->alias()); - mDatas.append(host2->alias()); - mDatas.append(host3->alias()); - endResetModel(); -} diff --git a/src/RWAHostModel.h b/src/RWAHostModel.h deleted file mode 100644 index 8697df2..0000000 --- a/src/RWAHostModel.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef RWAHOSTMODEL_H -#define RWAHOSTMODEL_H - -#include -#include - -#include "RWAHost.h" - -class RWAHostModel : public QAbstractListModel { - Q_OBJECT - -public: - explicit RWAHostModel(QObject * parent = nullptr); - int rowCount(const QModelIndex& parent = QModelIndex()) const; - int columnCount(const QModelIndex& parent = QModelIndex()) const; - QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; - void populate(); - -private: - QStringList mDatas; -}; - -#endif // RWAHOSTMODEL_H diff --git a/src/Toast.qml b/src/Toast.qml deleted file mode 100644 index 7a18dc8..0000000 --- a/src/Toast.qml +++ /dev/null @@ -1,158 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/remote-support-desktop - * Copyright 2020, 2021 Daniel Teichmann - * Copyright 2020, 2021 Mike Gabriel - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import QtQuick 2.0 -import QtQuick.Controls 2.0 -import QtQuick.Controls.Material 2.3 -import rwa.toast.type 1.0 - -/** - * adapted from StackOverflow: - * http://stackoverflow.com/questions/26879266/make-toast-in-android-by-qml - * GitHub Gist: https://gist.github.com/jonmcclung/bae669101d17b103e94790341301c129 - * Adapted to work with dark/light theming - */ - -/** - * @brief An Android-like timed message text in - * a box that self-destroys when finished if desired - */ -Control { - - /** - * Public - */ - - /** - * @brief Shows this Toast - * - * @param {string} text Text to show - * @param {real} duration Duration to show in milliseconds, defaults to 3000 - * @param {enum} type Type of toast. Available is: - * ToastType.Standard, ToastType.Info, ToastType.Warning - * ToastType.Success, ToastType.Error - */ - function show(text, duration, type) { - message.text = text; - - // checks if parameter was passed - if (typeof duration !== "undefined") { - time = Math.max(duration, 2 * fadeTime); - } else { - time = defaultTime; - } - - if (typeof type !== "undefined" ) { - if (type === ToastType.ToastStandard) { - selectedColor = "#dcdedc"; - } else if (type === ToastType.ToastInfo) { - selectedColor = "#0d5eaf"; - } else if (type === ToastType.ToastSuccess) { - selectedColor = "#0daf36"; - } else if (type === ToastType.ToastWarning) { - selectedColor = "#efef2a"; - } else if (type === ToastType.ToastError) { - selectedColor = "#ed1212"; - } - } else { - selectedColor = "#dcdedc"; - } - - animation.start(); - } - - // whether this Toast will self-destroy when it is finished - property bool selfDestroying: false - - /** - * Private - */ - - id: root - - property color selectedColor: "#dcdedc" - readonly property real defaultTime: 3000 - property real time: defaultTime - readonly property real fadeTime: 300 - - property real margin: 10 - - anchors { - left: parent.left - right: parent.right - margins: margin - } - - height: message.height + margin - - background: Rectangle { - color: (Material.theme == Material.Dark) ? "#212121" : "#dcdedc" - border.color: selectedColor - border.width: 1.5 - radius: margin - } - - opacity: 0 - - Text { - id: message - color: (Material.theme == Material.Dark) ? "#f1f1f1" : "#010101" - wrapMode: Text.Wrap - horizontalAlignment: Text.AlignHCenter - anchors { - top: parent.top - left: parent.left - right: parent.right - margins: margin / 2 - } - } - - SequentialAnimation on opacity { - id: animation - running: false - - - NumberAnimation { - to: .9 - duration: fadeTime - } - - PauseAnimation { - duration: time - 2 * fadeTime - } - - NumberAnimation { - to: 0 - duration: fadeTime - } - - onRunningChanged: { - if (!running && selfDestroying) { - root.destroy(); - } - } - } -} diff --git a/src/ToastManager.qml b/src/ToastManager.qml deleted file mode 100644 index 2f1600f..0000000 --- a/src/ToastManager.qml +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/remote-support-desktop - * Copyright 2020, 2021 Daniel Teichmann - * Copyright 2020, 2021 Mike Gabriel - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import QtQuick 2.0 - -/** - * adapted from StackOverflow: - * http://stackoverflow.com/questions/26879266/make-toast-in-android-by-qml - * GitHub Gist: https://gist.github.com/jonmcclung/bae669101d17b103e94790341301c129 - * @brief Manager that creates Toasts dynamically - */ -ListView { - /** - * Public - */ - - /** - * @brief Shows a Toast - * - * @param {string} text Text to show - * @param {real} duration Duration to show in milliseconds, defaults to 3000 - * @param {enum} type Type of toast. Available is: - * ToastType.Standard, ToastType.Info, ToastType.Warning - * ToastType.Success, ToastType.Error - */ - function show(text, duration, type) { - model.insert(0, {text: text, duration: duration, type: type}); - } - - /** - * Private - */ - - id: root - - z: Infinity - spacing: 5 - anchors.fill: parent - // parent.height * 0.1 = height of blue header rectangle on main - anchors.topMargin: parent.height * 0.1 + 5 - verticalLayoutDirection: ListView.TopToBottom - - interactive: false - - displaced: Transition { - NumberAnimation { - properties: "y" - easing.type: Easing.InOutQuad - } - } - - delegate: Toast { - Component.onCompleted: { - if (typeof duration === "undefined" && typeof type === "undefined") { - show(text, ToastType.ToastStandard); - } else if (typeof duration === "undefined" && - typeof type !== "undefined") { - show(text, type); - } else { - show(text, duration, type); - } - } - } - - model: ListModel {id: model} -} diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index e29c8db..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp - * Copyright 2020, 2021 Daniel Teichmann - * Copyright 2020, 2021 Mike Gabriel - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "DBusAPI.h" -#include "RWADBusAdaptor.cpp" -#include "session.h" -#include "scenes/add_rwahost_wizard/add_rwahost_wizard.h" -#include "scenes/remote_control/remote_control_manager.h" -#include "RWAHostModel.h" -#include "RWAHost.h" - -int main(int argc, char *argv[]) { - qDebug() << "This app was built on: " << __DATE__ << __TIME__; - - // We don't want users to have multiple instances of this app running - QString tmpDirPath = QDir::tempPath() + "/rwa.support.desktopapp"; - QString tmpFilePath = tmpDirPath + "/prevent-multiple-instances.lock"; - QDir tmpDir(tmpDirPath); - if (!tmpDir.exists()) { - // Ensure that the path exists - tmpDir.mkpath("."); - } - QLockFile lockFile(tmpFilePath); - qDebug().noquote() << QString("Checking for a lockfile at: '%0'").arg(tmpFilePath); - - if(!lockFile.tryLock(100)){ - qCritical().noquote() << "You already have this app running.\n" - << "Only one instance is allowed.\n" - << "Closing application now with an error."; - - return 1; - } - - QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QApplication app(argc, argv); - - QQuickStyle::setStyle("Material"); - - QTranslator translator; - qDebug().noquote() << QString("Locales: Loading locale: qrc:/locales/%0") - .arg(QLocale::system().name()); - if(translator.load(":/locales/" + QLocale::system().name())) { - app.installTranslator(&translator); - qDebug().noquote() << "Locales: Loaded: " + QLocale::system().name() + " locale!"; - } else { - qWarning() << "Locales: Unable to load translation!"; - } - - QQmlApplicationEngine engine(&app); - - QScopedPointer dbus_api (new DBusAPI()); - - // Make 'mainqmladaptor' available to QML - QScopedPointer main_gui ( - new MainQMLAdaptor(&app, &engine, dbus_api.data()) - ); - - engine.rootContext()->setContextProperty("mainqmladaptor", main_gui.data()); - - QObject::connect(dbus_api.data(), - SIGNAL(serviceGetWebAppHostsResponse(QJsonDocument*)), - main_gui.data(), - SLOT(get_web_app_hosts_response(QJsonDocument*))); - dbus_api.data()->get_web_app_hosts_request(); - - - engine.load(QUrl(QStringLiteral("qrc:/src/main.qml"))); - if (engine.rootObjects().isEmpty()) - return -1; - - QObject::connect(main_gui.data(), - SIGNAL(minimizeWindow()), - engine.rootObjects().takeFirst(), - SLOT(minimizeWindow())); - - QObject::connect(main_gui.data(), - SIGNAL(showWindow()), - engine.rootObjects().takeFirst(), - SLOT(showWindow())); - - QObject::connect(engine.rootObjects().takeFirst()-> - findChild("sidebar_drawer"), - SIGNAL(rwaHostSelected(QString)), - main_gui.data(), - SLOT(onRwaHostSelected(QString))); - - // Make 'AddRWAHostWizard' available to QML - QScopedPointer wizard ( - new AddRWAHostWizard(&app, - main_gui.data(), - dbus_api.data()) - ); - engine.rootContext()-> - setContextProperty("add_rwahost_wizard", wizard.data()); - - // Make 'remote_control_manager' available to QML - QScopedPointer remote_mngr ( - new RemoteControlManager(&engine, - main_gui.data(), - dbus_api.data()) - ); - engine.rootContext()-> - setContextProperty("remote_control_manager", remote_mngr.data()); - - return app.exec(); -} diff --git a/src/main.qml b/src/main.qml deleted file mode 100644 index a622c18..0000000 --- a/src/main.qml +++ /dev/null @@ -1,418 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/remote-support-desktop - * Copyright 2020, 2021 Daniel Teichmann - * Copyright 2020, 2021 Mike Gabriel - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import QtQuick 2.9 -import QtQuick.Window 2.2 -import QtQuick.Extras 1.4 -import QtQuick.Controls 2.2 -import QtQuick.Controls.Styles 1.4 -import QtQuick.Dialogs 1.2 -import QtQuick.Controls.Material 2.3 -import "scenes" as Scenes - -/*! - The main.qml file contains the window, with its header, sidebar, toast and main_content. - */ - -ApplicationWindow { - readonly property int normal_width: 650 - readonly property int normal_height: 500 - readonly property bool inPortrait: window.width < window.height - - minimumWidth: 400 - minimumHeight: 460 - - width: normal_width - height: normal_height - - id: window - visible: true - title: qsTr("Remote Support for your Desktop") - - onClosing: { - mainqmladaptor.onCloseHandler(); - } - - function minimizeWindow() { - showMinimized(); - console.log("Minimizing window now..."); - } - - function showWindow() { - showNormal(); - console.log("Opening window now..."); - } - - function main_content_pop(item) { - if(item) { - if(item.search(main_content.currentItem.objectName) >= 0) return - } - return main_content.pop(item) - } - - function main_content_push(item) { - if(item) { - if(item.search(main_content.currentItem.objectName) >= 0) return - } - return main_content.push(item) - } - - function main_content_replace(item) { - if(item) { - if(item.search(main_content.currentItem.objectName) >= 0) return - } - return main_content.replace(item) - } - - MessageDialog { - id: message_dialog - objectName: "message_dialog" - title: qsTr("Remote Support for your Desktop") - text: qsTr("You are not supposed to see this message.\nThis is a bug.") - icon: StandardIcon.Critical - } - - ToastManager { - id: toast - - anchors.leftMargin: inPortrait ? 0 : sidebar_drawer.width - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.top: parent.top - } - - Connections { - target: mainqmladaptor - function onShowToastSignal(text, durationMs, type) { - toast.show(text, durationMs, type) - } - } - - Connections { - target: mainqmladaptor - function onShowMessageDialogChanged(show) { - message_dialog.visible = show - } - } - - StackView { - id: main_content - objectName: "main_content" - - anchors.top: top_menu_bar_frame.bottom - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.leftMargin: !inPortrait ? sidebar_drawer.width : 0 - anchors.topMargin: 0 - - // Our Application will start with the following content: - initialItem: "scenes/Scene_placeholder.qml" - - replaceEnter: Transition { - PropertyAnimation { - property: "opacity" - from: 0 - to:1 - duration: 100 - } - } - replaceExit: Transition { - PropertyAnimation { - property: "opacity" - from: 1 - to:0 - duration: 100 - } - } - } - - Connections { - target: mainqmladaptor - function onMessageDialogTextChanged(text) { - message_dialog.text = text - } - } - - Connections { - target: mainqmladaptor - function onMessageDialogTitleChanged(title) { - message_dialog.title = title - } - } - - Connections { - target: mainqmladaptor - function onMessageDialogIconChanged(iconindex) { - message_dialog.icon = iconindex - } - } - - /*! - This is our sidebar (sidemenu) for navigation purposes. - It will collapse if the window gets resized to a portrait format. - Then it can be opened using the now visible button in the header - or by swiping from left to right. - main_content's leftMargin depends on sidebar_drawers's width - We don't want them to overlap on different window heights und widths. - */ - Drawer { - id: sidebar_drawer - objectName: "sidebar_drawer" - - y: top_menu_bar_frame.height - width: !inPortrait ? - Math.min(300, Math.max(200, window.width * 0.333)) : - (window.width * 0.5) - height: window.height - top_menu_bar_frame.height - - modal: inPortrait - interactive: inPortrait - position: inPortrait ? 0 : 1 - dragMargin: 1 - margins: -2 - visible: !inPortrait - - signal rwaHostSelected(string host_uuid) - property bool rwaHostIsSelected: false - - ListView { - id: sidebar_listview - boundsBehavior: Flickable.StopAtBounds - interactive: true - clip: true - anchors.fill: parent - model: mainModel - - header: Rectangle { - height: 50 - width: parent.width - color: Material.background - - ComboBox { - id: server_chooser - objectName: "server_chooser" - - padding: 0 - width: parent.width - height: 56 - y - y: -6 - - model: mainqmladaptor.rwaHostModel - textRole: "alias" - - onCurrentIndexChanged: { - var rwa_host = mainqmladaptor.rwaHostModel - if (rwa_host[currentIndex] !== undefined) { - sidebar_drawer.rwaHostSelected(rwa_host[currentIndex].uuid) - displayText = rwa_host[currentIndex].alias - } - } - - - } - } - - footer: ItemDelegate { - id: footer - text: " " + qsTr("Settings") - width: parent.width - enabled: false - - onClicked: { - var scene_url = "scenes/Scene_placeholder.qml" - header_text.text = qsTr("Settings") - if (inPortrait) sidebar_drawer.close() - - if (scene_url.search(main_content.currentItem.objectName) >= 0) return - main_content.replace(scene_url, StackView.Transition) - } - - MenuSeparator { - parent: footer - width: parent.width - anchors.verticalCenter: parent.top - } - } - - VisualItemModel { - id: mainModel - - ListItem { - text: " " + qsTr("Remote Control") - scene_url: "scenes/remote_control/Scene_remote_control.qml" - onListItemClick: { - header_text.text = qsTr("Allow remote control") - if (inPortrait) sidebar_drawer.close() - - if (scene_url.search(main_content.currentItem.objectName) >= 0) return - main_content.replace(scene_url, StackView.Transition) - } - - // Disabled till a RWAHost object is selected. - enabled: sidebar_drawer.rwaHostIsSelected - } - ListItem { - text: " " + qsTr("Remote View") - scene_url: "scenes/Scene_remote_view.qml" - onListItemClick: { - header_text.text = qsTr("Allow remote view") - if (inPortrait) sidebar_drawer.close() - - if (scene_url.search(main_content.currentItem.objectName) >= 0) return - main_content.replace(scene_url, StackView.Transition) - } - - // Disabled till a RWAHost object is selected. - //enabled: sidebar_drawer.rwaHostIsSelected - - // But remote view is not implemented yet - enabled: false - } - ListItem { - text: " " + qsTr("Add RWA-Server") - scene_url: "scenes/add_rwahost_wizard/Scene_step_1.qml" - onListItemClick: { - header_text.text = qsTr("Server addition wizard") - if (inPortrait) sidebar_drawer.close() - - if (scene_url.search(main_content.currentItem.objectName) >= 0) return - main_content.push(scene_url, StackView.ReplaceTransition) - } - } - } - - ScrollIndicator.vertical: ScrollIndicator { } - } - } - - // Set dark/light theme based on the slider setting - Material.theme: inPortrait ? (theme_portrait.position < 1 ? Material.Light : Material.Dark) - : (theme_landscape.position < 1 ? Material.Light : Material.Dark) - - ToolBar { - id: top_menu_bar_frame - width: parent.width - height: parent.height * 0.10 - - background: Rectangle { - color: parent.Material.background - border.color: parent.Material.background - } - Material.background: "#0d5eaf" - Material.foreground: "#ffffff" - - anchors.margins: 0 - anchors.left: parent.left - anchors.top: parent.top - - Switch { - id: theme_landscape - width: 150 - implicitWidth: 100 - visible: !inPortrait - parent: inPortrait ? sidebar_listview : top_menu_bar_frame - - height: parent.height - anchors.margins: 10 - text: qsTr("Dark theme") - anchors.left: parent.left - anchors.verticalCenterOffset: 0 - anchors.leftMargin: 0 - anchors.verticalCenter: parent.verticalCenter - - /*! - Here is the default setting for dark/light mode - */ - checked: true - - onCheckedChanged: { - theme_portrait.checked = checked - } - } - - Switch { - id: theme_portrait - visible: inPortrait - parent: sidebar_listview - - height: 50 - width: parent.width - - anchors.bottom: parent.bottom - text: qsTr("Dark theme") - - checked: theme_landscape.checked - onCheckedChanged: { - theme_landscape.checked = checked - } - } - - Label { - id: header_text - height: parent.height - color: "white" - text: qsTr("Allow Remote Control") - font.pointSize: 20 - fontSizeMode: Text.Fit - horizontalAlignment: Text.AlignRight - verticalAlignment: Text.AlignVCenter - anchors.left: inPortrait ? burger_button.right : parent.left - anchors.leftMargin: inPortrait ? 5 : theme_landscape.width - anchors.right: parent.right - anchors.rightMargin: 5 - anchors.verticalCenter: parent.verticalCenter - padding: 5 - } - - Button { - id: burger_button - width: 50 - height: parent.height + 10 - visible: inPortrait - - text: "≡" - checkable: false - font.pointSize: 24 - flat: true - anchors.left: parent.left - anchors.leftMargin: 0 - anchors.verticalCenter: parent.verticalCenter - enabled: !sidebar_drawer.opened - - onClicked: { - sidebar_drawer.open() - enabled: false - } - } - } -} - -/*##^## Designer { - D{i:14;anchors_width:650} -} - ##^##*/ diff --git a/src/main_qmladaptor.cpp b/src/main_qmladaptor.cpp deleted file mode 100644 index 688b993..0000000 --- a/src/main_qmladaptor.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp - * Copyright 2020, 2021 Daniel Teichmann - * Copyright 2020, 2021 Mike Gabriel - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "main_qmladaptor.h" - -MainQMLAdaptor::MainQMLAdaptor(QObject *parent, QQmlApplicationEngine* engine, - DBusAPI *dbus_api) : QObject(parent) { - Q_ASSERT(engine != nullptr); - Q_ASSERT(dbus_api != nullptr); - - _engine = engine; - _dbus_api = dbus_api; - _selected_rwa_host = nullptr; - _rwaHostModel = new QList; - - QTimer *timer = new QTimer(this); - connect(timer, &QTimer::timeout, _dbus_api, - QOverload<>::of(&DBusAPI::get_web_app_hosts_request)); - timer->start(10000); - - qmlRegisterUncreatableMetaObject( - Toast::staticMetaObject, // meta object created by Q_NAMESPACE macro - "rwa.toast.type", // import statement (can be any string) - 1, 0, // major and minor version of the import - "ToastType", // name in QML (does not have to match C++ name) - "Error: only enums" // error if someone tries to create a ToastType object - ); - -} - -void MainQMLAdaptor::onRwaHostSelected(QString host_uuid) { - Q_ASSERT(host_uuid != ""); - - RWAHost *_host = nullptr; - for (int i = 0; i < getRWAHostModel().size(); i++) { - QObject *obj = _rwaHostModel->value(i); - RWAHost *host = qobject_cast(obj); - Q_ASSERT(host != nullptr); - - if (host->uuid() == host_uuid) { - _host = host; - } - } - Q_ASSERT(_host != nullptr); - - _selected_rwa_host = _host; - qDebug() << "RWAHost was selected!" << - _selected_rwa_host->uuid() << - "aka" << - _selected_rwa_host->alias(); - - setRWAHostSelected(true); -} - -RWAHost* MainQMLAdaptor::getSelectedRWAHost() { - return _selected_rwa_host; -} - -void MainQMLAdaptor::setRWAHostModel(QList *rwa_hosts) { - _rwaHostModel = rwa_hosts; - emit rwaHostModelChanged(*rwa_hosts); -} - -void MainQMLAdaptor::addRWAHost(RWAHost *rwa_host) { - _rwaHostModel->append(rwa_host); - emit rwaHostModelChanged(*_rwaHostModel); -} - -void MainQMLAdaptor::removeRWAHost(RWAHost *rwa_host) { - _rwaHostModel->removeOne(rwa_host); - emit rwaHostModelChanged(*_rwaHostModel); -} - -QList MainQMLAdaptor::getRWAHostModel() { - return *_rwaHostModel; -} - -void MainQMLAdaptor::setRWAHostSelected(bool value) { - // Find item via 'objectName' - QObject *sidebar_drawer = _engine->rootObjects().takeFirst()-> - findChild("sidebar_drawer"); - if (sidebar_drawer) { - sidebar_drawer->setProperty("rwaHostIsSelected", value); - } else { - qWarning() << "Unable to find 'sidebar_drawer' Item!"; - } - - QObject *server_chooser = _engine->rootObjects().takeFirst()-> - findChild("server_chooser"); - if (server_chooser) { - server_chooser->setProperty("displayText", value ? - server_chooser->property("currentText") : - tr("No RWA host available!")); - server_chooser->setProperty("enabled", value); - } else { - qWarning() << "Unable to find 'server_chooser' Item!"; - } -} - -void MainQMLAdaptor::get_web_app_hosts_response(QJsonDocument *doc) { - // Q_ASSERT lets the program crash immediatly at startup, - // when the session service is not started. - // Don't use Q_ASSERT(doc != nullptr); instead use: - if (doc == nullptr) { - setRWAHostSelected(false); - - showToast(tr("Can't connect to underlying session service!"), - 9800, - Toast::ToastError); - - // Go to the first page on the stack. - main_content_pop(nullptr); - - return; - } - - - bool atLeastOneHostAvailable = false; - - // Get the QJsonObject - QJsonObject jObject = doc->object(); - QVariantMap mainMap = jObject.toVariantMap(); - - // Status of request - QString request_status = mainMap["status"].toString(); - if (request_status == "success") { - // Building host_objects - QJsonArray host_objects = jObject.value("hosts").toArray(); - - QList *all_rwa_hosts = new QList; - foreach (const QJsonValue &host_object, host_objects) { - QString host_uuid = host_object["uuid"].toString(); - QString host_alias = host_object["alias"].toString(); - QString host_url = host_object["url"].toString(); - - if (host_url == "" || host_uuid == "") { - // This two values are required and can't be omitted. - QString reason = tr("A host object in the response of D-Bus service lacks" - " a necessary value. (host_url or host_uuid)"); - qCritical().noquote() << tr("An error occured while adding a new host:") - << reason; - - return; - } - - if (host_alias == "") { - qDebug().noquote() << QString("An alias for the host wasn't delivered " - "so just use '%0' as alias.").arg(host_url); - host_alias = host_url; - } - - - // Now built RWAHost object. - RWAHost *rwa_host = new RWAHost(host_uuid, host_alias, host_url); - all_rwa_hosts->append(rwa_host); - - bool found = false; - for (int i = 0; i < this->_rwaHostModel->size(); i++) { - RWAHost* old_host = qobject_cast(_rwaHostModel->value(i)); - Q_ASSERT(old_host != nullptr); - - if (rwa_host->uuid() == old_host->uuid()) { - found = true; - break; - } - } - - atLeastOneHostAvailable = true; - - if (!found) { - qInfo().noquote() << QString(tr("Successfully added new RWAHost '%0'")) - .arg(rwa_host->alias()); - addRWAHost(rwa_host); - } - } - - for (int i = 0; i < this->_rwaHostModel->size(); i++) { - RWAHost* old_host = qobject_cast(_rwaHostModel->value(i)); - Q_ASSERT(old_host != nullptr); - - bool found = false; - for (RWAHost *host : *all_rwa_hosts) { - if (host->uuid() == old_host->uuid()) { - found = true; - break; - } - } - - if (!found) { - removeRWAHost(old_host); - qInfo().noquote() << QString(tr("Removed RWAHost '%0'")).arg(old_host->alias()); - } - } - } else { - QString reason = tr("An error occured while adding a new host:"); - qCritical().noquote() << reason; - - QString type = mainMap["type"].toString(); - if (type != "") { - reason = QString(tr("The error is not clear. The session service " - "responded with status type '%0'")).arg(type); - qCritical().noquote() << reason; - } else { - reason = QString(tr("The error is not clear. The session service " - "responded with no status type!")); - qCritical().noquote() << reason; - } - - return; - } - - if (!atLeastOneHostAvailable) { - main_content_replace("scenes/Scene_no_server_available.qml"); - } - - setRWAHostSelected(atLeastOneHostAvailable); -} - -void MainQMLAdaptor::main_content_push(QString scene) { - // Find item via 'objectName' - QObject *window = _engine->rootObjects().takeFirst(); - Q_ASSERT(window != nullptr); - - QObject *main_content = _engine->rootObjects().takeFirst()->findChild("main_content"); - Q_ASSERT(main_content != nullptr); - - QVariant to_cast = main_content->property("currentItem"); - QObject *obj = qvariant_cast(to_cast); - if (obj) { - if (!(scene.contains(obj->objectName()))) { - QVariant arg = QVariant::fromValue(scene); - if(!QMetaObject::invokeMethod(window, "main_content_push", Q_ARG(QVariant, arg))) - qDebug() << "Failed to invoke push"; - } - } -} - -void MainQMLAdaptor::main_content_pop(QString scene) { - // Find item via 'objectName' - QObject *window = _engine->rootObjects().takeFirst(); - Q_ASSERT(window != nullptr); - - QObject *main_content = _engine->rootObjects().takeFirst()-> - findChild("main_content"); - Q_ASSERT(main_content != nullptr); - - QVariant to_cast = main_content->property("currentItem"); - QObject *obj = qvariant_cast(to_cast); - if (obj) { - if (!(scene.contains(obj->objectName()))) { - QVariant arg = QVariant::fromValue(scene); - if(!QMetaObject::invokeMethod(window, "main_content_pop", Q_ARG(QVariant, arg))) - qDebug() << "Failed to invoke pop"; - } - } -} - -void MainQMLAdaptor::main_content_replace(QString scene) { - // Find item via 'objectName' - QObject *window = _engine->rootObjects().takeFirst(); - Q_ASSERT(window != nullptr); - - QObject *main_content = _engine->rootObjects().takeFirst()-> - findChild("main_content"); - Q_ASSERT(main_content != nullptr); - - QVariant to_cast = main_content->property("currentItem"); - QObject *obj = qvariant_cast(to_cast); - if (obj) { - QString scene_add_rwahost_wizard = "Scene_step_1"; - if (!(scene.contains(obj->objectName()) || - scene_add_rwahost_wizard.contains(obj->objectName()))) { - QVariant arg = QVariant::fromValue(scene); - if (!QMetaObject::invokeMethod(window, "main_content_replace", - Q_ARG(QVariant, arg))) { - qDebug() << "Failed to invoke replace"; - } - } - } -} - -bool MainQMLAdaptor::openMessageDialog(QString title, QString text, QMessageBox::Icon icon) { - _messageDialogText = text; - _messageDialogTitle = title; - _messageDialogIcon = icon; - _showMessageDialog = true; - emit messageDialogIconChanged(_messageDialogIcon); - emit messageDialogTitleChanged(_messageDialogTitle); - emit messageDialogTextChanged(_messageDialogText); - - emit showMessageDialogChanged(_showMessageDialog); - - qDebug() << "Opening MessageDialog!"; - return true; -} - -QString MainQMLAdaptor::getMessageDialogTitle() { - return _messageDialogTitle; -} - -QString MainQMLAdaptor::getMessageDialogText() { - return _messageDialogText; -} - -QMessageBox::Icon MainQMLAdaptor::getMessageDialogIcon() { - return _messageDialogIcon; -} - -bool MainQMLAdaptor::getShowMessageDialog() { - return _showMessageDialog; -} - -void MainQMLAdaptor::onCloseHandler() { - // Do cleanup things here... - emit onCloseSignal(); -} - -void MainQMLAdaptor::showToast(QString text, uint durationMs, uint type) { - // type is actually Toast::ToastType - emit showToastSignal(text, QString::number(durationMs), type); -} diff --git a/src/main_qmladaptor.h b/src/main_qmladaptor.h deleted file mode 100644 index 70c075b..0000000 --- a/src/main_qmladaptor.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp - * Copyright 2020, 2021 Daniel Teichmann - * Copyright 2020, 2021 Mike Gabriel - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "RWAHost.h" -#include "DBusAPI.h" - -namespace Toast { - Q_NAMESPACE - enum ToastType { - ToastStandard, - ToastInfo, - ToastSuccess, - ToastWarning, - ToastError - }; - Q_ENUM_NS(ToastType) -} - -/*#include -namespace MyNamespace -{ - Q_NAMESPACE // required for meta object creation - enum EnStyle { - STYLE_RADIAL, - STYLE_ENVELOPE, - STYLE_FILLED - }; - Q_ENUM_NS(EnStyle) // register the enum in meta object data -}*/ - -class MainQMLAdaptor : public QObject { - Q_OBJECT - // this makes rwaHostModel available as a QML property - Q_PROPERTY(QList rwaHostModel READ getRWAHostModel NOTIFY rwaHostModelChanged) - // this makes showMessageDialog available as a QML property - Q_PROPERTY(bool showMessageDialog READ getShowMessageDialog NOTIFY showMessageDialogChanged) - // this makes showMessageDialogTitle available as a QML property - Q_PROPERTY(QString _messageDialogTitle READ getMessageDialogTitle NOTIFY messageDialogTitleChanged) - // this makes showMessageDialogText available as a QML property - Q_PROPERTY(QString _messageDialogText READ getMessageDialogText NOTIFY messageDialogTextChanged) - // this makes showMessageDialogIcon available as a QML property - Q_PROPERTY(QMessageBox::Icon _messageDialogIcon READ getMessageDialogIcon NOTIFY messageDialogIconChanged) - - -public: - explicit MainQMLAdaptor(QObject *parent, QQmlApplicationEngine *engine = nullptr, - DBusAPI *dbus_api = nullptr); - - void setRWAHostModel(QList *rwa_hosts); - - void main_content_push(QString); - void main_content_pop(QString); - void main_content_replace(QString); - - bool openMessageDialog(QString title, QString text, QMessageBox::Icon); - QString getMessageDialogTitle(); - QString getMessageDialogText(); - QMessageBox::Icon getMessageDialogIcon(); - bool getShowMessageDialog(); - -signals: - void showMessageDialogChanged(bool show); - void messageDialogTextChanged(QString text); - void messageDialogTitleChanged(QString title); - void messageDialogIconChanged(int iconindex); - - void minimizeWindow(); - void showWindow(); - - void rwaHostModelChanged(QList); - - void onCloseSignal(); - - void showToastSignal(QString text, QString durationMs, int type); - -protected: - DBusAPI *_dbus_api; - QList *_rwaHostModel; - -private: - QQmlApplicationEngine *_engine; - RWAHost *_selected_rwa_host; - - bool _showMessageDialog; - QString _messageDialogTitle; - QString _messageDialogText; - QMessageBox::Icon _messageDialogIcon; - -public slots: - void get_web_app_hosts_response(QJsonDocument *doc); - - void addRWAHost(RWAHost *rwa_host); - void removeRWAHost(RWAHost *rwa_host); - void setRWAHostSelected(bool value); - - // No pointer because QML doesn't - // like this type much with pointer - QList getRWAHostModel(); - - RWAHost *getSelectedRWAHost(); - - void onRwaHostSelected(QString host_uuid); - void onCloseHandler(); - - // arg type is actually Toast::ToastType - void showToast(QString text, - uint durationMs = 3000, - uint type = 0); -}; diff --git a/src/scenes/Scene_no_server_available.qml b/src/scenes/Scene_no_server_available.qml deleted file mode 100644 index 7b99b55..0000000 --- a/src/scenes/Scene_no_server_available.qml +++ /dev/null @@ -1,71 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Window 2.2 -import QtQuick.Extras 1.4 -import QtQuick.Controls 2.2 -import QtQuick.Dialogs 1.2 -import QtQuick.Controls.Material 2.3 - -/*! - * This .qml file is a Scene which can be loaded through for - * example a StackView (main_content in main.qml). - */ - -Item { - id: scene_no_server_available - objectName: "Scene_no_server_available" - - Rectangle { - id: rectangle - anchors.fill: parent - color: Material.background - - Text { - color: Material.foreground - id: title - - text: qsTr("Welcome!") - font.pointSize: 20 - font.bold: true - wrapMode: Text.WordWrap - - horizontalAlignment: Text.AlignLeft - - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - anchors.margins: 15 - } - - Text { - color: Material.foreground - anchors.top: title.bottom - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.margins: 15 - - horizontalAlignment: Text.AlignLeft - wrapMode: Text.WordWrap - /*: 'Add RWA-Server' has to be replaced with the correct translation in file main.qml .*/ - font.pointSize: 13 - text: qsTr("You need to add and select the remote \ -web app server to which you want to connect. \ -You can see a button to the left in the menu \ -which says 'Add RWA-Server'. Follow the steps \ -listed there and you can start your remote \ -support session afterwards using the buttons \ -above 'Add RWA-Server'.") - } - } -} - - - - - - - -/*##^## Designer { - D{i:0;autoSize:true;height:480;width:640} -} - ##^##*/ diff --git a/src/scenes/Scene_placeholder.qml b/src/scenes/Scene_placeholder.qml deleted file mode 100644 index f492e00..0000000 --- a/src/scenes/Scene_placeholder.qml +++ /dev/null @@ -1,56 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Window 2.2 -import QtQuick.Extras 1.4 -import QtQuick.Controls 2.2 -import QtQuick.Dialogs 1.2 -import QtQuick.Controls.Material 2.3 - -/*! - * This .qml file is a Scene which can be loaded through for - * example a StackView (main_content in main.qml). - */ - -Item { - id: scene_placeholder - objectName: "Scene_placeholder" - - Rectangle { - id: rectangle - anchors.fill: parent - color: Material.background - - Text { - color: Material.foreground - id: title - - text: qsTr("This is the placeholder scene!") - font.pointSize: 18 - wrapMode: Text.WordWrap - - font.bold: true - horizontalAlignment: Text.AlignHCenter - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.right: parent.right - anchors.margins: 5 - } - - Text { - color: Material.foreground - anchors.top: title.bottom - anchors.margins: 5 - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - - wrapMode: Text.WordWrap - text: qsTr("The features you expected here are not yet implemented.") - horizontalAlignment: Text.AlignHCenter - } - } -} - -/*##^## Designer { - D{i:0;autoSize:true;height:480;width:640} -} - ##^##*/ diff --git a/src/scenes/Scene_remote_view.qml b/src/scenes/Scene_remote_view.qml deleted file mode 100644 index 436d8aa..0000000 --- a/src/scenes/Scene_remote_view.qml +++ /dev/null @@ -1,371 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Window 2.2 -import QtQuick.Extras 1.4 -import QtQuick.Controls 2.2 -import QtQuick.Dialogs 1.2 -import QtQuick.Controls.Material 2.3 - -/*! - * This .qml file is a Scene which can be loaded through for - * example a StackView (main_content in main.qml). - */ - -Item { - id: scene_remote_view - objectName: "Scene_remote_view" - - Label { - id: dbus_api_status_text - text: "Unknown state of Service" - anchors.leftMargin: 10 + 5 + dbus_api_status_indicator.width - anchors.bottom: parent.bottom - anchors.bottomMargin: 10 - wrapMode: Text.WrapAtWordBoundaryOrAnywhere - verticalAlignment: Text.AlignVCenter - font.pointSize: 11 - fontSizeMode: Text.Fit - objectName: "dbus_api_status_text" - anchors.left: parent.left - - StatusIndicator { - id: dbus_api_status_indicator - width: height - height: parent.height - objectName: "dbus_api_status_indicator" - color: "#73d216" - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.left - anchors.rightMargin: 5 - active: false - } - } - - Label { - id: explain_function_label - text: qsTr("Please tell your remote support partner your access address and your access-PIN to let your partner connect to this computer.") - font.pixelSize: 18 - fontSizeMode: Text.VerticalFit - wrapMode: Text.WordWrap - anchors.left: parent.left - anchors.leftMargin: 10 - anchors.top: parent.top - anchors.topMargin: 10 - anchors.right: parent.right - anchors.rightMargin: 10 - horizontalAlignment: Text.AlignLeft - enabled: false - - color: Material.theme == Material.Light ? "#000000" : "#FFFFFF" - } - - Rectangle { - id: dbus_api_status_line - y: 379 - height: 1 - radius: 1 - anchors.right: parent.right - anchors.rightMargin: 10 - anchors.bottom: dbus_api_status_text.top - anchors.bottomMargin: 10 - opacity: 0.3 - gradient: Gradient { - GradientStop { - position: 0.391 - color: "#ffffff" - } - - GradientStop { - position: 0.975 - color: "#8b8b8b" - } - } - border.width: 1 - border.color: "#00000000" - anchors.left: parent.left - anchors.leftMargin: 10 - } - - Column { - id: column - spacing: 6 - anchors.right: parent.right - anchors.rightMargin: 10 - anchors.left: parent.left - anchors.leftMargin: 10 - anchors.bottom: dbus_api_status_line.top - anchors.bottomMargin: 10 - anchors.top: explain_function_label.bottom - anchors.topMargin: 10 - - Column { - id: url_group - width: parent.width - height: parent.height * 0.25 - spacing: 5 - - Label { - id: your_url_text - height: parent.height/2 - text: qsTr("Remote viewing Address") - font.weight: Font.Bold - font.bold: true - verticalAlignment: Text.AlignBottom - horizontalAlignment: Text.AlignLeft - font.pointSize: 14 - fontSizeMode: Text.Fit - } - - TextEdit { - id: url_text - height: parent.height/2 - text: mainqmladaptor.url - anchors.rightMargin: 10 + copy_url_to_clipboard_button.width - anchors.right: parent.right - wrapMode: Text.WrapAtWordBoundaryOrAnywhere - anchors.leftMargin: 10 - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignLeft - font.pointSize: 15 - - readOnly: true - color: Material.foreground - selectByMouse: true - anchors.left: parent.left - - leftPadding: 5 - Rectangle { - radius: 5 - color: Material.theme == Material.Light ? "#F0F0F0" : "#383838" - height: url_text.height - // whole line + copy-into-clipboard button + some margin - width: url_text.width + copy_url_to_clipboard_button.width + 5 + 5 - x: 0; y: 0 - z: -1 - } - - Button { - id: copy_url_to_clipboard_button - width: copy_url_to_clipboard_image.width + 6 - height: copy_url_to_clipboard_image.height + 6 + 10 - anchors.verticalCenter: parent.verticalCenter - display: AbstractButton.IconOnly - anchors.leftMargin: 5 - anchors.left: url_text.right - highlighted: false - flat: true - - Image { - id: copy_url_to_clipboard_image - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - source: "../../images/into-clipboard.svg" - opacity: 0.65 - } - - onClicked: { - mainqmladaptor.handleCopyToClipboardButtonClick(url_text.text); - toast.show(qsTr("Copied access address into clipboard!"), "1000"); - } - - ToolTip.text: qsTr("Copy the access address into the clipboard") - hoverEnabled: true - - ToolTip.delay: 1000 - ToolTip.timeout: 5000 - ToolTip.visible: hovered - } - } - } - - Column { - id: session_id_group - width: parent.width - height: parent.height * 0.25 - spacing: 5 - - Label { - id: your_session_id_text - height: parent.height/2 - text: qsTr("Session-ID") - font.weight: Font.Bold - font.bold: true - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - font.pointSize: 14 - verticalAlignment: Text.AlignBottom - horizontalAlignment: Text.AlignLeft - fontSizeMode: Text.Fit - } - - TextEdit { - objectName: "session_id_text" - id: session_id_text - height: parent.height/2 - text: mainqmladaptor.session_id - font.letterSpacing: 10 - anchors.rightMargin: 10 + copy_session_id_to_clipboard_button.width - anchors.right: parent.right - font.pointSize: 15 - anchors.left: parent.left - anchors.leftMargin: 10 - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - - leftPadding: 5 - Rectangle { - radius: 5 - color: Material.theme == Material.Light ? "#F0F0F0" : "#383838" - height: url_text.height - // whole line + copy-into-clipboard button + some margin - width: url_text.width + copy_url_to_clipboard_button.width + 5 + 5 - x: 0; y: 0 - z: -1 - } - - readOnly: true - color: Material.foreground - wrapMode: Text.WordWrap - selectByMouse: true - - Button { - id: copy_session_id_to_clipboard_button - width: copy_session_id_to_clipboard_image.width + 6 - height: copy_session_id_to_clipboard_image.height + 6 + 10 - anchors.verticalCenter: parent.verticalCenter - flat: true - display: AbstractButton.IconOnly - anchors.left: session_id_text.right - anchors.leftMargin: 5 - - Image { - id: copy_session_id_to_clipboard_image - anchors.horizontalCenter: parent.horizontalCenter - opacity: 0.65 - anchors.verticalCenter: parent.verticalCenter - source: "../../images/into-clipboard.svg" - fillMode: Image.PreserveAspectFit - } - - onClicked: { - mainqmladaptor.handleCopyToClipboardButtonClick(pin_text.text); - toast.show(qsTr("Copied session-ID into clipboard!"), "1000"); - } - - ToolTip.text: qsTr("Copy the session-ID into the clipboard") - hoverEnabled: true - - ToolTip.delay: 1000 - ToolTip.timeout: 5000 - ToolTip.visible: hovered - } - } - } - - Column { - id: pin_group - width: parent.width - height: parent.height * 0.25 - spacing: 5 - - Label { - id: your_pin_text - height: parent.height/2 - text: qsTr("Access-PIN") - font.weight: Font.Bold - font.bold: true - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - font.pointSize: 14 - verticalAlignment: Text.AlignBottom - horizontalAlignment: Text.AlignLeft - } - - TextEdit { - objectName: "pin_text" - id: pin_text - height: parent.height/2 - text: mainqmladaptor.pin - anchors.rightMargin: 10 + copy_pin_to_clipboard_button.width - anchors.right: parent.right - font.pointSize: 15 - anchors.left: parent.left - anchors.leftMargin: 10 - font.letterSpacing: 10 - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - - leftPadding: 5 - Rectangle { - radius: 5 - color: Material.theme == Material.Light ? "#F0F0F0" : "#383838" - height: url_text.height - // whole line + copy-into-clipboard button + some margin - width: url_text.width + copy_url_to_clipboard_button.width + 5 + 5 - x: 0; y: 0 - z: -1 - } - - readOnly: true - color: Material.foreground - wrapMode: Text.WordWrap - selectByMouse: true - - Button { - id: copy_pin_to_clipboard_button - width: copy_pin_to_clipboard_image.width + 6 - height: copy_pin_to_clipboard_image.height + 6 + 10 - anchors.verticalCenter: parent.verticalCenter - flat: true - display: AbstractButton.IconOnly - anchors.left: pin_text.right - anchors.leftMargin: 5 - - Image { - id: copy_pin_to_clipboard_image - anchors.verticalCenter: parent.verticalCenter - opacity: 0.65 - anchors.horizontalCenter: parent.horizontalCenter - source: "../../images/into-clipboard.svg" - fillMode: Image.PreserveAspectFit - } - - onClicked: { - mainqmladaptor.handleCopyToClipboardButtonClick(pin_text.text); - toast.show(qsTr("Copied PIN into clipboard!"), "1000"); - } - - ToolTip.text: qsTr("Copy the pin into the clipboard") - hoverEnabled: true - - ToolTip.delay: 1000 - ToolTip.timeout: 5000 - ToolTip.visible: hovered - } - } - } - - } - - Button { - id: start_support_button - height: Math.min(50) - objectName: "start_support_button" - text: qsTr("Start remote viewing session") - anchors.rightMargin: column.anchors.leftMargin - anchors.bottom: dbus_api_status_line.top - anchors.bottomMargin: 10 - anchors.right: parent.right - checkable: true - - onClicked: mainqmladaptor.handleConnectButtonClick(checked); - } -} - -/*##^## Designer { - D{i:0;autoSize:true;height:480;width:640} -} - ##^##*/ diff --git a/src/scenes/Scene_settings.qml b/src/scenes/Scene_settings.qml deleted file mode 100644 index e2f89da..0000000 --- a/src/scenes/Scene_settings.qml +++ /dev/null @@ -1,34 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Window 2.2 -import QtQuick.Extras 1.4 -import QtQuick.Controls 2.2 -import QtQuick.Dialogs 1.2 -import QtQuick.Controls.Material 2.3 - -/*! - * This .qml file is a Scene which can be loaded through for - * example a StackView (main_content in main.qml). - */ - -Item { - id: scene_settings - objectName: "Scene_settings" - - Rectangle { - id: rectangle - anchors.fill: parent - color: Material.background - - Text { - color: Material.foreground - text: "Settings tab!" - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - } - } -} - -/*##^## Designer { - D{i:0;autoSize:true;height:480;width:640} -} - ##^##*/ diff --git a/src/scenes/add_rwahost_wizard/Scene_step_1.qml b/src/scenes/add_rwahost_wizard/Scene_step_1.qml deleted file mode 100644 index 873e0fd..0000000 --- a/src/scenes/add_rwahost_wizard/Scene_step_1.qml +++ /dev/null @@ -1,282 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Window 2.2 -import QtQuick.Extras 1.4 -import QtQuick.Controls 2.2 -import QtQuick.Controls.Material 2.3 -import rwa.toast.type 1.0 - -/*! - * This .qml file is a Scene which can be loaded through for - * example a StackView (main_content in main.qml). - */ - -Item { - id: scene_server_wizard_step_1 - objectName: "Scene_step_1" - - Connections { - target: add_rwahost_wizard - function onStep1Success() { - // Go onto the first page of the stack. - main_content_pop(null) - mainqmladaptor.showToast(qsTr("Successfully added remote web app host."), - 5000, - ToastType.ToastSuccess); - } - } - - Connections { - target: add_rwahost_wizard - function onStep1Failed(reason, toast_type) { - mainqmladaptor.showToast(reason, - 5000, - toast_type) - } - } - - Rectangle { - id: rectangle - anchors.fill: parent - color: Material.background - - Button { - id: next_step1_button - text: qsTr("Next Step") - anchors.bottom: parent.bottom - anchors.bottomMargin: 15 - anchors.right: parent.right - anchors.rightMargin: 15 - - onClicked: { - add_rwahost_wizard.processStep1(host_url.text, host_alias.text) - } - } - - /*Text { - color: Material.foreground - id: step_indicator - - text: qsTr("Step 1") - anchors.leftMargin: 15 - anchors.top: parent.top - anchors.topMargin: 15 - font.pointSize: 21 - wrapMode: Text.WordWrap - - font.bold: true - horizontalAlignment: Text.AlignHCenter - anchors.left: parent.left - anchors.margins: 5 - }*/ - - Text { - color: Material.foreground - id: explaining_text - - text: qsTr("Please input the address for the "+ - "remote web app server which you want "+ - "to connect to.\nIf you don't know "+ - "what this means, ask your local "+ - "administrator about it please.\nBefore you can "+ - "start any remote sessions you will have to "+ - "be approved for remote support.") - font.pointSize: 12 - anchors.right: parent.right - anchors.rightMargin: 15 - anchors.leftMargin: 15 - anchors.top: parent.top //step_indicator.bottom - anchors.topMargin: 15 - wrapMode: Text.WordWrap - - anchors.left: parent.left - anchors.margins: 5 - } - - TextField { - id: host_url - selectByMouse: true - placeholderText: qsTr("http://example.com:8000") - - font.pixelSize: 16 - color: Material.foreground - anchors.topMargin: 30 - - padding: 15 - topPadding: 15 - - anchors.top: explaining_text.bottom - anchors.left: parent.left - anchors.leftMargin: 15 - anchors.right: parent.right - anchors.margins: 30 - - MouseArea { - anchors.fill: parent - hoverEnabled: true - onHoveredChanged: { - if (containsMouse) { - host_url_background.state = "hovered" - } else if (!host_url.focus) { - host_url_background.state = "unhovered" - } - } - onClicked: { - host_url.forceActiveFocus(); - } - } - - onFocusChanged: { - host_url_background.state = host_url.focus ? "hovered" : "unhovered" - } - - background: Rectangle { - id: host_url_background - color: Material.background - border.color: Material.foreground - border.width: 1 - radius: 4 - - states: [ - State { - name: "hovered" - PropertyChanges { - target: host_url_background - border.color: "#0178EF" - } - }, - State { - name: "unhovered" - PropertyChanges { - target: host_url_background - border.color: Material.foreground - } - } - ] - transitions: [ - Transition { - from: "*" - to: "*" - PropertyAnimation { - property: "border.color" - duration: 100 - easing.type: Easing.Linear - } - } - ] - - Text { - color: Material.foreground - text: qsTr("RWA host address") - anchors.left: parent.left - anchors.leftMargin: 15 - anchors.verticalCenterOffset: - host_url.height / 2 - anchors.verticalCenter: parent.verticalCenter - leftPadding: 5 - - Rectangle { - color: Material.background - width: parent.width + 5 + 3 - height: parent.height - z: -1 - } - } - } - } - - TextField { - id: host_alias - selectByMouse: true - placeholderText: qsTr("My example host") - - font.pixelSize: 16 - color: Material.foreground - - padding: 15 - topPadding: 15 - - anchors.top: host_url.bottom - anchors.topMargin: 30 - anchors.left: parent.left - anchors.leftMargin: 15 - anchors.right: parent.right - anchors.margins: 30 - - MouseArea { - anchors.fill: parent - hoverEnabled: true - onHoveredChanged: { - if (containsMouse) { - host_alias_background.state = "hovered" - } else if (!host_alias.focus) { - host_alias_background.state = "unhovered" - } - } - onClicked: { - host_alias.forceActiveFocus(); - } - } - - onFocusChanged: { - host_alias_background.state = host_alias.focus ? "hovered" : "unhovered" - } - - background: Rectangle { - id: host_alias_background - color: Material.background - border.color: Material.foreground - border.width: 1 - radius: 4 - - states: [ - State { - name: "hovered" - PropertyChanges { - target: host_alias_background - border.color: "#0178EF" - } - }, - State { - name: "unhovered" - PropertyChanges { - target: host_alias_background - border.color: Material.foreground - } - } - ] - transitions: [ - Transition { - from: "*" - to: "*" - PropertyAnimation { - property: "border.color" - duration: 100 - easing.type: Easing.Linear - } - } - ] - - Text { - color: Material.foreground - text: qsTr("RWA host alias") - anchors.left: parent.left - anchors.leftMargin: 15 - anchors.verticalCenterOffset: - host_alias.height / 2 - anchors.verticalCenter: parent.verticalCenter - leftPadding: 5 - - Rectangle { - color: Material.background - width: parent.width + 5 + 3 - height: parent.height - z: -1 - } - } - } - } - } -} - -/*##^## Designer { - D{i:0;autoSize:true;height:480;width:640}D{i:4;anchors_width:351;anchors_x:279} -} - ##^##*/ diff --git a/src/scenes/add_rwahost_wizard/add_rwahost_wizard.cpp b/src/scenes/add_rwahost_wizard/add_rwahost_wizard.cpp deleted file mode 100644 index 7adbdf9..0000000 --- a/src/scenes/add_rwahost_wizard/add_rwahost_wizard.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp - * Copyright 2021 Daniel Teichmann - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "add_rwahost_wizard.h" -#include "../../RWADBusAdaptor.h" -#include "../../RWAHost.h" - -AddRWAHostWizard::AddRWAHostWizard(QObject *parent, - MainQMLAdaptor *main_gui, DBusAPI *dbus_api) : QObject(parent) { - Q_ASSERT(main_gui != nullptr); - Q_ASSERT(dbus_api != nullptr); - - _dbus_api = dbus_api; - _main_gui = main_gui; - - // _dbus_api --serviceAddWebAppHostResponse-> this.add_web_app_host_response() - QObject::connect(_dbus_api, - SIGNAL(serviceAddWebAppHostResponse(QJsonDocument*)), - this, - SLOT(add_web_app_host_response(QJsonDocument*))); -} - -void AddRWAHostWizard::processStep1(QString host_url, QString host_alias) { - qDebug() << "Processing Step 1 with args: " << host_url << host_alias; - - if(host_alias == "" || host_url == "") { - QString reason = tr("Both textfields can't be empty!"); - emit step1Failed(reason, Toast::ToastType::ToastWarning); - qDebug().noquote() << reason; - return; - } - - return add_server(host_url, host_alias); -} - -void AddRWAHostWizard::processStep2() { - qDebug() << "Processing Step 2 with args: No Args."; - emit step2Failed(tr("The features you expected here are not yet implemented."), Toast::ToastType::ToastWarning); - // Just show placeholder scene now. - emit step2Success(); -} - -void AddRWAHostWizard::add_server(QString host_url, QString host_alias) { - _dbus_api->add_web_app_host_request(host_url, host_alias); -} - -void AddRWAHostWizard::add_web_app_host_response(QJsonDocument *doc) { - // Q_ASSERT lets the program crash immediatly at startup, - // when the session service is not started. - // Don't use Q_ASSERT(doc != nullptr); instead use: - if (doc == nullptr) { - _main_gui->setRWAHostSelected(false); - _main_gui->showToast(tr("Can't connect to underlying session service!"), - 9800, - Toast::ToastType::ToastError); - return; - } - - // Get the QJsonObject - QJsonObject jObject = doc->object(); - QVariantMap mainMap = jObject.toVariantMap(); - - // Status of request - QString request_status = mainMap["status"].toString(); - if (request_status == "success") { - _dbus_api->get_web_app_hosts_request(); - - qInfo() << "Successfully added a new RWAHost."; - emit step1Success(); - } else { - qCritical().noquote() << tr("An error occured while adding a new host!"); - - uint toast_type = Toast::ToastType::ToastStandard; - QString reason = tr("An error occured while adding a new host!"); - QString type = mainMap["type"].toString(); - - if(type == "connection"){ - reason = tr("Couldn't connect to the specified host!"); - toast_type = Toast::ToastType::ToastError; - qCritical().noquote() << reason; - } else if (type == "duplicate") { - reason = tr("The specified host was already added!"); - toast_type = Toast::ToastType::ToastWarning; - qCritical().noquote() << reason; - } else if (type == "invalid_url") { - reason = tr("The specified host address is not valid!"); - toast_type = Toast::ToastType::ToastWarning; - qCritical().noquote() << reason; - } else if (type == "permission_denied") { - reason = tr("The specified host address does not grant access!"); - toast_type = Toast::ToastType::ToastError; - qCritical().noquote() << reason; - } else if (type == "unsupported_server") { - reason = tr("The specified host address is not supported!"); - toast_type = Toast::ToastType::ToastError; - qCritical().noquote() << reason; - } - emit step1Failed(reason, toast_type); - - return; - } -} diff --git a/src/scenes/add_rwahost_wizard/add_rwahost_wizard.h b/src/scenes/add_rwahost_wizard/add_rwahost_wizard.h deleted file mode 100644 index f019be1..0000000 --- a/src/scenes/add_rwahost_wizard/add_rwahost_wizard.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp - * Copyright 2021 Daniel Teichmann - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef ADD_RWAHOST_WIZARD_H -#define ADD_RWAHOST_WIZARD_H - -#include - -#include "../../RWADBusAdaptor.h" -#include "../../DBusAPI.h" -#include "../../main_qmladaptor.h" - -class AddRWAHostWizard : public QObject -{ - Q_OBJECT -public: - explicit AddRWAHostWizard(QObject *parent = nullptr, - MainQMLAdaptor *main_gui = nullptr, - DBusAPI *dbus_api = nullptr); - void add_server(QString host_url, QString host_alias); - -private: - DBusAPI *_dbus_api; - MainQMLAdaptor *_main_gui; - -signals: - void step1Success(); - void step1Failed(QString reason, uint toast_type); - void step2Success(); - void step2Failed(QString reason, uint toast_type); - -public slots: - void processStep1(QString host_url, QString host_alias); - void processStep2(); - - void add_web_app_host_response(QJsonDocument *doc); -}; - -#endif // ADD_SERVER_WIZARD_H diff --git a/src/scenes/remote_control/Scene_remote_control.qml b/src/scenes/remote_control/Scene_remote_control.qml deleted file mode 100644 index dc152ef..0000000 --- a/src/scenes/remote_control/Scene_remote_control.qml +++ /dev/null @@ -1,382 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Window 2.2 -import QtQuick.Extras 1.4 -import QtQuick.Controls 2.2 -import QtQuick.Dialogs 1.2 -import QtQuick.Controls.Material 2.3 - -/*! - * This .qml file is a Scene which can be loaded through for - * example a StackView (main_content in main.qml). - */ - -Item { - id: scene_remote_control - objectName: "Scene_remote_control" - - Label { - id: dbus_api_status_text - text: qsTr("Unknown state of session service.") - anchors.leftMargin: 10 + 5 + dbus_api_status_indicator.width - anchors.bottom: parent.bottom - anchors.bottomMargin: 10 - wrapMode: Text.WordWrap - anchors.rightMargin: 10 - verticalAlignment: Text.AlignVCenter - font.pointSize: 11 - fontSizeMode: Text.Fit - objectName: "dbus_api_status_text" - anchors.left: parent.left - anchors.right: parent.right - - StatusIndicator { - id: dbus_api_status_indicator - width: height - height: 20 - objectName: "dbus_api_status_indicator" - color: "#73d216" - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.left - anchors.rightMargin: 5 - active: false - } - } - - Label { - id: explain_function_label - text: qsTr("Please tell your remote support \ -partner your access address and \ -your access-PIN to let your partner \ -connect to this computer.") - wrapMode: Text.WordWrap - font.pixelSize: 18 - anchors.topMargin: 10 - anchors.leftMargin: 10 - anchors.rightMargin: 10 - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - horizontalAlignment: Text.AlignLeft - - color: Material.theme == Material.Light ? "#000000" : "#FFFFFF" - } - - Rectangle { - id: dbus_api_status_line - height: 1 - radius: 1 - anchors.right: parent.right - anchors.rightMargin: 10 - anchors.bottom: dbus_api_status_text.top - anchors.bottomMargin: 10 - opacity: 0.3 - gradient: Gradient { - GradientStop { - position: 0.391 - color: "#ffffff" - } - - GradientStop { - position: 0.975 - color: "#8b8b8b" - } - } - border.width: 1 - border.color: "#00000000" - anchors.left: parent.left - anchors.leftMargin: 10 - } - - Column { - id: column - spacing: 6 - anchors.right: parent.right - anchors.rightMargin: 10 - anchors.left: parent.left - anchors.leftMargin: 10 - anchors.bottom: dbus_api_status_line.top - anchors.bottomMargin: 10 - anchors.top: explain_function_label.bottom - anchors.topMargin: 10 - - Column { - id: url_group - width: parent.width - height: parent.height * 0.25 - spacing: 5 - - Label { - id: your_url_text - height: parent.height/2 - text: qsTr("Remote Support Address") - font.weight: Font.Bold - font.bold: true - verticalAlignment: Text.AlignBottom - horizontalAlignment: Text.AlignLeft - font.pointSize: 14 - fontSizeMode: Text.Fit - } - - TextEdit { - id: url_text - height: parent.height/2 - text: remote_control_manager.url - anchors.rightMargin: 10 + copy_url_to_clipboard_button.width - anchors.right: parent.right - wrapMode: Text.WrapAtWordBoundaryOrAnywhere - anchors.leftMargin: 10 - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignLeft - font.pointSize: 15 - - readOnly: true - color: Material.foreground - selectByMouse: true - anchors.left: parent.left - - leftPadding: 5 - Rectangle { - radius: 5 - color: Material.theme == Material.Light ? "#F0F0F0" : "#383838" - height: url_text.height - // whole line + copy-into-clipboard button + some margin - width: url_text.width + copy_url_to_clipboard_button.width + 5 + 5 - x: 0; y: 0 - z: -1 - } - - Button { - id: copy_url_to_clipboard_button - width: copy_url_to_clipboard_image.width + 6 - height: copy_url_to_clipboard_image.height + 6 + 10 - anchors.verticalCenter: parent.verticalCenter - display: AbstractButton.IconOnly - anchors.leftMargin: 5 - anchors.left: url_text.right - highlighted: false - flat: true - - Image { - id: copy_url_to_clipboard_image - x: 0 - y: -26 - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - source: "../../../images/into-clipboard.svg" - opacity: 0.65 - } - - onClicked: { - remote_control_manager.handleCopyToClipboardButtonClick(url_text.text); - toast.show(qsTr("Copied access address into clipboard!"), - "5000", - mainqmladaptor.ToastInfo); - } - - ToolTip.text: qsTr("Copy the access address into the clipboard") - hoverEnabled: true - - ToolTip.delay: 600 - ToolTip.timeout: 5000 - ToolTip.visible: hovered - } - } - } - - Column { - id: session_id_group - width: parent.width - height: parent.height * 0.25 - spacing: 5 - - Label { - id: your_session_id_text - height: parent.height/2 - text: qsTr("Session-ID") - font.weight: Font.Bold - font.bold: true - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - font.pointSize: 14 - verticalAlignment: Text.AlignBottom - horizontalAlignment: Text.AlignLeft - fontSizeMode: Text.Fit - } - - TextEdit { - objectName: "session_id_text" - id: session_id_text - height: parent.height/2 - text: remote_control_manager.session_id - font.letterSpacing: 10 - anchors.rightMargin: 10 + copy_session_id_to_clipboard_button.width - anchors.right: parent.right - font.pointSize: 15 - anchors.left: parent.left - anchors.leftMargin: 10 - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - - leftPadding: 5 - Rectangle { - radius: 5 - color: Material.theme == Material.Light ? "#F0F0F0" : "#383838" - height: session_id_text.height - // whole line + copy-into-clipboard button + some margin - width: session_id_text.width + copy_session_id_to_clipboard_button.width + 5 + 5 - x: 0; y: 0 - z: -1 - } - - readOnly: true - color: Material.foreground - wrapMode: Text.WordWrap - selectByMouse: true - - Button { - id: copy_session_id_to_clipboard_button - width: copy_session_id_to_clipboard_image.width + 6 - height: copy_session_id_to_clipboard_image.height + 6 + 10 - anchors.verticalCenter: parent.verticalCenter - flat: true - display: AbstractButton.IconOnly - anchors.left: session_id_text.right - anchors.leftMargin: 5 - - Image { - id: copy_session_id_to_clipboard_image - anchors.horizontalCenter: parent.horizontalCenter - opacity: 0.65 - anchors.verticalCenter: parent.verticalCenter - source: "../../../images/into-clipboard.svg" - fillMode: Image.PreserveAspectFit - } - - onClicked: { - remote_control_manager.handleCopyToClipboardButtonClick(session_id_text.text); - toast.show(qsTr("Copied session-ID into clipboard!"), - "5000", - mainqmladaptor.ToastInfo); - } - - ToolTip.text: qsTr("Copy the session-ID into the clipboard") - hoverEnabled: true - - ToolTip.delay: 600 - ToolTip.timeout: 5000 - ToolTip.visible: hovered - } - } - } - - Column { - id: pin_group - width: parent.width - height: parent.height * 0.25 - spacing: 5 - - Label { - id: your_pin_text - height: parent.height/2 - text: qsTr("Access-PIN") - font.weight: Font.Bold - font.bold: true - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.left: parent.left - anchors.leftMargin: 0 - font.pointSize: 14 - verticalAlignment: Text.AlignBottom - horizontalAlignment: Text.AlignLeft - } - - TextEdit { - objectName: "pin_text" - id: pin_text - height: parent.height/2 - text: remote_control_manager.pin - anchors.rightMargin: 10 + copy_pin_to_clipboard_button.width - anchors.right: parent.right - font.pointSize: 15 - anchors.left: parent.left - anchors.leftMargin: 10 - font.letterSpacing: 10 - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - - leftPadding: 5 - Rectangle { - radius: 5 - color: Material.theme == Material.Light ? "#F0F0F0" : "#383838" - height: url_text.height - // whole line + copy-into-clipboard button + some margin - width: url_text.width + copy_url_to_clipboard_button.width + 5 + 5 - x: 0; y: 0 - z: -1 - } - - readOnly: true - color: Material.foreground - wrapMode: Text.WordWrap - selectByMouse: true - - Button { - id: copy_pin_to_clipboard_button - width: copy_pin_to_clipboard_image.width + 6 - height: copy_pin_to_clipboard_image.height + 6 + 10 - anchors.verticalCenter: parent.verticalCenter - flat: true - display: AbstractButton.IconOnly - anchors.left: pin_text.right - anchors.leftMargin: 5 - - Image { - id: copy_pin_to_clipboard_image - anchors.verticalCenter: parent.verticalCenter - opacity: 0.65 - anchors.horizontalCenter: parent.horizontalCenter - source: "../../../images/into-clipboard.svg" - fillMode: Image.PreserveAspectFit - } - - onClicked: { - remote_control_manager.handleCopyToClipboardButtonClick(pin_text.text); - toast.show(qsTr("Copied PIN into clipboard!"), - "5000", - mainqmladaptor.ToastInfo); - } - - ToolTip.text: qsTr("Copy the pin into the clipboard") - hoverEnabled: true - - ToolTip.delay: 600 - ToolTip.timeout: 5000 - ToolTip.visible: hovered - } - } - } - - } - - Button { - id: start_support_button - height: Math.min(50) - objectName: "start_support_button" - text: checked ? qsTr("Stop remote support session") : qsTr("Start remote support session") - anchors.rightMargin: column.anchors.leftMargin - anchors.bottom: dbus_api_status_line.top - anchors.bottomMargin: 10 - anchors.right: parent.right - checkable: true - - onClicked: remote_control_manager.handleConnectButtonClick(checked); - } -} - -/*##^## -Designer { - D{i:0;autoSize:true;height:480;width:640} -} -##^##*/ diff --git a/src/scenes/remote_control/remote_control_manager.cpp b/src/scenes/remote_control/remote_control_manager.cpp deleted file mode 100644 index b76ea2a..0000000 --- a/src/scenes/remote_control/remote_control_manager.cpp +++ /dev/null @@ -1,511 +0,0 @@ -#include "remote_control_manager.h" - -#ifndef QT_NO_DEBUG -#define CHECK_TRUE(instruction) Q_ASSERT(instruction) -#else -#define CHECK_TRUE(instruction) (instruction) -#endif - -RemoteControlManager::RemoteControlManager(QQmlApplicationEngine *engine, - MainQMLAdaptor *main_gui, - DBusAPI *dbus_api) : QObject() { - Q_ASSERT(dbus_api != nullptr); - Q_ASSERT(main_gui != nullptr); - Q_ASSERT(engine != nullptr); - - _current_session = nullptr; - _sessions = new QSet; - _dbus_api = dbus_api; - _main_gui = main_gui; - _engine = engine; -} - -bool RemoteControlManager::setConnectButtonEnabled(bool enabled) { - // Find item via 'objectName' - QQuickItem *scene_remote_control = _engine->rootObjects().takeFirst()-> - findChild("Scene_remote_control"); - QQuickItem *item = scene_remote_control-> - findChild("start_support_button"); - if (item) { - item->setProperty("enabled", enabled); - if (item->property("checked").toBool()) { - item->setProperty("text", tr("Stop remote support session")); - } else { - item->setProperty("text", tr("Start remote support session")); - } - } else { - qWarning() << "Unable to find 'start_support_button' Item!"; - return false; - } - - return true; -} - -bool RemoteControlManager::setConnectButtonChecked(bool checked) { - // Find item via 'objectName' - QQuickItem *scene_remote_control = _engine->rootObjects().takeFirst()-> - findChild("Scene_remote_control"); - QQuickItem *item = scene_remote_control-> - findChild("start_support_button"); - if (item) { - item->setProperty("checked", checked); - } else { - qWarning() << "Unable to find 'start_support_button' Item!"; - return false; - } - - return true; -} - -bool RemoteControlManager::setStatusIndicatorText(QString status_text) { - // Find item via 'objectName' - QQuickItem *scene_remote_control = _engine->rootObjects().takeFirst()-> - findChild("Scene_remote_control"); - QQuickItem *item = scene_remote_control-> - findChild("dbus_api_status_text"); - if (item) { - item->setProperty("text", status_text); - } else { - qWarning() << "Unable to find 'dbus_api_status_text' Item!"; - return false; - } - - return true; -} - -bool RemoteControlManager::setStatusIndicatorColor(bool active, QColor color) { - // Find item via 'objectName' - QQuickItem *scene_remote_control = _engine->rootObjects().takeFirst()-> - findChild("Scene_remote_control"); - QQuickItem *item = scene_remote_control-> - findChild("dbus_api_status_indicator"); - if (item) { - item->setProperty("active", active); - item->setProperty("color", color); - } else { - qWarning() << "Unable to find 'dbus_api_status_indicator' Item!"; - return false; - } - - return true; -} - -void RemoteControlManager::handleCopyToClipboardButtonClick(QString copy_data) { - QClipboard *clipboard = QApplication::clipboard(); - QString originalText = clipboard->text(); - clipboard->setText(copy_data); - qDebug() << "Copied into clipboard:" << copy_data; -} - -QString RemoteControlManager::getURL() { - if (getCurrentSession() == nullptr) { - return tr("Not available yet"); - } - return getCurrentSession()->getURL(); -} - -QString RemoteControlManager::getPin() { - if (getCurrentSession() == nullptr) { - return "-----"; - } - return getCurrentSession()->getPin(); -} - -QString RemoteControlManager::getSessionID() { - if (getCurrentSession() == nullptr) { - return "-----"; - } - return getCurrentSession()->getSessionID(); -} - -Session* RemoteControlManager::getCurrentSession() { - return _current_session; -} - -void RemoteControlManager::addSession(Session *session) { - _sessions->insert(session); -} - -bool RemoteControlManager::removeSession(Session *session) { - if (getCurrentSession() == session) { - setCurrentSession(nullptr); - } - - bool ok = _sessions->remove(session); - - if (session != nullptr) { - session->disconnect(); - session->deleteLater(); - } - - setConnectButtonChecked(false); - setConnectButtonEnabled(true); - - currentSessionUrlChanged(tr("Not available yet")); - currentSessionPinChanged("-----"); - currentSessionSessionIDChanged("-----"); - - return ok; -} - -void RemoteControlManager::setCurrentSession(Session *session) { - if (session == nullptr) { - qDebug() << "Deselecting currentSession."; - _current_session = nullptr; - - return; - } - - if (_sessions->contains(session)) { - qDebug() << "Set currentSession to new session."; - _current_session = session; - - connectSession(_current_session); - } else { - qDebug() << "Given session was not in _sessions!"; - } -} - -void RemoteControlManager::connectSession(Session *session) { - // session --statusChanged-> this.currentSessionStatusChanged() - CHECK_TRUE(QObject::connect(session, - &Session::statusChanged, - this, - &RemoteControlManager::currentSessionStatusChanged)); - - // session --pinChanged-> this.currentSessionPinChanged() - CHECK_TRUE(QObject::connect(session, - &Session::pinChanged, - this, - &RemoteControlManager::currentSessionPinChanged)); - - // session --urlChanged-> this.currentSessionUrlChanged() - CHECK_TRUE(QObject::connect(session, - &Session::urlChanged, - this, - &RemoteControlManager::currentSessionUrlChanged)); - - // session --sessionIDChanged-> this.currentSessionSessionIDChanged() - CHECK_TRUE(QObject::connect(session, - &Session::sessionIDChanged, - this, - &RemoteControlManager::currentSessionSessionIDChanged)); - - - // session --startSucceeded -> this.currentSessionStartSucceeded() - CHECK_TRUE(QObject::connect(session, - &Session::startSucceeded, - this, - &RemoteControlManager::currentSessionStartSucceeded)); - - // session --startFailed-> this.currentSessionStartFailed() - CHECK_TRUE(QObject::connect(session, - &Session::startFailed, - this, - &RemoteControlManager::currentSessionStartFailed)); - - - // session --stopSucceeded-> this.currentSessionStopSucceeded() - CHECK_TRUE(QObject::connect(session, - &Session::stopSucceeded, - this, - &RemoteControlManager::currentSessionStopSucceeded)); - - // session --stopFailed-> this.currentSessionStopFailed() - CHECK_TRUE(QObject::connect(session, - &Session::stopFailed, - this, - &RemoteControlManager::currentSessionStopFailed)); - - - // session --statusSucceeded-> this.currentSessionStatusSucceeded() - CHECK_TRUE(QObject::connect(session, - &Session::statusSucceeded, - this, - &RemoteControlManager::currentSessionStatusSucceeded)); - - // session --statusFailed-> this.currentSessionStatusFailed() - CHECK_TRUE(QObject::connect(session, - &Session::statusFailed, - this, - &RemoteControlManager::currentSessionStatusFailed)); -} - -void RemoteControlManager::currentSessionStartFailed(QString error_message) { - _main_gui->showToast(error_message, 6000, Toast::ToastType::ToastError); - - // Start failed. No need to stop session, so remove it directly. - removeSession(getCurrentSession()); - - setConnectButtonChecked(false); - setConnectButtonEnabled(true); - - emit _main_gui->showWindow(); -} - -void RemoteControlManager::currentSessionStopFailed(QString error_message) { - _main_gui->showToast(error_message, 6000, Toast::ToastType::ToastError); - - // Stop failed, so don't do anything! The user should try again. - - // Set status indicator to the corresponding error message. - QString translated = translateStatusIndicatorText("stop_session_error"); - setStatusIndicatorText(translated); - - setConnectButtonChecked(true); - setConnectButtonEnabled(true); - - emit _main_gui->showWindow(); -} - -void RemoteControlManager::currentSessionStatusFailed(QString error_message) { - _main_gui->showToast(error_message, 6000, Toast::ToastType::ToastError); - - // Set status indicator to the corresponding error message. - QString translated = translateStatusIndicatorText("status_session_error"); - setStatusIndicatorText(translated); - - setConnectButtonChecked(false); - setConnectButtonEnabled(true); - - currentSessionUrlChanged(tr("Not available yet")); - currentSessionPinChanged("-----"); - currentSessionSessionIDChanged("-----"); - - emit _main_gui->showWindow(); -} - -void RemoteControlManager::currentSessionStartSucceeded() { - Session *current_session = getCurrentSession(); - if (current_session != nullptr) { - _main_gui->showToast( - tr("Session was started on '%0' successfully") - .arg(current_session->getHost()->alias()), - 6000, - Toast::ToastType::ToastSuccess - ); - } else { - qCritical().noquote() << tr("currentSessionStartSucceeded(): " - "Current Session is nullptr!"); - _engine->exit(1); - } - - // Set status indicator to the corresponding error message. - QString translated = translateStatusIndicatorText("start_session_success"); - setStatusIndicatorText(translated); - - setConnectButtonChecked(true); - setConnectButtonEnabled(true); -} - -void RemoteControlManager::currentSessionStopSucceeded() { - qDebug() << "Session stop succeeded: Delete current session object now."; - bool ok = removeSession(getCurrentSession()); - if (!ok) { - qWarning() << tr("Couldn't remove current session out of '_sessions' list."); - } - - _main_gui->showToast(tr("Remote support session was stopped."), - 6000, - Toast::ToastType::ToastSuccess); - - // Set status indicator to the corresponding error message. - QString translated = translateStatusIndicatorText("stop_session_success"); - setStatusIndicatorText(translated); - - setConnectButtonChecked(false); - setConnectButtonEnabled(true); -} - -void RemoteControlManager::currentSessionUnexpectedStop(QString error_message) { - _main_gui->showToast(error_message, 6000, Toast::ToastType::ToastError); - - setConnectButtonChecked(false); - setConnectButtonEnabled(true); - - qDebug() << "Delete current session object now."; - bool ok = removeSession(getCurrentSession()); - if (!ok) { - qWarning() << tr("Couldn't remove current session out of '_sessions' list."); - } -} - -void RemoteControlManager::currentSessionStatusSucceeded() { - // Nothing to do. -} - -void RemoteControlManager::currentSessionStatusChanged(QString new_status_code) { - Session *current_session = getCurrentSession(); - if (current_session == nullptr || !current_session->started) { - qDebug() << "RemoteControlManager::currentSessionStatusChanged(QString): " - "got called even though the session isn't even started."; - return; - } - QString translated = translateStatusIndicatorText(new_status_code); - setStatusIndicatorText(translated); -} - -QString RemoteControlManager::translateStatusIndicatorText(QString status_code) { - QString guiString = tr("Unknown state of service"); - setStatusIndicatorColor(false); - - if (status_code == "dead") { - - /* Session died */ - guiString = tr("Remote Support session was stopped ungracefully"); - - // Red color - setStatusIndicatorColor(true, QColor(255, 0, 0, 127)); - - currentSessionUnexpectedStop(guiString); - - } else if (status_code == "stopped") { - - /* Session was stopped normally somehow other than the users request. - * Remote support partner could have clicked exit for example */ - guiString = tr("Remote Support session was stopped"); - - // Green color - setStatusIndicatorColor(true, QColor(0, 255, 0, 127)); - - currentSessionUnexpectedStop(guiString); - - } else if (status_code == "active") { - - /* Partner is connected */ - guiString = tr("Your partner is connected to the Remote Support session"); - - // Green color - setStatusIndicatorColor(true, QColor(0, 255, 0, 127)); - - } else if (status_code == "start_session_success" || status_code == "running") { - - /* Session successfully started */ - guiString = tr("Remote Support session successfully started! " - "Waiting for your remote support partner to connect."); - - // yellow color (will be green when partner is connected) - setStatusIndicatorColor(true, QColor(255, 255, 0, 127)); - - } else if (status_code == "start_session_error") { - - /* Session couldn't be started */ - guiString = tr("Remote Support session couldn't be started!"); - - // Red color - setStatusIndicatorColor(true, QColor(255, 0, 0, 127)); - - } else if (status_code == "stop_session_success") { - - /* Session was successfully stopped by the users request */ - guiString = tr("Session stopped successfully."); - - // Green color - setStatusIndicatorColor(true, QColor(0, 255, 0, 127)); - - } else if (status_code == "stop_session_error") { - - /* Session couldn't be stopped */ - guiString = tr("Session could not be stopped!") + "\n" + - tr("remote support partner could still be connected!"); - - // Red color - setStatusIndicatorColor(true, QColor(255, 0, 0, 127)); - - } else if (status_code == "status_session_error") { - - /* Session's status couldn't be refreshed */ - guiString = tr("Session status could not be refreshed! " - "Your remote support partner could still be connected!"); - - // Red color - setStatusIndicatorColor(true, QColor(255, 0, 0, 127)); - - } - - qDebug().noquote() << QString("Translating status code '%0' to '%1'") - .arg(status_code) - .arg(guiString); - return guiString; -} - -void RemoteControlManager::currentSessionPinChanged(QString pin) { - emit pinChanged(pin); -} - -void RemoteControlManager::currentSessionUrlChanged(QString url) { - emit urlChanged(url); -} - -void RemoteControlManager::currentSessionSessionIDChanged(QString session_id) { - emit sessionIDChanged(session_id); -} - -void RemoteControlManager::connectToDBusAPI(Session *session) { - // _dbus_api --sessionStartResponse-> this.start_response() - CHECK_TRUE(QObject::connect(_dbus_api, - &DBusAPI::serviceStartResponse, - session, - &Session::start_response)); - - // _dbus_api --serviceStopResponse-> this.stop_response() - CHECK_TRUE(QObject::connect(_dbus_api, - &DBusAPI::serviceStopResponse, - session, - &Session::stop_response, - Qt::DirectConnection)); - - // _dbus_api --sessionStatusResponse-> this.status_response() - CHECK_TRUE(QObject::connect(_dbus_api, - &DBusAPI::serviceStatusResponse, - session, - &Session::status_response)); -} - -void RemoteControlManager::handleConnectButtonClick(bool checked) { - if (checked) { - // Create a Session object and start it. - qDebug() << "Creating and starting a new session object now."; - RWAHost *selected_host = _main_gui->getSelectedRWAHost(); - if (selected_host) { - qInfo() << tr("Creating a new session object."); - Session *new_session = new Session(_dbus_api, selected_host); - - connectToDBusAPI(new_session); - - qDebug() << "Adding session to QSet"; - addSession(new_session); - - qDebug() << "Setting session as current session."; - setCurrentSession(new_session); - - qInfo().noquote() << tr("Starting a remote support session on host '%0' " - "using the new session object.") - .arg(selected_host->uuid()); - new_session->start(); - } else { - qCritical().noquote() << tr("Can't start a remote support session. " - "There is no RWA host is selected!"); - } - - setConnectButtonChecked(false); - setConnectButtonEnabled(false); - } else { - Session *current_session = getCurrentSession(); - if (current_session != nullptr) { - emit current_session->stop(); - } else { - qCritical().noquote() << tr("RemoteControlManager::" - "handleConnectButtonClick(): Current Session " - "is nullptr!"); - setConnectButtonChecked(false); - setConnectButtonEnabled(true); - } - } -} - -/*void RemoteControlManager::onCloseHandler() { - // To cleanup things here - // check current session nullptr - getCurrentSession()->stop(); -}*/ diff --git a/src/scenes/remote_control/remote_control_manager.h b/src/scenes/remote_control/remote_control_manager.h deleted file mode 100644 index 4554724..0000000 --- a/src/scenes/remote_control/remote_control_manager.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef REMOTE_CONTROL_MANAGER_H -#define REMOTE_CONTROL_MANAGER_H - -#include - -#include "../../main_qmladaptor.h" -#include "../../DBusAPI.h" -#include "../../session.h" - -class RemoteControlManager : public QObject { - - Q_OBJECT - // this makes url available as a QML property - Q_PROPERTY(QString url READ getURL NOTIFY urlChanged) - // this makes pin available as a QML property - Q_PROPERTY(QString pin READ getPin NOTIFY pinChanged) - // this makes session_id available as a QML property - Q_PROPERTY(QString session_id READ getSessionID NOTIFY sessionIDChanged) - -public: - explicit RemoteControlManager(QQmlApplicationEngine *engine = nullptr, - MainQMLAdaptor *main_gui = nullptr, - DBusAPI *dbus_api = nullptr); - - bool setConnectButtonEnabled(bool enabled); - bool setConnectButtonChecked(bool checked); - bool setStatusIndicatorColor(bool active, QColor color = QColor(255,255,255)); - - QString translateStatusIndicatorText(QString status_code); - bool setStatusIndicatorText(QString status_text); - -private: - DBusAPI *_dbus_api; - MainQMLAdaptor *_main_gui; - QQmlApplicationEngine *_engine; - Session *_current_session; - QSet *_sessions; - - void connectSession(Session *session); - void connectToDBusAPI(Session *session); - - bool refreshTimerIsRunning; - -signals: - void onConnectButtonClick(bool checked); - void pinChanged(QString pin); - void urlChanged(QString URL); - void sessionIDChanged(QString session_id); - -public slots: - void handleCopyToClipboardButtonClick(QString copy_data); - void handleConnectButtonClick(bool checked); - - void setCurrentSession(Session *session); - void addSession(Session *session); - bool removeSession(Session *session); - - void currentSessionStatusChanged(QString); - void currentSessionPinChanged(QString); - void currentSessionSessionIDChanged(QString); - void currentSessionUrlChanged(QString); - - QString getURL(); - QString getPin(); - QString getSessionID(); - Session* getCurrentSession(); - - void currentSessionStartFailed(QString error_message); - void currentSessionStopFailed(QString error_message); - void currentSessionStatusFailed(QString error_message); - void currentSessionUnexpectedStop(QString error_message); - - void currentSessionStartSucceeded(); - void currentSessionStopSucceeded(); - void currentSessionStatusSucceeded(); -}; - -#endif // REMOTECONTROLMANAGER_H diff --git a/src/session.cpp b/src/session.cpp deleted file mode 100644 index 25a8512..0000000 --- a/src/session.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp - * Copyright 2020, 2021 Daniel Teichmann - * Copyright 2020, 2021 Mike Gabriel - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "session.h" - -Session::Session(DBusAPI *dbus_api, RWAHost *host) : QObject() { - Q_ASSERT(host != nullptr); - Q_ASSERT(dbus_api != nullptr); - - _dbus_api = dbus_api; - _host = host; - - setPin("-----"); - setSessionID("-----"); - setURL(tr("Not available yet")); - setStatus("unknown"); - started = false; -} - -Session::~Session() { - qDebug().noquote() << QString("Session #'%0' on host '%1' will be deconstructed.") - .arg(getSessionID()) - .arg(getHost()->alias()); - stop(); - disconnect(); -} - -void Session::statusTimerEvent() { - qDebug() << "Status timer event triggered"; - - refresh_status(); -} - -bool Session::isSessionAliveOrRunning() { - if (getStatus() == "running" || getStatus() == "active") { - return true; - } else { - return false; - } -} - -RWAHost* Session::getHost() { - return _host; -} - -QString Session::getStatus() { - return _status; -} - -QString Session::getURL() { - return _url; -} - -QString Session::getSessionID() { - return _session_id; -} - -QString Session::getPin() { - return _pin; -} - -void Session::setURL(QString url) { - _url = url; - emit urlChanged(url); -} - -void Session::setSessionID(QString session_id) { - _session_id = session_id; - emit sessionIDChanged(session_id); -} - -void Session::setPin(QString pin) { - _pin = pin; - emit pinChanged(pin); -} - -void Session::setHost(RWAHost *host) { - _host = host; - emit hostChanged(host); -} - -void Session::setStatus(QString status) { - _status = status; - emit statusChanged(status); -} - -void Session::start() { - _dbus_api->start_request(_host); -} - -void Session::start_response(QJsonDocument *doc) { - // Q_ASSERT lets the program crash immediatly after method call - // when the session service is not started. - // Don't use Q_ASSERT(doc != nullptr); instead use: - if (doc == nullptr) { - emit startFailed(tr("Can't connect to underlying session service! " - "Is the session service started?")); - return; - } - - // Get the QJsonObject - QJsonObject jObject = doc->object(); - QVariantMap mainMap = jObject.toVariantMap(); - - // Status of request - QString status = mainMap["status"].toString(); - if (status != "success") { - QString type = mainMap["type"].toString(); - QString error_message = tr("An error occured while creating a new session!"); - - if (type == "multiple") { - // TODO: Ask to stop other session via a message dialog. - error_message = tr("The session service is configured " - "to not support multiple sessions " - "and there is already a session running."); - } else if (type == "connection") { - error_message = tr("Couldn't connect to host '%0'.") - .arg(getHost()->alias()); - } else if (type == "host_not_found") { - error_message = tr("The RWA host '%0' couldn't be found.") - .arg(getHost()->alias()); - } else if (type == "permission_denid") { - error_message = tr("The RWA host '%0' doesn't grant access.") - .arg(getHost()->alias()); - } else if (type == "unsupported_server") { - error_message = tr("The RWA host '%0' is not supported.") - .arg(getHost()->alias()); - } - - setStatus("start_session_error"); - qCritical().noquote() << error_message; - emit startFailed(error_message); - return; - } - - bool ok; - - // URL of remote web app frontend - QString url = mainMap["url"].toString(); - this->setURL(url); - - // PIN - long long pin = mainMap["pin"].toLongLong(&ok); - // Sanity Check - if(ok == false){ - QString error_message = "Unable to parse into longo long out of dbus answer!"; - qCritical().noquote() << error_message; - emit startFailed(error_message); - return; - } - this->setPin(QString::number(pin)); - - // session_id = remote support id from the rwa-server - long long session_id = mainMap["session_id"].toLongLong(); - // Sanity Check - if(ok == false){ - QString error_message = "Unable to parse into long long out of dbus answer!"; - qCritical().noquote() << error_message; - emit startFailed(error_message); - return; - } - this->setSessionID(QString::number(session_id)); - - qDebug() << "Got session_id:" << session_id << - "\nGot url:" << url << - "\nGot pin:" << pin; - - emit pinChanged(QString::number(pin)); - emit urlChanged(url); - emit sessionIDChanged(QString::number(session_id)); - - started = true; - - // Ask status every 1000 millisecond - - QTimer *timer = new QTimer(this); - connect(timer, &QTimer::timeout, this, - QOverload<>::of(&Session::statusTimerEvent)); - timer->start(1000); - - qDebug() << "Successfully started a session."; - this->setStatus("start_session_success"); - - emit startSucceeded(); -} - -void Session::stop() { - if (started) - _dbus_api->stop_request(getHost(), getSessionID()); -} - -void Session::stop_response(QJsonDocument *doc) { - // Q_ASSERT lets the program crash immediatly after method call - // when the session service is not started. - // Don't use Q_ASSERT(doc != nullptr); instead use: - if (doc == nullptr) { - emit stopFailed(tr("Can't connect to underlying session service! " - "Is the session service started?")); - return; - } - - QJsonObject jObject = doc->object(); - QVariantMap mainMap = jObject.toVariantMap(); - - QString new_status = mainMap["status"].toString(); - qDebug() << "stop_response() retrieved json. Status now:" << new_status; - - started = false; - - this->setStatus(new_status); - - emit stopSucceeded(); -} - -void Session::status() { - _dbus_api->status_request(getHost(), this->getSessionID()); -} - -void Session::refresh_status() { - _dbus_api->refresh_status_request(getHost(), this->getSessionID()); -} - -void Session::status_response(QJsonDocument *doc) { - // Q_ASSERT lets the program crash immediatly after method call, - // when the session service is not started. - // Don't use Q_ASSERT(doc != nullptr); instead use: - if (doc == nullptr) { - if (!_emitted_status_error_already) { - emit statusFailed(tr("Can't connect to underlying session service! " - "Is the session service started?")); - - _emitted_status_error_already = true; - } - - return; - } - - _emitted_status_error_already = false; - - QJsonObject jObject = doc->object(); - QVariantMap mainMap = jObject.toVariantMap(); - QString new_status = mainMap["status"].toString(); - qDebug() << "status_response() retrieved json. Status:" << new_status; - - setStatus(new_status); - - emit statusSucceeded(); -} diff --git a/src/session.h b/src/session.h deleted file mode 100644 index e1c924f..0000000 --- a/src/session.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * This file is part of Remote Support Desktop - * https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp - * Copyright 2020, 2021 Daniel Teichmann - * Copyright 2020, 2021 Mike Gabriel - * SPDX-License-Identifier: GPL-2.0-or-later - * - * 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. - * - * 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 General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef SESSION_H -#define SESSION_H - -#include -#include -#include -#include -#include - -#include "RWAHost.h" -#include "DBusAPI.h" - -class Session : public QObject { - Q_OBJECT - -public: - explicit Session(DBusAPI *dbus_api = nullptr, - RWAHost *host = nullptr); - ~Session(); - - QString getStatus(); - QString getURL(); - QString getSessionID(); - QString getPin(); - RWAHost* getHost(); - - void setStatus(QString status); - void setURL(QString url); - void setSessionID(QString session_id); - void setPin(QString pin); - void setHost(RWAHost *host); - - void start(); - void stop(); - void status(); - void refresh_status(); - - bool started; - -private: - void statusTimerEvent(); - - bool _emitted_status_error_already; - QString _status; - RWAHost *_host; - DBusAPI *_dbus_api; - - QString _session_id; - QString _url; - QString _pin; - - bool _minimizedBefore = false; - -signals: - void statusChanged(QString); - void sessionIDChanged(QString); - void urlChanged(QString); - void pinChanged(QString); - void hostChanged(RWAHost*); - - void startFailed(QString error_message); - void stopFailed(QString error_message); - void statusFailed(QString error_message); - - void startSucceeded(); - void stopSucceeded(); - void statusSucceeded(); - -public slots: - // Returns true if a session is somewhat usable (Running, Alive, etc..) - bool isSessionAliveOrRunning(); - - void start_response(QJsonDocument*); - void stop_response(QJsonDocument*); - void status_response(QJsonDocument*); -}; - -#endif // SESSION_H diff --git a/tests/testqstring.cpp b/tests/testqstring.cpp new file mode 100644 index 0000000..20ecf78 --- /dev/null +++ b/tests/testqstring.cpp @@ -0,0 +1,15 @@ +#include + +class TestQString: public QObject { + Q_OBJECT +private slots: + void toUpper(); +}; + +void TestQString::toUpper() { + QString str = "Hello"; + QCOMPARE(str.toUpper(), QString("HELLO")); +} + +QTEST_MAIN(TestQString) +#include "testqstring.moc" diff --git a/tests/tests.pro b/tests/tests.pro new file mode 100644 index 0000000..0f9e09e --- /dev/null +++ b/tests/tests.pro @@ -0,0 +1,4 @@ +QT += testlib + +SOURCES += testqstring.cpp + diff --git a/update_locales.sh b/update_locales.sh deleted file mode 100755 index 8c05ece..0000000 --- a/update_locales.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -# This file is part of Remote Support Desktop -# https://gitlab.das-netzwerkteam.de/RemoteWebApp/rwa.support.desktopapp -# Copyright 2020-2021 Daniel Teichmann -# Copyright 2020-2021 Mike Gabriel -# SPDX-License-Identifier: GPL-2.0-or-later -# -# 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. -# -# 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 General Public License -# along with this program; if not, write to the -# Free Software Foundation, Inc., -# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -lupdate rwa-support-desktopapp.pro -no-obsolete -linguist locales/*.ts -lrelease rwa-support-desktopapp.pro -compress -removeidentical -- cgit v1.2.3