diff options
Diffstat (limited to 'xT')
| -rw-r--r-- | xT/CMakeLists.txt | 100 | ||||
| -rw-r--r-- | xT/xT.cpp | 12 | ||||
| -rw-r--r-- | xT/xTq.cpp | 40 | ||||
| -rw-r--r-- | xT/xTq.h | 15 | ||||
| -rw-r--r-- | xT/xTq.qml | 105 |
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>") @@ -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() - } - } - } -} |
