Merge lp:~donadigo/wingpanel-indicator-session/use-native-accounts-library into lp:~wingpanel-devs/wingpanel-indicator-session/trunk
- use-native-accounts-library
- Merge into trunk
Proposed by
Adam Bieńkowski
Status: | Merged |
---|---|
Approved by: | Felipe Escoto |
Approved revision: | 96 |
Merged at revision: | 94 |
Proposed branch: | lp:~donadigo/wingpanel-indicator-session/use-native-accounts-library |
Merge into: | lp:~wingpanel-devs/wingpanel-indicator-session/trunk |
Diff against target: |
655 lines (+245/-206) 7 files modified
src/CMakeLists.txt (+0/-1) src/Indicator.vala (+6/-3) src/Services/DbusInterfaces.vala (+12/-23) src/Services/User.vala (+0/-108) src/Services/UserManager.vala (+144/-50) src/Widgets/UserBox.vala (+56/-18) src/Widgets/UserListBox.vala (+27/-3) |
To merge this branch: | bzr merge lp:~donadigo/wingpanel-indicator-session/use-native-accounts-library |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Felipe Escoto | code/ux | Approve | |
Review via email: mp+302229@code.launchpad.net |
Commit message
* Use native accounts-service library
* Close indicator on activating row (logging of, switching accounts)
* Show guest account proper state when logged in
Description of the change
This branch replaces the old DBus implementation with native accounts-service library. In result we don't need a User class, that's provided already by the library.
Other features include:
- Close indicator on activating row (logging of, switching accounts)
- Show guest account proper state when logged in
To post a comment you must log in.
- 94. By Adam Bieńkowski
-
Use enums
Revision history for this message
Felipe Escoto (philip.scott) wrote : | # |
review:
Needs Fixing
(code/ux)
- 95. By Adam Bieńkowski
-
Prevent logged in users to be able to click themselves
- 96. By Adam Bieńkowski
-
Simpler draw function
Revision history for this message
Felipe Escoto (philip.scott) : | # |
review:
Approve
(code/ux)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/CMakeLists.txt' | |||
2 | --- src/CMakeLists.txt 2016-02-18 19:58:35 +0000 | |||
3 | +++ src/CMakeLists.txt 2016-08-08 16:32:36 +0000 | |||
4 | @@ -17,7 +17,6 @@ | |||
5 | 17 | Widgets/UserBox.vala | 17 | Widgets/UserBox.vala |
6 | 18 | Widgets/UserListBox.vala | 18 | Widgets/UserListBox.vala |
7 | 19 | Widgets/EndSessionDialog.vala | 19 | Widgets/EndSessionDialog.vala |
8 | 20 | Services/User.vala | ||
9 | 21 | Services/UserManager.vala | 20 | Services/UserManager.vala |
10 | 22 | Services/DbusInterfaces.vala | 21 | Services/DbusInterfaces.vala |
11 | 23 | ${CMAKE_CURRENT_BINARY_DIR}/config.vala | 22 | ${CMAKE_CURRENT_BINARY_DIR}/config.vala |
12 | 24 | 23 | ||
13 | === modified file 'src/Indicator.vala' | |||
14 | --- src/Indicator.vala 2016-07-12 16:33:07 +0000 | |||
15 | +++ src/Indicator.vala 2016-08-08 16:32:36 +0000 | |||
16 | @@ -67,11 +67,10 @@ | |||
17 | 67 | users_separator = new Wingpanel.Widgets.Separator (); | 67 | users_separator = new Wingpanel.Widgets.Separator (); |
18 | 68 | manager = new Session.Services.UserManager (users_separator); | 68 | manager = new Session.Services.UserManager (users_separator); |
19 | 69 | 69 | ||
20 | 70 | main_grid.add (manager.current_user); | ||
21 | 71 | main_grid.add (manager.user_grid); | 70 | main_grid.add (manager.user_grid); |
22 | 72 | 71 | ||
23 | 73 | if (manager.has_guest) { | 72 | if (manager.has_guest) { |
25 | 74 | manager.user_grid.add_guest (manager.guest (false)); | 73 | manager.add_guest (false); |
26 | 75 | } | 74 | } |
27 | 76 | 75 | ||
28 | 77 | main_grid.add (users_separator); | 76 | main_grid.add (users_separator); |
29 | @@ -118,6 +117,8 @@ | |||
30 | 118 | } | 117 | } |
31 | 119 | 118 | ||
32 | 120 | public void connections () { | 119 | public void connections () { |
33 | 120 | manager.close.connect (() => close ()); | ||
34 | 121 | |||
35 | 121 | lock_screen.clicked.connect (() => { | 122 | lock_screen.clicked.connect (() => { |
36 | 122 | close (); | 123 | close (); |
37 | 123 | try { | 124 | try { |
38 | @@ -151,7 +152,9 @@ | |||
39 | 151 | }); | 152 | }); |
40 | 152 | } | 153 | } |
41 | 153 | 154 | ||
43 | 154 | public override void opened () {} | 155 | public override void opened () { |
44 | 156 | manager.update_all (); | ||
45 | 157 | } | ||
46 | 155 | 158 | ||
47 | 156 | public override void closed () {} | 159 | public override void closed () {} |
48 | 157 | } | 160 | } |
49 | 158 | 161 | ||
50 | === modified file 'src/Services/DbusInterfaces.vala' | |||
51 | --- src/Services/DbusInterfaces.vala 2016-08-05 22:26:34 +0000 | |||
52 | +++ src/Services/DbusInterfaces.vala 2016-08-08 16:32:36 +0000 | |||
53 | @@ -17,12 +17,9 @@ | |||
54 | 17 | * Boston, MA 02111-1307, USA. | 17 | * Boston, MA 02111-1307, USA. |
55 | 18 | */ | 18 | */ |
56 | 19 | 19 | ||
63 | 20 | /* To generate new UserBoxes for each user, and when a new one is added */ | 20 | struct UserInfo { |
64 | 21 | [DBus (name = "org.freedesktop.Accounts")] | 21 | uint32 uid; |
65 | 22 | interface AccountsInterface : Object { | 22 | string user_name; |
60 | 23 | public abstract string[] list_cached_users () throws IOError; | ||
61 | 24 | public signal void user_added (ObjectPath user_path); | ||
62 | 25 | public signal void user_deleted (ObjectPath user_path); | ||
66 | 26 | } | 23 | } |
67 | 27 | 24 | ||
68 | 28 | /* Power and system control */ | 25 | /* Power and system control */ |
69 | @@ -42,26 +39,18 @@ | |||
70 | 42 | public abstract void reboot (bool interactive) throws IOError; | 39 | public abstract void reboot (bool interactive) throws IOError; |
71 | 43 | public abstract void power_off (bool interactive) throws IOError; | 40 | public abstract void power_off (bool interactive) throws IOError; |
72 | 44 | 41 | ||
74 | 45 | public abstract string? get_user (uint32 uuid) throws IOError; | 42 | public abstract UserInfo[] list_users () throws IOError; |
75 | 43 | public abstract ObjectPath? get_user (uint32 uuid) throws IOError; | ||
76 | 44 | } | ||
77 | 45 | |||
78 | 46 | [DBus (name = "org.freedesktop.login1.User")] | ||
79 | 47 | interface UserInterface : Object { | ||
80 | 48 | public abstract string state { owned get; } | ||
81 | 46 | } | 49 | } |
82 | 47 | 50 | ||
83 | 48 | [DBus (name = "org.freedesktop.DisplayManager.Seat")] | 51 | [DBus (name = "org.freedesktop.DisplayManager.Seat")] |
84 | 49 | interface SeatInterface : Object { | 52 | interface SeatInterface : Object { |
86 | 50 | //public abstract void SwitchToGreeter () throws IOError; | 53 | public abstract bool has_guest_account { get; } |
87 | 51 | public abstract void switch_to_guest (string session_name) throws IOError; | 54 | public abstract void switch_to_guest (string session_name) throws IOError; |
88 | 52 | public abstract void switch_to_user (string username, string session_name) throws IOError; | 55 | public abstract void switch_to_user (string username, string session_name) throws IOError; |
104 | 53 | } | 56 | } |
90 | 54 | |||
91 | 55 | /* for User.vala, to get the user properties */ | ||
92 | 56 | [DBus (name = "org.freedesktop.Accounts.User")] | ||
93 | 57 | interface UserInterface : Object { | ||
94 | 58 | public signal void changed (); | ||
95 | 59 | } | ||
96 | 60 | |||
97 | 61 | [DBus (name = "org.freedesktop.DBus.Properties")] | ||
98 | 62 | interface PropertiesInterface : Object { | ||
99 | 63 | public abstract Variant get (string interface, string propname) throws IOError; | ||
100 | 64 | |||
101 | 65 | /* public abstract void Set (string interface, string propname, Variant value) throws IOError; */ | ||
102 | 66 | public signal void properties_changed (); | ||
103 | 67 | } | ||
105 | 68 | \ No newline at end of file | 57 | \ No newline at end of file |
106 | 69 | 58 | ||
107 | === removed file 'src/Services/User.vala' | |||
108 | --- src/Services/User.vala 2016-01-15 18:20:25 +0000 | |||
109 | +++ src/Services/User.vala 1970-01-01 00:00:00 +0000 | |||
110 | @@ -1,108 +0,0 @@ | |||
111 | 1 | /* | ||
112 | 2 | * Copyright (c) 2011-2015 Wingpanel Developers (http://launchpad.net/wingpanel) | ||
113 | 3 | * | ||
114 | 4 | * This program is free software; you can redistribute it and/or | ||
115 | 5 | * modify it under the terms of the GNU General Public | ||
116 | 6 | * License as published by the Free Software Foundation; either | ||
117 | 7 | * version 2 of the License, or (at your option) any later version. | ||
118 | 8 | * | ||
119 | 9 | * This program is distributed in the hope that it will be useful, | ||
120 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
121 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
122 | 12 | * General Public License for more details. | ||
123 | 13 | * | ||
124 | 14 | * You should have received a copy of the GNU General Public | ||
125 | 15 | * License along with this program; if not, write to the | ||
126 | 16 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
127 | 17 | * Boston, MA 02111-1307, USA. | ||
128 | 18 | */ | ||
129 | 19 | |||
130 | 20 | public class Session.Services.User : Object { | ||
131 | 21 | private static string ACCOUNTS_INTERFACE = "org.freedesktop.Accounts"; | ||
132 | 22 | private static string USER_INTERFACE = "org.freedesktop.Accounts.User"; | ||
133 | 23 | private static string LOGIN_INTERFACE = "org.freedesktop.login1"; | ||
134 | 24 | private static string MANAGER = "/org/freedesktop/login1"; | ||
135 | 25 | |||
136 | 26 | public string user_path { get; private set; } | ||
137 | 27 | public string real_name { get; private set; } | ||
138 | 28 | public string user_name { get; private set; } | ||
139 | 29 | public string icon_file { get; private set; } | ||
140 | 30 | public uint64 Uid { get; private set; } | ||
141 | 31 | public bool locked { get; private set; } | ||
142 | 32 | |||
143 | 33 | private UserInterface? user_interface = null; | ||
144 | 34 | private PropertiesInterface? user_properties = null; | ||
145 | 35 | private PropertiesInterface? state_properties = null; | ||
146 | 36 | private SystemInterface? system_interface = null; | ||
147 | 37 | |||
148 | 38 | public signal void properties_updated (); | ||
149 | 39 | |||
150 | 40 | public User (string user_path_) { | ||
151 | 41 | this.user_path = user_path_; | ||
152 | 42 | |||
153 | 43 | connect_to_bus (); | ||
154 | 44 | connect_signals (); | ||
155 | 45 | update_properties (); | ||
156 | 46 | get_state (); | ||
157 | 47 | |||
158 | 48 | } | ||
159 | 49 | |||
160 | 50 | private bool connect_to_bus () { | ||
161 | 51 | try { | ||
162 | 52 | system_interface = Bus.get_proxy_sync (BusType.SYSTEM, LOGIN_INTERFACE, MANAGER, DBusProxyFlags.NONE); | ||
163 | 53 | user_interface = Bus.get_proxy_sync (BusType.SYSTEM, ACCOUNTS_INTERFACE, user_path, DBusProxyFlags.NONE); | ||
164 | 54 | user_properties = Bus.get_proxy_sync (BusType.SYSTEM, ACCOUNTS_INTERFACE, user_path, DBusProxyFlags.NONE); | ||
165 | 55 | |||
166 | 56 | update_properties (); | ||
167 | 57 | string? user_object_path = system_interface.get_user ((uint32)Uid); | ||
168 | 58 | state_properties = Bus.get_proxy_sync (BusType.SYSTEM, LOGIN_INTERFACE, user_object_path, DBusProxyFlags.NONE); | ||
169 | 59 | |||
170 | 60 | debug ("Connection to user account established. User path: %s", user_object_path); | ||
171 | 61 | |||
172 | 62 | return user_interface != null & user_properties != null; | ||
173 | 63 | } catch (Error e) { | ||
174 | 64 | critical ("Connecting to Accounts failed: %s", e.message); | ||
175 | 65 | return false; | ||
176 | 66 | } | ||
177 | 67 | } | ||
178 | 68 | |||
179 | 69 | private void connect_signals () { | ||
180 | 70 | user_interface.changed.connect (update_properties); | ||
181 | 71 | user_properties.properties_changed.connect (update_properties); | ||
182 | 72 | state_properties.properties_changed.connect (update_properties); | ||
183 | 73 | } | ||
184 | 74 | |||
185 | 75 | public bool get_state () { | ||
186 | 76 | bool state = false; | ||
187 | 77 | |||
188 | 78 | try { | ||
189 | 79 | string status = state_properties.get (LOGIN_INTERFACE + ".User", "State").get_string (); | ||
190 | 80 | |||
191 | 81 | if (status == "active" || status == "online") { | ||
192 | 82 | state = true; | ||
193 | 83 | } | ||
194 | 84 | } catch (Error e) { | ||
195 | 85 | critical ("Could not get users' state: %s", e.message); | ||
196 | 86 | } | ||
197 | 87 | |||
198 | 88 | return state; | ||
199 | 89 | } | ||
200 | 90 | |||
201 | 91 | public void update_properties () { | ||
202 | 92 | try { | ||
203 | 93 | real_name = user_properties.get (USER_INTERFACE, "RealName").get_string (); | ||
204 | 94 | user_name = user_properties.get (USER_INTERFACE, "UserName").get_string (); | ||
205 | 95 | icon_file = user_properties.get (USER_INTERFACE, "IconFile").get_string (); | ||
206 | 96 | locked = user_properties.get (USER_INTERFACE, "Locked").get_boolean (); | ||
207 | 97 | Uid = user_properties.get (USER_INTERFACE, "Uid").get_uint64 (); | ||
208 | 98 | |||
209 | 99 | if (real_name == "") { | ||
210 | 100 | real_name = user_name; | ||
211 | 101 | } | ||
212 | 102 | |||
213 | 103 | properties_updated (); | ||
214 | 104 | } catch (Error e) { | ||
215 | 105 | critical ("Updating device properties failed: %s", e.message); | ||
216 | 106 | } | ||
217 | 107 | } | ||
218 | 108 | } | ||
219 | 109 | 0 | ||
220 | === modified file 'src/Services/UserManager.vala' | |||
221 | --- src/Services/UserManager.vala 2016-05-21 15:56:59 +0000 | |||
222 | +++ src/Services/UserManager.vala 2016-08-08 16:32:36 +0000 | |||
223 | @@ -17,16 +17,93 @@ | |||
224 | 17 | * Boston, MA 02111-1307, USA. | 17 | * Boston, MA 02111-1307, USA. |
225 | 18 | */ | 18 | */ |
226 | 19 | 19 | ||
227 | 20 | public enum UserState { | ||
228 | 21 | ACTIVE, | ||
229 | 22 | ONLINE, | ||
230 | 23 | OFFLINE; | ||
231 | 24 | |||
232 | 25 | public static UserState to_enum (string state) { | ||
233 | 26 | switch (state) { | ||
234 | 27 | case "active": | ||
235 | 28 | return UserState.ACTIVE; | ||
236 | 29 | case "online": | ||
237 | 30 | return UserState.ONLINE; | ||
238 | 31 | } | ||
239 | 32 | |||
240 | 33 | return UserState.OFFLINE; | ||
241 | 34 | } | ||
242 | 35 | } | ||
243 | 36 | |||
244 | 20 | public class Session.Services.UserManager : Object { | 37 | public class Session.Services.UserManager : Object { |
245 | 38 | public signal void close (); | ||
246 | 39 | |||
247 | 40 | private const string LOGIN_IFACE = "org.freedesktop.login1"; | ||
248 | 41 | private const string LOGIN_PATH = "/org/freedesktop/login1"; | ||
249 | 42 | |||
250 | 21 | private signal void delete_user (ObjectPath user_path); | 43 | private signal void delete_user (ObjectPath user_path); |
253 | 22 | private AccountsInterface accounts_interface; | 44 | private Act.UserManager manager; |
254 | 23 | private PropertiesInterface state_properties; | 45 | private List<Widgets.Userbox> userbox_list; |
255 | 46 | private SeatInterface dm_proxy; | ||
256 | 24 | private Wingpanel.Widgets.Separator users_separator; | 47 | private Wingpanel.Widgets.Separator users_separator; |
257 | 25 | 48 | ||
258 | 26 | public Session.Widgets.UserListBox user_grid; | 49 | public Session.Widgets.UserListBox user_grid; |
259 | 27 | public Session.Widgets.Userbox current_user; | ||
260 | 28 | 50 | ||
262 | 29 | public bool has_guest {public get; private set; default = false;} | 51 | public bool has_guest { public get; private set; default = false; } |
263 | 52 | |||
264 | 53 | private static SystemInterface? login_proxy; | ||
265 | 54 | |||
266 | 55 | static construct { | ||
267 | 56 | try { | ||
268 | 57 | login_proxy = Bus.get_proxy_sync (BusType.SYSTEM, LOGIN_IFACE, LOGIN_PATH, DBusProxyFlags.NONE); | ||
269 | 58 | } catch (IOError e) { | ||
270 | 59 | stderr.printf ("UserManager error: %s\n", e.message); | ||
271 | 60 | } | ||
272 | 61 | } | ||
273 | 62 | |||
274 | 63 | public static UserState get_user_state (uint32 uuid) { | ||
275 | 64 | if (login_proxy == null) { | ||
276 | 65 | return UserState.OFFLINE; | ||
277 | 66 | } | ||
278 | 67 | |||
279 | 68 | try { | ||
280 | 69 | ObjectPath? path = login_proxy.get_user (uuid); | ||
281 | 70 | if (path == null) { | ||
282 | 71 | return UserState.OFFLINE; | ||
283 | 72 | } | ||
284 | 73 | |||
285 | 74 | UserInterface? user = Bus.get_proxy_sync (BusType.SYSTEM, LOGIN_IFACE, path, DBusProxyFlags.NONE); | ||
286 | 75 | if (user == null) { | ||
287 | 76 | return UserState.OFFLINE; | ||
288 | 77 | } | ||
289 | 78 | |||
290 | 79 | return UserState.to_enum (user.state); | ||
291 | 80 | } catch (IOError e) { | ||
292 | 81 | stderr.printf ("Error: %s\n", e.message); | ||
293 | 82 | } | ||
294 | 83 | |||
295 | 84 | return UserState.OFFLINE; | ||
296 | 85 | } | ||
297 | 86 | |||
298 | 87 | public static UserState get_guest_state () { | ||
299 | 88 | if (login_proxy == null) { | ||
300 | 89 | return UserState.OFFLINE; | ||
301 | 90 | } | ||
302 | 91 | |||
303 | 92 | try { | ||
304 | 93 | UserInfo[] users = login_proxy.list_users (); | ||
305 | 94 | foreach (UserInfo user in users) { | ||
306 | 95 | var state = get_user_state (user.uid); | ||
307 | 96 | if (user.user_name.has_prefix ("guest-") | ||
308 | 97 | && state == UserState.ACTIVE) { | ||
309 | 98 | return UserState.ACTIVE; | ||
310 | 99 | } | ||
311 | 100 | } | ||
312 | 101 | } catch (IOError e) { | ||
313 | 102 | stderr.printf ("Error: %s\n", e.message); | ||
314 | 103 | } | ||
315 | 104 | |||
316 | 105 | return UserState.OFFLINE; | ||
317 | 106 | } | ||
318 | 30 | 107 | ||
319 | 31 | public UserManager (Wingpanel.Widgets.Separator users_separator) { | 108 | public UserManager (Wingpanel.Widgets.Separator users_separator) { |
320 | 32 | this.users_separator = users_separator; | 109 | this.users_separator = users_separator; |
321 | @@ -37,74 +114,91 @@ | |||
322 | 37 | } | 114 | } |
323 | 38 | 115 | ||
324 | 39 | private void init () { | 116 | private void init () { |
325 | 117 | userbox_list = new List<Widgets.Userbox> (); | ||
326 | 40 | user_grid = new Session.Widgets.UserListBox (); | 118 | user_grid = new Session.Widgets.UserListBox (); |
327 | 119 | user_grid.close.connect (() => close ()); | ||
328 | 120 | |||
329 | 121 | manager = Act.UserManager.get_default (); | ||
330 | 122 | connect_signals (); | ||
331 | 123 | init_users (); | ||
332 | 41 | 124 | ||
333 | 42 | try { | 125 | try { |
340 | 43 | accounts_interface = Bus.get_proxy_sync (BusType.SYSTEM, "org.freedesktop.Accounts", "/org/freedesktop/Accounts", DBusProxyFlags.NONE); | 126 | dm_proxy = Bus.get_proxy_sync (BusType.SYSTEM, "org.freedesktop.DisplayManager", Environment.get_variable ("XDG_SEAT_PATH"), DBusProxyFlags.NONE); |
341 | 44 | state_properties = Bus.get_proxy_sync (BusType.SYSTEM, "org.freedesktop.DisplayManager", Environment.get_variable ("XDG_SEAT_PATH"), DBusProxyFlags.NONE); | 127 | has_guest = dm_proxy.has_guest_account; |
336 | 45 | has_guest = state_properties.get ("org.freedesktop.DisplayManager.Seat", "HasGuestAccount").get_boolean (); | ||
337 | 46 | |||
338 | 47 | connect_signals (); | ||
339 | 48 | init_users (); | ||
342 | 49 | } catch (IOError e) { | 128 | } catch (IOError e) { |
343 | 50 | stderr.printf ("UserManager error: %s\n", e.message); | 129 | stderr.printf ("UserManager error: %s\n", e.message); |
344 | 51 | } | 130 | } |
345 | 52 | } | 131 | } |
346 | 53 | 132 | ||
347 | 54 | private void connect_signals () { | 133 | private void connect_signals () { |
350 | 55 | accounts_interface.user_added.connect ((user_path) => { | 134 | manager.user_added.connect (add_user); |
351 | 56 | var user = new_user (user_path); | 135 | manager.user_removed.connect (remove_user); |
352 | 136 | manager.user_is_logged_in_changed.connect (update_user); | ||
353 | 57 | 137 | ||
356 | 58 | if (user != null) { | 138 | manager.notify["is-loaded"].connect (() => { |
357 | 59 | user_grid.add (user); | 139 | if (manager.is_loaded) { |
358 | 140 | init_users (); | ||
359 | 60 | } | 141 | } |
365 | 61 | }); | 142 | }); |
361 | 62 | |||
362 | 63 | accounts_interface.user_deleted.connect ((user_path) => { | ||
363 | 64 | delete_user (user_path); | ||
364 | 65 | }); | ||
366 | 66 | } | 143 | } |
367 | 67 | 144 | ||
368 | 68 | private void init_users () { | 145 | private void init_users () { |
384 | 69 | string current_user = GLib.Environment.get_user_name (); | 146 | foreach (Act.User user in manager.list_users ()) { |
385 | 70 | 147 | add_user (user); | |
371 | 71 | try { | ||
372 | 72 | var users = accounts_interface.list_cached_users (); | ||
373 | 73 | foreach (string user_address in users) { | ||
374 | 74 | var userbox = new_user (user_address); | ||
375 | 75 | |||
376 | 76 | if (userbox.user.user_name == current_user) { | ||
377 | 77 | this.current_user = userbox; | ||
378 | 78 | } else { | ||
379 | 79 | user_grid.add (userbox); | ||
380 | 80 | } | ||
381 | 81 | } | ||
382 | 82 | } catch (IOError e) { | ||
383 | 83 | stderr.printf ("ERROR: %s\n", e.message); | ||
386 | 84 | } | 148 | } |
387 | 85 | } | 149 | } |
388 | 86 | 150 | ||
391 | 87 | private Session.Widgets.Userbox new_user (string user_address) { | 151 | private void add_user (Act.User user) { |
390 | 88 | var user = new Session.Services.User (user_address); | ||
392 | 89 | var userbox = new Session.Widgets.Userbox (user); | 152 | var userbox = new Session.Widgets.Userbox (user); |
397 | 90 | 153 | userbox_list.append (userbox); | |
398 | 91 | delete_user.connect ((user_path) => { | 154 | |
399 | 92 | if (userbox.user.user_path == user_path) { | 155 | user_grid.add (userbox); |
400 | 93 | user_grid.remove (userbox); | 156 | |
401 | 157 | users_separator.visible = true; | ||
402 | 158 | } | ||
403 | 159 | |||
404 | 160 | private Widgets.Userbox? get_userbox_from_user (Act.User user) { | ||
405 | 161 | foreach (Widgets.Userbox userbox in userbox_list) { | ||
406 | 162 | if (userbox.user.get_user_name () == user.get_user_name ()) { | ||
407 | 163 | return userbox; | ||
408 | 94 | } | 164 | } |
417 | 95 | }); | 165 | } |
418 | 96 | 166 | ||
419 | 97 | users_separator.visible = true; | 167 | return null; |
420 | 98 | 168 | } | |
421 | 99 | return userbox; | 169 | |
422 | 100 | } | 170 | private void remove_user (Act.User user) { |
423 | 101 | 171 | var userbox = get_userbox_from_user (user); | |
424 | 102 | public Session.Widgets.Userbox guest (bool logged_in) { | 172 | if (userbox == null) { |
425 | 173 | return; | ||
426 | 174 | } | ||
427 | 175 | |||
428 | 176 | userbox_list.remove (userbox); | ||
429 | 177 | user_grid.remove (userbox); | ||
430 | 178 | } | ||
431 | 179 | |||
432 | 180 | private void update_user (Act.User user) { | ||
433 | 181 | var userbox = get_userbox_from_user (user); | ||
434 | 182 | if (userbox == null) { | ||
435 | 183 | return; | ||
436 | 184 | } | ||
437 | 185 | |||
438 | 186 | userbox.update_state (); | ||
439 | 187 | } | ||
440 | 188 | |||
441 | 189 | public void update_all () { | ||
442 | 190 | foreach (var userbox in userbox_list) { | ||
443 | 191 | userbox.update_state (); | ||
444 | 192 | } | ||
445 | 193 | } | ||
446 | 194 | |||
447 | 195 | public void add_guest (bool logged_in) { | ||
448 | 103 | var userbox = new Session.Widgets.Userbox.from_data (_("Guest"), logged_in, true); | 196 | var userbox = new Session.Widgets.Userbox.from_data (_("Guest"), logged_in, true); |
449 | 197 | userbox_list.append (userbox); | ||
450 | 104 | userbox.visible = true; | 198 | userbox.visible = true; |
451 | 105 | 199 | ||
452 | 200 | user_grid.add_guest (userbox); | ||
453 | 201 | |||
454 | 106 | users_separator.visible = true; | 202 | users_separator.visible = true; |
455 | 107 | |||
456 | 108 | return userbox; | ||
457 | 109 | } | 203 | } |
458 | 110 | } | 204 | } |
459 | 111 | 205 | ||
460 | === modified file 'src/Widgets/UserBox.vala' | |||
461 | --- src/Widgets/UserBox.vala 2016-05-21 17:15:08 +0000 | |||
462 | +++ src/Widgets/UserBox.vala 2016-08-08 16:32:36 +0000 | |||
463 | @@ -22,28 +22,30 @@ | |||
464 | 22 | private const string LOGGED_OFF = _("Logged out"); | 22 | private const string LOGGED_OFF = _("Logged out"); |
465 | 23 | private const int ICON_SIZE = 48; | 23 | private const int ICON_SIZE = 48; |
466 | 24 | 24 | ||
468 | 25 | public Session.Services.User user { public get; private set; } | 25 | public Act.User? user { public get; private set; } |
469 | 26 | public bool is_guest = false; | 26 | public bool is_guest = false; |
470 | 27 | 27 | ||
471 | 28 | private Granite.Widgets.Avatar avatar; | 28 | private Granite.Widgets.Avatar avatar; |
472 | 29 | private Gtk.Label fullname_label; | 29 | private Gtk.Label fullname_label; |
473 | 30 | private Gtk.Label status_label; | 30 | private Gtk.Label status_label; |
474 | 31 | 31 | ||
476 | 32 | public Userbox (Session.Services.User user) { | 32 | public Userbox (Act.User user) { |
477 | 33 | this.user = user; | 33 | this.user = user; |
478 | 34 | build_ui (); | 34 | build_ui (); |
479 | 35 | connect_signals (); | 35 | connect_signals (); |
481 | 36 | user.update_properties (); | 36 | update (); |
482 | 37 | update_state (); | ||
483 | 37 | } | 38 | } |
484 | 38 | 39 | ||
485 | 39 | public Userbox.from_data (string fullname, bool logged_in, bool is_guest = false) { | 40 | public Userbox.from_data (string fullname, bool logged_in, bool is_guest = false) { |
486 | 40 | this.is_guest = is_guest; | 41 | this.is_guest = is_guest; |
488 | 41 | build_ui (false); | 42 | this.user = null; |
489 | 43 | build_ui (); | ||
490 | 42 | fullname_label.label = "<b>" + fullname + "</b>"; | 44 | fullname_label.label = "<b>" + fullname + "</b>"; |
492 | 43 | update_state (logged_in); | 45 | update_state (); |
493 | 44 | } | 46 | } |
494 | 45 | 47 | ||
496 | 46 | private void build_ui (bool load_icon = true) { | 48 | private void build_ui () { |
497 | 47 | get_style_context ().add_class ("menuitem"); | 49 | get_style_context ().add_class ("menuitem"); |
498 | 48 | 50 | ||
499 | 49 | var grid = new Gtk.Grid (); | 51 | var grid = new Gtk.Grid (); |
500 | @@ -56,11 +58,12 @@ | |||
501 | 56 | status_label = new Gtk.Label (LOGGED_OFF); | 58 | status_label = new Gtk.Label (LOGGED_OFF); |
502 | 57 | status_label.halign = Gtk.Align.START; | 59 | status_label.halign = Gtk.Align.START; |
503 | 58 | 60 | ||
507 | 59 | if (load_icon) { | 61 | if (is_guest) { |
505 | 60 | avatar = new Granite.Widgets.Avatar.from_file (user.icon_file, ICON_SIZE); | ||
506 | 61 | } else { | ||
508 | 62 | avatar = new Granite.Widgets.Avatar.with_default_icon (ICON_SIZE); | 62 | avatar = new Granite.Widgets.Avatar.with_default_icon (ICON_SIZE); |
509 | 63 | } else { | ||
510 | 64 | avatar = new Granite.Widgets.Avatar.from_file (user.get_icon_file (), ICON_SIZE); | ||
511 | 63 | } | 65 | } |
512 | 66 | |||
513 | 64 | avatar.margin_end = 6; | 67 | avatar.margin_end = 6; |
514 | 65 | 68 | ||
515 | 66 | grid.attach (avatar, 0, 0, 3, 3); | 69 | grid.attach (avatar, 0, 0, 3, 3); |
516 | @@ -69,11 +72,34 @@ | |||
517 | 69 | this.add (grid); | 72 | this.add (grid); |
518 | 70 | } | 73 | } |
519 | 71 | 74 | ||
522 | 72 | public void update (string? fullname, string icon) { | 75 | // For some reason Act.User.is_logged_in () does not work |
523 | 73 | this.fullname_label.set_label ("<b>" + fullname + "</b>"); | 76 | public UserState get_user_state () { |
524 | 77 | if (is_guest) { | ||
525 | 78 | return Services.UserManager.get_guest_state (); | ||
526 | 79 | } | ||
527 | 80 | |||
528 | 81 | return Services.UserManager.get_user_state (user.get_uid ()); | ||
529 | 82 | } | ||
530 | 83 | |||
531 | 84 | public bool is_logged_in () { | ||
532 | 85 | var state = get_user_state (); | ||
533 | 86 | return state == UserState.ONLINE || state == UserState.ACTIVE; | ||
534 | 87 | } | ||
535 | 88 | |||
536 | 89 | public void set_can_activate (bool can_activate) { | ||
537 | 90 | selectable = can_activate; | ||
538 | 91 | activatable = can_activate; | ||
539 | 92 | } | ||
540 | 93 | |||
541 | 94 | private void update () { | ||
542 | 95 | if (is_guest) { | ||
543 | 96 | return; | ||
544 | 97 | } | ||
545 | 98 | |||
546 | 99 | this.fullname_label.label = "<b>" + user.get_real_name () + "</b>"; | ||
547 | 74 | 100 | ||
548 | 75 | try { | 101 | try { |
550 | 76 | var pixbuf = new Gdk.Pixbuf.from_file (icon); | 102 | var pixbuf = new Gdk.Pixbuf.from_file (user.get_icon_file ()); |
551 | 77 | pixbuf = pixbuf.scale_simple (ICON_SIZE, ICON_SIZE, Gdk.InterpType.BILINEAR); | 103 | pixbuf = pixbuf.scale_simple (ICON_SIZE, ICON_SIZE, Gdk.InterpType.BILINEAR); |
552 | 78 | avatar.pixbuf = pixbuf; | 104 | avatar.pixbuf = pixbuf; |
553 | 79 | } catch (Error e) { | 105 | } catch (Error e) { |
554 | @@ -81,21 +107,33 @@ | |||
555 | 81 | } | 107 | } |
556 | 82 | } | 108 | } |
557 | 83 | 109 | ||
560 | 84 | public void update_state (bool logged_in) { | 110 | public void update_state () { |
561 | 85 | if (logged_in) { | 111 | var state = get_user_state (); |
562 | 112 | set_can_activate (state != UserState.ACTIVE); | ||
563 | 113 | if (is_logged_in ()) { | ||
564 | 86 | status_label.label = LOGGED_IN; | 114 | status_label.label = LOGGED_IN; |
565 | 87 | } else { | 115 | } else { |
566 | 88 | status_label.label = LOGGED_OFF; | 116 | status_label.label = LOGGED_OFF; |
567 | 89 | } | 117 | } |
568 | 118 | |||
569 | 119 | changed (); | ||
570 | 90 | } | 120 | } |
571 | 91 | 121 | ||
572 | 92 | private void connect_signals () { | 122 | private void connect_signals () { |
576 | 93 | user.properties_updated.connect (() => { | 123 | user.changed.connect (() => { |
577 | 94 | update (user.real_name, user.icon_file); | 124 | update (); |
578 | 95 | update_state (user.get_state ()); | 125 | update_state (); |
579 | 96 | }); | 126 | }); |
580 | 97 | 127 | ||
581 | 98 | user.bind_property ("locked", this, "visible", BindingFlags.SYNC_CREATE | BindingFlags.INVERT_BOOLEAN); | 128 | user.bind_property ("locked", this, "visible", BindingFlags.SYNC_CREATE | BindingFlags.INVERT_BOOLEAN); |
583 | 99 | user.bind_property ("locked", this, "no_show_all", BindingFlags.SYNC_CREATE); | 129 | user.bind_property ("locked", this, "no-show-all", BindingFlags.SYNC_CREATE); |
584 | 100 | } | 130 | } |
585 | 131 | |||
586 | 132 | public override bool draw (Cairo.Context ctx) { | ||
587 | 133 | if (!get_selectable ()) { | ||
588 | 134 | get_style_context ().set_state (Gtk.StateFlags.NORMAL); | ||
589 | 135 | } | ||
590 | 136 | |||
591 | 137 | return base.draw (ctx); | ||
592 | 138 | } | ||
593 | 101 | } | 139 | } |
594 | 102 | 140 | ||
595 | === modified file 'src/Widgets/UserListBox.vala' | |||
596 | --- src/Widgets/UserListBox.vala 2016-02-22 17:24:06 +0000 | |||
597 | +++ src/Widgets/UserListBox.vala 2016-08-08 16:32:36 +0000 | |||
598 | @@ -18,6 +18,8 @@ | |||
599 | 18 | */ | 18 | */ |
600 | 19 | 19 | ||
601 | 20 | public class Session.Widgets.UserListBox : Gtk.ListBox { | 20 | public class Session.Widgets.UserListBox : Gtk.ListBox { |
602 | 21 | public signal void close (); | ||
603 | 22 | |||
604 | 21 | private SeatInterface? seat = null; | 23 | private SeatInterface? seat = null; |
605 | 22 | private string session_path; | 24 | private string session_path; |
606 | 23 | private bool has_guest; | 25 | private bool has_guest; |
607 | @@ -32,6 +34,7 @@ | |||
608 | 32 | stderr.printf ("DisplayManager.Seat error: %s\n", e.message); | 34 | stderr.printf ("DisplayManager.Seat error: %s\n", e.message); |
609 | 33 | } | 35 | } |
610 | 34 | 36 | ||
611 | 37 | this.set_sort_func (sort_func); | ||
612 | 35 | this.set_activate_on_single_click (true); | 38 | this.set_activate_on_single_click (true); |
613 | 36 | } | 39 | } |
614 | 37 | 40 | ||
615 | @@ -50,14 +53,35 @@ | |||
616 | 50 | return; | 53 | return; |
617 | 51 | } | 54 | } |
618 | 52 | 55 | ||
619 | 56 | close (); | ||
620 | 53 | try { | 57 | try { |
621 | 54 | if (userbox.is_guest) { | 58 | if (userbox.is_guest) { |
622 | 55 | seat.switch_to_guest (""); | 59 | seat.switch_to_guest (""); |
623 | 56 | } else { | 60 | } else { |
626 | 57 | seat.switch_to_user (userbox.user.user_name, session_path); | 61 | seat.switch_to_user (userbox.user.get_user_name (), session_path); |
627 | 58 | } | 62 | } |
628 | 59 | } catch (IOError e) { | 63 | } catch (IOError e) { |
629 | 60 | stderr.printf ("DisplayManager.Seat error: %s\n", e.message); | 64 | stderr.printf ("DisplayManager.Seat error: %s\n", e.message); |
630 | 61 | } | 65 | } |
631 | 62 | } | 66 | } |
632 | 63 | } | ||
633 | 64 | \ No newline at end of file | 67 | \ No newline at end of file |
634 | 68 | |||
635 | 69 | // We could use here Act.User.collate () but we want to show the logged user first | ||
636 | 70 | public int sort_func (Gtk.ListBoxRow row1, Gtk.ListBoxRow row2) { | ||
637 | 71 | var userbox1 = (Userbox)row1; | ||
638 | 72 | var userbox2 = (Userbox)row2; | ||
639 | 73 | |||
640 | 74 | if (userbox1.get_user_state () == UserState.ACTIVE) { | ||
641 | 75 | return -1; | ||
642 | 76 | } else if (userbox2.get_user_state () == UserState.ACTIVE) { | ||
643 | 77 | return 1; | ||
644 | 78 | } | ||
645 | 79 | |||
646 | 80 | if (userbox1.is_guest && !userbox2.is_guest) { | ||
647 | 81 | return 1; | ||
648 | 82 | } else if (!userbox1.is_guest && userbox2.is_guest) { | ||
649 | 83 | return -1; | ||
650 | 84 | } | ||
651 | 85 | |||
652 | 86 | return 0; | ||
653 | 87 | } | ||
654 | 88 | } | ||
655 | 65 | \ No newline at end of file | 89 | \ No newline at end of file |
Code wise the indicator now looks better than ever! The only problem I have is with the current user being clickable.