GCC Code Coverage Report


Directory: ./
File: panels/system/region/cc-region-page.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 408 0.0%
Functions: 0 44 0.0%
Branches: 0 219 0.0%

Line Branch Exec Source
1 /*
2 * cc-region-page.c
3 *
4 * Copyright (C) 2010 Intel, Inc
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 *
19 * Authors:
20 * Sergey Udaltsov <svu@gnome.org>
21 * Gotam Gorabh <gautamy672@gmail.com>
22 */
23
24 #undef G_LOG_DOMAIN
25 #define G_LOG_DOMAIN "cc-region-page"
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include "cc-common-language.h"
32 #include "cc-format-chooser.h"
33 #include "cc-language-chooser.h"
34 #include "cc-list-row.h"
35 #include "cc-region-page.h"
36
37 #include <act/act.h>
38 #include <errno.h>
39 #include <glib/gi18n.h>
40 #include <gio/gio.h>
41 #include <gio/gdesktopappinfo.h>
42 #include <gtk/gtk.h>
43
44 #define GNOME_DESKTOP_USE_UNSTABLE_API
45 #include <libgnome-desktop/gnome-languages.h>
46 #include <libgnome-desktop/gnome-xkb-info.h>
47
48 #include <locale.h>
49 #include <polkit/polkit.h>
50
51 #define GNOME_SYSTEM_LOCALE_DIR "org.gnome.system.locale"
52 #define KEY_REGION "region"
53
54 #define DEFAULT_LOCALE "en_US.utf-8"
55
56 typedef enum {
57 USER,
58 SYSTEM,
59 } CcLocaleTarget;
60
61 struct _CcRegionPage {
62 AdwNavigationPage parent_instance;
63
64 CcListRow *formats_row;
65 AdwBanner *banner;
66 GtkSizeGroup *input_size_group;
67 CcListRow *login_formats_row;
68 GtkWidget *login_group;
69 CcListRow *login_language_row;
70 CcListRow *language_row;
71
72 gboolean login_auto_apply;
73 GPermission *permission;
74 GDBusProxy *localed;
75 GDBusProxy *session;
76
77 ActUserManager *user_manager;
78 ActUser *user;
79 GSettings *locale_settings;
80
81 gchar *language;
82 gchar *region;
83 gchar *system_language;
84 gchar *system_region;
85
86 GCancellable *cancellable;
87 };
88
89 G_DEFINE_TYPE (CcRegionPage, cc_region_page, ADW_TYPE_NAVIGATION_PAGE)
90
91 /* Auxiliary methods */
92
93 static GFile *
94 get_needs_restart_file (void)
95 {
96 g_autofree gchar *path = NULL;
97
98 path = g_build_filename (g_get_user_runtime_dir (),
99 "gnome-control-center-region-needs-restart",
100 NULL);
101 return g_file_new_for_path (path);
102 }
103
104 static void
105 restart_now (CcRegionPage *self)
106 {
107 g_autoptr(GFile) file = NULL;
108
109 file = get_needs_restart_file ();
110 g_file_delete (file, NULL, NULL);
111
112 g_dbus_proxy_call (self->session,
113 "Logout",
114 g_variant_new ("(u)", 0),
115 G_DBUS_CALL_FLAGS_NONE,
116 -1, NULL, NULL, NULL);
117 }
118
119 static void
120 set_restart_notification_visible (CcRegionPage *self,
121 const gchar *locale,
122 gboolean visible)
123 {
124 locale_t new_locale;
125 locale_t current_locale;
126 g_autoptr(GFile) file = NULL;
127 g_autoptr(GFileOutputStream) output_stream = NULL;
128 g_autoptr(GError) error = NULL;
129
130 if (locale) {
131 new_locale = newlocale (LC_MESSAGES_MASK, locale, (locale_t) 0);
132 if (new_locale != (locale_t) 0) {
133 current_locale = uselocale (new_locale);
134 uselocale (current_locale);
135 freelocale (new_locale);
136 } else {
137 g_warning ("Failed to create locale %s: %s", locale, g_strerror (errno));
138 }
139 }
140
141 adw_banner_set_revealed (self->banner, visible);
142
143 file = get_needs_restart_file ();
144
145 if (!visible) {
146 g_file_delete (file, NULL, NULL);
147 return;
148 }
149
150 output_stream = g_file_create (file, G_FILE_CREATE_NONE, NULL, &error);
151 if (output_stream == NULL) {
152 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
153 g_warning ("Unable to create %s: %s", g_file_get_path (file), error->message);
154 }
155 }
156
157 typedef struct {
158 CcRegionPage *self;
159 int category;
160 gchar *target_locale;
161 } MaybeNotifyData;
162
163 static void
164 maybe_notify_data_free (MaybeNotifyData *data)
165 {
166 g_free (data->target_locale);
167 g_free (data);
168 }
169
170 G_DEFINE_AUTOPTR_CLEANUP_FUNC (MaybeNotifyData, maybe_notify_data_free)
171
172 static void
173 maybe_notify_finish (GObject *source,
174 GAsyncResult *res,
175 gpointer data)
176 {
177 g_autoptr(MaybeNotifyData) mnd = data;
178 CcRegionPage *self = mnd->self;
179 g_autoptr(GError) error = NULL;
180 g_autoptr(GVariant) retval = NULL;
181 g_autofree gchar *current_lang_code = NULL;
182 g_autofree gchar *current_country_code = NULL;
183 g_autofree gchar *target_lang_code = NULL;
184 g_autofree gchar *target_country_code = NULL;
185 const gchar *current_locale = NULL;
186
187 retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
188 if (!retval) {
189 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
190 g_warning ("Failed to get locale: %s\n", error->message);
191 return;
192 }
193
194 g_variant_get (retval, "(&s)", &current_locale);
195
196 if (!gnome_parse_locale (current_locale,
197 &current_lang_code,
198 &current_country_code,
199 NULL,
200 NULL))
201 return;
202
203 if (!gnome_parse_locale (mnd->target_locale,
204 &target_lang_code,
205 &target_country_code,
206 NULL,
207 NULL))
208 return;
209
210 if (g_str_equal (current_lang_code, target_lang_code) == FALSE ||
211 g_str_equal (current_country_code, target_country_code) == FALSE)
212 set_restart_notification_visible (self,
213 mnd->category == LC_MESSAGES ? mnd->target_locale : NULL,
214 TRUE);
215 else
216 set_restart_notification_visible (self,
217 mnd->category == LC_MESSAGES ? mnd->target_locale : NULL,
218 FALSE);
219 }
220
221 static void
222 maybe_notify (CcRegionPage *self,
223 int category,
224 const gchar *target_locale)
225 {
226 MaybeNotifyData *mnd;
227
228 mnd = g_new0 (MaybeNotifyData, 1);
229 mnd->self = self;
230 mnd->category = category;
231 mnd->target_locale = g_strdup (target_locale);
232
233 g_dbus_proxy_call (self->session,
234 "GetLocale",
235 g_variant_new ("(i)", category),
236 G_DBUS_CALL_FLAGS_NONE,
237 -1,
238 self->cancellable,
239 maybe_notify_finish,
240 mnd);
241 }
242
243 static void
244 set_localed_locale (CcRegionPage *self)
245 {
246 g_autoptr(GVariantBuilder) b = NULL;
247 g_autofree gchar *lang_value = NULL;
248
249 b = g_variant_builder_new (G_VARIANT_TYPE ("as"));
250 lang_value = g_strconcat ("LANG=", self->system_language, NULL);
251 g_variant_builder_add (b, "s", lang_value);
252
253 if (self->system_region != NULL) {
254 g_autofree gchar *time_value = NULL;
255 g_autofree gchar *numeric_value = NULL;
256 g_autofree gchar *monetary_value = NULL;
257 g_autofree gchar *measurement_value = NULL;
258 g_autofree gchar *paper_value = NULL;
259 time_value = g_strconcat ("LC_TIME=", self->system_region, NULL);
260 g_variant_builder_add (b, "s", time_value);
261 numeric_value = g_strconcat ("LC_NUMERIC=", self->system_region, NULL);
262 g_variant_builder_add (b, "s", numeric_value);
263 monetary_value = g_strconcat ("LC_MONETARY=", self->system_region, NULL);
264 g_variant_builder_add (b, "s", monetary_value);
265 measurement_value = g_strconcat ("LC_MEASUREMENT=", self->system_region, NULL);
266 g_variant_builder_add (b, "s", measurement_value);
267 paper_value = g_strconcat ("LC_PAPER=", self->system_region, NULL);
268 g_variant_builder_add (b, "s", paper_value);
269 }
270 g_dbus_proxy_call (self->localed,
271 "SetLocale",
272 g_variant_new ("(asb)", b, TRUE),
273 G_DBUS_CALL_FLAGS_NONE,
274 -1, NULL, NULL, NULL);
275 }
276
277 static void
278 set_system_language (CcRegionPage *self,
279 const gchar *language)
280 {
281 if (g_strcmp0 (language, self->system_language) == 0)
282 return;
283
284 g_free (self->system_language);
285 self->system_language = g_strdup (language);
286
287 set_localed_locale (self);
288 }
289
290 static void
291 update_language (CcRegionPage *self,
292 CcLocaleTarget target,
293 const gchar *language)
294 {
295 switch (target) {
296 case USER:
297 if (g_strcmp0 (language, self->language) == 0)
298 return;
299 act_user_set_language (self->user, language);
300 if (self->login_auto_apply)
301 set_system_language (self, language);
302 maybe_notify (self, LC_MESSAGES, language);
303 break;
304
305 case SYSTEM:
306 set_system_language (self, language);
307 break;
308 }
309 }
310
311 static void
312 set_system_region (CcRegionPage *self,
313 const gchar *region)
314 {
315 if (g_strcmp0 (region, self->system_region) == 0)
316 return;
317
318 g_free (self->system_region);
319 self->system_region = g_strdup (region);
320
321 set_localed_locale (self);
322 }
323
324 static void
325 update_region (CcRegionPage *self,
326 CcLocaleTarget target,
327 const gchar *region)
328 {
329 switch (target) {
330 case USER:
331 if (g_strcmp0 (region, self->region) == 0)
332 return;
333 if (region == NULL || region[0] == '\0')
334 g_settings_reset (self->locale_settings, KEY_REGION);
335 else
336 g_settings_set_string (self->locale_settings, KEY_REGION, region);
337 if (self->login_auto_apply)
338 set_system_region (self, region);
339
340 if (region == NULL || region[0] == '\0') {
341 // Formats (region) are being reset as part of changing the language,
342 // and that already triggers the notification check.
343 return;
344 }
345
346 maybe_notify (self, LC_TIME, region);
347 break;
348
349 case SYSTEM:
350 set_system_region (self, region);
351 break;
352 }
353 }
354
355 static void
356 language_response (CcRegionPage *self,
357 gint response_id,
358 CcLanguageChooser *chooser)
359 {
360 const gchar *language;
361
362 if (response_id == GTK_RESPONSE_OK) {
363 CcLocaleTarget target;
364
365 language = cc_language_chooser_get_language (chooser);
366 target = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (chooser), "target"));
367 update_language (self, target, language);
368
369 /* Keep format strings consistent with the user's language */
370 update_region (self, target, NULL);
371 }
372
373 gtk_window_destroy (GTK_WINDOW (chooser));
374 }
375
376 static const gchar *
377 get_effective_language (CcRegionPage *self,
378 CcLocaleTarget target)
379 {
380 switch (target) {
381 case USER:
382 return self->language;
383 case SYSTEM:
384 return self->system_language;
385 default:
386 g_assert_not_reached ();
387 }
388 }
389
390 static void
391 show_language_chooser (CcRegionPage *self,
392 CcLocaleTarget target)
393 {
394 CcLanguageChooser *chooser;
395 GtkNative *native;
396
397 chooser = cc_language_chooser_new ();
398 cc_language_chooser_set_language (chooser, get_effective_language (self, target));
399 g_object_set_data (G_OBJECT (chooser), "target", GINT_TO_POINTER (target));
400 g_signal_connect_object (chooser, "response",
401 G_CALLBACK (language_response), self, G_CONNECT_SWAPPED);
402
403 native = gtk_widget_get_native (GTK_WIDGET (self));
404 gtk_window_set_transient_for (GTK_WINDOW (chooser),
405 GTK_WINDOW (native));
406 gtk_window_present (GTK_WINDOW (chooser));
407 }
408
409 static const gchar *
410 get_effective_region (CcRegionPage *self,
411 CcLocaleTarget target)
412 {
413 const gchar *region = NULL;
414
415 switch (target) {
416 case USER:
417 region = self->region;
418 break;
419
420 case SYSTEM:
421 region = self->system_region;
422 break;
423 }
424
425 /* Region setting might be empty - show the language because
426 * that's what LC_TIME and others will effectively be when the
427 * user logs in again. */
428 if (region == NULL || region[0] == '\0')
429 region = get_effective_language (self, target);
430
431 return region;
432 }
433
434 static void
435 format_response (CcRegionPage *self,
436 gint response_id,
437 CcFormatChooser *chooser)
438 {
439 const gchar *region;
440
441 if (response_id == GTK_RESPONSE_OK) {
442 CcLocaleTarget target;
443
444 region = cc_format_chooser_get_region (chooser);
445 target = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (chooser), "target"));
446
447 update_region (self, target, region);
448 }
449
450 gtk_window_destroy (GTK_WINDOW (chooser));
451 }
452
453 static void
454 show_region_chooser (CcRegionPage *self,
455 CcLocaleTarget target)
456 {
457 CcFormatChooser *chooser;
458 GtkNative *native;
459
460 chooser = cc_format_chooser_new ();
461 cc_format_chooser_set_region (chooser, get_effective_region (self, target));
462 g_object_set_data (G_OBJECT (chooser), "target", GINT_TO_POINTER (target));
463 g_signal_connect_object (chooser, "response",
464 G_CALLBACK (format_response), self, G_CONNECT_SWAPPED);
465
466 native = gtk_widget_get_native (GTK_WIDGET (self));
467 gtk_window_set_transient_for (GTK_WINDOW (chooser),
468 GTK_WINDOW (native));
469 gtk_window_present (GTK_WINDOW (chooser));
470 }
471
472 static gboolean
473 permission_acquired (GPermission *permission, GAsyncResult *res, const gchar *action)
474 {
475 g_autoptr(GError) error = NULL;
476
477 if (!g_permission_acquire_finish (permission, res, &error)) {
478 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
479 g_warning ("Failed to acquire permission to %s: %s\n", error->message, action);
480 return FALSE;
481 }
482
483 return TRUE;
484 }
485
486 static void
487 choose_language_permission_cb (GObject *source, GAsyncResult *res, gpointer user_data)
488 {
489 CcRegionPage *self = user_data;
490 if (permission_acquired (G_PERMISSION (source), res, "choose language"))
491 show_language_chooser (self, SYSTEM);
492 }
493
494 static void
495 choose_region_permission_cb (GObject *source, GAsyncResult *res, gpointer user_data)
496 {
497 CcRegionPage *self = user_data;
498 if (permission_acquired (G_PERMISSION (source), res, "choose region"))
499 show_region_chooser (self, SYSTEM);
500 }
501
502 static void
503 update_user_region_row (CcRegionPage *self)
504 {
505 const gchar *region = get_effective_region (self, USER);
506 g_autofree gchar *name = NULL;
507
508 if (region)
509 name = gnome_get_country_from_locale (region, region);
510
511 if (!name)
512 name = gnome_get_country_from_locale (DEFAULT_LOCALE, DEFAULT_LOCALE);
513
514 cc_list_row_set_secondary_label (self->formats_row, name);
515 }
516
517 static void
518 update_user_language_row (CcRegionPage *self)
519 {
520 g_autofree gchar *name = NULL;
521
522 if (self->language)
523 name = gnome_get_language_from_locale (self->language, self->language);
524
525 if (!name)
526 name = gnome_get_language_from_locale (DEFAULT_LOCALE, DEFAULT_LOCALE);
527
528 cc_list_row_set_secondary_label (self->language_row, name);
529
530 /* Formats will change too if not explicitly set. */
531 update_user_region_row (self);
532 }
533
534 static void
535 update_language_from_user (CcRegionPage *self)
536 {
537 const gchar *language = NULL;
538
539 if (act_user_is_loaded (self->user))
540 language = act_user_get_language (self->user);
541
542 if (language == NULL || *language == '\0')
543 language = setlocale (LC_MESSAGES, NULL);
544
545 g_free (self->language);
546 self->language = g_strdup (language);
547 update_user_language_row (self);
548 }
549
550 static void
551 update_region_from_setting (CcRegionPage *self)
552 {
553 g_free (self->region);
554 self->region = g_settings_get_string (self->locale_settings, KEY_REGION);
555 update_user_region_row (self);
556 }
557
558 static void
559 setup_language_section (CcRegionPage *self)
560 {
561 self->user = act_user_manager_get_user_by_id (self->user_manager, getuid ());
562 g_signal_connect_object (self->user, "notify::language",
563 G_CALLBACK (update_language_from_user), self, G_CONNECT_SWAPPED);
564 g_signal_connect_object (self->user, "notify::is-loaded",
565 G_CALLBACK (update_language_from_user), self, G_CONNECT_SWAPPED);
566
567 self->locale_settings = g_settings_new (GNOME_SYSTEM_LOCALE_DIR);
568 g_signal_connect_object (self->locale_settings, "changed::" KEY_REGION,
569 G_CALLBACK (update_region_from_setting), self, G_CONNECT_SWAPPED);
570
571 update_language_from_user (self);
572 update_region_from_setting (self);
573 }
574
575 static void
576 update_login_region (CcRegionPage *self)
577 {
578 g_autofree gchar *name = NULL;
579
580 if (self->system_region)
581 name = gnome_get_country_from_locale (self->system_region, self->system_region);
582 else if (self->system_language)
583 name = gnome_get_country_from_locale (self->system_language, self->system_language);
584
585 if (!name)
586 name = gnome_get_country_from_locale (DEFAULT_LOCALE, DEFAULT_LOCALE);
587
588 cc_list_row_set_secondary_label (self->login_formats_row, name);
589 }
590
591 static void
592 update_login_language (CcRegionPage *self)
593 {
594 g_autofree gchar *name = NULL;
595
596 if (self->system_language)
597 name = gnome_get_language_from_locale (self->system_language, self->system_language);
598
599 if (!name)
600 name = gnome_get_language_from_locale (DEFAULT_LOCALE, DEFAULT_LOCALE);
601
602 cc_list_row_set_secondary_label (self->login_language_row, name);
603 update_login_region (self);
604 }
605
606 static void
607 set_login_button_visibility (CcRegionPage *self)
608 {
609 gboolean has_multiple_users;
610 gboolean loaded;
611
612 g_object_get (self->user_manager, "is-loaded", &loaded, NULL);
613 if (!loaded)
614 return;
615
616 g_object_get (self->user_manager, "has-multiple-users", &has_multiple_users, NULL);
617
618 self->login_auto_apply = !has_multiple_users && g_permission_get_allowed (self->permission);
619 gtk_widget_set_visible (self->login_group, !self->login_auto_apply);
620
621 g_signal_handlers_disconnect_by_func (self->user_manager, set_login_button_visibility, self);
622 }
623
624 /* Callbacks */
625
626 static void
627 on_localed_properties_changed (GDBusProxy *localed_proxy,
628 GVariant *changed_properties,
629 const gchar **invalidated_properties,
630 CcRegionPage *self)
631 {
632 g_autoptr(GVariant) v = NULL;
633
634 v = g_dbus_proxy_get_cached_property (localed_proxy, "Locale");
635 if (v) {
636 g_autofree const gchar **strv = NULL;
637 gsize len;
638 gint i;
639 const gchar *lang, *messages, *time;
640
641 strv = g_variant_get_strv (v, &len);
642
643 lang = messages = time = NULL;
644 for (i = 0; strv[i]; i++) {
645 if (g_str_has_prefix (strv[i], "LANG=")) {
646 lang = strv[i] + strlen ("LANG=");
647 } else if (g_str_has_prefix (strv[i], "LC_MESSAGES=")) {
648 messages = strv[i] + strlen ("LC_MESSAGES=");
649 } else if (g_str_has_prefix (strv[i], "LC_TIME=")) {
650 time = strv[i] + strlen ("LC_TIME=");
651 }
652 }
653 if (!lang) {
654 lang = setlocale (LC_MESSAGES, NULL);
655 }
656 if (!messages) {
657 messages = lang;
658 }
659 g_free (self->system_language);
660 self->system_language = g_strdup (messages);
661 g_free (self->system_region);
662 self->system_region = g_strdup (time);
663
664 update_login_language (self);
665 }
666 }
667
668 static void
669 localed_proxy_ready (GObject *source,
670 GAsyncResult *res,
671 gpointer data)
672 {
673 CcRegionPage *self = data;
674 GDBusProxy *proxy;
675 g_autoptr(GError) error = NULL;
676
677 proxy = g_dbus_proxy_new_finish (res, &error);
678
679 if (!proxy) {
680 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
681 g_warning ("Failed to contact localed: %s\n", error->message);
682 return;
683 }
684
685 self->localed = proxy;
686
687 g_signal_connect_object (self->localed,
688 "g-properties-changed",
689 G_CALLBACK (on_localed_properties_changed),
690 self,
691 0);
692
693 on_localed_properties_changed (self->localed, NULL, NULL, self);
694 }
695
696 static void
697 setup_login_permission (CcRegionPage *self)
698 {
699 g_autoptr(GDBusConnection) bus = NULL;
700 g_autoptr(GError) error = NULL;
701 gboolean can_acquire;
702 gboolean loaded;
703
704 self->permission = polkit_permission_new_sync ("org.freedesktop.locale1.set-locale", NULL, NULL, &error);
705 if (self->permission == NULL) {
706 g_warning ("Could not get 'org.freedesktop.locale1.set-locale' permission: %s",
707 error->message);
708 return;
709 }
710
711 bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
712 g_dbus_proxy_new (bus,
713 G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
714 NULL,
715 "org.freedesktop.locale1",
716 "/org/freedesktop/locale1",
717 "org.freedesktop.locale1",
718 self->cancellable,
719 (GAsyncReadyCallback) localed_proxy_ready,
720 self);
721
722 g_object_get (self->user_manager, "is-loaded", &loaded, NULL);
723 if (loaded)
724 set_login_button_visibility (self);
725 else
726 g_signal_connect_object (self->user_manager, "notify::is-loaded",
727 G_CALLBACK (set_login_button_visibility), self, G_CONNECT_SWAPPED);
728
729 can_acquire = self->permission &&
730 (g_permission_get_allowed (self->permission) ||
731 g_permission_get_can_acquire (self->permission));
732 gtk_widget_set_sensitive (self->login_group, can_acquire);
733 }
734
735 static void
736 session_proxy_ready (GObject *source,
737 GAsyncResult *res,
738 gpointer data)
739 {
740 CcRegionPage *self = data;
741 GDBusProxy *proxy;
742 g_autoptr(GError) error = NULL;
743
744 proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
745
746 if (!proxy) {
747 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
748 g_warning ("Failed to contact gnome-session: %s\n", error->message);
749 return;
750 }
751
752 self->session = proxy;
753 }
754
755 static void
756 on_login_formats_row_activated_cb (CcRegionPage *self)
757 {
758 if (g_permission_get_allowed (self->permission)) {
759 show_region_chooser (self, SYSTEM);
760 } else if (g_permission_get_can_acquire (self->permission)) {
761 g_permission_acquire_async (self->permission,
762 self->cancellable,
763 choose_region_permission_cb,
764 self);
765 }
766 }
767
768 static void
769 on_login_language_row_activated_cb (CcRegionPage *self)
770 {
771 if (g_permission_get_allowed (self->permission)) {
772 show_language_chooser (self, SYSTEM);
773 } else if (g_permission_get_can_acquire (self->permission)) {
774 g_permission_acquire_async (self->permission,
775 self->cancellable,
776 choose_language_permission_cb,
777 self);
778 }
779 }
780
781 static void
782 on_user_formats_row_activated_cb (CcRegionPage *self)
783 {
784 show_region_chooser (self, USER);
785 }
786
787 static void
788 on_user_language_row_activated_cb (CcRegionPage *self)
789 {
790 show_language_chooser (self, USER);
791 }
792
793 /* GObject overrides */
794
795 static void
796 cc_region_page_finalize (GObject *object)
797 {
798 CcRegionPage *self = CC_REGION_PAGE (object);
799 GtkWidget *chooser;
800
801 if (self->user_manager) {
802 g_signal_handlers_disconnect_by_data (self->user_manager, self);
803 self->user_manager = NULL;
804 }
805
806 if (self->user) {
807 g_signal_handlers_disconnect_by_data (self->user, self);
808 self->user = NULL;
809 }
810
811 g_clear_object (&self->permission);
812 g_clear_object (&self->localed);
813 g_clear_object (&self->session);
814 g_clear_object (&self->locale_settings);
815 g_free (self->language);
816 g_free (self->region);
817 g_free (self->system_language);
818 g_free (self->system_region);
819
820 chooser = g_object_get_data (G_OBJECT (self), "input-chooser");
821 if (chooser)
822 gtk_window_destroy (GTK_WINDOW (chooser));
823
824 g_cancellable_cancel (self->cancellable);
825 g_clear_object (&self->cancellable);
826
827 G_OBJECT_CLASS (cc_region_page_parent_class)->finalize (object);
828 }
829
830 static void
831 cc_region_page_class_init (CcRegionPageClass * klass)
832 {
833 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
834 GObjectClass *object_class = G_OBJECT_CLASS (klass);
835
836 object_class->finalize = cc_region_page_finalize;
837
838 g_type_ensure (CC_TYPE_LIST_ROW);
839
840 gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/system/region/cc-region-page.ui");
841
842 gtk_widget_class_bind_template_child (widget_class, CcRegionPage, formats_row);
843 gtk_widget_class_bind_template_child (widget_class, CcRegionPage, banner);
844 gtk_widget_class_bind_template_child (widget_class, CcRegionPage, login_formats_row);
845 gtk_widget_class_bind_template_child (widget_class, CcRegionPage, login_group);
846 gtk_widget_class_bind_template_child (widget_class, CcRegionPage, login_language_row);
847 gtk_widget_class_bind_template_child (widget_class, CcRegionPage, language_row);
848
849 gtk_widget_class_bind_template_callback (widget_class, on_login_formats_row_activated_cb);
850 gtk_widget_class_bind_template_callback (widget_class, on_login_language_row_activated_cb);
851 gtk_widget_class_bind_template_callback (widget_class, on_user_formats_row_activated_cb);
852 gtk_widget_class_bind_template_callback (widget_class, on_user_language_row_activated_cb);
853 gtk_widget_class_bind_template_callback (widget_class, restart_now);
854 }
855
856 static void
857 cc_region_page_init (CcRegionPage *self)
858 {
859 g_autoptr(GFile) needs_restart_file = NULL;
860
861 gtk_widget_init_template (GTK_WIDGET (self));
862
863 self->cancellable = g_cancellable_new ();
864
865 self->user_manager = act_user_manager_get_default ();
866
867 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
868 G_DBUS_PROXY_FLAGS_NONE,
869 NULL,
870 "org.gnome.SessionManager",
871 "/org/gnome/SessionManager",
872 "org.gnome.SessionManager",
873 self->cancellable,
874 session_proxy_ready,
875 self);
876
877 setup_login_permission (self);
878 setup_language_section (self);
879
880 needs_restart_file = get_needs_restart_file ();
881 if (g_file_query_exists (needs_restart_file, NULL))
882 set_restart_notification_visible (self, NULL, TRUE);
883 }
884