From c8c3d8641f72e979cd7da11901b6a2ae0745de0b Mon Sep 17 00:00:00 2001
From: Přemysl Eric Janouch
Date: Fri, 13 Dec 2024 06:37:21 +0100
Subject: WIP: Add a Qt Quick frontend for xC
We have to decouple the UI from the relay code.
---
xT/CMakeLists.txt | 25 ++++++++++---
xT/xT.cpp | 2 +-
xT/xTq.cpp | 40 +++++++++++++++++++++
xT/xTq.h | 15 ++++++++
xT/xTq.qml | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 181 insertions(+), 6 deletions(-)
create mode 100644 xT/xTq.cpp
create mode 100644 xT/xTq.h
create mode 100644 xT/xTq.qml
(limited to 'xT')
diff --git a/xT/CMakeLists.txt b/xT/CMakeLists.txt
index 8f27be3..562c15a 100644
--- a/xT/CMakeLists.txt
+++ b/xT/CMakeLists.txt
@@ -12,8 +12,10 @@ project (xT VERSION "${project_version}"
set (CMAKE_CXX_STANDARD 17)
set (CMAKE_CXX_STANDARD_REQUIRED ON)
-find_package (Qt6 REQUIRED COMPONENTS Widgets Network Multimedia)
-qt_standard_project_setup ()
+find_package (Qt6 REQUIRED COMPONENTS Widgets Network Multimedia
+ Quick QuickControls2)
+# XXX: The version requirement is probably for Qt Quick only.
+qt_standard_project_setup (REQUIRES 6.5)
add_compile_options ("$<$:/utf-8>")
add_compile_options ("$<$:-Wall;-Wextra>")
@@ -77,7 +79,7 @@ else ()
endif ()
# Build the main executable and link it
-find_program (awk_EXECUTABLE awk ${find_program_REQUIRE})
+find_program (awk_EXECUTABLE awk REQUIRED)
add_custom_command (OUTPUT xC-proto.cpp
COMMAND ${CMAKE_COMMAND} -E env LC_ALL=C ${awk_EXECUTABLE}
-f ${root}/liberty/tools/lxdrgen.awk
@@ -103,11 +105,24 @@ set_target_properties (xT PROPERTIES WIN32_EXECUTABLE ON MACOSX_BUNDLE ON
# https://stackoverflow.com/questions/79079161 and resolved in Qt Creator 16.
set (QT_QML_GENERATE_QMLLS_INI ON)
+# TODO(p): Perhaps do it in one-or-the-other way,
+# as Qt Quick sucks on the desktop, and Qt Widgets is unusable on mobile.
+qt_add_executable (xTq
+ xTq.cpp ${project_config} ${project_sources} "${icon_icns}")
+set_property (SOURCE xTq.qml APPEND PROPERTY QT_QML_SOURCE_TYPENAME Main)
+qt_add_qml_module (xTq URI xTquick VERSION 1.0 QML_FILES xTq.qml)
+add_dependencies (xTq xC-proto)
+qt_add_resources (xTq "rsrc" PREFIX / FILES "${beep}" ${icon_rsrc_list})
+target_link_libraries (xTq PRIVATE
+ Qt6::Quick Qt6::QuickControls2 Qt6::Network Qt6::Multimedia)
+set_target_properties (xTq PROPERTIES WIN32_EXECUTABLE ON MACOSX_BUNDLE ON
+ MACOSX_BUNDLE_GUI_IDENTIFIER name.janouch.xTq)
+
# The files to be installed
include (GNUInstallDirs)
if (ANDROID)
- install (TARGETS xT DESTINATION .)
+ install (TARGETS xTq DESTINATION .)
elseif (APPLE OR WIN32)
install (TARGETS xT
BUNDLE DESTINATION .
@@ -144,7 +159,7 @@ if (WIN32)
foreach (lib ${libs})
string (STRIP "${lib}" lib)
file (COPY "${cygroot}${lib}" DESTINATION "${bindir}")
- endforeach()
+ endforeach ()
endif ()
]=])
endif ()
diff --git a/xT/xT.cpp b/xT/xT.cpp
index f84c87c..72f5892 100644
--- a/xT/xT.cpp
+++ b/xT/xT.cpp
@@ -1,5 +1,5 @@
/*
- * xT.cpp: Qt frontend for xC
+ * xT.cpp: Qt Widgets frontend for xC
*
* Copyright (c) 2024, Přemysl Eric Janouch
*
diff --git a/xT/xTq.cpp b/xT/xTq.cpp
new file mode 100644
index 0000000..a6d48bf
--- /dev/null
+++ b/xT/xTq.cpp
@@ -0,0 +1,40 @@
+/*
+ * xTq.cpp: Qt Quick frontend for xC
+ *
+ * Copyright (c) 2024, Přemysl Eric Janouch
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "xC-proto.cpp"
+
+#include
+
+#include
+#include
+
+#include "xTq.h"
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+int
+main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QQmlApplicationEngine engine;
+ QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
+ &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection);
+ engine.loadFromModule("xTquick", "Main");
+ return app.exec();
+}
diff --git a/xT/xTq.h b/xT/xTq.h
new file mode 100644
index 0000000..70a0374
--- /dev/null
+++ b/xT/xTq.h
@@ -0,0 +1,15 @@
+#ifndef XTQ_H
+#define XTQ_H
+
+#include
+#include
+
+class RelayConnection : public QObject {
+ Q_OBJECT
+ QML_ELEMENT
+
+public:
+ QTcpSocket *socket; ///< Buffered relay socket
+};
+
+#endif // XTQ_H
diff --git a/xT/xTq.qml b/xT/xTq.qml
new file mode 100644
index 0000000..50063c9
--- /dev/null
+++ b/xT/xTq.qml
@@ -0,0 +1,105 @@
+import QtQuick
+import QtQuick.Controls.Fusion
+//import QtQuick.Controls
+import QtQuick.Layouts
+
+ApplicationWindow {
+ id: window
+ width: 640
+ height: 480
+ visible: true
+ title: qsTr("xT")
+
+ property RelayConnection connection
+
+ ColumnLayout {
+ id: column
+ anchors.fill: parent
+ anchors.margins: 6
+
+ ScrollView {
+ id: bufferScroll
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ TextArea {
+ id: buffer
+ text: qsTr("Buffer text")
+ }
+ }
+
+ RowLayout {
+ id: row
+ Layout.fillWidth: true
+
+ Label {
+ Layout.fillWidth: true
+ id: prompt
+ text: qsTr("Prompt")
+ }
+
+ Label {
+ Layout.fillWidth: true
+ id: status
+ horizontalAlignment: Text.AlignRight
+ text: qsTr("Status")
+ }
+ }
+
+ TextArea {
+ id: input
+ Layout.fillWidth: true
+ text: qsTr("Input")
+ }
+ }
+
+ Component.onCompleted: {}
+
+ Dialog {
+ id: connect
+ title: "Connect to relay"
+ anchors.centerIn: parent
+ modal: true
+ visible: true
+
+ onRejected: Qt.quit()
+ onAccepted: {
+ // TODO(p): Store the host, store the port, initiate connection.
+ }
+
+ GridLayout {
+ anchors.fill: parent
+ anchors.margins: 6
+ columns: 2
+
+ // It is a bit silly that one has to do everything manually.
+ Keys.onReturnPressed: connect.accept()
+
+ Label { text: "Host:" }
+ TextField {
+ id: connectHost
+ Layout.fillWidth: true
+ // And if this doesn't work reliably, do it after open().
+ focus: true
+ }
+ Label { text: "Port:" }
+ TextField {
+ id: connectPort
+ Layout.fillWidth: true
+ }
+ }
+
+ footer: DialogButtonBox {
+ Button {
+ text: qsTr("Connect")
+ DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
+ Keys.onReturnPressed: connect.accept()
+ highlighted: true
+ }
+ Button {
+ text: qsTr("Close")
+ DialogButtonBox.buttonRole: DialogButtonBox.DestructiveRole
+ Keys.onReturnPressed: connect.reject()
+ }
+ }
+ }
+}
--
cgit v1.2.3-70-g09d2