From ee582df8eefe9bf5692fb7c7abf1f9c1d46decd5 Mon Sep 17 00:00:00 2001 From: Lasan Mahaliyana Date: Mon, 9 Feb 2026 19:43:56 +0530 Subject: [PATCH] Added qml tray app for testing --- sharing/linux/qml_tray_app/CMakeLists.txt | 22 +++- sharing/linux/qml_tray_app/Main.qml | 8 ++ sharing/linux/qml_tray_app/README.md | 38 +++++++ sharing/linux/qml_tray_app/main.cpp | 15 ++- .../qml_tray_app/nearby_tray_controller.cc | 105 ++++++++++++++++++ .../qml_tray_app/nearby_tray_controller.h | 8 ++ sharing/linux/qml_tray_app/resources.qrc | 4 + 7 files changed, 198 insertions(+), 2 deletions(-) diff --git a/sharing/linux/qml_tray_app/CMakeLists.txt b/sharing/linux/qml_tray_app/CMakeLists.txt index 700072c2..6d99fd49 100644 --- a/sharing/linux/qml_tray_app/CMakeLists.txt +++ b/sharing/linux/qml_tray_app/CMakeLists.txt @@ -9,6 +9,7 @@ set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC OFF) find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Qml Quick QuickControls2) +include(GNUInstallDirs) set(REPO_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../..") get_filename_component(REPO_ROOT "${REPO_ROOT}" ABSOLUTE) @@ -128,5 +129,24 @@ add_dependencies(nearby_qml_tray_app bazel_nearby_connections_service_linux) set_target_properties(nearby_qml_tray_app PROPERTIES BUILD_RPATH "${BAZEL_BIN_DIR}/sharing/linux" - INSTALL_RPATH "${BAZEL_BIN_DIR}/sharing/linux" + INSTALL_RPATH "$ORIGIN" ) + +install(TARGETS nearby_qml_tray_app + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" +) + +install(FILES "${BAZEL_NEARBY_SO}" + DESTINATION "${CMAKE_INSTALL_BINDIR}" +) + +qt_generate_deploy_qml_app_script( + TARGET nearby_qml_tray_app + OUTPUT_SCRIPT nearby_qml_tray_app_deploy_script +) +install(SCRIPT "${nearby_qml_tray_app_deploy_script}") + +set(CPACK_GENERATOR "ZIP") +set(CPACK_PACKAGE_NAME "nearby_qml_tray_app") +set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") +include(CPack) diff --git a/sharing/linux/qml_tray_app/Main.qml b/sharing/linux/qml_tray_app/Main.qml index be28a990..b5910846 100644 --- a/sharing/linux/qml_tray_app/Main.qml +++ b/sharing/linux/qml_tray_app/Main.qml @@ -185,6 +185,14 @@ ApplicationWindow { onActivated: nearbyController.mode = currentText } + Label { text: "Incoming" } + CheckBox { + id: autoAcceptIncomingCheckbox + text: "Auto accept" + checked: nearbyController.autoAcceptIncoming + onCheckedChanged: nearbyController.autoAcceptIncoming = checked + } + ColumnLayout { anchors.leftMargin: 30 anchors.rightMargin: 30 diff --git a/sharing/linux/qml_tray_app/README.md b/sharing/linux/qml_tray_app/README.md index aee4d415..883c593d 100644 --- a/sharing/linux/qml_tray_app/README.md +++ b/sharing/linux/qml_tray_app/README.md @@ -72,3 +72,41 @@ If you already have Bazel + Qt 6 dev dependencies installed: ```bash ./sharing/linux/qml_tray_app/build.sh ``` + +## Bundle `libnearby_connections_service_linux_shared.so` with the app + +From `sharing/linux/qml_tray_app`: + +```bash +cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$PWD/dist" +cmake --build build -j +cmake --install build +``` + +Bundle output: + +- `dist/bin/nearby_qml_tray_app` +- `dist/bin/libnearby_connections_service_linux_shared.so` + +The app is installed with `INSTALL_RPATH=$ORIGIN`, so it resolves the Nearby +shared library from the same folder in the bundle. + +## Build a distributable `.zip` (includes runtime dependencies) + +From `sharing/linux/qml_tray_app`: + +```bash +cmake -S . -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build -j +cpack --config build/CPackConfig.cmake -G ZIP +``` + +Output: + +- `build/nearby_qml_tray_app-Linux-x86_64.zip` + +This zip is created from the CMake install tree and includes: + +- `nearby_qml_tray_app` +- `libnearby_connections_service_linux_shared.so` +- Qt runtime libs/plugins/QML imports discovered by Qt deploy tooling diff --git a/sharing/linux/qml_tray_app/main.cpp b/sharing/linux/qml_tray_app/main.cpp index d4a94d70..f1db84cd 100644 --- a/sharing/linux/qml_tray_app/main.cpp +++ b/sharing/linux/qml_tray_app/main.cpp @@ -27,7 +27,20 @@ int main(int argc, char* argv[]) { return 1; } - QIcon tray_icon = QIcon::fromTheme(QStringLiteral("network-wireless")); + // Try custom symbolic icon first (will auto-theme if available) + QIcon tray_icon = QIcon(QStringLiteral(":/icons/tray_icon-symbolic.svg")); + + // Fallback to system themed icon + if (tray_icon.isNull()) { + tray_icon = QIcon::fromTheme(QStringLiteral("network-wireless-symbolic")); + } + + // Fallback to custom PNG icon + if (tray_icon.isNull()) { + tray_icon = QIcon(QStringLiteral(":/icons/tray_icon.png")); + } + + // Final fallback if (tray_icon.isNull()) { tray_icon = app.windowIcon(); } diff --git a/sharing/linux/qml_tray_app/nearby_tray_controller.cc b/sharing/linux/qml_tray_app/nearby_tray_controller.cc index b5960add..1f15d05a 100644 --- a/sharing/linux/qml_tray_app/nearby_tray_controller.cc +++ b/sharing/linux/qml_tray_app/nearby_tray_controller.cc @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -91,6 +92,7 @@ NearbyTrayController::NearbyTrayController(QObject* parent) : QObject(parent) { if (!host.isEmpty()) { device_name_ = host; } + LoadSettings(); ReopenLogFile(); LogLine(QStringLiteral("Started Nearby tray controller")); } @@ -102,6 +104,84 @@ NearbyTrayController::~NearbyTrayController() { } } +void NearbyTrayController::LoadSettings() { + QSettings settings(QStringLiteral("Nearby"), QStringLiteral("QmlTrayApp")); + + const QString stored_mode = + settings.value(QStringLiteral("mode"), mode_).toString(); + mode_ = stored_mode.trimmed().toLower() == QStringLiteral("send") + ? QStringLiteral("Send") + : QStringLiteral("Receive"); + + const QString stored_device_name = + settings.value(QStringLiteral("deviceName"), device_name_) + .toString() + .trimmed(); + if (!stored_device_name.isEmpty()) { + device_name_ = stored_device_name; + } + + const QString stored_service_id = + settings + .value(QStringLiteral("serviceId"), + QString::fromStdString(service_id_)) + .toString() + .trimmed(); + if (!stored_service_id.isEmpty()) { + service_id_ = stored_service_id.toStdString(); + } + + mediums_mode_ = NormalizeMediumsMode( + settings.value(QStringLiteral("mediumsMode"), mediums_mode_).toString()); + bluetooth_enabled_ = settings + .value(QStringLiteral("bluetoothEnabled"), + bluetooth_enabled_) + .toBool(); + ble_enabled_ = settings.value(QStringLiteral("bleEnabled"), ble_enabled_).toBool(); + wifi_lan_enabled_ = settings + .value(QStringLiteral("wifiLanEnabled"), + wifi_lan_enabled_) + .toBool(); + wifi_hotspot_enabled_ = settings + .value(QStringLiteral("wifiHotspotEnabled"), + wifi_hotspot_enabled_) + .toBool(); + web_rtc_enabled_ = + settings.value(QStringLiteral("webRtcEnabled"), web_rtc_enabled_).toBool(); + auto_accept_incoming_ = settings + .value(QStringLiteral("autoAcceptIncoming"), + auto_accept_incoming_) + .toBool(); + connection_strategy_ = NormalizeConnectionStrategy( + settings + .value(QStringLiteral("connectionStrategy"), connection_strategy_) + .toString()); + + const QString stored_log_path = + settings.value(QStringLiteral("logPath"), log_path_).toString().trimmed(); + if (!stored_log_path.isEmpty()) { + log_path_ = stored_log_path; + } +} + +void NearbyTrayController::SaveSettings() const { + QSettings settings(QStringLiteral("Nearby"), QStringLiteral("QmlTrayApp")); + settings.setValue(QStringLiteral("mode"), mode_); + settings.setValue(QStringLiteral("deviceName"), device_name_); + settings.setValue(QStringLiteral("serviceId"), + QString::fromStdString(service_id_)); + settings.setValue(QStringLiteral("mediumsMode"), mediums_mode_); + settings.setValue(QStringLiteral("bluetoothEnabled"), bluetooth_enabled_); + settings.setValue(QStringLiteral("bleEnabled"), ble_enabled_); + settings.setValue(QStringLiteral("wifiLanEnabled"), wifi_lan_enabled_); + settings.setValue(QStringLiteral("wifiHotspotEnabled"), wifi_hotspot_enabled_); + settings.setValue(QStringLiteral("webRtcEnabled"), web_rtc_enabled_); + settings.setValue(QStringLiteral("autoAcceptIncoming"), auto_accept_incoming_); + settings.setValue(QStringLiteral("connectionStrategy"), connection_strategy_); + settings.setValue(QStringLiteral("logPath"), log_path_); + settings.sync(); +} + void NearbyTrayController::setMode(const QString& mode) { const QString normalized = mode.trimmed().toLower() == QStringLiteral("send") @@ -112,6 +192,7 @@ void NearbyTrayController::setMode(const QString& mode) { } mode_ = normalized; emit modeChanged(); + SaveSettings(); LogLine(QStringLiteral("Mode changed to %1").arg(mode_)); if (running_) { stop(); @@ -126,6 +207,7 @@ void NearbyTrayController::setDeviceName(const QString& device_name) { } device_name_ = trimmed; emit deviceNameChanged(); + SaveSettings(); LogLine(QStringLiteral("Device name changed to %1").arg(device_name_)); } @@ -136,6 +218,7 @@ void NearbyTrayController::setServiceId(const QString& service_id) { } service_id_ = value; emit serviceIdChanged(); + SaveSettings(); LogLine(QStringLiteral("Service ID changed to %1") .arg(QString::fromStdString(service_id_))); } @@ -147,6 +230,7 @@ void NearbyTrayController::setMediumsMode(const QString& mode) { } mediums_mode_ = normalized; emit mediumsModeChanged(); + SaveSettings(); LogLine(QStringLiteral("Mediums mode changed to %1").arg(mediums_mode_)); if (running_) { stop(); @@ -160,6 +244,7 @@ void NearbyTrayController::setBluetoothEnabled(bool enabled) { } bluetooth_enabled_ = enabled; emit bluetoothEnabledChanged(); + SaveSettings(); LogLine(QStringLiteral("Bluetooth %1").arg(enabled ? "enabled" : "disabled")); if (running_) { stop(); @@ -173,6 +258,7 @@ void NearbyTrayController::setBleEnabled(bool enabled) { } ble_enabled_ = enabled; emit bleEnabledChanged(); + SaveSettings(); LogLine(QStringLiteral("BLE %1").arg(enabled ? "enabled" : "disabled")); if (running_) { stop(); @@ -186,6 +272,7 @@ void NearbyTrayController::setWifiLanEnabled(bool enabled) { } wifi_lan_enabled_ = enabled; emit wifiLanEnabledChanged(); + SaveSettings(); LogLine(QStringLiteral("WiFi LAN %1").arg(enabled ? "enabled" : "disabled")); if (running_) { stop(); @@ -199,6 +286,7 @@ void NearbyTrayController::setWifiHotspotEnabled(bool enabled) { } wifi_hotspot_enabled_ = enabled; emit wifiHotspotEnabledChanged(); + SaveSettings(); LogLine(QStringLiteral("WiFi Hotspot %1").arg(enabled ? "enabled" : "disabled")); if (running_) { stop(); @@ -212,6 +300,7 @@ void NearbyTrayController::setWebRtcEnabled(bool enabled) { } web_rtc_enabled_ = enabled; emit webRtcEnabledChanged(); + SaveSettings(); LogLine(QStringLiteral("WebRTC %1").arg(enabled ? "enabled" : "disabled")); if (running_) { stop(); @@ -219,6 +308,17 @@ void NearbyTrayController::setWebRtcEnabled(bool enabled) { } } +void NearbyTrayController::setAutoAcceptIncoming(bool enabled) { + if (auto_accept_incoming_ == enabled) { + return; + } + auto_accept_incoming_ = enabled; + emit autoAcceptIncomingChanged(); + SaveSettings(); + LogLine(QStringLiteral("Auto-accept incoming connections %1") + .arg(enabled ? "enabled" : "disabled")); +} + void NearbyTrayController::setConnectionStrategy(const QString& strategy) { const QString normalized = NormalizeConnectionStrategy(strategy); if (connection_strategy_ == normalized) { @@ -226,6 +326,7 @@ void NearbyTrayController::setConnectionStrategy(const QString& strategy) { } connection_strategy_ = normalized; emit connectionStrategyChanged(); + SaveSettings(); LogLine(QStringLiteral("Connection strategy changed to %1") .arg(connection_strategy_)); if (running_) { @@ -241,6 +342,7 @@ void NearbyTrayController::setLogPath(const QString& path) { } log_path_ = trimmed; emit logPathChanged(); + SaveSettings(); ReopenLogFile(); LogLine(QStringLiteral("Log path changed to %1").arg(log_path_)); } @@ -562,6 +664,9 @@ NearbyTrayController::BuildConnectionListener() { AddPendingConnection(endpoint); SetStatus( QStringLiteral("Incoming connection from %1").arg(peer)); + if (auto_accept_incoming_) { + acceptIncoming(endpoint); + } } else { acceptIncoming(endpoint); } diff --git a/sharing/linux/qml_tray_app/nearby_tray_controller.h b/sharing/linux/qml_tray_app/nearby_tray_controller.h index 4b746c5c..545d54c9 100644 --- a/sharing/linux/qml_tray_app/nearby_tray_controller.h +++ b/sharing/linux/qml_tray_app/nearby_tray_controller.h @@ -26,6 +26,7 @@ class NearbyTrayController : public QObject { Q_PROPERTY(bool wifiLanEnabled READ wifiLanEnabled WRITE setWifiLanEnabled NOTIFY wifiLanEnabledChanged) Q_PROPERTY(bool wifiHotspotEnabled READ wifiHotspotEnabled WRITE setWifiHotspotEnabled NOTIFY wifiHotspotEnabledChanged) Q_PROPERTY(bool webRtcEnabled READ webRtcEnabled WRITE setWebRtcEnabled NOTIFY webRtcEnabledChanged) + Q_PROPERTY(bool autoAcceptIncoming READ autoAcceptIncoming WRITE setAutoAcceptIncoming NOTIFY autoAcceptIncomingChanged) Q_PROPERTY(QString connectionStrategy READ connectionStrategy WRITE setConnectionStrategy NOTIFY connectionStrategyChanged) Q_PROPERTY(QString statusMessage READ statusMessage NOTIFY statusMessageChanged) Q_PROPERTY(bool running READ running NOTIFY runningChanged) @@ -67,6 +68,9 @@ class NearbyTrayController : public QObject { bool webRtcEnabled() const { return web_rtc_enabled_; } void setWebRtcEnabled(bool enabled); + bool autoAcceptIncoming() const { return auto_accept_incoming_; } + void setAutoAcceptIncoming(bool enabled); + QString connectionStrategy() const { return connection_strategy_; } void setConnectionStrategy(const QString& strategy); @@ -105,6 +109,7 @@ class NearbyTrayController : public QObject { void wifiLanEnabledChanged(); void wifiHotspotEnabledChanged(); void webRtcEnabledChanged(); + void autoAcceptIncomingChanged(); void connectionStrategyChanged(); void statusMessageChanged(); void runningChanged(); @@ -122,6 +127,8 @@ class NearbyTrayController : public QObject { private: void startSendMode(); void startReceiveMode(); + void LoadSettings(); + void SaveSettings() const; std::vector BuildEndpointInfo() const; @@ -186,6 +193,7 @@ class NearbyTrayController : public QObject { bool wifi_lan_enabled_ = true; bool wifi_hotspot_enabled_ = true; bool web_rtc_enabled_ = false; + bool auto_accept_incoming_ = false; QString log_path_ = QStringLiteral("/tmp/nearby_qml_tray.log"); QFile log_file_; diff --git a/sharing/linux/qml_tray_app/resources.qrc b/sharing/linux/qml_tray_app/resources.qrc index 53f24fa5..741bd3af 100644 --- a/sharing/linux/qml_tray_app/resources.qrc +++ b/sharing/linux/qml_tray_app/resources.qrc @@ -2,4 +2,8 @@ Main.qml + + tray_icon.png + tray_icon-symbolic.svg +