aboutsummaryrefslogtreecommitdiff
path: root/xT
diff options
context:
space:
mode:
Diffstat (limited to 'xT')
-rw-r--r--xT/CMakeLists.txt100
-rw-r--r--xT/xT.cpp12
-rw-r--r--xT/xTq.cpp40
-rw-r--r--xT/xTq.h15
-rw-r--r--xT/xTq.qml105
5 files changed, 67 insertions, 205 deletions
diff --git a/xT/CMakeLists.txt b/xT/CMakeLists.txt
index 562c15a..db2d634 100644
--- a/xT/CMakeLists.txt
+++ b/xT/CMakeLists.txt
@@ -1,4 +1,5 @@
# As per Qt 6.8 documentation, at least 3.16 is necessary
+# CMake 3.21 has RUNTIME_DEPENDENCY_SET.
cmake_minimum_required (VERSION 3.21.1)
file (READ ../xK-version project_version)
@@ -12,10 +13,8 @@ project (xT VERSION "${project_version}"
set (CMAKE_CXX_STANDARD 17)
set (CMAKE_CXX_STANDARD_REQUIRED ON)
-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)
+find_package (Qt6 REQUIRED COMPONENTS Widgets Network Multimedia)
+qt_standard_project_setup ()
add_compile_options ("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
add_compile_options ("$<$<CXX_COMPILER_ID:GNU>:-Wall;-Wextra>")
@@ -49,7 +48,32 @@ foreach (icon xT xT-highlighted)
list (APPEND icon_rsrc_list "${icon_png}")
endforeach ()
-if (APPLE)
+function (android_mipmap_icon svg density size output_dir output)
+ set (_mipmap_dir "${output_dir}/res/mipmap-${density}")
+ set (_png "${_mipmap_dir}/ic_launcher.png")
+ set (${output} "${_png}" PARENT_SCOPE)
+
+ find_program (rsvg_convert_EXECUTABLE rsvg-convert REQUIRED)
+ add_custom_command (OUTPUT "${_png}"
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${_mipmap_dir}"
+ COMMAND ${rsvg_convert_EXECUTABLE} "--output=${_png}"
+ "--width=${size}" "--height=${size}" -- "${svg}"
+ DEPENDS "${svg}"
+ COMMENT "Generating Android ${density} application icon" VERBATIM)
+endfunction ()
+
+if (ANDROID)
+ set (android_base "${PROJECT_BINARY_DIR}/android")
+ set (android_icon_list)
+ foreach (density_size
+ ldpi:36 mdpi:48 hdpi:72 xhdpi:96 xxhdpi:144 xxxhdpi:192)
+ string (REPLACE ":" ";" density_size "${density_size}")
+ android_mipmap_icon ("${PROJECT_SOURCE_DIR}/xT.svg"
+ ${density_size} "${android_base}" android_icon)
+ list (APPEND android_icon_list "${android_icon}")
+ endforeach ()
+ add_custom_target (android-icons ALL DEPENDS ${android_icon_list})
+elseif (APPLE)
set (MACOSX_BUNDLE_ICON_FILE xT.icns)
icon_to_icns ("${PROJECT_SOURCE_DIR}/xT.svg"
"${MACOSX_BUNDLE_ICON_FILE}" icon_icns)
@@ -70,8 +94,9 @@ else ()
set (resource_file "${PROJECT_BINARY_DIR}/xT.rc")
list (APPEND project_sources "${resource_file}")
+ # Qt specifically looks up IDI_ICON1 and nothing else.
add_custom_command (OUTPUT "${resource_file}"
- COMMAND ${CMAKE_COMMAND} -E echo "1 ICON \"xT.ico\""
+ COMMAND ${CMAKE_COMMAND} -E echo "IDI_ICON1 ICON \"xT.ico\""
> ${resource_file} VERBATIM)
set_property (SOURCE "${resource_file}"
APPEND PROPERTY OBJECT_DEPENDS ${icon_ico})
@@ -99,39 +124,46 @@ qt_add_executable (xT
add_dependencies (xT xC-proto)
qt_add_resources (xT "rsrc" PREFIX / FILES "${beep}" ${icon_rsrc_list})
target_link_libraries (xT PRIVATE Qt6::Widgets Qt6::Network Qt6::Multimedia)
-set_target_properties (xT PROPERTIES WIN32_EXECUTABLE ON MACOSX_BUNDLE ON
- MACOSX_BUNDLE_GUI_IDENTIFIER name.janouch.xT)
+set_target_properties (xT PROPERTIES
+ WIN32_EXECUTABLE ON
+ MACOSX_BUNDLE ON
+ MACOSX_BUNDLE_GUI_IDENTIFIER name.janouch.xT
+ QT_ANDROID_APP_NAME xT
+ QT_ANDROID_APP_ICON "@mipmap/ic_launcher"
+ QT_ANDROID_PACKAGE_NAME name.janouch.xT
+ QT_ANDROID_PACKAGE_SOURCE_DIR "${android_base}")
+if (ANDROID)
+ add_dependencies (xT android-icons)
+endif ()
# 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 xTq DESTINATION .)
+ install (TARGETS xT DESTINATION .)
elseif (APPLE OR WIN32)
install (TARGETS xT
+ RUNTIME_DEPENDENCY_SET dependencies_xT
BUNDLE DESTINATION .
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
- # XXX: QTBUG-127075, which can be circumvented by manually running
- # macdeployqt on xT.app before the install.
+ if (WIN32)
+ install (RUNTIME_DEPENDENCY_SET dependencies_xT DIRECTORIES $ENV{PATH}
+ PRE_EXCLUDE_REGEXES "api-ms-win-.*"
+ POST_EXCLUDE_REGEXES ".*[/\\]system32[/\\].*")
+ endif ()
+
qt_generate_deploy_app_script (TARGET xT OUTPUT_SCRIPT deploy_xT)
install (SCRIPT "${deploy_xT}")
+
+ # At least with Homebrew Qt, you will get QTBUG-127075,
+ # which can be circumvented by running macdeployqt twice.
+ if (APPLE)
+ install (SCRIPT "${deploy_xT}")
+ endif ()
else ()
install (TARGETS xT DESTINATION ${CMAKE_INSTALL_BINDIR})
install (FILES ../LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
@@ -144,26 +176,6 @@ else ()
DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
endif ()
-# Within MSYS2, windeployqt doesn't copy the compiler runtime,
-# which is always linked dynamically by the Qt binaries.
-# TODO(p): Consider whether or not to use MSYS2 to cross-compile, and how.
-if (WIN32)
- install (CODE [=[
- set (bindir "${CMAKE_INSTALL_PREFIX}/bin")
- execute_process (COMMAND cygpath -m /
- OUTPUT_VARIABLE cygroot OUTPUT_STRIP_TRAILING_WHITESPACE)
- if (cygroot)
- execute_process (COMMAND ldd "${bindir}/xT.exe"
- OUTPUT_VARIABLE ldd_output OUTPUT_STRIP_TRAILING_WHITESPACE)
- string (REGEX MATCHALL " /mingw64/bin/[^ ]+ " libs "${ldd_output}")
- foreach (lib ${libs})
- string (STRIP "${lib}" lib)
- file (COPY "${cygroot}${lib}" DESTINATION "${bindir}")
- endforeach ()
- endif ()
- ]=])
-endif ()
-
# CPack
set (CPACK_PACKAGE_VENDOR "Premysl Eric Janouch")
set (CPACK_PACKAGE_CONTACT "Přemysl Eric Janouch <p@janouch.name>")
diff --git a/xT/xT.cpp b/xT/xT.cpp
index 72f5892..d82b87b 100644
--- a/xT/xT.cpp
+++ b/xT/xT.cpp
@@ -1,5 +1,5 @@
/*
- * xT.cpp: Qt Widgets frontend for xC
+ * xT.cpp: Qt frontend for xC
*
* Copyright (c) 2024, Přemysl Eric Janouch <p@janouch.name>
*
@@ -180,6 +180,14 @@ beep()
// --- Networking --------------------------------------------------------------
static void
+on_relay_generic_response(
+ std::wstring error, const Relay::ResponseData *response)
+{
+ if (!response)
+ show_error_message(QString::fromStdWString(error));
+}
+
+static void
relay_send(Relay::CommandData *data, Callback callback = {})
{
Relay::CommandMessage m = {};
@@ -190,6 +198,8 @@ relay_send(Relay::CommandData *data, Callback callback = {})
if (callback)
g.command_callbacks[m.command_seq] = std::move(callback);
+ else
+ g.command_callbacks[m.command_seq] = on_relay_generic_response;
auto len = qToBigEndian<uint32_t>(w.data.size());
auto prefix = reinterpret_cast<const char *>(&len);
diff --git a/xT/xTq.cpp b/xT/xTq.cpp
deleted file mode 100644
index a6d48bf..0000000
--- a/xT/xTq.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * xTq.cpp: Qt Quick frontend for xC
- *
- * Copyright (c) 2024, Přemysl Eric Janouch <p@janouch.name>
- *
- * 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 <cstdint>
-
-#include <QGuiApplication>
-#include <QQmlApplicationEngine>
-
-#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
deleted file mode 100644
index 70a0374..0000000
--- a/xT/xTq.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef XTQ_H
-#define XTQ_H
-
-#include <QTcpSocket>
-#include <QtQmlIntegration/qqmlintegration.h>
-
-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
deleted file mode 100644
index 50063c9..0000000
--- a/xT/xTq.qml
+++ /dev/null
@@ -1,105 +0,0 @@
-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()
- }
- }
- }
-}