Browse Source

Merge branch 'us51-gui-final-layout-change' into 'develop'

Resolve "US51: GUI final layout change"

Closes #95

See merge request tobias.wach/ccats!101
Wach, Tobias Alexander 4 years ago
parent
commit
c2f2844aed
33 changed files with 926 additions and 753 deletions
  1. 68 0
      gui/Readme.md
  2. 1 0
      gui/include/cmdmanager.h
  3. 1 0
      gui/include/jsonhandler.h
  4. 21 23
      gui/include/qmlhandler.h
  5. 20 1
      gui/src/Forms/Connect/IpPopup.ui.qml
  6. 0 120
      gui/src/Forms/Connect/LoginForm.ui.qml
  7. 312 2
      gui/src/Forms/Connect/LoginSignupPopup.ui.qml
  8. 0 148
      gui/src/Forms/Connect/SignupForm.ui.qml
  9. 0 20
      gui/src/Forms/Help/HelpForm.ui.qml
  10. 40 0
      gui/src/Forms/Log/LogForm.ui.qml
  11. 29 47
      gui/src/Forms/Main/FooterForm.ui.qml
  12. 6 2
      gui/src/Forms/Main/InvalidCliPathPopup.ui.qml
  13. 5 1
      gui/src/Forms/Main/InvalidConfigPopup.ui.qml
  14. 6 2
      gui/src/Forms/Main/NoConfigFoundPopup.ui.qml
  15. 66 32
      gui/src/Forms/Main/main.qml
  16. 0 84
      gui/src/Forms/Messages/MessagesForm.ui.qml
  17. 0 2
      gui/src/Forms/Notifications/NotificationTemplate.ui.qml
  18. 2 3
      gui/src/Forms/Notifications/NotificationsForm.ui.qml
  19. 0 76
      gui/src/Forms/Receiving/ReceivingForm.ui.qml
  20. 0 95
      gui/src/Forms/Sending/SendingForm.ui.qml
  21. 9 10
      gui/src/Forms/ServerFiles/ServerFilesFileTemplate.ui.qml
  22. 6 2
      gui/src/Forms/ServerFiles/ServerFilesFileTemplateDeletePopup.ui.qml
  23. 225 0
      gui/src/Forms/ServerFiles/ServerFilesForm.ui.qml
  24. 9 1
      gui/src/Forms/Settings/DeleteMePopup.ui.qml
  25. 14 19
      gui/src/Forms/Settings/SettingsForm.ui.qml
  26. 6 9
      gui/src/climanager.cpp
  27. 28 14
      gui/src/cmdmanager.cpp
  28. BIN
      gui/src/images/tray-icon.png
  29. 23 3
      gui/src/jsonhandler.cpp
  30. 1 0
      gui/src/main.cpp
  31. 5 13
      gui/src/qml.qrc
  32. 18 22
      gui/src/qmlhandler.cpp
  33. 5 2
      gui/src/qtquickcontrols2.conf

+ 68 - 0
gui/Readme.md

@@ -0,0 +1,68 @@
+# Using the Graphical User Interface (GUI)
+
+The GUI of the Covert Channel Application provides an easy way to interact with a covert channel server. It is using the CLI for this interaction, so a valid CLI executable is required for it to work.
+
+
+## Starting the GUI
+
+The graphical user interface should be started without any additional parameters.
+
+
+## Configuration
+
+The GUI uses a configuration file. This file should be called <i>configGUI.txt</i> and should be located in the same folder where the GUI is executed from. On start, the program will check if a valid configuration file exists and if the specified CLI path is valid.
+
+If no configuration file exists, the program will generate a default file. The user will be notified about this and will be asked to set a path to the CLI.
+
+If the configuration file is not valid, the user will get notified and has the option to either quit the program or to generate the default configuration file. The latter would overwrite the existing one.
+
+### Configuration Values
+
+`Autofill-IP`: Should the default IP automatically be filled in on startup.<br/>
+`Autofill-Username`: Should the default Username automatically be filled in on startup.<br/>
+`CLI-Path`: The absolute path to the command line interface (CLI) file.<br/>
+`Default-IP`: The default IP to be used for the autofill.<br/>
+`Default-Username`: The default Username to be used for the autofill.<br/>
+`Keyfile-Path`: The absolute path to the keyfile to be used for encryption.<br/>
+
+
+## Connecting to a server
+
+On startup, the GUI asks the user for an IP-address to connect to. This address can contain a port (for example `127.0.0.1:1234`). If no port is specified, the default port <i>1234</i> is used. Additionally, the user has the option to set the given IP-address as the default one in the configuration file.
+
+If the connection was successful, the user will be asked to either log in or sign up using the given forms. Additionally, the user has the option to set the given username as the default one in the configuration file.
+
+
+## Layout Overview
+
+The GUI is splitted into 3 parts: The menubar, the main window and the footer.
+
+The menubar on the top gives the user the option to change the server, to quit the application and to show the <i>about</i> page.
+
+The footer shows the user some information about his active connection such as the server status, the IP-address and their username. Additionally, any error that occurs will be shown here for 3 seconds.
+
+The main window contains of the following 4 tabs:
+
+### Server Files
+
+This tab shows the user all the files that are currently on the server, including their size, encryption and status. The user has the option to enqueue/dequeue, download or delete the files.
+
+Downloading a file will download it to the same folder where the GUI is executed from.
+
+At the bottom, the user can select a file to be uploaded to the server. The selection is done with a file dialog.
+
+### Notifications
+
+This tab shows the user all notifications that get sent from the server (for example when a transfer is complete). Every notification can be dismissed. Additionally, notifications will trigger a system notification.
+
+The title of this tab will contain a star (<b>* Notifications</b>) when there is a new notification.
+
+### Settings
+
+This tab shows the user the current settings that are specified in the configuration file. These can be changed and saved to the file. Additionally the user has the option to reset the settings to the default values.
+
+In this tab, the user can also delete his account from the server. This requires the users password.
+
+### Log
+
+This tab shows the user the log.

+ 1 - 0
gui/include/cmdmanager.h

@@ -51,6 +51,7 @@ void handleDequeue(Json::Value root);
 void handleExtendedStatus(Json::Value root);
 void handleKeyfile(Json::Value root);
 void handleClosekey(Json::Value root);
+void handleDisconnect(Json::Value root);
 } // namespace CmdManager
 
 #endif // CMDMANAGER_H

+ 1 - 0
gui/include/jsonhandler.h

@@ -5,6 +5,7 @@
 #include <json/json.h>
 
 namespace JsonHandler {
+void setQmlHandler(QMLHandler *q);
 void parseJSON(std::string buffer);
 } // namespace JsonHandler
 

+ 21 - 23
gui/include/qmlhandler.h

@@ -34,17 +34,16 @@ signals:
 	void invalidConfigPopupOpen();
 	void invalidConfigPopupClose();
 
-	// Sending
-	void sendingSetFileUrlText(QString signalText);
-	void sendingEnableSendButton();
-	void sendingDisableSendButton();
-
-	// Receiving
-	void receivingClearFileList();
-	void receivingListFile(QString fileName, QString fileSize, QString fileDecryptable, bool existsLocally);
-	void receivingUpdateFile(QString fileName, QString fileProgress, bool isQueued);
-	void receivingDisableDownloadButton(QString fileName);
-	void receivingCloseConfirmDeletePopup();
+	// Server Files
+	void serverFilesSetFileUrlText(QString signalText);
+	void serverFilesEnableSendButton();
+	void serverFilesDisableSendButton();
+
+	void serverFilesClearFileList();
+	void serverFilesListFile(QString fileName, QString fileSize, QString fileDecryptable, bool existsLocally);
+	void serverFilesUpdateFile(QString fileName, QString fileProgress, bool isQueued);
+	void serverFilesDisableDownloadButton(QString fileName);
+	void serverFilesCloseConfirmDeletePopup();
 
 	// Messages
 	void message(QString msg);
@@ -86,6 +85,7 @@ signals:
 	// Footer
 	void log(QString logText);
 	void footerSetStatus(QString status);
+	void footerSetError(QString error);
 
 	// Notifications
 	void notification(QString message);
@@ -94,7 +94,10 @@ signals:
 
 	// QML -> C++
 public slots:
-	void onStart();
+	// Main
+	void onStart(bool startWithCli);
+
+	void onSwitchServer();
 
 	// No Config Found Popup
 	void onNoConfigFoundPopupContinueButton(QString cli_path);
@@ -107,15 +110,13 @@ public slots:
 	void onInvalidConfigPopupCreateDefaultButton();
 	void onInvalidConfigPopupQuitButton();
 
-	// Sending
-	void onSendingSelectFileButton(QUrl url);
-	void onSendingSendFileButton();
-	void onSendingClearSelectionButton();
+	// Server Files
+	void onServerFilesSelectFileButton(QUrl url);
+	void onServerFilesSendFileButton();
+	void onServerFilesClearSelectionButton();
 
-	// Receiving
-	void onReceivingListFilesButton();
-	void onReceivingDownloadFileButton(QString fileName);
-	void onReceivingConfirmDeleteFileButton(QString fileName);
+	void onServerFilesDownloadFileButton(QString fileName);
+	void onServerFilesConfirmDeleteFileButton(QString fileName);
 
 	// Messages
 	void onMessagesSendButton(QString msg);
@@ -137,9 +138,6 @@ public slots:
 	// Signup
 	void onSignupRegisterButton(QString username, QString passwordOne, QString passwordTwo, bool saveAsDefault);
 
-	// Footer
-	void onFooterGetStatusButton();
-
 	// Notifications
 	void onDismissNotificationButton(int id);
 

+ 20 - 1
gui/src/Forms/Connect/IpPopup.ui.qml

