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
229public 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