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