@@ -13,6 +13,16 @@ Popup {
     closePolicy: Popup.NoAutoClose
     anchors.centerIn: Overlay.overlay
 
+    signal resetOnClose
+
+    onClosed: {
+        resetOnClose()
+    }
+
+    Overlay.modal: Rectangle {
+        color: "#b5c5c5c5"
+    }
+
     Connections {
         target: _qmlHandler
         onIpPopupSetIP: {
@@ -45,7 +55,6 @@ Popup {
         Text {
             Layout.alignment: Qt.AlignCenter
             id: ipPopupText
-            color: "#ffffff"
             text: qsTr("Enter the IP to connect:")
             horizontalAlignment: Text.AlignHCenter
             verticalAlignment: Text.AlignVCenter
@@ -69,6 +78,11 @@ Popup {
             Keys.onEnterPressed: ipPopupConnectButton.activate()
 
             onTextEdited: ipPopupConnectButton.enabled = ipPopupIpInput.acceptableInput
+
+            Connections {
+                target: popup
+                onResetOnClose: ipPopupIpInput.text = ""
+            }
         }
 
         CheckBox {
@@ -88,6 +102,11 @@ Popup {
             font.pixelSize: 20
             wrapMode: Text.WordWrap
             Layout.preferredWidth: parent.width
+
+            Connections {
+                target: popup
+                onResetOnClose: ipPopupStatusText.text = ""
+            }
         }
 
         Button {

+ 0 - 120
gui/src/Forms/Connect/LoginForm.ui.qml

@@ -1,120 +0,0 @@
-import QtQuick 2.12
-import QtQuick.Controls 2.5
-import QtQuick.Layouts 1.3
-
-Page {
-    width: 400
-    height: 400
-    title: ""
-
-    Connections {
-        target: _qmlHandler
-        onLoginSetUsername: {
-            loginUsernameInput.text = username
-        }
-        onLoginSetStatus: {
-            loginStatusText.text = status
-        }
-        onLoginEnableLoginButton: {
-            loginLoginButton.enabled = true
-        }
-        onLoginDisableLoginButton: {
-            loginLoginButton.enabled = false
-        }
-        onLoginSignupCheckSaveCheckbox: {
-            loginSetDefaultCheckbox.checked = true
-        }
-    }
-
-    ColumnLayout {
-        anchors.fill: parent
-
-        Text {
-            Layout.alignment: Qt.AlignCenter
-            id: loginTitle
-            color: "#ffffff"
-            text: qsTr("Login")
-            horizontalAlignment: Text.AlignHCenter
-            verticalAlignment: Text.AlignVCenter
-            font.pixelSize: 20
-        }
-
-        TextField {
-            Layout.alignment: Qt.AlignCenter
-            id: loginUsernameInput
-            selectByMouse: true
-            focus: true
-            text: qsTr("")
-            placeholderText: "Username"
-            horizontalAlignment: Text.AlignHCenter
-            // @disable-check M222
-            Keys.onReturnPressed: loginLoginButton.activate()
-            // @disable-check M222
-            Keys.onEnterPressed: loginLoginButton.activate()
-
-            onTextEdited: loginLoginButton.enabled = (loginUsernameInput.text != ""
-                                                      && loginPasswordInput.text != "")
-        }
-
-        TextField {
-            Layout.alignment: Qt.AlignCenter
-            id: loginPasswordInput
-            selectByMouse: true
-            text: qsTr("")
-            placeholderText: "Password"
-            horizontalAlignment: Text.AlignHCenter
-            // @disable-check M222
-            Keys.onReturnPressed: loginLoginButton.activate()
-            // @disable-check M222
-            Keys.onEnterPressed: loginLoginButton.activate()
-            echoMode: TextInput.Password
-
-            onTextEdited: loginLoginButton.enabled = (loginUsernameInput.text != ""
-                                                      && loginPasswordInput.text != "")
-        }
-
-        CheckBox {
-            id: loginSetDefaultCheckbox
-            Layout.alignment: Qt.AlignCenter
-            checked: false
-            text: "Save as default user"
-        }
-
-        Text {
-            id: loginStatusText
-            color: "#df3f3f"
-            text: qsTr("")
-            wrapMode: Text.WordWrap
-            Layout.preferredWidth: parent.width
-            horizontalAlignment: Text.AlignHCenter
-            verticalAlignment: Text.AlignVCenter
-            Layout.alignment: Qt.AlignCenter
-            font.pixelSize: 20
-        }
-
-        Button {
-            Layout.alignment: Qt.AlignCenter
-            id: loginLoginButton
-            text: qsTr("Login")
-            enabled: false
-            font.pointSize: 16
-            // @disable-check M223
-            onClicked: {
-                // @disable-check M222
-                loginLoginButton.activate()
-            }
-
-            // @disable-check M222
-            function activate() {
-                // @disable-check M223
-                if (loginLoginButton.enabled) {
-                    // @disable-check M222
-                    _qmlHandler.onLoginLoginButton(
-                                loginUsernameInput.text,
-                                loginPasswordInput.text,
-                                loginSetDefaultCheckbox.checked)
-                }
-            }
-        }
-    }
-}

+ 312 - 2
gui/src/Forms/Connect/LoginSignupPopup.ui.qml

@@ -13,6 +13,16 @@ Popup {
     closePolicy: Popup.NoAutoClose
     anchors.centerIn: Overlay.overlay
 
+    signal resetOnClose
+
+    onClosed: {
+        resetOnClose()
+    }
+
+    Overlay.modal: Rectangle {
+        color: "#b5c5c5c5"
+    }
+
     Connections {
         target: _qmlHandler
         onLoginSignupPopupClose: {
@@ -21,6 +31,33 @@ Popup {
         onLoginSignupPopupOpen: {
             popup.open()
         }
+
+        onLoginSetUsername: {
+            loginUsernameInput.text = username
+        }
+        onLoginSetStatus: {
+            loginStatusText.text = status
+        }
+        onLoginEnableLoginButton: {
+            loginLoginButton.enabled = true
+        }
+        onLoginDisableLoginButton: {
+            loginLoginButton.enabled = false
+        }
+        onLoginSignupCheckSaveCheckbox: {
+            loginSetDefaultCheckbox.checked = true
+            signupSetDefaultCheckbox.checked = true
+        }
+
+        onSignupSetStatus: {
+            signupStatusText.text = status
+        }
+        onSignupEnableRegisterButton: {
+            signupRegisterButton.enabled = true
+        }
+        onSignupDisableRegisterButton: {
+            signupRegisterButton.enabled = false
+        }
     }
 
     Page {
@@ -46,10 +83,283 @@ Popup {
             currentIndex: header.currentIndex
             clip: true
 
-            LoginForm {
+            // Login
+            Page {
+                width: 400
+                height: 400
+                title: ""
+
+                ColumnLayout {
+                    anchors.fill: parent
+
+                    Text {
+                        Layout.alignment: Qt.AlignCenter
+                        id: loginTitle
+
+                        text: qsTr("Login")
+                        horizontalAlignment: Text.AlignHCenter
+                        verticalAlignment: Text.AlignVCenter
+                        font.pixelSize: 20
+                    }
+
+                    TextField {
+                        Layout.alignment: Qt.AlignCenter
+                        id: loginUsernameInput
+                        selectByMouse: true
+                        focus: true
+                        text: qsTr("")
+                        placeholderText: "Username"
+                        horizontalAlignment: Text.AlignHCenter
+                        // @disable-check M222
+                        Keys.onReturnPressed: loginLoginButton.activate()
+                        // @disable-check M222
+                        Keys.onEnterPressed: loginLoginButton.activate()
+
+                        onTextEdited: loginLoginButton.enabled
+                                      = (loginUsernameInput.text != ""
+                                         && loginPasswordInput.text != "")
+
+                        Connections {
+                            target: popup
+                            onResetOnClose: loginUsernameInput.text = ""
+                        }
+                    }
+
+                    TextField {
+                        Layout.alignment: Qt.AlignCenter
+                        id: loginPasswordInput
+                        selectByMouse: true
+                        text: qsTr("")
+                        placeholderText: "Password"
+                        horizontalAlignment: Text.AlignHCenter
+                        // @disable-check M222
+                        Keys.onReturnPressed: loginLoginButton.activate()
+                        // @disable-check M222
+                        Keys.onEnterPressed: loginLoginButton.activate()
+                        echoMode: TextInput.Password
+
+                        onTextEdited: loginLoginButton.enabled
+                                      = (loginUsernameInput.text != ""
+                                         && loginPasswordInput.text != "")
+
+                        Connections {
+                            target: popup
+                            onResetOnClose: loginPasswordInput.text = ""
+                        }
+                    }
+
+                    CheckBox {
+                        id: loginSetDefaultCheckbox
+                        Layout.alignment: Qt.AlignCenter
+                        checked: false
+                        text: "Save as default user"
+
+                        Connections {
+                            target: popup
+                            onResetOnClose: loginSetDefaultCheckbox.checked = false
+                        }
+                    }
+
+                    Text {
+                        id: loginStatusText
+                        color: "#df3f3f"
+                        text: qsTr("")
+                        wrapMode: Text.WordWrap
+                        Layout.preferredWidth: parent.width
+                        horizontalAlignment: Text.AlignHCenter
+                        verticalAlignment: Text.AlignVCenter
+                        Layout.alignment: Qt.AlignCenter
+                        font.pixelSize: 20
+
+                        Connections {
+                            target: popup
+                            onResetOnClose: loginStatusText.text = ""
+                        }
+                    }
+
+                    Button {
+                        Layout.alignment: Qt.AlignCenter
+                        id: loginLoginButton
+                        text: qsTr("Login")
+                        enabled: false
+                        font.pointSize: 16
+                        // @disable-check M223
+                        onClicked: {
+                            // @disable-check M222
+                            loginLoginButton.activate()
+                        }
+
+                        // @disable-check M222
+                        function activate() {
+                            // @disable-check M223
+                            if (loginLoginButton.enabled) {
+                                // @disable-check M222
+                                _qmlHandler.onLoginLoginButton(
+                                            loginUsernameInput.text,
+                                            loginPasswordInput.text,
+                                            loginSetDefaultCheckbox.checked)
+                            }
+                        }
+                    }
+                }
             }
 
-            SignupForm {
+            // Signup
+            Page {
+                width: 400
+                height: 400
+
+                ColumnLayout {
+                    anchors.fill: parent
+
+                    Text {
+                        Layout.alignment: Qt.AlignCenter
+                        id: signupTitle
+
+                        text: qsTr("Signup")
+                        horizontalAlignment: Text.AlignHCenter
+                        verticalAlignment: Text.AlignVCenter
+                        font.pixelSize: 20
+                    }
+
+                    TextField {
+                        Layout.alignment: Qt.AlignCenter
+                        id: signupUsernameInput
+                        selectByMouse: true
+                        focus: true
+                        text: qsTr("")
+                        placeholderText: "Username"
+                        horizontalAlignment: Text.AlignHCenter
+                        // @disable-check M222
+                        Keys.onReturnPressed: signupRegisterButton.activate()
+                        // @disable-check M222
+                        Keys.onEnterPressed: signupRegisterButton.activate()
+
+                        onTextEdited: {
+                            signupStatusText.text = ""
+                            signupRegisterButton.enabled
+                                    = (signupUsernameInput.text != ""
+                                       && signupPasswordOneInput.text != ""
+                                       && signupPasswordTwoInput.text != "")
+                        }
+
+                        Connections {
+                            target: popup
+                            onResetOnClose: signupUsernameInput.text = ""
+                        }
+                    }
+
+                    TextField {
+                        Layout.alignment: Qt.AlignCenter
+                        id: signupPasswordOneInput
+                        selectByMouse: true
+                        focus: true
+                        text: qsTr("")
+                        placeholderText: "Password"
+                        horizontalAlignment: Text.AlignHCenter
+                        // @disable-check M222
+                        Keys.onReturnPressed: signupRegisterButton.activate()
+                        // @disable-check M222
+                        Keys.onEnterPressed: signupRegisterButton.activate()
+                        echoMode: TextInput.Password
+
+                        onTextEdited: {
+                            signupStatusText.text = ""
+                            signupRegisterButton.enabled
+                                    = (signupUsernameInput.text != ""
+                                       && signupPasswordOneInput.text != ""
+                                       && signupPasswordTwoInput.text != "")
+                        }
+
+                        Connections {
+                            target: popup
+                            onResetOnClose: signupPasswordOneInput.text = ""
+                        }
+                    }
+
+                    TextField {
+                        Layout.alignment: Qt.AlignCenter
+                        id: signupPasswordTwoInput
+                        selectByMouse: true
+                        focus: true
+                        text: qsTr("")
+                        placeholderText: "Repeat Passw."
+                        horizontalAlignment: Text.AlignHCenter
+                        // @disable-check M222
+                        Keys.onReturnPressed: signupRegisterButton.activate()
+                        // @disable-check M222
+                        Keys.onEnterPressed: signupRegisterButton.activate()
+                        echoMode: TextInput.Password
+
+                        onTextEdited: {
+                            signupStatusText.text = ""
+                            signupRegisterButton.enabled
+                                    = (signupUsernameInput.text != ""
+                                       && signupPasswordOneInput.text != ""
+                                       && signupPasswordTwoInput.text != "")
+                        }
+
+                        Connections {
+                            target: popup
+                            onResetOnClose: signupPasswordTwoInput.text = ""
+                        }
+                    }
+
+                    CheckBox {
+                        id: signupSetDefaultCheckbox
+                        Layout.alignment: Qt.AlignCenter
+                        checked: false
+                        text: "Save as default user"
+
+                        Connections {
+                            target: popup
+                            onResetOnClose: signupSetDefaultCheckbox.checked = false
+                        }
+                    }
+
+                    Text {
+                        id: signupStatusText
+                        color: "#df3f3f"
+                        text: qsTr("")
+                        horizontalAlignment: Text.AlignHCenter
+                        verticalAlignment: Text.AlignVCenter
+                        Layout.alignment: Qt.AlignCenter
+                        wrapMode: Text.WordWrap
+                        Layout.preferredWidth: parent.width
+                        font.pixelSize: 20
+
+                        Connections {
+                            target: popup
+                            onResetOnClose: signupStatusText.text = ""
+                        }
+                    }
+
+                    Button {
+                        Layout.alignment: Qt.AlignCenter
+                        id: signupRegisterButton
+                        text: qsTr("Register")
+                        enabled: false
+                        font.pointSize: 16
+                        // @disable-check M223
+                        onClicked: {
+                            // @disable-check M222
+                            signupRegisterButton.activate()
+                        }
+
+                        // @disable-check M222
+                        function activate() {
+                            // @disable-check M223
+                            if (signupRegisterButton.enabled) {
+                                // @disable-check M222
+                                _qmlHandler.onSignupRegisterButton(
+                                            signupUsernameInput.text,
+                                            signupPasswordOneInput.text,
+                                            signupPasswordTwoInput.text,
+                                            signupSetDefaultCheckbox.checked)
+                            }
+                        }
+                    }
+                }
             }
         }
     }

+ 0 - 148
gui/src/Forms/Connect/SignupForm.ui.qml

@@ -1,148 +0,0 @@
-import QtQuick 2.12
-import QtQuick.Controls 2.5
-import QtQuick.Layouts 1.3
-
-Page {
-    width: 400
-    height: 400
-
-    Connections {
-        target: _qmlHandler
-        onSignupSetStatus: {
-            signupStatusText.text = status
-        }
-        onSignupEnableRegisterButton: {
-            signupRegisterButton.enabled = true
-        }
-        onSignupDisableRegisterButton: {
-            signupRegisterButton.enabled = false
-        }
-        onLoginSignupCheckSaveCheckbox: {
-            signupSetDefaultCheckbox.checked = true
-        }
-    }
-
-    ColumnLayout {
-        anchors.fill: parent
-
-        Text {
-            Layout.alignment: Qt.AlignCenter
-            id: signupTitle
-            color: "#ffffff"
-            text: qsTr("Signup")
-            horizontalAlignment: Text.AlignHCenter
-            verticalAlignment: Text.AlignVCenter
-            font.pixelSize: 20
-        }
-
-        TextField {
-            Layout.alignment: Qt.AlignCenter
-            id: signupUsernameInput
-            selectByMouse: true
-            focus: true
-            text: qsTr("")
-            placeholderText: "Username"
-            horizontalAlignment: Text.AlignHCenter
-            // @disable-check M222
-            Keys.onReturnPressed: signupRegisterButton.activate()
-            // @disable-check M222
-            Keys.onEnterPressed: signupRegisterButton.activate()
-
-            onTextEdited: {
-                signupStatusText.text = ""
-                signupRegisterButton.enabled = (signupUsernameInput.text != ""
-                                                && signupPasswordOneInput.text != ""
-                                                && signupPasswordTwoInput.text != "")
-            }
-        }
-
-        TextField {
-            Layout.alignment: Qt.AlignCenter
-            id: signupPasswordOneInput
-            selectByMouse: true
-            focus: true
-            text: qsTr("")
-            placeholderText: "Password"
-            horizontalAlignment: Text.AlignHCenter
-            // @disable-check M222
-            Keys.onReturnPressed: signupRegisterButton.activate()
-            // @disable-check M222
-            Keys.onEnterPressed: signupRegisterButton.activate()
-            echoMode: TextInput.Password
-
-            onTextEdited: {
-                signupStatusText.text = ""
-                signupRegisterButton.enabled = (signupUsernameInput.text != ""
-                                                && signupPasswordOneInput.text != ""
-                                                && signupPasswordTwoInput.text != "")
-            }
-        }
-
-        TextField {
-            Layout.alignment: Qt.AlignCenter
-            id: signupPasswordTwoInput
-            selectByMouse: true
-            focus: true
-            text: qsTr("")
-            placeholderText: "Repeat Passw."
-            horizontalAlignment: Text.AlignHCenter
-            // @disable-check M222
-            Keys.onReturnPressed: signupRegisterButton.activate()
-            // @disable-check M222
-            Keys.onEnterPressed: signupRegisterButton.activate()
-            echoMode: TextInput.Password
-
-            onTextEdited: {
-                signupStatusText.text = ""
-                signupRegisterButton.enabled = (signupUsernameInput.text != ""
-                                                && signupPasswordOneInput.text != ""
-                                                && signupPasswordTwoInput.text != "")
-            }
-        }
-
-        CheckBox {
-            id: signupSetDefaultCheckbox
-            Layout.alignment: Qt.AlignCenter
-            checked: false
-            text: "Save as default user"
-        }
-
-        Text {
-            id: signupStatusText
-            color: "#df3f3f"
-            text: qsTr("")
-            horizontalAlignment: Text.AlignHCenter
-            verticalAlignment: Text.AlignVCenter
-            Layout.alignment: Qt.AlignCenter
-            wrapMode: Text.WordWrap
-            Layout.preferredWidth: parent.width
-            font.pixelSize: 20
-        }
-
-        Button {
-            Layout.alignment: Qt.AlignCenter
-            id: signupRegisterButton
-            text: qsTr("Register")
-            enabled: false
-            font.pointSize: 16
-            // @disable-check M223
-            onClicked: {
-                // @disable-check M222
-                signupRegisterButton.activate()
-            }
-
-            // @disable-check M222
-            function activate() {
-                // @disable-check M223
-                if (signupRegisterButton.enabled) {
-                    // @disable-check M222
-                    _qmlHandler.onSignupRegisterButton(
-                                signupUsernameInput.text,
-                                signupPasswordOneInput.text,
-                                signupPasswordTwoInput.text,
-                                signupSetDefaultCheckbox.checked)
-                }
-            }
-        }
-    }
-}

+ 0 - 20
gui/src/Forms/Help/HelpForm.ui.qml

@@ -1,20 +0,0 @@
-import QtQuick 2.12
-import QtQuick.Controls 2.5
-
-Page {
-    width: 1280
-    height: 470
-
-    Text {
-        id: helpPlaceholder
-        x: 220
-        y: 135
-        width: 840
-        height: 200
-        color: "#ffffff"
-        text: qsTr("Tons of useful information goes here")
-        horizontalAlignment: Text.AlignHCenter
-        verticalAlignment: Text.AlignVCenter
-        font.pixelSize: 40
-    }
-}

+ 40 - 0
gui/src/Forms/Log/LogForm.ui.qml

@@ -0,0 +1,40 @@
+import QtQuick 2.4
+import QtQuick.Controls 2.4
+import QtQuick.Layouts 1.3
+
+Page {
+    width: 1280
+    height: 570
+    id: logForm
+
+    font.capitalization: Font.MixedCase
+
+    Connections {
+        target: _qmlHandler
+        onLog: {
+            log.append(new Date().toLocaleTimeString(Qt.locale("C"),
+                                                     "[hh:mm:ss]\n") + logText)
+            logFlickable.contentY = log.height - logFlickable.height
+        }
+    }
+
+    Flickable {
+        anchors.fill: parent
+        id: logFlickable
+        flickableDirection: Flickable.VerticalFlick
+        Layout.preferredHeight: 170
+        Layout.preferredWidth: parent.width
+
+        TextArea.flickable: TextArea {
+            selectByMouse: true
+            id: log
+            readOnly: true
+            wrapMode: TextArea.Wrap
+            text: qsTr("")
+            font.pointSize: 15
+        }
+
+        ScrollBar.vertical: ScrollBar {
+        }
+    }
+}

+ 29 - 47
gui/src/Forms/Main/FooterForm.ui.qml

@@ -4,75 +4,57 @@ import QtQuick.Layouts 1.3
 
 Page {
     width: 1280
-    height: 200
+    height: 70
 
     font.capitalization: Font.MixedCase
 
     Connections {
         target: _qmlHandler
-        onLog: {
-            footerLog.append(new Date().toLocaleTimeString(
-                                 Qt.locale("C"), "[hh:mm:ss]\n") + logText)
-            footerFlickable.contentY = footerLog.height - footerFlickable.height
-        }
-
         onFooterSetStatus: {
             footerStatusText.text = "Status: " + status
         }
+
+        onFooterSetError: {
+            footerErrorText.text = "Error: " + error
+            timer.start()
+        }
     }
 
     Rectangle {
         anchors.fill: parent
-        color: "#404040"
+        color: "#c4c4c4"
 
         ColumnLayout {
+            spacing: 3
             anchors.fill: parent
 
-            RowLayout {
-                Layout.preferredHeight: 30
+            Text {
+                id: footerStatusText
                 Layout.preferredWidth: parent.width
 
-                Text {
-                    id: footerStatusText
-                    Layout.preferredHeight: parent.height
-                    Layout.preferredWidth: 1000
-                    color: "#ffffff"
-                    text: qsTr("")
-                    font.pixelSize: 23
-                }
-
-                Button {
-                    id: footerGetStatusButton
-                    Layout.preferredHeight: 30
-                    Layout.preferredWidth: 250
-                    text: qsTr("Get Status")
-                    // @disable-check M223
-                    onClicked: {
-                        footerStatusText.text = ""
-                        // @disable-check M222
-                        _qmlHandler.onFooterGetStatusButton()
-                    }
-                }
+                text: qsTr("")
+                Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+                verticalAlignment: Text.AlignVCenter
+                font.pixelSize: 23
             }
 
-            Flickable {
-                id: footerFlickable
-                flickableDirection: Flickable.VerticalFlick
-                Layout.preferredHeight: 170
+            Text {
+                id: footerErrorText
                 Layout.preferredWidth: parent.width
-
-                TextArea.flickable: TextArea {
-                    selectByMouse: true
-                    id: footerLog
-                    readOnly: true
-                    wrapMode: TextArea.Wrap
-                    text: qsTr("")
-                    font.pointSize: 15
-                }
-
-                ScrollBar.vertical: ScrollBar {
-                }
+                color: "#fa3737"
+                text: qsTr("")
+                Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+                verticalAlignment: Text.AlignVCenter
+                font.pixelSize: 23
             }
         }
     }
+
+    Timer {
+        id: timer
+        interval: 3000
+        onTriggered: {
+            footerErrorText.text = ""
+        }
+    }
 }

+ 6 - 2
gui/src/Forms/Main/InvalidCliPathPopup.ui.qml

@@ -14,6 +14,10 @@ Popup {
     closePolicy: Popup.NoAutoClose
     anchors.centerIn: Overlay.overlay
 
+    Overlay.modal: Rectangle {
+        color: "#b5c5c5c5"
+    }
+
     Connections {
         target: _qmlHandler
         onInvalidCliPathPopupClose: {
@@ -32,7 +36,7 @@ Popup {
             Layout.preferredWidth: parent.width
             Layout.preferredHeight: 50
             id: invalidCliPathPopupText
-            color: "#ffffff"
+
             text: qsTr("Invalid CLI-Path: CLI could not be found on the location specified in the config file.\nPlease specify the new location of the CLI:")
             wrapMode: Text.WordWrap
             horizontalAlignment: Text.AlignHCenter
@@ -50,7 +54,7 @@ Popup {
                 Layout.preferredHeight: parent.height
                 Layout.preferredWidth: 600
                 id: invalidCliPathPopupCliPath
-                color: "#ffffff"
+
                 text: qsTr("Select CLI Path >>>")
                 horizontalAlignment: Text.AlignLeft
                 font.italic: true

+ 5 - 1
gui/src/Forms/Main/InvalidConfigPopup.ui.qml

@@ -14,6 +14,10 @@ Popup {
     closePolicy: Popup.NoAutoClose
     anchors.centerIn: Overlay.overlay
 
+    Overlay.modal: Rectangle {
+        color: "#b5c5c5c5"
+    }
+
     Connections {
         target: _qmlHandler
         onInvalidConfigPopupClose: {
@@ -32,7 +36,7 @@ Popup {
             Layout.preferredWidth: parent.width
             Layout.preferredHeight: 50
             id: invalidConfigPopupText
-            color: "#ffffff"
+
             text: qsTr("Configuration file invalid!\nWarning: Creating the default config will overwrite your config file!")
             wrapMode: Text.WordWrap
             horizontalAlignment: Text.AlignHCenter

+ 6 - 2
gui/src/Forms/Main/NoConfigFoundPopup.ui.qml

@@ -14,6 +14,10 @@ Popup {
     closePolicy: Popup.NoAutoClose
     anchors.centerIn: Overlay.overlay
 
+    Overlay.modal: Rectangle {
+        color: "#b5c5c5c5"
+    }
+
     Connections {
         target: _qmlHandler
         onNoConfigFoundPopupClose: {
@@ -32,7 +36,7 @@ Popup {
             Layout.preferredWidth: parent.width
             Layout.preferredHeight: 50
             id: noConfigFoundPopupText
-            color: "#ffffff"
+
             text: qsTr("No configuration file found. Default config will be created.\nPlease specify the location of the CLI:")
             wrapMode: Text.WordWrap
             horizontalAlignment: Text.AlignHCenter
@@ -50,7 +54,7 @@ Popup {
                 Layout.preferredHeight: parent.height
                 Layout.preferredWidth: 600
                 id: noConfigFoundPopupCliPath
-                color: "#ffffff"
+
                 text: qsTr("Select CLI Path >>>")
                 horizontalAlignment: Text.AlignLeft
                 font.italic: true

+ 66 - 32
gui/src/Forms/Main/main.qml

@@ -1,12 +1,10 @@
 import QtQuick 2.12
 import QtQuick.Controls 2.5
-import "../Sending"
-import "../Receiving"
-import "../Messages"
+import "../ServerFiles"
 import "../Settings"
-import "../Help"
 import "../Connect"
 import "../Notifications"
+import "../Log"
 
 ApplicationWindow {
     id: window
@@ -19,7 +17,7 @@ ApplicationWindow {
 
     minimumHeight: height
     minimumWidth: width
-    title: qsTr("Covert Channel - Control Panel")
+    title: qsTr("Covert Channel Application")
 
     property string notificationTabTitle: "Notifications"
 
@@ -27,25 +25,48 @@ ApplicationWindow {
         target: _qmlHandler
 
         onNotification: {
-            if (swipeView.currentIndex != 5)
+            if (swipeView.currentIndex != 2)
               notificationTabTitle = "* Notifications"
         }
     }
 
+    menuBar: MenuBar {
+        contentHeight: 30
+        Menu {
+            title: qsTr("&File")
+            Action {
+                text: qsTr("Change Server...")
+                onTriggered: {
+                    _qmlHandler.onSwitchServer()
+                    _qmlHandler.onStart(false)
+                    ipPopup.open()
+                }
+            }
+            MenuSeparator { }
+            Action {
+                text: qsTr("&Quit")
+                onTriggered: window.close()
+            }
+        }
+        Menu {
+            title: qsTr("&Help")
+            Action {
+                text: qsTr("About")
+                onTriggered: aboutPopup.open()
+            }
+        }
+    }
+
     SwipeView {
         id: swipeView
         anchors.fill: parent
         currentIndex: header.currentIndex
 
-        SendingForm {
-
-        }
-
-        ReceivingForm {
+        ServerFilesForm {
 
         }
 
-        MessagesForm {
+        NotificationsForm {
 
         }
 
@@ -53,11 +74,7 @@ ApplicationWindow {
 
         }
 
-        HelpForm {
-
-        }
-
-        NotificationsForm {
+        LogForm {
 
         }
     }
@@ -68,15 +85,15 @@ ApplicationWindow {
         contentHeight: 50
 
         TabButton {
-            text: qsTr("Sending")
+            text: qsTr("Server Files")
         }
 
         TabButton {
-            text: qsTr("Receiving")
-        }
+            text: notificationTabTitle
 
-        TabButton {
-            text: qsTr("Messages")
+            onClicked: {
+                text = "Notifications"
+            }
         }
 
         TabButton {
@@ -84,15 +101,7 @@ ApplicationWindow {
         }
 
         TabButton {
-            text: qsTr("Help")
-        }
-
-        TabButton {
-            text: notificationTabTitle
-
-            onClicked: {
-                text = "Notifications"
-            }
+            text: qsTr("Log")
         }
     }
 
@@ -120,9 +129,34 @@ ApplicationWindow {
         id: invalidCliPathPopup
     }
 
+    Popup {
+        id: aboutPopup
+        height: 300
+        dim: true
+        clip: false
+        width: 400
+        modal: true
+        focus: true
+        anchors.centerIn: Overlay.overlay
+
+        Overlay.modal: Rectangle {
+                color: "#b5b5b5e7"
+            }
+
+        TextArea {
+            anchors.fill: parent
+            text: "Covert Channel Application\n\nDeveloped by:\n\nTobias Alexander Wach\nPaul Leonard Sander\nMarius Rescheleit\nDenys Serdyukov\nJonas Pflanzer\n\nLicensed under the GNU General Public License v3.0"
+            wrapMode: Text.WordWrap
+            horizontalAlignment: Text.AlignHCenter
+            verticalAlignment: Text.AlignVCenter
+            font.pixelSize: 20
+        }
+    }
+
+
     Component.onCompleted: {
       swipeView.interactive = false
       ipPopup.open()
-      _qmlHandler.onStart()
+      _qmlHandler.onStart(true)
     }
 }

+ 0 - 84
gui/src/Forms/Messages/MessagesForm.ui.qml

@@ -1,84 +0,0 @@
-import QtQuick 2.12
-import QtQuick.Controls 2.5
-import QtQuick.Layouts 1.3
-
-Page {
-    width: 1280
-    height: 470
-
-    font.capitalization: Font.MixedCase
-
-    Connections {
-        target: _qmlHandler
-        onMessage: {
-            messagesLog.append(msg)
-            messagesFlickable.contentY = messagesLog.height - messagesFlickable.height
-        }
-    }
-
-    ColumnLayout {
-        anchors.fill: parent
-
-        Flickable {
-            id: messagesFlickable
-            flickableDirection: Flickable.VerticalFlick
-            Layout.preferredHeight: 400
-            Layout.preferredWidth: parent.width
-
-            TextArea.flickable: TextArea {
-                id: messagesLog
-                readOnly: true
-                selectByMouse: true
-                wrapMode: TextArea.Wrap
-                font.pointSize: 15
-            }
-
-            ScrollBar.vertical: ScrollBar {
-            }
-        }
-
-        RowLayout {
-            Layout.preferredHeight: 70
-            Layout.preferredWidth: parent.width
-
-            TextField {
-                id: messagesInputField
-                selectByMouse: true
-                Layout.preferredWidth: 1060
-                Layout.preferredHeight: parent.height
-                placeholderText: "Enter message..."
-                text: qsTr("")
-                font.pixelSize: 20
-                // @disable-check M222
-                Keys.onReturnPressed: messagesSendButton.activate()
-                // @disable-check M222
-                Keys.onEnterPressed: messagesSendButton.activate()
-            }
-
-            Button {
-                id: messagesSendButton
-                Layout.preferredWidth: 180
-                Layout.preferredHeight: parent.height
-                text: qsTr("Send")
-
-                // @disable-check M223
-                onClicked: {
-                    // @disable-check M222
-                    messagesSendButton.activate()
-                }
-
-                enabled: messagesInputField.text != ""
-                // @disable-check M222
-                function activate() {
-                    // @disable-check M223
-                    if (messagesInputField.text != "") {
-                        // @disable-check M222
-                        _qmlHandler.onMessagesSendButton(
-                                    messagesInputField.text)
-                        messagesInputField.text = ""
-                    }
-                }
-            }
-        }
-    }
-}

+ 0 - 2
gui/src/Forms/Notifications/NotificationTemplate.ui.qml

@@ -21,7 +21,6 @@ Item {
             verticalAlignment: Text.AlignVCenter
             horizontalAlignment: Text.AlignHLeft
             text: notificationDateText
-            color: "#ffffff"
         }
 
         Text {
@@ -32,7 +31,6 @@ Item {
             verticalAlignment: Text.AlignVCenter
             horizontalAlignment: Text.AlignHLeft
             text: notificationMessageText
-            color: "#ffffff"
         }
 
         Button {

+ 2 - 3
gui/src/Forms/Notifications/NotificationsForm.ui.qml

@@ -5,7 +5,7 @@ import Qt.labs.platform 1.1
 
 Page {
     width: 1280
-    height: 470
+    height: 570
     id: notificationsForm
 
     font.capitalization: Font.MixedCase
@@ -60,7 +60,7 @@ Page {
             Layout.preferredWidth: parent.width
             Layout.preferredHeight: 30
             id: loginTitle
-            color: "#ffffff"
+
             text: qsTr("No new notifications!")
             horizontalAlignment: Text.AlignHCenter
             verticalAlignment: Text.AlignVCenter
@@ -88,6 +88,5 @@ Page {
     SystemTrayIcon {
         id: trayIcon
         visible: true
-        icon.source: "qrc:/images/tray-icon.png"
     }
 }

+ 0 - 76
gui/src/Forms/Receiving/ReceivingForm.ui.qml

@@ -1,76 +0,0 @@
-import QtQuick 2.12
-import QtQuick.Controls 2.5
-import QtQuick.Layouts 1.3
-
-Page {
-    width: 1280
-    height: 470
-    id: receivingForm
-
-    font.capitalization: Font.MixedCase
-
-    Connections {
-        target: _qmlHandler
-        onReceivingListFile: {
-            fileList.append({
-                                "fileName": fileName,
-                                "fileSize": fileSize + " kB",
-                                "fileProgress": "",
-                                "fileDecryptable": fileDecryptable,
-                                "fileExistsLocally": existsLocally
-                            })
-        }
-
-        onReceivingClearFileList: {
-            fileList.clear()
-        }
-    }
-
-    ColumnLayout {
-        anchors.fill: parent
-
-        ScrollView {
-            Layout.preferredWidth: parent.width
-            Layout.preferredHeight: 400
-
-            ListView {
-                anchors.fill: parent
-                model: fileList
-                clip: true
-
-                delegate: ReceivingFileTemplate {
-                    fileNameText: fileName
-                    fileSizeText: fileSize
-                    fileProgressText: fileProgress
-                    fileDecryptableText: fileDecryptable
-                    fileExists: fileExistsLocally
-                }
-            }
-        }
-
-        ListModel {
-            id: fileList
-        }
-
-        RowLayout {
-            Layout.preferredWidth: parent.width
-            Layout.preferredHeight: 70
-
-            Button {
-                id: receivingListFilesButton
-                Layout.preferredWidth: 180
-                Layout.preferredHeight: parent.height
-                text: qsTr("Refresh File List")
-
-                // @disable-check M223
-                onClicked: {
-                    // @disable-check M222
-                    _qmlHandler.onReceivingListFilesButton()
-                }
-            }
-        }
-    }
-}
-
-
-

+ 0 - 95
gui/src/Forms/Sending/SendingForm.ui.qml

@@ -1,95 +0,0 @@
-import QtQuick 2.12
-import QtQuick.Controls 2.5
-import QtQuick.Dialogs 1.0
-
-Page {
-    width: 1280
-    height: 470
-    font.capitalization: Font.MixedCase
-
-    title: qsTr("Sending")
-
-    Connections {
-        target: _qmlHandler
-        onSendingSetFileUrlText: {
-            sendingSelectedFileText.text = signalText
-        }
-        onSendingEnableSendButton: {
-            sendingSendFileButton.enabled = true
-        }
-        onSendingDisableSendButton: {
-            sendingSendFileButton.enabled = false
-        }
-    }
-
-    Button {
-        id: sendingClearFileButton
-        x: 900
-        y: 40
-        width: 260
-        height: 90
-        text: qsTr("Clear Selection")
-        enabled: sendingSendFileButton.enabled
-        font.pointSize: 16
-        // @disable-check M223
-        onClicked: {
-            // @disable-check M222
-            _qmlHandler.onSendingClearSelectionButton()
-        }
-    }
-
-    Button {
-        id: sendingSelectFileButton
-        x: 120
-        y: 40
-        width: 260
-        height: 90
-        text: qsTr("Select File")
-        font.pointSize: 16
-        // @disable-check M223
-        onClicked: {
-            // @disable-check M222
-            sendingFileDialog.open()
-        }
-    }
-
-    Text {
-        id: sendingSelectedFileText
-        x: 54
-        y: 186
-        width: 1172
-        height: 52
-        color: "#ffffff"
-        text: qsTr("Selected File: None")
-        verticalAlignment: Text.AlignVCenter
-        horizontalAlignment: Text.AlignHCenter
-        font.pixelSize: 23
-    }
-
-    FileDialog {
-        id: sendingFileDialog
-        title: "Please choose a file"
-        folder: shortcuts.home
-        // @disable-check M223
-        onAccepted: {
-            // @disable-check M222
-            _qmlHandler.onSendingSelectFileButton(sendingFileDialog.fileUrl)
-        }
-    }
-
-    Button {
-        id: sendingSendFileButton
-        x: 510
-        y: 304
-        enabled: false
-        width: 260
-        height: 90
-        text: qsTr("Send File")
-        font.pointSize: 16
-        // @disable-check M223
-        onClicked: {
-            // @disable-check M222
-            _qmlHandler.onSendingSendFileButton()
-        }
-    }
-}

+ 9 - 10
gui/src/Forms/Receiving/ReceivingFileTemplate.ui.qml → gui/src/Forms/ServerFiles/ServerFilesFileTemplate.ui.qml

@@ -14,20 +14,20 @@ Item {
 
     Connections {
         target: _qmlHandler
-        onReceivingDisableDownloadButton: {
+        onServerFilesDisableDownloadButton: {
             if (fileNameText == fileName) {
                 fileExists = true
             }
         }
 
-        onReceivingUpdateFile: {
+        onServerFilesUpdateFile: {
             if (fileNameText == fileName) {
                 fileProgressText = fileProgress
                 fileQueued = isQueued
             }
         }
 
-        onReceivingCloseConfirmDeletePopup: {
+        onServerFilesCloseConfirmDeletePopup: {
             confirmDeletePopup.close()
         }
     }
@@ -43,7 +43,6 @@ Item {
             Layout.preferredWidth: 400
             verticalAlignment: Text.AlignVCenter
             text: fileNameText
-            color: "#ffffff"
         }
 
         Text {
@@ -52,9 +51,8 @@ Item {
             Layout.preferredHeight: parent.height
             Layout.preferredWidth: 100
             verticalAlignment: Text.AlignVCenter
-            horizontalAlignment: Text.AlignHCenter
+            horizontalAlignment: Text.AlignRight
             text: fileSizeText
-            color: "#ffffff"
         }
 
         Text {
@@ -65,7 +63,6 @@ Item {
             verticalAlignment: Text.AlignVCenter
             horizontalAlignment: Text.AlignHCenter
             text: fileProgressText
-            color: "#ffffff"
         }
 
         Text {
@@ -76,7 +73,9 @@ Item {
             verticalAlignment: Text.AlignVCenter
             horizontalAlignment: Text.AlignHCenter
             text: fileDecryptableText
-            color: (fileDecryptableText == "decryptable") ? "#3fdf3f" : (fileDecryptableText == "undecryptable") ? "#df3f3f" : "#ffffff"
+            color: (fileDecryptableText
+                    == "decryptable") ? "#3fdf3f" : (fileDecryptableText
+                                                     == "undecryptable") ? "#df3f3f" : "#000000"
         }
 
         Button {
@@ -107,7 +106,7 @@ Item {
             // @disable-check M223
             onClicked: {
                 // @disable-check M222
-                _qmlHandler.onReceivingDownloadFileButton(fileNameText)
+                _qmlHandler.onServerFilesDownloadFileButton(fileNameText)
             }
         }
 
@@ -126,7 +125,7 @@ Item {
         }
     }
 
-    ReceivingFileTemplateDeletePopup {
+    ServerFilesFileTemplateDeletePopup {
         id: confirmDeletePopup
     }
 }

+ 6 - 2
gui/src/Forms/Receiving/ReceivingFileTemplateDeletePopup.ui.qml → gui/src/Forms/ServerFiles/ServerFilesFileTemplateDeletePopup.ui.qml

@@ -13,6 +13,10 @@ Popup {
     closePolicy: Popup.NoAutoClose
     anchors.centerIn: Overlay.overlay
 
+    Overlay.modal: Rectangle {
+        color: "#b5c5c5c5"
+    }
+
     ColumnLayout {
         anchors.fill: parent
 
@@ -26,7 +30,6 @@ Popup {
             horizontalAlignment: Text.AlignHCenter
             wrapMode: Text.WordWrap
             font.pointSize: 15
-            color: "#ffffff"
         }
         RowLayout {
             Layout.preferredHeight: 80
@@ -39,7 +42,8 @@ Popup {
                 // @disable-check M223
                 onClicked: {
                     // @disable-check M222
-                    _qmlHandler.onReceivingConfirmDeleteFileButton(fileNameText)
+                    _qmlHandler.onServerFilesConfirmDeleteFileButton(
+                                fileNameText)
                 }
             }
 

+ 225 - 0
gui/src/Forms/ServerFiles/ServerFilesForm.ui.qml

@@ -0,0 +1,225 @@
+import QtQuick 2.12
+import QtQuick.Controls 2.5
+import QtQuick.Controls.Material 2.3
+import QtQuick.Layouts 1.3
+import QtQuick.Dialogs 1.0
+
+Page {
+    width: 1280
+    height: 570
+    id: serverFilesForm
+
+    font.capitalization: Font.MixedCase
+
+    Connections {
+        target: _qmlHandler
+        onServerFilesListFile: {
+            fileList.append({
+                                "fileName": fileName,
+                                "fileSize": fileSize + " kB",
+                                "fileProgress": "",
+                                "fileDecryptable": fileDecryptable,
+                                "fileExistsLocally": existsLocally
+                            })
+        }
+
+        onServerFilesClearFileList: {
+            fileList.clear()
+        }
+
+        onServerFilesSetFileUrlText: {
+            sendingSelectedFileText.text = signalText
+        }
+
+        onServerFilesEnableSendButton: {
+            sendingSendFileButton.enabled = true
+        }
+
+        onServerFilesDisableSendButton: {
+            sendingSendFileButton.enabled = false
+        }
+    }
+
+    ColumnLayout {
+        anchors.fill: parent
+
+        RowLayout {
+            Layout.preferredWidth: 750
+            Layout.preferredHeight: 30
+
+            Text {
+
+                text: qsTr("File Name")
+                Layout.alignment: Qt.AlignCenter
+                Layout.preferredWidth: 400
+                Layout.preferredHeight: parent.height
+                verticalAlignment: Text.AlignVCenter
+                horizontalAlignment: Text.AlignLeft
+                font.pixelSize: 15
+            }
+
+            Text {
+
+                text: qsTr("Size")
+                Layout.alignment: Qt.AlignCenter
+                Layout.preferredWidth: 100
+                Layout.preferredHeight: parent.height
+                verticalAlignment: Text.AlignVCenter
+                horizontalAlignment: Text.AlignHCenter
+                font.pixelSize: 15
+            }
+
+            Text {
+
+                text: qsTr("Status")
+                Layout.alignment: Qt.AlignCenter
+                Layout.preferredWidth: 100
+                Layout.preferredHeight: parent.height
+                verticalAlignment: Text.AlignVCenter
+                horizontalAlignment: Text.AlignHCenter
+                font.pixelSize: 15
+            }
+
+            Text {
+
+                text: qsTr("Encryption")
+                Layout.alignment: Qt.AlignCenter
+                Layout.preferredWidth: 150
+                Layout.preferredHeight: parent.height
+                verticalAlignment: Text.AlignVCenter
+                horizontalAlignment: Text.AlignHCenter
+                font.pixelSize: 15
+            }
+        }
+
+        Rectangle {
+            Layout.alignment: Qt.AlignCenter
+            Layout.preferredWidth: parent.width
+            Layout.preferredHeight: 2
+            color: "#404040"
+        }
+
+        ScrollView {
+            Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
+            Layout.preferredWidth: parent.width
+
+            Layout.preferredHeight: 440
+            ListView {
+                anchors.fill: parent
+                model: fileList
+                clip: true
+
+                delegate: ServerFilesFileTemplate {
+                    fileNameText: fileName
+                    fileSizeText: fileSize
+                    fileProgressText: fileProgress
+                    fileDecryptableText: fileDecryptable
+                    fileExists: fileExistsLocally
+                }
+            }
+        }
+
+        ListModel {
+            id: fileList
+        }
+
+        Rectangle {
+            Layout.alignment: Qt.AlignCenter
+            Layout.preferredWidth: parent.width
+            Layout.preferredHeight: 2
+            color: Material.accent
+        }
+
+        RowLayout {
+            Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+            Layout.preferredWidth: parent.width
+
+            Text {
+
+                text: qsTr("Selected File: ")
+                Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
+                Layout.preferredWidth: 150
+                Layout.preferredHeight: 50
+                verticalAlignment: Text.AlignVCenter
+                horizontalAlignment: Text.AlignHCenter
+                font.pixelSize: 23
+            }
+
+            Text {
+                id: sendingSelectedFileText
+
+                text: qsTr("None")
+                Layout.preferredWidth: 450
+                Layout.preferredHeight: 50
+                verticalAlignment: Text.AlignVCenter
+                horizontalAlignment: Text.AlignLeft
+                font.pixelSize: 23
+                elide: Text.ElideLeft
+                ToolTip.visible: mouseArea.containsMouse
+                ToolTip.text: text
+                ToolTip.delay: 200
+
+                MouseArea {
+                    id: mouseArea
+                    anchors.fill: parent
+                    hoverEnabled: true
+                }
+            }
+
+            Button {
+                id: sendingClearFileButton
+                text: qsTr("Clear Selection")
+                Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+                Layout.preferredWidth: 200
+                Layout.preferredHeight: 50
+                enabled: sendingSendFileButton.enabled
+                font.pointSize: 16
+                // @disable-check M223
+                onClicked: {
+                    // @disable-check M222
+                    _qmlHandler.onServerFilesClearSelectionButton()
+                }
+            }
+
+            Button {
+                id: sendingSelectFileButton
+                text: qsTr("Select File")
+                Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+                Layout.preferredWidth: 200
+                Layout.preferredHeight: 50
+                font.pointSize: 16
+                // @disable-check M223
+                onClicked: {
+                    // @disable-check M222
+                    sendingFileDialog.open()
+                }
+            }
+
+            Button {
+                id: sendingSendFileButton
+                enabled: false
+                text: qsTr("Upload File")
+                Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+                Layout.preferredWidth: 200
+                Layout.preferredHeight: 50
+                font.pointSize: 16
+                // @disable-check M223
+                onClicked: {
+                    // @disable-check M222
+                    _qmlHandler.onServerFilesSendFileButton()
+                }
+            }
+        }
+    }
+
+    FileDialog {
+        id: sendingFileDialog
+        title: "Please choose a file"
+        folder: shortcuts.home
+        // @disable-check M223
+        onAccepted: {
+            // @disable-check M222
+            _qmlHandler.onServerFilesSelectFileButton(sendingFileDialog.fileUrl)
+        }
+    }
+}

+ 9 - 1
gui/src/Forms/Settings/DeleteMePopup.ui.qml

@@ -15,6 +15,10 @@ Popup {
 
     signal resetStatus
 
+    Overlay.modal: Rectangle {
+        color: "#b5c5c5c5"
+    }
+
     onClosed: {
         resetStatus()
     }
@@ -33,7 +37,7 @@ Popup {
             Layout.alignment: Qt.AlignCenter
             Layout.preferredWidth: parent.width
             Layout.preferredHeight: 100
-            color: "#ffffff"
+
             text: qsTr("Are you sure you want to delete your account on the server?\nThe application will restart.")
             wrapMode: Text.WordWrap
             horizontalAlignment: Text.AlignHCenter
@@ -67,6 +71,10 @@ Popup {
             text: ""
             horizontalAlignment: Text.AlignHCenter
             placeholderText: "Enter password to confirm"
+            Connections {
+                target: popup
+                onResetStatus: deleteMePopupPasswordInput.text = ""
+            }
         }
 
         RowLayout {

+ 14 - 19
gui/src/Forms/Settings/SettingsForm.ui.qml

@@ -6,8 +6,8 @@ import QtQuick.Dialogs 1.0
 
 Page {
     width: 1280
-    height: 470
-    id: page
+    height: 570
+    id: settingsForm
 
     font.capitalization: Font.MixedCase
 
@@ -20,14 +20,13 @@ Page {
             settingsSaveIpSwitch.checked = saveIP
             settingsSaveUsernameSwitch.checked = saveUsername
             settingsCliPath.text = "CLI-Path:   " + cliPath
-            settingsKeyPath.text = "CLI-Path:   " + keyPath
+            settingsKeyPath.text = "            " + keyPath
         }
         onKeyfileStatus: {
-            if(success) {
+            if (success) {
                 settingsKeyStatus.text = "Keyfile: OK"
                 settingsKeyStatus.color = "#3fdf3f"
-            }
-            else {
+            } else {
                 settingsKeyStatus.text = "Keyfile: Error"
                 settingsKeyStatus.color = "#df3f3f"
                 settingsKeyPath.text = msg
@@ -35,7 +34,7 @@ Page {
         }
         onKeyfileClosedOK: {
             settingsKeyStatus.text = "Keyfile:"
-            settingsKeyStatus.color = "#ffffff"
+            settingsKeyStatus.color = "#000000"
             settingsKeyPath.text = "   "
         }
     }
@@ -58,7 +57,7 @@ Page {
                     Layout.alignment: Qt.AlignCenter
                     Layout.preferredWidth: 400
                     Layout.preferredHeight: 50
-                    color: "#ffffff"
+
                     text: "Autofill default IP on start:"
                     verticalAlignment: Text.AlignVCenter
                     horizontalAlignment: Text.AlignLeft
@@ -69,7 +68,7 @@ Page {
                     Layout.alignment: Qt.AlignCenter
                     Layout.preferredWidth: 400
                     Layout.preferredHeight: 50
-                    color: "#ffffff"
+
                     text: "Autofill default username on start:"
                     verticalAlignment: Text.AlignVCenter
                     horizontalAlignment: Text.AlignLeft
@@ -81,7 +80,7 @@ Page {
                     Layout.alignment: Qt.AlignCenter
                     Layout.preferredWidth: 400
                     Layout.preferredHeight: 50
-                    color: "#ffffff"
+
                     text: "CLI-Path:   "
                     verticalAlignment: Text.AlignVCenter
                     horizontalAlignment: Text.AlignLeft
@@ -93,7 +92,7 @@ Page {
                     Layout.alignment: Qt.AlignCenter
                     Layout.preferredWidth: 400
                     Layout.preferredHeight: 50
-                    color: "#ffffff"
+
                     text: "Keyfile:"
                     verticalAlignment: Text.AlignVCenter
                     horizontalAlignment: Text.AlignLeft
@@ -105,7 +104,7 @@ Page {
                     Layout.alignment: Qt.AlignCenter
                     Layout.preferredWidth: 400
                     Layout.preferredHeight: 50
-                    color: "#ffffff"
+
                     text: "   "
                     verticalAlignment: Text.AlignVCenter
                     horizontalAlignment: Text.AlignLeft
@@ -116,7 +115,7 @@ Page {
                     Layout.alignment: Qt.AlignCenter
                     Layout.preferredWidth: 400
                     Layout.preferredHeight: 50
-                    color: "#ffffff"
+
                     text: "Delete my account:"
                     verticalAlignment: Text.AlignVCenter
                     horizontalAlignment: Text.AlignLeft
@@ -154,7 +153,7 @@ Page {
                     Layout.alignment: Qt.AlignCenter
                     Layout.preferredHeight: 50
                     Layout.preferredWidth: 220
-                    text: "Change (needs restart)"
+                    text: "Change (req. restart)"
                     font.pixelSize: 20
                     // @disable-check M223
                     onClicked: {
@@ -254,8 +253,7 @@ Page {
                                 settingsCliPath.text.replace("CLI-Path:   ",
                                                              ""),
                                 // @disable-check M222
-                                settingsKeyPath.text.replace("   ",
-                                                             ""))
+                                settingsKeyPath.text.replace("   ", ""))
                 }
             }
 
@@ -308,6 +306,3 @@ Page {
         id: deleteMePopup
     }
 }
-
-
-

+ 6 - 9
gui/src/climanager.cpp

@@ -58,7 +58,9 @@ void CliManager::onExit() {
 void CliManager::setQmlHandler(QMLHandler *q) { qmlHandler = q; }
 
 void CliManager::init() {
+	// TODO: Remove
 	qInfo() << QString::fromStdString(string("InitCLI with path ") + Config::getValue("CLI-Path"));
+	emit qmlHandler->log(QString::fromStdString(string("InitCLI with path ") + Config::getValue("CLI-Path")));
 	if (!Config::getValue("CLI-Path").size()) {
 		qInfo() << "Empty CLI-Path!";
 		return;
@@ -135,9 +137,6 @@ void CliManager::readPipeLoop() {
 			pipeInput.append(buf);
 			inputs = tokenizeByNewlines(pipeInput);
 			for (string s : inputs) {
-				emit qmlHandler->log(QString::fromStdString(s));
-				qInfo() << QString::fromStdString(s);
-				// handleJSON(s);
 				JsonHandler::parseJSON(s);
 			}
 			pipeInput = string();
@@ -145,7 +144,11 @@ void CliManager::readPipeLoop() {
 			pollCount = 0;
 			readOffset = 0;
 			if (waitpid(childpid, NULL, WNOHANG)) {
+				// TODO: Remove
 				qInfo() << "CLI has exited/did not launch";
+				emit qmlHandler->log("CLI has exited/did not launch");
+
+				emit qmlHandler->footerSetError("CLI crashed. Please restart the application.");
 				setProgramActive(false);
 				// nonzero means error or childid has changed state
 				// for us that means child has exited -> CLI is dead
@@ -157,15 +160,9 @@ void CliManager::readPipeLoop() {
 			pipeInput.append(buf);
 			inputs = tokenizeByNewlines(pipeInput);
 			for (unsigned i = 0; i < inputs.size() - 1; i++) { // process all lines except the last, potentially incomplete one
-				// do not log these lines, Qt/Quick has no simple way of limiting the number of lines in the logging window so we might go OoM real quick
-				//~ emit qmlHandler->log(QString::fromStdString(inputs[i]));
-				qInfo() << QString::fromStdString(inputs[i]);
-				// handleJSON(s);
 				JsonHandler::parseJSON(inputs[i]);
 			}
 			if (pipeInput.back() == '\n') { // process last line if it was complete
-				qInfo() << QString::fromStdString(inputs.back());
-				// handleJSON(s);
 				JsonHandler::parseJSON(inputs.back());
 				pipeInput = string();
 			} else {

+ 28 - 14
gui/src/cmdmanager.cpp

@@ -38,6 +38,7 @@ void CmdManager::init() {
 	cmdmap["extendedstatus"] = &CmdManager::handleExtendedStatus;
 	cmdmap["keyfile"] = &CmdManager::handleKeyfile;
 	cmdmap["closekey"] = &CmdManager::handleClosekey;
+	cmdmap["disconnect"] = &CmdManager::handleDisconnect;
 
 	filemap.clear();
 }
@@ -69,11 +70,11 @@ void CmdManager::emitFileList() {
 				progstr = it->second.type + " via " + it->second.method + "\n" + std::to_string(it->second.progress) + "%" + " @ " + speedbuf;
 			} else
 				progstr = it->second.type + "\n" + std::to_string(it->second.progress) + "%";
-			emit qmlHandler->receivingUpdateFile(it->first.c_str(), progstr.c_str(), it->second.type == "Queued" || it->second.type == "Sending");
+			emit qmlHandler->serverFilesUpdateFile(it->first.c_str(), progstr.c_str(), it->second.type == "Queued" || it->second.type == "Sending");
 		}
 		// else emit plain entry
 		else
-			emit qmlHandler->receivingUpdateFile(it->first.c_str(), "", false);
+			emit qmlHandler->serverFilesUpdateFile(it->first.c_str(), "", false);
 	}
 }
 
@@ -109,6 +110,7 @@ void CmdManager::executeCmd(string cmd, Json::Value root) {
 }
 
 void CmdManager::setCachedIP(QString ip) { cachedIP = ip; }
+
 void CmdManager::setCachedPort(QString port) { cachedPort = port; }
 
 void CmdManager::handleError(Json::Value root) { emit qmlHandler->log(root["error"].asString().c_str()); }
@@ -121,14 +123,14 @@ void CmdManager::handleList(Json::Value root) {
 	char sizebuf[256];
 	snprintf(sizebuf, 256, "%.2f", 4.2f);
 	if (root["accept"] == true) {
-		emit qmlHandler->receivingClearFileList();
+		emit qmlHandler->serverFilesClearFileList();
 		filemap.clear();
 
 		// Get the array of file Names
 		auto fileNames = root["names"];
 		for (int i = 0; i < fileNames.size(); i++) {
-			emit qmlHandler->receivingListFile(QString::fromStdString(fileNames[i].asString()), QString::fromStdString(sizebuf), QString("Decryptable"),
-			                                   !!ifstream(fileNames[i].asString()));
+			emit qmlHandler->serverFilesListFile(QString::fromStdString(fileNames[i].asString()), QString::fromStdString(sizebuf), QString("Decryptable"),
+			                                     !!ifstream(fileNames[i].asString()));
 			filemap[fileNames[i].asString()] = {false, "", "", 0, 0};
 		}
 	} else {
@@ -139,15 +141,15 @@ void CmdManager::handleList(Json::Value root) {
 void CmdManager::handleExtendedList(Json::Value root) {
 	char sizebuf[256];
 	if (root["accept"] == true) {
-		emit qmlHandler->receivingClearFileList();
+		emit qmlHandler->serverFilesClearFileList();
 		filemap.clear();
 
 		// Get the array of file Names
 		auto files = root["files"];
 		for (Json::Value f : files) {
 			snprintf(sizebuf, 256, "%.2f", f["size"].asFloat());
-			emit qmlHandler->receivingListFile(QString::fromStdString(f["name"].asString()), QString::fromStdString(sizebuf),
-			                                   QString::fromStdString(f["encrypted"].asString()), !!ifstream(f["name"].asString()));
+			emit qmlHandler->serverFilesListFile(QString::fromStdString(f["name"].asString()), QString::fromStdString(sizebuf),
+			                                     QString::fromStdString(f["encrypted"].asString()), !!ifstream(f["name"].asString()));
 			filemap[f["name"].asString()] = {false, "", "", 0, 0};
 		}
 	} else {
@@ -206,7 +208,10 @@ void CmdManager::handlePut(Json::Value root) {
 }
 
 void CmdManager::handlePutData(Json::Value root) {
-	// TODO: Show speed and handle Error
+	if (root["cancel"] == true) {
+		QString errorMessage = QString::fromStdString(string("Error when uploading file " + root["file"].asString() + ":\n" + root["error"].asString()));
+		emit qmlHandler->log(errorMessage);
+	}
 }
 
 void CmdManager::handleGet(Json::Value root) {
@@ -215,17 +220,20 @@ void CmdManager::handleGet(Json::Value root) {
 		emit qmlHandler->log(errorMessage);
 	} else {
 		string fileName = root["file"].asString();
-		// TODO: Only do this in getdata when remaining is 0 (when the file is fully downloaded) - maybe set text to "downloading.." in between
-		emit qmlHandler->receivingDisableDownloadButton(QString::fromStdString(fileName));
+		emit qmlHandler->serverFilesDisableDownloadButton(QString::fromStdString(fileName));
 	}
 }
 
 void CmdManager::handleGetData(Json::Value root) {
-	// TODO: Show speed and handle Error
+	if (root["cancel"] == true) {
+		QString errorMessage = QString::fromStdString(string("Error when downloading file " + root["file"].asString() + ":\n" + root["error"].asString()));
+		emit qmlHandler->log(errorMessage);
+	}
 }
 
 void CmdManager::handleDeleteMe(Json::Value root) {
 	if (root["accept"] == true) {
+		CliManager::loggedin = true;
 		qmlHandler->setRestart(true);
 		emit qmlHandler->closeWindow();
 	} else {
@@ -235,7 +243,7 @@ void CmdManager::handleDeleteMe(Json::Value root) {
 }
 
 void CmdManager::handleDeleteFile(Json::Value root) {
-	emit qmlHandler->receivingCloseConfirmDeletePopup();
+	emit qmlHandler->serverFilesCloseConfirmDeletePopup();
 	if (root["accept"] == false) {
 		QString errorMessage = QString::fromStdString(string("Error when deleting file " + root["file"].asString() + ":\n" + root["error"].asString()));
 		emit qmlHandler->log(errorMessage);
@@ -325,4 +333,10 @@ void CmdManager::handleClosekey(Json::Value root) {
 	} else {
 		emit qmlHandler->keyfileClosedOK();
 	}
-}
+}
+
+void CmdManager::handleDisconnect(Json::Value root) {
+	if (root["accept"] == true) {
+		CliManager::loggedin = false;
+	}
+}

BIN
gui/src/images/tray-icon.png


+ 23 - 3
gui/src/jsonhandler.cpp

@@ -1,8 +1,16 @@
-#include "../include/jsonhandler.h"
+#include <QDebug>
+
 #include "../include/cmdmanager.h"
+#include "../include/jsonhandler.h"
 
 using namespace std;
 
+namespace JsonHandler {
+QMLHandler *qmlHandler;
+}
+
+void JsonHandler::setQmlHandler(QMLHandler *q) { qmlHandler = q; }
+
 // This method gets a string and tries to read it as Json
 // If it fails to do so, return and do nothing, else handle the content
 void JsonHandler::parseJSON(string buffer) {
@@ -11,8 +19,7 @@ void JsonHandler::parseJSON(string buffer) {
 	Json::CharReader *reader = builder.newCharReader();
 	string jsonError;
 
-	// Try to parse the string as Json and store the result of the pasring in a
-	// boolean
+	// Try to parse the string as Json and store the result of the parsing in a boolean
 	bool parsingSuccessful = reader->parse(buffer.c_str(), buffer.c_str() + buffer.size(), &root, &jsonError);
 
 	delete (reader);
@@ -23,6 +30,19 @@ void JsonHandler::parseJSON(string buffer) {
 	}
 
 	string cmd = root["command"].asString();
+	string err = root["error"].asString();
+
+	// Filter the commands to not be printed
+	if (cmd.compare("notifications") && cmd.compare("extendedlist") && cmd.compare("extendedstatus") && cmd.compare("status") && cmd.compare("putdata") &&
+	    cmd.compare("getdata")) {
+		emit qmlHandler->log(QString::fromStdString(buffer));
+		// TODO: Remove
+		qInfo() << QString::fromStdString(buffer);
+	}
+
+	if (err.compare("")) {
+		emit qmlHandler->footerSetError(QString::fromStdString(err));
+	}
 
 	CmdManager::executeCmd(cmd, root);
 }

+ 1 - 0
gui/src/main.cpp

@@ -34,6 +34,7 @@ int main(int argc, char *argv[]) {
 	CmdManager::setQmlHandler(&qmlHandler);
 	CmdManager::init();
 	CliManager::setQmlHandler(&qmlHandler);
+	JsonHandler::setQmlHandler(&qmlHandler);
 
 	// Set the context for the window, so that the qml files can be connected to
 	// the qmlHandler

+ 5 - 13
gui/src/qml.qrc

@@ -8,27 +8,19 @@
         <file>Forms/Main/InvalidCliPathPopup.ui.qml</file>
         <file>Forms/Main/InvalidConfigPopup.ui.qml</file>
 
-        <file>Forms/Connect/LoginForm.ui.qml</file>
+        <file>Forms/ServerFiles/ServerFilesForm.ui.qml</file>
+        <file>Forms/ServerFiles/ServerFilesFileTemplate.ui.qml</file>
+        <file>Forms/ServerFiles/ServerFilesFileTemplateDeletePopup.ui.qml</file>
+
         <file>Forms/Connect/IpPopup.ui.qml</file>
         <file>Forms/Connect/LoginSignupPopup.ui.qml</file>
-        <file>Forms/Connect/SignupForm.ui.qml</file>
-
-        <file>Forms/Sending/SendingForm.ui.qml</file>
-
-        <file>Forms/Receiving/ReceivingForm.ui.qml</file>
-        <file>Forms/Receiving/ReceivingFileTemplate.ui.qml</file>
-        <file>Forms/Receiving/ReceivingFileTemplateDeletePopup.ui.qml</file>
 
-        <file>Forms/Messages/MessagesForm.ui.qml</file>
+        <file>Forms/Log/LogForm.ui.qml</file>
 
         <file>Forms/Settings/DeleteMePopup.ui.qml</file>
         <file>Forms/Settings/SettingsForm.ui.qml</file>
 
         <file>Forms/Notifications/NotificationsForm.ui.qml</file>
         <file>Forms/Notifications/NotificationTemplate.ui.qml</file>
-
-        <file>Forms/Help/HelpForm.ui.qml</file>
-
-        <file>images/tray-icon.png</file>
     </qresource>
 </RCC>

+ 18 - 22
gui/src/qmlhandler.cpp

@@ -42,7 +42,8 @@ void QMLHandler::loadSettingsToGUI() {
 
 // ### QML Handlers ###
 
-void QMLHandler::onStart() {
+// Main
+void QMLHandler::onStart(bool startWithCli) {
 	bool configExists = Config::loadFile();
 
 	if (configExists) {
@@ -60,7 +61,7 @@ void QMLHandler::onStart() {
 			if (!ifstream(Config::getValue("CLI-Path"))) {
 				// Invalid CLI Path
 				emit invalidCliPathPopupOpen();
-			} else {
+			} else if (startWithCli) {
 				// Everything OK, init CLI
 				CliManager::init();
 			}
@@ -75,18 +76,20 @@ void QMLHandler::onStart() {
 	}
 }
 
+void QMLHandler::onSwitchServer() { CliManager::writeToCli("disconnect"); }
+
 // No Config Found Popup
 void QMLHandler::onNoConfigFoundPopupContinueButton(QString cli_path) {
 	Config::setValue("CLI-Path", cli_path.toUtf8().constData());
 	Config::saveFile();
-	onStart();
+	onStart(true);
 }
 
 // Invalid Cli Path Popup
 void QMLHandler::onInvalidCliPathPopupContinueButton(QString cli_path) {
 	Config::setValue("CLI-Path", cli_path.toUtf8().constData());
 	Config::saveFile();
-	onStart();
+	onStart(true);
 }
 
 void QMLHandler::onInvalidCliPathPopupQuitButton() { emit closeWindow(); }
@@ -99,39 +102,34 @@ void QMLHandler::onInvalidConfigPopupCreateDefaultButton() {
 	emit noConfigFoundPopupOpen();
 }
 
-// Sending
-void QMLHandler::onSendingSelectFileButton(QUrl url) {
+// Server Files
+void QMLHandler::onServerFilesSelectFileButton(QUrl url) {
 	sendFileUrl = url.toLocalFile();
 	emit log("File Selected: " + sendFileUrl.toString());
-	emit sendingSetFileUrlText("Selected File: " + sendFileUrl.toString());
-	emit sendingEnableSendButton();
+	emit serverFilesSetFileUrlText(sendFileUrl.toString());
+	emit serverFilesEnableSendButton();
 }
 
-void QMLHandler::onSendingSendFileButton() {
+void QMLHandler::onServerFilesSendFileButton() {
 	QString command = "put \"" + sendFileUrl.toString() + "\"";
 	CliManager::writeToCli(command);
-	CliManager::writeToCli("extendedlist");
 }
 
-void QMLHandler::onSendingClearSelectionButton() {
+void QMLHandler::onServerFilesClearSelectionButton() {
 	sendFileUrl = QUrl("");
 	emit log("Cleared Selection");
-	emit sendingSetFileUrlText("Selected File: None");
-	emit sendingDisableSendButton();
+	emit serverFilesSetFileUrlText("None");
+	emit serverFilesDisableSendButton();
 }
 
-// Receiving
-void QMLHandler::onReceivingListFilesButton() { CliManager::writeToCli("extendedlist"); }
-
-void QMLHandler::onReceivingDownloadFileButton(QString fileName) {
+void QMLHandler::onServerFilesDownloadFileButton(QString fileName) {
 	QString command = "get \"" + fileName + "\"";
 	CliManager::writeToCli(command);
 }
 
-void QMLHandler::onReceivingConfirmDeleteFileButton(QString fileName) {
+void QMLHandler::onServerFilesConfirmDeleteFileButton(QString fileName) {
 	QString command = "deletefile \"" + fileName + "\"";
 	CliManager::writeToCli(command);
-	CliManager::writeToCli("extendedlist");
 }
 
 // Messages
@@ -143,6 +141,7 @@ void QMLHandler::onKeyfileSelected(QString path) {
 	CliManager::writeToCli(command);
 }
 void QMLHandler::onKeyfileClosed() { CliManager::writeToCli("closekey"); }
+
 void QMLHandler::onSettingsDeleteMeButton(QString password) {
 	QString command = "deleteme " + password;
 	CliManager::writeToCli(command);
@@ -223,9 +222,6 @@ void QMLHandler::onSignupRegisterButton(QString username, QString passwordOne, Q
 	}
 }
 
-// Footer
-void QMLHandler::onFooterGetStatusButton() { CliManager::writeToCli("extendedstatus"); }
-
 // Notifications
 void QMLHandler::onDismissNotificationButton(int index) { emit dismissNotification(index); }
 

+ 5 - 2
gui/src/qtquickcontrols2.conf

@@ -3,8 +3,11 @@
 ; http://doc.qt.io/qt-5/qtquickcontrols2-configuration.html
 
 [Controls]
-Style=Material
+Style=Fusion
 
 [Material]
-Theme=Dark
 Accent=Cyan
+
+[Fusion]
+Palette\Window=#dedede
+Palette\WindowText=#000000