Skip to content

Commit d39055e

Browse files
authored
MainView: use list model (#245)
1 parent be69bea commit d39055e

2 files changed

Lines changed: 53 additions & 59 deletions

File tree

data/bluetooth.metainfo.xml.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
</ul>
4040
</description>
4141
<issues>
42+
<issue url="https://github.com/elementary/switchboard-plug-bluetooth/issues/188">Devices are duplicated when there are multiple Bluetooth adapters</issue>
4243
<issue url="https://github.com/elementary/switchboard-plug-bluetooth/issues/192">Incorrect "DISPLAY_PASSKEY" prompt used for bluetooth keyboard pairing</issue>
4344
<issue url="https://github.com/elementary/switchboard-plug-bluetooth/issues/200">The buttons of the Bluetooth password confirmation window do not work</issue>
4445
</issues>

src/MainView.vala

Lines changed: 52 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,18 @@
1-
// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
2-
/*-
3-
* Copyright (c) 2016-2018 elementary LLC.
4-
*
5-
* This program is free software: you can redistribute it and/or modify
6-
* it under the terms of the GNU General Public License as published by
7-
* the Free Software Foundation, either version 3 of the License, or
8-
* (at your option) any later version.
9-
*
10-
* This program is distributed in the hope that it will be useful,
11-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13-
* GNU General Public License for more details.
14-
*
15-
* You should have received a copy of the GNU General Public License
16-
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17-
*
18-
* Authored by: Corentin Noël <corentin@elementary.io>
19-
* Oleksandr Lynok <oleksandr.lynok@gmail.com>
20-
*/
1+
/*
2+
* SPDX-License-Identifier: LGPL-3.0-or-later
3+
* SPDX-FileCopyrightText: 2016-2025 elementary, Inc. (https://elementary.io)
4+
*
5+
* Authored by: Corentin Noël <corentin@elementary.io>
6+
* Oleksandr Lynok <oleksandr.lynok@gmail.com>
7+
*/
218

229
public class Bluetooth.MainView : Switchboard.SettingsPage {
23-
private Gtk.ListBox list_box;
24-
private Granite.OverlayBar overlaybar;
10+
public signal void quit_plug ();
2511

12+
private GLib.ListStore device_model;
13+
private Granite.OverlayBar overlaybar;
2614
private Services.ObjectManager manager;
2715

28-
public signal void quit_plug ();
29-
3016
public MainView () {
3117
Object (
3218
title: _("Bluetooth"),
@@ -35,18 +21,16 @@ public class Bluetooth.MainView : Switchboard.SettingsPage {
3521
}
3622

3723
construct {
38-
manager = Bluetooth.Services.ObjectManager.get_default ();
39-
4024
var empty_alert = new Granite.Placeholder (_("No Devices Found")) {
4125
description = _("Please ensure that your devices are visible and ready for pairing.")
4226
};
4327

44-
list_box = new Gtk.ListBox () {
28+
var list_box = new Gtk.ListBox () {
4529
activate_on_single_click = false,
4630
selection_mode = BROWSE
4731
};
4832
list_box.add_css_class (Granite.STYLE_CLASS_RICH_LIST);
49-
list_box.set_sort_func ((Gtk.ListBoxSortFunc) compare_rows);
33+
list_box.bind_model (device_model, create_widget_func);
5034
list_box.set_header_func ((Gtk.ListBoxUpdateHeaderFunc) title_rows);
5135
list_box.set_placeholder (empty_alert);
5236

@@ -71,6 +55,9 @@ public class Bluetooth.MainView : Switchboard.SettingsPage {
7155

7256
child = frame;
7357

58+
device_model = new GLib.ListStore (typeof (Services.Device));
59+
60+
manager = Bluetooth.Services.ObjectManager.get_default ();
7461
if (manager.retrieve_finished) {
7562
complete_setup ();
7663
} else {
@@ -88,41 +75,17 @@ public class Bluetooth.MainView : Switchboard.SettingsPage {
8875

8976
private void complete_setup () {
9077
foreach (var device in manager.get_devices ()) {
91-
var row = new DeviceRow (device);
92-
list_box.append (row);
93-
}
94-
95-
var first_row = list_box.get_row_at_index (0);
96-
if (first_row != null) {
97-
list_box.select_row (first_row);
98-
list_box.row_activated (first_row);
78+
on_device_added (device);
9979
}
10080

10181
update_description ();
10282

10383
status_switch.active = manager.is_powered;
10484

10585
/* Now retrieve finished, we can connect manager signals */
106-
manager.device_added.connect ((device) => {
107-
var row = new DeviceRow (device);
108-
list_box.append (row);
109-
if (list_box.get_selected_row () == null) {
110-
list_box.select_row (row);
111-
list_box.row_activated (row);
112-
}
113-
});
114-
115-
manager.device_removed.connect_after ((device) => {
116-
var child = list_box.get_first_child ();
117-
while (child != null) {
118-
if (((DeviceRow) child).device == device) {
119-
list_box.remove (child);
120-
break;
121-
}
86+
manager.device_added.connect (on_device_added);
12287

123-
child = child.get_next_sibling ();
124-
}
125-
});
88+
manager.device_removed.connect_after (on_device_removed);
12689

12790
manager.adapter_added.connect ((adapter) => {
12891
update_description ();
@@ -148,6 +111,33 @@ public class Bluetooth.MainView : Switchboard.SettingsPage {
148111
manager.bind_property ("is-powered", status_switch, "active", GLib.BindingFlags.DEFAULT);
149112
}
150113

114+
private void on_device_added (Services.Device device) {
115+
uint pos = -1;
116+
if (device_model.find (device, out pos)) {
117+
return;
118+
}
119+
120+
((DBusProxy) device).g_properties_changed.connect (on_device_changed);
121+
122+
device_model.insert_sorted (device, compare_func);
123+
}
124+
125+
// Exists as separate function so we can disconnect when devices are removed
126+
private void on_device_changed () {
127+
device_model.sort (compare_func);
128+
}
129+
130+
private void on_device_removed (Services.Device device) {
131+
uint pos = -1;
132+
if (!device_model.find (device, out pos)) {
133+
return;
134+
}
135+
136+
((DBusProxy) device).g_properties_changed.disconnect (on_device_changed);
137+
138+
device_model.remove (pos);
139+
}
140+
151141
private void update_description () {
152142
string? name = manager.get_name ();
153143
var powered = manager.is_powered;
@@ -167,10 +157,9 @@ public class Bluetooth.MainView : Switchboard.SettingsPage {
167157
}
168158
}
169159

170-
[CCode (instance_pos = -1)]
171-
private int compare_rows (DeviceRow row1, DeviceRow row2) {
172-
unowned Services.Device device1 = row1.device;
173-
unowned Services.Device device2 = row2.device;
160+
private int compare_func (Object obj1, Object obj2) {
161+
unowned var device1 = (Services.Device) obj1;
162+
unowned var device2 = (Services.Device) obj2;
174163
if (device1.paired && !device2.paired) {
175164
return -1;
176165
}
@@ -200,6 +189,10 @@ public class Bluetooth.MainView : Switchboard.SettingsPage {
200189
return name1.collate (name2);
201190
}
202191

192+
private Gtk.Widget create_widget_func (Object obj) {
193+
return new DeviceRow ((Services.Device) obj);
194+
}
195+
203196
[CCode (instance_pos = -1)]
204197
private void title_rows (DeviceRow row1, DeviceRow? row2) {
205198
if (row2 == null && row1.device.paired) {

0 commit comments

Comments
 (0)