removed old tray app code

This commit is contained in:
Lasan Mahaliyana
2026-02-28 21:25:22 +05:30
parent 3b2f307fe3
commit 447b15e7b6
7 changed files with 9 additions and 2469 deletions
-34
View File
@@ -49,13 +49,6 @@ set_target_properties(
INTERFACE_INCLUDE_DIRECTORIES "${NEARBY_FACADE_INCLUDE_ROOT}"
)
qt_add_executable(nearby_qml_tray_app
main.cpp
nearby_tray_controller.cc
nearby_tray_controller.h
resources.qrc
)
qt_add_executable(nearby_qml_file_tray_app
file_share_tray_main.cpp
file_share_tray_controller.cc
@@ -63,20 +56,6 @@ qt_add_executable(nearby_qml_file_tray_app
resources_file_share.qrc
)
target_include_directories(nearby_qml_tray_app PRIVATE
"${CMAKE_CURRENT_LIST_DIR}"
"${NEARBY_FACADE_INCLUDE_ROOT}"
)
target_link_libraries(nearby_qml_tray_app PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
Qt6::Qml
Qt6::Quick
Qt6::QuickControls2
nearby_connections_service_linux_installed
)
target_include_directories(nearby_qml_file_tray_app PRIVATE
"${CMAKE_CURRENT_LIST_DIR}"
"${NEARBY_FACADE_INCLUDE_ROOT}"
@@ -93,18 +72,11 @@ target_link_libraries(nearby_qml_file_tray_app PRIVATE
get_filename_component(NEARBY_CONNECTIONS_SHARED_LIB_DIR "${NEARBY_CONNECTIONS_SHARED_LIB}" DIRECTORY)
set_target_properties(nearby_qml_tray_app PROPERTIES
BUILD_RPATH "${NEARBY_CONNECTIONS_SHARED_LIB_DIR}"
INSTALL_RPATH "$ORIGIN"
)
set_target_properties(nearby_qml_file_tray_app PROPERTIES
BUILD_RPATH "${NEARBY_CONNECTIONS_SHARED_LIB_DIR}"
INSTALL_RPATH "$ORIGIN"
)
install(TARGETS nearby_qml_tray_app
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
)
install(TARGETS nearby_qml_file_tray_app
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
)
@@ -113,12 +85,6 @@ install(FILES "${NEARBY_CONNECTIONS_SHARED_LIB}"
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}")
qt_generate_deploy_qml_app_script(
TARGET nearby_qml_file_tray_app
OUTPUT_SCRIPT nearby_qml_file_tray_app_deploy_script
-858
View File
@@ -1,858 +0,0 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
ApplicationWindow {
id: root
width: 1200
height: 820
minimumWidth: 980
minimumHeight: 700
visible: true
title: "Nearby QML Tray"
property string apiEndpointId: ""
property string apiPayloadText: ""
property string queryMediumResult: "-"
property string queryPeerResult: "-"
readonly property color appBg: "#f5f6f8"
readonly property color surface: "#ffffff"
readonly property color border: "#d7dbe0"
readonly property color textPrimary: "#1f2328"
readonly property color textMuted: "#59636e"
palette.window: appBg
palette.base: surface
palette.button: "#f0f3f7"
palette.text: textPrimary
palette.windowText: textPrimary
palette.buttonText: textPrimary
palette.placeholderText: textMuted
palette.highlight: "#2f6feb"
palette.highlightedText: "#ffffff"
background: Rectangle {
color: root.appBg
}
ListModel {
id: connectedEndpointsModel
}
ListModel {
id: payloadEventsModel
}
function endpointLabel(endpointId) {
var label = nearbyController.peerNameForEndpoint(endpointId)
if (!label || label.length === 0 || label === "Unknown device") {
return "Unknown device"
}
return label
}
function formatBytes(bytes) {
if (bytes === undefined || bytes === null) {
return "0 B"
}
var value = Number(bytes)
if (!isFinite(value) || value < 0) {
return "0 B"
}
var units = ["B", "KB", "MB", "GB", "TB"]
var unit = 0
while (value >= 1024 && unit < units.length - 1) {
value /= 1024
unit += 1
}
return (value >= 10 || unit === 0 ? value.toFixed(0) : value.toFixed(1)) + " " + units[unit]
}
function refreshConnectedEndpointsModel() {
var selectedId = targetCombo.currentValue ? String(targetCombo.currentValue) : ""
connectedEndpointsModel.clear()
var devices = nearbyController.connectedDevices
for (var i = 0; i < devices.length; ++i) {
var endpointId = String(devices[i])
connectedEndpointsModel.append({
"endpointId": endpointId,
"label": endpointLabel(endpointId)
})
}
var nextIndex = -1
for (var j = 0; j < connectedEndpointsModel.count; ++j) {
if (connectedEndpointsModel.get(j).endpointId === selectedId) {
nextIndex = j
break
}
}
if (nextIndex < 0 && connectedEndpointsModel.count > 0) {
nextIndex = 0
}
targetCombo.currentIndex = nextIndex
}
onClosing: function(close) {
close.accepted = false
root.hide()
nearbyController.hideToTray()
}
header: ToolBar {
height: 54
// background: Rectangle {
// color: root.surface
// border.color: root.border
// }
RowLayout {
anchors.fill: parent
anchors.leftMargin: 12
anchors.rightMargin: 12
spacing: 10
Label {
text: "Nearby Control"
font.bold: true
font.pixelSize: 18
color: root.textPrimary
}
Item { Layout.fillWidth: true }
Label {
text: nearbyController.running ? "Running" : "Stopped"
color: nearbyController.running ? "#1f7a1f" : "#a33"
font.bold: true
}
Button {
text: nearbyController.running ? "Stop" : "Start"
onClicked: {
if (nearbyController.running) {
nearbyController.stop()
} else {
nearbyController.start()
}
}
}
Button {
text: "Hide To Tray"
onClicked: {
root.hide()
nearbyController.hideToTray()
}
}
}
}
ColumnLayout {
anchors.fill: parent
anchors.margins: 12
spacing: 10
Frame {
Layout.fillWidth: true
padding: 10
background: Rectangle {
color: root.surface
border.color: root.border
radius: 6
}
ColumnLayout {
anchors.fill: parent
spacing: 8
Label {
text: "Settings"
font.bold: true
}
GridLayout {
Layout.fillWidth: true
columns: 8
columnSpacing: 8
rowSpacing: 8
Label { text: "Mode" }
ComboBox {
id: modeCombo
model: ["Receive", "Send"]
currentIndex: nearbyController.mode === "Send" ? 1 : 0
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
Label {
anchors.fill : parent
text: "Mediums"
Layout.alignment: Qt.AlignTop
horizontalAlignment: Text.AlignHCenter
topPadding: 6
}
RowLayout {
spacing: 4
CheckBox {
id: bluetoothCheckbox
text: "Bluetooth"
checked: nearbyController.bluetoothEnabled
onCheckedChanged: nearbyController.bluetoothEnabled = checked
}
CheckBox {
id: bleCheckbox
text: "BLE"
checked: nearbyController.bleEnabled
onCheckedChanged: nearbyController.bleEnabled = checked
}
CheckBox {
id: wifiLanCheckbox
text: "WiFi LAN"
checked: nearbyController.wifiLanEnabled
onCheckedChanged: nearbyController.wifiLanEnabled = checked
}
CheckBox {
id: wifiHotspotCheckbox
text: "WiFi Hotspot"
checked: nearbyController.wifiHotspotEnabled
onCheckedChanged: nearbyController.wifiHotspotEnabled = checked
}
CheckBox {
id: webRtcCheckbox
text: "WebRTC"
checked: nearbyController.webRtcEnabled
onCheckedChanged: nearbyController.webRtcEnabled = checked
}
}
}
Label { text: "Strategy" }
ComboBox {
id: strategyCombo
Layout.preferredWidth: 170
model: ["P2pCluster", "P2pStar", "P2pPointToPoint"]
currentIndex: {
var strategy = String(nearbyController.connectionStrategy)
if (strategy === "P2pStar")
return 1
if (strategy === "P2pPointToPoint")
return 2
return 0
}
onActivated: nearbyController.connectionStrategy = currentText
}
Label { text: "Device" }
TextField {
Layout.preferredWidth: 180
text: nearbyController.deviceName
onEditingFinished: nearbyController.deviceName = text
}
Label { text: "Service ID" }
TextField {
Layout.fillWidth: true
Layout.columnSpan: 3
text: nearbyController.serviceId
onEditingFinished: nearbyController.serviceId = text
}
Label { text: "Log Path" }
TextField {
Layout.fillWidth: true
Layout.columnSpan: 7
text: nearbyController.logPath
onEditingFinished: nearbyController.logPath = text
}
}
Label {
Layout.fillWidth: true
text: "Status: " + nearbyController.statusMessage
elide: Text.ElideRight
}
}
}
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 10
Frame {
Layout.fillHeight: true
Layout.preferredWidth: 420
padding: 10
background: Rectangle {
color: root.surface
border.color: root.border
radius: 6
}
ColumnLayout {
anchors.fill: parent
spacing: 10
Label {
text: "API Controls"
font.bold: true
}
Frame {
Layout.fillWidth: true
Layout.preferredHeight: 150
padding: 6
background: Rectangle {
color: root.surface
border.color: root.border
radius: 4
}
ColumnLayout {
anchors.fill: parent
spacing: 4
Label {
text: "Incoming Requests"
font.bold: true
}
ListView {
id: incomingRequestsList
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
spacing: 4
model: nearbyController.pendingConnections
delegate: Rectangle {
required property string modelData
width: incomingRequestsList.width
height: 38
color: root.surface
border.color: root.border
radius: 4
RowLayout {
anchors.fill: parent
anchors.leftMargin: 6
anchors.rightMargin: 6
spacing: 6
Label {
Layout.fillWidth: true
text: root.endpointLabel(modelData)
elide: Text.ElideRight
}
Button {
text: "Accept"
onClicked: nearbyController.acceptIncoming(modelData)
}
Button {
text: "Reject"
onClicked: nearbyController.rejectIncoming(modelData)
}
}
}
}
}
}
TextField {
id: endpointField
Layout.fillWidth: true
Layout.minimumWidth: 0
placeholderText: "Endpoint ID (advanced)"
text: root.apiEndpointId
onTextChanged: root.apiEndpointId = text
}
GridLayout {
Layout.fillWidth: true
columns: 2
columnSpacing: 6
rowSpacing: 6
Button {
text: "Connect"
Layout.fillWidth: true
enabled: endpointField.text.trim().length > 0
onClicked: nearbyController.connectToDevice(endpointField.text.trim())
}
Button {
text: "Disconnect"
Layout.fillWidth: true
enabled: endpointField.text.trim().length > 0
onClicked: nearbyController.disconnectDevice(endpointField.text.trim())
}
Button {
text: "Accept"
Layout.fillWidth: true
enabled: endpointField.text.trim().length > 0
onClicked: nearbyController.acceptIncoming(endpointField.text.trim())
}
Button {
text: "Reject"
Layout.fillWidth: true
enabled: endpointField.text.trim().length > 0
onClicked: nearbyController.rejectIncoming(endpointField.text.trim())
}
}
RowLayout {
Layout.fillWidth: true
spacing: 6
ComboBox {
id: targetCombo
Layout.fillWidth: true
Layout.minimumWidth: 0
model: connectedEndpointsModel
textRole: "label"
valueRole: "endpointId"
displayText: currentIndex >= 0 ? currentText : "Select connected device"
}
Button {
text: "Use ID"
enabled: targetCombo.currentValue !== undefined && targetCombo.currentValue !== null
onClicked: {
endpointField.text = String(targetCombo.currentValue)
root.apiEndpointId = endpointField.text
}
}
}
TextField {
id: payloadField
Layout.fillWidth: true
Layout.minimumWidth: 0
placeholderText: "Text payload"
text: root.apiPayloadText
onTextChanged: root.apiPayloadText = text
}
GridLayout {
Layout.fillWidth: true
columns: 2
columnSpacing: 6
rowSpacing: 6
Button {
text: "Send Text"
Layout.fillWidth: true
enabled: endpointField.text.trim().length > 0 && payloadField.text.length > 0
onClicked: nearbyController.sendText(endpointField.text.trim(), payloadField.text)
}
Button {
text: "Get Medium"
Layout.fillWidth: true
enabled: endpointField.text.trim().length > 0
onClicked: root.queryMediumResult = nearbyController.mediumForEndpoint(endpointField.text.trim())
}
Button {
text: "Upgrade Bandwidth"
Layout.fillWidth: true
enabled: endpointField.text.trim().length > 0
onClicked: nearbyController.initiateBandwidthUpgrade(endpointField.text.trim())
}
Button {
text: "Get Peer Name"
Layout.fillWidth: true
enabled: endpointField.text.trim().length > 0
onClicked: root.queryPeerResult = nearbyController.peerNameForEndpoint(endpointField.text.trim())
}
}
GridLayout {
Layout.fillWidth: true
columns: 2
columnSpacing: 8
Label { text: "Medium" }
Label {
text: root.queryMediumResult
Layout.fillWidth: true
elide: Text.ElideRight
}
Label { text: "Peer" }
Label {
text: root.queryPeerResult
Layout.fillWidth: true
elide: Text.ElideRight
}
}
GridLayout {
Layout.fillWidth: true
columns: 2
columnSpacing: 6
Button {
text: "Clear Transfers"
Layout.fillWidth: true
onClicked: nearbyController.clearTransfers()
}
Button {
text: "Hide To Tray"
Layout.fillWidth: true
onClicked: {
root.hide()
nearbyController.hideToTray()
}
}
}
Label {
text: "Payload Events"
font.bold: true
}
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
model: payloadEventsModel
spacing: 4
delegate: Rectangle {
required property var model
width: ListView.view.width
height: 44
color: root.surface
border.color: root.border
radius: 4
ColumnLayout {
anchors.fill: parent
anchors.leftMargin: 6
anchors.rightMargin: 6
spacing: 0
Label {
Layout.fillWidth: true
text: model.peer
font.bold: true
elide: Text.ElideRight
}
Label {
Layout.fillWidth: true
text: model.type + ": " + model.value
elide: Text.ElideRight
}
}
}
}
}
}
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 10
Frame {
Layout.fillWidth: true
Layout.preferredHeight: 320
padding: 8
background: Rectangle {
color: root.surface
border.color: root.border
radius: 6
}
ColumnLayout {
anchors.fill: parent
spacing: 6
Label {
text: "Endpoints"
font.bold: true
}
TabBar {
id: endpointTabs
Layout.fillWidth: true
TabButton { text: "Discovered" }
TabButton { text: "Pending" }
TabButton { text: "Connected" }
}
StackLayout {
Layout.fillWidth: true
Layout.fillHeight: true
currentIndex: endpointTabs.currentIndex
ListView {
id: discoveredList
clip: true
spacing: 4
model: nearbyController.discoveredDevices
delegate: Rectangle {
required property string modelData
width: discoveredList.width
height: 42
color: root.surface
border.color: root.border
radius: 4
RowLayout {
anchors.fill: parent
anchors.leftMargin: 8
anchors.rightMargin: 8
Label {
Layout.fillWidth: true
text: root.endpointLabel(modelData)
elide: Text.ElideRight
}
Button {
text: "Use"
onClicked: {
endpointField.text = modelData
root.apiEndpointId = modelData
}
}
Button {
text: "Connect"
onClicked: nearbyController.connectToDevice(modelData)
}
}
}
}
ListView {
id: pendingList
clip: true
spacing: 4
model: nearbyController.pendingConnections
delegate: Rectangle {
required property string modelData
width: pendingList.width
height: 42
color: root.surface
border.color: root.border
radius: 4
RowLayout {
anchors.fill: parent
anchors.leftMargin: 8
anchors.rightMargin: 8
Label {
Layout.fillWidth: true
text: root.endpointLabel(modelData)
elide: Text.ElideRight
}
Button {
text: "Use"
onClicked: {
endpointField.text = modelData
root.apiEndpointId = modelData
}
}
Button {
text: "Accept"
onClicked: nearbyController.acceptIncoming(modelData)
}
Button {
text: "Reject"
onClicked: nearbyController.rejectIncoming(modelData)
}
}
}
}
ListView {
id: connectedList
clip: true
spacing: 4
model: nearbyController.connectedDevices
delegate: Rectangle {
required property string modelData
width: connectedList.width
height: 46
color: root.surface
border.color: root.border
radius: 4
RowLayout {
anchors.fill: parent
anchors.leftMargin: 8
anchors.rightMargin: 8
Label {
Layout.fillWidth: true
text: root.endpointLabel(modelData)
elide: Text.ElideRight
}
Label {
text: nearbyController.mediumForEndpoint(modelData)
}
Button {
text: "Use"
onClicked: {
endpointField.text = modelData
root.apiEndpointId = modelData
}
}
Button {
text: "Disconnect"
onClicked: nearbyController.disconnectDevice(modelData)
}
}
}
}
}
}
}
Frame {
Layout.fillWidth: true
Layout.fillHeight: true
padding: 8
background: Rectangle {
color: root.surface
border.color: root.border
radius: 6
}
ColumnLayout {
anchors.fill: parent
spacing: 6
RowLayout {
Layout.fillWidth: true
Label {
text: "Transfers"
font.bold: true
}
Item { Layout.fillWidth: true }
Button {
text: "Clear"
onClicked: nearbyController.clearTransfers()
}
}
ListView {
id: transferList
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
spacing: 6
model: nearbyController.transfers
delegate: Rectangle {
required property var modelData
width: transferList.width
height: 86
color: root.surface
border.color: root.border
radius: 4
ColumnLayout {
anchors.fill: parent
anchors.leftMargin: 8
anchors.rightMargin: 8
spacing: 4
RowLayout {
Layout.fillWidth: true
Label {
Layout.fillWidth: true
text: modelData.direction + " | " + root.endpointLabel(modelData.endpointId) + " | payload " + modelData.payloadId
elide: Text.ElideRight
}
Label { text: modelData.status }
Label { text: modelData.medium }
}
ProgressBar {
Layout.fillWidth: true
from: 0
to: 1
value: modelData.progress
}
Label {
Layout.fillWidth: true
horizontalAlignment: Text.AlignRight
text: root.formatBytes(modelData.bytesTransferred) + " / " + root.formatBytes(modelData.totalBytes)
color: root.textMuted
}
}
}
}
}
}
}
}
}
Connections {
target: nearbyController
function onConnectedDevicesChanged() {
root.refreshConnectedEndpointsModel()
}
function onPendingConnectionsChanged() {
if (nearbyController.pendingConnections.length > 0) {
endpointTabs.currentIndex = 1
}
}
function onPayloadReceived(endpoint_id, type, value) {
payloadEventsModel.insert(0, {
"peer": root.endpointLabel(endpoint_id),
"type": type,
"value": String(value)
})
if (payloadEventsModel.count > 200) {
payloadEventsModel.remove(payloadEventsModel.count - 1)
}
}
function onModeChanged() {
modeCombo.currentIndex = nearbyController.mode === "Send" ? 1 : 0
}
}
Component.onCompleted: refreshConnectedEndpointsModel()
}
+9 -8
View File
@@ -1,6 +1,6 @@
# Nearby QML Tray App
# Nearby File Share Tray App
This folder contains a Qt/QML tray application backend and UI wired to:
This folder contains the Qt/QML **FileShareTray** application — a system tray app for file sharing via Nearby Connections, wired to:
- `nearby::sharing::linux::NearbyConnectionsServiceLinux`
- Send mode (discovery + connect)
@@ -12,10 +12,11 @@ This folder contains a Qt/QML tray application backend and UI wired to:
## Files
- `main.cpp`: Qt app bootstrap + system tray behavior.
- `nearby_tray_controller.h/.cc`: QML-facing backend wrapper around Nearby Connections.
- `Main.qml`: UI for send/receive workflows and transfer monitoring.
- `resources.qrc`: embeds `Main.qml`.
- `file_share_tray_main.cpp`: Qt app bootstrap + system tray behavior.
- `file_share_tray_controller.h/.cc`: QML-facing backend wrapper around Nearby Connections.
- `FileShareTray.qml`: Top-level UI for the file share tray app.
- `components/`: Shared QML UI components used by `FileShareTray.qml`.
- `resources_file_share.qrc`: Embeds `FileShareTray.qml` and components.
## Runtime behavior
@@ -64,7 +65,7 @@ cmake --install build
Bundle output:
- `dist/bin/nearby_qml_tray_app`
- `dist/bin/nearby_qml_file_tray_app`
- `dist/bin/libnearby_connections_service_linux_shared.so`
The app is installed with `INSTALL_RPATH=$ORIGIN`, so it resolves the Nearby
@@ -86,6 +87,6 @@ Output:
This zip is created from the CMake install tree and includes:
- `nearby_qml_tray_app`
- `nearby_qml_file_tray_app`
- `libnearby_connections_service_linux_shared.so`
- Qt runtime libs/plugins/QML imports discovered by Qt deploy tooling
-143
View File
@@ -1,143 +0,0 @@
#include <QAction>
#include <QApplication>
#include <QIcon>
#include <QMenu>
#include <QPainter>
#include <QPalette>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickWindow>
#include <QStyleHints>
#include <QSystemTrayIcon>
#include "nearby_tray_controller.h"
namespace {
QIcon BuildTintedSymbolicIcon(const QString& source, const QColor& color) {
QIcon source_icon(source);
if (source_icon.isNull()) {
return QIcon();
}
QIcon tinted_icon;
for (int size : {16, 18, 20, 22, 24, 32}) {
QPixmap pixmap = source_icon.pixmap(size, size);
if (pixmap.isNull()) {
continue;
}
QPixmap tinted(pixmap.size());
tinted.fill(Qt::transparent);
QPainter painter(&tinted);
painter.drawPixmap(0, 0, pixmap);
painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
painter.fillRect(tinted.rect(), color);
painter.end();
tinted_icon.addPixmap(tinted);
}
return tinted_icon;
}
} // namespace
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
app.setQuitOnLastWindowClosed(false);
NearbyTrayController controller;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("nearbyController", &controller);
engine.load(QUrl(QStringLiteral("qrc:/qml/Main.qml")));
if (engine.rootObjects().isEmpty()) {
return 1;
}
auto* window = qobject_cast<QQuickWindow*>(engine.rootObjects().first());
if (window == nullptr) {
return 1;
}
const auto resolve_tray_icon = [&app]() {
// Render the bundled symbolic icon with palette text color so it adapts to light/dark themes.
const QColor symbolic_color = app.palette().color(QPalette::WindowText);
QIcon tray_icon = BuildTintedSymbolicIcon(
QStringLiteral(":/icons/tray_icon-symbolic.svg"), symbolic_color);
// 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();
}
return tray_icon;
};
QIcon tray_icon = resolve_tray_icon();
QSystemTrayIcon tray(tray_icon);
tray.setToolTip(QStringLiteral("Nearby QML Tray"));
QMenu tray_menu;
QAction* show_action = tray_menu.addAction(QStringLiteral("Show"));
QAction* hide_action = tray_menu.addAction(QStringLiteral("Hide"));
tray_menu.addSeparator();
QAction* quit_action = tray_menu.addAction(QStringLiteral("Quit"));
QObject::connect(show_action, &QAction::triggered, window, [window]() {
window->show();
window->raise();
window->requestActivate();
});
QObject::connect(hide_action, &QAction::triggered, window, [window]() {
window->hide();
});
QObject::connect(quit_action, &QAction::triggered, &app, [&controller, &app]() {
controller.stop();
app.quit();
});
QObject::connect(&tray, &QSystemTrayIcon::activated, window,
[&tray, window](QSystemTrayIcon::ActivationReason reason) {
if (reason != QSystemTrayIcon::Trigger &&
reason != QSystemTrayIcon::DoubleClick) {
return;
}
if (window->isVisible()) {
window->hide();
} else {
window->show();
window->raise();
window->requestActivate();
}
});
QObject::connect(&controller, &NearbyTrayController::requestTrayMessage, &tray,
[&tray](const QString& title, const QString& body) {
tray.showMessage(title, body, QSystemTrayIcon::Information,
3000);
});
QObject::connect(&app, &QCoreApplication::aboutToQuit, &controller,
[&controller]() { controller.stop(); });
QObject::connect(app.styleHints(), &QStyleHints::colorSchemeChanged, &tray,
[&tray, &resolve_tray_icon](Qt::ColorScheme) {
tray.setIcon(resolve_tray_icon());
});
tray.setContextMenu(&tray_menu);
tray.show();
return app.exec();
}
File diff suppressed because it is too large Load Diff
@@ -1,204 +0,0 @@
#ifndef SHARING_LINUX_QML_TRAY_APP_NEARBY_TRAY_CONTROLLER_H_
#define SHARING_LINUX_QML_TRAY_APP_NEARBY_TRAY_CONTROLLER_H_
#include <QObject>
#include <QFile>
#include <QHash>
#include <QString>
#include <QStringList>
#include <QVariantList>
#include <QVariantMap>
#include <string>
#include <vector>
#include "sharing/linux/nearby_connections_qt_facade.h"
using NearbyConnectionsQtFacade = nearby::sharing::NearbyConnectionsQtFacade;
class NearbyTrayController : public QObject {
Q_OBJECT
Q_PROPERTY(QString mode READ mode WRITE setMode NOTIFY modeChanged)
Q_PROPERTY(QString deviceName READ deviceName WRITE setDeviceName NOTIFY deviceNameChanged)
Q_PROPERTY(QString serviceId READ serviceId WRITE setServiceId NOTIFY serviceIdChanged)
Q_PROPERTY(QString mediumsMode READ mediumsMode WRITE setMediumsMode NOTIFY mediumsModeChanged)
Q_PROPERTY(bool bluetoothEnabled READ bluetoothEnabled WRITE setBluetoothEnabled NOTIFY bluetoothEnabledChanged)
Q_PROPERTY(bool bleEnabled READ bleEnabled WRITE setBleEnabled NOTIFY bleEnabledChanged)
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)
Q_PROPERTY(QString logPath READ logPath WRITE setLogPath NOTIFY logPathChanged)
Q_PROPERTY(QStringList discoveredDevices READ discoveredDevices NOTIFY discoveredDevicesChanged)
Q_PROPERTY(QStringList connectedDevices READ connectedDevices NOTIFY connectedDevicesChanged)
Q_PROPERTY(QStringList pendingConnections READ pendingConnections NOTIFY pendingConnectionsChanged)
Q_PROPERTY(QVariantMap endpointMediums READ endpointMediums NOTIFY endpointMediumsChanged)
Q_PROPERTY(QVariantList transfers READ transfers NOTIFY transfersChanged)
public:
explicit NearbyTrayController(QObject* parent = nullptr);
~NearbyTrayController() override;
QString mode() const { return mode_; }
void setMode(const QString& mode);
QString deviceName() const { return device_name_; }
void setDeviceName(const QString& device_name);
QString serviceId() const { return QString::fromStdString(service_id_); }
void setServiceId(const QString& service_id);
QString mediumsMode() const { return mediums_mode_; }
void setMediumsMode(const QString& mode);
bool bluetoothEnabled() const { return bluetooth_enabled_; }
void setBluetoothEnabled(bool enabled);
bool bleEnabled() const { return ble_enabled_; }
void setBleEnabled(bool enabled);
bool wifiLanEnabled() const { return wifi_lan_enabled_; }
void setWifiLanEnabled(bool enabled);
bool wifiHotspotEnabled() const { return wifi_hotspot_enabled_; }
void setWifiHotspotEnabled(bool enabled);
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);
QString statusMessage() const { return status_message_; }
bool running() const { return running_; }
QString logPath() const { return log_path_; }
void setLogPath(const QString& path);
QStringList discoveredDevices() const { return discovered_devices_; }
QStringList connectedDevices() const { return connected_devices_; }
QStringList pendingConnections() const { return pending_connections_; }
QVariantMap endpointMediums() const { return endpoint_mediums_; }
QVariantList transfers() const { return transfers_; }
Q_INVOKABLE void start();
Q_INVOKABLE void stop();
Q_INVOKABLE void connectToDevice(const QString& endpoint_id);
Q_INVOKABLE void disconnectDevice(const QString& endpoint_id);
Q_INVOKABLE void acceptIncoming(const QString& endpoint_id);
Q_INVOKABLE void rejectIncoming(const QString& endpoint_id);
Q_INVOKABLE void sendText(const QString& endpoint_id, const QString& text);
Q_INVOKABLE void initiateBandwidthUpgrade(const QString& endpoint_id);
Q_INVOKABLE QString mediumForEndpoint(const QString& endpoint_id) const;
Q_INVOKABLE QString peerNameForEndpoint(const QString& endpoint_id) const;
Q_INVOKABLE void clearTransfers();
Q_INVOKABLE void hideToTray();
signals:
void modeChanged();
void deviceNameChanged();
void serviceIdChanged();
void mediumsModeChanged();
void bluetoothEnabledChanged();
void bleEnabledChanged();
void wifiLanEnabledChanged();
void wifiHotspotEnabledChanged();
void webRtcEnabledChanged();
void autoAcceptIncomingChanged();
void connectionStrategyChanged();
void statusMessageChanged();
void runningChanged();
void logPathChanged();
void discoveredDevicesChanged();
void connectedDevicesChanged();
void pendingConnectionsChanged();
void endpointMediumsChanged();
void transfersChanged();
void payloadReceived(const QString& endpoint_id, const QString& type,
const QString& value);
void requestTrayMessage(const QString& title, const QString& body);
private:
void startSendMode();
void startReceiveMode();
void LoadSettings();
void SaveSettings() const;
std::vector<uint8_t> BuildEndpointInfo() const;
NearbyConnectionsQtFacade::ConnectionListener BuildConnectionListener();
NearbyConnectionsQtFacade::DiscoveryListener BuildDiscoveryListener();
NearbyConnectionsQtFacade::PayloadListener BuildPayloadListener();
NearbyConnectionsQtFacade::AdvertisingOptions BuildAdvertisingOptions() const;
NearbyConnectionsQtFacade::DiscoveryOptions BuildDiscoveryOptions() const;
NearbyConnectionsQtFacade::ConnectionOptions BuildConnectionOptions() const;
NearbyConnectionsQtFacade::MediumSelection BuildMediumSelection() const;
void AddDiscoveredDevice(const QString& endpoint_id);
void RemoveDiscoveredDevice(const QString& endpoint_id);
void AddConnectedDevice(const QString& endpoint_id);
void RemoveConnectedDevice(const QString& endpoint_id);
void AddPendingConnection(const QString& endpoint_id);
void RemovePendingConnection(const QString& endpoint_id);
void SetPeerNameForEndpoint(const QString& endpoint_id,
const QString& peer_name);
QString PeerLabelForEndpoint(const QString& endpoint_id) const;
QString FinalizeReceivedFilePath(const QString& received_path,
const QString& received_file_name,
qlonglong payload_id) const;
void UpsertTransfer(const QString& endpoint_id, qlonglong payload_id,
const QString& status, qulonglong bytes_transferred,
qulonglong total_bytes, const QString& direction);
void UpdateTransferMediumForEndpoint(const QString& endpoint_id,
const QString& medium);
void SetStatus(const QString& status);
void LogLine(const QString& line);
void ReopenLogFile();
static QString StatusToString(NearbyConnectionsQtFacade::Status status);
static QString PayloadStatusToString(
NearbyConnectionsQtFacade::PayloadStatus status);
static QString MediumToString(NearbyConnectionsQtFacade::Medium medium);
NearbyConnectionsQtFacade service_;
QString mode_ = QStringLiteral("Receive");
QString device_name_ = QStringLiteral("NearbyQt");
std::string service_id_ = "com.nearby.qml.tray";
QString mediums_mode_ = QStringLiteral("balanced");
QString connection_strategy_ = QStringLiteral("P2pCluster");
QString status_message_ = QStringLiteral("Idle");
bool running_ = false;
bool bluetooth_enabled_ = true;
bool ble_enabled_ = true;
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_;
QStringList discovered_devices_;
QStringList connected_devices_;
QStringList pending_connections_;
QHash<QString, QString> endpoint_peer_names_;
QVariantMap endpoint_mediums_;
QVariantList transfers_;
QHash<qlonglong, int> transfer_row_for_payload_;
QHash<QString, QString> pending_file_names_;
};
#endif // SHARING_LINUX_QML_TRAY_APP_NEARBY_TRAY_CONTROLLER_H_
-9
View File
@@ -1,9 +0,0 @@
<RCC>
<qresource prefix="/qml">
<file>Main.qml</file>
</qresource>
<qresource prefix="/icons">
<file>tray_icon.png</file>
<file alias="tray_icon-symbolic.svg">tray_icon-symbolic.svg</file>
</qresource>
</RCC>