quick-settings: add Bluetooth tile with bluez5 D-Bus integration

parent 54664737
......@@ -13,6 +13,7 @@ src/controlCenter/widgets/quickSettings/tiles/caffeineTile.vala
src/controlCenter/widgets/quickSettings/tiles/nightLightTile.vala
src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala
src/controlCenter/widgets/quickSettings/tiles/vpnTile.vala
src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala
data/ui/widgets/notifications.blp
data/ui/widgets/title.blp
data/ui/widgets/inhibitors.blp
......
......@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ximper-shell-notification-center 0.1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-26 18:49+0300\n"
"POT-Creation-Date: 2026-03-26 22:05+0300\n"
"PO-Revision-Date: 2026-03-24 00:00+0300\n"
"Last-Translator: \n"
"Language-Team: Russian\n"
......@@ -108,10 +108,12 @@ msgid "Wi-Fi"
msgstr "Wi-Fi"
#: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:94
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:58
msgid "Disabled"
msgstr "Отключён"
#: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:135
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:70
msgid "Not Connected"
msgstr "Не подключён"
......@@ -120,6 +122,7 @@ msgid "Password"
msgstr "Пароль"
#: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:409
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:120
msgid "Connect"
msgstr "Подключить"
......@@ -143,6 +146,18 @@ msgstr "Отключён"
msgid "VPN Settings"
msgstr "Настройки VPN"
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:10
msgid "Bluetooth"
msgstr "Bluetooth"
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:119
msgid "Disconnect"
msgstr "Отключить"
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:162
msgid "Bluetooth Settings"
msgstr "Настройки Bluetooth"
#: data/ui/widgets/notifications.blp:57
msgid "No Notifications"
msgstr "Нет уведомлений"
......
......@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ximper-shell-notification-center\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-26 18:49+0300\n"
"POT-Creation-Date: 2026-03-26 22:05+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
......@@ -105,10 +105,12 @@ msgid "Wi-Fi"
msgstr ""
#: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:94
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:58
msgid "Disabled"
msgstr ""
#: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:135
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:70
msgid "Not Connected"
msgstr ""
......@@ -117,6 +119,7 @@ msgid "Password"
msgstr ""
#: src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala:409
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:120
msgid "Connect"
msgstr ""
......@@ -140,6 +143,18 @@ msgstr ""
msgid "VPN Settings"
msgstr ""
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:10
msgid "Bluetooth"
msgstr ""
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:119
msgid "Disconnect"
msgstr ""
#: src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala:162
msgid "Bluetooth Settings"
msgstr ""
#: data/ui/widgets/notifications.blp:57
msgid "No Notifications"
msgstr ""
......
......@@ -39,6 +39,7 @@
"tiles": [
{ "type": "wifi" },
{ "type": "vpn" },
{ "type": "bluetooth" },
{ "type": "power-profiles" },
{ "type": "dnd" },
{ "type": "dark-mode" },
......
......@@ -459,7 +459,7 @@
"type": {
"type": "string",
"description": "The tile type",
"enum": ["dnd", "dark-mode", "power-profiles", "caffeine", "night-light", "command", "wifi", "vpn"]
"enum": ["dnd", "dark-mode", "power-profiles", "caffeine", "night-light", "command", "bluetooth", "wifi", "vpn"]
},
"label": {
"type": "string",
......
......@@ -28,6 +28,9 @@ namespace XimperShellNotificationCenter.Widgets {
case "night-light":
tile = new NightLightTile (cfg);
break;
case "bluetooth":
tile = new BluetoothTile (cfg);
break;
case "wifi":
tile = new WifiTile (cfg);
break;
......
namespace XimperShellNotificationCenter.Widgets {
public class BluetoothTile : QuickSettingsTile {
private BluetoothProxy bt_proxy;
private uint sync_timeout = 0;
private static string ?settings_cmd = null;
private static bool settings_cmd_checked = false;
public BluetoothTile (Json.Object ?cfg) {
base ("bluetooth-active-symbolic",
_("Bluetooth"));
setup_arrow ();
bt_proxy = BluetoothProxy.get_instance ();
bt_proxy.state_changed.connect (schedule_sync);
bt_proxy.devices_changed.connect (() => {
sync_subtitle ();
submenu_update_requested ();
});
sync_subtitle ();
}
public override bool is_available () {
return bt_proxy.available;
}
public override void on_toggle () {
bt_proxy.set_powered (!bt_proxy.powered);
}
public override void on_cc_visibility_change (
bool visible) {
if (visible) {
sync_subtitle ();
} else {
bt_proxy.stop_discovery ();
}
}
private void schedule_sync () {
if (sync_timeout != 0) {
Source.remove (sync_timeout);
}
sync_timeout = Timeout.add (500, () => {
sync_timeout = 0;
sync_subtitle ();
submenu_update_requested ();
return Source.REMOVE;
});
}
private void sync_subtitle () {
active = bt_proxy.powered;
if (!bt_proxy.powered) {
icon.set_from_icon_name (
"bluetooth-disabled-symbolic");
set_subtitle (_("Disabled"));
return;
}
icon.set_from_icon_name (
"bluetooth-active-symbolic");
string ?connected_name =
bt_proxy.get_connected_device_name ();
if (connected_name != null) {
set_subtitle (connected_name);
} else {
set_subtitle (_("Not Connected"));
}
}
// Submenu
public override Gtk.Widget ?create_submenu () {
var box = new Gtk.Box (
Gtk.Orientation.VERTICAL, 0);
box.add_css_class ("quick-settings-submenu");
bt_proxy.start_discovery ();
build_device_list (box);
return box;
}
private void build_device_list (Gtk.Box box) {
foreach (var dev in bt_proxy.devices) {
var row = new Gtk.Box (
Gtk.Orientation.HORIZONTAL, 8);
row.add_css_class ("submenu-row");
var row_icon = new Gtk.Image.from_icon_name (
BluetoothProxy.get_device_icon (
dev.icon_name));
var row_label = new Gtk.Label (dev.name);
row_label.set_ellipsize (
Pango.EllipsizeMode.END);
row_label.set_hexpand (true);
row_label.set_halign (Gtk.Align.START);
row.append (row_icon);
row.append (row_label);
ObjectPath dev_path = dev.path;
bool is_connected = dev.connected;
bool is_busy =
bt_proxy.connecting_device != null
&& (string) bt_proxy.connecting_device
== (string) dev.path;
if (is_busy) {
var spinner = new Gtk.Spinner ();
spinner.start ();
row.append (spinner);
} else {
var action_label = new Gtk.Label (
is_connected
? _("Disconnect")
: _("Connect"));
action_label.add_css_class ("dim-label");
row.append (action_label);
}
var btn = new Gtk.Button ();
btn.set_child (row);
btn.add_css_class ("flat");
btn.set_sensitive (!is_busy);
btn.clicked.connect (() => {
if (is_connected) {
bt_proxy.disconnect_device.begin (
dev_path);
} else {
bt_proxy.connect_device.begin (
dev_path);
}
});
box.append (btn);
}
// Settings button
build_settings_button (box);
}
private void build_settings_button (Gtk.Box box) {
string ?cmd = get_settings_command ();
if (cmd == null) return;
if (bt_proxy.devices.size > 0) {
box.append (new Gtk.Separator (
Gtk.Orientation.HORIZONTAL));
}
var row = new Gtk.Box (
Gtk.Orientation.HORIZONTAL, 8);
row.add_css_class ("submenu-row");
row.append (new Gtk.Image.from_icon_name (
"emblem-system-symbolic"));
var label = new Gtk.Label (
_("Bluetooth Settings"));
label.set_hexpand (true);
label.set_halign (Gtk.Align.START);
row.append (label);
var btn = new Gtk.Button ();
btn.set_child (row);
btn.add_css_class ("flat");
btn.clicked.connect (() => {
try {
Process.spawn_command_line_async (cmd);
ximper_shell_notification_center_daemon
.set_visibility (false);
} catch (Error e) {
warning ("BT Settings: %s", e.message);
}
});
box.append (btn);
}
private static string ?get_settings_command () {
if (settings_cmd_checked) return settings_cmd;
settings_cmd_checked = true;
if (Environment.find_program_in_path (
"blueman-manager") != null) {
settings_cmd = "blueman-manager";
return settings_cmd;
}
return null;
}
}
}
......@@ -364,15 +364,10 @@ namespace XimperShellNotificationCenter.Widgets {
}
private static string ?get_settings_command () {
try {
string output;
Process.spawn_command_line_sync (
"which nm-connection-editor",
out output, null, null);
if (output.strip ().length > 0) {
return "nm-connection-editor";
}
} catch (SpawnError e) {}
if (Environment.find_program_in_path (
"nm-connection-editor") != null) {
return "nm-connection-editor";
}
return null;
}
}
......
......@@ -505,15 +505,10 @@ namespace XimperShellNotificationCenter.Widgets {
}
private static string ?get_settings_command () {
try {
string output;
Process.spawn_command_line_sync (
"which nm-connection-editor",
out output, null, null);
if (output.strip ().length > 0) {
return "nm-connection-editor";
}
} catch (SpawnError e) {}
if (Environment.find_program_in_path (
"nm-connection-editor") != null) {
return "nm-connection-editor";
}
return null;
}
......
......@@ -53,6 +53,8 @@ widget_sources = [
'controlCenter/widgets/quickSettings/tiles/caffeineTile.vala',
'controlCenter/widgets/quickSettings/tiles/nightLightTile.vala',
'controlCenter/widgets/quickSettings/networkManagerProxy.vala',
'controlCenter/widgets/quickSettings/bluetoothProxy.vala',
'controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala',
'controlCenter/widgets/quickSettings/tiles/wifiTile.vala',
'controlCenter/widgets/quickSettings/tiles/vpnTile.vala',
]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment