Added settings tray

This commit is contained in:
Lasan Mahaliyana
2026-02-25 23:24:08 +05:30
parent 05062f69f3
commit d6ad048d97
5 changed files with 230 additions and 13 deletions
+7 -1
View File
@@ -21,11 +21,17 @@ ApplicationWindow {
fileShareController.hideToTray()
}
SettingsPanel {
id: settingsPanel
}
ColumnLayout {
anchors.fill: parent
spacing: 0
AppHeader {}
AppHeader {
onSettingsRequested: settingsPanel.open()
}
// ── Body ─────────────────────────────────────────────────────────
RowLayout {
@@ -6,6 +6,8 @@ Item {
Layout.fillWidth: true
height: 80
signal settingsRequested()
readonly property color textPrimary: "#111827"
readonly property color textMuted: "#6b7280"
readonly property color accent: "#16a34a"
@@ -60,5 +62,28 @@ Item {
onClicked: fileShareController.running ? fileShareController.stop() : fileShareController.start()
}
}
Rectangle {
width: 40
height: 40
radius: 12
color: settingsBtn.containsMouse ? "#dcfce7" : "transparent"
border.color: settingsBtn.containsMouse ? "#86efac" : "transparent"
Label {
anchors.centerIn: parent
text: "⚙"
font.pixelSize: 18
color: settingsBtn.containsMouse ? accent : textMuted
}
MouseArea {
id: settingsBtn
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: settingsRequested()
}
}
}
}
@@ -23,6 +23,30 @@ bool IsTerminalPayloadStatus(NearbyConnectionsQtFacade::PayloadStatus status) {
status == NearbyConnectionsQtFacade::PayloadStatus::kCanceled;
}
QString NormalizeConnectionStrategy(const QString& strategy) {
const QString token = strategy.trimmed().toLower();
if (token == QStringLiteral("p2pstar") || token == QStringLiteral("star")) {
return QStringLiteral("P2pStar");
}
if (token == QStringLiteral("p2ppointtopoint") ||
token == QStringLiteral("pointtopoint") ||
token == QStringLiteral("point_to_point")) {
return QStringLiteral("P2pPointToPoint");
}
return QStringLiteral("P2pCluster");
}
NearbyConnectionsQtFacade::Strategy StrategyFromName(
const QString& normalized_strategy) {
if (normalized_strategy == QStringLiteral("P2pStar")) {
return NearbyConnectionsQtFacade::Strategy::kP2pStar;
}
if (normalized_strategy == QStringLiteral("P2pPointToPoint")) {
return NearbyConnectionsQtFacade::Strategy::kP2pPointToPoint;
}
return NearbyConnectionsQtFacade::Strategy::kP2pCluster;
}
} // namespace
FileShareTrayController::FileShareTrayController(QObject* parent)
@@ -54,11 +78,49 @@ void FileShareTrayController::LoadSettings() {
if (!stored_device_name.isEmpty()) {
device_name_ = stored_device_name;
}
auto_accept_incoming_ =
settings.value(QStringLiteral("autoAcceptIncoming"), auto_accept_incoming_)
.toBool();
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();
connection_strategy_ = NormalizeConnectionStrategy(
settings.value(QStringLiteral("connectionStrategy"), connection_strategy_)
.toString());
const QString stored_service_id =
settings.value(QStringLiteral("serviceId"), serviceId()).toString().trimmed();
if (!stored_service_id.isEmpty()) {
service_id_ = stored_service_id.toStdString();
}
const QString stored_log_path =
settings.value(QStringLiteral("logPath"), log_path_).toString().trimmed();
if (!stored_log_path.isEmpty()) {
log_path_ = stored_log_path;
}
}
void FileShareTrayController::SaveSettings() const {
QSettings settings(QStringLiteral("Nearby"), QStringLiteral("QmlFileTrayApp"));
settings.setValue(QStringLiteral("deviceName"), device_name_);
settings.setValue(QStringLiteral("autoAcceptIncoming"), auto_accept_incoming_);
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("connectionStrategy"), connection_strategy_);
settings.setValue(QStringLiteral("serviceId"), serviceId());
settings.setValue(QStringLiteral("logPath"), log_path_);
settings.sync();
}
@@ -79,6 +141,73 @@ void FileShareTrayController::setDeviceName(const QString& device_name) {
}
}
void FileShareTrayController::setAutoAcceptIncoming(bool enabled) {
if (auto_accept_incoming_ == enabled) return;
auto_accept_incoming_ = enabled;
emit autoAcceptIncomingChanged();
SaveSettings();
}
void FileShareTrayController::setBluetoothEnabled(bool enabled) {
if (bluetooth_enabled_ == enabled) return;
bluetooth_enabled_ = enabled;
emit bluetoothEnabledChanged();
SaveSettings();
}
void FileShareTrayController::setBleEnabled(bool enabled) {
if (ble_enabled_ == enabled) return;
ble_enabled_ = enabled;
emit bleEnabledChanged();
SaveSettings();
}
void FileShareTrayController::setWifiLanEnabled(bool enabled) {
if (wifi_lan_enabled_ == enabled) return;
wifi_lan_enabled_ = enabled;
emit wifiLanEnabledChanged();
SaveSettings();
}
void FileShareTrayController::setWifiHotspotEnabled(bool enabled) {
if (wifi_hotspot_enabled_ == enabled) return;
wifi_hotspot_enabled_ = enabled;
emit wifiHotspotEnabledChanged();
SaveSettings();
}
void FileShareTrayController::setWebRtcEnabled(bool enabled) {
if (web_rtc_enabled_ == enabled) return;
web_rtc_enabled_ = enabled;
emit webRtcEnabledChanged();
SaveSettings();
}
void FileShareTrayController::setConnectionStrategy(const QString& strategy) {
const QString normalized = NormalizeConnectionStrategy(strategy);
if (connection_strategy_ == normalized) return;
connection_strategy_ = normalized;
emit connectionStrategyChanged();
SaveSettings();
}
void FileShareTrayController::setServiceId(const QString& service_id) {
const QString trimmed = service_id.trimmed();
if (trimmed.isEmpty() || trimmed.toStdString() == service_id_) return;
service_id_ = trimmed.toStdString();
emit serviceIdChanged();
SaveSettings();
}
void FileShareTrayController::setLogPath(const QString& path) {
const QString trimmed = path.trimmed();
if (trimmed.isEmpty() || trimmed == log_path_) return;
log_path_ = trimmed;
emit logPathChanged();
SaveSettings();
ReopenLogFile();
}
void FileShareTrayController::start() {
if (running_) {
return;
@@ -327,10 +456,13 @@ FileShareTrayController::BuildConnectionListener() {
if (incoming) {
SetStatus(QStringLiteral("Incoming connection from %1").arg(peer));
if (auto_accept_incoming_) {
acceptIncomingInternal(endpoint);
}
} else {
// Always accept outgoing connections (initiated by us for send).
acceptIncomingInternal(endpoint);
}
// Always auto-accept connections for this app.
acceptIncomingInternal(endpoint);
},
Qt::QueuedConnection);
};
@@ -576,18 +708,18 @@ FileShareTrayController::BuildPayloadListener() {
NearbyConnectionsQtFacade::MediumSelection
FileShareTrayController::BuildMediumSelection() const {
NearbyConnectionsQtFacade::MediumSelection selection;
selection.bluetooth = true;
selection.ble = true;
selection.wifi_lan = true;
selection.wifi_hotspot = true;
selection.web_rtc = false;
selection.bluetooth = bluetooth_enabled_;
selection.ble = ble_enabled_;
selection.wifi_lan = wifi_lan_enabled_;
selection.wifi_hotspot = wifi_hotspot_enabled_;
selection.web_rtc = web_rtc_enabled_;
return selection;
}
NearbyConnectionsQtFacade::AdvertisingOptions
FileShareTrayController::BuildAdvertisingOptions() const {
NearbyConnectionsQtFacade::AdvertisingOptions options;
options.strategy = NearbyConnectionsQtFacade::Strategy::kP2pPointToPoint;
options.strategy = StrategyFromName(connection_strategy_);
options.allowed_mediums = BuildMediumSelection();
options.auto_upgrade_bandwidth = true;
options.enable_bluetooth_listening = true;
@@ -598,7 +730,7 @@ FileShareTrayController::BuildAdvertisingOptions() const {
NearbyConnectionsQtFacade::DiscoveryOptions
FileShareTrayController::BuildDiscoveryOptions() const {
NearbyConnectionsQtFacade::DiscoveryOptions options;
options.strategy = NearbyConnectionsQtFacade::Strategy::kP2pPointToPoint;
options.strategy = StrategyFromName(connection_strategy_);
options.allowed_mediums = BuildMediumSelection();
return options;
}
@@ -30,6 +30,15 @@ class FileShareTrayController : public QObject {
Q_PROPERTY(QStringList connectedDevices READ connectedDevices NOTIFY connectedDevicesChanged)
Q_PROPERTY(QVariantMap endpointMediums READ endpointMediums NOTIFY endpointMediumsChanged)
Q_PROPERTY(QVariantList transfers READ transfers NOTIFY transfersChanged)
Q_PROPERTY(bool autoAcceptIncoming READ autoAcceptIncoming WRITE setAutoAcceptIncoming NOTIFY autoAcceptIncomingChanged)
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(QString connectionStrategy READ connectionStrategy WRITE setConnectionStrategy NOTIFY connectionStrategyChanged)
Q_PROPERTY(QString serviceId READ serviceId WRITE setServiceId NOTIFY serviceIdChanged)
Q_PROPERTY(QString logPath READ logPath WRITE setLogPath NOTIFY logPathChanged)
public:
explicit FileShareTrayController(QObject* parent = nullptr);
@@ -51,6 +60,33 @@ class FileShareTrayController : public QObject {
QVariantMap endpointMediums() const { return endpoint_mediums_; }
QVariantList transfers() const { return transfers_; }
bool autoAcceptIncoming() const { return auto_accept_incoming_; }
void setAutoAcceptIncoming(bool enabled);
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);
QString connectionStrategy() const { return connection_strategy_; }
void setConnectionStrategy(const QString& strategy);
QString serviceId() const { return QString::fromStdString(service_id_); }
void setServiceId(const QString& service_id);
QString logPath() const { return log_path_; }
void setLogPath(const QString& path);
Q_INVOKABLE void start();
Q_INVOKABLE void stop();
Q_INVOKABLE void switchToReceiveMode();
@@ -72,6 +108,15 @@ class FileShareTrayController : public QObject {
void connectedDevicesChanged();
void endpointMediumsChanged();
void transfersChanged();
void autoAcceptIncomingChanged();
void bluetoothEnabledChanged();
void bleEnabledChanged();
void wifiLanEnabledChanged();
void wifiHotspotEnabledChanged();
void webRtcEnabledChanged();
void connectionStrategyChanged();
void serviceIdChanged();
void logPathChanged();
void requestTrayMessage(const QString& title, const QString& body);
@@ -129,10 +174,19 @@ class FileShareTrayController : public QObject {
QString mode_ = QStringLiteral("Receive");
QString device_name_ = QStringLiteral("NearbyQtFile");
const std::string service_id_ = "com.nearby.qml.tray";
std::string service_id_ = "com.nearby.qml.tray";
QString status_message_ = QStringLiteral("Idle");
bool running_ = false;
bool auto_accept_incoming_ = true;
bool bluetooth_enabled_ = true;
bool ble_enabled_ = true;
bool wifi_lan_enabled_ = true;
bool wifi_hotspot_enabled_ = true;
bool web_rtc_enabled_ = false;
QString connection_strategy_ = QStringLiteral("P2pPointToPoint");
QString log_path_ = QStringLiteral("/tmp/nearby_qml_file_tray.log");
QString pending_send_file_path_;
QString pending_send_file_name_;
QString target_endpoint_for_send_;
@@ -153,7 +207,6 @@ class FileShareTrayController : public QObject {
QHash<qlonglong, QString> outgoing_file_payload_to_name_;
QSet<qlonglong> send_terminal_notified_;
QString log_path_ = QStringLiteral("/tmp/nearby_qml_file_tray.log");
QFile log_file_;
};
@@ -6,6 +6,7 @@
<file>components/AnimatedBlob.qml</file>
<file>components/DeviceCard.qml</file>
<file>components/TransferCard.qml</file>
<file>components/SettingsPanel.qml</file>
</qresource>
<qresource prefix="/icons">
<file>tray_icon.png</file>