commit bb92fd683bac36962f4675d2acdde76c55bfe04c Author: Toshaan Bharvani Date: Mon May 23 02:40:04 2022 +0200 initial package creation Signed-off-by: Toshaan Bharvani diff --git a/SOURCES/0001-display-Only-display-configuration-options-if-apply-.patch b/SOURCES/0001-display-Only-display-configuration-options-if-apply-.patch new file mode 100644 index 0000000..54cdd38 --- /dev/null +++ b/SOURCES/0001-display-Only-display-configuration-options-if-apply-.patch @@ -0,0 +1,189 @@ +From f6e0cba768d376a7f710dd8a69c17ec50c7a13a9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Fri, 4 Feb 2022 11:09:24 +0100 +Subject: [PATCH] display: Only display configuration options if apply is + allowed + +org.gnome.Mutter.DisplayConfig contains a new property that tells +whether apply will be allowed to be called or not. Whether it is true or +not depends on policy stored in any of its monitors.xml configuration +files. + +In order to make it clearer that configuration is not possible, except +for night light, make sure to hide the unconfigurable parts, leaving +only night light. +--- + .../display/cc-display-config-manager-dbus.c | 36 +++++++++++++++++++ + panels/display/cc-display-config-manager.c | 6 ++++ + panels/display/cc-display-config-manager.h | 3 ++ + panels/display/cc-display-panel.c | 11 ++++++ + panels/display/cc-display-panel.ui | 2 +- + 5 files changed, 57 insertions(+), 1 deletion(-) + +diff --git a/panels/display/cc-display-config-manager-dbus.c b/panels/display/cc-display-config-manager-dbus.c +index 653bea0b5..392140101 100644 +--- a/panels/display/cc-display-config-manager-dbus.c ++++ b/panels/display/cc-display-config-manager-dbus.c +@@ -31,6 +31,8 @@ struct _CcDisplayConfigManagerDBus + guint monitors_changed_id; + + GVariant *current_state; ++ ++ gboolean apply_allowed; + }; + + G_DEFINE_TYPE (CcDisplayConfigManagerDBus, +@@ -118,6 +120,8 @@ bus_gotten (GObject *object, + CcDisplayConfigManagerDBus *self; + GDBusConnection *connection; + g_autoptr(GError) error = NULL; ++ g_autoptr(GDBusProxy) proxy = NULL; ++ g_autoptr(GVariant) variant = NULL; + + connection = g_bus_get_finish (result, &error); + if (!connection) +@@ -143,12 +147,35 @@ bus_gotten (GObject *object, + monitors_changed, + self, + NULL); ++ ++ proxy = g_dbus_proxy_new_sync (self->connection, ++ G_DBUS_PROXY_FLAGS_NONE, ++ NULL, ++ "org.gnome.Mutter.DisplayConfig", ++ "/org/gnome/Mutter/DisplayConfig", ++ "org.gnome.Mutter.DisplayConfig", ++ NULL, ++ &error); ++ if (!proxy) ++ { ++ g_warning ("Failed to create D-Bus proxy to \"org.gnome.Mutter.DisplayConfig\": %s", ++ error->message); ++ return; ++ } ++ ++ variant = g_dbus_proxy_get_cached_property (proxy, "ApplyMonitorsConfigAllowed"); ++ if (variant) ++ self->apply_allowed = g_variant_get_boolean (variant); ++ else ++ g_warning ("Missing property 'ApplyMonitorsConfigAllowed' on DisplayConfig API"); ++ + get_current_state (self); + } + + static void + cc_display_config_manager_dbus_init (CcDisplayConfigManagerDBus *self) + { ++ self->apply_allowed = TRUE; + self->cancellable = g_cancellable_new (); + g_bus_get (G_BUS_TYPE_SESSION, self->cancellable, bus_gotten, self); + } +@@ -170,6 +197,14 @@ cc_display_config_manager_dbus_finalize (GObject *object) + G_OBJECT_CLASS (cc_display_config_manager_dbus_parent_class)->finalize (object); + } + ++static gboolean ++cc_display_config_manager_dbus_get_apply_allowed (CcDisplayConfigManager *pself) ++{ ++ CcDisplayConfigManagerDBus *self = CC_DISPLAY_CONFIG_MANAGER_DBUS (pself); ++ ++ return self->apply_allowed; ++} ++ + static void + cc_display_config_manager_dbus_class_init (CcDisplayConfigManagerDBusClass *klass) + { +@@ -179,6 +214,7 @@ cc_display_config_manager_dbus_class_init (CcDisplayConfigManagerDBusClass *klas + gobject_class->finalize = cc_display_config_manager_dbus_finalize; + + parent_class->get_current = cc_display_config_manager_dbus_get_current; ++ parent_class->get_apply_allowed = cc_display_config_manager_dbus_get_apply_allowed; + } + + CcDisplayConfigManager * +diff --git a/panels/display/cc-display-config-manager.c b/panels/display/cc-display-config-manager.c +index 0da298a29..3d683c53d 100644 +--- a/panels/display/cc-display-config-manager.c ++++ b/panels/display/cc-display-config-manager.c +@@ -59,3 +59,9 @@ cc_display_config_manager_get_current (CcDisplayConfigManager *self) + { + return CC_DISPLAY_CONFIG_MANAGER_GET_CLASS (self)->get_current (self); + } ++ ++gboolean ++cc_display_config_manager_get_apply_allowed (CcDisplayConfigManager *self) ++{ ++ return CC_DISPLAY_CONFIG_MANAGER_GET_CLASS (self)->get_apply_allowed (self); ++} +diff --git a/panels/display/cc-display-config-manager.h b/panels/display/cc-display-config-manager.h +index 1e1b36373..64f0775e9 100644 +--- a/panels/display/cc-display-config-manager.h ++++ b/panels/display/cc-display-config-manager.h +@@ -34,10 +34,13 @@ struct _CcDisplayConfigManagerClass + GObjectClass parent_class; + + CcDisplayConfig * (*get_current) (CcDisplayConfigManager *self); ++ gboolean (* get_apply_allowed) (CcDisplayConfigManager *self); + }; + + CcDisplayConfig * cc_display_config_manager_get_current (CcDisplayConfigManager *self); + ++gboolean cc_display_config_manager_get_apply_allowed (CcDisplayConfigManager *self); ++ + void _cc_display_config_manager_emit_changed (CcDisplayConfigManager *self); + + G_END_DECLS +diff --git a/panels/display/cc-display-panel.c b/panels/display/cc-display-panel.c +index 93c983f89..2cfd714d3 100644 +--- a/panels/display/cc-display-panel.c ++++ b/panels/display/cc-display-panel.c +@@ -69,6 +69,8 @@ struct _CcDisplayPanel + + gint rebuilding_counter; + ++ GtkWidget *displays_page; ++ + CcDisplayArrangement *arrangement; + CcDisplaySettings *settings; + +@@ -691,6 +693,7 @@ cc_display_panel_class_init (CcDisplayPanelClass *klass) + gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, current_output_label); + gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, display_settings_frame); + gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, multi_selection_box); ++ gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, displays_page); + gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, night_light_page); + gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, output_enabled_switch); + gtk_widget_class_bind_template_child (widget_class, CcDisplayPanel, output_selection_combo); +@@ -779,8 +782,16 @@ rebuild_ui (CcDisplayPanel *panel) + GList *outputs, *l; + CcDisplayConfigType type; + ++ if (!cc_display_config_manager_get_apply_allowed (panel->manager)) ++ { ++ gtk_widget_set_visible (panel->displays_page, FALSE); ++ return; ++ } ++ + panel->rebuilding_counter++; + ++ gtk_widget_set_visible (panel->displays_page, TRUE); ++ + g_list_store_remove_all (panel->primary_display_list); + gtk_list_store_clear (panel->output_selection_list); + +diff --git a/panels/display/cc-display-panel.ui b/panels/display/cc-display-panel.ui +index 855b34814..80fd63ace 100644 +--- a/panels/display/cc-display-panel.ui ++++ b/panels/display/cc-display-panel.ui +@@ -47,7 +47,7 @@ + + + +- ++ + True + False + never +-- +2.33.1 + diff --git a/SOURCES/0001-network-Fix-OWE-settings.patch b/SOURCES/0001-network-Fix-OWE-settings.patch new file mode 100644 index 0000000..0cd0505 --- /dev/null +++ b/SOURCES/0001-network-Fix-OWE-settings.patch @@ -0,0 +1,59 @@ +From 43bb1d9200554527cefaa2ce969bebc80d781c73 Mon Sep 17 00:00:00 2001 +From: Ana Cabral +Date: Mon, 21 Feb 2022 21:49:29 +0100 +Subject: [PATCH] network: Fix OWE settings + +Enhanced Open (OWE) is not being saved properly from connection-editor. +When we create a Wi-Fi connection using Enhanced Open (OWE) Security +from nm-connection-editor and save it, it was not being saved and the +security was being set as "None", with Wireless Security Setting +being discarded. This is fixed by this commit. The fix is also being +done in libnma (implementing OWE in libnma, +https://gitlab.gnome.org/GNOME/libnma/-/issues/9), but this commit +fixes meanwhile it gets ready. + +It was solved by adding treatment for the case in which owe was set. +OWE is not treated anymore in the same case as None. + +https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1521 +--- + .../connection-editor/ce-page-security.c | 23 +++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +diff --git a/panels/network/connection-editor/ce-page-security.c b/panels/network/connection-editor/ce-page-security.c +index a63b9394a..c7cd7d940 100644 +--- a/panels/network/connection-editor/ce-page-security.c ++++ b/panels/network/connection-editor/ce-page-security.c +@@ -460,10 +460,25 @@ ce_page_security_validate (CEPage *page, + } + } + } else { +- /* No security, unencrypted */ +- nm_connection_remove_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY); +- nm_connection_remove_setting (connection, NM_TYPE_SETTING_802_1X); +- valid = TRUE; ++ ++ if (gtk_combo_box_get_active ((CE_PAGE_SECURITY (self))->security_combo) == 0) { ++ /* No security, unencrypted */ ++ nm_connection_remove_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY); ++ nm_connection_remove_setting (connection, NM_TYPE_SETTING_802_1X); ++ valid = TRUE; ++ } else { ++ /* owe case: ++ * fill the connection manually until libnma implements OWE wireless security ++ */ ++ NMSetting *sws; ++ ++ sws = nm_setting_wireless_security_new (); ++ g_object_set (sws, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "owe", NULL); ++ nm_connection_add_setting (connection, sws); ++ nm_connection_remove_setting (connection, NM_TYPE_SETTING_802_1X); ++ valid = TRUE; ++ } ++ + } + + return valid; +-- +2.35.1 + diff --git a/SOURCES/application-use-icon-name-that-exists.patch b/SOURCES/application-use-icon-name-that-exists.patch new file mode 100644 index 0000000..cd44190 --- /dev/null +++ b/SOURCES/application-use-icon-name-that-exists.patch @@ -0,0 +1,42 @@ +From 0e2562c2c5ff081561424c625b090f089ef45fe7 Mon Sep 17 00:00:00 2001 +From: Felipe Borges +Date: Fri, 14 Jan 2022 13:28:24 +0100 +Subject: [PATCH] applications: Set the Icon key in desktop file to a icon that + exists + +While we dynamically append --symbolic to the icons while creating +the sidebar model in +https://gitlab.gnome.org/GNOME/gnome-control-center/-/blob/master/shell/cc-shell-model.c#L270 +There are automation tools (such as rpmdiff) that parse desktop files +and verify whether their Icon= matches to an existing file in the +icon theme package. + +preferences-desktop-apps doesn't exist in adwaita-icon-theme but +preferences-desktop-apps-symbolic does. +--- + panels/applications/gnome-applications-panel.desktop.in.in | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/panels/applications/gnome-applications-panel.desktop.in.in b/panels/applications/gnome-applications-panel.desktop.in.in +index 86e816645..83616c89e 100644 +--- a/panels/applications/gnome-applications-panel.desktop.in.in ++++ b/panels/applications/gnome-applications-panel.desktop.in.in +@@ -4,7 +4,7 @@ Comment=Control various application permissions and settings + Exec=gnome-control-center applications + # FIXME + # Translators: Do NOT translate or transliterate this text (this is an icon file name)! +-Icon=preferences-desktop-apps ++Icon=preferences-desktop-apps-symbolic + Terminal=false + Type=Application + NoDisplay=true +@@ -13,4 +13,4 @@ Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-Acc + OnlyShowIn=GNOME;Unity; + # Translators: Search terms to find the Privacy panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + Keywords=application;flatpak;permission;setting; +-X-GNOME-ControlCenter-HasSidebar=true +\ No newline at end of file ++X-GNOME-ControlCenter-HasSidebar=true +-- +2.33.1 + diff --git a/SOURCES/backport-multitasking-panel.patch b/SOURCES/backport-multitasking-panel.patch new file mode 100644 index 0000000..0ff42a3 --- /dev/null +++ b/SOURCES/backport-multitasking-panel.patch @@ -0,0 +1,15005 @@ +From 6162b67495cb83bf729a711357c1a6b23346544e Mon Sep 17 00:00:00 2001 +From: Georges Basile Stavracas Neto +Date: Sun, 29 Mar 2020 21:13:35 -0300 +Subject: [PATCH 01/10] Introduce the Multitasking panel + +The Multitasking panel brings some additional settings +from Tweaks that are relevant to the general platform. + +Related: https://gitlab.gnome.org/GNOME/gnome-control-center/issues/558 +--- + gnome-control-center.doap | 2 +- + panels/meson.build | 1 + + .../assets/active-screen-edges.svg | 118 +++ + panels/multitasking/assets/hot-corner.svg | 124 ++++ + .../assets/workspaces-primary-display.svg | 130 ++++ + .../assets/workspaces-span-displays.svg | 178 +++++ + panels/multitasking/cc-multitasking-panel.c | 150 ++++ + panels/multitasking/cc-multitasking-panel.h | 30 + + panels/multitasking/cc-multitasking-panel.ui | 357 +++++++++ + panels/multitasking/cc-multitasking-row.c | 684 ++++++++++++++++++ + panels/multitasking/cc-multitasking-row.h | 63 ++ + panels/multitasking/cc-multitasking-row.ui | 122 ++++ + .../gnome-multitasking-panel.desktop.in.in | 14 + + panels/multitasking/icons/meson.build | 4 + + ...g.gnome.Settings-multitasking-symbolic.svg | 106 +++ + panels/multitasking/meson.build | 49 ++ + .../multitasking/multitasking.gresource.xml | 13 + + shell/cc-panel-list.c | 1 + + shell/cc-panel-loader.c | 2 + + shell/gnome-control-center.gresource.xml | 6 + + shell/icons/multitasking-symbolic.svg | 98 +++ + 21 files changed, 2251 insertions(+), 1 deletion(-) + create mode 100644 panels/multitasking/assets/active-screen-edges.svg + create mode 100644 panels/multitasking/assets/hot-corner.svg + create mode 100644 panels/multitasking/assets/workspaces-primary-display.svg + create mode 100644 panels/multitasking/assets/workspaces-span-displays.svg + create mode 100644 panels/multitasking/cc-multitasking-panel.c + create mode 100644 panels/multitasking/cc-multitasking-panel.h + create mode 100644 panels/multitasking/cc-multitasking-panel.ui + create mode 100644 panels/multitasking/cc-multitasking-row.c + create mode 100644 panels/multitasking/cc-multitasking-row.h + create mode 100644 panels/multitasking/cc-multitasking-row.ui + create mode 100644 panels/multitasking/gnome-multitasking-panel.desktop.in.in + create mode 100644 panels/multitasking/icons/meson.build + create mode 100644 panels/multitasking/icons/scalable/org.gnome.Settings-multitasking-symbolic.svg + create mode 100644 panels/multitasking/meson.build + create mode 100644 panels/multitasking/multitasking.gresource.xml + create mode 100644 shell/icons/multitasking-symbolic.svg + +diff --git a/gnome-control-center.doap b/gnome-control-center.doap +index 600fd66c8..7986d9150 100644 +--- a/gnome-control-center.doap ++++ b/gnome-control-center.doap +@@ -13,7 +13,7 @@ + + C + +- ++ + + + Georges Basile Stavracas Neto +diff --git a/panels/meson.build b/panels/meson.build +index 2f4fdc5e3..1318904ae 100644 +--- a/panels/meson.build ++++ b/panels/meson.build +@@ -15,6 +15,7 @@ panels = [ + 'lock', + 'microphone', + 'mouse', ++ 'multitasking', + 'notifications', + 'online-accounts', + 'power', +diff --git a/panels/multitasking/assets/active-screen-edges.svg b/panels/multitasking/assets/active-screen-edges.svg +new file mode 100644 +index 000000000..34dc67b4e +--- /dev/null ++++ b/panels/multitasking/assets/active-screen-edges.svg +@@ -0,0 +1,118 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/panels/multitasking/assets/hot-corner.svg b/panels/multitasking/assets/hot-corner.svg +new file mode 100644 +index 000000000..0a1732c0e +--- /dev/null ++++ b/panels/multitasking/assets/hot-corner.svg +@@ -0,0 +1,124 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/panels/multitasking/assets/workspaces-primary-display.svg b/panels/multitasking/assets/workspaces-primary-display.svg +new file mode 100644 +index 000000000..56e05c4bb +--- /dev/null ++++ b/panels/multitasking/assets/workspaces-primary-display.svg +@@ -0,0 +1,130 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/panels/multitasking/assets/workspaces-span-displays.svg b/panels/multitasking/assets/workspaces-span-displays.svg +new file mode 100644 +index 000000000..7b3655df9 +--- /dev/null ++++ b/panels/multitasking/assets/workspaces-span-displays.svg +@@ -0,0 +1,178 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/panels/multitasking/cc-multitasking-panel.c b/panels/multitasking/cc-multitasking-panel.c +new file mode 100644 +index 000000000..6a3177fe9 +--- /dev/null ++++ b/panels/multitasking/cc-multitasking-panel.c +@@ -0,0 +1,150 @@ ++/* cc-multitasking-panel.h ++ * ++ * Copyright 2020 Georges Basile Stavracas Neto ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * SPDX-License-Identifier: GPL-2.0-or-later ++ */ ++ ++ ++#include "cc-multitasking-panel.h" ++ ++#include "cc-multitasking-resources.h" ++#include "cc-multitasking-row.h" ++#include "list-box-helper.h" ++ ++struct _CcMultitaskingPanel ++{ ++ CcPanel parent_instance; ++ ++ GSettings *interface_settings; ++ GSettings *mutter_settings; ++ GSettings *overrides_settings; ++ GSettings *shell_settings; ++ GSettings *wm_settings; ++ ++ GtkSwitch *active_screen_edges_switch; ++ GtkToggleButton *current_workspace_radio; ++ GtkToggleButton *dynamic_workspaces_radio; ++ GtkToggleButton *fixed_workspaces_radio; ++ GtkSwitch *hot_corner_switch; ++ GtkSpinButton *number_of_workspaces_spin; ++ GtkToggleButton *workspaces_primary_display_radio; ++ GtkToggleButton *workspaces_span_displays_radio; ++}; ++ ++CC_PANEL_REGISTER (CcMultitaskingPanel, cc_multitasking_panel) ++ ++/* GObject overrides */ ++ ++static void ++cc_multitasking_panel_finalize (GObject *object) ++{ ++ CcMultitaskingPanel *self = (CcMultitaskingPanel *)object; ++ ++ g_clear_object (&self->interface_settings); ++ g_clear_object (&self->mutter_settings); ++ g_clear_object (&self->overrides_settings); ++ g_clear_object (&self->shell_settings); ++ g_clear_object (&self->wm_settings); ++ ++ G_OBJECT_CLASS (cc_multitasking_panel_parent_class)->finalize (object); ++} ++ ++static void ++cc_multitasking_panel_class_init (CcMultitaskingPanelClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); ++ ++ g_type_ensure (CC_TYPE_MULTITASKING_ROW); ++ ++ object_class->finalize = cc_multitasking_panel_finalize; ++ ++ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/multitasking/cc-multitasking-panel.ui"); ++ ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, active_screen_edges_switch); ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, current_workspace_radio); ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, dynamic_workspaces_radio); ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, fixed_workspaces_radio); ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, hot_corner_switch); ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, number_of_workspaces_spin); ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, workspaces_primary_display_radio); ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, workspaces_span_displays_radio); ++} ++ ++static void ++cc_multitasking_panel_init (CcMultitaskingPanel *self) ++{ ++ g_resources_register (cc_multitasking_get_resource ()); ++ ++ gtk_widget_init_template (GTK_WIDGET (self)); ++ ++ self->interface_settings = g_settings_new ("org.gnome.desktop.interface"); ++ g_settings_bind (self->interface_settings, ++ "enable-hot-corners", ++ self->hot_corner_switch, ++ "active", ++ G_SETTINGS_BIND_DEFAULT); ++ ++ self->mutter_settings = g_settings_new ("org.gnome.mutter"); ++ ++ if (g_settings_get_boolean (self->mutter_settings, "workspaces-only-on-primary")) ++ gtk_toggle_button_set_active (self->workspaces_primary_display_radio, TRUE); ++ else ++ gtk_toggle_button_set_active (self->workspaces_span_displays_radio, TRUE); ++ ++ g_settings_bind (self->mutter_settings, ++ "workspaces-only-on-primary", ++ self->workspaces_primary_display_radio, ++ "active", ++ G_SETTINGS_BIND_DEFAULT); ++ g_settings_bind (self->mutter_settings, ++ "edge-tiling", ++ self->active_screen_edges_switch, ++ "active", ++ G_SETTINGS_BIND_DEFAULT); ++ ++ self->overrides_settings = g_settings_new ("org.gnome.shell.overrides"); ++ ++ if (g_settings_get_boolean (self->overrides_settings, "dynamic-workspaces")) ++ gtk_toggle_button_set_active (self->dynamic_workspaces_radio, TRUE); ++ else ++ gtk_toggle_button_set_active (self->fixed_workspaces_radio, TRUE); ++ ++ g_settings_bind (self->overrides_settings, ++ "dynamic-workspaces", ++ self->dynamic_workspaces_radio, ++ "active", ++ G_SETTINGS_BIND_DEFAULT); ++ ++ self->wm_settings = g_settings_new ("org.gnome.desktop.wm.preferences"); ++ g_settings_bind (self->wm_settings, ++ "num-workspaces", ++ self->number_of_workspaces_spin, ++ "value", ++ G_SETTINGS_BIND_DEFAULT); ++ ++ self->shell_settings = g_settings_new ("org.gnome.shell.app-switcher"); ++ ++ if (g_settings_get_boolean (self->shell_settings, "current-workspace-only")) ++ gtk_toggle_button_set_active (self->current_workspace_radio, TRUE); ++ ++ g_settings_bind (self->shell_settings, ++ "current-workspace-only", ++ self->current_workspace_radio, ++ "active", ++ G_SETTINGS_BIND_DEFAULT); ++} +diff --git a/panels/multitasking/cc-multitasking-panel.h b/panels/multitasking/cc-multitasking-panel.h +new file mode 100644 +index 000000000..81e78f071 +--- /dev/null ++++ b/panels/multitasking/cc-multitasking-panel.h +@@ -0,0 +1,30 @@ ++/* cc-multitasking-panel.h ++ * ++ * Copyright 2020 Georges Basile Stavracas Neto ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * SPDX-License-Identifier: GPL-2.0-or-later ++ */ ++ ++#pragma once ++ ++#include ++ ++G_BEGIN_DECLS ++ ++#define CC_TYPE_MULTITASKING_PANEL (cc_multitasking_panel_get_type()) ++G_DECLARE_FINAL_TYPE (CcMultitaskingPanel, cc_multitasking_panel, CC, MULTITASKING_PANEL, CcPanel) ++ ++G_END_DECLS +diff --git a/panels/multitasking/cc-multitasking-panel.ui b/panels/multitasking/cc-multitasking-panel.ui +new file mode 100644 +index 000000000..5b5725038 +--- /dev/null ++++ b/panels/multitasking/cc-multitasking-panel.ui +@@ -0,0 +1,357 @@ ++ ++ ++ ++ ++ ++ 1.0 ++ 1.0 ++ 4.0 ++ ++ 36.0 ++ ++ +diff --git a/panels/multitasking/cc-multitasking-row.c b/panels/multitasking/cc-multitasking-row.c +new file mode 100644 +index 000000000..608e4c48f +--- /dev/null ++++ b/panels/multitasking/cc-multitasking-row.c +@@ -0,0 +1,684 @@ ++/* cc-multitasking-row.c ++ * ++ * Copyright 2018 Purism SPC ++ * 2021 Georges Basile Stavracas Neto ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#include "cc-multitasking-row.h" ++ ++struct _CcMultitaskingRow ++{ ++ HdyPreferencesRow parent; ++ ++ GtkBox *artwork_box; ++ GtkBox *header; ++ GtkImage *image; ++ GtkBox *prefixes; ++ GtkLabel *subtitle; ++ GtkBox *suffixes; ++ GtkLabel *title; ++ GtkBox *title_box; ++ ++ GtkWidget *previous_parent; ++ ++ gboolean use_underline; ++ gint title_lines; ++ gint subtitle_lines; ++ GtkWidget *activatable_widget; ++}; ++ ++static void cc_multitasking_row_buildable_init (GtkBuildableIface *iface); ++ ++G_DEFINE_TYPE_WITH_CODE (CcMultitaskingRow, cc_multitasking_row, HDY_TYPE_PREFERENCES_ROW, ++ G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, cc_multitasking_row_buildable_init)) ++ ++enum ++{ ++ PROP_0, ++ PROP_ICON_NAME, ++ PROP_ACTIVATABLE_WIDGET, ++ PROP_SUBTITLE, ++ PROP_USE_UNDERLINE, ++ PROP_TITLE_LINES, ++ PROP_SUBTITLE_LINES, ++ N_PROPS, ++}; ++ ++enum ++{ ++ SIGNAL_ACTIVATED, ++ SIGNAL_LAST_SIGNAL, ++}; ++ ++static GParamSpec *props[N_PROPS] = { NULL, }; ++static guint signals[SIGNAL_LAST_SIGNAL] = { 0, }; ++ ++static void ++row_activated_cb (CcMultitaskingRow *self, ++ GtkListBoxRow *row) ++{ ++ /* No need to use GTK_LIST_BOX_ROW() for a pointer comparison. */ ++ if ((GtkListBoxRow *) self == row) ++ cc_multitasking_row_activate (self); ++} ++ ++static void ++parent_cb (CcMultitaskingRow *self) ++{ ++ GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (self)); ++ ++ if (self->previous_parent != NULL) ++ { ++ g_signal_handlers_disconnect_by_func (self->previous_parent, ++ G_CALLBACK (row_activated_cb), ++ self); ++ self->previous_parent = NULL; ++ } ++ ++ if (parent == NULL || !GTK_IS_LIST_BOX (parent)) ++ return; ++ ++ self->previous_parent = parent; ++ g_signal_connect_swapped (parent, "row-activated", G_CALLBACK (row_activated_cb), self); ++} ++ ++static void ++update_subtitle_visibility (CcMultitaskingRow *self) ++{ ++ gtk_widget_set_visible (GTK_WIDGET (self->subtitle), ++ gtk_label_get_text (self->subtitle) != NULL && ++ g_strcmp0 (gtk_label_get_text (self->subtitle), "") != 0); ++} ++ ++static void ++cc_multitasking_row_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec) ++{ ++ CcMultitaskingRow *self = CC_MULTITASKING_ROW (object); ++ ++ switch (prop_id) ++ { ++ case PROP_ICON_NAME: ++ g_value_set_string (value, cc_multitasking_row_get_icon_name (self)); ++ break; ++ case PROP_ACTIVATABLE_WIDGET: ++ g_value_set_object (value, (GObject *) cc_multitasking_row_get_activatable_widget (self)); ++ break; ++ case PROP_SUBTITLE: ++ g_value_set_string (value, cc_multitasking_row_get_subtitle (self)); ++ break; ++ case PROP_SUBTITLE_LINES: ++ g_value_set_int (value, cc_multitasking_row_get_subtitle_lines (self)); ++ break; ++ case PROP_TITLE_LINES: ++ g_value_set_int (value, cc_multitasking_row_get_title_lines (self)); ++ break; ++ case PROP_USE_UNDERLINE: ++ g_value_set_boolean (value, cc_multitasking_row_get_use_underline (self)); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } ++} ++ ++static void ++cc_multitasking_row_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ CcMultitaskingRow *self = CC_MULTITASKING_ROW (object); ++ ++ switch (prop_id) ++ { ++ case PROP_ICON_NAME: ++ cc_multitasking_row_set_icon_name (self, g_value_get_string (value)); ++ break; ++ case PROP_ACTIVATABLE_WIDGET: ++ cc_multitasking_row_set_activatable_widget (self, (GtkWidget*) g_value_get_object (value)); ++ break; ++ case PROP_SUBTITLE: ++ cc_multitasking_row_set_subtitle (self, g_value_get_string (value)); ++ break; ++ case PROP_SUBTITLE_LINES: ++ cc_multitasking_row_set_subtitle_lines (self, g_value_get_int (value)); ++ break; ++ case PROP_TITLE_LINES: ++ cc_multitasking_row_set_title_lines (self, g_value_get_int (value)); ++ break; ++ case PROP_USE_UNDERLINE: ++ cc_multitasking_row_set_use_underline (self, g_value_get_boolean (value)); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } ++} ++ ++static void ++cc_multitasking_row_dispose (GObject *object) ++{ ++ CcMultitaskingRow *self = CC_MULTITASKING_ROW (object); ++ ++ if (self->previous_parent != NULL) { ++ g_signal_handlers_disconnect_by_func (self->previous_parent, G_CALLBACK (row_activated_cb), self); ++ self->previous_parent = NULL; ++ } ++ ++ G_OBJECT_CLASS (cc_multitasking_row_parent_class)->dispose (object); ++} ++ ++static void ++cc_multitasking_row_show_all (GtkWidget *widget) ++{ ++ CcMultitaskingRow *self = CC_MULTITASKING_ROW (widget); ++ ++ g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); ++ ++ gtk_container_foreach (GTK_CONTAINER (self->prefixes), ++ (GtkCallback) gtk_widget_show_all, ++ NULL); ++ ++ gtk_container_foreach (GTK_CONTAINER (self->suffixes), ++ (GtkCallback) gtk_widget_show_all, ++ NULL); ++ ++ GTK_WIDGET_CLASS (cc_multitasking_row_parent_class)->show_all (widget); ++} ++ ++static void ++cc_multitasking_row_destroy (GtkWidget *widget) ++{ ++ CcMultitaskingRow *self = CC_MULTITASKING_ROW (widget); ++ ++ if (self->header) ++ { ++ gtk_widget_destroy (GTK_WIDGET (self->header)); ++ self->header = NULL; ++ } ++ ++ cc_multitasking_row_set_activatable_widget (self, NULL); ++ ++ self->prefixes = NULL; ++ self->suffixes = NULL; ++ ++ GTK_WIDGET_CLASS (cc_multitasking_row_parent_class)->destroy (widget); ++} ++ ++static void ++cc_multitasking_row_add (GtkContainer *container, ++ GtkWidget *child) ++{ ++ CcMultitaskingRow *self = CC_MULTITASKING_ROW (container); ++ ++ /* When constructing the widget, we want the box to be added as the child of ++ * the GtkListBoxRow, as an implementation detail. ++ */ ++ if (!self->header) ++ { ++ GTK_CONTAINER_CLASS (cc_multitasking_row_parent_class)->add (container, child); ++ } ++ else ++ { ++ gtk_container_add (GTK_CONTAINER (self->suffixes), child); ++ gtk_widget_show (GTK_WIDGET (self->suffixes)); ++ } ++} ++ ++static void ++cc_multitasking_row_remove (GtkContainer *container, ++ GtkWidget *child) ++{ ++ CcMultitaskingRow *self = CC_MULTITASKING_ROW (container); ++ ++ if (child == GTK_WIDGET (self->header)) ++ GTK_CONTAINER_CLASS (cc_multitasking_row_parent_class)->remove (container, child); ++ else if (gtk_widget_get_parent (child) == GTK_WIDGET (self->prefixes)) ++ gtk_container_remove (GTK_CONTAINER (self->prefixes), child); ++ else ++ gtk_container_remove (GTK_CONTAINER (self->suffixes), child); ++} ++ ++typedef struct { ++ CcMultitaskingRow *row; ++ GtkCallback callback; ++ gpointer callback_data; ++} ForallData; ++ ++static void ++for_non_internal_child (GtkWidget *widget, ++ gpointer callback_data) ++{ ++ ForallData *data = callback_data; ++ CcMultitaskingRow *self = data->row; ++ ++ if (widget != (GtkWidget *) self->image && ++ widget != (GtkWidget *) self->prefixes && ++ widget != (GtkWidget *) self->suffixes && ++ widget != (GtkWidget *) self->title_box) ++ { ++ data->callback (widget, data->callback_data); ++ } ++} ++ ++static void ++cc_multitasking_row_forall (GtkContainer *container, ++ gboolean include_internals, ++ GtkCallback callback, ++ gpointer callback_data) ++{ ++ CcMultitaskingRow *self = CC_MULTITASKING_ROW (container); ++ ForallData data; ++ ++ if (include_internals) ++ { ++ GTK_CONTAINER_CLASS (cc_multitasking_row_parent_class)->forall (GTK_CONTAINER (self), ++ include_internals, ++ callback, ++ callback_data); ++ return; ++ } ++ ++ data.row = self; ++ data.callback = callback; ++ data.callback_data = callback_data; ++ ++ if (self->prefixes) ++ { ++ GTK_CONTAINER_GET_CLASS (self->prefixes)->forall (GTK_CONTAINER (self->prefixes), ++ include_internals, ++ for_non_internal_child, ++ &data); ++ } ++ if (self->suffixes) ++ { ++ GTK_CONTAINER_GET_CLASS (self->suffixes)->forall (GTK_CONTAINER (self->suffixes), ++ include_internals, ++ for_non_internal_child, ++ &data); ++ } ++ if (self->header) ++ { ++ GTK_CONTAINER_GET_CLASS (self->header)->forall (GTK_CONTAINER (self->header), ++ include_internals, ++ for_non_internal_child, ++ &data); ++ } ++} ++ ++static void ++cc_multitasking_row_class_init (CcMultitaskingRowClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); ++ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass); ++ ++ object_class->get_property = cc_multitasking_row_get_property; ++ object_class->set_property = cc_multitasking_row_set_property; ++ object_class->dispose = cc_multitasking_row_dispose; ++ ++ widget_class->destroy = cc_multitasking_row_destroy; ++ widget_class->show_all = cc_multitasking_row_show_all; ++ ++ container_class->add = cc_multitasking_row_add; ++ container_class->remove = cc_multitasking_row_remove; ++ container_class->forall = cc_multitasking_row_forall; ++ ++ props[PROP_ICON_NAME] = ++ g_param_spec_string ("icon-name", ++ "Icon name", ++ "Icon name", ++ "", ++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); ++ ++ props[PROP_ACTIVATABLE_WIDGET] = ++ g_param_spec_object ("activatable-widget", ++ "Activatable widget", ++ "The widget to be activated when the row is activated", ++ GTK_TYPE_WIDGET, ++ G_PARAM_READWRITE); ++ ++ props[PROP_SUBTITLE] = ++ g_param_spec_string ("subtitle", ++ "Subtitle", ++ "Subtitle", ++ "", ++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); ++ ++ props[PROP_USE_UNDERLINE] = ++ g_param_spec_boolean ("use-underline", ++ "Use underline", ++ "If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key", ++ FALSE, ++ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); ++ ++ props[PROP_TITLE_LINES] = ++ g_param_spec_int ("title-lines", ++ "Number of title lines", ++ "The desired number of title lines", ++ 0, G_MAXINT, ++ 1, ++ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); ++ ++ props[PROP_SUBTITLE_LINES] = ++ g_param_spec_int ("subtitle-lines", ++ "Number of subtitle lines", ++ "The desired number of subtitle lines", ++ 0, G_MAXINT, ++ 1, ++ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); ++ ++ g_object_class_install_properties (object_class, N_PROPS, props); ++ ++ signals[SIGNAL_ACTIVATED] = ++ g_signal_new ("activated", ++ G_TYPE_FROM_CLASS (klass), ++ G_SIGNAL_RUN_LAST, ++ 0, ++ NULL, NULL, NULL, ++ G_TYPE_NONE, ++ 0); ++ ++ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/multitasking/cc-multitasking-row.ui"); ++ ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, artwork_box); ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, header); ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, image); ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, prefixes); ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, subtitle); ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, suffixes); ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, title); ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingRow, title_box); ++} ++ ++static gboolean ++string_is_not_empty (GBinding *binding, ++ const GValue *from_value, ++ GValue *to_value, ++ gpointer user_data) ++{ ++ const gchar *string = g_value_get_string (from_value); ++ ++ g_value_set_boolean (to_value, string != NULL && g_strcmp0 (string, "") != 0); ++ ++ return TRUE; ++} ++ ++static void ++cc_multitasking_row_init (CcMultitaskingRow *self) ++{ ++ self->title_lines = 1; ++ self->subtitle_lines = 1; ++ ++ gtk_widget_init_template (GTK_WIDGET (self)); ++ ++ g_object_bind_property_full (self, "title", ++ self->title, "visible", ++ G_BINDING_SYNC_CREATE, ++ string_is_not_empty, ++ NULL, NULL, NULL); ++ ++ update_subtitle_visibility (self); ++ ++ g_signal_connect (self, "notify::parent", G_CALLBACK (parent_cb), NULL); ++} ++ ++static void ++cc_multitasking_row_buildable_add_child (GtkBuildable *buildable, ++ GtkBuilder *builder, ++ GObject *child, ++ const gchar *type) ++{ ++ CcMultitaskingRow *self = CC_MULTITASKING_ROW (buildable); ++ ++ if (self->header == NULL || !type) ++ gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (child)); ++ else if (type && strcmp (type, "prefix") == 0) ++ cc_multitasking_row_add_prefix (self, GTK_WIDGET (child)); ++ else if (type && strcmp (type, "artwork") == 0) ++ cc_multitasking_row_add_artwork(self, GTK_WIDGET (child)); ++ else ++ GTK_BUILDER_WARN_INVALID_CHILD_TYPE (self, type); ++} ++ ++static void ++cc_multitasking_row_buildable_init (GtkBuildableIface *iface) ++{ ++ iface->add_child = cc_multitasking_row_buildable_add_child; ++} ++ ++const gchar * ++cc_multitasking_row_get_subtitle (CcMultitaskingRow *self) ++{ ++ g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), NULL); ++ ++ return gtk_label_get_text (self->subtitle); ++} ++ ++void ++cc_multitasking_row_set_subtitle (CcMultitaskingRow *self, ++ const gchar *subtitle) ++{ ++ g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); ++ ++ if (g_strcmp0 (gtk_label_get_text (self->subtitle), subtitle) == 0) ++ return; ++ ++ gtk_label_set_text (self->subtitle, subtitle); ++ gtk_widget_set_visible (GTK_WIDGET (self->subtitle), ++ subtitle != NULL && g_strcmp0 (subtitle, "") != 0); ++ ++ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SUBTITLE]); ++} ++ ++const gchar * ++cc_multitasking_row_get_icon_name (CcMultitaskingRow *self) ++{ ++ const gchar *icon_name; ++ ++ g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), NULL); ++ ++ gtk_image_get_icon_name (self->image, &icon_name, NULL); ++ ++ return icon_name; ++} ++ ++void ++cc_multitasking_row_set_icon_name (CcMultitaskingRow *self, ++ const gchar *icon_name) ++{ ++ const gchar *old_icon_name; ++ ++ g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); ++ ++ gtk_image_get_icon_name (self->image, &old_icon_name, NULL); ++ if (g_strcmp0 (old_icon_name, icon_name) == 0) ++ return; ++ ++ gtk_image_set_from_icon_name (self->image, icon_name, GTK_ICON_SIZE_INVALID); ++ gtk_widget_set_visible (GTK_WIDGET (self->image), ++ icon_name != NULL && g_strcmp0 (icon_name, "") != 0); ++ ++ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ICON_NAME]); ++} ++ ++GtkWidget * ++cc_multitasking_row_get_activatable_widget (CcMultitaskingRow *self) ++{ ++ g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), NULL); ++ ++ return self->activatable_widget; ++} ++ ++static void ++activatable_widget_weak_notify (gpointer data, ++ GObject *where_the_object_was) ++{ ++ CcMultitaskingRow *self = CC_MULTITASKING_ROW (data); ++ ++ self->activatable_widget = NULL; ++ ++ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACTIVATABLE_WIDGET]); ++} ++ ++void ++cc_multitasking_row_set_activatable_widget (CcMultitaskingRow *self, ++ GtkWidget *widget) ++{ ++ g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); ++ g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget)); ++ ++ if (self->activatable_widget == widget) ++ return; ++ ++ if (self->activatable_widget) ++ g_object_weak_unref (G_OBJECT (self->activatable_widget), ++ activatable_widget_weak_notify, ++ self); ++ ++ self->activatable_widget = widget; ++ ++ if (self->activatable_widget != NULL) { ++ g_object_weak_ref (G_OBJECT (self->activatable_widget), ++ activatable_widget_weak_notify, ++ self); ++ gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (self), TRUE); ++ } ++ ++ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ACTIVATABLE_WIDGET]); ++} ++ ++gboolean ++cc_multitasking_row_get_use_underline (CcMultitaskingRow *self) ++{ ++ g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), FALSE); ++ ++ return self->use_underline; ++} ++ ++void ++cc_multitasking_row_set_use_underline (CcMultitaskingRow *self, ++ gboolean use_underline) ++{ ++ g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); ++ ++ use_underline = !!use_underline; ++ ++ if (self->use_underline == use_underline) ++ return; ++ ++ self->use_underline = use_underline; ++ hdy_preferences_row_set_use_underline (HDY_PREFERENCES_ROW (self), self->use_underline); ++ gtk_label_set_use_underline (self->title, self->use_underline); ++ gtk_label_set_use_underline (self->subtitle, self->use_underline); ++ gtk_label_set_mnemonic_widget (self->title, GTK_WIDGET (self)); ++ gtk_label_set_mnemonic_widget (self->subtitle, GTK_WIDGET (self)); ++ ++ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_USE_UNDERLINE]); ++} ++ ++gint ++cc_multitasking_row_get_title_lines (CcMultitaskingRow *self) ++{ ++ g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), 0); ++ ++ return self->title_lines; ++} ++ ++void ++cc_multitasking_row_set_title_lines (CcMultitaskingRow *self, ++ gint title_lines) ++{ ++ g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); ++ g_return_if_fail (title_lines >= 0); ++ ++ if (self->title_lines == title_lines) ++ return; ++ ++ self->title_lines = title_lines; ++ ++ gtk_label_set_lines (self->title, title_lines); ++ gtk_label_set_ellipsize (self->title, title_lines == 0 ? PANGO_ELLIPSIZE_NONE : PANGO_ELLIPSIZE_END); ++ ++ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TITLE_LINES]); ++} ++ ++gint ++cc_multitasking_row_get_subtitle_lines (CcMultitaskingRow *self) ++{ ++ g_return_val_if_fail (CC_IS_MULTITASKING_ROW (self), 0); ++ ++ return self->subtitle_lines; ++} ++ ++void ++cc_multitasking_row_set_subtitle_lines (CcMultitaskingRow *self, ++ gint subtitle_lines) ++{ ++ g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); ++ g_return_if_fail (subtitle_lines >= 0); ++ ++ if (self->subtitle_lines == subtitle_lines) ++ return; ++ ++ self->subtitle_lines = subtitle_lines; ++ ++ gtk_label_set_lines (self->subtitle, subtitle_lines); ++ gtk_label_set_ellipsize (self->subtitle, subtitle_lines == 0 ? PANGO_ELLIPSIZE_NONE : PANGO_ELLIPSIZE_END); ++ ++ g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SUBTITLE_LINES]); ++} ++ ++void ++cc_multitasking_row_add_prefix (CcMultitaskingRow *self, ++ GtkWidget *widget) ++{ ++ g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); ++ g_return_if_fail (GTK_IS_WIDGET (self)); ++ ++ gtk_box_pack_start (self->prefixes, widget, FALSE, TRUE, 0); ++ gtk_widget_show (GTK_WIDGET (self->prefixes)); ++} ++ ++void ++cc_multitasking_row_add_artwork (CcMultitaskingRow *self, ++ GtkWidget *widget) ++{ ++ g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); ++ g_return_if_fail (GTK_IS_WIDGET (self)); ++ ++ /* HACK: the artwork box pushes the title too much to the top, so we ++ * need to compensate this here. ++ */ ++ gtk_widget_set_margin_top (GTK_WIDGET (self->header), 12); ++ ++ gtk_box_pack_start (self->artwork_box, widget, FALSE, TRUE, 0); ++ gtk_widget_show (GTK_WIDGET (self->artwork_box)); ++} ++ ++void ++cc_multitasking_row_activate (CcMultitaskingRow *self) ++{ ++ g_return_if_fail (CC_IS_MULTITASKING_ROW (self)); ++ ++ if (self->activatable_widget) ++ gtk_widget_mnemonic_activate (self->activatable_widget, FALSE); ++ ++ g_signal_emit (self, signals[SIGNAL_ACTIVATED], 0); ++} +diff --git a/panels/multitasking/cc-multitasking-row.h b/panels/multitasking/cc-multitasking-row.h +new file mode 100644 +index 000000000..c35d9d688 +--- /dev/null ++++ b/panels/multitasking/cc-multitasking-row.h +@@ -0,0 +1,63 @@ ++/* cc-multitasking-row.h ++ * ++ * Copyright 2018 Purism SPC ++ * 2021 Georges Basile Stavracas Neto ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#pragma once ++ ++#include ++ ++G_BEGIN_DECLS ++ ++#define CC_TYPE_MULTITASKING_ROW (cc_multitasking_row_get_type()) ++G_DECLARE_FINAL_TYPE (CcMultitaskingRow, cc_multitasking_row, CC, MULTITASKING_ROW, HdyPreferencesRow) ++ ++const gchar *cc_multitasking_row_get_subtitle (CcMultitaskingRow *self); ++void cc_multitasking_row_set_subtitle (CcMultitaskingRow *self, ++ const gchar *subtitle); ++ ++const gchar *cc_multitasking_row_get_icon_name (CcMultitaskingRow *self); ++void cc_multitasking_row_set_icon_name (CcMultitaskingRow *self, ++ const gchar *icon_name); ++ ++GtkWidget *cc_multitasking_row_get_activatable_widget (CcMultitaskingRow *self); ++void cc_multitasking_row_set_activatable_widget (CcMultitaskingRow *self, ++ GtkWidget *widget); ++ ++gboolean cc_multitasking_row_get_use_underline (CcMultitaskingRow *self); ++void cc_multitasking_row_set_use_underline (CcMultitaskingRow *self, ++ gboolean use_underline); ++ ++gint cc_multitasking_row_get_title_lines (CcMultitaskingRow *self); ++void cc_multitasking_row_set_title_lines (CcMultitaskingRow *self, ++ gint title_lines); ++ ++gint cc_multitasking_row_get_subtitle_lines (CcMultitaskingRow *self); ++void cc_multitasking_row_set_subtitle_lines (CcMultitaskingRow *self, ++ gint subtitle_lines); ++ ++void cc_multitasking_row_add_prefix (CcMultitaskingRow *self, ++ GtkWidget *widget); ++ ++void cc_multitasking_row_add_artwork (CcMultitaskingRow *self, ++ GtkWidget *widget); ++ ++void cc_multitasking_row_activate (CcMultitaskingRow *self); ++ ++G_END_DECLS +diff --git a/panels/multitasking/cc-multitasking-row.ui b/panels/multitasking/cc-multitasking-row.ui +new file mode 100644 +index 000000000..a3377229f +--- /dev/null ++++ b/panels/multitasking/cc-multitasking-row.ui +@@ -0,0 +1,122 @@ ++ ++ ++ ++ +diff --git a/panels/multitasking/gnome-multitasking-panel.desktop.in.in b/panels/multitasking/gnome-multitasking-panel.desktop.in.in +new file mode 100644 +index 000000000..675879bc2 +--- /dev/null ++++ b/panels/multitasking/gnome-multitasking-panel.desktop.in.in +@@ -0,0 +1,14 @@ ++[Desktop Entry] ++Name=Multitasking ++Comment=Manage preferences for productivity and multitasking ++Exec=gnome-control-center multitasking ++# Translators: Do NOT translate or transliterate this text (this is an icon file name)! ++Icon=org.gnome.Settings-multitasking-symbolic ++Terminal=false ++Type=Application ++NoDisplay=true ++StartupNotify=true ++Categories=GNOME;GTK;Settings;DesktopSettings;X-GNOME-Settings-Panel;X-GNOME-PersonalizationSettings; ++OnlyShowIn=GNOME; ++# Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++Keywords=Multitasking;Multitask;Productivity;Customize;Desktop; +diff --git a/panels/multitasking/icons/meson.build b/panels/multitasking/icons/meson.build +new file mode 100644 +index 000000000..b274dd102 +--- /dev/null ++++ b/panels/multitasking/icons/meson.build +@@ -0,0 +1,4 @@ ++install_data( ++ 'scalable/org.gnome.Settings-multitasking-symbolic.svg', ++ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'apps') ++) +diff --git a/panels/multitasking/icons/scalable/org.gnome.Settings-multitasking-symbolic.svg b/panels/multitasking/icons/scalable/org.gnome.Settings-multitasking-symbolic.svg +new file mode 100644 +index 000000000..0e09bbcd5 +--- /dev/null ++++ b/panels/multitasking/icons/scalable/org.gnome.Settings-multitasking-symbolic.svg +@@ -0,0 +1,106 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/panels/multitasking/meson.build b/panels/multitasking/meson.build +new file mode 100644 +index 000000000..772b63813 +--- /dev/null ++++ b/panels/multitasking/meson.build +@@ -0,0 +1,49 @@ ++panels_list += cappletname ++desktop = 'gnome-@0@-panel.desktop'.format(cappletname) ++ ++desktop_in = configure_file( ++ input: desktop + '.in.in', ++ output: desktop + '.in', ++ configuration: desktop_conf ++) ++ ++i18n.merge_file( ++ desktop, ++ type: 'desktop', ++ input: desktop_in, ++ output: desktop, ++ po_dir: po_dir, ++ install: true, ++ install_dir: control_center_desktopdir ++) ++ ++sources = files( ++ 'cc-multitasking-panel.c', ++ 'cc-multitasking-row.c', ++) ++ ++resource_data = files( ++ 'cc-multitasking-panel.ui', ++) ++ ++sources += gnome.compile_resources( ++ 'cc-' + cappletname + '-resources', ++ cappletname + '.gresource.xml', ++ c_name: 'cc_' + cappletname, ++ dependencies: resource_data, ++ export: true ++) ++ ++cflags += [ ++ '-DDATADIR="@0@"'.format(control_center_datadir) ++] ++ ++panels_libs += static_library( ++ cappletname, ++ sources: sources, ++ include_directories: [ top_inc, common_inc ], ++ dependencies: common_deps, ++ c_args: cflags ++) ++ ++subdir('icons') +diff --git a/panels/multitasking/multitasking.gresource.xml b/panels/multitasking/multitasking.gresource.xml +new file mode 100644 +index 000000000..db8365f68 +--- /dev/null ++++ b/panels/multitasking/multitasking.gresource.xml +@@ -0,0 +1,13 @@ ++ ++ ++ ++ cc-multitasking-panel.ui ++ cc-multitasking-row.ui ++ ++ ++ assets/active-screen-edges.svg ++ assets/hot-corner.svg ++ assets/workspaces-primary-display.svg ++ assets/workspaces-span-displays.svg ++ ++ +diff --git a/shell/cc-panel-list.c b/shell/cc-panel-list.c +index e23da0b87..38be643ea 100644 +--- a/shell/cc-panel-list.c ++++ b/shell/cc-panel-list.c +@@ -386,6 +386,7 @@ static const gchar * const panel_order[] = { + "background", + "notifications", + "search", ++ "multitasking", + "applications", + "privacy", + "online-accounts", +diff --git a/shell/cc-panel-loader.c b/shell/cc-panel-loader.c +index f20384394..fcbf398ca 100644 +--- a/shell/cc-panel-loader.c ++++ b/shell/cc-panel-loader.c +@@ -43,6 +43,7 @@ extern GType cc_display_panel_get_type (void); + extern GType cc_info_overview_panel_get_type (void); + extern GType cc_keyboard_panel_get_type (void); + extern GType cc_mouse_panel_get_type (void); ++extern GType cc_multitasking_panel_get_type (void); + #ifdef BUILD_NETWORK + extern GType cc_network_panel_get_type (void); + extern GType cc_wifi_panel_get_type (void); +@@ -107,6 +108,7 @@ static CcPanelLoaderVtable default_panels[] = + PANEL_TYPE("lock", cc_lock_panel_get_type, NULL), + PANEL_TYPE("microphone", cc_microphone_panel_get_type, NULL), + PANEL_TYPE("mouse", cc_mouse_panel_get_type, NULL), ++ PANEL_TYPE("multitasking", cc_multitasking_panel_get_type, NULL), + #ifdef BUILD_NETWORK + PANEL_TYPE("network", cc_network_panel_get_type, NULL), + PANEL_TYPE("wifi", cc_wifi_panel_get_type, cc_wifi_panel_static_init_func), +diff --git a/shell/gnome-control-center.gresource.xml b/shell/gnome-control-center.gresource.xml +index 9be077ec9..5550440e1 100644 +--- a/shell/gnome-control-center.gresource.xml ++++ b/shell/gnome-control-center.gresource.xml +@@ -6,4 +6,10 @@ + help-overlay.ui + style.css + ++ ++ ++ ++ icons/multitasking-symbolic.svg ++ style.css ++ + +diff --git a/shell/icons/multitasking-symbolic.svg b/shell/icons/multitasking-symbolic.svg +new file mode 100644 +index 000000000..7959ddbfc +--- /dev/null ++++ b/shell/icons/multitasking-symbolic.svg +@@ -0,0 +1,98 @@ ++ ++ ++ ++ ++ ++ image/svg+xml ++ ++ Gnome Symbolic Icon Theme ++ ++ ++ ++ Gnome Symbolic Icon Theme ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +-- +2.34.1 + + +From ba6abb04a0cb344faaa9aed7cc8d90bff0077c04 Mon Sep 17 00:00:00 2001 +From: Georges Basile Stavracas Neto +Date: Fri, 13 Aug 2021 18:39:57 -0300 +Subject: [PATCH 02/10] multitasking: Use Mutter settings for dynamic + workspaces + +The overrides weren't meant to be used like that. +--- + panels/multitasking/cc-multitasking-panel.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/panels/multitasking/cc-multitasking-panel.c b/panels/multitasking/cc-multitasking-panel.c +index 6a3177fe9..1523e35b1 100644 +--- a/panels/multitasking/cc-multitasking-panel.c ++++ b/panels/multitasking/cc-multitasking-panel.c +@@ -31,7 +31,6 @@ struct _CcMultitaskingPanel + + GSettings *interface_settings; + GSettings *mutter_settings; +- GSettings *overrides_settings; + GSettings *shell_settings; + GSettings *wm_settings; + +@@ -56,7 +55,6 @@ cc_multitasking_panel_finalize (GObject *object) + + g_clear_object (&self->interface_settings); + g_clear_object (&self->mutter_settings); +- g_clear_object (&self->overrides_settings); + g_clear_object (&self->shell_settings); + g_clear_object (&self->wm_settings); + +@@ -117,14 +115,12 @@ cc_multitasking_panel_init (CcMultitaskingPanel *self) + "active", + G_SETTINGS_BIND_DEFAULT); + +- self->overrides_settings = g_settings_new ("org.gnome.shell.overrides"); +- +- if (g_settings_get_boolean (self->overrides_settings, "dynamic-workspaces")) ++ if (g_settings_get_boolean (self->mutter_settings, "dynamic-workspaces")) + gtk_toggle_button_set_active (self->dynamic_workspaces_radio, TRUE); + else + gtk_toggle_button_set_active (self->fixed_workspaces_radio, TRUE); + +- g_settings_bind (self->overrides_settings, ++ g_settings_bind (self->mutter_settings, + "dynamic-workspaces", + self->dynamic_workspaces_radio, + "active", +-- +2.34.1 + + +From cad4930697dcfa7ff2345a3eab09d6ecd6439469 Mon Sep 17 00:00:00 2001 +From: Felipe Borges +Date: Wed, 6 Oct 2021 12:37:44 +0200 +Subject: [PATCH 03/10] multitasking: Expand row subtitles to a second line + +Depending on the language used, the label could get long and +unreadable (ellipsized). + +Fixes #1486 +--- + panels/multitasking/cc-multitasking-row.ui | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/panels/multitasking/cc-multitasking-row.ui b/panels/multitasking/cc-multitasking-row.ui +index a3377229f..dcb90e9d4 100644 +--- a/panels/multitasking/cc-multitasking-row.ui ++++ b/panels/multitasking/cc-multitasking-row.ui +@@ -75,7 +75,7 @@ + end + start + True +- 1 ++ 2 + True + word-char + 0 +-- +2.34.1 + + +From 80701f7b6480254f18ad42928249a29cb250d604 Mon Sep 17 00:00:00 2001 +From: Jakub Steiner +Date: Fri, 28 Jan 2022 09:51:22 +0100 +Subject: [PATCH 04/10] multitasking: make graphics work in dark mode + +- more of a workaround than a solution. Getting rid of the white fills + at the expense of clarity and style. + +Fixes #1565 +--- + .../assets/active-screen-edges.svg | 159 +++++------- + panels/multitasking/assets/hot-corner.svg | 175 ++++++------- + .../assets/workspaces-primary-display.svg | 187 ++++++-------- + .../assets/workspaces-span-displays.svg | 244 +++++++----------- + 4 files changed, 301 insertions(+), 464 deletions(-) + +diff --git a/panels/multitasking/assets/active-screen-edges.svg b/panels/multitasking/assets/active-screen-edges.svg +index 34dc67b4e..66694cdca 100644 +--- a/panels/multitasking/assets/active-screen-edges.svg ++++ b/panels/multitasking/assets/active-screen-edges.svg +@@ -1,118 +1,79 @@ + +- +- + ++ + +- +- +- +- +- +- +- +- ++ showborder="false" ++ inkscape:current-layer="svg20"> ++ ++ ++ ++ + +- ++ transform="matrix(0.26458,0,0,0.26458,-400.06245,1156.76)" ++ style="display:inline" ++ id="g16"> + ++ ry="3" ++ rx="3" ++ y="-4353.0068" ++ x="1520.006" ++ height="58" ++ width="76" ++ style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#3584e4;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none" ++ id="rect6" /> ++ + +- ++ style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#3584e4;stroke-opacity:1" ++ id="g14"> ++ + +- +- +- +- ++ style="color:#000000;display:block;overflow:visible;visibility:visible;fill:#3584e4;fill-opacity:1;fill-rule:nonzero;stroke:#3584e4;stroke-width:0.612915;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" ++ d="m 26.605,2.318 v 16.44 l 3.712,-3.624 2.122,4.331 c 0.52,1.172 3.22,0.23 2.452,-1.337 l -2.099,-4.496 h 4.685 z" ++ transform="matrix(1.6306,0,0,1.63249,1484.124,-4348.541)" ++ id="path12" /> + +- + ++ + +diff --git a/panels/multitasking/assets/hot-corner.svg b/panels/multitasking/assets/hot-corner.svg +index 0a1732c0e..f540458ce 100644 +--- a/panels/multitasking/assets/hot-corner.svg ++++ b/panels/multitasking/assets/hot-corner.svg +@@ -1,124 +1,97 @@ + +- +- + + ++ inkscape:current-layer="svg31" /> + ++ id="defs5"> + +- ++ + + + +- +- +- +- +- +- +- +- +- +- ++ style="display:inline" ++ id="g11"> ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + ++ style="display:inline" ++ id="g27"> + +- +- +- +- ++ style="color:#000;display:block;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#3584e4;stroke-width:0.612915;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:1.22583, 0.612915;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate" ++ d="M29.691 6.634v16.44l3.712-3.624 2.122 4.331c.52 1.171 3.22.23 2.452-1.337l-2.099-4.497h4.685z" ++ transform="matrix(.42866 0 0 .42916 1.739 7.533)" ++ id="path25" /> + + + +diff --git a/panels/multitasking/assets/workspaces-primary-display.svg b/panels/multitasking/assets/workspaces-primary-display.svg +index 56e05c4bb..5930fab69 100644 +--- a/panels/multitasking/assets/workspaces-primary-display.svg ++++ b/panels/multitasking/assets/workspaces-primary-display.svg +@@ -1,130 +1,99 @@ + +- +- + + ++ inkscape:current-layer="svg29" ++ width="326px"> ++ ++ + ++ id="defs5"> + +- ++ ++ d="m 1448,-3870.014 h 127 v 73 h -127 z" ++ id="path2" /> + + +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++ ++ ++ ++ ++ ++ ++ ++ ++ + +diff --git a/panels/multitasking/assets/workspaces-span-displays.svg b/panels/multitasking/assets/workspaces-span-displays.svg +index 7b3655df9..a18c74eae 100644 +--- a/panels/multitasking/assets/workspaces-span-displays.svg ++++ b/panels/multitasking/assets/workspaces-span-displays.svg +@@ -1,178 +1,112 @@ + +- +- + + ++ inkscape:current-layer="svg29"> ++ ++ + ++ id="defs5"> + +- ++ +- +- +- +- +- +- ++ d="m 1448,-3870.014 h 127 v 73 h -127 z" ++ id="path2" /> + + ++ ++ ++ ++ ++ ++ ++ ++ + ++ id="g4804" ++ transform="translate(43.921149,-0.5285854)"> + +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++ style="opacity:1;fill:#3584e4;fill-opacity:1;stroke:#ed333b;stroke-width:0;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none" ++ id="rect4795" ++ width="26.458509" ++ height="15.345935" ++ x="7.9374046" ++ y="5.2917023" ++ rx="1.3229257" ++ ry="1.3229256" /> ++ ++ + + +-- +2.34.1 + + +From 1de41cac78f7b740d48e12947b0191c2a067318a Mon Sep 17 00:00:00 2001 +From: Christopher Davis +Date: Thu, 6 Jan 2022 18:24:25 -0800 +Subject: [PATCH 05/10] cc-multitasking-panel: Fix initial state for "all + workspaces" setting + +--- + panels/multitasking/cc-multitasking-panel.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/panels/multitasking/cc-multitasking-panel.c b/panels/multitasking/cc-multitasking-panel.c +index 1523e35b1..9a4041e43 100644 +--- a/panels/multitasking/cc-multitasking-panel.c ++++ b/panels/multitasking/cc-multitasking-panel.c +@@ -35,6 +35,7 @@ struct _CcMultitaskingPanel + GSettings *wm_settings; + + GtkSwitch *active_screen_edges_switch; ++ GtkToggleButton *all_workspaces_radio; + GtkToggleButton *current_workspace_radio; + GtkToggleButton *dynamic_workspaces_radio; + GtkToggleButton *fixed_workspaces_radio; +@@ -74,6 +75,7 @@ cc_multitasking_panel_class_init (CcMultitaskingPanelClass *klass) + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/multitasking/cc-multitasking-panel.ui"); + + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, active_screen_edges_switch); ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, all_workspaces_radio); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, current_workspace_radio); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, dynamic_workspaces_radio); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, fixed_workspaces_radio); +@@ -137,6 +139,8 @@ cc_multitasking_panel_init (CcMultitaskingPanel *self) + + if (g_settings_get_boolean (self->shell_settings, "current-workspace-only")) + gtk_toggle_button_set_active (self->current_workspace_radio, TRUE); ++ else ++ gtk_toggle_button_set_active (self->all_workspaces_radio, TRUE); + + g_settings_bind (self->shell_settings, + "current-workspace-only", +-- +2.34.1 + + +From 7431df3d58327e39daf6f5a4e46aa1e9a18d6aae Mon Sep 17 00:00:00 2001 +From: Jakub Steiner +Date: Fri, 28 Jan 2022 15:53:48 +0100 +Subject: [PATCH 06/10] multitasking: provide rtl asset + +- provide a RTL variant of the hot corner graphic +- revert one of the arrow to be outine only (unrelated to rtl) +- provide RTL variant of the active screen edges (close button + on the opposite side) + +See https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1559 +--- + .../assets/active-screen-edges-rtl.svg | 73 ++++++++++++++ + panels/multitasking/assets/hot-corner-rtl.svg | 94 +++++++++++++++++++ + panels/multitasking/assets/hot-corner.svg | 2 +- + 3 files changed, 168 insertions(+), 1 deletion(-) + create mode 100644 panels/multitasking/assets/active-screen-edges-rtl.svg + create mode 100644 panels/multitasking/assets/hot-corner-rtl.svg + +diff --git a/panels/multitasking/assets/active-screen-edges-rtl.svg b/panels/multitasking/assets/active-screen-edges-rtl.svg +new file mode 100644 +index 000000000..4a0351213 +--- /dev/null ++++ b/panels/multitasking/assets/active-screen-edges-rtl.svg +@@ -0,0 +1,73 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/panels/multitasking/assets/hot-corner-rtl.svg b/panels/multitasking/assets/hot-corner-rtl.svg +new file mode 100644 +index 000000000..e0286f57d +--- /dev/null ++++ b/panels/multitasking/assets/hot-corner-rtl.svg +@@ -0,0 +1,94 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/panels/multitasking/assets/hot-corner.svg b/panels/multitasking/assets/hot-corner.svg +index f540458ce..bfff29791 100644 +--- a/panels/multitasking/assets/hot-corner.svg ++++ b/panels/multitasking/assets/hot-corner.svg +@@ -80,7 +80,7 @@ + style="display:inline" + id="g29"> + +-- +2.34.1 + + +From 65becdf1b6544184c0c914f0c90eecdf6bb06558 Mon Sep 17 00:00:00 2001 +From: Jakub Steiner +Date: Wed, 23 Feb 2022 13:34:18 +0100 +Subject: [PATCH 07/10] multitasking: no more rounded top bar + +- update the look of the top bar not to have the rounding of +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++ +\ No newline at end of file +diff --git a/panels/multitasking/assets/active-screen-edges.svg b/panels/multitasking/assets/active-screen-edges.svg +index 66694cdca..bc249ab39 100644 +--- a/panels/multitasking/assets/active-screen-edges.svg ++++ b/panels/multitasking/assets/active-screen-edges.svg +@@ -1,79 +1 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++ +\ No newline at end of file +diff --git a/panels/multitasking/assets/hot-corner-rtl.svg b/panels/multitasking/assets/hot-corner-rtl.svg +index e0286f57d..9d02e4aba 100644 +--- a/panels/multitasking/assets/hot-corner-rtl.svg ++++ b/panels/multitasking/assets/hot-corner-rtl.svg +@@ -1,94 +1 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++ +\ No newline at end of file +diff --git a/panels/multitasking/assets/hot-corner.svg b/panels/multitasking/assets/hot-corner.svg +index bfff29791..7ce8e501e 100644 +--- a/panels/multitasking/assets/hot-corner.svg ++++ b/panels/multitasking/assets/hot-corner.svg +@@ -1,97 +1 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++ +\ No newline at end of file +diff --git a/panels/multitasking/assets/workspaces-primary-display.svg b/panels/multitasking/assets/workspaces-primary-display.svg +index 5930fab69..3a3bed759 100644 +--- a/panels/multitasking/assets/workspaces-primary-display.svg ++++ b/panels/multitasking/assets/workspaces-primary-display.svg +@@ -1,99 +1 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++ +\ No newline at end of file +diff --git a/panels/multitasking/assets/workspaces-span-displays.svg b/panels/multitasking/assets/workspaces-span-displays.svg +index a18c74eae..571ee10c1 100644 +--- a/panels/multitasking/assets/workspaces-span-displays.svg ++++ b/panels/multitasking/assets/workspaces-span-displays.svg +@@ -1,112 +1 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- ++ +\ No newline at end of file +-- +2.34.1 + + +From b0563736af68abb643fa5ef60a672f402c6024f5 Mon Sep 17 00:00:00 2001 +From: Jakub Steiner +Date: Wed, 2 Mar 2022 09:57:10 +0100 +Subject: [PATCH 08/10] multitasking: clean up illustration + +- fills removed to make dark mode possible exposed the rings + going through the cursors and arrows, which isn't a nice + aesthetic. convert to shapes and cut them with booleans + to get the previous look without using solid color fills +--- + panels/multitasking/assets/hot-corner-rtl.svg | 2 +- + panels/multitasking/assets/hot-corner.svg | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/panels/multitasking/assets/hot-corner-rtl.svg b/panels/multitasking/assets/hot-corner-rtl.svg +index 9d02e4aba..4eb3aba22 100644 +--- a/panels/multitasking/assets/hot-corner-rtl.svg ++++ b/panels/multitasking/assets/hot-corner-rtl.svg +@@ -1 +1 @@ +- +\ No newline at end of file ++ +\ No newline at end of file +diff --git a/panels/multitasking/assets/hot-corner.svg b/panels/multitasking/assets/hot-corner.svg +index 7ce8e501e..66cee2a0b 100644 +--- a/panels/multitasking/assets/hot-corner.svg ++++ b/panels/multitasking/assets/hot-corner.svg +@@ -1 +1 @@ +- +\ No newline at end of file ++ +\ No newline at end of file +-- +2.34.1 + + +From 61b9191a527c9444b2dc1b66388611c319d78099 Mon Sep 17 00:00:00 2001 +From: Felipe Borges +Date: Mon, 28 Feb 2022 11:23:48 +0100 +Subject: [PATCH 09/10] multitasking: Display Right-to-Left ilustrations for + RTL locales + +Fixes #1559 +--- + panels/multitasking/cc-multitasking-panel.c | 12 ++++++++++++ + panels/multitasking/cc-multitasking-panel.ui | 4 ++-- + panels/multitasking/multitasking.gresource.xml | 2 ++ + 3 files changed, 16 insertions(+), 2 deletions(-) + +diff --git a/panels/multitasking/cc-multitasking-panel.c b/panels/multitasking/cc-multitasking-panel.c +index 9a4041e43..448f8cc55 100644 +--- a/panels/multitasking/cc-multitasking-panel.c ++++ b/panels/multitasking/cc-multitasking-panel.c +@@ -34,11 +34,13 @@ struct _CcMultitaskingPanel + GSettings *shell_settings; + GSettings *wm_settings; + ++ GtkImage *active_screen_edges_picture; + GtkSwitch *active_screen_edges_switch; + GtkToggleButton *all_workspaces_radio; + GtkToggleButton *current_workspace_radio; + GtkToggleButton *dynamic_workspaces_radio; + GtkToggleButton *fixed_workspaces_radio; ++ GtkImage *hot_corner_picture; + GtkSwitch *hot_corner_switch; + GtkSpinButton *number_of_workspaces_spin; + GtkToggleButton *workspaces_primary_display_radio; +@@ -74,11 +76,13 @@ cc_multitasking_panel_class_init (CcMultitaskingPanelClass *klass) + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/multitasking/cc-multitasking-panel.ui"); + ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, active_screen_edges_picture); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, active_screen_edges_switch); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, all_workspaces_radio); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, current_workspace_radio); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, dynamic_workspaces_radio); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, fixed_workspaces_radio); ++ gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, hot_corner_picture); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, hot_corner_switch); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, number_of_workspaces_spin); + gtk_widget_class_bind_template_child (widget_class, CcMultitaskingPanel, workspaces_primary_display_radio); +@@ -147,4 +151,12 @@ cc_multitasking_panel_init (CcMultitaskingPanel *self) + self->current_workspace_radio, + "active", + G_SETTINGS_BIND_DEFAULT); ++ ++ if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL) ++ { ++ gtk_image_set_from_resource (self->hot_corner_picture, ++ "/org/gnome/control-center/multitasking/assets/hot-corner-rtl.svg"); ++ gtk_image_set_from_resource (self->active_screen_edges_picture, ++ "/org/gnome/control-center/multitasking/assets/active-screen-edges-rtl.svg"); ++ } + } +diff --git a/panels/multitasking/cc-multitasking-panel.ui b/panels/multitasking/cc-multitasking-panel.ui +index 5b5725038..32c85afe5 100644 +--- a/panels/multitasking/cc-multitasking-panel.ui ++++ b/panels/multitasking/cc-multitasking-panel.ui +@@ -64,7 +64,7 @@ + + + +- ++ + True + True + center +@@ -92,7 +92,7 @@ + + + +- ++ + True + True + center +diff --git a/panels/multitasking/multitasking.gresource.xml b/panels/multitasking/multitasking.gresource.xml +index db8365f68..df47764c1 100644 +--- a/panels/multitasking/multitasking.gresource.xml ++++ b/panels/multitasking/multitasking.gresource.xml +@@ -6,7 +6,9 @@ + + + assets/active-screen-edges.svg ++ assets/active-screen-edges-rtl.svg + assets/hot-corner.svg ++ assets/hot-corner-rtl.svg + assets/workspaces-primary-display.svg + assets/workspaces-span-displays.svg + +-- +2.34.1 + + +From 4a557d08f17d35c8ffaf84efba89933b240af908 Mon Sep 17 00:00:00 2001 +From: Felipe Borges +Date: Mon, 14 Mar 2022 10:50:34 +0100 +Subject: [PATCH 10/10] multitasking: Backport translations + +--- + po/POTFILES.in | 2 + + po/be.po | 116 +++++++- + po/bg.po | 129 ++++++++- + po/ca.po | 403 ++++++++++++++++++---------- + po/cs.po | 135 +++++++++- + po/da.po | 141 +++++++++- + po/de.po | 109 +++++++- + po/es.po | 127 ++++++++- + po/eu.po | 602 ++++++++++++++++++++++++++++++++--------- + po/fa.po | 707 ++++++++++++++++++++++++++++++------------------- + po/fi.po | 111 +++++++- + po/fr.po | 152 ++++++++++- + po/gl.po | 143 +++++++++- + po/he.po | 120 ++++++++- + po/hr.po | 109 +++++++- + po/hu.po | 131 ++++++++- + po/id.po | 119 ++++++++- + po/is.po | 142 ++++++++-- + po/ja.po | 140 +++++++++- + po/kk.po | 109 +++++++- + po/ko.po | 113 +++++++- + po/lt.po | 110 +++++++- + po/lv.po | 180 ++++++++++--- + po/nl.po | 150 ++++++++++- + po/oc.po | 183 ++++++++++--- + po/pa.po | 392 +++++++++++++-------------- + po/pl.po | 109 +++++++- + po/pt.po | 130 ++++++++- + po/pt_BR.po | 144 +++++++++- + po/ro.po | 116 +++++++- + po/ru.po | 108 +++++++- + po/sk.po | 129 ++++++++- + po/sl.po | 122 ++++++++- + po/sr.po | 123 ++++++++- + po/sv.po | 123 ++++++++- + po/tr.po | 125 ++++++++- + po/uk.po | 123 ++++++++- + po/vi.po | 120 ++++++++- + po/zh_CN.po | 140 +++++++++- + 39 files changed, 5486 insertions(+), 1001 deletions(-) + +diff --git a/po/POTFILES.in b/po/POTFILES.in +index 5f7e8d49a..b5c6e98ce 100644 +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -82,6 +82,8 @@ panels/mouse/cc-mouse-panel.ui + panels/mouse/cc-mouse-test.c + panels/mouse/cc-mouse-test.ui + panels/mouse/gnome-mouse-panel.desktop.in.in ++panels/multitasking/cc-multitasking-panel.ui ++panels/multitasking/gnome-multitasking-panel.desktop.in.in + panels/network/cc-network-panel.c + panels/network/cc-network-panel.ui + panels/network/cc-wifi-connection-row.c +diff --git a/po/be.po b/po/be.po +index fba62b145..e7ea7074a 100644 +--- a/po/be.po ++++ b/po/be.po +@@ -4,8 +4,27 @@ + # Ihar Hrachyshka , 2011, 2012, 2013, 2014. + # Kasia Bondarava , 2012. + # Yuras Shumovich , 2017. ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# be.po.multitasking (gnome-control-center.master) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center.master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-07 09:53+0000\n" ++"PO-Revision-Date: 2021-09-08 01:31+0300\n" ++"Last-Translator: Launchpad translators\n" ++"Language-Team: Belarusian \n" ++"Language: be\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" ++"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" ++"X-Launchpad-Export-Date: 2020-05-05 21:37+0000\n" ++"X-Generator: Poedit 3.0\n" ++"X-Project-Style: gnome\n" ++"#-#-#-#-# be.po (gnome-control-center.master) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center.master\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -22,6 +41,99 @@ msgstr "" + "X-Generator: Poedit 2.1.1\n" + "X-Project-Style: gnome\n" + ++#. #-#-#-#-# be.po.multitasking (gnome-control-center.master) #-#-#-#-# ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++#: panels/mouse/gnome-mouse-properties.ui:50 ++#, fuzzy ++msgid "General" ++msgstr "" ++"#-#-#-#-# be.po.multitasking (gnome-control-center.master) #-#-#-#-#\n" ++"Агульныя\n" ++"#-#-#-#-# be.po (gnome-control-center.master) #-#-#-#-#\n" ++"Агульныя настройкі" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "Актыўны _кут" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Крананне верхняга левага кута адкрывае меню Агляд дзейнасці." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Актыўныя краі экрана" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Каб змяніць памер акна, перацягніце яго да верхняга, левага ці правага краю " ++"экрана." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Працоўныя прасторы" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Дынамічныя працоўныя прасторы" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Пустыя працоўныя прасторы выдаляюцца аўтаматычна." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Фіксаваная колькасць працоўных прастор" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Вызначыце колькасць пастаянных працоўных прастор." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Колькасць працоўных прастор" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Некалькі манітораў" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Працоўныя прасторы толькі на _асноўным дысплэі" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Працоўныя прасторы на _ўсіх дысплэях" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Пераключэнне паміж праграмамі" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Уключаць праграмы з усіх працоўных прастор" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Уключаць толькі праграмы з бягучай працоўнай прасторы" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Шматзадачнасць" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Кіраванне параметрамі прадукцыйнасці і шматзадачнасці" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "Шматзадачнасць;Прадукцыйнасць;Працоўны стол;Кастамізацыя;" ++ + #: panels/background/background.ui:49 + msgid "_Background" + msgstr "_Абрус" +@@ -2014,10 +2126,6 @@ msgstr "" + "Чулая панэль;Паказальнік;Пстрычка;Дотык;Падвойная пстрычка;Кнопка;Трэкбол;" + "Пракрутка;" + +-#: panels/mouse/gnome-mouse-properties.ui:50 +-msgid "General" +-msgstr "Агульныя настройкі" +- + #: panels/mouse/gnome-mouse-properties.ui:88 + msgid "Primary Button" + msgstr "Галоўная кнопка" +diff --git a/po/bg.po b/po/bg.po +index 63d9c3dfb..f35ab413f 100644 +--- a/po/bg.po ++++ b/po/bg.po +@@ -1,3 +1,22 @@ ++# #-#-#-#-# bg.po.multitasking (gnome-control-center master) #-#-#-#-# ++# Bulgarian translation of gnome-control-center po-file. ++# Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc. ++# Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. ++# Copyright (C) 2011, 2012, 2013, 2014 Free Software Foundation, Inc. ++# Copyright (C) 2015, 2016 Free Software Foundation, Inc. ++# Copyright (C) 2009 Krasimir "Bfaf" Chonov . ++# Copyright (C) 2021 Alexander Shopov . ++# Borislav Aleksandrov , 2002. ++# Yanko Kaneti , 2002. ++# Rostislav Raykov , 2004, 2005. ++# Vladimir Petkov , 2004, 2005, 2006. ++# Alexander Shopov , 2006, 2007, 2009, 2012, 2014, 2015, 2016, 2021. ++# Yavor Doganov , 2007, 2008. ++# Krasimir "Bfaf" Chonov , 2009. ++# Jordan Miladinov , 2011 ++# Ivaylo Valkov , 2011, 2012, 2013. ++# ++# #-#-#-#-# bg.po (gnome-control-center master) #-#-#-#-# + # Bulgarian translation of gnome-control-center po-file. + # Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc. + # Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +@@ -14,8 +33,23 @@ + # Jordan Miladinov , 2011 + # Ivaylo Valkov , 2011, 2012, 2013. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# bg.po.multitasking (gnome-control-center master) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-15 07:31+0000\n" ++"PO-Revision-Date: 2021-09-21 11:02+0200\n" ++"Last-Translator: Alexander Shopov \n" ++"Language-Team: Bulgarian \n" ++"Language: bg\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"#-#-#-#-# bg.po (gnome-control-center master) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center master\n" + "Report-Msgid-Bugs-To: \n" + "POT-Creation-Date: 2017-09-12 22:26+0300\n" +@@ -28,6 +62,97 @@ msgstr "" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" + ++#. #-#-#-#-# bg.po.multitasking (gnome-control-center master) #-#-#-#-# ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++#: ../panels/mouse/gnome-mouse-properties.ui.h:1 ++msgid "General" ++msgstr "Общи" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "Активен _ъгъл" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "" ++"Натиснете горния ляв ъгъл на екрана, за да отворите прегледа на дейностите." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "Активни _ръбове" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Завлачете прозорците до горния, долния, левия или десния ръб на екрана, за " ++"да ги преоразмерите." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Работно пространство" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Динамични работни пространства" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Автоматично изчистване на незаети работни пространства." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Постоянен брой работни пространства" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Укажете точен брой на работните пространства" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Брой работни пространства" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "На много монитори" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Работни пространства _само на основния екран" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Работни пространства на _всички екрани" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Смяна на програмите" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Програми от всички _работни пространства" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Програми само от текущото _работно пространство" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Многозадачност" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Настройките за производителност и работа по много задачи" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"multitasking;multitask;productivity;customize;desktop;многозадачност;" ++"паралелност;производителност;продуктивност;работно пространство;" ++ + #: ../panels/background/background.ui.h:1 + msgid "_Background" + msgstr "_Фон" +@@ -2013,10 +2138,6 @@ msgstr "" + "натискане;бутон;джойстик;придвижване;trackpad;pointer;click;tap;double;" + "button;trackball;scroll;" + +-#: ../panels/mouse/gnome-mouse-properties.ui.h:1 +-msgid "General" +-msgstr "Общи" +- + #: ../panels/mouse/gnome-mouse-properties.ui.h:2 + msgid "Primary Button" + msgstr "Основен бутон" +diff --git a/po/ca.po b/po/ca.po +index db22a817f..fd49a05f5 100644 +--- a/po/ca.po ++++ b/po/ca.po +@@ -1,3 +1,24 @@ ++# #-#-#-#-# ca.po.multitasking (gnome-control-center) #-#-#-#-# ++# Traducció del gnome-control-center de l'equip de Softcatalà. ++# Copyright © 1999-2009 Free Software Foundation, Inc. ++# ++# Terminologia ++# ++# Hotspot -> punt d'accés Wi-Fi ++# Plugged In -> endollat (si es refereix al corrent) ++# ++# Ivan Vilata i Balaguer , 1999, 2000. ++# Softcatalà , 2000, 2001. ++# Jordi Mallach , 2002, 2003, 2004, 2005. ++# Xavier Conde Rueda , 2005. ++# Josep Puigdemont i Casamajó , 2005, 2006, 2007. ++# Joan Duran , 2008-2013. ++# Jordi Serratosa , 2012, 2017. ++# Josep Sànchez , 2013. ++# Jordi Mas i Hernàndez , 2015-2021 ++# Gil Forcada , 2013-2020. ++# Carles Ferrando Garcia , 2018. ++# #-#-#-#-# ca.po (gnome-control-center) #-#-#-#-# + # Traducció del gnome-control-center de l'equip de Softcatalà. + # Copyright © 1999-2009 Free Software Foundation, Inc. + # +@@ -17,13 +38,31 @@ + # Jordi Mas i Hernàndez , 2015-2018. + # Gil Forcada , 2013-2020. + # Carles Ferrando Garcia , 2018. ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# ca.po.multitasking (gnome-control-center) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-08 08:29+0000\n" ++"PO-Revision-Date: 2020-12-21 13:29+0100\n" ++"Last-Translator: Jordi Mas \n" ++"Language-Team: Catalan \n" ++"Language: ca\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 2.4.1\n" ++"#-#-#-#-# ca.po (gnome-control-center) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center\n" +-"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/issues\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" + "POT-Creation-Date: 2021-02-02 07:02+0000\n" + "PO-Revision-Date: 2020-12-21 13:29+0100\n" +-"Last-Translator: Miquel-Àngel Burgos i Fradeja \n" ++"Last-Translator: Miquel-Àngel Burgos i Fradeja \n" + "Language-Team: Catalan \n" + "Language: ca\n" + "MIME-Version: 1.0\n" +@@ -32,6 +71,95 @@ msgstr "" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" + "X-Generator: Poedit 2.4.1\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "General" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Cantonada activa" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "" ++"Toqueu la cantonada superior esquerra per a obrir la vista general " ++"d'Activitats." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Activa les vores de la pantalla" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Arrossegueu les finestres contra les vores superior, esquerra i dreta de la " ++"pantalla per a redimensionar-les." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Espais de treball" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Espais de treball dinàmics" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Suprimeix automàticament els espais de treball buits." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Nombre fix d'espais de treball" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Especifiqueu un nombre d'espais de treball permanents." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Nombre d'espais de treball" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Multi-Monitor" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "_Només espais de treball en la pantalla primària" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "_Espais de treball en totes les pantalles" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Commutació d'aplicacions" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "_Inclou aplicacions de tots els espais de treball" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "I_nclou aplicacions només de l'espai de treball actual" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Multitasca" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Gestiona les preferències de productivitat i multitasca" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or ++#. localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "Multitasca;Productivitat;Personalitza;Escriptori;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Bus del sistema" +@@ -101,8 +229,7 @@ msgid "" + "are concerned about these permissions, consider removing this application." + msgstr "" + "%s té els següents permisos integrats. Aquests no poden ser alterats. Si " +-"esteu preocupats per aquests permisos, considereu suprimir aquesta " +-"aplicació." ++"esteu preocupats per aquests permisos, considereu suprimir aquesta aplicació." + + #: panels/applications/cc-applications-panel.c:1024 + msgid "Web Links" +@@ -184,8 +311,8 @@ msgstr "Permisos i accés" + + #: panels/applications/cc-applications-panel.ui:106 + msgid "" +-"Data and services that this app has asked for access to and permissions that" +-" it requires." ++"Data and services that this app has asked for access to and permissions that " ++"it requires." + msgstr "" + "Dades i serveis que aquesta aplicació ha demanat accés i permisos que " + "requereix." +@@ -208,8 +335,7 @@ msgstr "Càmera" + #: panels/applications/cc-applications-panel.ui:262 + #: panels/keyboard/cc-keyboard-shortcut-editor.ui:85 + #: panels/keyboard/cc-xkb-modifier-dialog.c:355 +-#: panels/keyboard/keyboard-shortcuts.c:367 +-#: panels/network/network-proxy.ui:129 ++#: panels/keyboard/keyboard-shortcuts.c:367 panels/network/network-proxy.ui:129 + #: panels/user-accounts/cc-user-panel.c:843 + #: panels/user-accounts/cc-user-panel.c:938 + #: subprojects/gvc/gvc-mixer-control.c:1900 +@@ -239,8 +365,8 @@ msgstr "No es pot canviar" + + #: panels/applications/cc-applications-panel.ui:175 + msgid "" +-"Individual permissions for applications can be reviewed in the Privacy Settings." ++"Individual permissions for applications can be reviewed in the Privacy Settings." + msgstr "" + "Els permisos individuals per aplicacions poden revisar-se en els paràmetres " + "de Privacitat." +@@ -502,8 +628,8 @@ msgstr "Cap aplicació pot capturar fotografies o vídeo." + + #: panels/camera/cc-camera-panel.ui:75 + msgid "" +-"Use of the camera allows applications to capture photos and video. Disabling" +-" the camera may cause some applications to not function properly." ++"Use of the camera allows applications to capture photos and video. Disabling " ++"the camera may cause some applications to not function properly." + msgstr "" + "L'ús de la càmera permet a les aplicacions capturar fotografies i vídeo. " + "Inhabilitar la càmera pot causar que algunes aplicacions no funcionin " +@@ -527,9 +653,11 @@ msgstr "Protegiu les vostres imatges" + #: panels/camera/gnome-camera-panel.desktop.in.in:20 + #: panels/microphone/gnome-microphone-panel.desktop.in.in:20 + msgid "" +-"screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;network;identity;" ++"screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;" ++"network;identity;" + msgstr "" +-"pantalla;bloca;diagnòstics;fallades;privat;recent;temporal;tmp;índex;nom;xarxa;identitat;" ++"pantalla;bloca;diagnòstics;fallades;privat;recent;temporal;tmp;índex;nom;" ++"xarxa;identitat;" + + #. TRANSLATORS: The user has to attach the sensor to the screen + #: panels/color/cc-color-calibrate.c:347 +@@ -839,8 +967,8 @@ msgstr "Tipus de pantalla" + + #: panels/color/cc-color-panel.ui:241 + msgid "" +-"Select a display target white point. Most displays should be calibrated to a" +-" D65 illuminant." ++"Select a display target white point. Most displays should be calibrated to a " ++"D65 illuminant." + msgstr "" + "Seleccioneu un punt blanc objectiu de la pantalla. La majoria de pantalles " + "s'haurien de calibrar amb una il·luminació D65." +@@ -907,13 +1035,13 @@ msgstr "Requereix connexió a Internet" + + #: panels/color/cc-color-panel.ui:591 + msgid "" +-"You may find these instructions on how to use the profile on GNU/Linux, Apple OS X and Microsoft Windows systems useful." ++"You may find these instructions on how to use the profile on GNU/Linux, Apple OS X and Microsoft Windows systems useful." + msgstr "" + "Podeu trobar les instruccions de com utilitzar el perfil als sistemes GNU/Linux, Apple OS X i Microsoft Windows." ++"href=\"linux\">GNU/Linux, Apple OS X i Microsoft Windows." + + #: panels/color/cc-color-panel.ui:607 + msgid "Summary" +@@ -939,8 +1067,8 @@ msgid "" + "Problems detected. The profile may not work correctly. Show " + "details." + msgstr "" +-"S'han detectat problemes. Aquest perfil no funcionarà correctament. Mostra els detalls." ++"S'han detectat problemes. Aquest perfil no funcionarà correctament. Mostra els detalls." + + #: panels/color/cc-color-panel.ui:788 + msgid "Each device needs an up to date color profile to be color managed." +@@ -1154,8 +1282,8 @@ msgstr "Dades de calibratge de fàbrica proporcionades pel venedor" + #: panels/color/cc-color-profile.c:197 + msgid "Full-screen display correction not possible with this profile" + msgstr "" +-"Amb aquest perfil no es pot fer la correcció de la pantalla en mode pantalla" +-" completa" ++"Amb aquest perfil no es pot fer la correcció de la pantalla en mode pantalla " ++"completa" + + #: panels/color/cc-color-profile.c:219 + msgid "This profile may no longer be accurate" +@@ -1577,9 +1705,11 @@ msgstr "Informeu de problemes" + #: panels/lock/gnome-lock-panel.desktop.in.in:20 + #: panels/usage/gnome-usage-panel.desktop.in.in:20 + msgid "" +-"screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;network;identity;privacy;" ++"screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;" ++"network;identity;privacy;" + msgstr "" +-"pantalla;bloca;diagnòstics;fallades;privat;recent;temporal;tmp;índex;nom;xarxa;identitat;privadesa;privacitat;" ++"pantalla;bloca;diagnòstics;fallades;privat;recent;temporal;tmp;índex;nom;" ++"xarxa;identitat;privadesa;privacitat;" + + #: panels/display/cc-display-panel.c:1014 + #: panels/network/connection-editor/connection-editor.ui:27 +@@ -1793,10 +1923,11 @@ msgstr "Trieu com utilitzar els monitors i projectors connectats" + #. localize the semicolons! The list MUST also end with a semicolon! + #: panels/display/gnome-display-panel.desktop.in.in:19 + msgid "" +-"Panel;Projector;xrandr;Screen;Resolution;Refresh;Monitor;Night;Light;Blue;redshift;color;sunset;sunrise;" ++"Panel;Projector;xrandr;Screen;Resolution;Refresh;Monitor;Night;Light;Blue;" ++"redshift;color;sunset;sunrise;" + msgstr "" +-"Quadre;Projector;xrandr;Pantalla;Resolució;Refresca;Monitor;Nit;Llum;Blau;color;posta" +-" de sol;" ++"Quadre;Projector;xrandr;Pantalla;Resolució;Refresca;Monitor;Nit;Llum;Blau;" ++"color;posta de sol;" + + #: panels/info-overview/cc-info-overview-panel.c:417 + #: panels/info-overview/cc-info-overview-panel.c:432 +@@ -1902,8 +2033,8 @@ msgid "" + "The device name is used to identify this device when it is viewed over the " + "network, or when pairing Bluetooth devices." + msgstr "" +-"El nom del dispositiu s'utilitza per a identificar aquest dispositiu quan es" +-" visualitza en xarxa, o quan s'emparella amb dispositius Bluetooth." ++"El nom del dispositiu s'utilitza per a identificar aquest dispositiu quan es " ++"visualitza en xarxa, o quan s'emparella amb dispositius Bluetooth." + + #: panels/info-overview/cc-info-overview-panel.ui:234 + msgid "_Rename" +@@ -1924,11 +2055,12 @@ msgstr "Visualitzeu informació sobre el sistema" + #. sure that you use the same "translation" for those keywords + #: panels/info-overview/gnome-info-overview-panel.desktop.in.in:23 + msgid "" +-"device;system;information;hostname;memory;processor;version;default;application;preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;" ++"device;system;information;hostname;memory;processor;version;default;" ++"application;preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;" + msgstr "" + "dispositiu;sistema;informació;amfitrió;memòria;processador;versió;per " +-"defecte;aplicació;preferit;cd;dvd;usb;àudio;vídeo;disc;extraïble;multimèdia;execució" +-" automàtica;" ++"defecte;aplicació;preferit;cd;dvd;usb;àudio;vídeo;disc;extraïble;multimèdia;" ++"execució automàtica;" + + #: panels/keyboard/00-multimedia.xml.in:2 + msgid "Sound and Media" +@@ -2335,8 +2467,7 @@ msgstr "No s'ha trobat la tecla de drecera" + + #: panels/keyboard/cc-keyboard-shortcut-editor.c:391 + #, c-format +-msgid "" +-"%s is already being used for %s. If you replace it, %s will be disabled" ++msgid "%s is already being used for %s. If you replace it, %s will be disabled" + msgstr "%s ja s'utilitza per %s. Si la reemplaceu, %s s'inhabilitarà" + + #: panels/keyboard/cc-keyboard-shortcut-editor.c:535 +@@ -2418,8 +2549,8 @@ msgstr "" + msgid "" + "Shortcut;Workspace;Window;Resize;Zoom;Contrast;Input;Source;Lock;Volume;" + msgstr "" +-"Drecera;Espai de treball;Finestra;Canvia la " +-"mida;Amplia;Contrast;Entrada;Font;Bloqueig;Volum;" ++"Drecera;Espai de treball;Finestra;Canvia la mida;Amplia;Contrast;Entrada;" ++"Font;Bloqueig;Volum;" + + #: panels/location/cc-location-panel.ui:31 + msgid "Location services turned off" +@@ -2439,12 +2570,11 @@ msgstr "" + + #: panels/location/cc-location-panel.ui:81 + msgid "" +-"Uses Mozilla Location Service: Privacy Policy" ++"Uses Mozilla Location Service: Privacy Policy" + msgstr "" +-"Utilitza el servei d'ubicació de Mozilla: Política de " +-"privacitat" ++"Utilitza el servei d'ubicació de Mozilla: Política de privacitat" + + #: panels/location/cc-location-panel.ui:93 + msgid "Allow the applications below to determine your location." +@@ -2461,8 +2591,8 @@ msgstr "Protegiu la vostra informació d'ubicació" + #. FIXME + #: panels/lock/cc-lock-panel.ui:27 + msgid "" +-"Automatically locking the screen prevents others from accessing the computer" +-" while you're away." ++"Automatically locking the screen prevents others from accessing the computer " ++"while you're away." + msgstr "" + "Blocar la pantalla automàticament evita que altres puguin accedir a " + "l'ordinador mentre no hi sou." +@@ -2473,8 +2603,7 @@ msgstr "Retard per a posar la pantalla en blanc" + + #: panels/lock/cc-lock-panel.ui:45 + msgid "Period of inactivity after which the screen will go blank." +-msgstr "" +-"Període d'inactivitat després del qual la pantalla es posarà en blanc." ++msgstr "Període d'inactivitat després del qual la pantalla es posarà en blanc." + + #: panels/lock/cc-lock-panel.ui:65 + msgid "Automatic Screen _Lock" +@@ -2485,8 +2614,7 @@ msgid "Automatic _Screen Lock Delay" + msgstr "_Retard per a blocar la pantalla automàticament" + + #: panels/lock/cc-lock-panel.ui:83 +-msgid "" +-"Period after the screen blanks when the screen is automatically locked." ++msgid "Period after the screen blanks when the screen is automatically locked." + msgstr "" + "Període després del qual la pantalla es posa en blanc quan la pantalla es " + "bloca automàticament." +@@ -2661,11 +2789,6 @@ msgstr "Cap aplicació ha demanat accés al micròfon" + msgid "Protect your conversations" + msgstr "Protegiu les vostres converses" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "General" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Botó primari" +@@ -2785,8 +2908,7 @@ msgstr "Ratolí tàctil;Punter;Clic;Toc;Doble;Botó;Ratolí de bola;Desplaça;" + #: panels/network/cc-network-panel.c:661 panels/network/cc-wifi-panel.ui:307 + msgid "Oops, something has gone wrong. Please contact your software vendor." + msgstr "" +-"S'ha produït un error inesperat. Contacteu el vostre proveïdor de " +-"programari." ++"S'ha produït un error inesperat. Contacteu el vostre proveïdor de programari." + + #: panels/network/cc-network-panel.c:667 + msgid "NetworkManager needs to be running." +@@ -2834,8 +2956,7 @@ msgid "Secure network" + msgstr "Xarxa segura" + + #. TRANSLATORS: device status +-#: panels/network/cc-wifi-connection-row.ui:68 +-#: panels/network/panel-common.c:63 ++#: panels/network/cc-wifi-connection-row.ui:68 panels/network/panel-common.c:63 + msgid "Connected" + msgstr "Connectat" + +@@ -2867,8 +2988,8 @@ msgstr "Cal activar el punt d'accés Wi-Fi?" + + #: panels/network/cc-wifi-hotspot-dialog.ui:19 + msgid "" +-"Wi-Fi hotspot allows others to share your internet connection, by creating a" +-" Wi-Fi network that they can connect to. To do this, you must have an " ++"Wi-Fi hotspot allows others to share your internet connection, by creating a " ++"Wi-Fi network that they can connect to. To do this, you must have an " + "internet connection through a source other than Wi-Fi." + msgstr "" + "El punt d'accés Wi-Fi permet compatir la vostra connexió a Internet amb " +@@ -2987,8 +3108,8 @@ msgstr "Estable" + #: panels/network/connection-editor/ce-page.c:241 + msgid "" + "The MAC address entered here will be used as hardware address for the " +-"network device this connection is activated on. This feature is known as MAC" +-" cloning or spoofing. Example: 00:11:22:33:44:55" ++"network device this connection is activated on. This feature is known as MAC " ++"cloning or spoofing. Example: 00:11:22:33:44:55" + msgstr "" + "L'adreça MAC introduïda aquí s'utilitzarà com adreça de maquinari per la " + "connexió per la qual s'activi aquest dispositiu. Aquesta funcionalitat es " +@@ -3268,8 +3389,7 @@ msgstr "Connexió li_mitada: té dades limitades o pot incórrer en càrrecs" + + #: panels/network/connection-editor/details-page.ui:478 + msgid "" +-"Software updates and other large downloads will not be started " +-"automatically." ++"Software updates and other large downloads will not be started automatically." + msgstr "" + "Les actualitzacions de programari i altres baixades grans no s'iniciaran " + "automàticament." +@@ -3432,11 +3552,13 @@ msgstr "No es pot importar la connexió VPN" + #: panels/network/connection-editor/vpn-helpers.c:141 + #, c-format + msgid "" +-"The file “%s” could not be read or does not contain recognized VPN connection information\n" ++"The file “%s” could not be read or does not contain recognized VPN " ++"connection information\n" + "\n" + "Error: %s." + msgstr "" +-"No s'ha pogut llegir el fitxer «%s» o no conté informació reconeguda d'una connexió VPN\n" ++"No s'ha pogut llegir el fitxer «%s» o no conté informació reconeguda d'una " ++"connexió VPN\n" + "\n" + "Error: %s." + +@@ -3509,8 +3631,8 @@ msgstr "Controleu com us connecteu a les xarxes sense fil" + #: panels/network/gnome-wifi-panel.desktop.in.in:19 + msgid "Network;Wireless;Wi-Fi;Wifi;IP;LAN;Broadband;DNS;Hotspot;" + msgstr "" +-"Xarxa;Sense fil;Wi-Fi;Wifi;IP;LAN;Servidor intermediari;WAN;Banda " +-"ampla;DNS;punt d'accés Wi-Fi;" ++"Xarxa;Sense fil;Wi-Fi;Wifi;IP;LAN;Servidor intermediari;WAN;Banda ampla;DNS;" ++"punt d'accés Wi-Fi;" + + #: panels/network/net-device-ethernet.c:95 + msgid "never" +@@ -3533,8 +3655,7 @@ msgstr "Utilitzada per últim cop" + #. * profile. It is also used to display ethernet in the + #. * device list. + #: panels/network/net-device-ethernet.c:261 +-#: panels/network/network-bluetooth.ui:38 +-#: panels/network/network-ethernet.ui:18 ++#: panels/network/network-bluetooth.ui:38 panels/network/network-ethernet.ui:18 + msgid "Wired" + msgstr "Amb fil" + +@@ -4160,11 +4281,15 @@ msgstr "Les claus privades sense xifrar no són segures" + + #: panels/network/wireless-security/eap-method-tls.c:275 + msgid "" +-"The selected private key does not appear to be protected by a password. This could allow your security credentials to be compromised. Please select a password-protected private key.\n" ++"The selected private key does not appear to be protected by a password. This " ++"could allow your security credentials to be compromised. Please select a " ++"password-protected private key.\n" + "\n" + "(You can password-protect your private key with openssl)" + msgstr "" +-"La clau privada que heu seleccionat no sembla protegida amb una contrasenya. Això podria permetre que les credencials de seguretat fossin compromeses. Seleccioneu una clau privada protegida per contrasenya.\n" ++"La clau privada que heu seleccionat no sembla protegida amb una contrasenya. " ++"Això podria permetre que les credencials de seguretat fossin compromeses. " ++"Seleccioneu una clau privada protegida per contrasenya.\n" + "\n" + "(Podeu protegir la vostra clau privada amb una contrasenya amb l'openssl)" + +@@ -4341,14 +4466,13 @@ msgid "" + "invalid wpa-psk: invalid key-length %zu. Must be [8,63] bytes or 64 hex " + "digits" + msgstr "" +-"wpa-psk no vàlid: longitud de clau %zu no vàlida. Ha de tenir [8,63] bytes o" +-" 64 dígits hexadecimals" ++"wpa-psk no vàlid: longitud de clau %zu no vàlida. Ha de tenir [8,63] bytes o " ++"64 dígits hexadecimals" + + #: panels/network/wireless-security/ws-wpa-psk.c:86 + msgid "invalid wpa-psk: cannot interpret key with 64 bytes as hex" + msgstr "" +-"wpa-psk no vàlid: no es pot interpretar la clau de 64 bytes com a " +-"hexadecimal" ++"wpa-psk no vàlid: no es pot interpretar la clau de 64 bytes com a hexadecimal" + + #. This is the per application switch for message tray usage. + #: panels/notifications/cc-app-notifications-dialog.ui:60 +@@ -4458,10 +4582,11 @@ msgstr "Connecteu-vos als comptes en línia i decidiu quin ús en voleu fer" + #. http://en.wikipedia.org/wiki/Pocket_(application) + #: panels/online-accounts/gnome-online-accounts-panel.desktop.in.in:22 + msgid "" +-"Google;Facebook;Twitter;Yahoo;Web;Online;Chat;Calendar;Mail;Contact;ownCloud;Kerberos;IMAP;SMTP;Pocket;ReadItLater;" ++"Google;Facebook;Twitter;Yahoo;Web;Online;Chat;Calendar;Mail;Contact;ownCloud;" ++"Kerberos;IMAP;SMTP;Pocket;ReadItLater;" + msgstr "" +-"Google;Facebook;Twitter;Yahoo;Web;En " +-"línia;Xat;Calendari;Correu;Contacte;ownCloud;Kerberos;IMAP;SMTP;Pocket;ReadItLater;" ++"Google;Facebook;Twitter;Yahoo;Web;En línia;Xat;Calendari;Correu;Contacte;" ++"ownCloud;Kerberos;IMAP;SMTP;Pocket;ReadItLater;" + + #. Translators: This is the button which allows undoing the removal of the + #. printer. +@@ -4476,8 +4601,8 @@ msgstr "Connecteu-vos a les vostres dades al núvol" + #: panels/online-accounts/online-accounts.ui:109 + msgid "No internet connection — connect to set up new online accounts" + msgstr "" +-"No hi ha connexió a Internet. Connecteu-vos per a configurar nous comptes en" +-" línia" ++"No hi ha connexió a Internet. Connecteu-vos per a configurar nous comptes en " ++"línia" + + #: panels/online-accounts/online-accounts.ui:134 + msgid "Add an account" +@@ -4779,8 +4904,8 @@ msgstr "Banda ampla _mòbil" + #: panels/power/cc-power-panel.ui:621 + msgid "Mobile broadband (LTE, 4G, 3G, etc.) can be turned off to save power." + msgstr "" +-"La banda ampla mòbil (LTE, 4G, 3G, etc.) pot ser desactivada per a estalviar" +-" energia." ++"La banda ampla mòbil (LTE, 4G, 3G, etc.) pot ser desactivada per a estalviar " ++"energia." + + #: panels/power/cc-power-panel.ui:671 + msgid "_Bluetooth" +@@ -4867,11 +4992,11 @@ msgstr "" + #. localize the semicolons! The list MUST also end with a semicolon! + #: panels/power/gnome-power-panel.desktop.in.in:19 + msgid "" +-"Power;Sleep;Suspend;Hibernate;Battery;Brightness;Dim;Blank;Monitor;DPMS;Idle;Energy;" ++"Power;Sleep;Suspend;Hibernate;Battery;Brightness;Dim;Blank;Monitor;DPMS;Idle;" ++"Energy;" + msgstr "" +-"Energia;Baix consum;Aturada " +-"temporal;Hibernació;Bateria;Brillantor;Atenuar;En " +-"blanc;Monitor;DPMS;Inactiu;Energia;" ++"Energia;Baix consum;Aturada temporal;Hibernació;Bateria;Brillantor;Atenuar;" ++"En blanc;Monitor;DPMS;Inactiu;Energia;" + + #: panels/printers/authentication-dialog.ui:11 + msgid " " +@@ -4954,8 +5079,8 @@ msgstr "Introduïu una adreça de xarxa o cerqueu una impressora" + #: panels/printers/new-printer-dialog.ui:356 + msgid "Enter username and password to view printers on Print Server." + msgstr "" +-"Introduïu el nom d'usuari i la contrasenya per a visualitzar les impressores" +-" al servidor d'impressió." ++"Introduïu el nom d'usuari i la contrasenya per a visualitzar les impressores " ++"al servidor d'impressió." + + #. Translators: This is the title of the dialog. %s is the printer name. + #: panels/printers/pp-details-dialog.c:74 +@@ -4974,14 +5099,13 @@ msgstr "Selecció d'un fitxer PPD" + + #: panels/printers/pp-details-dialog.c:261 + msgid "" +-"PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, " +-"*.PPD.GZ)" ++"PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *." ++"PPD.GZ)" + msgstr "" +-"Fitxers de descripció d'impressora PostScript (*.ppd, *.PPD, *.ppd.gz, " +-"*.PPD.gz, *.PPD.GZ)" ++"Fitxers de descripció d'impressora PostScript (*.ppd, *.PPD, *.ppd.gz, *.PPD." ++"gz, *.PPD.GZ)" + +-#: panels/printers/pp-details-dialog.ui:68 +-#: panels/printers/printer-entry.ui:223 ++#: panels/printers/pp-details-dialog.ui:68 panels/printers/printer-entry.ui:223 + msgid "Location" + msgstr "Ubicació" + +@@ -5185,8 +5309,8 @@ msgstr "Desbloqueja %s." + #, c-format + msgid "Enter username and password to view printers on %s." + msgstr "" +-"Introduïu el nom d'usuari i la contrasenya per a visualitzar les impressores" +-" a %s." ++"Introduïu el nom d'usuari i la contrasenya per a visualitzar les impressores " ++"a %s." + + #: panels/printers/pp-new-printer-dialog.c:790 + msgid "Searching for Printers" +@@ -5822,11 +5946,11 @@ msgstr "Configura els paràmetres del suport extraïble" + #. semicolon! + #: panels/removable-media/gnome-removable-media-panel.desktop.in.in:19 + msgid "" +-"device;system;default;application;preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;" ++"device;system;default;application;preferred;cd;dvd;usb;audio;video;disc;" ++"removable;media;autorun;" + msgstr "" +-"dispositiu;sistema;informació;per " +-"defecte;aplicació;preferit;cd;dvd;usb;àudio;vídeo;disc;extraïble;multimèdia;execució" +-" automàtica;" ++"dispositiu;sistema;informació;per defecte;aplicació;preferit;cd;dvd;usb;" ++"àudio;vídeo;disc;extraïble;multimèdia;execució automàtica;" + + #: panels/search/cc-search-locations-dialog.c:636 + msgid "Select Location" +@@ -5845,8 +5969,8 @@ msgstr "Ubicacions de cerca" + #: panels/search/cc-search-locations-dialog.ui:69 + #: panels/search/cc-search-locations-dialog.ui:107 + msgid "" +-"Folders which are searched by system applications, such as Files, Photos and" +-" Videos." ++"Folders which are searched by system applications, such as Files, Photos and " ++"Videos." + msgstr "" + "Carpetes que se cerquen per les aplicacions del sistema, com Fitxers, Fotos " + "i Vídeos." +@@ -5877,8 +6001,8 @@ msgstr "Mou avall" + + #: panels/search/cc-search-panel.ui:31 + msgid "" +-"Control which search results are shown in the Activities Overview. The order" +-" of search results can also be changed by moving rows in the list." ++"Control which search results are shown in the Activities Overview. The order " ++"of search results can also be changed by moving rows in the list." + msgstr "" + "Controleu quins resultats de la cerca es mostren a la vista general " + "d'activitats. Podeu canviar l'ordre dels resultats de la cerca movent les " +@@ -5945,10 +6069,12 @@ msgstr "" + #: panels/sharing/cc-sharing-panel.c:702 + #, c-format + msgid "" +-"When remote login is enabled, remote users can connect using the Secure Shell command:\n" ++"When remote login is enabled, remote users can connect using the Secure " ++"Shell command:\n" + "%s" + msgstr "" +-"Quan l'entrada remota està habilitada, els usuaris remots poden connectar-se utilitzant l'ordre del Secure Shell:\n" ++"Quan l'entrada remota està habilitada, els usuaris remots poden connectar-se " ++"utilitzant l'ordre del Secure Shell:\n" + "%s" + + #. TRANSLATORS: %s is replaced with a link to a vnc:// URL +@@ -6058,9 +6184,11 @@ msgstr "Controleu què voleu compartir amb els altres" + #. localize the semicolons! The list MUST also end with a semicolon! + #: panels/sharing/gnome-sharing-panel.desktop.in.in:16 + msgid "" +-"share;sharing;ssh;host;name;remote;desktop;media;audio;video;pictures;photos;movies;server;renderer;" ++"share;sharing;ssh;host;name;remote;desktop;media;audio;video;pictures;photos;" ++"movies;server;renderer;" + msgstr "" +-"comparteix;compartició;ssh;amfitrió;nom;remot;escriptori;multimèdia;àudio;vídeo;imatges;fotografies;pel·lícules;servidor;renderitzar;" ++"comparteix;compartició;ssh;amfitrió;nom;remot;escriptori;multimèdia;àudio;" ++"vídeo;imatges;fotografies;pel·lícules;servidor;renderitzar;" + + #: panels/sharing/org.gnome.controlcenter.remote-login-helper.policy.in.in:11 + msgid "Enable or disable remote login" +@@ -6179,7 +6307,8 @@ msgstr "" + msgid "" + "Card;Microphone;Volume;Fade;Balance;Bluetooth;Headset;Audio;Output;Input;" + msgstr "" +-"Targeta;Micròfon;Volum;Esvair;Balanç;Bluetooth;Auriculars;Àudio;Sortida;Entrada;" ++"Targeta;Micròfon;Volum;Esvair;Balanç;Bluetooth;Auriculars;Àudio;Sortida;" ++"Entrada;" + + #: panels/thunderbolt/cc-bolt-device-dialog.c:94 + #: panels/thunderbolt/cc-bolt-device-entry.c:125 +@@ -6298,10 +6427,12 @@ msgstr "" + #: panels/thunderbolt/cc-bolt-panel.c:468 + msgid "" + "Thunderbolt could not be detected.\n" +-"Either the system lacks Thunderbolt support, it has been disabled in the BIOS or is set to an unsupported security level in the BIOS." ++"Either the system lacks Thunderbolt support, it has been disabled in the " ++"BIOS or is set to an unsupported security level in the BIOS." + msgstr "" + "No s'ha pogut detectar Thunderbolt.\n" +-"O bé el sistema no és compatible amb Thunderbolt, s'ha inhabilitat al BIOS o està configurat amb un nivell de seguretat no compatible al BIOS." ++"O bé el sistema no és compatible amb Thunderbolt, s'ha inhabilitat al BIOS o " ++"està configurat amb un nivell de seguretat no compatible al BIOS." + + #: panels/thunderbolt/cc-bolt-panel.c:512 + msgid "Thunderbolt support has been disabled in the BIOS." +@@ -6897,13 +7028,15 @@ msgstr "Feu més fàcil veure, sentir, teclejar, apuntar i fer clic" + #. or localize the semicolons! The list MUST also end with a semicolon! + #: panels/universal-access/gnome-universal-access-panel.desktop.in.in:19 + msgid "" +-"Keyboard;Mouse;a11y;Accessibility;Universal " +-"Access;Contrast;Cursor;Sound;Zoom;Screen;Reader;big;high;large;text;font;size;AccessX;Sticky;Keys;Slow;Bounce;Mouse;Double;click;Delay;Speed;Assist;Repeat;Blink;visual;hearing;audio;typing;" ++"Keyboard;Mouse;a11y;Accessibility;Universal Access;Contrast;Cursor;Sound;" ++"Zoom;Screen;Reader;big;high;large;text;font;size;AccessX;Sticky;Keys;Slow;" ++"Bounce;Mouse;Double;click;Delay;Speed;Assist;Repeat;Blink;visual;hearing;" ++"audio;typing;" + msgstr "" +-"Teclat;Ratolí;a11y;Accessibilitat;Accés " +-"universal;Contrast;Cursor;So;Zoom;Pantalla;Lector;gran;alt;llarg;text;lletra;mida;AccessX;Tecles" +-" " +-"enganxoses;Tecles;Lent;Salt;Ratolí;Doble;clic;Retard;Assistència;Repetició;Parpelleig;visual;escoltar;àudio;teclejar;" ++"Teclat;Ratolí;a11y;Accessibilitat;Accés universal;Contrast;Cursor;So;Zoom;" ++"Pantalla;Lector;gran;alt;llarg;text;lletra;mida;AccessX;Tecles enganxoses;" ++"Tecles;Lent;Salt;Ratolí;Doble;clic;Retard;Assistència;Repetició;Parpelleig;" ++"visual;escoltar;àudio;teclejar;" + + #: panels/usage/cc-usage-panel.c:154 + msgid "Empty all items from Trash?" +@@ -6935,8 +7068,8 @@ msgstr "Historial dels fitxers" + + #: panels/usage/cc-usage-panel.ui:41 + msgid "" +-"File history keeps a record of files that you have used. This information is" +-" shared between applications, and makes it easier to find files that you " ++"File history keeps a record of files that you have used. This information is " ++"shared between applications, and makes it easier to find files that you " + "might want to use." + msgstr "" + "L'historial dels fitxers manté un registre dels fitxers que heu utilitzat. " +@@ -7261,8 +7394,8 @@ msgid "" + "Fingerprint login allows you to unlock and log into your computer with your " + "finger" + msgstr "" +-"L'inici de sessió amb empremta dactilar permet desbloquejar i iniciar sessió" +-" a l'ordinador amb el dit" ++"L'inici de sessió amb empremta dactilar permet desbloquejar i iniciar sessió " ++"a l'ordinador amb el dit" + + #: panels/user-accounts/cc-fingerprint-dialog.ui:352 + msgid "_Delete Fingerprints" +@@ -7399,8 +7532,7 @@ msgid "" + "Repeatedly lift and place your finger on the reader to enroll your " + "fingerprint" + msgstr "" +-"Aixequeu i poseu el dit al lector per a inscriure la vostra empremta " +-"dactilar" ++"Aixequeu i poseu el dit al lector per a inscriure la vostra empremta dactilar" + + #. TRANSLATORS: This is the label for the button to enroll a new finger + #: panels/user-accounts/cc-fingerprint-dialog.c:1118 +@@ -7610,8 +7742,7 @@ msgstr "C_onserva els fitxers" + #: panels/user-accounts/cc-user-panel.c:646 + #, c-format + msgid "Are you sure you want to revoke remotely managed %s’s account?" +-msgstr "" +-"Segur que voleu revocar el compte %s de l'usuari gestionat remotament?" ++msgstr "Segur que voleu revocar el compte %s de l'usuari gestionat remotament?" + + #: panels/user-accounts/cc-user-panel.c:650 + msgid "_Delete" +@@ -7906,8 +8037,7 @@ msgstr "Combineu majúscules i minúscules i empreu un o dos nombres." + #: panels/user-accounts/pw-utils.c:132 + msgctxt "Password hint" + msgid "" +-"Adding more letters, numbers and punctuation will make the password " +-"stronger." ++"Adding more letters, numbers and punctuation will make the password stronger." + msgstr "" + "Si hi afegiu més lletres, nombres i signes de puntuació la contrasenya serà " + "més segura." +@@ -7980,8 +8110,7 @@ msgstr "El nom d'usuari és massa llarg." + #: panels/user-accounts/user-utils.c:537 + msgid "This will be used to name your home folder and can’t be changed." + msgstr "" +-"Es farà servir per a anomenar la vostra carpeta personal i no es pot " +-"canviar." ++"Es farà servir per a anomenar la vostra carpeta personal i no es pot canviar." + + #: panels/wacom/button-mapping.ui:9 + msgid "Map Buttons" +@@ -8002,8 +8131,8 @@ msgid "" + "shortcut button and hold down the new keys or press Backspace to clear." + msgstr "" + "Per a editar una drecera, feu clic a l'acció «Envia una pulsació de tecla», " +-"premeu el botó de drecera de teclat i premeu la combinació de tecles nova, o" +-" premeu la tecla de retrocés per a netejar-la." ++"premeu el botó de drecera de teclat i premeu la combinació de tecles nova, o " ++"premeu la tecla de retrocés per a netejar-la." + + #: panels/wacom/calibrator/calibrator.ui:61 + msgid "" +@@ -8274,8 +8403,8 @@ msgid "" + "issues. " + msgstr "" + "Aquesta versió del Paràmetres només s'ha d'utilitzar amb finalitats de " +-"desenvolupament. Podeu exposar-vos a un comportament incorrecte del sistema," +-" pèrdua de dades, i altres problemes inesperats. " ++"desenvolupament. Podeu exposar-vos a un comportament incorrecte del sistema, " ++"pèrdua de dades, i altres problemes inesperats. " + + #: shell/cc-window.ui:330 + msgid "Help" +@@ -8323,8 +8452,8 @@ msgstr "L'identificador de l'últim quadre de configuració a obrir" + + #: shell/org.gnome.ControlCenter.gschema.xml:6 + msgid "" +-"The identifier for the last Settings panel to be opened. Unrecognised values" +-" will be ignored and the first panel in the list selected." ++"The identifier for the last Settings panel to be opened. Unrecognised values " ++"will be ignored and the first panel in the list selected." + msgstr "" + "L'identificador de l'últim quadre de configuració a obrir. S'ignoraran els " + "valors que no siguin reconeguts i se seleccionarà el primer quadre de la " +diff --git a/po/cs.po b/po/cs.po +index 6501155ad..ccf0ad9bb 100644 +--- a/po/cs.po ++++ b/po/cs.po +@@ -1,3 +1,4 @@ ++# #-#-#-#-# cs.po.multitasking (gnome-control-center) #-#-#-#-# + # Czech translation of gnome-control-center. + # Copyright (C) 1999, 2003, 2006, 2007, 2008, 2009, 2010, 2011 the author(s) of gnome-control-center. + # Copyright (C) 2003, 2004, 2005, 2006 Miloslav Trmac . +@@ -18,9 +19,49 @@ + # Jiri Eischmann , 2013. + # František Zatloukal , 2014. + # Marek Černocký , 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021. ++# Vojtěch Perník , 2021. + # ++# #-#-#-#-# cs.po (gnome-control-center) #-#-#-#-# ++# Czech translation of gnome-control-center. ++# Copyright (C) 1999, 2003, 2006, 2007, 2008, 2009, 2010, 2011 the author(s) of gnome-control-center. ++# Copyright (C) 2003, 2004, 2005, 2006 Miloslav Trmac . ++# Copyright (C) 2006 Lukas Novotny . ++# This file is distributed under the same license as the gnome-control-center package. ++# ++# David Šauer , 1999. ++# Jiří Lebl , 2002. ++# Michal Bukovjan , 2002, 2003. ++# Miloslav Trmac , 2003, 2004, 2005, 2006. ++# Jakub Friedl , 2006, 2007. ++# Petr Tomeš , 2006. ++# Lukas Novotny , 2006. ++# Petr Kovar , 2007, 2008, 2009, 2010, 2011, 2012. ++# Andre Klapper , 2009. ++# Ondřej Kopka , 2011. ++# Adam Matoušek , 2012. ++# Jiri Eischmann , 2013. ++# František Zatloukal , 2014. ++# Marek Černocký , 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# cs.po.multitasking (gnome-control-center) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-08 08:29+0000\n" ++"PO-Revision-Date: 2021-09-08 10:36+0200\n" ++"Last-Translator: Marek Černocký \n" ++"Language-Team: Czech \n" ++"Language: cs\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n" ++"X-Generator: Gtranslator 40.0\n" ++"X-Project-Style: gnome\n" ++"#-#-#-#-# cs.po (gnome-control-center) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -36,6 +77,94 @@ msgstr "" + "X-Generator: Poedit 2.3\n" + "X-Project-Style: gnome\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Obecné" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "Citlivý ro_h" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Dotkněte se levého horního roku a otevře se přehled Činností." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Aktivní okraje obrazovky" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Přetažením okna k horní, levé nebo pravé hraně obrazovky změníte jeho " ++"velikost." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Pracovní plochy" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Dynamické pracovní plochy" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Bude automaticky odebírat prázdné pracovní plochy." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Neměnný počet pracovních ploch" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Je dán počet trvalých pracovních ploch." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Počet pracovních ploch" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Více monitorů" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Pracovní plochy pouze na _hlavním displeji" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Pracovní plochy na _všech displejích" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Přepínání aplikací" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Zahrnovat aplikace ze _všech pracovních ploch" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Zahrnovat jen aplikace ze _aktuální pracovní plochy" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Multitasking" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Správa předvoleb pro produktivitu a multitasking" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"multitasking;multitask;více úkolů;více úloh;produktivita;přizpůsobit;" ++"přizpůsobení;desktop;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Systémová sběrnice" +@@ -2642,11 +2771,6 @@ msgstr "Žádná aplikace si nepožádala o přístup k mikrofonu" + msgid "Protect your conversations" + msgstr "Ochránit své konverzace" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Obecné" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Hlavní tlačítko" +@@ -8310,4 +8434,3 @@ msgstr[2] "%u vstupů" + #: subprojects/gvc/gvc-mixer-control.c:2867 + msgid "System Sounds" + msgstr "Systémové zvuky" +- +diff --git a/po/da.po b/po/da.po +index 8278336a1..07f7d6509 100644 +--- a/po/da.po ++++ b/po/da.po +@@ -1,3 +1,37 @@ ++# #-#-#-#-# da.po.multitasking (gnome-control-center) #-#-#-#-# ++# Danish translation of the Gnome Control Center. ++# Copyright (C) 1998-2018 ++# This file is distributed under the same license as the gnome-control-center package. ++# Kenneth Christiansen , 1998-2000. ++# Birger Langkjer . ++# Keld Simonsen , 2000. ++# Ole Laursen , 2001, 02, 03, 04, 06. ++# Martin Willemoes Hansen , 2004, 05. ++# Lasse Bang Mikkelsen , 2006. ++# flemming christensen , 2011. ++# Kris Thomsen , 2014. ++# Ask Hjorth Larsen , 2007, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18. ++# scootergrisen, 2015-2016, 2019-2020. ++# Alan Mortensen , 2019-21. ++# ++# Konventioner: ++# ++# detach -> frigøre ++# display -> skærm (fysisk) ++# -> skærmvisning (logisk, når der skal skelnes; ellers skærm) ++# extension -> endelse (det refererer nemlig som regel til f.eks. '.html') ++# GL -> 3d ++# help browser -> hjælpefremviser ++# properties -> indstillinger ++# torn off -> frigøre ++# typing break -> tastepause ++# toggle key -> skiftetast ++# modifier key -> modifikationstast ++# universal access -> tilgængelighed (med mindre nogen kan finde grund til at der bør skelnes) ++# ++# Vær opmærksom på at ordet key bruges både i betydningen nøgle og (genvejs)tast ++# ++# #-#-#-#-# da.po (gnome-control-center) #-#-#-#-# + # Danish translation of the Gnome Control Center. + # Copyright (C) 1998-2018 + # This file is distributed under the same license as the gnome-control-center package. +@@ -30,8 +64,24 @@ + # + # Vær opmærksom på at ordet key bruges både i betydningen nøgle og (genvejs)tast + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# da.po.multitasking (gnome-control-center) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-08 08:29+0000\n" ++"PO-Revision-Date: 2021-09-13 20:12+0200\n" ++"Last-Translator: Alan Mortensen \n" ++"Language-Team: Danish \n" ++"Language: da\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 2.3\n" ++"#-#-#-#-# da.po (gnome-control-center) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -45,6 +95,92 @@ msgstr "" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Generelt" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "Aktivt _hjørne" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Berør det øverste venstre hjørne for at åbne aktivitetsoversigten." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Aktive skærmkanter" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Træk vinduer til øverste, venstre eller højre skærmkanter for at ændre deres " ++"størrelse." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Arbejdsområder" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Dynamiske arbejdsområder" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Fjerner automatisk tomme arbejdsområder." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Fast antal arbejdsområder" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Angiv et antal permanente arbejdsområder." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Antal arbejdsområder" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Flere skærme" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Arbejdsområder kun på den _primære skærm" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Arbejdsområder _på alle skærme" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Skift mellem programmer" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "_Medtag programmer fra alle arbejdsområder" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Medtag _kun programmer fra aktuelle arbejdsområde" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Multitasking" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Håndtér indstillinger for produktivitet og multitasking" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "Multitasking;Multitaske;Produktivitet;Tilpas;Skrivebord;" ++ + #: panels/applications/cc-applications-panel.c:815 + msgid "System Bus" + msgstr "Systembus" +@@ -2549,11 +2685,6 @@ msgstr "Ingen programmer har spurgt om adgang til mikrofon" + msgid "Protect your conversations" + msgstr "Beskyt dine samtaler" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Generelt" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Primær knap" +diff --git a/po/de.po b/po/de.po +index 8f23a5242..6a885be3c 100644 +--- a/po/de.po ++++ b/po/de.po +@@ -24,8 +24,24 @@ + # Tim Sabsch , 2019-2021. + # Philipp Kiemle , 2020-2021. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# de.po.multitasking (gnome-control-center master) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-18 09:55+0000\n" ++"PO-Revision-Date: 2021-09-21 22:08+0200\n" ++"Last-Translator: Philipp Kiemle \n" ++"Language-Team: German \n" ++"Language: de\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 3.0\n" ++"#-#-#-#-# de.po (gnome-control-center master) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center master\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -40,6 +56,94 @@ msgstr "" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" + "X-Generator: Poedit 2.4.2\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Allgemein" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "Funktionale _Ecke" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Die obere linke Ecke berühren, um die Aktivitäten-Übersicht zu öffnen." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "Aktive Bildschirmkanten" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Fenster an den oberen, linken und rechten Bildschirmrand ziehen, um dessen " ++"Größe anzupassen." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Arbeitsflächen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Dynamische Arbeitsflächen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Entfernt leere Arbeitsflächen automatisch." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Feste Anzahl an Arbeitsflächen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Anzahl an permanenten Arbeitsflächen angeben." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "An_zahl der Arbeitsflächen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Mehrere Bildschirme" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Arbeitsflächen nur auf dem _primären Bildschirm" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Arbeitsflächen auf _allen Bildschirmen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Anwendungen wechseln" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Anwendungen von allen A_rbeitsflächen anzeigen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Anwendungen nur von der a_ktuellen Arbeitsfläche anzeigen" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Multitasking" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Einstellungen für Produktivität und Multitasking verwalten" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"Multitasking;Multitask;Productivity;Produktivität;Customize;Bearbeiten;" ++"Desktop;Arbeitsumgebung;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "System-Bus" +@@ -2667,11 +2771,6 @@ msgstr "Es hat keine Anwendung um Mikrofonzugriff gebeten" + msgid "Protect your conversations" + msgstr "Ihre Unterhaltungen schützen" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Allgemein" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Primäre Taste" +diff --git a/po/es.po b/po/es.po +index 6a0f7b997..f2da3977a 100644 +--- a/po/es.po ++++ b/po/es.po +@@ -1,3 +1,4 @@ ++# #-#-#-#-# es.po.multitasking (gnome-control-center master) #-#-#-#-# + # translation of gnome-control-center.master.po to Español + # Copyright © 1999-2002, 2006, 2007, 2008 Free Software Foundation, Inc. + # This file is distributed under the same license as the gnome-control-center package. +@@ -14,9 +15,44 @@ + # + # Jorge González , 2007, 2008, 2009, 2010, 2011. + # Daniel Mustieles , 2010-2021. ++# Daniel Mustieles García , 2021. + # ++# #-#-#-#-# es.po (gnome-control-center master) #-#-#-#-# ++# translation of gnome-control-center.master.po to Español ++# Copyright © 1999-2002, 2006, 2007, 2008 Free Software Foundation, Inc. ++# This file is distributed under the same license as the gnome-control-center package. ++# ++# Pablo Saratxaga , 1998-2001. ++# Carlos Perelló Marín , 2001. ++# Héctor García Álvarez , 2001. ++# Germán Poo Caamaño , 2002 (Revisor). ++# Lucas Di Pentima , 2002. ++# Pablo Gonzalo del Campo , 2002,2003. ++# Francisco Javier F. Serrador , 2003, 2004, 2005, 2006. ++# Claudio Saavedra , 2007. ++# ++# ++# Jorge González , 2007, 2008, 2009, 2010, 2011. ++# Daniel Mustieles , 2010-2021. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# es.po.multitasking (gnome-control-center master) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-08 16:00+0000\n" ++"PO-Revision-Date: 2021-09-14 13:59+0200\n" ++"Last-Translator: Daniel Mustieles García \n" ++"Language-Team: Spanish - Spain \n" ++"Language: es_ES\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1)\n" ++"X-Generator: Gtranslator 40.0\n" ++"#-#-#-#-# es.po (gnome-control-center master) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center master\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -31,6 +67,92 @@ msgstr "" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" + "X-Generator: Gtranslator 3.38.0\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "General" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Esquina activa" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Toque la esquina superior izquierda para abrir la vista de Actividades" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Activar bordes de la pantalla" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Arrastre ventanas a los bordes superior, izquierdo y derecho para " ++"redimensionarlas." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Áreas de trabajo" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "Áreas de trabajo _dinámicas" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Quita las áreas de trabajo vacías automáticamente" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "Número _fijo de áreas de trabajo" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Especifique un número de áreas de trabajo permanentes." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Número de áreas de trabajo" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Multi-pantalla" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Áreas de trabajo sólo en la pantalla _primaria" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Áreas de trabajo en todas las pa_ntallas" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Cambio de aplicaciones" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Incluir aplicaciones de todas las áreas de trabajo" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Incluir aplicaciones sólo del área de trabajo a_ctual" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Multitarea" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Gestionar las preferencias para productividad y multitarea" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "multitarea;productividad;personalizar;escritorio;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Bus del sistema" +@@ -2640,11 +2762,6 @@ msgstr "Ninguna aplicación ha solicitado acceso al micrófono" + msgid "Protect your conversations" + msgstr "Proteger sus conversaciones" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "General" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Botón primario" +diff --git a/po/eu.po b/po/eu.po +index 1e8ded63c..fc6a0792e 100644 +--- a/po/eu.po ++++ b/po/eu.po +@@ -7,9 +7,26 @@ + # Iñaki Larrañaga Murgoitio , 2011, 2012, 2013, 2014, 2015, 2016, 2017. + # Asier Sarasua Garmendia , 2013, 2019, 2020, 2021. + # ++#, fuzzy + msgid "" +-msgstr "Project-Id-Version: gnome-control-center master\n" +-"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/issues\n" ++msgstr "" ++"#-#-#-#-# eu.po.multitasking (gnome-control-center master) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-08 08:29+0000\n" ++"PO-Revision-Date: 2021-09-08 14:00+0100\n" ++"Last-Translator: Asier Sarasua Garmendia \n" ++"Language-Team: Basque \n" ++"Language: eu\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"#-#-#-#-# eu.po (gnome-control-center master) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" + "POT-Creation-Date: 2021-02-17 19:12+0000\n" + "PO-Revision-Date: 2021-02-20 06:00+0100\n" + "Last-Translator: Asier Sarasua Garmendia \n" +@@ -20,6 +37,92 @@ msgstr "Project-Id-Version: gnome-control-center master\n" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Orokorra" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "Izkina _beroa" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Ukitu goiko ezkerreko izkina jardueren ikuspegi orokorra irekitzeko." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "Pantailaren ertz _aktiboak" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Arrastatu leihoak pantailaren goiko, ezkerreko eta eskuineko ertzetara haien " ++"tamaina aldatzeko." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Laneko areak" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "Laneko area _dinamikoak" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Laneko area hutsak automatikoki kentzen ditu." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "Laneko areen kopuru _finkoa" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Zehaztu laneko area iraunkorren kopuru bat." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "Laneko areen _kopurua" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Monitore anitz" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Laneko areak monitore _nagusian soilik" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Laneko areak pantaila _guztietan" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Aplikazioen txandakatzea" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Sartu _laneko area guztietako aplikazioak" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Sartu _uneko laneko areako aplikazioak soilik" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Aldi bereko zereginak" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Kudeatu hobespenak produktibitaterako eta aldi bereko zereginetarako" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "Aldi bereko zereginak;Produktibitatea:Pertsonalizazioa;Mahaigaina;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Sistemaren bus-a" +@@ -87,7 +190,10 @@ msgstr "Ezarpenak aldatu ditzake" + msgid "" + "%s has the following permissions built-in. These cannot be altered. If you " + "are concerned about these permissions, consider removing this application." +-msgstr "%s aplikazioak honako baimenak ditu integratuta. Baimen horiek ezin dira aldatu. Baimen horien inguruko kezkaren bat baduzu, beharbada aplikazio hori kendu beharko zenuke." ++msgstr "" ++"%s aplikazioak honako baimenak ditu integratuta. Baimen horiek ezin dira " ++"aldatu. Baimen horien inguruko kezkaren bat baduzu, beharbada aplikazio hori " ++"kendu beharko zenuke." + + #: panels/applications/cc-applications-panel.c:1024 + msgid "Web Links" +@@ -171,7 +277,9 @@ msgstr "Baimenak eta sarbidea" + msgid "" + "Data and services that this app has asked for access to and permissions that " + "it requires." +-msgstr "Aplikazio honek atzitu nahi dituen datuak eta zerbitzuak eta horrek behar dituen baimenak." ++msgstr "" ++"Aplikazio honek atzitu nahi dituen datuak eta zerbitzuak eta horrek behar " ++"dituen baimenak." + + #: panels/applications/cc-applications-panel.ui:121 + #: panels/applications/cc-applications-panel.ui:127 +@@ -224,7 +332,9 @@ msgstr "Ezin dira aldatu" + msgid "" + "Individual permissions for applications can be reviewed in the Privacy Settings." +-msgstr "Aplikazioen banakako baimenak Pribatutasuna ezarpenetan berrikusi daitezke." ++msgstr "" ++"Aplikazioen banakako baimenak Pribatutasuna " ++"ezarpenetan berrikusi daitezke." + + #: panels/applications/cc-applications-panel.ui:199 + msgid "Integration" +@@ -305,7 +415,8 @@ msgstr "Saiatu bestelako bilaketa" + #: panels/applications/cc-applications-panel.ui:552 + msgid "" + "How much disk space this application is occupying with app data and caches." +-msgstr "Diskoko zenbat espazio betetzen ari den aplikazio hau datuekin eta cacheekin." ++msgstr "" ++"Diskoko zenbat espazio betetzen ari den aplikazio hau datuekin eta cacheekin." + + #: panels/applications/cc-applications-panel.ui:561 + msgid "Application" +@@ -481,7 +592,10 @@ msgstr "Aplikazioek ezin dituzte argazkiak edo bideoa kapturatu." + msgid "" + "Use of the camera allows applications to capture photos and video. Disabling " + "the camera may cause some applications to not function properly." +-msgstr "Kamera erabilita, aplikazioek argazkiak eta bideoak kaptura ditzakete. Kamera desgaitzen bada, beharbada zenbait aplikaziok ez dute behar den moduan funtzionatuko." ++msgstr "" ++"Kamera erabilita, aplikazioek argazkiak eta bideoak kaptura ditzakete. " ++"Kamera desgaitzen bada, beharbada zenbait aplikaziok ez dute behar den " ++"moduan funtzionatuko." + + #: panels/camera/cc-camera-panel.ui:85 + msgid "Allow the applications below to use your camera." +@@ -502,12 +616,16 @@ msgstr "Babestu zure irudiak" + msgid "" + "screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;" + "network;identity;" +-msgstr "pantaila;blokeoa;diagnostikoa;kraskadura;pribatua;azkena;aldi baterako;tmp;izena;sarea;identitatea;" ++msgstr "" ++"pantaila;blokeoa;diagnostikoa;kraskadura;pribatua;azkena;aldi baterako;tmp;" ++"izena;sarea;identitatea;" + + #. TRANSLATORS: The user has to attach the sensor to the screen + #: panels/color/cc-color-calibrate.c:347 + msgid "Place your calibration device over the square and press “Start”" +-msgstr "Jarri kalibrazioaren gailua karratuaren gainean eta egin klik \"Hasi\" botoian" ++msgstr "" ++"Jarri kalibrazioaren gailua karratuaren gainean eta egin klik \"Hasi\" " ++"botoian" + + #. TRANSLATORS: Some calibration devices need the user to move a + #. * dial or switch manually. We also show a picture showing them +@@ -515,7 +633,9 @@ msgstr "Jarri kalibrazioaren gailua karratuaren gainean eta egin klik \"Hasi\" b + #: panels/color/cc-color-calibrate.c:353 + msgid "" + "Move your calibration device to the calibrate position and press “Continue”" +-msgstr "Mugitu kalibrazioaren gailua posizioa kalibratzeko eta egin klik \"Jarraitu\" botoian" ++msgstr "" ++"Mugitu kalibrazioaren gailua posizioa kalibratzeko eta egin klik \"Jarraitu" ++"\" botoian" + + #. TRANSLATORS: Some calibration devices need the user to move a + #. * dial or switch manually. We also show a picture showing them +@@ -523,7 +643,9 @@ msgstr "Mugitu kalibrazioaren gailua posizioa kalibratzeko eta egin klik \"Jarr + #: panels/color/cc-color-calibrate.c:359 + msgid "" + "Move your calibration device to the surface position and press “Continue”" +-msgstr "Mugitu kalibrazioaren gailua gainazalaren posiziora eta egin klik \"Jarraitu\" botoian" ++msgstr "" ++"Mugitu kalibrazioaren gailua gainazalaren posiziora eta egin klik \"Jarraitu" ++"\" botoian" + + #. TRANSLATORS: on some hardware e.g. Lenovo W700 the sensor + #. * is built into the palmrest and we need to fullscreen the +@@ -720,7 +842,8 @@ msgstr "Berrabiarazi ordenagailu hau eta abiatu sistema eragile arrunta." + + #: panels/color/cc-color-panel.c:855 + msgid "Type the URL into your browser to download and install the profile." +-msgstr "Idatzi URLa zure web arakatzailean profila deskargatzeko eta instalatzeko" ++msgstr "" ++"Idatzi URLa zure web arakatzailean profila deskargatzeko eta instalatzeko" + + #. TRANSLATORS: this is the dialog to save the ICC profile + #: panels/color/cc-color-panel.c:883 +@@ -742,7 +865,9 @@ msgstr "Sortu kolore-profil bat hautatutako gailuarentzako" + msgid "" + "The measuring instrument is not detected. Please check it is turned on and " + "correctly connected." +-msgstr "Ez da neurgailurik detektatu. Ziurtatu zaitez piztuta eta ongi konektatuta dagoela." ++msgstr "" ++"Ez da neurgailurik detektatu. Ziurtatu zaitez piztuta eta ongi konektatuta " ++"dagoela." + + #. TRANSLATORS: this is when the button is insensitive + #: panels/color/cc-color-panel.c:1245 +@@ -763,7 +888,10 @@ msgid "" + "Calibration will produce a profile that you can use to color manage your " + "screen. The longer you spend on calibration, the better the quality of the " + "color profile." +-msgstr "Kalibrazioak profil bat sortuko du pantailaren kolorea kudeatzeko. Kalibrazioa zenbat eta sakonagoa izan, kolore-profilaren kalitatea hobea izango da." ++msgstr "" ++"Kalibrazioak profil bat sortuko du pantailaren kolorea kudeatzeko. " ++"Kalibrazioa zenbat eta sakonagoa izan, kolore-profilaren kalitatea hobea " ++"izango da." + + #: panels/color/cc-color-panel.ui:38 + msgid "" +@@ -804,7 +932,9 @@ msgstr "Pantaila mota" + msgid "" + "Select a display target white point. Most displays should be calibrated to a " + "D65 illuminant." +-msgstr "Hautatu helburuko pantailaren puntu zuria. Pantaila gehienak D65 argitasunera doitu beharko lirateke." ++msgstr "" ++"Hautatu helburuko pantailaren puntu zuria. Pantaila gehienak D65 " ++"argitasunera doitu beharko lirateke." + + #: panels/color/cc-color-panel.ui:278 + msgid "Profile Whitepoint" +@@ -814,13 +944,17 @@ msgstr "Profilaren puntu zuria" + msgid "" + "Please set the display to a brightness that is typical for you. Color " + "management will be most accurate at this brightness level." +-msgstr "Ezarri pantailan zuretzako ohikoa den distira. Kolorearen kudeaketa zehatzagoa izango da distiraren maila horretan." ++msgstr "" ++"Ezarri pantailan zuretzako ohikoa den distira. Kolorearen kudeaketa " ++"zehatzagoa izango da distiraren maila horretan." + + #: panels/color/cc-color-panel.ui:307 + msgid "" + "Alternatively, you can use the brightness level used with one of the other " + "profiles for this device." +-msgstr "Bestela, gailu honen beste profiletariko batekin erabilitako distiraren maila erabil dezakezu" ++msgstr "" ++"Bestela, gailu honen beste profiletariko batekin erabilitako distiraren " ++"maila erabil dezakezu" + + #: panels/color/cc-color-panel.ui:318 + msgid "Display Brightness" +@@ -830,7 +964,9 @@ msgstr "Pantailaren distira" + msgid "" + "You can use a color profile on different computers, or even create profiles " + "for different lighting conditions." +-msgstr "KOlore-profila bat erabil dezakezu ordenagailu desberdinetan, edo argitasun baldintza desberdinetarako profilak sor ditzakezu baita ere." ++msgstr "" ++"KOlore-profila bat erabil dezakezu ordenagailu desberdinetan, edo argitasun " ++"baldintza desberdinetarako profilak sor ditzakezu baita ere." + + #: panels/color/cc-color-panel.ui:348 + msgid "Profile Name:" +@@ -865,7 +1001,11 @@ msgid "" + "You may find these instructions on how to use the profile on GNU/Linux, Apple OS X and Microsoft Windows systems useful." +-msgstr "You may find these instructions on how to use the profile on Profila GNU/Linux, Apple OS X eta Microsoft Windows sistemetan nola erabil daitekeen buruzko informazioa lagungarri gerta dakizuke." ++msgstr "" ++"You may find these instructions on how to use the profile on Profila GNU/Linux, Apple OS X eta Microsoft Windows sistemetan nola erabil daitekeen buruzko " ++"informazioa lagungarri gerta dakizuke." + + #: panels/color/cc-color-panel.ui:607 + msgid "Summary" +@@ -890,11 +1030,14 @@ msgstr "_Gehitu" + msgid "" + "Problems detected. The profile may not work correctly. Show " + "details." +-msgstr "Arazoak aurkitu dira. Baliteke profilak ongi ez funtzionatzea. Erakutsi xehetasunak." ++msgstr "" ++"Arazoak aurkitu dira. Baliteke profilak ongi ez funtzionatzea. Erakutsi xehetasunak." + + #: panels/color/cc-color-panel.ui:788 + msgid "Each device needs an up to date color profile to be color managed." +-msgstr "Gailu bakoitzak koloreen profilaren eguneratzea behar du koloreak kudeatzeko." ++msgstr "" ++"Gailu bakoitzak koloreen profilaren eguneratzea behar du koloreak kudeatzeko." + + #. translators: Text used in link to privacy policy + #: panels/color/cc-color-panel.ui:810 +@@ -1408,7 +1551,9 @@ msgstr "Ordu-_zona automatikoa" + + #: panels/datetime/cc-datetime-panel.ui:439 + msgid "Requires location services enabled and internet access" +-msgstr "Kokaleku-zerbitzuek gaituta egon behar dute eta Interneterako sarbide eduki behar da" ++msgstr "" ++"Kokaleku-zerbitzuek gaituta egon behar dute eta Interneterako sarbide eduki " ++"behar da" + + #: panels/datetime/cc-datetime-panel.ui:454 + msgid "Time Z_one" +@@ -1441,7 +1586,9 @@ msgstr "Aldatu sistemaren ordua eta dataren ezarpenak" + + #: panels/datetime/org.gnome.controlcenter.datetime.policy.in:12 + msgid "To change time or date settings, you need to authenticate." +-msgstr "Sistemaren ordua eta dataren ezarpenak aldatzeko, autentifikatu egin behar zara." ++msgstr "" ++"Sistemaren ordua eta dataren ezarpenak aldatzeko, autentifikatu egin behar " ++"zara." + + #: panels/default-apps/cc-default-apps-panel.ui:31 + msgid "_Web" +@@ -1487,7 +1634,9 @@ msgstr "lehenetsia;aplikazioa;hobetsia;euskarria;" + msgid "" + "Sending reports of technical problems helps us improve %s. Reports are sent " + "anonymously and are scrubbed of personal data. %s" +-msgstr "Arazo teknikoei buruzko txostenak bidaltzean %s hobetzen laguntzen diguzu. Txostenak modu anonimoan bidaltzen dira eta ez dute datu pertsonalik. %s" ++msgstr "" ++"Arazo teknikoei buruzko txostenak bidaltzean %s hobetzen laguntzen diguzu. " ++"Txostenak modu anonimoan bidaltzen dira eta ez dute datu pertsonalik. %s" + + #: panels/diagnostics/cc-diagnostics-panel.ui:28 + msgid "Problem Reporting" +@@ -1514,7 +1663,9 @@ msgstr "Eman zure arazoen berri" + msgid "" + "screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;" + "network;identity;privacy;" +-msgstr "pantaila;blokeoa;diagnostikoa;kraskadura;pribatua;azkena;aldi baterakoa;tmp;indizea;izena;sarea;identitatea;pribatutasuna;" ++msgstr "" ++"pantaila;blokeoa;diagnostikoa;kraskadura;pribatua;azkena;aldi baterakoa;tmp;" ++"indizea;izena;sarea;identitatea;pribatutasuna;" + + #: panels/display/cc-display-panel.c:1014 + #: panels/network/connection-editor/connection-editor.ui:27 +@@ -1562,7 +1713,9 @@ msgstr "Pantaila nagusia" + msgid "" + "Drag displays to match your physical display setup. Select a display to " + "change its settings." +-msgstr "Arrastatu pantailak zure pantaila fisikoaren konfigurazioarekin bat egin dezaten. Hautatu pantaila bat haren ezarpenak aldatzeko." ++msgstr "" ++"Arrastatu pantailak zure pantaila fisikoaren konfigurazioarekin bat egin " ++"dezaten. Hautatu pantaila bat haren ezarpenak aldatzeko." + + #: panels/display/cc-display-panel.ui:250 + msgid "Display Arrangement" +@@ -1657,7 +1810,9 @@ msgstr "Denbora baterako desgaituta bihar arte" + msgid "" + "Night light makes the screen color warmer. This can help to prevent eye " + "strain and sleeplessness." +-msgstr "Gaueko argiaren moduak pantailaren kolorea epeltzen du. Horrek begien estresa eta lo arazoak saihesten lagun dezake." ++msgstr "" ++"Gaueko argiaren moduak pantailaren kolorea epeltzen du. Horrek begien " ++"estresa eta lo arazoak saihesten lagun dezake." + + #: panels/display/cc-night-light-page.ui:127 + msgid "Schedule" +@@ -1724,7 +1879,9 @@ msgstr "Aldatu konektatutako pantaila eta proiektagailuak nola erabiliko diren" + msgid "" + "Panel;Projector;xrandr;Screen;Resolution;Refresh;Monitor;Night;Light;Blue;" + "redshift;color;sunset;sunrise;" +-msgstr "Panela;Proiektagailua;xrandr;Pantaila;Bereizmena;Freskatu;Monitorea;Gaua;Argia;Urdina;kolorea;egunsentia;ilunabarra;" ++msgstr "" ++"Panela;Proiektagailua;xrandr;Pantaila;Bereizmena;Freskatu;Monitorea;Gaua;" ++"Argia;Urdina;kolorea;egunsentia;ilunabarra;" + + #: panels/info-overview/cc-info-overview-panel.c:418 + #: panels/info-overview/cc-info-overview-panel.c:433 +@@ -1829,7 +1986,9 @@ msgstr "Aldatu gailuaren izena" + msgid "" + "The device name is used to identify this device when it is viewed over the " + "network, or when pairing Bluetooth devices." +-msgstr "Gailuaren izena hura identifikatzeko erabiltzen da sarean barrena bistaratzen denean, edo Bluetooth gailuekin parekatzen denean." ++msgstr "" ++"Gailuaren izena hura identifikatzeko erabiltzen da sarean barrena " ++"bistaratzen denean, edo Bluetooth gailuekin parekatzen denean." + + #: panels/info-overview/cc-info-overview-panel.ui:233 + msgid "_Rename" +@@ -1852,7 +2011,10 @@ msgstr "Ikusi sistemari buruzko informazioa" + msgid "" + "device;system;information;hostname;memory;processor;version;default;" + "application;preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;" +-msgstr "gailua;sistema;informazioa;ostalari-izena;memoria;prozesadorea;bertsioa;lehenetsia;aplikazioa;hobetsia;cd;dvd;usb;audioa;bideoa;diskoa;aldagarria;euskarria;auto-exekuzioa;" ++msgstr "" ++"gailua;sistema;informazioa;ostalari-izena;memoria;prozesadorea;bertsioa;" ++"lehenetsia;aplikazioa;hobetsia;cd;dvd;usb;audioa;bideoa;diskoa;aldagarria;" ++"euskarria;auto-exekuzioa;" + + #: panels/keyboard/00-multimedia.xml.in:2 + msgid "Sound and Media" +@@ -2082,7 +2244,9 @@ msgstr "Ordezko karaktereen tekla" + msgid "" + "The alternate characters key can be used to enter additional characters. " + "These are sometimes printed as a third-option on your keyboard." +-msgstr "Ordezko karaktereen tekla karaktere gehigarriak sartzeko erabil daiteke. Batzuetan hirugarren aukera gisa inprimatuta ageri dira zure teklatuan." ++msgstr "" ++"Ordezko karaktereen tekla karaktere gehigarriak sartzeko erabil daiteke. " ++"Batzuetan hirugarren aukera gisa inprimatuta ageri dira zure teklatuan." + + #: panels/keyboard/cc-keyboard-panel.c:74 + #: panels/keyboard/cc-keyboard-panel.c:92 +@@ -2131,7 +2295,12 @@ msgid "" + "it, press compose then a sequence of characters. For example, compose key " + "followed by C and o will enter ©, a followed by " + "' will enter á." +-msgstr "Compose teklak mota askotako karaktereak sartzea ahalbidetzen du. Hura erabiltzeko, sakatu Compose tekla eta, ondoren, karaktereen sekuentzia bat. Adibidez, Compose tekla sakatuta, eta ondoren C eta o erabilita, © sartuko du; a eta ondoren ' erabilita, á sartuko du." ++msgstr "" ++"Compose teklak mota askotako karaktereak sartzea ahalbidetzen du. Hura " ++"erabiltzeko, sakatu Compose tekla eta, ondoren, karaktereen sekuentzia bat. " ++"Adibidez, Compose tekla sakatuta, eta ondoren C eta o " ++"erabilita, © sartuko du; a eta ondoren ' erabilita, " ++"á sartuko du." + + #: panels/keyboard/cc-keyboard-panel.c:98 + msgctxt "keyboard key" +@@ -2202,7 +2371,9 @@ msgstr "Berrezarri lasterbide guztiak?" + msgid "" + "Resetting the shortcuts may affect your custom shortcuts. This cannot be " + "undone." +-msgstr "Lasterbideak berrezartzeak zure lasterbide pertsonalizatuei eragin diezaieke. Hori ezin da desegin." ++msgstr "" ++"Lasterbideak berrezartzeak zure lasterbide pertsonalizatuei eragin " ++"diezaieke. Hori ezin da desegin." + + #: panels/keyboard/cc-keyboard-shortcut-dialog.c:430 + #: panels/keyboard/cc-keyboard-shortcut-editor.ui:275 +@@ -2221,7 +2392,9 @@ msgstr "Gehitu laster-tekla pertsonalizatuak" + + #: panels/keyboard/cc-keyboard-shortcut-dialog.ui:124 + msgid "Set up custom shortcuts for launching apps, running scripts, and more." +-msgstr "Konfiguratu laster-tekla pertsonalizatuak aplikazioak abiarazteko, scriptak exekutatzeko eta gehiagorako." ++msgstr "" ++"Konfiguratu laster-tekla pertsonalizatuak aplikazioak abiarazteko, scriptak " ++"exekutatzeko eta gehiagorako." + + #: panels/keyboard/cc-keyboard-shortcut-dialog.ui:131 + msgid "Add Shortcut" +@@ -2249,7 +2422,9 @@ msgstr "Berrezarri laster-tekla guztiak beraien laster-tekla lehenetsira" + #: panels/keyboard/cc-keyboard-shortcut-editor.c:391 + #, c-format + msgid "%s is already being used for %s. If you replace it, %s will be disabled" +-msgstr "%s dagoeneko erabilia izaten ari da %s(e)rako. Hura ordezten baduzu, %s desgaitu egingo da" ++msgstr "" ++"%s dagoeneko erabilia izaten ari da %s(e)rako. Hura ordezten baduzu, %s " ++"desgaitu egingo da" + + #: panels/keyboard/cc-keyboard-shortcut-editor.c:535 + msgid "Enter the new shortcut" +@@ -2275,7 +2450,9 @@ msgstr "Gehitu laster-tekla pertsonalizatua" + + #: panels/keyboard/cc-keyboard-shortcut-editor.ui:60 + msgid "Press Esc to cancel or Backspace to disable the keyboard shortcut." +-msgstr "Sakatu Esc tekla laster-tekla bertan behera uzteko edo atzera-tekla desgaitzeko." ++msgstr "" ++"Sakatu Esc tekla laster-tekla bertan behera uzteko edo atzera-tekla " ++"desgaitzeko." + + #: panels/keyboard/cc-keyboard-shortcut-editor.ui:135 + #: panels/printers/pp-details-dialog.ui:40 +@@ -2320,13 +2497,16 @@ msgstr "Teklatua" + + #: panels/keyboard/gnome-keyboard-panel.desktop.in.in:4 + msgid "View and change keyboard shortcuts and set your typing preferences" +-msgstr "Ikusi eta aldatu teklatuaren laster-teklak eta ezarri idazteko hobespenak" ++msgstr "" ++"Ikusi eta aldatu teklatuaren laster-teklak eta ezarri idazteko hobespenak" + + #. Translators: Search terms to find the Keyboard panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/keyboard/gnome-keyboard-panel.desktop.in.in:19 + msgid "" + "Shortcut;Workspace;Window;Resize;Zoom;Contrast;Input;Source;Lock;Volume;" +-msgstr "Laster-tekla;Laneko area;Leihoa;Tamaina aldatzea;Zooma;Kontrastea;Sarrera;Iturburua;Blokeatu;Bolumena;" ++msgstr "" ++"Laster-tekla;Laneko area;Leihoa;Tamaina aldatzea;Zooma;Kontrastea;Sarrera;" ++"Iturburua;Blokeatu;Bolumena;" + + #: panels/location/cc-location-panel.ui:31 + msgid "Location services turned off" +@@ -2340,13 +2520,18 @@ msgstr "Aplikazioek ezin dute kokalekuaren informazioa eskuratu." + msgid "" + "Location services allow applications to know your location. Using Wi-Fi and " + "mobile broadband increases accuracy." +-msgstr "Kokaleku-zerbitzuek aplikazioek zure kokalekua ezagutzea baimentzen dute. Haririk gabekoa eta mugikorren banda zabala erabiltzeak zehaztasuna handiagotzen du." ++msgstr "" ++"Kokaleku-zerbitzuek aplikazioek zure kokalekua ezagutzea baimentzen dute. " ++"Haririk gabekoa eta mugikorren banda zabala erabiltzeak zehaztasuna " ++"handiagotzen du." + + #: panels/location/cc-location-panel.ui:81 + msgid "" + "Uses Mozilla Location Service: Privacy Policy" +-msgstr "Mozilla Location Service erabiltzen du: Pribatutasun-politika" ++msgstr "" ++"Mozilla Location Service erabiltzen du: Pribatutasun-politika" + + #: panels/location/cc-location-panel.ui:93 + msgid "Allow the applications below to determine your location." +@@ -2365,7 +2550,9 @@ msgstr "Babestu zure kokalekuaren informazioa" + msgid "" + "Automatically locking the screen prevents others from accessing the computer " + "while you're away." +-msgstr "Pantaila automatikoki blokeatuta, beste batzuk zure ordenagailura sar daitezen eragozten da zu kanpoan zauden bitartean." ++msgstr "" ++"Pantaila automatikoki blokeatuta, beste batzuk zure ordenagailura sar " ++"daitezen eragozten da zu kanpoan zauden bitartean." + + #: panels/lock/cc-lock-panel.ui:44 + msgid "Blank Screen Delay" +@@ -2385,7 +2572,9 @@ msgstr "Pantailaren blokeo _automatikoaren atzerapena" + + #: panels/lock/cc-lock-panel.ui:83 + msgid "Period after the screen blanks when the screen is automatically locked." +-msgstr "Pantaila automatikoki blokeatuta dagoenean pantaila belzteko igaroko den denbora-tartea." ++msgstr "" ++"Pantaila automatikoki blokeatuta dagoenean pantaila belzteko igaroko den " ++"denbora-tartea." + + #: panels/lock/cc-lock-panel.ui:103 + msgid "Show _Notifications on Lock Screen" +@@ -2399,7 +2588,9 @@ msgstr "Debekatu _USB gailu berriak" + msgid "" + "Prevent new USB devices from interacting with the system when the screen is " + "locked." +-msgstr "Eragotzi USB gailu berriek sistemarekin lan egin dezaten pantaila blokeatuta dagoenean." ++msgstr "" ++"Eragotzi USB gailu berriek sistemarekin lan egin dezaten pantaila blokeatuta " ++"dagoenean." + + #. Translators: Option for "Lock screen after blank for" in "Screen Lock" dialog. + #: panels/lock/cc-lock-panel.ui:166 +@@ -2531,7 +2722,10 @@ msgid "" + "Use of the microphone allows applications to record and listen to audio. " + "Disabling the microphone may cause some applications to not function " + "properly." +-msgstr "Mikrofonoa erabilita, aplikazioek audioa grabatu eta entzun dezakete. Mikrofonoa desgaitzen bada, beharbada zenbait aplikaziok ez dute behar den moduan funtzionatuko." ++msgstr "" ++"Mikrofonoa erabilita, aplikazioek audioa grabatu eta entzun dezakete. " ++"Mikrofonoa desgaitzen bada, beharbada zenbait aplikaziok ez dute behar den " ++"moduan funtzionatuko." + + #: panels/microphone/cc-microphone-panel.ui:85 + msgid "Allow the applications below to use your microphone." +@@ -2545,11 +2739,6 @@ msgstr "Ez dago aplikaziorik mikrofonoa erabiltzea eskatu duenik" + msgid "Protect your conversations" + msgstr "Babestu zure hizketaldiak" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Orokorra" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Botoi nagusia" +@@ -2651,7 +2840,9 @@ msgstr "Sagua eta ukipen-panela" + #: panels/mouse/gnome-mouse-panel.desktop.in.in:4 + msgid "" + "Change your mouse or touchpad sensitivity and select right or left-handed" +-msgstr "Aldatu saguaren edo ukipen-panelaren sentikortasuna eta hautatu eskuin edo ezkerreko eskuarekin erabiltzea" ++msgstr "" ++"Aldatu saguaren edo ukipen-panelaren sentikortasuna eta hautatu eskuin edo " ++"ezkerreko eskuarekin erabiltzea" + + #. Translators: Search terms to find the Mouse and Touchpad panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/mouse/gnome-mouse-panel.desktop.in.in:19 +@@ -2660,7 +2851,8 @@ msgstr "Trackpad;Erakuslea;Klik;Sakatu;Bikoitza;Botoia;Trackball;Korritu;" + + #: panels/network/cc-network-panel.c:661 panels/network/cc-wifi-panel.ui:307 + msgid "Oops, something has gone wrong. Please contact your software vendor." +-msgstr "Zerbait gaizki joan da. Jar zaitez harremanetan softwarearen sortzailearekin." ++msgstr "" ++"Zerbait gaizki joan da. Jar zaitez harremanetan softwarearen sortzailearekin." + + #: panels/network/cc-network-panel.c:667 + msgid "NetworkManager needs to be running." +@@ -2725,7 +2917,9 @@ msgstr "Aukerak…" + msgid "" + "Turning on the hotspot will disconnect from %s, and it will not be possible " + "to access the internet through Wi-Fi." +-msgstr "Wifigunea aktibatzen bada, gailua %s saretik deskonektatuko da eta ezin izango da internetera sartu wifi bidez." ++msgstr "" ++"Wifigunea aktibatzen bada, gailua %s saretik deskonektatuko da eta ezin " ++"izango da internetera sartu wifi bidez." + + #: panels/network/cc-wifi-hotspot-dialog.c:265 + msgid "Must have a minimum of 8 characters" +@@ -2740,7 +2934,10 @@ msgid "" + "Wi-Fi hotspot allows others to share your internet connection, by creating a " + "Wi-Fi network that they can connect to. To do this, you must have an " + "internet connection through a source other than Wi-Fi." +-msgstr "Wifiguneari esker, zure internet-konexioa beste batzuekin partekatuko duzu, haiek konektatu ahal izango diren wifi-sare bat sortuko baituzu. Hori egiteko, wifi bidezkoa ez den interneteko konexio bat izan behar duzu." ++msgstr "" ++"Wifiguneari esker, zure internet-konexioa beste batzuekin partekatuko duzu, " ++"haiek konektatu ahal izango diren wifi-sare bat sortuko baituzu. Hori " ++"egiteko, wifi bidezkoa ez den interneteko konexio bat izan behar duzu." + + #: panels/network/cc-wifi-hotspot-dialog.ui:44 + msgid "Network Name" +@@ -2795,7 +2992,8 @@ msgstr "Ez da haririk gabeko moldagailurik aurkitu" + + #: panels/network/cc-wifi-panel.ui:99 + msgid "Make sure you have a Wi-Fi adapter plugged and turned on" +-msgstr "Ziurtatu zaitez haririk gabeko moldagailua entxufatuta eta piztuta edukitzeaz" ++msgstr "" ++"Ziurtatu zaitez haririk gabeko moldagailua entxufatuta eta piztuta edukitzeaz" + + #: panels/network/cc-wifi-panel.ui:134 + msgid "Airplane Mode On" +@@ -2856,7 +3054,10 @@ msgid "" + "The MAC address entered here will be used as hardware address for the " + "network device this connection is activated on. This feature is known as MAC " + "cloning or spoofing. Example: 00:11:22:33:44:55" +-msgstr "Hemen sartutako MAC helbidea erabiliko da konexio hau aktibatzen den sareko gailuaren hardwarearen helbide gisa. Eginbide hau MAC helbidea klonatzea edo iruzurtzea bezala ezagutzen da. Adibidea: 00:11:22:33:44:55" ++msgstr "" ++"Hemen sartutako MAC helbidea erabiliko da konexio hau aktibatzen den sareko " ++"gailuaren hardwarearen helbide gisa. Eginbide hau MAC helbidea klonatzea edo " ++"iruzurtzea bezala ezagutzen da. Adibidea: 00:11:22:33:44:55" + + #: panels/network/connection-editor/ce-page.c:399 + #, c-format +@@ -3128,12 +3329,15 @@ msgstr "Egin erabilgarri beste _erabiltzaileentzako" + + #: panels/network/connection-editor/details-page.ui:467 + msgid "_Metered connection: has data limits or can incur charges" +-msgstr "_Neurtutako konexioa: datu-mugak ditu edo ordainketaren bat eragin dezake" ++msgstr "" ++"_Neurtutako konexioa: datu-mugak ditu edo ordainketaren bat eragin dezake" + + #: panels/network/connection-editor/details-page.ui:478 + msgid "" + "Software updates and other large downloads will not be started automatically." +-msgstr "Software eguneratzeak eta beste deskarga handi batzuk ez dira automatikoki abiaraziko." ++msgstr "" ++"Software eguneratzeak eta beste deskarga handi batzuk ez dira automatikoki " ++"abiaraziko." + + #: panels/network/connection-editor/ethernet-page.ui:25 + #: panels/network/connection-editor/vpn-page.ui:23 +@@ -3297,7 +3501,9 @@ msgid "" + "connection information\n" + "\n" + "Error: %s." +-msgstr "Ezin izan da “%s” fitxategia irakurri, edo ez dauka VPN konexioaren informazio ezagunik.\n" ++msgstr "" ++"Ezin izan da “%s” fitxategia irakurri, edo ez dauka VPN konexioaren " ++"informazio ezagunik.\n" + "\n" + "Errorea: %s." + +@@ -3329,7 +3535,8 @@ msgid "" + "The VPN connection “%s” could not be exported to %s.\n" + "\n" + "Error: %s." +-msgstr "The VPN connection “%s” could not be exported to %s.\n" ++msgstr "" ++"The VPN connection “%s” could not be exported to %s.\n" + "\n" + "Error: %s." + +@@ -3401,7 +3608,9 @@ msgstr "Gehitu konexio berria" + msgid "" + "Network details for the selected networks, including passwords and any " + "custom configuration will be lost." +-msgstr "Hautatutako sareen xehetasunak, pasahitzak eta konfigurazio pertsonalizatuak barne, galdu egingo dira." ++msgstr "" ++"Hautatutako sareen xehetasunak, pasahitzak eta konfigurazio pertsonalizatuak " ++"barne, galdu egingo dira." + + #: panels/network/net-device-wifi.c:855 + msgid "_Forget" +@@ -3448,7 +3657,9 @@ msgstr "Desaktibatuta" + #: panels/network/net-proxy.c:112 + msgid "" + "Web Proxy Autodiscovery is used when a Configuration URL is not provided." +-msgstr "Webeko proxy-autoaurkitzailea erabiltzen da konfigurazioaren URLa ez denean ematen." ++msgstr "" ++"Webeko proxy-autoaurkitzailea erabiltzen da konfigurazioaren URLa ez denean " ++"ematen." + + #. TRANSLATORS: WPAD is bad: if you enable it on an untrusted + #. * network, then anyone else on that network can tell your +@@ -4015,7 +4226,10 @@ msgid "" + "password-protected private key.\n" + "\n" + "(You can password-protect your private key with openssl)" +-msgstr "Hautatutako gako pribatua ez dirudi pasahitz batekin babestuta dagoenik. Horrek zure segurtasun-kredentzialak arriskuan jar ditzake. Hautatu pasahitzarekin babestutako gako pribatu bat.\n" ++msgstr "" ++"Hautatutako gako pribatua ez dirudi pasahitz batekin babestuta dagoenik. " ++"Horrek zure segurtasun-kredentzialak arriskuan jar ditzake. Hautatu " ++"pasahitzarekin babestutako gako pribatu bat.\n" + "\n" + "(Zure gako pribatua pasahitz batekin babes dezakezu openssl-rekin)" + +@@ -4133,20 +4347,26 @@ msgstr "wep gakoa falta da" + #: panels/network/wireless-security/ws-wep-key.c:123 + #, c-format + msgid "invalid wep-key: key with a length of %zu must contain only hex-digits" +-msgstr "baliogabeko wep gakoa: %zu luzera duen gakoak soilik digitu hamaseitarrak eduki ditzake" ++msgstr "" ++"baliogabeko wep gakoa: %zu luzera duen gakoak soilik digitu hamaseitarrak " ++"eduki ditzake" + + #: panels/network/wireless-security/ws-wep-key.c:131 + #, c-format + msgid "" + "invalid wep-key: key with a length of %zu must contain only ascii characters" +-msgstr "baliogabeko wep gakoa: %zu luzera duen gakoak soilik ascii karaktereak eduki ditzake" ++msgstr "" ++"baliogabeko wep gakoa: %zu luzera duen gakoak soilik ascii karaktereak eduki " ++"ditzake" + + #: panels/network/wireless-security/ws-wep-key.c:137 + #, c-format + msgid "" + "invalid wep-key: wrong key length %zu. A key must be either of length 5/13 " + "(ascii) or 10/26 (hex)" +-msgstr "baliogabeko wep gakoa: gakoak okerreko %zu luzera du. Gako baten luzerak 5/13 (ascii) edo 10/26 (hamaseitarra) izan behar du" ++msgstr "" ++"baliogabeko wep gakoa: gakoak okerreko %zu luzera du. Gako baten luzerak " ++"5/13 (ascii) edo 10/26 (hamaseitarra) izan behar du" + + #: panels/network/wireless-security/ws-wep-key.c:144 + msgid "invalid wep-key: passphrase must be non-empty" +@@ -4154,7 +4374,9 @@ msgstr "baliogabeko wep gakoa: pasaesaldia ezin da hutsik egon behar" + + #: panels/network/wireless-security/ws-wep-key.c:146 + msgid "invalid wep-key: passphrase must be shorter than 64 characters" +-msgstr "baliogabeko wep gakoa: pasaesaldiak 64 karaktere baino gutxiago izan behar ditu" ++msgstr "" ++"baliogabeko wep gakoa: pasaesaldiak 64 karaktere baino gutxiago izan behar " ++"ditu" + + #: panels/network/wireless-security/ws-wep-key.ui:11 + msgid "1 (Default)" +@@ -4185,11 +4407,15 @@ msgstr "WEP _indizea" + msgid "" + "invalid wpa-psk: invalid key-length %zu. Must be [8,63] bytes or 64 hex " + "digits" +-msgstr "baliogabeko wpa-psk: gakoaren %zu luzera baliogabea. [8,63] byte edo 64 digitu hamaseitarrekoa izan behar du" ++msgstr "" ++"baliogabeko wpa-psk: gakoaren %zu luzera baliogabea. [8,63] byte edo 64 " ++"digitu hamaseitarrekoa izan behar du" + + #: panels/network/wireless-security/ws-wpa-psk.c:86 + msgid "invalid wpa-psk: cannot interpret key with 64 bytes as hex" +-msgstr "baliogabeko wepwpa-psk: ezin da hamaseitar gisa 64 byte dituen gakoa interpretatu" ++msgstr "" ++"baliogabeko wepwpa-psk: ezin da hamaseitar gisa 64 byte dituen gakoa " ++"interpretatu" + + #. This is the per application switch for message tray usage. + #: panels/notifications/cc-app-notifications-dialog.ui:60 +@@ -4212,7 +4438,9 @@ msgstr "_Jakinarazpenen laster-leihoak" + msgid "" + "Notifications will continue to appear in the notification list when popups " + "are disabled." +-msgstr "Jakinarazpenak jakinarazpenen zerrendan agertzen jarraituko dute laster-leihoak desgaituta daudenean." ++msgstr "" ++"Jakinarazpenak jakinarazpenen zerrendan agertzen jarraituko dute laster-" ++"leihoak desgaituta daudenean." + + #. Popups here refers to message tray notifications in the middle of the screen. + #: panels/notifications/cc-app-notifications-dialog.ui:249 +@@ -4250,7 +4478,8 @@ msgstr "Pantaila b_lokeatzearen jakinarazpenak" + + #: panels/notifications/gnome-notifications-panel.desktop.in.in:4 + msgid "Control which notifications are displayed and what they show" +-msgstr "Kontrolatu jakinarazpenak nola bistaratzen diren eta zer erakusten duten" ++msgstr "" ++"Kontrolatu jakinarazpenak nola bistaratzen diren eta zer erakusten duten" + + #. Translators: Search terms to find the Notifications panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/notifications/gnome-notifications-panel.desktop.in.in:20 +@@ -4287,7 +4516,8 @@ msgstr "Lineako kontuak" + + #: panels/online-accounts/gnome-online-accounts-panel.desktop.in.in:4 + msgid "Connect to your online accounts and decide what to use them for" +-msgstr "Konektatu lineako zure kontuetara eta erabaki zertarako erabiliko dituzun" ++msgstr "" ++"Konektatu lineako zure kontuetara eta erabaki zertarako erabiliko dituzun" + + #. Translators: Search terms to find the Online Accounts panel. + #. Do NOT translate or localize the semicolons! +@@ -4297,7 +4527,9 @@ msgstr "Konektatu lineako zure kontuetara eta erabaki zertarako erabiliko dituzu + msgid "" + "Google;Facebook;Twitter;Yahoo;Web;Online;Chat;Calendar;Mail;Contact;ownCloud;" + "Kerberos;IMAP;SMTP;Pocket;ReadItLater;" +-msgstr "Google;Facebook;Twitter;Yahoo;Weba;Linean;Berriketa;Egutegia;Posta;Kontaktua;ownCloud;Kerberos;IMAP;SMTP;Pocket;ReadItLater;" ++msgstr "" ++"Google;Facebook;Twitter;Yahoo;Weba;Linean;Berriketa;Egutegia;Posta;Kontaktua;" ++"ownCloud;Kerberos;IMAP;SMTP;Pocket;ReadItLater;" + + #. Translators: This is the button which allows undoing the removal of the printer. + #: panels/online-accounts/online-accounts.ui:38 panels/printers/printers.ui:61 +@@ -4310,7 +4542,9 @@ msgstr "Konektatu zure datuak lainoan" + + #: panels/online-accounts/online-accounts.ui:109 + msgid "No internet connection — connect to set up new online accounts" +-msgstr "Ez dago Interneteko konexiorik — konektatu lineako kontu berriak konfiguratzeko" ++msgstr "" ++"Ez dago Interneteko konexiorik — konektatu lineako kontu berriak " ++"konfiguratzeko" + + #: panels/online-accounts/online-accounts.ui:134 + msgid "Add an account" +@@ -4611,7 +4845,9 @@ msgstr "Bandazabal _mugikorra" + + #: panels/power/cc-power-panel.ui:621 + msgid "Mobile broadband (LTE, 4G, 3G, etc.) can be turned off to save power." +-msgstr "Banda zabala mugikorra (LTE, 4G, 3G eta abar) itzali egin daiteke energia aurrezteko." ++msgstr "" ++"Banda zabala mugikorra (LTE, 4G, 3G eta abar) itzali egin daiteke energia " ++"aurrezteko." + + #: panels/power/cc-power-panel.ui:671 + msgid "_Bluetooth" +@@ -4696,7 +4932,9 @@ msgstr "Ikusi bateriaren egoera eta aldatu energia aurrezteko ezarpenak" + msgid "" + "Power;Sleep;Suspend;Hibernate;Battery;Brightness;Dim;Blank;Monitor;DPMS;Idle;" + "Energy;" +-msgstr "Argindarra;Lo egin;Eseki;Hibernatu;Bateria;Distira;Itzali;Belztu;Monitorea;DPMS;Inaktibo;Energia;" ++msgstr "" ++"Argindarra;Lo egin;Eseki;Hibernatu;Bateria;Distira;Itzali;Belztu;Monitorea;" ++"DPMS;Inaktibo;Energia;" + + #: panels/printers/authentication-dialog.ui:11 + msgid " " +@@ -4741,7 +4979,9 @@ msgstr "Inprimagailuak" + + #: panels/printers/gnome-printers-panel.desktop.in.in:4 + msgid "Add printers, view printer jobs and decide how you want to print" +-msgstr "Gehitu inprimagailuak, ikusi inprimatze-lanak eta erabaki zer inprimatzea nahi duzun" ++msgstr "" ++"Gehitu inprimagailuak, ikusi inprimatze-lanak eta erabaki zer inprimatzea " ++"nahi duzun" + + #. Translators: Search terms to find the Printers panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/printers/gnome-printers-panel.desktop.in.in:16 +@@ -4795,7 +5035,9 @@ msgstr "Hautatu PPD fitxategia" + msgid "" + "PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *." + "PPD.GZ)" +-msgstr "PostScript Printer Description fitxategiak (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *.PPD.GZ)" ++msgstr "" ++"PostScript Printer Description fitxategiak (*.ppd, *.PPD, *.ppd.gz, *.PPD." ++"gz, *.PPD.GZ)" + + #: panels/printers/pp-details-dialog.ui:68 panels/printers/printer-entry.ui:223 + msgid "Location" +@@ -4992,7 +5234,9 @@ msgstr "Desblokeatu %s." + #: panels/printers/pp-new-printer-dialog.c:367 + #, c-format + msgid "Enter username and password to view printers on %s." +-msgstr "Sartu zure erabiltzaile-izena eta pasahitza %s kokalekuan dauden inprimagailuak ikusteko." ++msgstr "" ++"Sartu zure erabiltzaile-izena eta pasahitza %s kokalekuan dauden " ++"inprimagailuak ikusteko." + + #: panels/printers/pp-new-printer-dialog.c:790 + msgid "Searching for Printers" +@@ -5352,7 +5596,8 @@ msgstr "Gehitu inprimagailua…" + msgid "" + "Sorry! The system printing service\n" + "doesn’t seem to be available." +-msgstr "Badirudi sistemako inprimatzeko\n" ++msgstr "" ++"Badirudi sistemako inprimatzeko\n" + "zerbitzua ez dagoela erabilgarri." + + #: panels/region/cc-format-chooser.c:148 panels/region/cc-format-chooser.c:189 +@@ -5364,7 +5609,9 @@ msgstr "Formatuak" + msgid "" + "Choose the format for numbers, dates and currencies. Changes take effect on " + "next login." +-msgstr "Aukeratu zenbakietarako, datetarako eta monetetarako formatuak. Aldaketak hurrengo saioa hastean sartuko dira indarrean." ++msgstr "" ++"Aukeratu zenbakietarako, datetarako eta monetetarako formatuak. Aldaketak " ++"hurrengo saioa hastean sartuko dira indarrean." + + #: panels/region/cc-format-chooser.ui:117 + msgid "Search locales..." +@@ -5455,7 +5702,9 @@ msgstr "_Formatuak" + + #: panels/region/cc-region-panel.ui:231 + msgid "Login settings are used by all users when logging into the system" +-msgstr "Erabiltzaile guztiek saio-hasierako ezarpenak darabilte sisteman saioa hastean" ++msgstr "" ++"Erabiltzaile guztiek saio-hasierako ezarpenak darabilte sisteman saioa " ++"hastean" + + #: panels/region/gnome-region-panel.desktop.in.in:3 + msgid "Region & Language" +@@ -5464,7 +5713,9 @@ msgstr "Eskualdea eta hizkuntza" + #: panels/region/gnome-region-panel.desktop.in.in:4 + msgid "" + "Select your display language, formats, keyboard layouts and input sources" +-msgstr "Hautatu pantailaren hizkuntza, formatua, teklatuaren diseinua eta sarrerako iturburuak" ++msgstr "" ++"Hautatu pantailaren hizkuntza, formatua, teklatuaren diseinua eta sarrerako " ++"iturburuak" + + #. Translators: Search terms to find the Region and Language panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/region/gnome-region-panel.desktop.in.in:19 +@@ -5497,7 +5748,8 @@ msgstr "Hautatu aplikazioa bideo DVDentzako" + + #: panels/removable-media/cc-removable-media-panel.c:364 + msgid "Select an application to run when a music player is connected" +-msgstr "Hautatu aplikazio bat exekutatzeko musika erreproduzigailu bat konektatzean" ++msgstr "" ++"Hautatu aplikazio bat exekutatzeko musika erreproduzigailu bat konektatzean" + + #: panels/removable-media/cc-removable-media-panel.c:365 + msgid "Select an application to run when a camera is connected" +@@ -5613,7 +5865,9 @@ msgstr "Konfiguratu euskarri aldagarriaren ezarpenak" + msgid "" + "device;system;default;application;preferred;cd;dvd;usb;audio;video;disc;" + "removable;media;autorun;" +-msgstr "gailua;sistema;lehenetsia;aplikazioa;hobetsia;cd;dvd;usb;audioa;bideoa;diskoa;aldagarria;euskarria;exekuzioa;" ++msgstr "" ++"gailua;sistema;lehenetsia;aplikazioa;hobetsia;cd;dvd;usb;audioa;bideoa;" ++"diskoa;aldagarria;euskarria;exekuzioa;" + + #: panels/search/cc-search-locations-dialog.c:636 + msgid "Select Location" +@@ -5634,7 +5888,9 @@ msgstr "Bilatu kokalekuak" + msgid "" + "Folders which are searched by system applications, such as Files, Photos and " + "Videos." +-msgstr "Sistema-aplikazioek zein karpetetan egingo dituzten bilaketak, adibidez 'Fitxategiak', 'Argazkiak' eta 'Bideoak' karpetetan" ++msgstr "" ++"Sistema-aplikazioek zein karpetetan egingo dituzten bilaketak, adibidez " ++"'Fitxategiak', 'Argazkiak' eta 'Bideoak' karpetetan" + + #: panels/search/cc-search-locations-dialog.ui:52 + msgid "Places" +@@ -5664,12 +5920,16 @@ msgstr "Eraman behera" + msgid "" + "Control which search results are shown in the Activities Overview. The order " + "of search results can also be changed by moving rows in the list." +-msgstr "Jardueren ikuspegi orokorrean zein emaitza erakutsiko den kontrolatzen du. Bilaketa-emaitzen ordena ere aldatu daiteke zerrendako errenkadak mugituta." ++msgstr "" ++"Jardueren ikuspegi orokorrean zein emaitza erakutsiko den kontrolatzen du. " ++"Bilaketa-emaitzen ordena ere aldatu daiteke zerrendako errenkadak mugituta." + + #: panels/search/gnome-search-panel.desktop.in.in:4 + msgid "" + "Control which applications show search results in the Activities Overview" +-msgstr "Kontrolatu zer aplikaziok erakusten dituzten bilaketen emaitzak Jardueren ikuspegian" ++msgstr "" ++"Kontrolatu zer aplikaziok erakusten dituzten bilaketen emaitzak Jardueren " ++"ikuspegian" + + #. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/search/gnome-search-panel.desktop.in.in:19 +@@ -5715,7 +5975,9 @@ msgstr "Aukeratu karpeta" + msgid "" + "File Sharing allows you to share your Public folder with others on your " + "current network using: %s" +-msgstr "Fitxategiak partekatzeak zure uneko sareko beste erabiltzaileek zure 'Publikoa' karpeta ikustea ahalbidetzen du honakoa erabilita: %s" ++msgstr "" ++"Fitxategiak partekatzeak zure uneko sareko beste erabiltzaileek zure " ++"'Publikoa' karpeta ikustea ahalbidetzen du honakoa erabilita: %s" + + #. TRANSLATORS: %s is replaced with a link to a "ssh " command to run + #: panels/sharing/cc-sharing-panel.c:702 +@@ -5724,7 +5986,9 @@ msgid "" + "When remote login is enabled, remote users can connect using the Secure " + "Shell command:\n" + "%s" +-msgstr "Urruneko saio-hasiera gaituta dagoenean, urruneko erabiltzaileek konekta daitezke Shell Seguruko komandoa erabiliz: \n" ++msgstr "" ++"Urruneko saio-hasiera gaituta dagoenean, urruneko erabiltzaileek konekta " ++"daitezke Shell Seguruko komandoa erabiliz: \n" + "%s" + + #. TRANSLATORS: %s is replaced with a link to a vnc:// URL +@@ -5733,7 +5997,9 @@ msgstr "Urruneko saio-hasiera gaituta dagoenean, urruneko erabiltzaileek konekta + msgid "" + "Screen sharing allows remote users to view or control your screen by " + "connecting to %s" +-msgstr "Urruneko pantaila partekatzeak urruneko erabiltzaileek zure pantaila ikustea edo kontrolatzea baimentzen du hona konektatuz: %s" ++msgstr "" ++"Urruneko pantaila partekatzeak urruneko erabiltzaileek zure pantaila ikustea " ++"edo kontrolatzea baimentzen du hona konektatuz: %s" + + #: panels/sharing/cc-sharing-panel.c:813 + msgid "Copy" +@@ -5833,7 +6099,9 @@ msgstr "Kontrolatu besteekin zer partekatzea nahi duzun" + msgid "" + "share;sharing;ssh;host;name;remote;desktop;media;audio;video;pictures;photos;" + "movies;server;renderer;" +-msgstr "partekatu;partekatzea;ssh;ostalaria;izena;urrunekoa;mahaigaina;multimedia;bideoa;irudiak;argazkiak;filmak;zerbitzaria;errendatzea;" ++msgstr "" ++"partekatu;partekatzea;ssh;ostalaria;izena;urrunekoa;mahaigaina;multimedia;" ++"bideoa;irudiak;argazkiak;filmak;zerbitzaria;errendatzea;" + + #: panels/sharing/org.gnome.controlcenter.remote-login-helper.policy.in.in:11 + msgid "Enable or disable remote login" +@@ -5949,7 +6217,9 @@ msgstr "Aldatu soinuaren bolumena, sarrerak, irteerak eta eta alerten soinuak" + #: panels/sound/gnome-sound-panel.desktop.in.in:20 + msgid "" + "Card;Microphone;Volume;Fade;Balance;Bluetooth;Headset;Audio;Output;Input;" +-msgstr "Txartela;Mikrofonoa;Bolumena;Iraungi;Balantzea;Bluetooth-a;Entzungailua;Audioa;Irteera;Sarrera;" ++msgstr "" ++"Txartela;Mikrofonoa;Bolumena;Iraungi;Balantzea;Bluetooth-a;Entzungailua;" ++"Audioa;Irteera;Sarrera;" + + #: panels/thunderbolt/cc-bolt-device-dialog.c:94 + #: panels/thunderbolt/cc-bolt-device-entry.c:125 +@@ -6061,15 +6331,19 @@ msgstr "Baimendua" + #: panels/thunderbolt/cc-bolt-panel.c:175 + msgid "" + "The Thunderbolt subsystem (boltd) is not installed or not set up properly." +-msgstr "Thunderbolt azpisistema (boltd) ez dago instalatuta edo gaizki konfiguratuta dago." ++msgstr "" ++"Thunderbolt azpisistema (boltd) ez dago instalatuta edo gaizki konfiguratuta " ++"dago." + + #: panels/thunderbolt/cc-bolt-panel.c:468 + msgid "" + "Thunderbolt could not be detected.\n" + "Either the system lacks Thunderbolt support, it has been disabled in the " + "BIOS or is set to an unsupported security level in the BIOS." +-msgstr "Thunderbolt ezin izan da detektatu.\n" +-"Sistemak ez dauka Thunderbolt euskarririk, BIOSean desgaitu egin da edo onartzen ez den segurtasun-maila batean ezarri da BIOSean." ++msgstr "" ++"Thunderbolt ezin izan da detektatu.\n" ++"Sistemak ez dauka Thunderbolt euskarririk, BIOSean desgaitu egin da edo " ++"onartzen ez den segurtasun-maila batean ezarri da BIOSean." + + #: panels/thunderbolt/cc-bolt-panel.c:512 + msgid "Thunderbolt support has been disabled in the BIOS." +@@ -6094,7 +6368,8 @@ msgstr "Sarbide zuzena" + + #: panels/thunderbolt/cc-bolt-panel.ui:269 + msgid "Allow direct access to devices such as docks and external GPUs." +-msgstr "Sarbide zuzena baimentzen du atrakeak eta kanpoko GPUak bezalako gailuetara." ++msgstr "" ++"Sarbide zuzena baimentzen du atrakeak eta kanpoko GPUak bezalako gailuetara." + + #: panels/thunderbolt/cc-bolt-panel.ui:289 + msgid "Only USB and Display Port devices can attach." +@@ -6145,7 +6420,9 @@ msgstr "Kurtsorearen tamaina" + #: panels/universal-access/cc-cursor-size-dialog.ui:29 + msgid "" + "Cursor size can be combined with zoom to make it easier to see the cursor." +-msgstr "Kurtsorearen tamaina zoomarekin erabil daiteke kurtsorea errazago ikus ahal izateko." ++msgstr "" ++"Kurtsorearen tamaina zoomarekin erabil daiteke kurtsorea errazago ikus ahal " ++"izateko." + + #: panels/universal-access/cc-pointing-dialog.ui:7 + msgid "Click Assist" +@@ -6221,7 +6498,8 @@ msgstr "Errepikatze-teklak" + + #: panels/universal-access/cc-repeat-keys-dialog.ui:37 + msgid "Key presses repeat when key is held down." +-msgstr "Tekla sakatuta dagoen bitartean, tekla hori behin eta berriz errepikatzen da." ++msgstr "" ++"Tekla sakatuta dagoen bitartean, tekla hori behin eta berriz errepikatzen da." + + #: panels/universal-access/cc-repeat-keys-dialog.ui:102 + msgid "Repeat keys delay" +@@ -6237,7 +6515,9 @@ msgstr "Teklak soinuarekin" + + #: panels/universal-access/cc-sound-keys-dialog.ui:25 + msgid "Beep when Num Lock or Caps Lock are turned on or off." +-msgstr "Jo soinua zenbakiak blokeatzeko edo maiuskulak blokeatzeko teklak aktibatzen edo desaktibatzen direnean." ++msgstr "" ++"Jo soinua zenbakiak blokeatzeko edo maiuskulak blokeatzeko teklak aktibatzen " ++"edo desaktibatzen direnean." + + #: panels/universal-access/cc-sound-keys-dialog.ui:45 + #: panels/universal-access/cc-ua-panel.ui:374 +@@ -6250,7 +6530,9 @@ msgstr "Pantaila irakurlea" + + #: panels/universal-access/cc-screen-reader-dialog.ui:24 + msgid "The screen reader reads displayed text as you move the focus." +-msgstr "Pantailaren irakurleak bistaratutako testua irakurtzen du fokua mugitzen duzun arabera." ++msgstr "" ++"Pantailaren irakurleak bistaratutako testua irakurtzen du fokua mugitzen " ++"duzun arabera." + + #: panels/universal-access/cc-screen-reader-dialog.ui:52 + msgid "_Screen Reader" +@@ -6651,7 +6933,8 @@ msgstr "Kolore-efektuak" + + #: panels/universal-access/gnome-universal-access-panel.desktop.in.in:4 + msgid "Make it easier to see, hear, type, point and click" +-msgstr "Egin errazagoa ikusteko, entzuteko, idazteko, kokatzeko eta klik egiteko" ++msgstr "" ++"Egin errazagoa ikusteko, entzuteko, idazteko, kokatzeko eta klik egiteko" + + #. Translators: Search terms to find the Accessibility panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/universal-access/gnome-universal-access-panel.desktop.in.in:19 +@@ -6660,7 +6943,12 @@ msgid "" + "Zoom;Screen;Reader;big;high;large;text;font;size;AccessX;Sticky;Keys;Slow;" + "Bounce;Mouse;Double;click;Delay;Speed;Assist;Repeat;Blink;visual;hearing;" + "audio;typing;" +-msgstr "Teklatua;Sagua;a11y;Irisgarritasuna;Irisgarritasun Unibertsala;Kontrastea;Kurtsorea;Soinua;Zooma;Pantaila;Irakurgailua;handia;altua;handia;testua;letra-tipoa;tamaina;AccessX;Itsaskorra;Teklak;Geldoa;Errebotea;Sagua;Bikoitza;klik;Atzerapena;Abiadura;Lagundu;Errepikatu;Keinua;bisuala;entzumena;audioa;idazketa;" ++msgstr "" ++"Teklatua;Sagua;a11y;Irisgarritasuna;Irisgarritasun Unibertsala;Kontrastea;" ++"Kurtsorea;Soinua;Zooma;Pantaila;Irakurgailua;handia;altua;handia;testua;" ++"letra-tipoa;tamaina;AccessX;Itsaskorra;Teklak;Geldoa;Errebotea;Sagua;" ++"Bikoitza;klik;Atzerapena;Abiadura;Lagundu;Errepikatu;Keinua;bisuala;" ++"entzumena;audioa;idazketa;" + + #: panels/usage/cc-usage-panel.c:154 + msgid "Empty all items from Trash?" +@@ -6695,7 +6983,10 @@ msgid "" + "File history keeps a record of files that you have used. This information is " + "shared between applications, and makes it easier to find files that you " + "might want to use." +-msgstr "Fitxategien historiak zuk erabilitako fitxategien erregistro bat gordetzen du. Informazio hori aplikazioen artean partekatzen da, eta errazago bihurtzen du erabili nahi dituzun fitxategiak aurkitzeko lana." ++msgstr "" ++"Fitxategien historiak zuk erabilitako fitxategien erregistro bat gordetzen " ++"du. Informazio hori aplikazioen artean partekatzen da, eta errazago " ++"bihurtzen du erabili nahi dituzun fitxategiak aurkitzeko lana." + + #: panels/usage/cc-usage-panel.ui:56 + msgid "File H_istory" +@@ -6717,7 +7008,10 @@ msgstr "Zakarrontziko eta aldi baterako fitxategiak" + msgid "" + "Trash and temporary files can sometimes include personal or sensitive " + "information. Automatically deleting them can help to protect privacy." +-msgstr "Zakarrontziko eta aldi baterako fitxategiek zenbaitetan informazio pertsonala edo sentikorra izan dezakete. Automatikoki ezabatzen badira, pribatutasuna babesten lagundu dezakete." ++msgstr "" ++"Zakarrontziko eta aldi baterako fitxategiek zenbaitetan informazio " ++"pertsonala edo sentikorra izan dezakete. Automatikoki ezabatzen badira, " ++"pribatutasuna babesten lagundu dezakete." + + #: panels/usage/cc-usage-panel.ui:159 + msgid "Automatically Delete _Trash Content" +@@ -6863,14 +7157,16 @@ msgstr "Huts egin du domeinuarekin elkartzean" + msgid "" + "That login name didn’t work.\n" + "Please try again." +-msgstr "Saioaren hasierako izenak ez du funtzionatzen.\n" ++msgstr "" ++"Saioaren hasierako izenak ez du funtzionatzen.\n" + "Saiatu berriro." + + #: panels/user-accounts/cc-add-user-dialog.c:1173 + msgid "" + "That login password didn’t work.\n" + "Please try again." +-msgstr "Saioaren hasierako pasahitzak ez du funtzionatzen.\n" ++msgstr "" ++"Saioaren hasierako pasahitzak ez du funtzionatzen.\n" + "Saiatu berriro." + + #: panels/user-accounts/cc-add-user-dialog.c:1181 +@@ -6920,7 +7216,10 @@ msgid "" + "Enterprise login allows an existing centrally managed user account to be " + "used on this device. You can also use this account to access company " + "resources on the internet." +-msgstr "Enpresako saio-hasieran baimenduta dago erabiltzaileen kontu zentralizatua erabiltzea gailu honetan. Kontu hau enpresaren interneteko baliabideak atzitzeko ere erabil dezakezu." ++msgstr "" ++"Enpresako saio-hasieran baimenduta dago erabiltzaileen kontu zentralizatua " ++"erabiltzea gailu honetan. Kontu hau enpresaren interneteko baliabideak " ++"atzitzeko ere erabil dezakezu." + + #: panels/user-accounts/cc-add-user-dialog.ui:732 + msgid "You are Offline" +@@ -6966,7 +7265,9 @@ msgstr "_Bai" + msgid "" + "Do you want to delete your registered fingerprints so fingerprint login is " + "disabled?" +-msgstr "Erregistratutako zure hatz-markak ezabatze nahi duzu, hatz-marken bidezko saio-hasiera desgaituz?" ++msgstr "" ++"Erregistratutako zure hatz-markak ezabatze nahi duzu, hatz-marken bidezko " ++"saio-hasiera desgaituz?" + + #. Translators: This is the empty state page label which states that there are no devices ready. + #: panels/user-accounts/cc-fingerprint-dialog.ui:249 +@@ -6993,7 +7294,9 @@ msgstr "Hatz-marken gailua" + msgid "" + "Fingerprint login allows you to unlock and log into your computer with your " + "finger" +-msgstr "Hatz-marken bidezko saio-hasierak hatza erabilita ordenagailua desblokeatzea eta saioa hastea ahalbidetzen du." ++msgstr "" ++"Hatz-marken bidezko saio-hasierak hatza erabilita ordenagailua desblokeatzea " ++"eta saioa hastea ahalbidetzen du." + + #: panels/user-accounts/cc-fingerprint-dialog.ui:352 + msgid "_Delete Fingerprints" +@@ -7129,7 +7432,9 @@ msgstr "Huts egin du erregistroa gelditzeak: %s" + msgid "" + "Repeatedly lift and place your finger on the reader to enroll your " + "fingerprint" +-msgstr "Altxatu eta kokatu hatza irakurgailuan behin eta berriro, zure hatz-marka erregistratzeko" ++msgstr "" ++"Altxatu eta kokatu hatza irakurgailuan behin eta berriro, zure hatz-marka " ++"erregistratzeko" + + #. TRANSLATORS: This is the label for the button to enroll a new finger + #: panels/user-accounts/cc-fingerprint-dialog.c:1118 +@@ -7255,7 +7560,8 @@ msgstr "Uneko _pasahitza" + + #: panels/user-accounts/cc-password-dialog.ui:254 + msgid "Allow user to change their password on next login" +-msgstr "Baimendu erabiltzaileei hurrengo saio-hasieran haien pasahitzak ezartzea" ++msgstr "" ++"Baimendu erabiltzaileei hurrengo saio-hasieran haien pasahitzak ezartzea" + + #: panels/user-accounts/cc-password-dialog.ui:267 + msgid "Set a password now" +@@ -7311,7 +7617,9 @@ msgstr "%s oraindik saioan sartuta dago" + msgid "" + "Deleting a user while they are logged in can leave the system in an " + "inconsistent state." +-msgstr "Erabiltzailea ezabatzen bada saioan sartuta dagoen bitartean, sistema egoera inkoherentean utz daiteke." ++msgstr "" ++"Erabiltzailea ezabatzen bada saioan sartuta dagoen bitartean, sistema egoera " ++"inkoherentean utz daiteke." + + #: panels/user-accounts/cc-user-panel.c:624 + #, c-format +@@ -7322,7 +7630,9 @@ msgstr "%s(r)en fitxategiak mantentzea nahi dituzu?" + msgid "" + "It is possible to keep the home directory, mail spool and temporary files " + "around when deleting a user account." +-msgstr "Karpeta nagusia, postaren ilara eta aldi baterako fitxategiak gordetzeko aukera dago erabiltzaile baten kontua ezabatzean." ++msgstr "" ++"Karpeta nagusia, postaren ilara eta aldi baterako fitxategiak gordetzeko " ++"aukera dago erabiltzaile baten kontua ezabatzean." + + #: panels/user-accounts/cc-user-panel.c:631 + msgid "_Delete Files" +@@ -7335,7 +7645,8 @@ msgstr "_Mantendu fitxategiak" + #: panels/user-accounts/cc-user-panel.c:646 + #, c-format + msgid "Are you sure you want to revoke remotely managed %s’s account?" +-msgstr "Ziur zaude urrunetik kudeatutako “%s”(r)en kontua errebokatzea nahi duzula?" ++msgstr "" ++"Ziur zaude urrunetik kudeatutako “%s”(r)en kontua errebokatzea nahi duzula?" + + #: panels/user-accounts/cc-user-panel.c:650 + msgid "_Delete" +@@ -7382,7 +7693,8 @@ msgstr "Ziurtatu zaitez kontuen zerbitzua instalatuta eta gaituta dagoela." + msgid "" + "To make changes,\n" + "click the * icon first" +-msgstr "Aldaketak egiteko\n" ++msgstr "" ++"Aldaketak egiteko\n" + "aurrenik egin klik * ikonoan" + + #: panels/user-accounts/cc-user-panel.c:1361 +@@ -7394,7 +7706,8 @@ msgstr "Ezabatu hautatutako erabiltzailearen kontua" + msgid "" + "To delete the selected user account,\n" + "click the * icon first" +-msgstr "Hautatutako erabiltzailearen kontua ezabatzeko\n" ++msgstr "" ++"Hautatutako erabiltzailearen kontua ezabatzeko\n" + "aurrenik egin klik * ikonoan" + + #: panels/user-accounts/cc-user-panel.c:1545 +@@ -7434,7 +7747,9 @@ msgstr "_Administratzailea" + msgid "" + "Administrators can add and remove other users, and can change settings for " + "all users." +-msgstr "Administratzaileek beste erabiltzaile batzuk gehitu edo kendu ditzakete, eta erabiltzaile guztien ezarpenak aldatu ditzakete." ++msgstr "" ++"Administratzaileek beste erabiltzaile batzuk gehitu edo kendu ditzakete, eta " ++"erabiltzaile guztien ezarpenak aldatu ditzakete." + + #: panels/user-accounts/cc-user-panel.ui:333 + msgid "_Parental Controls" +@@ -7484,7 +7799,8 @@ msgstr "Gehitu edo kendu erabiltzaileak eta aldatu zure pasahitza" + #. Translators: Search terms to find the Users panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in:20 + msgid "Login;Name;Fingerprint;Avatar;Logo;Face;Password;" +-msgstr "Erabiltzaile-izena;Izena;Hatz-marka;Avatarra;Logotipoa;Aurpegia;Pasahitza;" ++msgstr "" ++"Erabiltzaile-izena;Izena;Hatz-marka;Avatarra;Logotipoa;Aurpegia;Pasahitza;" + + #. Translators: This button enrolls the computer in the domain in order to use enterprise logins. + #: panels/user-accounts/data/join-dialog.ui:39 +@@ -7500,7 +7816,8 @@ msgid "" + "In order to use enterprise logins, this computer needs to be\n" + "enrolled in the domain. Please have your network administrator\n" + "type their domain password here." +-msgstr "Enpresako saioa erabil ahal izateko, ordenagailu honek\n" ++msgstr "" ++"Enpresako saioa erabil ahal izateko, ordenagailu honek\n" + "domeinun erregistratuta egon behar du. Eskatu iezaiozu sareko\n" + "administratzaileari domeinuaren bere pasahitza idazteko hemen." + +@@ -7538,7 +7855,8 @@ msgstr "Saiatu pasahitza piska bat gehiago aldatzen." + #: panels/user-accounts/pw-utils.c:100 + msgctxt "Password hint" + msgid "A password without your user name would be stronger." +-msgstr "Zure erabiltzaile-izenik gabeko pasahitz bat askoz ere sendoagoa litzateke." ++msgstr "" ++"Zure erabiltzaile-izenik gabeko pasahitz bat askoz ere sendoagoa litzateke." + + #: panels/user-accounts/pw-utils.c:102 + msgctxt "Password hint" +@@ -7578,7 +7896,8 @@ msgstr "Saiatu hizki minuskulak gehiago erabiltzea." + #: panels/user-accounts/pw-utils.c:118 + msgctxt "Password hint" + msgid "Try to use more special characters, like punctuation." +-msgstr "Saiatu karaktere berezi gehiago erabiltzea, harridura ikurra bezalakoak." ++msgstr "" ++"Saiatu karaktere berezi gehiago erabiltzea, harridura ikurra bezalakoak." + + #: panels/user-accounts/pw-utils.c:120 + msgctxt "Password hint" +@@ -7595,7 +7914,9 @@ msgctxt "Password hint" + msgid "" + "Try to avoid repeating the same type of character: you need to mix up " + "letters, numbers and punctuation." +-msgstr "Saiatu karaktere mota berdina errepikatzea saihestea: hizki, zenbaki eta ikurrak nahastu behar dituzu." ++msgstr "" ++"Saiatu karaktere mota berdina errepikatzea saihestea: hizki, zenbaki eta " ++"ikurrak nahastu behar dituzu." + + #: panels/user-accounts/pw-utils.c:126 + msgctxt "Password hint" +@@ -7607,12 +7928,15 @@ msgctxt "Password hint" + msgid "" + "Password needs to be longer. Try to add more letters, numbers and " + "punctuation." +-msgstr "Pasahitzak luzeagoa izan behar du. Saiatu hizki, zenbaki eta ikurren arteko nahasketa gehiagorekin." ++msgstr "" ++"Pasahitzak luzeagoa izan behar du. Saiatu hizki, zenbaki eta ikurren arteko " ++"nahasketa gehiagorekin." + + #: panels/user-accounts/pw-utils.c:130 + msgctxt "Password hint" + msgid "Mix uppercase and lowercase and try to use a number or two." +-msgstr "Nahastu hizki maiuskulak eta minuskulak eta erabili zenbaki bat edo bi." ++msgstr "" ++"Nahastu hizki maiuskulak eta minuskulak eta erabili zenbaki bat edo bi." + + #: panels/user-accounts/pw-utils.c:132 + msgctxt "Password hint" +@@ -7673,7 +7997,9 @@ msgstr "Errore ezezaguna" + msgid "" + "The username should usually only consist of lower case letters from a-z, " + "digits and the following characters: - _" +-msgstr "Erabiltzaile-izenak honako karaktereak soilik eduki ditzake: alfabetoko a-z arteko hizki minuskulak, digituak eta '.', '-' eta '_' karaktereak." ++msgstr "" ++"Erabiltzaile-izenak honako karaktereak soilik eduki ditzake: alfabetoko a-z " ++"arteko hizki minuskulak, digituak eta '.', '-' eta '_' karaktereak." + + #: panels/user-accounts/user-utils.c:436 + msgid "Sorry, that user name isn’t available. Please try another." +@@ -7704,13 +8030,18 @@ msgstr "Mapatu botoiak funtzioetara" + msgid "" + "To edit a shortcut, choose the “Send Keystroke” action, press the keyboard " + "shortcut button and hold down the new keys or press Backspace to clear." +-msgstr "Laster-tekla bat editatzeko: aukeratu \"Bidali tekla sakatzea\" ekintza, sakatu teklatuaren laster-teklaren botoia eta eduki sakatuta tekla berriak edo sakatu Atzera-tekla garbitzeko." ++msgstr "" ++"Laster-tekla bat editatzeko: aukeratu \"Bidali tekla sakatzea\" ekintza, " ++"sakatu teklatuaren laster-teklaren botoia eta eduki sakatuta tekla berriak " ++"edo sakatu Atzera-tekla garbitzeko." + + #: panels/wacom/calibrator/calibrator.ui:61 + msgid "" + "Please tap the target markers as they appear on screen to calibrate the " + "tablet." +-msgstr "Ukitu helburuko markatzaileak pantailan agertzen diren ordenan taula kalibratzeko." ++msgstr "" ++"Ukitu helburuko markatzaileak pantailan agertzen diren ordenan taula " ++"kalibratzeko." + + #: panels/wacom/calibrator/calibrator.ui:78 + msgid "Mis-click detected, restarting…" +@@ -7779,7 +8110,9 @@ msgstr "Wacom taula" + + #: panels/wacom/gnome-wacom-panel.desktop.in.in:4 + msgid "Set button mappings and adjust stylus sensitivity for graphics tablets" +-msgstr "Ezarri botoi-mapatzea eta doitu arkatzaren sentikortasuna taula grafikoentzako" ++msgstr "" ++"Ezarri botoi-mapatzea eta doitu arkatzaren sentikortasuna taula " ++"grafikoentzako" + + #. Translators: Search terms to find the Wacom Tablet panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/wacom/gnome-wacom-panel.desktop.in.in:19 +@@ -7968,7 +8301,10 @@ msgid "" + "This version of Settings should only be used for development purposes. You " + "may experience incorrect system behavior, data loss, and other unexpected " + "issues. " +-msgstr "Ezarpenen bertsio hau garapenerako soilik erabili beharko litzateke. Sistemaren portaera okerra, datuen galera eta espero gabeko beste arazo batzuk gerta daitezke. " ++msgstr "" ++"Ezarpenen bertsio hau garapenerako soilik erabili beharko litzateke. " ++"Sistemaren portaera okerra, datuen galera eta espero gabeko beste arazo " ++"batzuk gerta daitezke. " + + #: shell/cc-window.ui:330 + msgid "Help" +@@ -8017,7 +8353,9 @@ msgstr "Irekiko den ezarpenen azken panelaren identifikatzailea" + msgid "" + "The identifier for the last Settings panel to be opened. Unrecognised values " + "will be ignored and the first panel in the list selected." +-msgstr "Irekiko den ezarpenen azken panelaren identifikatzailea. Ezagutzen ez diren balioak ezikusi egingo dira eta zerrendako lehen panela hautatuko da." ++msgstr "" ++"Irekiko den ezarpenen azken panelaren identifikatzailea. Ezagutzen ez diren " ++"balioak ezikusi egingo dira eta zerrendako lehen panela hautatuko da." + + #: shell/org.gnome.ControlCenter.gschema.xml:13 + msgid "Show warning when running a development build of Settings" +@@ -8026,7 +8364,9 @@ msgstr "Erakutsi abisu bat ezarpenen garapen-bertsio bat exekutatzean" + #: shell/org.gnome.ControlCenter.gschema.xml:14 + msgid "" + "Whether Settings should show a warning when running a development build." +-msgstr "Ezarpenek abisu bat erakutsi behar duen ala ez garapen-bertsio bat exekutatzen denean." ++msgstr "" ++"Ezarpenek abisu bat erakutsi behar duen ala ez garapen-bertsio bat " ++"exekutatzen denean." + + #. translators: + #. * The number of sound outputs on a particular device +diff --git a/po/fa.po b/po/fa.po +index c83473ac8..c701e1e47 100644 +--- a/po/fa.po ++++ b/po/fa.po +@@ -7,8 +7,26 @@ + # Arash Mousavi , 2011-2015, 2017. + # Danial Behzadi , 2018-2021. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# fa.po.multitasking (procman) #-#-#-#-#\n" ++"Project-Id-Version: procman\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-24 15:42+0000\n" ++"PO-Revision-Date: 2021-10-19 14:44+0330\n" ++"Last-Translator: eshagh \n" ++"Language-Team: Persian\n" ++"Language: fa\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n > 1);\n" ++"X-DamnedLies-Scope: partial\n" ++"X-Generator: Poedit 3.0\n" ++"X-Poedit-SourceCharset: utf-8\n" ++"#-#-#-#-# fa.po (procman) #-#-#-#-#\n" + "Project-Id-Version: procman\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -25,6 +43,92 @@ msgstr "" + "X-Generator: Poedit 2.4.2\n" + "X-Poedit-SourceCharset: utf-8\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "عمومی" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_گوشهٔ داغ" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "لمس گوشهٔ راست بالا برای گشودن نمای کلّی فعّالیت‌ها." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "لیه‌های صفحهٔ _فعّال" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "کشیدن پنجره‌ها مقابل لبه‌های بالا، راست و جپ صفحه برای تغییر اندازه‌شان." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "فضاهای کاری" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "فضاهای کاری _پویا" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "برداشتن خودکار فضاهای کاری خالی." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "تعداد _ثابت برای فضاهای کاری" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "مشخّص کردن تعداد فضاهای کاری ثابت." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_تعداد فضاهای کاری" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "چندنمایشگره" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "فضاهای کاری فقط روی نمایشگر _اصلی" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "فضاهای کاری روی _تمامی نمایشگرها" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "تعویض برنامه" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "شامل برنامه‌ها از تمامی _فضاهای کاری" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "شامل برنامه‌ها فقط از فضای کاری _کنونی" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "چندوظیفگی" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "مدیریت ترجیحات برای بهره‌وری و چندوظیفگی" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"Multitasking;Multitask;Productivity;Customize;Desktop;چندوظیفگی;بهره‌وری;" ++"شخصی‌سازی;میزکار;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "گذرگاه سامانه" +@@ -90,8 +194,8 @@ msgstr "می‌تواند تنظیمات را تغییر دهد" + #: panels/applications/cc-applications-panel.c:851 + #, c-format + msgid "" +-"%s has the following permissions built-in. These cannot be altered. If you are " +-"concerned about these permissions, consider removing this application." ++"%s has the following permissions built-in. These cannot be altered. If you " ++"are concerned about these permissions, consider removing this application." + msgstr "" + "%s این اجازه‌ها را به صورت توکار دارد و نمی‌توان تغییرش داد. در صورتی که نگران " + "این اجازه‌هایید، حذف این برنامه را در نظر بگیرید." +@@ -176,8 +280,8 @@ msgstr "اجازه‌ها و دسترسی" + + #: panels/applications/cc-applications-panel.ui:106 + msgid "" +-"Data and services that this app has asked for access to and permissions that it " +-"requires." ++"Data and services that this app has asked for access to and permissions that " ++"it requires." + msgstr "" + "داده‌ها و خدماتی که این کاره برای دسترسی به آن‌ها درخواست کرده و اجازه‌هایی که " + "نیاز دارد." +@@ -231,11 +335,11 @@ msgstr "قابل تغییر نیست" + + #: panels/applications/cc-applications-panel.ui:175 + msgid "" +-"Individual permissions for applications can be reviewed in the Privacy Settings." ++"Individual permissions for applications can be reviewed in the Privacy Settings." + msgstr "" +-"اجازه‌های تکّی برای برنامه‌ها می‌توانند در تنظیمات محرمانگی " +-"بازبینی شوند." ++"اجازه‌های تکّی برای برنامه‌ها می‌توانند در تنظیمات محرمانگی بازبینی شوند." + + #: panels/applications/cc-applications-panel.ui:199 + msgid "Integration" +@@ -308,7 +412,8 @@ msgid "No results found" + msgstr "هیچ نتیجه‌ای پیدا نشد" + + #: panels/applications/cc-applications-panel.ui:484 +-#: panels/keyboard/cc-keyboard-shortcut-dialog.ui:177 shell/cc-panel-list.ui:132 ++#: panels/keyboard/cc-keyboard-shortcut-dialog.ui:177 ++#: shell/cc-panel-list.ui:132 + msgid "Try a different search" + msgstr "جست‌وجویی دیگر را بیازمایید" + +@@ -356,15 +461,19 @@ msgstr "گزینش یک عکس" + #: panels/background/cc-background-chooser.c:348 + #: panels/color/cc-color-calibrate.ui:25 panels/color/cc-color-panel.c:238 + #: panels/color/cc-color-panel.c:886 panels/color/cc-color-panel.ui:657 +-#: panels/common/cc-language-chooser.ui:25 panels/display/cc-display-panel.c:1003 ++#: panels/common/cc-language-chooser.ui:25 ++#: panels/display/cc-display-panel.c:1003 + #: panels/info-overview/cc-info-overview-panel.ui:242 + #: panels/keyboard/cc-input-chooser.ui:11 +-#: panels/network/cc-wifi-hotspot-dialog.ui:122 panels/network/cc-wifi-panel.c:866 ++#: panels/network/cc-wifi-hotspot-dialog.ui:122 ++#: panels/network/cc-wifi-panel.c:866 + #: panels/network/connection-editor/connection-editor.ui:17 + #: panels/network/connection-editor/vpn-helpers.c:176 + #: panels/network/connection-editor/vpn-helpers.c:299 +-#: panels/network/net-device-wifi.c:854 panels/printers/new-printer-dialog.ui:45 +-#: panels/printers/pp-details-dialog.c:235 panels/region/cc-format-chooser.ui:28 ++#: panels/network/net-device-wifi.c:854 ++#: panels/printers/new-printer-dialog.ui:45 ++#: panels/printers/pp-details-dialog.c:235 ++#: panels/region/cc-format-chooser.ui:28 + #: panels/search/cc-search-locations-dialog.c:639 + #: panels/sharing/cc-sharing-panel.c:396 panels/usage/cc-usage-panel.c:133 + #: panels/user-accounts/cc-add-user-dialog.ui:28 +@@ -380,7 +489,8 @@ msgstr "_لغو" + + #: panels/background/cc-background-chooser.c:349 + #: panels/network/connection-editor/vpn-helpers.c:177 +-#: panels/printers/pp-details-dialog.c:236 panels/sharing/cc-sharing-panel.c:397 ++#: panels/printers/pp-details-dialog.c:236 ++#: panels/sharing/cc-sharing-panel.c:397 + #: panels/user-accounts/cc-avatar-chooser.c:224 + msgid "_Open" + msgstr "گشودن" +@@ -489,8 +599,8 @@ msgid "" + "Use of the camera allows applications to capture photos and video. Disabling " + "the camera may cause some applications to not function properly." + msgstr "" +-"استفاده از دوربین به برنامه‌ها اجازه می‌دهد که عکس و ویدیو ضبط کنند. ممکن است از " +-"کار انداختن دوربین باعث کارکرد نادرست برخی برنامه‌ها شود." ++"استفاده از دوربین به برنامه‌ها اجازه می‌دهد که عکس و ویدیو ضبط کنند. ممکن است " ++"از کار انداختن دوربین باعث کارکرد نادرست برخی برنامه‌ها شود." + + #: panels/camera/cc-camera-panel.ui:85 + msgid "Allow the applications below to use your camera." +@@ -509,11 +619,11 @@ msgstr "محافظت از عکس‌هایتان" + #: panels/camera/gnome-camera-panel.desktop.in.in:20 + #: panels/microphone/gnome-microphone-panel.desktop.in.in:20 + msgid "" +-"screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;network;" +-"identity;" ++"screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;" ++"network;identity;" + msgstr "" +-"screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;network;" +-"identity;صفحه;قفل;کرش;خصوصی;اخیر;موقت;نمایه;نام;شبکه;هویت;" ++"screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;" ++"network;identity;صفحه;قفل;کرش;خصوصی;اخیر;موقت;نمایه;نام;شبکه;هویت;" + + #. TRANSLATORS: The user has to attach the sensor to the screen + #: panels/color/cc-color-calibrate.c:347 +@@ -532,7 +642,8 @@ msgstr "افزارهٔ واسنجیتان را به موقعیت واسنجی م + #. * dial or switch manually. We also show a picture showing them + #. * what to do... + #: panels/color/cc-color-calibrate.c:359 +-msgid "Move your calibration device to the surface position and press “Continue”" ++msgid "" ++"Move your calibration device to the surface position and press “Continue”" + msgstr "افزارهٔ واسنجیتان را به موقعیت سطح منتقل کرده و «ادامه» را بزنید" + + #. TRANSLATORS: on some hardware e.g. Lenovo W700 the sensor +@@ -776,11 +887,12 @@ msgid "" + "color profile." + msgstr "" + "واسنجی، نمایه‌ای ایجاد خواهد کرد که می‌توانید از آن برای مدیریت رنگ صفحه‌تان " +-"استفاده کنید. هر چه زمان بیش‌تری برای واسنجی بگذارید، کیفت نمایهٔ رنگیتان بیش‌تر " +-"خواهد بود." ++"استفاده کنید. هر چه زمان بیش‌تری برای واسنجی بگذارید، کیفت نمایهٔ رنگیتان " ++"بیش‌تر خواهد بود." + + #: panels/color/cc-color-panel.ui:38 +-msgid "You will not be able to use your computer while calibration takes place." ++msgid "" ++"You will not be able to use your computer while calibration takes place." + msgstr "تا پایان واسنجی نمی‌توانید از رایانه‌تان استفاده کنید." + + #. This is the approximate time it takes to calibrate the display. +@@ -830,8 +942,8 @@ msgid "" + "Please set the display to a brightness that is typical for you. Color " + "management will be most accurate at this brightness level." + msgstr "" +-"لطفا روشنایی صفحه‌نمایش به میزان که برای شما مناسب است تنظیم کنید. مدیریت رنگ در " +-"این سطح روشنایی دقیق‌تر خواهد بود." ++"لطفا روشنایی صفحه‌نمایش به میزان که برای شما مناسب است تنظیم کنید. مدیریت رنگ " ++"در این سطح روشنایی دقیق‌تر خواهد بود." + + #: panels/color/cc-color-panel.ui:307 + msgid "" +@@ -846,11 +958,11 @@ msgstr "روشنایی نمایشگر" + + #: panels/color/cc-color-panel.ui:333 + msgid "" +-"You can use a color profile on different computers, or even create profiles for " +-"different lighting conditions." ++"You can use a color profile on different computers, or even create profiles " ++"for different lighting conditions." + msgstr "" +-"می‌توانید از یک نمایهٔ رنگی روی رایانه‌های مختلف استفاده کرده یا حتا برای حالت‌های " +-"روشنایی متفاوت، نمایه بسازید." ++"می‌توانید از یک نمایهٔ رنگی روی رایانه‌های مختلف استفاده کرده یا حتا برای " ++"حالت‌های روشنایی متفاوت، نمایه بسازید." + + #: panels/color/cc-color-panel.ui:348 + msgid "Profile Name:" +@@ -886,9 +998,9 @@ msgid "" + "\">GNU/Linux, Apple OS X and Microsoft Windows systems useful." + msgstr "" +-"ممکن است این راهنماهای ساخت نمایه روی سامانه‌های گنو/لینوکس، اواس ده اپل و ویندوز مایکروسافت " +-"مفید باشند." ++"ممکن است این راهنماهای ساخت نمایه روی سامانه‌های گنو/" ++"لینوکس، اواس ده اپل و ویندوز " ++"مایکروسافت مفید باشند." + + #: panels/color/cc-color-panel.ui:607 + msgid "Summary" +@@ -914,8 +1026,8 @@ msgid "" + "Problems detected. The profile may not work correctly. Show " + "details." + msgstr "" +-"مشکلاتی شناسایی شدند. ممکن است نمایه درست کار نکند. نمایش جزییات." ++"مشکلاتی شناسایی شدند. ممکن است نمایه درست کار نکند. نمایش " ++"جزییات." + + #: panels/color/cc-color-panel.ui:788 + msgid "Each device needs an up to date color profile to be color managed." +@@ -1136,7 +1248,8 @@ msgid "Color" + msgstr "رنگ" + + #: panels/color/gnome-color-panel.desktop.in.in:4 +-msgid "Calibrate the color of your devices, such as displays, cameras or printers" ++msgid "" ++"Calibrate the color of your devices, such as displays, cameras or printers" + msgstr "رنگ افزاره‌هایتان نظیر نمایشگرها، دوربین‌ها یا چاپگرها را واسنجی کنید" + + #. Translators: Search terms to find the Color panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +@@ -1161,7 +1274,8 @@ msgstr "_انتخاب" + msgid "No languages found" + msgstr "هیچ زبانی پیدا نشد" + +-#: panels/common/cc-language-chooser.ui:82 panels/keyboard/cc-input-chooser.c:178 ++#: panels/common/cc-language-chooser.ui:82 ++#: panels/keyboard/cc-input-chooser.c:178 + msgid "More…" + msgstr "بیش‌تر…" + +@@ -1512,8 +1626,8 @@ msgid "" + "Sending reports of technical problems helps us improve %s. Reports are sent " + "anonymously and are scrubbed of personal data. %s" + msgstr "" +-"ارسال گزارش‌های مشکلات فنی، به بهبود %s کمک می‌کند. گزارش‌ها به صورت ناشناس ارسال " +-"شده و عاری از اطلاعات شخصیند. %s" ++"ارسال گزارش‌های مشکلات فنی، به بهبود %s کمک می‌کند. گزارش‌ها به صورت ناشناس " ++"ارسال شده و عاری از اطلاعات شخصیند. %s" + + #: panels/diagnostics/cc-diagnostics-panel.ui:28 + msgid "Problem Reporting" +@@ -1538,12 +1652,12 @@ msgstr "گزارش مشکلاتتان" + #: panels/lock/gnome-lock-panel.desktop.in.in:20 + #: panels/usage/gnome-usage-panel.desktop.in.in:20 + msgid "" +-"screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;network;" +-"identity;privacy;" ++"screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;" ++"network;identity;privacy;" + msgstr "" +-"screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;network;" +-"identity;privacy;صفحه;قفل;کرش;خصوصی;اخیر;موقت;نمایه;نام;شبکه;هویت;محرمانگی" +-"\"حریم شخصی;حریم خصوصی;" ++"screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;" ++"network;identity;privacy;صفحه;قفل;کرش;خصوصی;اخیر;موقت;نمایه;نام;شبکه;هویت;" ++"محرمانگی\"حریم شخصی;حریم خصوصی;" + + #: panels/display/cc-display-panel.c:1014 + #: panels/network/connection-editor/connection-editor.ui:27 +@@ -1566,7 +1680,8 @@ msgstr "می‌تواند به دلیلی محدودیت‌های سخت‌اف + msgid "Single Display" + msgstr "نمایشگر تکی" + +-#: panels/display/cc-display-panel.ui:108 panels/display/cc-display-panel.ui:310 ++#: panels/display/cc-display-panel.ui:108 ++#: panels/display/cc-display-panel.ui:310 + msgid "Join Displays" + msgstr "پیوند نمایشگرها" + +@@ -1588,8 +1703,8 @@ msgstr "نمایشگر اصلی" + + #: panels/display/cc-display-panel.ui:243 + msgid "" +-"Drag displays to match your physical display setup. Select a display to change " +-"its settings." ++"Drag displays to match your physical display setup. Select a display to " ++"change its settings." + msgstr "" + "نمایشگرها را برای تطبیق با وضعیت واقعی بکشید. برای تغییر تنظیمات یک نمایشگر، " + "برگزینیدش." +@@ -1685,11 +1800,11 @@ msgstr "تا فردا از کار بیفتد" + + #: panels/display/cc-night-light-page.ui:88 + msgid "" +-"Night light makes the screen color warmer. This can help to prevent eye strain " +-"and sleeplessness." ++"Night light makes the screen color warmer. This can help to prevent eye " ++"strain and sleeplessness." + msgstr "" +-"نور شب رنگ صفحه را گرم‌تر می‌کند. این کار به پیش‌گیری از آسیب چشمی و بی‌خوابی کمک " +-"می کند." ++"نور شب رنگ صفحه را گرم‌تر می‌کند. این کار به پیش‌گیری از آسیب چشمی و بی‌خوابی " ++"کمک می کند." + + #: panels/display/cc-night-light-page.ui:127 + msgid "Schedule" +@@ -1703,7 +1818,8 @@ msgstr "غروب تا طلوع" + msgid "Manual Schedule" + msgstr "زمان‌بندی دستی" + +-#: panels/display/cc-night-light-page.ui:148 panels/region/cc-format-preview.ui:40 ++#: panels/display/cc-night-light-page.ui:148 ++#: panels/region/cc-format-preview.ui:40 + msgid "Times" + msgstr "زمان‌ها" + +@@ -1757,8 +1873,8 @@ msgid "" + "redshift;color;sunset;sunrise;" + msgstr "" + "Panel;Projector;xrandr;Screen;Resolution;Refresh;Monitor;Night;Light;Blue;" +-"redshift;color;sunset;sunrise;تابلو;پروژکتور;صفحه;مانیتور;نمایشگر;تفکیک;شب;نور;" +-"آبی;رنگ;غروب;طلوع;" ++"redshift;color;sunset;sunrise;تابلو;پروژکتور;صفحه;مانیتور;نمایشگر;تفکیک;شب;" ++"نور;آبی;رنگ;غروب;طلوع;" + + #: panels/info-overview/cc-info-overview-panel.c:418 + #: panels/info-overview/cc-info-overview-panel.c:433 +@@ -1864,8 +1980,8 @@ msgid "" + "The device name is used to identify this device when it is viewed over the " + "network, or when pairing Bluetooth devices." + msgstr "" +-"نام دستگاه برای تشخیص این دستگاه هنگام دیده شدن روی شبکه یا جفت شدن افزاره‌های " +-"بلوتوثی استفاده می‌شود." ++"نام دستگاه برای تشخیص این دستگاه هنگام دیده شدن روی شبکه یا جفت شدن " ++"افزاره‌های بلوتوثی استفاده می‌شود." + + #: panels/info-overview/cc-info-overview-panel.ui:233 + msgid "_Rename" +@@ -1886,13 +2002,13 @@ msgstr "دیدن اطّلاعات دربارهٔ سامانه‌تان" + #. sure that you use the same "translation" for those keywords + #: panels/info-overview/gnome-info-overview-panel.desktop.in.in:23 + msgid "" +-"device;system;information;hostname;memory;processor;version;default;application;" +-"preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;" ++"device;system;information;hostname;memory;processor;version;default;" ++"application;preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;" + msgstr "" +-"device;system;information;hostname;memory;processor;version;default;application;" +-"preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;دستگاه;سیستم;" +-"سامانه;اطلاعات;نام دامنه;حافظه;پردازشگر;نسخه;پیش‌گزیده;برنامه;یدکی;ترجیح‌شده;سی‌دی;" +-"دی‌وی‌دی;یواس‌بی;صوت;ویدیو;دیسک;قابل حذف;رسانه;اجرای خودکار;" ++"device;system;information;hostname;memory;processor;version;default;" ++"application;preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;" ++"دستگاه;سیستم;سامانه;اطلاعات;نام دامنه;حافظه;پردازشگر;نسخه;پیش‌گزیده;برنامه;" ++"یدکی;ترجیح‌شده;سی‌دی;دی‌وی‌دی;یواس‌بی;صوت;ویدیو;دیسک;قابل حذف;رسانه;اجرای خودکار;" + + #: panels/keyboard/00-multimedia.xml.in:2 + msgid "Sound and Media" +@@ -2113,63 +2229,71 @@ msgstr "برداشتن" + msgid "Custom Shortcuts" + msgstr "میان‌برهای سفارشی" + +-#: panels/keyboard/cc-keyboard-panel.c:71 panels/keyboard/cc-keyboard-panel.ui:179 ++#: panels/keyboard/cc-keyboard-panel.c:71 ++#: panels/keyboard/cc-keyboard-panel.ui:179 + msgid "Alternate Characters Key" + msgstr "کلید نویسه‌های جایگزین" + + #: panels/keyboard/cc-keyboard-panel.c:72 + msgid "" +-"The alternate characters key can be used to enter additional characters. These " +-"are sometimes printed as a third-option on your keyboard." ++"The alternate characters key can be used to enter additional characters. " ++"These are sometimes printed as a third-option on your keyboard." + msgstr "" +-"کلید نویسهٔ جایگزین می‌تواند برای ورود نویسه‌های اضافی استفاده شود. گاهی به عنوان " +-"گزینهٔ سوم روی صفحه‌کلیدتان چاپ شده‌اند." ++"کلید نویسهٔ جایگزین می‌تواند برای ورود نویسه‌های اضافی استفاده شود. گاهی به " ++"عنوان گزینهٔ سوم روی صفحه‌کلیدتان چاپ شده‌اند." + +-#: panels/keyboard/cc-keyboard-panel.c:74 panels/keyboard/cc-keyboard-panel.c:92 ++#: panels/keyboard/cc-keyboard-panel.c:74 ++#: panels/keyboard/cc-keyboard-panel.c:92 + msgctxt "keyboard key" + msgid "Left Alt" + msgstr "دگرساز چپ" + +-#: panels/keyboard/cc-keyboard-panel.c:75 panels/keyboard/cc-keyboard-panel.c:93 ++#: panels/keyboard/cc-keyboard-panel.c:75 ++#: panels/keyboard/cc-keyboard-panel.c:93 + msgctxt "keyboard key" + msgid "Right Alt" + msgstr "دگرساز راست" + +-#: panels/keyboard/cc-keyboard-panel.c:76 panels/keyboard/cc-keyboard-panel.c:94 ++#: panels/keyboard/cc-keyboard-panel.c:76 ++#: panels/keyboard/cc-keyboard-panel.c:94 + msgctxt "keyboard key" + msgid "Left Super" + msgstr "سوپر چپ" + +-#: panels/keyboard/cc-keyboard-panel.c:77 panels/keyboard/cc-keyboard-panel.c:95 ++#: panels/keyboard/cc-keyboard-panel.c:77 ++#: panels/keyboard/cc-keyboard-panel.c:95 + msgctxt "keyboard key" + msgid "Right Super" + msgstr "سوپر راست" + +-#: panels/keyboard/cc-keyboard-panel.c:78 panels/keyboard/cc-keyboard-panel.c:96 ++#: panels/keyboard/cc-keyboard-panel.c:78 ++#: panels/keyboard/cc-keyboard-panel.c:96 + msgctxt "keyboard key" + msgid "Menu key" + msgstr "کلید فهرست" + +-#: panels/keyboard/cc-keyboard-panel.c:79 panels/keyboard/cc-keyboard-panel.c:97 ++#: panels/keyboard/cc-keyboard-panel.c:79 ++#: panels/keyboard/cc-keyboard-panel.c:97 + msgctxt "keyboard key" + msgid "Right Ctrl" + msgstr "مهار راست" + +-#: panels/keyboard/cc-keyboard-panel.c:87 panels/keyboard/cc-keyboard-panel.ui:204 ++#: panels/keyboard/cc-keyboard-panel.c:87 ++#: panels/keyboard/cc-keyboard-panel.ui:204 + msgid "Compose Key" + msgstr "کلید ایجاد" + + #: panels/keyboard/cc-keyboard-panel.c:88 + msgid "" +-"The compose key allows a wide variety of characters to be entered. To use it, " +-"press compose then a sequence of characters. For example, compose key followed " +-"by C and o will enter ©, a followed by ' " +-"will enter á." ++"The compose key allows a wide variety of characters to be entered. To use " ++"it, press compose then a sequence of characters. For example, compose key " ++"followed by C and o will enter ©, a followed by " ++"' will enter á." + msgstr "" +-"دکمهٔ ایجاد، امکان ورود طیف وسیعی از نویسه‌ها را می‌دهد. برای استفاده از آن، ایجاد " +-"و به دنبالش، دنباله‌ای از نویسه‌ها را بفشارید. برای مثال، کلید ایجاد به همراه " +-"C و o، نویسهٔ © و a به همراه '، نویسهٔ á را وارد می‌کند." ++"دکمهٔ ایجاد، امکان ورود طیف وسیعی از نویسه‌ها را می‌دهد. برای استفاده از آن، " ++"ایجاد و به دنبالش، دنباله‌ای از نویسه‌ها را بفشارید. برای مثال، کلید ایجاد به " ++"همراه C و o، نویسهٔ © و a به همراه '، " ++"نویسهٔ á را وارد می‌کند." + + #: panels/keyboard/cc-keyboard-panel.c:98 + msgctxt "keyboard key" +@@ -2238,7 +2362,8 @@ msgstr "بازنشانی تمام میان‌برها؟" + + #: panels/keyboard/cc-keyboard-shortcut-dialog.c:426 + msgid "" +-"Resetting the shortcuts may affect your custom shortcuts. This cannot be undone." ++"Resetting the shortcuts may affect your custom shortcuts. This cannot be " ++"undone." + msgstr "" + "ممکن است بازنشانی میان‌برها روی میان‌برهای شخصیتان اثر بگذارد. این کار قابل " + "بازگشت نیست." +@@ -2364,10 +2489,11 @@ msgstr "نمایش و تغییر میان‌برهای صفحه‌کلید و ت + + #. Translators: Search terms to find the Keyboard panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/keyboard/gnome-keyboard-panel.desktop.in.in:19 +-msgid "Shortcut;Workspace;Window;Resize;Zoom;Contrast;Input;Source;Lock;Volume;" ++msgid "" ++"Shortcut;Workspace;Window;Resize;Zoom;Contrast;Input;Source;Lock;Volume;" + msgstr "" +-"Shortcut;Workspace;Window;Resize;Zoom;Contrast;Input;Source;Lock;Volume;میانبر;" +-"میان‌بر;فضای کاری;پنجره;اندازه;بزرگ‌نمایی;تضاد;ورودی;منبع;قفل;صدا;" ++"Shortcut;Workspace;Window;Resize;Zoom;Contrast;Input;Source;Lock;Volume;" ++"میانبر;میان‌بر;فضای کاری;پنجره;اندازه;بزرگ‌نمایی;تضاد;ورودی;منبع;قفل;صدا;" + + #: panels/location/cc-location-panel.ui:31 + msgid "Location services turned off" +@@ -2382,16 +2508,16 @@ msgid "" + "Location services allow applications to know your location. Using Wi-Fi and " + "mobile broadband increases accuracy." + msgstr "" +-"خدمت‌های موقعیت‌یابی می‌گذارند برنامه‌ها موقعیتتان را بدانند. استفاده از Wi-Fi یا " +-"پهن‌باند همراه، دقّت را افزایش می‌دهد." ++"خدمت‌های موقعیت‌یابی می‌گذارند برنامه‌ها موقعیتتان را بدانند. استفاده از Wi-Fi " ++"یا پهن‌باند همراه، دقّت را افزایش می‌دهد." + + #: panels/location/cc-location-panel.ui:81 + msgid "" +-"Uses Mozilla Location Service: Privacy Policy" ++"Uses Mozilla Location Service: Privacy Policy" + msgstr "" +-"از خدمات مکانی موزیلا استفاده می‌کند: سیاست محرمانگی" ++"از خدمات مکانی موزیلا استفاده می‌کند: سیاست محرمانگی" + + #: panels/location/cc-location-panel.ui:93 + msgid "Allow the applications below to determine your location." +@@ -2410,7 +2536,8 @@ msgstr "محافظت از اطّلاعات موقعیتتان" + msgid "" + "Automatically locking the screen prevents others from accessing the computer " + "while you're away." +-msgstr "قفل خودکار صفحه از دسترسی دیگران به رایانه هنگام نبودنتان جلوگیری می‌کند." ++msgstr "" ++"قفل خودکار صفحه از دسترسی دیگران به رایانه هنگام نبودنتان جلوگیری می‌کند." + + #: panels/lock/cc-lock-panel.ui:44 + msgid "Blank Screen Delay" +@@ -2575,10 +2702,11 @@ msgstr "هیچ برنامه‌ای نمی‌تواند صدا ضبط کند." + #: panels/microphone/cc-microphone-panel.ui:75 + msgid "" + "Use of the microphone allows applications to record and listen to audio. " +-"Disabling the microphone may cause some applications to not function properly." ++"Disabling the microphone may cause some applications to not function " ++"properly." + msgstr "" +-"استفاده از میکروفون به برنامه‌ها اجازه می‌دهد که صدا را ضبط و به آن گوش کنند. از " +-"کار انداختن میکروفون ممکن است باعث کارکرد نادرست برخی برنامه‌ها شود." ++"استفاده از میکروفون به برنامه‌ها اجازه می‌دهد که صدا را ضبط و به آن گوش کنند. " ++"از کار انداختن میکروفون ممکن است باعث کارکرد نادرست برخی برنامه‌ها شود." + + #: panels/microphone/cc-microphone-panel.ui:85 + msgid "Allow the applications below to use your microphone." +@@ -2592,11 +2720,6 @@ msgstr "هیچ برنامه‌ای برای دسترسی به میکروفون + msgid "Protect your conversations" + msgstr "محافظت از گفت‌وگوهایتان" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "عمومی" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "دکمهٔ اصلی" +@@ -2696,15 +2819,16 @@ msgid "Mouse & Touchpad" + msgstr "موشی و صفحه‌لمسی" + + #: panels/mouse/gnome-mouse-panel.desktop.in.in:4 +-msgid "Change your mouse or touchpad sensitivity and select right or left-handed" ++msgid "" ++"Change your mouse or touchpad sensitivity and select right or left-handed" + msgstr "تغییر میزان حساسیت موشی یا صفحه‌لمسی و انتخاب راست‌دست یا چپ‌دست بودن" + + #. Translators: Search terms to find the Mouse and Touchpad panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/mouse/gnome-mouse-panel.desktop.in.in:19 + msgid "Trackpad;Pointer;Click;Tap;Double;Button;Trackball;Scroll;" + msgstr "" +-"Trackpad;Pointer;Click;Tap;Double;Button;Trackball;Scroll;صفحه‌جهت‌ده;نشانگر;کلیک;" +-"ضربه;دوبار;دکمه;صفحه ردیاب;لغزش;" ++"Trackpad;Pointer;Click;Tap;Double;Button;Trackball;Scroll;صفحه‌جهت‌ده;نشانگر;" ++"کلیک;ضربه;دوبار;دکمه;صفحه ردیاب;لغزش;" + + #: panels/network/cc-network-panel.c:661 panels/network/cc-wifi-panel.ui:307 + msgid "Oops, something has gone wrong. Please contact your software vendor." +@@ -2760,7 +2884,8 @@ msgid "Connected" + msgstr "متّصل" + + #: panels/network/cc-wifi-connection-row.ui:100 +-#: panels/network/net-device-ethernet.c:327 panels/network/network-bluetooth.ui:76 ++#: panels/network/net-device-ethernet.c:327 ++#: panels/network/network-bluetooth.ui:76 + #: panels/network/network-ethernet.ui:111 panels/network/network-mobile.ui:450 + #: panels/network/network-vpn.ui:77 + msgid "Options…" +@@ -2770,11 +2895,11 @@ msgstr "گزینه‌ها…" + #: panels/network/cc-wifi-hotspot-dialog.c:134 + #, c-format + msgid "" +-"Turning on the hotspot will disconnect from %s, and it will not be possible to " +-"access the internet through Wi-Fi." ++"Turning on the hotspot will disconnect from %s, and it will not be possible " ++"to access the internet through Wi-Fi." + msgstr "" +-"روشن کردن نقطهٔ داغ، موجب قطع شدن از %s شده و قادر به دسترسی به اینترنت از طریق " +-"وای‌فای نیستید." ++"روشن کردن نقطهٔ داغ، موجب قطع شدن از %s شده و قادر به دسترسی به اینترنت از " ++"طریق وای‌فای نیستید." + + #: panels/network/cc-wifi-hotspot-dialog.c:265 + msgid "Must have a minimum of 8 characters" +@@ -2786,9 +2911,9 @@ msgstr "روشن کردن نقطهٔ داغ بی‌سیم؟" + + #: panels/network/cc-wifi-hotspot-dialog.ui:19 + msgid "" +-"Wi-Fi hotspot allows others to share your internet connection, by creating a Wi-" +-"Fi network that they can connect to. To do this, you must have an internet " +-"connection through a source other than Wi-Fi." ++"Wi-Fi hotspot allows others to share your internet connection, by creating a " ++"Wi-Fi network that they can connect to. To do this, you must have an " ++"internet connection through a source other than Wi-Fi." + msgstr "" + "نقطهٔ داغ وای‌فای با ایجاد یک شبکهٔ وای‌فای، به دیگران اجازهٔ هم‌رسانی اتّصال " + "اینترنتتان را می‌دهد. برای این کار باید اتّصال اینترنتی از منبعی غیر از وای‌فای " +@@ -2801,7 +2926,8 @@ msgstr "نام شبکه" + #. Translators: This is a password needed for printing. + #: panels/network/cc-wifi-hotspot-dialog.ui:69 + #: panels/printers/authentication-dialog.ui:96 +-#: panels/printers/new-printer-dialog.ui:389 panels/printers/pp-jobs-dialog.ui:70 ++#: panels/printers/new-printer-dialog.ui:389 ++#: panels/printers/pp-jobs-dialog.ui:70 + #: panels/user-accounts/cc-add-user-dialog.ui:249 + msgid "Password" + msgstr "گذرواژه" +@@ -2904,13 +3030,13 @@ msgstr "پایدار" + + #: panels/network/connection-editor/ce-page.c:241 + msgid "" +-"The MAC address entered here will be used as hardware address for the network " +-"device this connection is activated on. This feature is known as MAC cloning or " +-"spoofing. Example: 00:11:22:33:44:55" ++"The MAC address entered here will be used as hardware address for the " ++"network device this connection is activated on. This feature is known as MAC " ++"cloning or spoofing. Example: 00:11:22:33:44:55" + msgstr "" +-"نشانی مک وارد شده در این‌جا به عنوان نشانی سخت‌افزاری برای افزارهٔ شبکه‌ای که این " +-"اتّصال رویش فعّال است استفاده خواهد شد. این ویژگی به نام MAC cloning یا spoofing " +-"شناخته می‌شود. مثال: 00:11:22:33:44:55" ++"نشانی مک وارد شده در این‌جا به عنوان نشانی سخت‌افزاری برای افزارهٔ شبکه‌ای که " ++"این اتّصال رویش فعّال است استفاده خواهد شد. این ویژگی به نام MAC cloning یا " ++"spoofing شناخته می‌شود. مثال: 00:11:22:33:44:55" + + #: panels/network/connection-editor/ce-page.c:399 + #, c-format +@@ -3019,32 +3145,36 @@ msgstr "عالی" + + #: panels/network/connection-editor/ce-page-details.c:410 + #: panels/network/connection-editor/details-page.ui:108 +-#: panels/network/net-device-ethernet.c:149 panels/network/net-device-mobile.c:447 ++#: panels/network/net-device-ethernet.c:149 ++#: panels/network/net-device-mobile.c:447 + msgid "IPv4 Address" + msgstr "نشانی IPv4" + + #: panels/network/connection-editor/ce-page-details.c:411 + #: panels/network/connection-editor/details-page.ui:126 +-#: panels/network/net-device-ethernet.c:150 panels/network/net-device-mobile.c:448 +-#: panels/network/network-mobile.ui:218 ++#: panels/network/net-device-ethernet.c:150 ++#: panels/network/net-device-mobile.c:448 panels/network/network-mobile.ui:218 + msgid "IPv6 Address" + msgstr "نشانی IPv6" + + #: panels/network/connection-editor/ce-page-details.c:414 + #: panels/network/connection-editor/ce-page-details.c:415 + #: panels/network/net-device-ethernet.c:152 +-#: panels/network/net-device-ethernet.c:154 panels/network/net-device-mobile.c:451 ++#: panels/network/net-device-ethernet.c:154 ++#: panels/network/net-device-mobile.c:451 + #: panels/network/net-device-mobile.c:452 panels/network/network-mobile.ui:201 + msgid "IP Address" + msgstr "نشانی IP" + + #: panels/network/connection-editor/ce-page-details.c:419 +-#: panels/network/net-device-ethernet.c:163 panels/network/net-device-mobile.c:456 ++#: panels/network/net-device-ethernet.c:163 ++#: panels/network/net-device-mobile.c:456 + msgid "DNS4" + msgstr "ساناد۴" + + #: panels/network/connection-editor/ce-page-details.c:420 +-#: panels/network/net-device-ethernet.c:164 panels/network/net-device-mobile.c:457 ++#: panels/network/net-device-ethernet.c:164 ++#: panels/network/net-device-mobile.c:457 + msgid "DNS6" + msgstr "ساناد۶" + +@@ -3055,7 +3185,8 @@ msgstr "ساناد۶" + #: panels/network/connection-editor/ip4-page.ui:211 + #: panels/network/connection-editor/ip6-page.ui:225 + #: panels/network/net-device-ethernet.c:166 +-#: panels/network/net-device-ethernet.c:168 panels/network/net-device-mobile.c:459 ++#: panels/network/net-device-ethernet.c:168 ++#: panels/network/net-device-mobile.c:459 + #: panels/network/net-device-mobile.c:460 panels/network/network-mobile.ui:253 + #: panels/network/network-mobile.ui:271 + msgid "DNS" +@@ -3158,7 +3289,8 @@ msgid "Supported Frequencies" + msgstr "بسامدهای پشتیبانی شده" + + #: panels/network/connection-editor/details-page.ui:180 +-#: panels/network/net-device-ethernet.c:160 panels/network/network-mobile.ui:235 ++#: panels/network/net-device-ethernet.c:160 ++#: panels/network/network-mobile.ui:235 + msgid "Default Route" + msgstr "بسامدهای پشتیبانی شده" + +@@ -3182,7 +3314,8 @@ msgstr "اتّصال _اندازه‌گیری‌شده: دارای محدویت + msgid "" + "Software updates and other large downloads will not be started automatically." + msgstr "" +-"به‌روز رسانی‌های نرم‌افزاری و دیگر بارگیری‌های بزرگ به صورت خودکار شروع نخواهند شد." ++"به‌روز رسانی‌های نرم‌افزاری و دیگر بارگیری‌های بزرگ به صورت خودکار شروع نخواهند " ++"شد." + + #: panels/network/connection-editor/ethernet-page.ui:25 + #: panels/network/connection-editor/vpn-page.ui:23 +@@ -3221,8 +3354,8 @@ msgid "Link-Local Only" + msgstr "فقط Link-Local" + + #: panels/network/connection-editor/ip4-page.ui:69 +-#: panels/network/connection-editor/ip6-page.ui:83 panels/network/net-proxy.c:71 +-#: panels/network/network-proxy.ui:118 ++#: panels/network/connection-editor/ip6-page.ui:83 ++#: panels/network/net-proxy.c:71 panels/network/network-proxy.ui:118 + msgid "Manual" + msgstr "دستی" + +@@ -3265,8 +3398,8 @@ msgstr "دروازه" + #: panels/network/connection-editor/ip4-page.ui:291 + #: panels/network/connection-editor/ip6-page.ui:42 + #: panels/network/connection-editor/ip6-page.ui:237 +-#: panels/network/connection-editor/ip6-page.ui:305 panels/network/net-proxy.c:73 +-#: panels/network/network-proxy.ui:107 ++#: panels/network/connection-editor/ip6-page.ui:305 ++#: panels/network/net-proxy.c:73 panels/network/network-proxy.ui:107 + #: panels/network/wireless-security/eap-method-peap.ui:33 + msgid "Automatic" + msgstr "خودکار" +@@ -3342,8 +3475,8 @@ msgstr "نمی‌توان اتصال وی‌پی‌ان را وارد کرد" + #: panels/network/connection-editor/vpn-helpers.c:141 + #, c-format + msgid "" +-"The file “%s” could not be read or does not contain recognized VPN connection " +-"information\n" ++"The file “%s” could not be read or does not contain recognized VPN " ++"connection information\n" + "\n" + "Error: %s." + msgstr "" +@@ -3408,8 +3541,8 @@ msgstr "واپایش شیوهٔ اتّصال به اینترنت" + #: panels/network/gnome-network-panel.desktop.in.in:19 + msgid "Network;IP;LAN;Proxy;WAN;Broadband;Modem;Bluetooth;vpn;DNS;" + msgstr "" +-"Network;IP;LAN;Proxy;WAN;Broadband;Modem;Bluetooth;vpn;DNS;شبکه;آی پی;لن;پیشکار;" +-"پروکسی;ون;پهن‌باند;مودم;بلوتوث;وی پی ان;دی ان اس;ساناد;" ++"Network;IP;LAN;Proxy;WAN;Broadband;Modem;Bluetooth;vpn;DNS;شبکه;آی پی;لن;" ++"پیشکار;پروکسی;ون;پهن‌باند;مودم;بلوتوث;وی پی ان;دی ان اس;ساناد;" + + #: panels/network/gnome-wifi-panel.desktop.in.in:4 + msgid "Control how you connect to Wi-Fi networks" +@@ -3419,8 +3552,8 @@ msgstr "واپایش شیوهٔ اتّصال به شبکه‌های وای‌ف + #: panels/network/gnome-wifi-panel.desktop.in.in:19 + msgid "Network;Wireless;Wi-Fi;Wifi;IP;LAN;Broadband;DNS;Hotspot;" + msgstr "" +-"Network;Wireless;Wi-Fi;Wifi;IP;LAN;Broadband;DNS;Hotspot;شبکه;بی سیم;وای فای;آی " +-"پی;لن;پروکسی;پهن‌باند;دی ان اس;ساناد;هات اسپات;" ++"Network;Wireless;Wi-Fi;Wifi;IP;LAN;Broadband;DNS;Hotspot;شبکه;بی سیم;وای فای;" ++"آی پی;لن;پروکسی;پهن‌باند;دی ان اس;ساناد;هات اسپات;" + + #: panels/network/net-device-ethernet.c:95 + msgid "never" +@@ -3443,8 +3576,8 @@ msgstr "آخرین استفاده" + #. * profile. It is also used to display ethernet in the + #. * device list. + #. +-#: panels/network/net-device-ethernet.c:261 panels/network/network-bluetooth.ui:38 +-#: panels/network/network-ethernet.ui:18 ++#: panels/network/net-device-ethernet.c:261 ++#: panels/network/network-bluetooth.ui:38 panels/network/network-ethernet.ui:18 + msgid "Wired" + msgstr "سیمی" + +@@ -3454,10 +3587,11 @@ msgstr "افزودن اتّصال جدید" + + #: panels/network/net-device-wifi.c:851 + msgid "" +-"Network details for the selected networks, including passwords and any custom " +-"configuration will be lost." ++"Network details for the selected networks, including passwords and any " ++"custom configuration will be lost." + msgstr "" +-"جزییات شبکه‌های گزیده، شامل گذرواژه‌ها و هر پیکربندی سفارشی‌ای از دست خواهند رفت." ++"جزییات شبکه‌های گزیده، شامل گذرواژه‌ها و هر پیکربندی سفارشی‌ای از دست خواهند " ++"رفت." + + #: panels/network/net-device-wifi.c:855 + msgid "_Forget" +@@ -3481,7 +3615,8 @@ msgstr "سیاست سامانه استفاده از نقطهٔ داغ را من + msgid "Wireless device does not support Hotspot mode" + msgstr "افزارهٔ بی‌سیم از حالت نقطهٔ داغ پشتیبانی نمی‌کند" + +-#: panels/network/net-proxy.c:69 panels/notifications/cc-notifications-panel.c:266 ++#: panels/network/net-proxy.c:69 ++#: panels/notifications/cc-notifications-panel.c:266 + #: panels/power/cc-power-panel.c:1133 panels/power/cc-power-panel.c:1144 + #: panels/universal-access/cc-ua-panel.c:328 + #: panels/universal-access/cc-ua-panel.c:603 +@@ -3501,7 +3636,8 @@ msgstr "خاموش" + + #. TRANSLATORS: this is when the use leaves the PAC textbox blank + #: panels/network/net-proxy.c:112 +-msgid "Web Proxy Autodiscovery is used when a Configuration URL is not provided." ++msgid "" ++"Web Proxy Autodiscovery is used when a Configuration URL is not provided." + msgstr "کشف خودکار پیشکار وب زمانی که URL فراهم نشده باشد استفاده می‌شود." + + #. TRANSLATORS: WPAD is bad: if you enable it on an untrusted +@@ -4070,9 +4206,9 @@ msgid "" + "\n" + "(You can password-protect your private key with openssl)" + msgstr "" +-"به‌نظر نمی‌رسد کلید خصوصی انتخاب شده با گذرواژه محافظت شده باشد. این امر ممکن است " +-"موجب به خطر افتادن اطلاعات حساس شما شود. لطفا یک کلید خصوصی محافظت شده با " +-"گذرواژه انتخاب کنید.\n" ++"به‌نظر نمی‌رسد کلید خصوصی انتخاب شده با گذرواژه محافظت شده باشد. این امر ممکن " ++"است موجب به خطر افتادن اطلاعات حساس شما شود. لطفا یک کلید خصوصی محافظت شده " ++"با گذرواژه انتخاب کنید.\n" + "\n" + "(می‌توانید با openssl روی کلیدتان گذرواژه بگذارید)" + +@@ -4190,7 +4326,8 @@ msgstr "گزینه wep-key فراهم نشده است" + #: panels/network/wireless-security/ws-wep-key.c:123 + #, c-format + msgid "invalid wep-key: key with a length of %zu must contain only hex-digits" +-msgstr "گزینه wep-key نامعتبر است: کلیدی با طول %zu تنها باید شامل hex-digit باشد" ++msgstr "" ++"گزینه wep-key نامعتبر است: کلیدی با طول %zu تنها باید شامل hex-digit باشد" + + #: panels/network/wireless-security/ws-wep-key.c:131 + #, c-format +@@ -4205,8 +4342,8 @@ msgid "" + "invalid wep-key: wrong key length %zu. A key must be either of length 5/13 " + "(ascii) or 10/26 (hex)" + msgstr "" +-"گزینه wep-key نامعتبر: طول کلید نامعتبر %zu. یک کلید یا باید طول 5/13 (ascii) " +-"یا 10/26 (hex) داشته باشد." ++"گزینه wep-key نامعتبر: طول کلید نامعتبر %zu. یک کلید یا باید طول 5/13 " ++"(ascii) یا 10/26 (hex) داشته باشد." + + #: panels/network/wireless-security/ws-wep-key.c:144 + msgid "invalid wep-key: passphrase must be non-empty" +@@ -4243,10 +4380,11 @@ msgstr "_فهرست WEP" + #: panels/network/wireless-security/ws-wpa-psk.c:77 + #, c-format + msgid "" +-"invalid wpa-psk: invalid key-length %zu. Must be [8,63] bytes or 64 hex digits" ++"invalid wpa-psk: invalid key-length %zu. Must be [8,63] bytes or 64 hex " ++"digits" + msgstr "" +-"گزینه wpa-psk نامعتبر: طول کلید نامعتبر %zu.باید یا [8,63] باید یا ۶۴ رقم hex " +-"باشد" ++"گزینه wpa-psk نامعتبر: طول کلید نامعتبر %zu.باید یا [8,63] باید یا ۶۴ رقم " ++"hex باشد" + + #: panels/network/wireless-security/ws-wpa-psk.c:86 + msgid "invalid wpa-psk: cannot interpret key with 64 bytes as hex" +@@ -4272,10 +4410,11 @@ msgstr "واشوهای ا_علان" + + #: panels/notifications/cc-app-notifications-dialog.ui:184 + msgid "" +-"Notifications will continue to appear in the notification list when popups are " +-"disabled." ++"Notifications will continue to appear in the notification list when popups " ++"are disabled." + msgstr "" +-"هنگام از کار افتادن واشوها، آگاهی‌ها به ظاهر شدن در فهرست آگاهی‌ها ادامه می‌دهند." ++"هنگام از کار افتادن واشوها، آگاهی‌ها به ظاهر شدن در فهرست آگاهی‌ها ادامه " ++"می‌دهند." + + #. Popups here refers to message tray notifications in the middle of the screen. + #: panels/notifications/cc-app-notifications-dialog.ui:249 +@@ -4361,8 +4500,8 @@ msgid "" + "Google;Facebook;Twitter;Yahoo;Web;Online;Chat;Calendar;Mail;Contact;ownCloud;" + "Kerberos;IMAP;SMTP;Pocket;ReadItLater;" + msgstr "" +-"گوگل;فیس بوک;تویتر;یاهو;وب;برخط;گپ;تقویم;پست‌الکترونیکی;آشنا;ownCloud;Kerberos;" +-"IMAP;SMTP;Pocket;ReadItLater;" ++"گوگل;فیس بوک;تویتر;یاهو;وب;برخط;گپ;تقویم;پست‌الکترونیکی;آشنا;ownCloud;" ++"Kerberos;IMAP;SMTP;Pocket;ReadItLater;" + + #. Translators: This is the button which allows undoing the removal of the printer. + #: panels/online-accounts/online-accounts.ui:38 panels/printers/printers.ui:61 +@@ -4723,7 +4862,8 @@ msgstr "دمای سخت‌افزار بالا: حالت کارایی موجود + msgid "Performance mode unavailable" + msgstr "حالت کارایی موجود نیست" + +-#: panels/power/cc-power-profile-row.c:87 panels/power/cc-power-profile-row.c:187 ++#: panels/power/cc-power-profile-row.c:87 ++#: panels/power/cc-power-profile-row.c:187 + msgid "High performance and power usage." + msgstr "استفاده از انرژی و کارایی بالا." + +@@ -4762,7 +4902,8 @@ msgid "" + "Energy;" + msgstr "" + "Power;Sleep;Suspend;Hibernate;Battery;Brightness;Dim;Blank;Monitor;DPMS;Idle;" +-"Energy;نیرو;انرژی;خواب;تعلیق;باتری;روشنایی;تاریکی;نمایشگر;مانیتور;مونیتور;صفحه;" ++"Energy;نیرو;انرژی;خواب;تعلیق;باتری;روشنایی;تاریکی;نمایشگر;مانیتور;مونیتور;" ++"صفحه;" + + #: panels/printers/authentication-dialog.ui:11 + msgid " " +@@ -4774,7 +4915,8 @@ msgstr "تصدیق هویت" + + #. Translators: This is a username on a print server. + #: panels/printers/authentication-dialog.ui:80 +-#: panels/printers/new-printer-dialog.ui:366 panels/printers/pp-jobs-dialog.ui:57 ++#: panels/printers/new-printer-dialog.ui:366 ++#: panels/printers/pp-jobs-dialog.ui:57 + msgid "Username" + msgstr "نام کاربری" + +@@ -4842,7 +4984,8 @@ msgid "Enter username and password to view printers on Print Server." + msgstr "برای دیدن چاپگرهای روی کارساز چاپ، نام‌کاربری و گذرواژه را وارد کنید." + + #. Translators: This is the title of the dialog. %s is the printer name. +-#: panels/printers/pp-details-dialog.c:74 panels/printers/pp-details-dialog.c:351 ++#: panels/printers/pp-details-dialog.c:74 ++#: panels/printers/pp-details-dialog.c:351 + #, c-format + msgid "%s Details" + msgstr "جزییات %s" +@@ -4857,9 +5000,10 @@ msgstr "انتخاب پروندهٔ PPD" + + #: panels/printers/pp-details-dialog.c:241 + msgid "" +-"PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *.PPD." +-"GZ)" +-msgstr "پرونده‌های تفسیری پست‌اسکریپت (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *.PPD.GZ)" ++"PostScript Printer Description files (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *." ++"PPD.GZ)" ++msgstr "" ++"پرونده‌های تفسیری پست‌اسکریپت (*.ppd, *.PPD, *.ppd.gz, *.PPD.gz, *.PPD.GZ)" + + #: panels/printers/pp-details-dialog.ui:68 panels/printers/printer-entry.ui:223 + msgid "Location" +@@ -5184,7 +5328,8 @@ msgstr "پیشرفته" + + #. Translators: Name of job which makes printer to print test page + #. Translators: This button triggers the printing of a test page. +-#: panels/printers/pp-options-dialog.c:857 panels/printers/pp-options-dialog.ui:18 ++#: panels/printers/pp-options-dialog.c:857 ++#: panels/printers/pp-options-dialog.ui:18 + msgid "Test Page" + msgstr "صفحهٔ آزمایشی" + +@@ -5312,7 +5457,8 @@ msgstr "برون‌خط" + + #. Translators: Someone has stopped the Printer + #. Translators: Printer's state (no jobs can be processed) +-#: panels/printers/pp-printer-entry.c:737 panels/printers/pp-printer-entry.c:880 ++#: panels/printers/pp-printer-entry.c:737 ++#: panels/printers/pp-printer-entry.c:880 + msgctxt "printer state" + msgid "Stopped" + msgstr "متوقف شده" +@@ -5496,7 +5642,8 @@ msgstr "زبان" + msgid "The language used for text in windows and web pages." + msgstr "زبان استفاده‌شده برای متن در پنجره‌ها و صفحه‌های وب." + +-#: panels/region/cc-region-panel.ui:85 panels/user-accounts/cc-user-panel.ui:406 ++#: panels/region/cc-region-panel.ui:85 ++#: panels/user-accounts/cc-user-panel.ui:406 + msgid "_Language" + msgstr "_زبان" + +@@ -5525,7 +5672,8 @@ msgid "Region & Language" + msgstr "ناحیه و زبان" + + #: panels/region/gnome-region-panel.desktop.in.in:4 +-msgid "Select your display language, formats, keyboard layouts and input sources" ++msgid "" ++"Select your display language, formats, keyboard layouts and input sources" + msgstr "زبان نمایش، قالب‌ها، چیدمان صفحه‌کلید و منابع ورودی خود را انتخاب کنید" + + #. Translators: Search terms to find the Region and Language panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +@@ -5679,8 +5827,8 @@ msgid "" + msgstr "" + "device;system;default;application;preferred;cd;dvd;usb;audio;video;disc;" + "removable;media;autorun;دستگاه;سامانه;سیستم;اطلاعات;حافظه;پردازشگر;نسخه;" +-"پیش‌گزیده;برنامه;یدکی;ترجیح‌شده;سی‌دی;دی‌وی‌دی;یواس‌بی;صوت;ویدئو;دیسک;قابل حذف;رسانه;" +-"اجرا خودکار;" ++"پیش‌گزیده;برنامه;یدکی;ترجیح‌شده;سی‌دی;دی‌وی‌دی;یواس‌بی;صوت;ویدئو;دیسک;قابل حذف;" ++"رسانه;اجرا خودکار;" + + #: panels/search/cc-search-locations-dialog.c:636 + msgid "Select Location" +@@ -5731,14 +5879,15 @@ msgstr "جابه‌جایی به پایین" + + #: panels/search/cc-search-panel.ui:31 + msgid "" +-"Control which search results are shown in the Activities Overview. The order of " +-"search results can also be changed by moving rows in the list." ++"Control which search results are shown in the Activities Overview. The order " ++"of search results can also be changed by moving rows in the list." + msgstr "" + "واپایش نتایج جست‌وجویی که در نمای کلی فعّالیت‌ها، نتیجه نشان داده می‌شوند. ترتیب " + "نتایج جست‌وجو نیز می‌تواند با جابه‌جایی ردیف‌ها در فهرست تغییر کند." + + #: panels/search/gnome-search-panel.desktop.in.in:4 +-msgid "Control which applications show search results in the Activities Overview" ++msgid "" ++"Control which applications show search results in the Activities Overview" + msgstr "واپایش برنامه‌های کاربردی‌ای که در نمای کلی فعّالیت‌ها، نتیجه نشان می‌دهند" + + #. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! +@@ -5785,8 +5934,8 @@ msgstr "گزینش یک شاخه" + #: panels/sharing/cc-sharing-panel.c:696 + #, c-format + msgid "" +-"File Sharing allows you to share your Public folder with others on your current " +-"network using: %s" ++"File Sharing allows you to share your Public folder with others on your " ++"current network using: %s" + msgstr "" + "هم‌رسانی پرونده، می‌گذارد شاخهٔ عمومیتان را با استفاده از این پیوند روی شبکهٔ " + "جاریتان با دیگران هم‌رسانی کنید: %s" +@@ -5795,8 +5944,8 @@ msgstr "" + #: panels/sharing/cc-sharing-panel.c:702 + #, c-format + msgid "" +-"When remote login is enabled, remote users can connect using the Secure Shell " +-"command:\n" ++"When remote login is enabled, remote users can connect using the Secure " ++"Shell command:\n" + "%s" + msgstr "" + "هنگام به کار افتادن ورود دوردست، کاربران دوردست می‌توانند با استفاده از این " +@@ -5807,11 +5956,11 @@ msgstr "" + #: panels/sharing/cc-sharing-panel.c:708 + #, c-format + msgid "" +-"Screen sharing allows remote users to view or control your screen by connecting " +-"to %s" ++"Screen sharing allows remote users to view or control your screen by " ++"connecting to %s" + msgstr "" +-"هم‌رسانی صفحه به کاربران دوردست اجازه می‌دهد تا صفحه‌نمایشتان را با وصل شدن به این " +-"پیوند واپایش کنند: %s" ++"هم‌رسانی صفحه به کاربران دوردست اجازه می‌دهد تا صفحه‌نمایشتان را با وصل شدن به " ++"این پیوند واپایش کنند: %s" + + #: panels/sharing/cc-sharing-panel.c:813 + msgid "Copy" +@@ -5846,7 +5995,8 @@ msgstr "ورود _دوردست" + msgid "Some services are disabled because of no network access." + msgstr "تعدادی از خدمت‌ها به‌دلیل در دسترس نبودن شبکه، از کار افتاده‌اند." + +-#: panels/sharing/cc-sharing-panel.ui:137 panels/sharing/cc-sharing-panel.ui:264 ++#: panels/sharing/cc-sharing-panel.ui:137 ++#: panels/sharing/cc-sharing-panel.ui:264 + msgid "File Sharing" + msgstr "هم‌رسانی پرونده" + +@@ -5854,11 +6004,13 @@ msgstr "هم‌رسانی پرونده" + msgid "_Require Password" + msgstr "گذرواژه _لازم است" + +-#: panels/sharing/cc-sharing-panel.ui:275 panels/sharing/cc-sharing-panel.ui:345 ++#: panels/sharing/cc-sharing-panel.ui:275 ++#: panels/sharing/cc-sharing-panel.ui:345 + msgid "Remote Login" + msgstr "ورود دوردست" + +-#: panels/sharing/cc-sharing-panel.ui:368 panels/sharing/cc-sharing-panel.ui:590 ++#: panels/sharing/cc-sharing-panel.ui:368 ++#: panels/sharing/cc-sharing-panel.ui:590 + msgid "Screen Sharing" + msgstr "هم‌رسانی صفحه‌نمایش" + +@@ -5886,7 +6038,8 @@ msgstr "اتصال‌های _جدید باید برای دسترسی اجازه + msgid "_Require a password" + msgstr "گذرواژه _لازم است" + +-#: panels/sharing/cc-sharing-panel.ui:601 panels/sharing/cc-sharing-panel.ui:695 ++#: panels/sharing/cc-sharing-panel.ui:601 ++#: panels/sharing/cc-sharing-panel.ui:695 + msgid "Media Sharing" + msgstr "هم‌رسانی رسانه" + +@@ -6024,10 +6177,11 @@ msgstr "تغییر بلندی صدا، ورودی‌ها، خروجی‌ها و + + #. Translators: Search terms to find the Sound panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/sound/gnome-sound-panel.desktop.in.in:20 +-msgid "Card;Microphone;Volume;Fade;Balance;Bluetooth;Headset;Audio;Output;Input;" ++msgid "" ++"Card;Microphone;Volume;Fade;Balance;Bluetooth;Headset;Audio;Output;Input;" + msgstr "" +-"Card;Microphone;Volume;Fade;Balance;Bluetooth;Headset;Audio;Output;Input;کارت;" +-"میکروفون;بلندی صدا;محو شدن;بالانس;بلوتوث;گوشی;صوت;صدا;ورودی;خروجی;" ++"Card;Microphone;Volume;Fade;Balance;Bluetooth;Headset;Audio;Output;Input;" ++"کارت;میکروفون;بلندی صدا;محو شدن;بالانس;بلوتوث;گوشی;صوت;صدا;ورودی;خروجی;" + + #: panels/thunderbolt/cc-bolt-device-dialog.c:94 + #: panels/thunderbolt/cc-bolt-device-entry.c:125 +@@ -6137,14 +6291,15 @@ msgid "Authorized" + msgstr "تصدیق هویت شده" + + #: panels/thunderbolt/cc-bolt-panel.c:175 +-msgid "The Thunderbolt subsystem (boltd) is not installed or not set up properly." ++msgid "" ++"The Thunderbolt subsystem (boltd) is not installed or not set up properly." + msgstr "زیرسامانهٔ تاندربولت (boltd) نصب یا به درستی پیکربندی نشده است." + + #: panels/thunderbolt/cc-bolt-panel.c:468 + msgid "" + "Thunderbolt could not be detected.\n" +-"Either the system lacks Thunderbolt support, it has been disabled in the BIOS " +-"or is set to an unsupported security level in the BIOS." ++"Either the system lacks Thunderbolt support, it has been disabled in the " ++"BIOS or is set to an unsupported security level in the BIOS." + msgstr "" + "تاندربولت تشخیص داده نشد.\n" + "یا سامانه فاقد پشتیبانی تاندربولت است، یا در بایوس از کار افتاده یا روی سطح " +@@ -6224,7 +6379,8 @@ msgid "Cursor Size" + msgstr "اندازهٔ نشانگر" + + #: panels/universal-access/cc-cursor-size-dialog.ui:29 +-msgid "Cursor size can be combined with zoom to make it easier to see the cursor." ++msgid "" ++"Cursor size can be combined with zoom to make it easier to see the cursor." + msgstr "" + "اندازهٔ نشانگر می‌تواند با بزرگنمایی ترکیب شده تا دیدن نشانگر را راحت‌تر کند." + +@@ -6737,16 +6893,17 @@ msgstr "ساده‌تر کردن دیدن، شنیدن، نوشتن، نشانه + #. Translators: Search terms to find the Accessibility panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/universal-access/gnome-universal-access-panel.desktop.in.in:19 + msgid "" +-"Keyboard;Mouse;a11y;Accessibility;Universal Access;Contrast;Cursor;Sound;Zoom;" +-"Screen;Reader;big;high;large;text;font;size;AccessX;Sticky;Keys;Slow;Bounce;" +-"Mouse;Double;click;Delay;Speed;Assist;Repeat;Blink;visual;hearing;audio;typing;" ++"Keyboard;Mouse;a11y;Accessibility;Universal Access;Contrast;Cursor;Sound;" ++"Zoom;Screen;Reader;big;high;large;text;font;size;AccessX;Sticky;Keys;Slow;" ++"Bounce;Mouse;Double;click;Delay;Speed;Assist;Repeat;Blink;visual;hearing;" ++"audio;typing;" + msgstr "" +-"Keyboard;Mouse;a11y;Accessibility;Universal Access;Contrast;Cursor;Sound;Zoom;" +-"Screen;Reader;big;high;large;text;font;size;AccessX;Sticky;Keys;Slow;Bounce;" +-"Mouse;Double;click;Delay;Speed;Assist;Repeat;Blink;visual;hearing;audio;typing;" +-"صفحه‌کلید;موشی;دسترسی‌پذیری;سایه روشن;نشانگر;صدا;بزرگ‌نمایی;صفحه‌نمایش خوان;متن;قلم;" +-"اندازه;کلیدهای چسبان;کلیدهای آرام;کلیدهای پرشی;کلیدهای موشی;چشمک;سرعت;بینایی;" +-"شنوایی;صدا;تایپ;نوشتن;" ++"Keyboard;Mouse;a11y;Accessibility;Universal Access;Contrast;Cursor;Sound;" ++"Zoom;Screen;Reader;big;high;large;text;font;size;AccessX;Sticky;Keys;Slow;" ++"Bounce;Mouse;Double;click;Delay;Speed;Assist;Repeat;Blink;visual;hearing;" ++"audio;typing;صفحه‌کلید;موشی;دسترسی‌پذیری;سایه روشن;نشانگر;صدا;بزرگ‌نمایی;" ++"صفحه‌نمایش خوان;متن;قلم;اندازه;کلیدهای چسبان;کلیدهای آرام;کلیدهای پرشی;" ++"کلیدهای موشی;چشمک;سرعت;بینایی;شنوایی;صدا;تایپ;نوشتن;" + + #: panels/usage/cc-usage-panel.c:154 + msgid "Empty all items from Trash?" +@@ -6779,12 +6936,12 @@ msgstr "تاریخچهٔ پرونده" + #: panels/usage/cc-usage-panel.ui:41 + msgid "" + "File history keeps a record of files that you have used. This information is " +-"shared between applications, and makes it easier to find files that you might " +-"want to use." ++"shared between applications, and makes it easier to find files that you " ++"might want to use." + msgstr "" +-"تاریخچهٔ پرونده، گزارشی از پرونده‌هایی که استفاده کرده‌اید نگه می‌دارد. این اطّلاعات " +-"بین برنامه‌ها هم‌رسانی شده و یافتن پرونده‌هایی که ممکن است بخواهید استفاده کنید را " +-"آسان‌تر می‌کند." ++"تاریخچهٔ پرونده، گزارشی از پرونده‌هایی که استفاده کرده‌اید نگه می‌دارد. این " ++"اطّلاعات بین برنامه‌ها هم‌رسانی شده و یافتن پرونده‌هایی که ممکن است بخواهید " ++"استفاده کنید را آسان‌تر می‌کند." + + #: panels/usage/cc-usage-panel.ui:56 + msgid "File H_istory" +@@ -7010,9 +7167,9 @@ msgstr "_تأیید" + #: panels/user-accounts/cc-add-user-dialog.ui:485 + #: panels/user-accounts/cc-add-user-dialog.ui:692 + msgid "" +-"Enterprise login allows an existing centrally managed user account to be used " +-"on this device. You can also use this account to access company resources on " +-"the internet." ++"Enterprise login allows an existing centrally managed user account to be " ++"used on this device. You can also use this account to access company " ++"resources on the internet." + msgstr "" + "ورود تجاری می‌گذارد حساب کاربری مدیریت شدهٔ متمرکزی در این دستگاه استفاده شود. " + "همچنین از این حساب می‌توان برای دسترسی به منابع شرکت در اینترنت استفاده کرد." +@@ -7090,8 +7247,8 @@ msgid "" + "Fingerprint login allows you to unlock and log into your computer with your " + "finger" + msgstr "" +-"ورود با اثر انگشت می‌گذارد با اثر انگشتتان، رایانه را قفل‌گشایی کرده و به آن وارد " +-"شوید" ++"ورود با اثر انگشت می‌گذارد با اثر انگشتتان، رایانه را قفل‌گشایی کرده و به آن " ++"وارد شوید" + + #: panels/user-accounts/cc-fingerprint-dialog.ui:352 + msgid "_Delete Fingerprints" +@@ -7225,7 +7382,8 @@ msgstr "شکست در توقّف ثبت: %s" + + #: panels/user-accounts/cc-fingerprint-dialog.c:974 + msgid "" +-"Repeatedly lift and place your finger on the reader to enroll your fingerprint" ++"Repeatedly lift and place your finger on the reader to enroll your " ++"fingerprint" + msgstr "برایثبت انگشتتان، چند بار بلندش کرده و روی حسگر بگذارید" + + #. TRANSLATORS: This is the label for the button to enroll a new finger +@@ -7409,7 +7567,8 @@ msgid "" + "Deleting a user while they are logged in can leave the system in an " + "inconsistent state." + msgstr "" +-"حذف یک کاربر در حالی که وارد بودن ممکن است سامانه را در حالتی متناقض قرار دهد." ++"حذف یک کاربر در حالی که وارد بودن ممکن است سامانه را در حالتی متناقض قرار " ++"دهد." + + #: panels/user-accounts/cc-user-panel.c:624 + #, c-format +@@ -7534,11 +7693,11 @@ msgstr "_مدیر" + + #: panels/user-accounts/cc-user-panel.ui:301 + msgid "" +-"Administrators can add and remove other users, and can change settings for all " +-"users." ++"Administrators can add and remove other users, and can change settings for " ++"all users." + msgstr "" +-"مدیران می‌توانند دیگر کاربران را افزوده، برداشته و تنظیمات همهٔ کاربران را تغییر " +-"دهند." ++"مدیران می‌توانند دیگر کاربران را افزوده، برداشته و تنظیمات همهٔ کاربران را " ++"تغییر دهند." + + #: panels/user-accounts/cc-user-panel.ui:333 + msgid "_Parental Controls" +@@ -7589,8 +7748,8 @@ msgstr "افزودن یا برداشتنن کاربرها و تعویض گذرو + #: panels/user-accounts/data/gnome-user-accounts-panel.desktop.in.in:20 + msgid "Login;Name;Fingerprint;Avatar;Logo;Face;Password;" + msgstr "" +-"Login;Name;Fingerprint;Avatar;Logo;Face;Password;نام ورود;نام;اثرانگشت;آواتار;" +-"نشان;تصویرصورت;گذرواژه;" ++"Login;Name;Fingerprint;Avatar;Logo;Face;Password;نام ورود;نام;اثرانگشت;" ++"آواتار;نشان;تصویرصورت;گذرواژه;" + + #. Translators: This button enrolls the computer in the domain in order to use enterprise logins. + #: panels/user-accounts/data/join-dialog.ui:39 +@@ -7700,11 +7859,11 @@ msgstr "سعی کنید از تکرار یک نویسه خودداری کنید. + #: panels/user-accounts/pw-utils.c:124 + msgctxt "Password hint" + msgid "" +-"Try to avoid repeating the same type of character: you need to mix up letters, " +-"numbers and punctuation." ++"Try to avoid repeating the same type of character: you need to mix up " ++"letters, numbers and punctuation." + msgstr "" +-"سعی کنید از تکرار یک نوع نویسه خودداری کنید: شما باید تلفیقی از حروف، اعداد و " +-"نقطه‌گذاری‌ها را بکار ببرید." ++"سعی کنید از تکرار یک نوع نویسه خودداری کنید: شما باید تلفیقی از حروف، اعداد " ++"و نقطه‌گذاری‌ها را بکار ببرید." + + #: panels/user-accounts/pw-utils.c:126 + msgctxt "Password hint" +@@ -7714,7 +7873,8 @@ msgstr "سعی کنید از رشته‌های متوالی مثل ۱۲۳۴ یا + #: panels/user-accounts/pw-utils.c:128 + msgctxt "Password hint" + msgid "" +-"Password needs to be longer. Try to add more letters, numbers and punctuation." ++"Password needs to be longer. Try to add more letters, numbers and " ++"punctuation." + msgstr "" + "گذرواژه‌ها باید بلندتر باشند. تلاش کنید حروف، اعداد و علائم بیش‌تری بیفزایید." + +@@ -7780,11 +7940,11 @@ msgstr "خطای ناشناخته" + + #: panels/user-accounts/user-utils.c:432 + msgid "" +-"The username should usually only consist of lower case letters from a-z, digits " +-"and the following characters: - _" ++"The username should usually only consist of lower case letters from a-z, " ++"digits and the following characters: - _" + msgstr "" +-"نام کاربری تنها باید شامل حرف کوچک در بازهٔ a-z، رقم‌ها و نویسه‌های مقابل باشد: . " +-"- _" ++"نام کاربری تنها باید شامل حرف کوچک در بازهٔ a-z، رقم‌ها و نویسه‌های مقابل " ++"باشد: . - _" + + #: panels/user-accounts/user-utils.c:436 + msgid "Sorry, that user name isn’t available. Please try another." +@@ -7817,13 +7977,14 @@ msgid "" + "To edit a shortcut, choose the “Send Keystroke” action, press the keyboard " + "shortcut button and hold down the new keys or press Backspace to clear." + msgstr "" +-"برای ویرایش یک میان‌بر، کنش «ارسال ضربهٔ کلید» را انتخاب کنید، دکمهٔ کلید میان‌بر " +-"را فشار دهید و کلیدهای جدید را بگیرید یا اینکه کلید پس‌بر را برای پاک‌سازی فشار " +-"دهید." ++"برای ویرایش یک میان‌بر، کنش «ارسال ضربهٔ کلید» را انتخاب کنید، دکمهٔ کلید " ++"میان‌بر را فشار دهید و کلیدهای جدید را بگیرید یا اینکه کلید پس‌بر را برای " ++"پاک‌سازی فشار دهید." + + #: panels/wacom/calibrator/calibrator.ui:61 + msgid "" +-"Please tap the target markers as they appear on screen to calibrate the tablet." ++"Please tap the target markers as they appear on screen to calibrate the " ++"tablet." + msgstr "به محض ظاهر شدن نشانه‌ها روی نمایشگر، رویشان زده تا رایانک واسنجی شود." + + #: panels/wacom/calibrator/calibrator.ui:78 +@@ -8079,11 +8240,12 @@ msgstr "هشدار: نگارش در حال توسعه" + + #: shell/cc-window.ui:319 + msgid "" +-"This version of Settings should only be used for development purposes. You may " +-"experience incorrect system behavior, data loss, and other unexpected issues. " ++"This version of Settings should only be used for development purposes. You " ++"may experience incorrect system behavior, data loss, and other unexpected " ++"issues. " + msgstr "" +-"این نگارش از تنظیمات باید فقط برای مقاصد توسعه استفاده شود. ممکن است با رفتار " +-"نادرست سامانه، از دست رفتن داده یا دیگر مشکلات غیرمنتظره برخورد کنید. " ++"این نگارش از تنظیمات باید فقط برای مقاصد توسعه استفاده شود. ممکن است با " ++"رفتار نادرست سامانه، از دست رفتن داده یا دیگر مشکلات غیرمنتظره برخورد کنید. " + + #: shell/cc-window.ui:330 + msgid "Help" +@@ -8141,7 +8303,8 @@ msgid "Show warning when running a development build of Settings" + msgstr "نمایش هشدار هنگام اجرای یک ساخت در حال توسعه از تنظیمات" + + #: shell/org.gnome.ControlCenter.gschema.xml:14 +-msgid "Whether Settings should show a warning when running a development build." ++msgid "" ++"Whether Settings should show a warning when running a development build." + msgstr "تنظیمات آب‌وهوا باید هنگام اجرای یک ساخت در حال توسعه، هشداری نشان دهد." + + #. translators: +@@ -8198,17 +8361,18 @@ msgstr "صداهای سامانه" + #~ msgid "" + #~ "System Monitor can help you find out what applications are using the " + #~ "processor or the memory of your computer, can manage the running " +-#~ "applications, force stop processes not responding, and change the state or " +-#~ "priority of existing processes." ++#~ "applications, force stop processes not responding, and change the state " ++#~ "or priority of existing processes." + #~ msgstr "" +-#~ "پایشگر سامانه این امکان را می‌دهد که بفهمید چه برنامه‌هایی در حال استفاده از " +-#~ "پردازشگر یا حافظهٔ رایانه‌تانند، بتوانید برنامه‌های درحال اجرا را مدیریت کرده، " +-#~ "فرایندهای ناپاسخگو را مجبور به توقف کنید و الویت یا وضعیت فرایندهای موجود را " +-#~ "تغییر دهید." ++#~ "پایشگر سامانه این امکان را می‌دهد که بفهمید چه برنامه‌هایی در حال استفاده " ++#~ "از پردازشگر یا حافظهٔ رایانه‌تانند، بتوانید برنامه‌های درحال اجرا را مدیریت " ++#~ "کرده، فرایندهای ناپاسخگو را مجبور به توقف کنید و الویت یا وضعیت فرایندهای " ++#~ "موجود را تغییر دهید." + + #~ msgid "" +-#~ "The resource graphs feature shows you a quick overview of what is going on " +-#~ "with your computer displaying recent network, memory and processor usage." ++#~ "The resource graphs feature shows you a quick overview of what is going " ++#~ "on with your computer displaying recent network, memory and processor " ++#~ "usage." + #~ msgstr "" + #~ "امکان نمایش نمودار منابع‌، نمایی کلی از آن‌چه روی رایانه‌تان رخ می‌دهد را با " + #~ "نمایش میزان استفاده از شبکه، حافظه و پردازشگر، به شما می‌دهد." +@@ -8427,11 +8591,11 @@ msgstr "صداهای سامانه" + #~ msgstr "مقدار _نایس:" + + #~ msgid "" +-#~ "Note: The priority of a process is given by its nice value. " +-#~ "A lower nice value corresponds to a higher priority." ++#~ "Note: The priority of a process is given by its nice " ++#~ "value. A lower nice value corresponds to a higher priority." + #~ msgstr "" +-#~ "نکته: اولویت یک فرایند با مقدار نایس آن تعیین می‌شود. هرچه " +-#~ "میزان نایس پایین‌تر باشد، الویت بیشتری دارد." ++#~ "نکته: اولویت یک فرایند با مقدار نایس آن تعیین می‌شود. " ++#~ "هرچه میزان نایس پایین‌تر باشد، الویت بیشتری دارد." + + #~ msgid "A simple process and system monitor." + #~ msgstr "یک پایشگر‌ سادهٔ فرایند و شبکه." +@@ -8563,7 +8727,8 @@ msgstr "صداهای سامانه" + #~ msgid "_Files opened by process “%s” (PID %u):" + #~ msgstr "_پرونده‌های گشوده با فرایند «%s» (شناسه %Iu):" + +-#~ msgid "Main window size and position in the form (width, height, xpos, ypos)" ++#~ msgid "" ++#~ "Main window size and position in the form (width, height, xpos, ypos)" + #~ msgstr "اندازه و مکان پنجرهٔ اصلی در شکل (width, height, xpos, ypos)" + + #~ msgid "Main Window should open maximized" +@@ -8576,9 +8741,9 @@ msgstr "صداهای سامانه" + #~ msgstr "حالت سولاریس برای درصد پردازنده" + + #~ msgid "" +-#~ "If TRUE, system-monitor operates in “Solaris mode” where a task’s CPU usage " +-#~ "is divided by the total number of CPUs. Otherwise, it operates in “Irix " +-#~ "mode”." ++#~ "If TRUE, system-monitor operates in “Solaris mode” where a task’s CPU " ++#~ "usage is divided by the total number of CPUs. Otherwise, it operates in " ++#~ "“Irix mode”." + #~ msgstr "" + #~ "اگر درست باشد، پایشگر سامانه در «حالت سولاریس» اجرا می‌شود که در آن مصرف " + #~ "پردازندهٔ یک تکلیف، بر تعداد کل پردازنده‌ها تقسیم می‌شود. در غیر این‌صورت در " +@@ -8600,13 +8765,13 @@ msgstr "صداهای سامانه" + #~ msgstr "این که باید اطّلاعات تمام سامانه پرونده‌ها نشان داده شود یا نه" + + #~ msgid "" +-#~ "Whether to display information about all file systems (including types like " +-#~ "“autofs” and “procfs”). Useful for getting a list of all currently mounted " +-#~ "file systems." ++#~ "Whether to display information about all file systems (including types " ++#~ "like “autofs” and “procfs”). Useful for getting a list of all currently " ++#~ "mounted file systems." + #~ msgstr "" +-#~ "این که اطّلاعات تمام سامانه پرونده‌ها (از جمله گونه‌هایی چون autofs و procfs) " +-#~ "نشان داده شود یا نه . مفید برای گرفتن فهرستی از تمام سامانه پرونده‌های " +-#~ "سوار‌شدهٔ جاری." ++#~ "این که اطّلاعات تمام سامانه پرونده‌ها (از جمله گونه‌هایی چون autofs و " ++#~ "procfs) نشان داده شود یا نه . مفید برای گرفتن فهرستی از تمام سامانه " ++#~ "پرونده‌های سوار‌شدهٔ جاری." + + #~ msgid "Time in milliseconds between updates of the devices list" + #~ msgstr "زمان بین به‌روزرسانی‌های فهرست افزاره‌ها بر حسب میلی‌ثانیه" +@@ -8639,8 +8804,8 @@ msgstr "صداهای سامانه" + #~ msgstr "نمایش مجموع شبکه بر حسب بیت" + + #~ msgid "" +-#~ "If TRUE, system-monitor shows the CPU chart as a stacked area chart instead " +-#~ "of a line chart." ++#~ "If TRUE, system-monitor shows the CPU chart as a stacked area chart " ++#~ "instead of a line chart." + #~ msgstr "" + #~ "اگر درست باشد، پایشگر سامانه نمودار پردازنده را به‌جای نمودار خطی، به شکل " + #~ "نمودار پشته‌ای نمایش می‌دهد." +@@ -8944,8 +9109,8 @@ msgstr "صداهای سامانه" + #~ msgstr[1] "_کشتن فرایندها" + + #~ msgid "" +-#~ "Ending a process may destroy data, break the session or introduce a security " +-#~ "risk. Only unresponsive processes should be ended." ++#~ "Ending a process may destroy data, break the session or introduce a " ++#~ "security risk. Only unresponsive processes should be ended." + #~ msgstr "" + #~ "پایام یک فرایند می‌تواند باعث از بین رفتن داده، خرابی نشست، یا ایجاد خطری " + #~ "امنیتی شود. تنها فرایند‌های ناپاسخگو باید پایان یابند." +@@ -8972,8 +9137,8 @@ msgstr "صداهای سامانه" + #~ "The priority of a process is given by its nice value. A lower nice value " + #~ "corresponds to a higher priority." + #~ msgstr "" +-#~ "اولویت یک فرایند با مقدار نایس آن تعیین می‌شود. هرچه میزان نایس پایین‌تر باشد، " +-#~ "الویت بیشتری دارد." ++#~ "اولویت یک فرایند با مقدار نایس آن تعیین می‌شود. هرچه میزان نایس پایین‌تر " ++#~ "باشد، الویت بیشتری دارد." + + #~ msgid "N/A" + #~ msgstr "نامعلوم" +@@ -9187,15 +9352,15 @@ msgstr "صداهای سامانه" + #~ msgstr "مکان Y پنجره اصلی" + + #~ msgid "" +-#~ "Determines which processes to show by default. 0 is All, 1 is user, and 2 is " +-#~ "active" ++#~ "Determines which processes to show by default. 0 is All, 1 is user, and 2 " ++#~ "is active" + #~ msgstr "" + #~ "مشخص می‌کند که چه فراروند‌هایی به طور پیش‌فرض نشان داده شوند. ۰ برای همه، ۱ " + #~ "برای کاربر، و ۲ برای فعال" + + #~ msgid "" +-#~ "0 for the System Info, 1 for the processes list, 2 for the resources and 3 " +-#~ "for the disks list" ++#~ "0 for the System Info, 1 for the processes list, 2 for the resources and " ++#~ "3 for the disks list" + #~ msgstr "" + #~ "۰ برای اطلاعات سیستم، ۱ برای فهرست فراروند‌ها، ۲ برای منابع و ۳ برای فهرست " + #~ "دیسک‌ها" +diff --git a/po/fi.po b/po/fi.po +index a53423121..a21bc42c9 100644 +--- a/po/fi.po ++++ b/po/fi.po +@@ -21,8 +21,26 @@ + # Lasse Liehu , 2013, 2014. + # Jiri Grönroos , 2012, 2013, 2014, 2015, 2016, 2017. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# fi.po.multitasking (gnome-control-center) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-08 16:18+0000\n" ++"PO-Revision-Date: 2021-09-14 13:17+0300\n" ++"Last-Translator: Jiri Grönroos \n" ++"Language-Team: suomi \n" ++"Language: fi\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 3.0\n" ++"X-POT-Import-Date: 2012-03-07 10:37:43+0000\n" ++"X-Project-Style: gnome\n" ++"#-#-#-#-# fi.po (gnome-control-center) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -39,6 +57,94 @@ msgstr "" + "X-POT-Import-Date: 2012-03-07 10:37:43+0000\n" + "X-Project-Style: gnome\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Yleiset" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Aktivointikulma" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Kosketa vasenta yläkulmaa avataksesi Toiminnot-yleisnäkymän." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "Aktiiviset _näytön reunat" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Vedä ikkunat näytön yläreunaa, vasenta reunaa ja oikeaa reunaa vasten " ++"muuttaaksesi ikkunoiden kokoa." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Työtilat" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Dynaamiset työtilat" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Poista automaattisesti tyhjät työtilat." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Muuttumaton määrä työtiloja" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Määritä muuttumattomien työtilojen määrä." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Työtilojen määrä" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Useampi näyttö" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Työtilat vain _ensisijaisella näytöllä" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Työtilat _kaikilla näytöillä" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Sovellusten välillä vaihtaminen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Sisällytä sovellukset k_aikista työtiloista" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Sisällytä sovellukset _vain nykyisestä työtilasta" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Moniajo" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Hallinnoi tuottavuuden ja moniajon asetuksia" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"Multitasking;Multitask;Productivity;Customize;Desktop;moniajo;tuottavuus;" ++"mukautus;samanaikainen;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Järjestelmäväylä" +@@ -2645,11 +2751,6 @@ msgstr "Mikään sovellus ei ole pyytänyt mikrofonin käyttöoikeutta" + msgid "Protect your conversations" + msgstr "Suojaa keskustelusi" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Yleiset" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Ensisijainen painike" +diff --git a/po/fr.po b/po/fr.po +index 0a30ea1be..8bf6e9a63 100644 +--- a/po/fr.po ++++ b/po/fr.po +@@ -1,3 +1,40 @@ ++# #-#-#-#-# fr.po.multitasking (gnome-control-center HEAD) #-#-#-#-# ++# French translation of gnome-control-center. ++# Copyright (C) 1998-2020 Free Software Foundation, Inc. ++# This file is under the same license as the gnome-control-center package. ++# ++# Vincent Renardias , 1998-1999. ++# Fabrice Bellet , 1999. ++# Thibaut Cousin , 1999. ++# Joaquim Fellmann , 2000. ++# Christophe Merlet , 2000-2006. ++# Christophe Fergeau , 2002. ++# Mathieu Gauthier-Pilote , 2002. ++# Sebastien Oustric , 2002. ++# Simon Manlay , 2005. ++# Vincent Untz , 2005. ++# Robert-André Mauchin , 2006-2008. ++# Jonathan Ernst , 2006-2007. ++# Benoît Dejean , 2006. ++# Samuel Mutel , 2006. ++# Damien Durand , 2006. ++# Marc Lorber , 2006. ++# Stéphane Raimbault , 2007-2008. ++# Christophe Benz , 2007. ++# Bruno Brouard , 2008-2012. ++# Laurent Coudeur , 2009, 2010. ++# Gérard Baylard , 2011. ++# Grawok , 2012. ++# Alain Lojewski , 2011-2018. ++# Julien Hardelin , 2013. ++# Guillaume Bernard , 2015-2021. ++# Erwan Georget , 2015. ++# Claude Paroz , 2007-2020. ++# Thibault Martin , 2020-2021. ++# Charles Monzat , 2016-2021. ++# Alexandre Franke , 2013-2021. ++# ++# #-#-#-#-# fr.po (gnome-control-center HEAD) #-#-#-#-# + # French translation of gnome-control-center. + # Copyright (C) 1998-2020 Free Software Foundation, Inc. + # This file is under the same license as the gnome-control-center package. +@@ -33,8 +70,24 @@ + # Thibault Martin , 2020-2021. + # Charles Monzat , 2016-2021. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# fr.po.multitasking (gnome-control-center HEAD) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center HEAD\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-13 00:22+0000\n" ++"PO-Revision-Date: 2021-09-13 17:51+0200\n" ++"Last-Translator: Alexandre Franke \n" ++"Language-Team: GNOME French Team \n" ++"Language: fr\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n > 1);\n" ++"X-Generator: Gtranslator 40.0\n" ++"#-#-#-#-# fr.po (gnome-control-center HEAD) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center HEAD\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -49,6 +102,93 @@ msgstr "" + "Plural-Forms: nplurals=2; plural=(n > 1);\n" + "X-Generator: Gtranslator 3.38.0\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Général" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Coin actif" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "" ++"Toucher le coin supérieur gauche pour ouvrir la vue d’ensemble des activités" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "Bords de l’écran _actifs" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Pousser les fenêtres contre les bords haut, gauche et droite pour les " ++"redimensionner." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Espace de travail" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "Espaces de travail _dynamiques" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Supprimer automatiquement les espaces de travail vides" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "Nombre d’espaces de travail _fixe" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Indiquez un nombre d’espaces de travail permanents" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Nombre d’espaces de travail" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Multi-écran" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Espaces de travail sur l’écran _principal uniquement" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Espaces de travail sur _tous les écrans" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Bascule entre les applications" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Inclure les applications de tous les _espaces de travail" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Inclure les applications de l’espace de travail a_ctuel uniquement" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Multi-tâches" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Gérer les préférences de productivité et du multi-tâches" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "Multi-tâches;productivité;personnalisation;bureau;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Bus système" +@@ -2233,8 +2373,8 @@ msgid "" + "' will enter á." + msgstr "" + "La touche de composition permet de saisir une grande variété de caractères. " +-"Pour l’utiliser, maintenez-la enfoncée et appuyez sur C et o pour " +-"saisir ©, ou a et pour saisir á." ++"Pour l’utiliser, maintenez-la enfoncée et appuyez sur C et o " ++"pour saisir ©, ou a et pour saisir á." + + #: panels/keyboard/cc-keyboard-panel.c:98 + msgctxt "keyboard key" +@@ -2682,11 +2822,6 @@ msgstr "Aucune application n’a demandé l’accès au micro" + msgid "Protect your conversations" + msgstr "Protégez vos conversations" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Général" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Bouton principal" +@@ -5629,8 +5764,7 @@ msgstr "Langue" + + #: panels/region/cc-region-panel.ui:45 + msgid "The language used for text in windows and web pages." +-msgstr "" +-"La langue utilisée pour le texte des fenêtres et des pages Web." ++msgstr "La langue utilisée pour le texte des fenêtres et des pages Web." + + #: panels/region/cc-region-panel.ui:85 + #: panels/user-accounts/cc-user-panel.ui:406 +diff --git a/po/gl.po b/po/gl.po +index 82e71b775..cafecd49d 100644 +--- a/po/gl.po ++++ b/po/gl.po +@@ -1,3 +1,4 @@ ++# #-#-#-#-# gl.po.multitasking (gnome-control-center-master-po-gl-72290.merged) #-#-#-#-# + # Galician translation of GNOME Control Center + # (C) 2002 Free Software Foundation, Inc. + # Proxecto Trasno - Adaptación do software libre á lingua galega: Se desexas +@@ -14,11 +15,54 @@ + # Fran Diéguez , 2009, 2010, 2011, 2012. + # Leandro Regueiro , 2011, 2012. + # Fran Dieguez , 2012-2021. ++# ++# #-#-#-#-# gl.po (gnome-control-center-master-po-gl-72290.merged) #-#-#-#-# ++# Galician translation of GNOME Control Center ++# (C) 2002 Free Software Foundation, Inc. ++# Proxecto Trasno - Adaptación do software libre á lingua galega: Se desexas ++# colaborar connosco, podes atopar máis información en http://www.trasno.net ++# ++# Rubén López Gómez , 1999, 2000. ++# Manuel A. Fernández Montecelo , 2002. ++# Xabi García , 2002. ++# Ignacio Casal Quinteiro , 2005, 2006. ++# Ignacio Casal Quinteiro , 2007, 2008. ++# Mancomún - Centro de Referencia e Servizos de Software Libre , 2009. ++# Antón Méixome , 2009. ++# Antón Méixome , 2010. ++# Fran Diéguez , 2009, 2010, 2011, 2012. ++# Leandro Regueiro , 2011, 2012. ++# Fran Dieguez , 2012-2021. ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# gl.po.multitasking (gnome-control-center-master-po-gl-72290." ++"merged) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center-master-po-gl-72290.merged\n" +-"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/issu" +-"es\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-08 08:29+0000\n" ++"PO-Revision-Date: 2021-09-08 11:40+0200\n" ++"Last-Translator: Fran Dieguez \n" ++"Language-Team: Galician \n" ++"Language: gl\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1)\n" ++"X-Generator: Gtranslator 40.0\n" ++"X-Launchpad-Export-Date: 2014-05-09 14:44+0000\n" ++"X-Project-Style: gnome\n" ++"X-DL-Team: gl\n" ++"X-DL-Module: gnome-control-center\n" ++"X-DL-Branch: master\n" ++"X-DL-Domain: po\n" ++"X-DL-State: Translating\n" ++"#-#-#-#-# gl.po (gnome-control-center-master-po-gl-72290.merged) #-#-#-#-" ++"#\n" ++"Project-Id-Version: gnome-control-center-master-po-gl-72290.merged\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" + "POT-Creation-Date: 2021-02-21 19:17+0000\n" + "PO-Revision-Date: 2021-02-24 15:32+0100\n" + "Last-Translator: Fran Diéguez \n" +@@ -32,6 +76,93 @@ msgstr "" + "X-Launchpad-Export-Date: 2014-05-09 14:44+0000\n" + "X-Project-Style: gnome\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Xeral" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "Esquina _activa" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "" ++"Toque a esquina superior esquerda para abrir a Vista xeral de actividades." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "Bordos da pantalla _activos" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Arrastre xanelas aos bordos superior, esquerdo e dereito da pantalla para " ++"redimensionalas." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Espazos de traballo" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "Espazos de traballo _dinámicos" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Os espazos de traballo baleiros elimínanse automaticamente." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "Número de espazos de traballo _fixos" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Especifique un número de espazos de traballo permanentes." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Número de espazos de traballo" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Multimonitor" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Espazos de traballo só na pantalla _principal" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Espazos de traballo en _todas as pantallas" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Trocar entre aplicacións" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Incluír aplicacións de todos os _espazos de traballo" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Incluír aplicacións só do espazos de traballo _actual" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Multitarefa" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Xestionar as preferencias para a productividade e multitarefa" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "Multitarefa;Productividade;Personalizar;Escritorio;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Bus do sistema" +@@ -452,8 +583,7 @@ msgstr "Bluetooth apagado" + #: panels/bluetooth/cc-bluetooth-panel.ui:80 + msgid "Turn on to connect devices and receive file transfers." + msgstr "" +-"Acender para conectarse a dispositivos e recibir transferencias de " +-"ficheiros." ++"Acender para conectarse a dispositivos e recibir transferencias de ficheiros." + + #: panels/bluetooth/cc-bluetooth-panel.ui:107 + msgid "Airplane Mode is on" +@@ -2638,11 +2768,6 @@ msgstr "Ningunha aplicación solicitou acceso ao micrófono" + msgid "Protect your conversations" + msgstr "Protexer as túas conversas" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Xeral" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "_Botón primario" +diff --git a/po/he.po b/po/he.po +index 7e20f06ac..2fa0e5213 100644 +--- a/po/he.po ++++ b/po/he.po +@@ -1,3 +1,14 @@ ++# #-#-#-#-# he.po.multitasking (gnome-control-center.HEAD.he) #-#-#-#-# ++# translation of gnome-control-center.HEAD.he.po to Hebrew ++# translation of gnome-control-center.gnome-2-0.he.po to Hebrew ++# This file is distributed under the same license as the PACKAGE package. ++# Copyright (C) 2005 THE PACKAGE'S COPYRIGHT HOLDER. ++# Gil 'Dolfin' Osher , 2002,2003. ++# Yuval Tanny, 2005. ++# Yaron Shahrabani , 2010, 2011. ++# Yosef Or Boczko , 2013-2021. ++# ++# #-#-#-#-# he.po (gnome-control-center.HEAD.he) #-#-#-#-# + # translation of gnome-control-center.HEAD.he.po to Hebrew + # translation of gnome-control-center.gnome-2-0.he.po to Hebrew + # This file is distributed under the same license as the PACKAGE package. +@@ -7,8 +18,25 @@ + # Yaron Shahrabani , 2010, 2011. + # Yosef Or Boczko , 2013-2020. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# he.po.multitasking (gnome-control-center.HEAD.he) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center.HEAD.he\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-24 15:42+0000\n" ++"PO-Revision-Date: 2021-09-23 10:57+0300\n" ++"Last-Translator: Yaron Shahrabani \n" ++"Language-Team: Hebrew \n" ++"Language: he\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : n==2 ? 1 : n>10 && n%10==0 ? " ++"2 : 3);\n" ++"X-Generator: Poedit 3.0\n" ++"#-#-#-#-# he.po (gnome-control-center.HEAD.he) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center.HEAD.he\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -23,6 +51,93 @@ msgstr "" + "Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n>2||n==0) ? 1 : 2\n" + "X-Generator: Gtranslator 3.36.0\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "כללי" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_פינה חמה" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "נגיעה בפינה הימנית העליונה תפתח את סקירת הפעילויות." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_קצוות מסך פעילים" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"גרירה של החלונות כלפי השוליים העליונים, שמאליים וימנים של המסך תשנה את גודלם." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "מרחבי עבודה" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "מרחבי עבודה _גמישים" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "מסיר מרחבי עבודה ריקים אוטומטית." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "מספר _קבוע של מרחבי עבודה" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "נא לציין מספר של מרחבי עבודה קבועים." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "מ_ספר מרחבי עבודה" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "ריבוי צגים" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "מרחבי עבודה בצג ה_ראשי בלבד" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "מרחבי עבודה ב_כל הצגים" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "החלפת יישומים" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "לכלול יישומים מ_כל מרחבי העבודה" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "לכלול יישומים ממרחב העבודה ה_נוכחי בלבד" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "ריבוי משימות" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "ניהול העדפות ליעילות וריבוי משימות" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"ריבוי משימות;ביצוע מפוצל;יעילות;פרודוקטיביות;מולטיטאסקינג;מולטיטסקינג;התאמה;" ++"שינוי;עריכה;שולחן עבודה;התאמה אישית;" ++ + #: panels/applications/cc-applications-panel.c:815 + #| msgid "System Sounds" + msgid "System Bus" +@@ -2526,11 +2641,6 @@ msgstr "אף יישום לא דרש גישה למיקרופון." + msgid "Protect your conversations" + msgstr "הגנה על השיחות שלך" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "כללי" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "לחצן ראשי" +diff --git a/po/hr.po b/po/hr.po +index e006274a9..1254f2b8e 100644 +--- a/po/hr.po ++++ b/po/hr.po +@@ -2,8 +2,26 @@ + # Copyright (C) Croatiann team + # Translators: Automatski Prijevod <>,Danijel Studen ,Denis Lackovic ,Robert Sedak ,Vedran Vyroubal ,Miroslav Sabljić + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# hr.po.multitasking (gnome-control-center 2.0) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center 2.0\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-24 15:42+0000\n" ++"PO-Revision-Date: 2021-10-06 19:03+0200\n" ++"Last-Translator: gogo \n" ++"Language-Team: Croatian \n" ++"Language: hr\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" ++"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" ++"X-Launchpad-Export-Date: 2016-10-09 11:56+0000\n" ++"X-Generator: Poedit 3.0\n" ++"#-#-#-#-# hr.po (gnome-control-center 2.0) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center 2.0\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -20,6 +38,92 @@ msgstr "" + "X-Launchpad-Export-Date: 2016-10-09 11:56+0000\n" + "X-Generator: Poedit 2.3\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Općenito" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Kut zaslona" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Dodirni gornji lijevi kut za otvaranje pregleda aktivnosti." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Aktivni rubovi zaslona" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Povlači prozore po gornjem, lijevom i desnom rubu zaslona kako bi im " ++"promijenili veličinu." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Radni prostori" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Promjenjivi radni prostori" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Automatski uklanja prazne radne prostore." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Nepromjenjiv broj radnih prostora" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Odredite broj stalnih radnih prostora." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Broj radnih prostora" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Više zaslona" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Radni prostori na _glavnom zaslonu" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Radni prostori na svima z_aslonima" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Prebacivanje aplikacija" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Obuhvati aplikacije sa svih _radnih prostora" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Obuhvati aplikacije samo s _trenutnog radnog prostora" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Višezadaćnost" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Upravljajte osobitostima za produktivnost i višezadaćnost" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "Višezadaćnost;Višezadaća;Produktivnost;Prilagodi;Radna površina;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Sabirnica sustava" +@@ -2629,11 +2733,6 @@ msgstr "Nema aplikacija koje su zatražile pristup vašem mikrofonu" + msgid "Protect your conversations" + msgstr "Zaštitite svoje razgovore" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Općenito" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Glavna tipka" +diff --git a/po/hu.po b/po/hu.po +index 0b635a0b3..2ece4a4b2 100644 +--- a/po/hu.po ++++ b/po/hu.po +@@ -1,3 +1,21 @@ ++# #-#-#-#-# hu.po.multitasking (gnome-control-center master) #-#-#-#-# ++# Hungarian translation for gnome-control-center. ++# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Free Software Foundation, Inc. ++# This file is distributed under the same license as the gnome-control-center package. ++# ++# Szabolcs Ban , 1998, 1999, 2000. ++# Emese Kovacs , 2001. ++# Peter Doma , 2002. ++# Andras Timar , 2001, 2002, 2003. ++# Gabor Sari , 2003. ++# Laszlo Dvornik , 2004. ++# Gabor Kelemen , 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2015, 2016, 2017, 2018. ++# Mate ORY , 2006. ++# Richard Somloi , 2011, 2012. ++# Peter Trombitas , 2012. ++# Balázs Úr , 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021. ++# Balázs Meskó , 2019, 2020, 2021. ++# #-#-#-#-# hu.po (gnome-control-center master) #-#-#-#-# + # Hungarian translation for gnome-control-center. + # Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Free Software Foundation, Inc. + # This file is distributed under the same license as the gnome-control-center package. +@@ -14,8 +32,24 @@ + # Peter Trombitas , 2012. + # Balázs Úr , 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021. + # Balázs Meskó , 2019, 2020. ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# hu.po.multitasking (gnome-control-center master) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-08 08:29+0000\n" ++"PO-Revision-Date: 2021-09-12 08:24+0200\n" ++"Last-Translator: Balázs Úr \n" ++"Language-Team: Hungarian \n" ++"Language: hu\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Lokalize 19.12.3\n" ++"#-#-#-#-# hu.po (gnome-control-center master) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center master\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -30,6 +64,98 @@ msgstr "" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" + "X-Generator: Poedit 2.4.2\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Általános" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Forró sarok" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "" ++"Érintse meg a bal felső sarkot, hogy megnyissa a Tevékenységek áttekintést." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Aktív képernyőszegélyek" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Húzza az ablakokat a képernyő felső, bal és jobb szegélyéhez, hogy " ++"átméretezze őket." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++#| msgid "Colorspace: " ++msgid "Workspaces" ++msgstr "Munkaterületek" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Dinamikus munkaterületek" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++#| msgid "Automatically Delete Temporary _Files" ++msgid "Automatically removes empty workspaces." ++msgstr "Automatikusan eltávolítja az üres munkaterületeket." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Kötött számú munkaterület" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Adja meg az állandó munkaterületek számát." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "Munkaterületek _száma" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++#| msgid "%s Monitor" ++msgid "Multi-Monitor" ++msgstr "Több kijelző" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Munkaterületek csak az _elsődleges kijelzőn" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Munkaterületek az összes _kijelzőn" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++#| msgctxt "Wacom action-type" ++#| msgid "Application defined" ++msgid "Application Switching" ++msgstr "Alkalmazásváltás" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Az összes munkaterületen szereplő alkalmazás belevétele" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Csak a _jelenlegi munkaterületen szereplő alkalmazások belevétele" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Többfeladatos munkavégzés" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "A hatékony többfeladatos munkavégzés beállításainak kezelése" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "Többfeladatos;Hatékony;Testreszabás;Asztal;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Rendszerbusz" +@@ -2645,11 +2771,6 @@ msgstr "Egyetlen alkalmazás sem kérte a mikrofon elérését" + msgid "Protect your conversations" + msgstr "A beszélgetései védelme" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Általános" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Elsődleges gomb" +diff --git a/po/id.po b/po/id.po +index 34c34fb2b..af581389e 100644 +--- a/po/id.po ++++ b/po/id.po +@@ -1,3 +1,15 @@ ++# #-#-#-#-# id.po.multitasking (gnome-control-center master) #-#-#-#-# ++# Terjemahan Bahasa Indonesia dari gnome-control-center ++# Copyright (C) 2003 gnome-control-center's copyright holder ++# This file is distributed under the same license as the gnome-control-center package. ++# ++# Mohammad DAMT , 2003. ++# Ahmad Riza H Nst , 2006. ++# Dirgita , 2010, 2012, 2014. ++# Andika Triwidada , 2009, 2011-2015, 2017, 2021. ++# Kukuh Syafaat , 2017-2021. ++# Sofyan Sugianto , 2020 ++# #-#-#-#-# id.po (gnome-control-center master) #-#-#-#-# + # Terjemahan Bahasa Indonesia dari gnome-control-center + # Copyright (C) 2003 gnome-control-center's copyright holder + # This file is distributed under the same license as the gnome-control-center package. +@@ -8,8 +20,24 @@ + # Andika Triwidada , 2009, 2011-2015, 2017. + # Kukuh Syafaat , 2017-2021. + # Sofyan Sugianto , 2020 ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# id.po.multitasking (gnome-control-center master) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-08 08:29+0000\n" ++"PO-Revision-Date: 2021-09-09 08:09+0700\n" ++"Last-Translator: Kukuh Syafaat \n" ++"Language-Team: Indonesian \n" ++"Language: id\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural= n!=1;\n" ++"X-Generator: Poedit 3.0\n" ++"#-#-#-#-# id.po (gnome-control-center master) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center master\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -24,6 +52,92 @@ msgstr "" + "Plural-Forms: nplurals=2; plural= n!=1;\n" + "X-Generator: Poedit 2.4.2\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Umum" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Pojok Panas" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Sentuh pojok kiri atas untuk membuka Ringkasan Aktivitas." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "Tepi Layar _Aktif" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Seret jendela ke tepi layar puncak, kiri, dan kanan untuk mengubah ukuran " ++"mereka." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Ruang kerja" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "Ruang kerja _dinamis" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Secara otomatis menghapus ruang kerja yang kosong." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Cacah tetap ruang kerja" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Nyatakan banyaknya ruang kerja permanen." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "Cacah rua_ng kerja" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Multi-Monitor" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Ruang kerja hanya pada tampilan _primer" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Ruang kerja pada semua tampilan" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Pengalihan Aplikasi" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Sertakan aplikasi dari semua ruang _kerja" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Sertakan aplikasi dari ruang kerja saat _ini saja" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Multitasking" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Mengelola preferensi untuk produktivitas dan multitasking" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "Multitasking;Multitask;Produktivitas;Menyesuaikan;Desktop;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Bus Sistem" +@@ -2625,11 +2739,6 @@ msgstr "Tak Ada Aplikasi yang Meminta Akses Mikrofon" + msgid "Protect your conversations" + msgstr "Lindungi percakapan Anda" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Umum" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Tombol primer" +diff --git a/po/is.po b/po/is.po +index 37f94c06f..0c8b637a4 100644 +--- a/po/is.po ++++ b/po/is.po +@@ -1,14 +1,39 @@ ++# #-#-#-#-# is.po.multitasking (gnome-control-center.master.is) #-#-#-#-# ++# translation of gnome-control-center.master.is.po to Íslenska ++# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER ++# This file is distributed under the same license as the PACKAGE package. ++# ++# Áki G. Karlsson , 2003. ++# Sveinn í Felli , 2015, 2016, 2017, 2019, 2021, 2022. ++# #-#-#-#-# is.po (gnome-control-center.master.is) #-#-#-#-# + # translation of gnome-control-center.master.is.po to Íslenska + # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER + # This file is distributed under the same license as the PACKAGE package. + # + # Áki G. Karlsson , 2003. + # Sveinn í Felli , 2015, 2016, 2017, 2019. ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# is.po.multitasking (gnome-control-center.master.is) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center.master.is\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2022-01-24 13:03+0000\n" ++"PO-Revision-Date: 2022-01-30 20:59+0000\n" ++"Last-Translator: Sveinn í Felli \n" ++"Language-Team: Icelandic \n" ++"Language: is\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"PPlural-Forms: nplurals=2; plural=n != 1;\n" ++"X-Generator: Lokalize 19.12.3\n" ++"Plural-Forms: nplurals=2; plural=n != 1;\n" ++"#-#-#-#-# is.po (gnome-control-center.master.is) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center.master.is\n" +-"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/issu" +-"es\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" + "POT-Creation-Date: 2019-07-25 08:20+0000\n" + "PO-Revision-Date: 2019-08-16 05:59+0000\n" + "Last-Translator: Sveinn í Felli \n" +@@ -20,6 +45,99 @@ msgstr "" + "Plural-Forms: nplurals=2; plural=1;\n" + "X-Generator: Lokalize 2.0\n" + ++#. #-#-#-#-# is.po.multitasking (gnome-control-center.master.is) #-#-#-#-# ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++#: panels/mouse/gnome-mouse-properties.ui:50 ++msgid "General" ++msgstr "Almennt" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "Virkni_horn" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Snertu hornið efst til vinstri til að opna virkniyfirlitið." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "Virkir skjáj_aðrar" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Dragðu glugga að efri, vinstri og hægri skjájöðrum til að breyta stærð " ++"þeirra." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++#| msgid "Colorspace: " ++msgid "Workspaces" ++msgstr "Vinnusvæði" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Breytilegur földi vinnusvæða" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++#| msgid "Automatically empty _Trash" ++msgid "Automatically removes empty workspaces." ++msgstr "Fjarlægir tóm vinnusvæði sjálfkrafa." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Fastur fjöldi vinnusvæða" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Tilgreindu fjölda varanlegra vinnusvæða." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Fjöldi vinnusvæða" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++#| msgid "%s Monitor" ++msgid "Multi-Monitor" ++msgstr "Margir skjáir" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Vinnusvæði eingöngu á _aðalskjá" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "V_innusvæði á öllum skjám" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++#| msgctxt "Wacom action-type" ++#| msgid "Application defined" ++msgid "Application Switching" ++msgstr "Skipting milli forrita" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Hafa með forrit frá öllum _vinnusvæðum" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "_Hafa einungis með forrit frá virku vinnusvæði" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Fjölverkavinnsla" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Sýsla með kjörstillingar varðandi afköst og fjölverkavinnslu" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "Fjölverkavinnsla;Verkefni;Afköst;Vinna;Sérsníða;Skjáborð;" ++ + #: panels/applications/cc-applications-panel.c:558 + #| msgid "System Sounds" + msgid "System Bus" +@@ -314,8 +432,8 @@ msgstr "Opna í hugbúnaðarstýringu" + msgid "" + "How much disk space this application is occupying with app data and caches." + msgstr "" +-"Hversu mikið diskpláss þetta forrit er að notað til að geyma forritsgögn og" +-" hrunupplýsingar." ++"Hversu mikið diskpláss þetta forrit er að notað til að geyma forritsgögn og " ++"hrunupplýsingar." + + #: panels/applications/cc-applications-panel.ui:484 + #| msgid "Applications" +@@ -1492,8 +1610,8 @@ msgid "" + "Drag displays to match your physical display setup. Select a display to " + "change its settings." + msgstr "" +-"Dragðu skjái til svo þeir samsvari uppsetningunni hjá þér. Veldu svo skjá til" +-" að breyta stillingum hans." ++"Dragðu skjái til svo þeir samsvari uppsetningunni hjá þér. Veldu svo skjá " ++"til að breyta stillingum hans." + + #: panels/display/cc-display-panel.ui:242 + msgid "Display Arrangement" +@@ -2283,10 +2401,6 @@ msgstr "Breyttu næmni músar eða snertiplatta og veldu rétt- eða örvhent" + msgid "Trackpad;Pointer;Click;Tap;Double;Button;Trackball;Scroll;" + msgstr "Snertiplatti;Bendill;Smella;Slá;Tvísmella;Hnappur;Bendilkúla;Skrun;" + +-#: panels/mouse/gnome-mouse-properties.ui:50 +-msgid "General" +-msgstr "Almennt" +- + #: panels/mouse/gnome-mouse-properties.ui:88 + msgid "Primary Button" + msgstr "Aðalhnappur" +@@ -6708,11 +6822,9 @@ msgid "" + "big;high;large;text;font;size;AccessX;Sticky;Keys;Slow;Bounce;Mouse;Double;" + "click;Delay;Speed;Assist;Repeat;Blink;visual;hearing;audio;typing;" + msgstr "" +-"Lyklaborð;Mús;a11y;Aðgengi;Birtuskil;Hljóð;Bendill;Aðdráttur;Skjár;Lesari;text" +-"i;letur;" +-"stærð;AccessX;Klístrað;Lyklar;Hægt;Endurtaka;Endurvarp;Tvísmella;smella;töf;hr" +-"aði;" +-"Aðstoð" ++"Lyklaborð;Mús;a11y;Aðgengi;Birtuskil;Hljóð;Bendill;Aðdráttur;Skjár;Lesari;" ++"texti;letur;stærð;AccessX;Klístrað;Lyklar;Hægt;Endurtaka;Endurvarp;Tvísmella;" ++"smella;töf;hraði;Aðstoð" + + #: panels/universal-access/zoom-options.c:305 + msgctxt "Distance" +diff --git a/po/ja.po b/po/ja.po +index a2955d815..13cca75a7 100644 +--- a/po/ja.po ++++ b/po/ja.po +@@ -1,3 +1,34 @@ ++# #-#-#-#-# ja.po.multitasking (gnome-control-center master) #-#-#-#-# ++# gnome-control-center ja.po. ++# Copyright (C) 1998-2001, 2003-2022 Free Software Foundation, Inc. ++# Yukihiro Nakai , 1998. ++# Eiichiro ITANI , 1999. ++# Takayuki KUSANO , 2000, 2009, 2010-2013. ++# Akira TAGOH , 2001. ++# KAMAGASAKO Masatoshi , 2003. ++# Takeshi AIHANA , 2003-2008. ++# Satoru SATOH , 2006. ++# Hiyoko Torisaki , 2009. ++# Hideki Yamane (Debian-JP) , 2009. ++# Shushi Kurose , 2009-2012, 2014, 2016. ++# Yasumichi Akahoshi , 2010. ++# Jiro Matsuzawa , 2010-2017. ++# GEN SAKASHITA , 2011. ++# Takashi Sakamoto , 2011. ++# Kiyotaka NISHIBORI , 2011. ++# Hideki Yamnane , 2011. ++# Noriko Mizumoto , 2012. ++# Koichi Akabe , 2012. ++# Kentaro KAZUHAMA , 2012, 2018, 2020. ++# Ikuya Awashiro , 2014, 2017. ++# Hajime Taira , 2015-2018. ++# TakashiUshikoshi , 2016. ++# Shinichirou Yamada , 2017-2018. ++# Kenichi Ito , 2018. ++# sicklylife , 2019-2020, 2022. ++# sujiniku , 2021. ++# ++# #-#-#-#-# ja.po (gnome-control-center master) #-#-#-#-# + # gnome-control-center ja.po. + # Copyright (C) 1998-2001, 2003-2020 Free Software Foundation, Inc. + # Yukihiro Nakai , 1998. +@@ -26,8 +57,23 @@ + # Kenichi Ito , 2018. + # sicklylife , 2019-2020. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# ja.po.multitasking (gnome-control-center master) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2022-01-24 13:03+0000\n" ++"PO-Revision-Date: 2022-02-05 22:00+0900\n" ++"Last-Translator: sicklylife \n" ++"Language-Team: Japanese \n" ++"Language: ja\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=1; plural=0;\n" ++"#-#-#-#-# ja.po (gnome-control-center master) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center master\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -41,6 +87,95 @@ msgstr "" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=1; plural=0;\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "全般" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "ホットコーナー(_H)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "画面左上隅にタッチするとアクティビティ画面を開きます。" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "スクリーンエッジを有効にする(_A)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"ウィンドウを画面上部、画面左端、画面右端にドラッグすることでウィンドウサイズ" ++"を変更できるようにします。" ++ ++# ref. gnome-color-manager ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "ワークスペース" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "動的ワークスペース(_D)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "空のワークスペースを自動的に削除します。" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "ワークスペースの数を指定する(_F)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "常に指定した数のワークスペースが用意されます。" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "ワークスペースの数(_N)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "マルチモニター" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "プライマリーディスプレイにのみワークスペースを表示する(_P)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "すべてのディスプレイにワークスペースを表示する(_I)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "アプリケーションの切り替え" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "すべてのワークスペースのアプリケーションを含める(_W)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "現在のワークスペースのアプリケーションのみを含める(_C)" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "マルチタスク" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "プロダクティビティとマルチタスクに関する設定を管理します" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"Multitasking;Multitask;Productivity;Customize;Desktop;マルチタスク;プロダク" ++"ティビティ;カスタマイズ;デスクトップ;" ++ + #: panels/applications/cc-applications-panel.c:815 + msgid "System Bus" + msgstr "システムバス" +@@ -2553,11 +2688,6 @@ msgstr "マイクへのアクセスを要求しているアプリケーション + msgid "Protect your conversations" + msgstr "会話を保護します" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "全般" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "主ボタン" +diff --git a/po/kk.po b/po/kk.po +index f72686dea..9d2ac5f7d 100644 +--- a/po/kk.po ++++ b/po/kk.po +@@ -3,8 +3,24 @@ + # This file is distributed under the same license as the gnome-control-center package. + # Baurzhan Muftakhidinov , 2010-2021. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# kk.po.multitasking (gnome-control-center master) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-08 08:29+0000\n" ++"PO-Revision-Date: 2021-09-08 15:35+0500\n" ++"Last-Translator: Baurzhan Muftakhidinov \n" ++"Language-Team: Kazakh \n" ++"Language: kk\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=1; plural=0;\n" ++"X-Generator: Poedit 3.0\n" ++"#-#-#-#-# kk.po (gnome-control-center master) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center master\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -19,6 +35,94 @@ msgstr "" + "Plural-Forms: nplurals=1; plural=0;\n" + "X-Generator: Poedit 2.4.2\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Жалпы" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Ыстық бұрыш" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Белсенділіктер көрінісін ашу үшін, жоғарғы сол жақ бұрышына тиіңіз." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Белсенді экран шеттері" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Терезелер өлшемін өзгерту үшін оларды жоғарғы, сол және оң жақ экран " ++"шеттеріне тартып апарыңыз." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Жұмыс орындары" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Динамикалық жұмыс орындары" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Бос жұмыс орындарын автоматты түрде өшіреді." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "Жұмыс орындарының _бекітілген саны" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Тұрақты жұмыс орындар санын көрсетіңіз." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "Жұмыс орындар са_ны" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Көпмониторлы" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Жұмыс орындары тек _біріншілік экранда" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Жұмыс орындары барлық э_крандарда" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Қолданбалар арасында ауысу" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Барлық _жұмыс орындарынан қолданбаларды есепке алу" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Тек ағымдағы _жұмыс орнынан қолданбаларды есепке алу" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Көптапсырмалылық" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Өнімділік және көптапсырмалылық баптауларын басқару" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"Multitasking;Multitask;Productivity;Customize;Desktop;көптапсырмалылық;" ++"өнімділік;баптау;жұмыс үстелі;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Жүйелік шина" +@@ -2635,11 +2739,6 @@ msgstr "Ешбір қолданба Микрофонға қатынау рұқс + msgid "Protect your conversations" + msgstr "Сөйлесулерді қорғау" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Жалпы" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Біріншілік батырма" +diff --git a/po/ko.po b/po/ko.po +index 941b5d9b3..3edc53de3 100644 +--- a/po/ko.po ++++ b/po/ko.po +@@ -26,8 +26,24 @@ + # msgid "Wallpaper;Screen;Desktop;" + # msgstr "Wallpaper;배경 이미지;Screen;화면;Desktop;바탕 화면;" + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# ko.po.multitasking (gnome-control-center) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-11-03 15:34+0000\n" ++"PO-Revision-Date: 2021-11-14 03:01+0900\n" ++"Last-Translator: Changwoo Ryu \n" ++"Language-Team: GNOME Korea \n" ++"Language: ko\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=1; plural=0;\n" ++"X-Generator: Poedit 1.5.3\n" ++"#-#-#-#-# ko.po (gnome-control-center) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -42,6 +58,92 @@ msgstr "" + "Plural-Forms: nplurals=1; plural=0;\n" + "X-Generator: Poedit 1.5.3\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "일반" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "구석 누르기(_H)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "위 왼쪽 구석을 터치해 현재 활동 요약 화면을 엽니다." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "화면 가장자리로 끌기(_A)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "창을 위, 왼쪽, 오른쪽 화면 가장자리로 끌어서 창 크기를 조절합니다." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "작업 공간" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "동적 작업 공간(_D)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "자동으로 빈 작업 공간을 제거합니다." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "고정된 작업 공간 개수(_F)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "영구적인 작업 공간의 개수를 지정합니다." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "작업 공간 개수(_N)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "다중 모니터" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "주 디스플레이만 작업 공간 사용(_P)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "모든 디스플레이에 작업 공간 사용(_I)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "프로그램 전환" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "모든 작업 공간의 프로그램을 포함(_W)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "현재 작업 공간의 프로그램만 포함(_C)" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "다중 작업" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "생산성 및 다중 작업에 대한 설정을 관리합니다" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"Multitasking;다중작업;다중 작업;멀티태스킹;Multitask;멀티태스크;Productivity;" ++"생산성;Customize;사용자설정;사용자 설정;Desktop;데스크톱;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "시스템 버스" +@@ -2206,7 +2308,11 @@ msgid "" + "it, press compose then a sequence of characters. For example, compose key " + "followed by C and o will enter ©, a followed by " + "' will enter á." +-msgstr "조합 키를 사용하면 여러가지 종류의 문자를 입력할수 있습니다. 조합 키를 사용하려면, 조합 키와 문자의 연속을 누릅니다. 예를 들어, 조합 키 다음에 Co를 누르면 © 문자를 입력하고, a'를 누르면 á 문자를 입력합니다." ++msgstr "" ++"조합 키를 사용하면 여러가지 종류의 문자를 입력할수 있습니다. 조합 키를 사용하" ++"려면, 조합 키와 문자의 연속을 누릅니다. 예를 들어, 조합 키 다음에 C " ++"및 o를 누르면 © 문자를 입력하고, a'를 누르면 " ++"á 문자를 입력합니다." + + #: panels/keyboard/cc-keyboard-panel.c:98 + msgctxt "keyboard key" +@@ -2636,11 +2742,6 @@ msgstr "마이크 접근을 요청한 프로그램이 없습니다" + msgid "Protect your conversations" + msgstr "대화를 보호합니다" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "일반" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "기본 단추" +diff --git a/po/lt.po b/po/lt.po +index 1547011a1..36d005535 100644 +--- a/po/lt.po ++++ b/po/lt.po +@@ -11,8 +11,27 @@ + # Algimantas Margevičius , 2011. + # Aurimas Černius , 2010-2021. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# lt.po.multitasking (gnome-control-center master) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-08 08:29+0000\n" ++"PO-Revision-Date: 2021-09-12 20:54+0300\n" ++"Last-Translator: Aurimas Černius \n" ++"Language-Team: Lietuvių \n" ++"Language: lt\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n" ++"%100<10 || n%100>=20) ? 1 : 2)\n" ++"X-Generator: Gtranslator 40.0\n" ++"X-Poedit-SourceCharset: utf-8\n" ++"X-Project-Style: gnome\n" ++"#-#-#-#-# lt.po (gnome-control-center master) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center master\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -30,6 +49,92 @@ msgstr "" + "X-Poedit-SourceCharset: utf-8\n" + "X-Project-Style: gnome\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Bendri" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Karštas kampas" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Paspauskite viršutinį kairįjį kampą veiklų apžvalgai atverti." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Aktyvūs ekrano kraštai" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Tempkite langus į viršutinį, kairį bei dešinį ekrano kraštus jų dydžiui " ++"pakeisti." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Darbo sritys" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Dinaminės darbo sritys" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Automatiškai pašalina tuščias darbo sritis." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Fiksuotas darbo sričių skaičius" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Nurodykite nuolatinių darbo sričių skaičių." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Darbo sričių skaičius" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Keli monitoriai" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Darbo sritys tik _pirminiame vaizduoklyje" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Darbo sritys v_isuose vaizduokliuose" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Automatinis perjungimas" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Įtraukti programas iš visų darbo _sričių" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Įtraukti programas tik iš _dabartinės darbo srities" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Daug užduočių" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Tvarkykite nuostatas produktyvumui ir daugeliui užduočių" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "Daugelis užduočių;Produktyvumas;Tinkinti;Darbastalis;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Sisteminė magistralė" +@@ -2630,11 +2735,6 @@ msgstr "Jokia programa neprašė prieigos prie mikrofono" + msgid "Protect your conversations" + msgstr "Apsaugokite savo pokalbius" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Bendri" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Pagrindinis mygtukas" +diff --git a/po/lv.po b/po/lv.po +index 6822bea6a..e879ec630 100644 +--- a/po/lv.po ++++ b/po/lv.po +@@ -1,3 +1,15 @@ ++# #-#-#-#-# lv.po.multitasking (gnome-control-center.HEAD.lv) #-#-#-#-# ++# translation of gnome-control-center.HEAD.lv.po to Latvian ++# gnome-control-center for Latvian. ++# Copyright (C) 2001, 2006, 2007, 2009 Free Software Foundation, Inc. ++# ++# Artis Trops , 2001. ++# Raivis Dejus , 2006, 2007, 2009. ++# Anita Reitere , 2010, 2012. ++# Rudolfs , 2011. ++# Rūdofls Mazurs , 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021. ++# Vika Leimane , 2020. ++# #-#-#-#-# lv.po (gnome-control-center.HEAD.lv) #-#-#-#-# + # translation of gnome-control-center.HEAD.lv.po to Latvian + # gnome-control-center for Latvian. + # Copyright (C) 2001, 2006, 2007, 2009 Free Software Foundation, Inc. +@@ -8,11 +20,28 @@ + # Rudolfs , 2011. + # Rūdofls Mazurs , 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020. + # Vika Leimane , 2020. ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# lv.po.multitasking (gnome-control-center.HEAD.lv) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center.HEAD.lv\n" +-"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/issu" +-"es\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-24 15:42+0000\n" ++"PO-Revision-Date: 2021-10-27 21:03+0300\n" ++"Last-Translator: Rūdolfs Mazurs \n" ++"Language-Team: Latvian \n" ++"Language: lv\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " ++"2);\n" ++"X-Generator: Lokalize 21.08.1\n" ++"#-#-#-#-# lv.po (gnome-control-center.HEAD.lv) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center.HEAD.lv\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" + "POT-Creation-Date: 2020-09-05 08:20+0000\n" + "PO-Revision-Date: 2020-09-06 22:19+0300\n" + "Last-Translator: Rūdolfs Mazurs \n" +@@ -21,10 +50,102 @@ msgstr "" + "MIME-Version: 1.0\n" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" +-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 :" +-" 2);\n" ++"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " ++"2);\n" + "X-Generator: Lokalize 19.12.3\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Vispārēji" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Karstais stūris" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "" ++"Pieskarieties augšējam kreisajam stūrim, lai atvērtu aktivitāšu pārskatu." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Aktivēt ekrāna malas" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Velciet logus pie loga augšpuses vai kreisā/labā loga sāna, lai mainītu to " ++"izmērus." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++#| msgid "Colorspace: " ++msgid "Workspaces" ++msgstr "Darbvietas" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Dinamiskās darbvietas" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++#| msgid "Automatically Delete Temporary _Files" ++msgid "Automatically removes empty workspaces." ++msgstr "Automātiski izņemt tukšās darbvietas." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Fiksēts darbvietu skaits" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Norādiet pastāvīgo darbvietu skaitu." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Darbvietu skaits" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++#| msgid "%s Monitor" ++msgid "Multi-Monitor" ++msgstr "Daudzmonitoru" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Darbvietas tikai uz _galvenā displeja" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Darbvietas uz v_isiem displejiem" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++#| msgctxt "Wacom action-type" ++#| msgid "Application defined" ++msgid "Application Switching" ++msgstr "Pārslēgšanās starp lietotnēm" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Iekļaut lietotnes no visām _darbvietām" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Iekļaut lietotnes tikai no _pašreizējās darbvietas" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Vairākuzdevumi" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Pārvaldiet iestatījumus produktivitātei un vairākuzdevumu darbam" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "Vairākuzdevumi;Produktivitāte;Pielāgot;Darbvirsma;" ++ + #: panels/applications/cc-applications-panel.c:815 + msgid "System Bus" + msgstr "Sistēmas kopne" +@@ -1951,11 +2072,10 @@ msgid "" + "device;system;information;hostname;memory;processor;version;default;" + "application;preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;" + msgstr "" +-"ierīce;sistēma;informācija;resursdatora nosaukums;atmiņa;procesors;versija;nok" +-"lusējums;lietotne;cd;" +-"dvd;usb;audio;video;disks;izņemams;noņemamas;vide;nesējs;datu nesējs;" +-"automātiski palaist;device;system;information;memory;processor;version;" +-"default;application;preferred;disc;removable;media;autorun;" ++"ierīce;sistēma;informācija;resursdatora nosaukums;atmiņa;procesors;versija;" ++"noklusējums;lietotne;cd;dvd;usb;audio;video;disks;izņemams;noņemamas;vide;" ++"nesējs;datu nesējs;automātiski palaist;device;system;information;memory;" ++"processor;version;default;application;preferred;disc;removable;media;autorun;" + + #: panels/keyboard/00-multimedia.xml.in:2 + msgid "Sound and Media" +@@ -2595,8 +2715,8 @@ msgid "" + "Disabling the microphone may cause some applications to not function " + "properly." + msgstr "" +-"Mikrofonu lietošana ļauj lietotnēm ierakstīt un klausīties skaņu. Mikrofona" +-" izslēgšana var traucēt dažām lietotnēm pilnvērtīgi strādāt." ++"Mikrofonu lietošana ļauj lietotnēm ierakstīt un klausīties skaņu. Mikrofona " ++"izslēgšana var traucēt dažām lietotnēm pilnvērtīgi strādāt." + + #: panels/microphone/cc-microphone-panel.ui:85 + msgid "Allow the applications below to use your microphone." +@@ -2610,11 +2730,6 @@ msgstr "Neviena lietotne nav pieprasījusi piekļuvi mikrofonam" + msgid "Protect your conversations" + msgstr "Aizsargāt savas sarunas" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Vispārēji" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Primārā poga" +@@ -2793,8 +2908,8 @@ msgid "" + "Turning on the hotspot will disconnect from %s, and it will not be possible " + "to access the internet through Wi-Fi." + msgstr "" +-"Ieslēdzot tīklāju, tiks pārtraukts savienojums ar %s, un nevarēs piekļūt" +-" internetam caur Wi-Fi." ++"Ieslēdzot tīklāju, tiks pārtraukts savienojums ar %s, un nevarēs piekļūt " ++"internetam caur Wi-Fi." + + #: panels/network/cc-wifi-hotspot-dialog.c:248 + msgid "Must have a minimum of 8 characters" +@@ -3431,9 +3546,7 @@ msgstr "Noteikt, kā savienoties ar internetu" + #| "Network;Wireless;Wi-Fi;Wifi;IP;LAN;Proxy;WAN;Broadband;Modem;Bluetooth;" + #| "vpn;DNS;" + msgid "Network;IP;LAN;Proxy;WAN;Broadband;Modem;Bluetooth;vpn;DNS;" +-msgstr "" +-"Tīkls;IP;LAN;Starpnieks;WAN;Platjosla;Modems;Bluetooth;" +-"vpn;DNS;" ++msgstr "Tīkls;IP;LAN;Starpnieks;WAN;Platjosla;Modems;Bluetooth;vpn;DNS;" + + #: panels/network/gnome-wifi-panel.desktop.in.in:4 + msgid "Control how you connect to Wi-Fi networks" +@@ -6166,8 +6279,8 @@ msgstr "Mainīt skaļumu, ievades, izvades un paziņojumu skaņas" + msgid "" + "Card;Microphone;Volume;Fade;Balance;Bluetooth;Headset;Audio;Output;Input;" + msgstr "" +-"Karte;Mikrofons;Skaļums;Klusināt;Balanss;Bluetooth;Austiņas;Audio;Izvade;Ievad" +-"e;" ++"Karte;Mikrofons;Skaļums;Klusināt;Balanss;Bluetooth;Austiņas;Audio;Izvade;" ++"Ievade;" + + #: panels/thunderbolt/cc-bolt-device-dialog.c:94 + #: panels/thunderbolt/cc-bolt-device-entry.c:125 +@@ -6717,11 +6830,10 @@ msgid "" + "Bounce;Mouse;Double;click;Delay;Speed;Assist;Repeat;Blink;visual;hearing;" + "audio;typing;" + msgstr "" +-"Tastatūra;Pele;a11y;Pieejamība;Universālā" +-" piekļuve;Kontrasts;Kursors;Skaņa;Mērogs;Ekrāna " +-"lasītājs;liels;augsts;teksts;fonts;izmērs;AccessX;Lipīgie;Taustiņi;Lēnie;" +-"Atlecošie;Pele;Dubults;klikšķis;Aizture;Ātrums;Atkārtot;Mirkšķināt;vizuāls;" +-"dzirdes;audio;raksta;" ++"Tastatūra;Pele;a11y;Pieejamība;Universālā piekļuve;Kontrasts;Kursors;Skaņa;" ++"Mērogs;Ekrāna lasītājs;liels;augsts;teksts;fonts;izmērs;AccessX;Lipīgie;" ++"Taustiņi;Lēnie;Atlecošie;Pele;Dubults;klikšķis;Aizture;Ātrums;Atkārtot;" ++"Mirkšķināt;vizuāls;dzirdes;audio;raksta;" + + #: panels/universal-access/zoom-options.c:303 + msgctxt "Distance" +@@ -7256,8 +7368,8 @@ msgid "" + "Fingerprint login allows you to unlock and log into your computer with your " + "finger" + msgstr "" +-"Pirkstu nospiedumu ierakstīšanās jums ļauj atslēgt un ierakstīties datorā," +-" izmantojot savu pirkstu" ++"Pirkstu nospiedumu ierakstīšanās jums ļauj atslēgt un ierakstīties datorā, " ++"izmantojot savu pirkstu" + + #: panels/user-accounts/cc-fingerprint-dialog.ui:352 + msgid "_Delete Fingerprints" +@@ -7377,8 +7489,8 @@ msgid "" + "Repeatedly lift and place your finger on the reader to enroll your " + "fingerprint" + msgstr "" +-"Atkārtoti paceliet un novietojiet pirkstu uz lasītāja, lai reģistrētu savu" +-" pirkstu nospiedumu" ++"Atkārtoti paceliet un novietojiet pirkstu uz lasītāja, lai reģistrētu savu " ++"pirkstu nospiedumu" + + #. TRANSLATORS: This is the label for the button to enroll a new finger + #: panels/user-accounts/cc-fingerprint-dialog.c:989 +@@ -7941,8 +8053,8 @@ msgid "" + "The username should usually only consist of lower case letters from a-z, " + "digits and the following characters: - _" + msgstr "" +-"Lietotājvārds parasti drīkst saturēt tikai mazos burtus no a–z, ciparus un" +-" šīs rakstzīmes: . - _" ++"Lietotājvārds parasti drīkst saturēt tikai mazos burtus no a–z, ciparus un " ++"šīs rakstzīmes: . - _" + + #: panels/user-accounts/user-utils.c:439 + msgid "Sorry, that user name isn’t available. Please try another." +diff --git a/po/nl.po b/po/nl.po +index c849efa57..d79977ff0 100644 +--- a/po/nl.po ++++ b/po/nl.po +@@ -1,3 +1,27 @@ ++# #-#-#-#-# nl.po.multitasking (gnome-control-center) #-#-#-#-# ++# Dutch translation for gnome-control-center ++# This file is distributed under the same license as the gnome-control-center package. ++# Bas Wagter ++# Hein-Jan Leliveld ++# desktop - werkblad ++# enroll (fingerprint) - (vingerafruk) nemen ++# modifier keys - optietoetsen ++# wallpaper - achtergrond ++# calibrate - kalibreren ++# keywords - Engelse keywords laten staan + enkele Nederlandse woorden die Rachid had toegevoegd. ++# Dennis Smit , 2000. ++# Almer S. Tigelaar , 2001. ++# Jan-Willem Harmanny , 2002. ++# Huib Kleinhout , 2002. ++# Ronald Hummelink , 2002. ++# Tino Meinen , 2004, 2006, 2007, 2009. ++# Wouter Bolsterlee , 2006, 2008, 2011–2012. ++# Rachid BM , 2011. ++# Reinout van Schouwen , 2002–2008, 2011, 2012, 2014, 2016. ++# Nathan Follens , 2015-2021. ++# Hannie Dumoleyn , 2011, 2012, 2013, 2014, 2015, 2017, 2018, 2020, 2021. ++# Justin van Steijn , 2016, 2018. ++# #-#-#-#-# nl.po (gnome-control-center) #-#-#-#-# + # Dutch translation for gnome-control-center + # This file is distributed under the same license as the gnome-control-center package. + # Bas Wagter +@@ -20,11 +44,28 @@ + # Nathan Follens , 2015-2020. + # Hannie Dumoleyn , 2011, 2012, 2013, 2014, 2015, 2017, 2018, 2020, 2021. + # Justin van Steijn , 2016, 2018. ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# nl.po.multitasking (gnome-control-center) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center\n" +-"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/issu" +-"es\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-13 15:00+0000\n" ++"PO-Revision-Date: 2021-09-13 17:08+0200\n" ++"Last-Translator: Nathan Follens \n" ++"Language-Team: Dutch \n" ++"Language: nl\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 3.0\n" ++"X-Project-Style: gnome\n" ++"#-#-#-#-# nl.po (gnome-control-center) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" + "POT-Creation-Date: 2021-02-21 15:21+0000\n" + "PO-Revision-Date: 2021-03-18 18:20+0100\n" + "Last-Translator: Hannie Dumoleyn \n" +@@ -37,6 +78,94 @@ msgstr "" + "X-Generator: Lokalize 19.12.3\n" + "X-Project-Style: gnome\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Algemeen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "Snel_hoek" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Tik op de linkerbovenhoek om het activiteitenoverzicht te openen." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "Schermranden _activeren" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Versleep vensters tegen boven-, linker en rechterrand van het scherm om hun " ++"grootte aan te passen." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Werkbladen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Dynamische werkbladen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Verwijdert automatisch lege werkbladen." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Vast aantal werkbladen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Geef een vast aantal werkbladen op." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "Aa_ntal werkbladen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Meerdere schermen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Werkbladen alleen op _hoofdscherm" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Werkbladen op alle _schermen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Wisselen tussen toepassingen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Toepassingen van alle _werkbladen tonen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Alleen toepassingen van het _huidige werkblad tonen" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Multitasken" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Beheer voorkeuren voor productiviteit en multitasken" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"Multitasking;Multitask;Productivity;Customize;Desktop;Multitasken;" ++"Productiviteit;Aanpassen;Bureaublad;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Systeembus" +@@ -2236,10 +2365,10 @@ msgid "" + "followed by C and o will enter ©, a followed by " + "' will enter á." + msgstr "" +-"Met de samensteltoets kan een grote verscheidenheid aan tekens worden" +-" ingevoerd. Om deze te gebruiken, drukt u op samenstellen en vervolgens op" +-" een reeks tekens. Bijvoorbeeld, samensteltoets gevolgd door C en o geeft ©, a gevolgd door ' geeft á." ++"Met de samensteltoets kan een grote verscheidenheid aan tekens worden " ++"ingevoerd. Om deze te gebruiken, drukt u op samenstellen en vervolgens op " ++"een reeks tekens. Bijvoorbeeld, samensteltoets gevolgd door C en " ++"o geeft ©, a gevolgd door ' geeft á." + + #: panels/keyboard/cc-keyboard-panel.c:98 + msgctxt "keyboard key" +@@ -2341,8 +2470,8 @@ msgstr "Aangepaste sneltoetsen toevoegen" + #: panels/keyboard/cc-keyboard-shortcut-dialog.ui:124 + msgid "Set up custom shortcuts for launching apps, running scripts, and more." + msgstr "" +-"Aangepaste sneltoetsen instellen voor het starten van toepassingen, het" +-" uitvoeren van scripts en meer." ++"Aangepaste sneltoetsen instellen voor het starten van toepassingen, het " ++"uitvoeren van scripts en meer." + + #: panels/keyboard/cc-keyboard-shortcut-dialog.ui:131 + #| msgid "Shortcut" +@@ -2685,11 +2814,6 @@ msgstr "Er hebben nog geen toepassingen toegang tot uw microfoon gevraagd" + msgid "Protect your conversations" + msgstr "Bescherm uw gesprekken" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Algemeen" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Primaire knop" +diff --git a/po/oc.po b/po/oc.po +index 0db3562d7..f4c8b67f8 100644 +--- a/po/oc.po ++++ b/po/oc.po +@@ -4,8 +4,26 @@ + # Cédric Valmary (Tot en òc) , 2015. + # Cédric Valmary (totenoc.eu) , 2016, 2018. + # Cedric , 2019. ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# oc.po.multitasking (gnome-control-center HEAD) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center HEAD\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2022-02-15 22:16+0000\n" ++"PO-Revision-Date: 2022-02-20 19:35+0100\n" ++"Last-Translator: Quentin PAGÈS\n" ++"Language-Team: Tot en òc\n" ++"Language: oc\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n > 1);\n" ++"X-Generator: Poedit 3.0\n" ++"X-DamnedLies-Scope: partial\n" ++"X-Project-Style: gnome\n" ++"#-#-#-#-# oc.po (gnome-control-center HEAD) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center HEAD\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -22,6 +40,94 @@ msgstr "" + "X-DamnedLies-Scope: partial\n" + "X-Project-Style: gnome\n" + ++#. #-#-#-#-# oc.po.multitasking (gnome-control-center HEAD) #-#-#-#-# ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++#: panels/mouse/gnome-mouse-properties.ui:50 ++msgid "General" ++msgstr "General" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Bòrd reactiu" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Tocar lo caire naut esquèr per dobrir l’apercebut de las activitats." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Bordaduras d’ecran actiu" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Lisatz las fenèstras contra los bòrds superiors a man esquèrra e drecha per " ++"los redimencionar." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Espacis de trabalh" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Espacis de trabalh dinamics" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Suprimir automaticament los espacis de trabalhs voids." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Nombre d’espacis de trabalh fixe" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Especificatz un nombre d’espacis de trabalh permanents." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Nombre d’espacis de trabalh" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Multi monitor" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Espacis de trabalh solament sus l’ecran _principal" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Espacis de trabalh per tote_s los ecrans" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Alternància entre aplicacions" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Inclure totas las aplicacions dels _espacis de trabalhs estant" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Inclure totas las aplicacions de l’espaci de trabalhs actual sonque" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Multiprètzfach" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Gerir las preferéncias per la productivitat e multi prètzfach" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "multi prètzfach;multitasca;productivitat;personalizar;burèu;" ++ + #: panels/applications/cc-applications-panel.c:561 + #| msgid "System Sounds" + msgid "System Bus" +@@ -1611,9 +1717,9 @@ msgid "" + "Panel;Projector;xrandr;Screen;Resolution;Refresh;Monitor;Night;Light;Blue;" + "redshift;color;sunset;sunrise;" + msgstr "" +-"Panèl;Projector;xrandr;Ecran;Definicion;Resolucion;Refrescament;Moniteur;Nuèi" +-"t;Nuèch,Esclairatge;Lum;Lutz;Blava;redshift;descalatge;espectral;color;levar;" +-"colcar;" ++"Panèl;Projector;xrandr;Ecran;Definicion;Resolucion;Refrescament;Moniteur;" ++"Nuèit;Nuèch,Esclairatge;Lum;Lutz;Blava;redshift;descalatge;espectral;color;" ++"levar;colcar;" + + #: panels/info/cc-info-default-apps-panel.ui:31 + msgid "_Web" +@@ -1879,8 +1985,8 @@ msgid "" + "device;system;information;memory;processor;version;default;application;" + "preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;" + msgstr "" +-"periferic;sistèma;informacion;memòria;processor;version;defaut;aplicacion;pre" +-"ferit;cd;dvd;usb;àudio;vidèo;disc;amovible;mèdia;execucion automatica;" ++"periferic;sistèma;informacion;memòria;processor;version;defaut;aplicacion;" ++"preferit;cd;dvd;usb;àudio;vidèo;disc;amovible;mèdia;execucion automatica;" + + #: panels/info/gnome-removable-media-panel.desktop.in.in:3 + msgid "Removable Media" +@@ -1896,9 +2002,8 @@ msgid "" + "device;system;default;application;preferred;cd;dvd;usb;audio;video;disc;" + "removable;media;autorun;" + msgstr "" +-"periferic;sistèma;per " +-"defaut;aplicacion;preferida;cd;dvd;usb;àudio;vidèo;disc;amovible;mèdia;" +-"execucion automatica;" ++"periferic;sistèma;per defaut;aplicacion;preferida;cd;dvd;usb;àudio;vidèo;" ++"disc;amovible;mèdia;execucion automatica;" + + #: panels/keyboard/00-multimedia.xml.in:2 + msgid "Sound and Media" +@@ -2179,8 +2284,8 @@ msgstr "" + msgid "" + "Shortcut;Workspace;Window;Resize;Zoom;Contrast;Input;Source;Lock;Volume;" + msgstr "" +-"Acorchi;Espaci de " +-"trabalh;Fenèstra;Redimensionar;Zoom;Contraste;Picada;Font;Verrolhar;Volum;" ++"Acorchi;Espaci de trabalh;Fenèstra;Redimensionar;Zoom;Contraste;Picada;Font;" ++"Verrolhar;Volum;" + + #: panels/keyboard/shortcut-editor.ui:68 panels/keyboard/shortcut-editor.ui:318 + #| msgid "Press Esc to cancel or Backspace to reset the keyboard shortcut." +@@ -2249,17 +2354,14 @@ msgstr "" + msgid "Trackpad;Pointer;Click;Tap;Double;Button;Trackball;Scroll;" + msgstr "Pavat;Tactil;Puntador;Clic;Quichada;Doble;Boton;Bola;Desfilament;" + +-#: panels/mouse/gnome-mouse-properties.ui:50 +-msgid "General" +-msgstr "General" +- + #: panels/mouse/gnome-mouse-properties.ui:88 + msgid "Primary Button" + msgstr "Boton principal" + + #: panels/mouse/gnome-mouse-properties.ui:107 + msgid "Sets the order of physical buttons on mice and touchpads." +-msgstr "Definís l’òrdre dels botons fisics sus las mirgas e los pavats tactils." ++msgstr "" ++"Definís l’òrdre dels botons fisics sus las mirgas e los pavats tactils." + + #: panels/mouse/gnome-mouse-properties.ui:136 + #: panels/sound/cc-balance-slider.ui:13 +@@ -2388,7 +2490,7 @@ msgstr "Pas configurat" + + #. TRANSLATORS: This happens when the connection name does not contain the SSID. + #: panels/network/cc-wifi-connection-row.c:189 +-#, c-format, c-format ++#, c-format + #| msgctxt "timezone desc" + #| msgid "%s (%s)" + msgctxt "Wi-Fi Connection" +@@ -4020,14 +4122,15 @@ msgid "" + "Notifications will continue to appear in the notification list when popups " + "are disabled." + msgstr "" +-"Las notificacions contunhan de s’afichar dins la lista del tirador quand l’" +-"afichatge de las bandièras es desactivat." ++"Las notificacions contunhan de s’afichar dins la lista del tirador quand " ++"l’afichatge de las bandièras es desactivat." + + #. Popups here refers to message tray notifications in the middle of the screen. + #: panels/notifications/cc-app-notifications-dialog.ui:249 + msgctxt "notifications" + msgid "Show Message _Content in Popups" +-msgstr "Afichar lo _contengut del messatge dins lo tirador de las notificacions" ++msgstr "" ++"Afichar lo _contengut del messatge dins lo tirador de las notificacions" + + #: panels/notifications/cc-app-notifications-dialog.ui:300 + msgctxt "notifications" +@@ -4108,8 +4211,8 @@ msgid "" + "Google;Facebook;Twitter;Yahoo;Web;Online;Chat;Calendar;Mail;Contact;ownCloud;" + "Kerberos;IMAP;SMTP;Pocket;ReadItLater;" + msgstr "" +-"Google;Facebook;Twitter;Yahoo;Web;En linha;Discussion;Agenda;Corrièr;Email;Co" +-"ntacte;ownCloud;Kerberos;IMAP;SMTP;Pocket;ReadItLater;" ++"Google;Facebook;Twitter;Yahoo;Web;En linha;Discussion;Agenda;Corrièr;Email;" ++"Contacte;ownCloud;Kerberos;IMAP;SMTP;Pocket;ReadItLater;" + + #. Translators: This is the button which allows undoing the removal of the printer. + #: panels/online-accounts/online-accounts.ui:38 panels/printers/printers.ui:71 +@@ -4634,8 +4737,8 @@ msgstr "" + msgid "" + "Power;Sleep;Suspend;Hibernate;Battery;Brightness;Dim;Blank;Monitor;DPMS;Idle;" + msgstr "" +-"Energia;Alimentacion;Velha;Suspension;Ivernacion;Batariá;Luminositat;Escurezi" +-"r;Negre;Ecran;DPMS;Inactiu;" ++"Energia;Alimentacion;Velha;Suspension;Ivernacion;Batariá;Luminositat;" ++"Escurezir;Negre;Ecran;DPMS;Inactiu;" + + #: panels/printers/authentication-dialog.ui:11 + msgid " " +@@ -5690,9 +5793,8 @@ msgid "" + "Uses Mozilla Location Service: Privacy Policy" + msgstr "" +-"Utiliza lo service de localizacion de Mozilla : Politica de " +-"Confidencialitat" ++"Utiliza lo service de localizacion de Mozilla : Politica de Confidencialitat" + + #: panels/privacy/cc-privacy-panel.ui:1038 + msgid "_Location Services" +@@ -5719,8 +5821,8 @@ msgid "" + "screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;" + "network;identity;" + msgstr "" +-"ecran;verrolhar;verrolhatge;diagnostic;plantatge;privat;confidencial;recent;t" +-"emporari;tmp;indèx;nom;rets;identitat;" ++"ecran;verrolhar;verrolhatge;diagnostic;plantatge;privat;confidencial;recent;" ++"temporari;tmp;indèx;nom;rets;identitat;" + + #: panels/region/cc-format-chooser.c:133 + msgctxt "measurement format" +@@ -5983,8 +6085,8 @@ msgid "" + "current network using: dav://%s" + msgstr "" + "Lo partiment de fichièrs vos permet de partejar vòstre dorsièr Public amb " +-"los autres sus la ret actuala en utilizant : dav://%s" ++"los autres sus la ret actuala en utilizant : dav://%s" + + #: panels/sharing/cc-sharing-panel.c:728 + #, c-format +@@ -6105,8 +6207,8 @@ msgid "" + "share;sharing;ssh;host;name;remote;desktop;media;audio;video;pictures;photos;" + "movies;server;renderer;" + msgstr "" +-"partiment;partejar;ssh;òste;nom;distant;burèu;bluetooth;obex;mèdia;àudio;vidè" +-"o;imatges;fòtos;filmes;servidor;renderer;motor de rendut;" ++"partiment;partejar;ssh;òste;nom;distant;burèu;bluetooth;obex;mèdia;àudio;" ++"vidèo;imatges;fòtos;filmes;servidor;renderer;motor de rendut;" + + #: panels/sharing/networks.ui:19 + msgid "Networks" +@@ -6154,7 +6256,7 @@ msgid "Front" + msgstr "Avant" + + #: panels/sound/cc-output-test-dialog.c:134 +-#, c-format, c-format ++#, c-format + #| msgid "Settings" + msgid "Testing %s" + msgstr "Tèst de %s" +@@ -6356,7 +6458,8 @@ msgstr "Autorizat" + #: panels/thunderbolt/cc-bolt-panel.c:176 + msgid "" + "The Thunderbolt subsystem (boltd) is not installed or not set up properly." +-msgstr "Lo sossistèma Thunderbolt (boltd) es pas installat o es mal configurat." ++msgstr "" ++"Lo sossistèma Thunderbolt (boltd) es pas installat o es mal configurat." + + #: panels/thunderbolt/cc-bolt-panel.c:469 + msgid "" +@@ -6791,10 +6894,10 @@ msgid "" + "big;high;large;text;font;size;AccessX;Sticky;Keys;Slow;Bounce;Mouse;Double;" + "click;Delay;Speed;Assist;Repeat;Blink;visual;hearing;audio;typing;" + msgstr "" +-"Clavièr;Mirga;ligam;Accessibilitat;Contraste;Cursor;Son;Zoom;Lector d’ecran;g" +-"rand;naut;elevat;tèxte;poliça;talha;AccessX;Remanentas;Tòcas;Lentas;Rebombs;M" +-"irgas;Doble;clic;Relambi;Velocitat;Assisténcia;Repeticion;Cluquejament;visual" +-";escota;àudio;picada;" ++"Clavièr;Mirga;ligam;Accessibilitat;Contraste;Cursor;Son;Zoom;Lector d’ecran;" ++"grand;naut;elevat;tèxte;poliça;talha;AccessX;Remanentas;Tòcas;Lentas;Rebombs;" ++"Mirgas;Doble;clic;Relambi;Velocitat;Assisténcia;Repeticion;Cluquejament;" ++"visual;escota;àudio;picada;" + + #: panels/universal-access/zoom-options.c:305 + msgctxt "Distance" +@@ -8114,8 +8217,8 @@ msgstr "" + msgid "" + "Whether Settings should show a warning when running a development build." + msgstr "" +-"Indica se Paramètres deu afichar un avertiment al moment de l’utilizacion d’" +-"una version de desvolopament." ++"Indica se Paramètres deu afichar un avertiment al moment de l’utilizacion " ++"d’una version de desvolopament." + + #. translators: + #. * The number of sound outputs on a particular device +diff --git a/po/pa.po b/po/pa.po +index 1ccd482a6..31932387c 100644 +--- a/po/pa.po ++++ b/po/pa.po +@@ -7,11 +7,27 @@ + # Amanpreet Singh Alam , 2004. + # Amanpreet Singh Alam , 2005,2006,2007,2008,2009. + # A S Alam , 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021. ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# pa.po.multitasking (gnome-control-center.HEAD) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center.HEAD\n" +-"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/issu" +-"es\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-18 09:55+0000\n" ++"PO-Revision-Date: 2021-09-18 16:30-0700\n" ++"Last-Translator: A S Alam \n" ++"Language-Team: Punjabi \n" ++"Language: pa\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=n != 1;\n" ++"X-Generator: Lokalize 20.12.2\n" ++"#-#-#-#-# pa.po (gnome-control-center.HEAD) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center.HEAD\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" + "POT-Creation-Date: 2021-02-01 20:21+0000\n" + "PO-Revision-Date: 2021-02-05 22:40-0800\n" + "Last-Translator: A S Alam \n" +@@ -23,6 +39,90 @@ msgstr "" + "Plural-Forms: nplurals=2; plural=n != 1;\n" + "X-Generator: Lokalize 20.08.1\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "ਆਮ" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "ਸਰਗਰਮ ਕੋਨਾ(_H)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "ਸਕਰੀਨ ਦੇ ਕੋਨੇ ਸਰਗਰਮ ਕਰੋ(_A)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "ਵਰਕਸਪੇਸ" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "ਸਫ਼ਰੀ ਵਰਕਸਪੇਸ(_D)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "ਖਾਲੀ ਵਰਕਸਪੇਸਾਂ ਨੂੰ ਆਪਣੇ-ਆਪ ਹਟਾਓ।" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "ਵਰਕਸਪੇਸਾਂ ਦੀ ਪੱਕੀ ਗਿਣਤੀ(_F)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "ਪੱਕੇ ਵਰਕਸਪੇਸਾਂ ਦੀ ਗਿਣਤੀ ਦਿਓ।" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "ਵਰਕਸਪੇਸਾਂ ਦੀ ਗਿਣਤੀ(_N)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "ਬਹੁ-ਮਾਨੀਟਰ" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "ਵਰਕਸੇਪਸ ਸਿਰਫ਼ ਪ੍ਰਾਇਮਰੀ ਡਿਸਪਲੇਅ ਉੱਤੇ(_p)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "ਸਾਰੇ ਡਿਸਪਲੇਅ ਉੱਤੇ ਵਰਕਸਪੇਸ(_i)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "ਐਪਲੀਕੇਸ਼ਨ ਬਦਲਣੀਆਂ" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "ਸਾਰੀਆਂ ਵਰਕਸਪੇਸਾਂ ਤੋਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਸਮੇਤ(_w)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "ਸਿਰਫ਼ ਮੌਜੂਦਾ ਵਰਕਸਪੇਸ ਤੋਂ ਹੀ ਐਪਲੀਕੇਸ਼ਨਾਂ ਸਮੇਤ(_c)" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "ਬਹੁ-ਕੰਮਕਾਜ" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "ਉਤਪਾਦਨ ਤੇ ਬਹੁ-ਕੰਮਕਾਜ ਲਈ ਤਜਰੀਹਾਂ ਦਾ ਇੰਤਜ਼ਾਮ ਕਰੋ" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "ਬਹੁ-ਕੰਮ;ਮਲਟੀ-ਟਾਸਕ;ਉਤਪਾਦਨ,ਕਸਟਮਾਈਜ਼ ਡੈਸਕਟਾਪ;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "ਸਿਸਟਮ ਬੱਸ" +@@ -91,8 +191,7 @@ msgid "" + "%s has the following permissions built-in. These cannot be altered. If you " + "are concerned about these permissions, consider removing this application." + msgstr "" +-"%s ਵਿੱਚ ਅੱਗੇ ਦਿੱਤੀਆਂ ਇਜਾਜ਼ਤਾਂ ਪਹਿਲਾਂ ਹੀ ਹਨ। ਇਹਨਾਂ ਨੂੰ ਬਦਲਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ ਹੈ।" +-" ਜੇ ਤੁਸੀਂ ਇਹ " ++"%s ਵਿੱਚ ਅੱਗੇ ਦਿੱਤੀਆਂ ਇਜਾਜ਼ਤਾਂ ਪਹਿਲਾਂ ਹੀ ਹਨ। ਇਹਨਾਂ ਨੂੰ ਬਦਲਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ ਹੈ। ਜੇ ਤੁਸੀਂ ਇਹ " + "ਇਜਾਜ਼ਤਾਂ ਬਾਰੇ ਫ਼ਿਕਰ ਕਰਦੇ ਹੋ ਤਾਂ ਇਸ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਹਟਾਉਣ ਬਾਰੇ ਵਿਚਾਰ ਕਰੋ।" + + #: panels/applications/cc-applications-panel.c:1024 +@@ -178,8 +277,7 @@ msgid "" + "Data and services that this app has asked for access to and permissions that " + "it requires." + msgstr "" +-"ਡਾਟਾ ਅਤੇ ਸੇਵਾਵਾਂ, ਜੋ ਇਸ ਐਪ ਨੇ ਪਹੁੰਚ ਲਈ ਅਤੇ ਇਜ਼ਾਜਤਾਂ ਦੀ ਮੰਗ ਕੀਤੀ ਹੈ, ਜੋ ਇਸ ਨੂੰ" +-" ਚਾਹੀਦੀਆਂ ਹਨ।" ++"ਡਾਟਾ ਅਤੇ ਸੇਵਾਵਾਂ, ਜੋ ਇਸ ਐਪ ਨੇ ਪਹੁੰਚ ਲਈ ਅਤੇ ਇਜ਼ਾਜਤਾਂ ਦੀ ਮੰਗ ਕੀਤੀ ਹੈ, ਜੋ ਇਸ ਨੂੰ ਚਾਹੀਦੀਆਂ ਹਨ।" + + #: panels/applications/cc-applications-panel.ui:121 + #: panels/applications/cc-applications-panel.ui:127 +@@ -233,8 +331,7 @@ msgid "" + "Individual permissions for applications can be reviewed in the Privacy Settings." + msgstr "" +-"ਐਪਲੀਕੇਸ਼ਨਾਂ ਲਈ ਵੱਖੋ-ਵੱਖ ਇਜਾਜ਼ਤਾਂ ਦੀ ਪੜਤਾਲ ਪਰਦੇਦਾਰੀ" +-" ਸੈਟਿੰਗਾਂ ਵਿੱਚ " ++"ਐਪਲੀਕੇਸ਼ਨਾਂ ਲਈ ਵੱਖੋ-ਵੱਖ ਇਜਾਜ਼ਤਾਂ ਦੀ ਪੜਤਾਲ ਪਰਦੇਦਾਰੀ ਸੈਟਿੰਗਾਂ ਵਿੱਚ " + "ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ।" + + #: panels/applications/cc-applications-panel.ui:199 +@@ -494,8 +591,7 @@ msgid "" + "Use of the camera allows applications to capture photos and video. Disabling " + "the camera may cause some applications to not function properly." + msgstr "" +-"ਕੈਮਰੇ ਦੀ ਵਰਤੋਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਨੂੰ ਫੋਟੋ ਖਿੱਚਣ ਅਤੇ ਵਿਡੀਓ ਬਣਾਉਣ ਦਿੰਦੀ ਹੈ। ਕੈਮਰੇ ਨੂੰ" +-" ਅਸਮਰੱਥ ਕਰਨ ਨਾਲ ਕੁਝ " ++"ਕੈਮਰੇ ਦੀ ਵਰਤੋਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਨੂੰ ਫੋਟੋ ਖਿੱਚਣ ਅਤੇ ਵਿਡੀਓ ਬਣਾਉਣ ਦਿੰਦੀ ਹੈ। ਕੈਮਰੇ ਨੂੰ ਅਸਮਰੱਥ ਕਰਨ ਨਾਲ ਕੁਝ " + "ਐਪਲੀਕੇਸ਼ਨਾਂ ਠੀਕ ਤਰ੍ਹਾਂ ਕੰਮ ਨਹੀਂ ਕਰ ਸਕਦੀਆਂ।" + + #: panels/camera/cc-camera-panel.ui:85 +@@ -517,8 +613,7 @@ msgstr "ਆਪਣੀਆਂ ਤਸਵੀਰਾਂ ਨੂੰ ਸੁਰੱਖਿਅ + msgid "" + "screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;" + "network;identity;" +-msgstr "" +-"ਸਕਰੀਨ;ਲਾਕ;ਜਾਂਚ;ਪੜਤਾਲ;ਪ੍ਰਾਈਵੇਟ;ਨਿੱਜੀ;ਆਰਜ਼ੀ;ਇੰਡੈਕਸ;ਨਾਂ;ਨੈੱਟਵਰਕ;ਪਛਾਣ;ਕਰੈਸ਼;ਤਾਜ਼ਾ;" ++msgstr "ਸਕਰੀਨ;ਲਾਕ;ਜਾਂਚ;ਪੜਤਾਲ;ਪ੍ਰਾਈਵੇਟ;ਨਿੱਜੀ;ਆਰਜ਼ੀ;ਇੰਡੈਕਸ;ਨਾਂ;ਨੈੱਟਵਰਕ;ਪਛਾਣ;ਕਰੈਸ਼;ਤਾਜ਼ਾ;" + + #. TRANSLATORS: The user has to attach the sensor to the screen + #: panels/color/cc-color-calibrate.c:347 +@@ -531,8 +626,7 @@ msgstr "ਆਪਣੇ ਕੈਲੀਬਰੇਸ਼ਨ ਜੰਤਰ ਨੂੰ ਵਰ + #: panels/color/cc-color-calibrate.c:353 + msgid "" + "Move your calibration device to the calibrate position and press “Continue”" +-msgstr "" +-"ਆਪਣੇ ਕੈਲੀਬਰੇਸ਼ਨ ਜੰਤਰ ਨੂੰ ਕੈਲੀਬਰੇਸ਼ਨ ਸਥਿਤੀ ਉਤੇ ਲੈ ਜਾਉ ਅਤੇ ”ਜਾਰੀ ਰੱਖੋ” ਦੱਬੋ" ++msgstr "ਆਪਣੇ ਕੈਲੀਬਰੇਸ਼ਨ ਜੰਤਰ ਨੂੰ ਕੈਲੀਬਰੇਸ਼ਨ ਸਥਿਤੀ ਉਤੇ ਲੈ ਜਾਉ ਅਤੇ ”ਜਾਰੀ ਰੱਖੋ” ਦੱਬੋ" + + #. TRANSLATORS: Some calibration devices need the user to move a + #. * dial or switch manually. We also show a picture showing them +@@ -733,8 +827,7 @@ msgstr "ਇਹ URL ਲਿਖ ਲਵੋ।" + + #: panels/color/cc-color-panel.c:854 + msgid "Restart this computer and boot your normal operating system." +-msgstr "" +-"ਆਪਣੇ ਕੰਪਿਊਟਰ ਨੂੰ ਮੁੜ-ਚਾਲੂ ਕਰੋ ਅਟੇ ਆਪਣੇ ਸਧਾਰਨ ਓਪਰੇਟਿੰਗ ਸਿਸਟਮ ਨੂੰ ਬੂਟ ਕਰੋ।" ++msgstr "ਆਪਣੇ ਕੰਪਿਊਟਰ ਨੂੰ ਮੁੜ-ਚਾਲੂ ਕਰੋ ਅਟੇ ਆਪਣੇ ਸਧਾਰਨ ਓਪਰੇਟਿੰਗ ਸਿਸਟਮ ਨੂੰ ਬੂਟ ਕਰੋ।" + + #: panels/color/cc-color-panel.c:855 + msgid "Type the URL into your browser to download and install the profile." +@@ -760,9 +853,7 @@ msgstr "ਚੁਣੇ ਜੰਤਰ ਲਈ ਇੱਕ ਰੰਗ ਪਰੋਫਾਇ + msgid "" + "The measuring instrument is not detected. Please check it is turned on and " + "correctly connected." +-msgstr "" +-"ਮਾਪ ਜੰਤਰ ਖੋਜਿਆ ਨਹੀਂ ਗਿਆ ਹੈ। ਚੈੱਕ ਕਰੋ ਕਿ ਇਹ ਚਾਲੂ ਹੈ ਅਤੇ ਠੀਕ ਤਰ੍ਹਾਂ ਕੂਨੈਕਟ ਕੀਤਾ" +-" ਹੋਇਆ ਹੈ।" ++msgstr "ਮਾਪ ਜੰਤਰ ਖੋਜਿਆ ਨਹੀਂ ਗਿਆ ਹੈ। ਚੈੱਕ ਕਰੋ ਕਿ ਇਹ ਚਾਲੂ ਹੈ ਅਤੇ ਠੀਕ ਤਰ੍ਹਾਂ ਕੂਨੈਕਟ ਕੀਤਾ ਹੋਇਆ ਹੈ।" + + #. TRANSLATORS: this is when the button is insensitive + #: panels/color/cc-color-panel.c:1245 +@@ -784,10 +875,8 @@ msgid "" + "screen. The longer you spend on calibration, the better the quality of the " + "color profile." + msgstr "" +-"ਕੈਲੀਬਰੇਸ਼ਨ ਇੱਕ ਪਰੋਫਾਇਲ ਦੇਵੇਗੀ, ਜਿਸ ਨੂੰ ਤੁਸੀਂ ਆਪਣੀ ਸਕਰੀਨ ਦੇ ਰੰਗ ਦੇ ਪਰਬੰਧ ਲਈ ਵਰਤ" +-" ਸਕਦੇ ਹੋ। " +-"ਕੈਲੀਬਰੇਸ਼ਨ ਉੱਤੇ ਜਿੰਨਾ ਵੱਧ ਸਮਾਂ ਤੁਸੀਂ ਲਗਾਉਗੇ, ਰੰਗ ਪਰੋਫਾਇਲ ਉਹਨਾਂ ਹੀ ਵੱਧ ਚੰਗਾ" +-" ਹੋਵੇਗਾ।" ++"ਕੈਲੀਬਰੇਸ਼ਨ ਇੱਕ ਪਰੋਫਾਇਲ ਦੇਵੇਗੀ, ਜਿਸ ਨੂੰ ਤੁਸੀਂ ਆਪਣੀ ਸਕਰੀਨ ਦੇ ਰੰਗ ਦੇ ਪਰਬੰਧ ਲਈ ਵਰਤ ਸਕਦੇ ਹੋ। " ++"ਕੈਲੀਬਰੇਸ਼ਨ ਉੱਤੇ ਜਿੰਨਾ ਵੱਧ ਸਮਾਂ ਤੁਸੀਂ ਲਗਾਉਗੇ, ਰੰਗ ਪਰੋਫਾਇਲ ਉਹਨਾਂ ਹੀ ਵੱਧ ਚੰਗਾ ਹੋਵੇਗਾ।" + + #: panels/color/cc-color-panel.ui:38 + msgid "" +@@ -829,8 +918,7 @@ msgid "" + "Select a display target white point. Most displays should be calibrated to a " + "D65 illuminant." + msgstr "" +-"ਡਿਸਪਲੇਅ ਟਾਰਗੇਟ ਚਿੱਟਾ ਬਿੰਦੂ ਚੁਣੋ। ਬਹੁਤੇ ਡਿਸਪਲੇਅ ਨੂੰ D65 illuminant ਤੱਕ" +-" ਕੈਲੀਬਰੇਟ ਕੀਤਾ ਜਾਣਾ " ++"ਡਿਸਪਲੇਅ ਟਾਰਗੇਟ ਚਿੱਟਾ ਬਿੰਦੂ ਚੁਣੋ। ਬਹੁਤੇ ਡਿਸਪਲੇਅ ਨੂੰ D65 illuminant ਤੱਕ ਕੈਲੀਬਰੇਟ ਕੀਤਾ ਜਾਣਾ " + "ਚਾਹੀਦਾ ਹੈ।" + + #: panels/color/cc-color-panel.ui:278 +@@ -842,17 +930,14 @@ msgid "" + "Please set the display to a brightness that is typical for you. Color " + "management will be most accurate at this brightness level." + msgstr "" +-"ਡਿਸਪਲੇਅ ਲਈ ਚਮਕ ਪੱਧਰ ਸੈੱਟ ਕਰੋ, ਜੋ ਤੁਸੀਂ ਆਮ ਤੌਰ ਉੱਤੇ ਵਰਤਦੇ ਹੋ। ਰੰਗ ਪਰਬੰਧ ਉਸ ਚਮਕ" +-" ਪੱਧਰ ਉੱਤੇ ਸਭ ਤੋਂ " ++"ਡਿਸਪਲੇਅ ਲਈ ਚਮਕ ਪੱਧਰ ਸੈੱਟ ਕਰੋ, ਜੋ ਤੁਸੀਂ ਆਮ ਤੌਰ ਉੱਤੇ ਵਰਤਦੇ ਹੋ। ਰੰਗ ਪਰਬੰਧ ਉਸ ਚਮਕ ਪੱਧਰ ਉੱਤੇ ਸਭ ਤੋਂ " + "ਵੱਧ ਸ਼ੁੱਧ ਹੋਵੇਗਾ।" + + #: panels/color/cc-color-panel.ui:307 + msgid "" + "Alternatively, you can use the brightness level used with one of the other " + "profiles for this device." +-msgstr "" +-"ਬਦਲਵੇਂ ਰੂਪ ਵਿੱਚ, ਤੁਸੀਂ ਇਹ ਜੰਤਰ ਲਈ ਹੋਰ ਪਰੋਫਾਇਲਾਂ ਵਿੱਚੋਂ ਇੱਕ ਨੂੰ ਚਮਕ ਪੱਧਰ ਲਈ" +-" ਵਰਤ ਸਕਦੇ ਹੋ।" ++msgstr "ਬਦਲਵੇਂ ਰੂਪ ਵਿੱਚ, ਤੁਸੀਂ ਇਹ ਜੰਤਰ ਲਈ ਹੋਰ ਪਰੋਫਾਇਲਾਂ ਵਿੱਚੋਂ ਇੱਕ ਨੂੰ ਚਮਕ ਪੱਧਰ ਲਈ ਵਰਤ ਸਕਦੇ ਹੋ।" + + #: panels/color/cc-color-panel.ui:318 + msgid "Display Brightness" +@@ -863,8 +948,7 @@ msgid "" + "You can use a color profile on different computers, or even create profiles " + "for different lighting conditions." + msgstr "" +-"ਤੁਸੀਂ ਵੱਖਰੇ ਕੰਪਿਊਟਰ ਉੱਤੇ ਰੰਗ ਪਰੋਫਾਇਲ ਵਰਤ ਸਕਦੇ ਹੋ ਜਾਂ ਵੱਖਰੀਆਂ ਚਾਨਣ ਸ਼ਰਤਾਂ" +-" ਮੁਤਾਬਕ ਰੰਗ ਪਰੋਫਾਇਲ ਬਣਾ " ++"ਤੁਸੀਂ ਵੱਖਰੇ ਕੰਪਿਊਟਰ ਉੱਤੇ ਰੰਗ ਪਰੋਫਾਇਲ ਵਰਤ ਸਕਦੇ ਹੋ ਜਾਂ ਵੱਖਰੀਆਂ ਚਾਨਣ ਸ਼ਰਤਾਂ ਮੁਤਾਬਕ ਰੰਗ ਪਰੋਫਾਇਲ ਬਣਾ " + "ਸਕਦੇ ਹੋ।" + + #: panels/color/cc-color-panel.ui:348 +@@ -901,10 +985,8 @@ msgid "" + "\">GNU/Linux, Apple OS X and Microsoft Windows systems useful." + msgstr "" +-"ਤੁਸੀਂ ਪਰੋਫਾਇਲ ਨੂੰ GNU/ਲੀਨਕਸ, ਐਪਲ OS X<" +-"/a> " +-"ਅਤੇ Microsoft Windows ਸਿਸਟਮ ਉੱਤੇ ਕਿਵੇਂ ਵਰਤੀਏ ਬਾਰੇ" +-" ਹਦਾਇਤਾਂ " ++"ਤੁਸੀਂ ਪਰੋਫਾਇਲ ਨੂੰ GNU/ਲੀਨਕਸ, ਐਪਲ OS X " ++"ਅਤੇ Microsoft Windows ਸਿਸਟਮ ਉੱਤੇ ਕਿਵੇਂ ਵਰਤੀਏ ਬਾਰੇ ਹਦਾਇਤਾਂ " + "ਵੇਖ ਸਕਦੇ ਹੋ।" + + #: panels/color/cc-color-panel.ui:607 +@@ -930,8 +1012,7 @@ msgstr "ਸ਼ਾਮਲ(_A)" + msgid "" + "Problems detected. The profile may not work correctly. Show " + "details." +-msgstr "" +-"ਸਮੱਸਿਆ ਆਈ ਹੈ। ਪਰੋਫਾਇਲ ਠੀਕ ਤਰ੍ਹਾਂ ਸ਼ਾਇਦ ਕੰਮ ਨਾ ਕਰੇ। ਵੇਰਵਾ ਵੇਖੋ" ++msgstr "ਸਮੱਸਿਆ ਆਈ ਹੈ। ਪਰੋਫਾਇਲ ਠੀਕ ਤਰ੍ਹਾਂ ਸ਼ਾਇਦ ਕੰਮ ਨਾ ਕਰੇ। ਵੇਰਵਾ ਵੇਖੋ" + + #: panels/color/cc-color-panel.ui:788 + msgid "Each device needs an up to date color profile to be color managed." +@@ -1154,14 +1235,12 @@ msgstr "ਰੰਗ" + #: panels/color/gnome-color-panel.desktop.in.in:4 + msgid "" + "Calibrate the color of your devices, such as displays, cameras or printers" +-msgstr "" +-"ਆਪਣੇ ਜੰਤਰਾਂ, ਜਿਵੇਂ ਕਿ ਡਿਸਪਲੇਅ, ਕੈਮਰੇ ਜਾਂ ਪਰਿੰਟਰਾਂ ਦੇ ਰੰਗ ਨੂੰ ਕੈਲੀਬਰੇਟ ਕਰੋ" ++msgstr "ਆਪਣੇ ਜੰਤਰਾਂ, ਜਿਵੇਂ ਕਿ ਡਿਸਪਲੇਅ, ਕੈਮਰੇ ਜਾਂ ਪਰਿੰਟਰਾਂ ਦੇ ਰੰਗ ਨੂੰ ਕੈਲੀਬਰੇਟ ਕਰੋ" + + #. Translators: Search terms to find the Color panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/color/gnome-color-panel.desktop.in.in:19 + msgid "Color;ICC;Profile;Calibrate;Printer;Display;" +-msgstr "" +-"ਰੰਗ;Color;ICC;Profile;Calibrate;ਪ੍ਰਿੰਟਰ;ਪਰਿੰਟਰ;Printer;Display;ਡਿਸਪਲੇਅ;" ++msgstr "ਰੰਗ;Color;ICC;Profile;Calibrate;ਪ੍ਰਿੰਟਰ;ਪਰਿੰਟਰ;Printer;Display;ਡਿਸਪਲੇਅ;" + + #: panels/common/cc-common-language.c:300 + msgid "Other…" +@@ -1541,8 +1620,7 @@ msgid "" + "Sending reports of technical problems helps us improve %s. Reports are sent " + "anonymously and are scrubbed of personal data. %s" + msgstr "" +-"ਤਕਨੀਕੀ ਸਮੱਸਿਆਵਾਂ ਬਾਰੇ ਰਿਪੋਰਟਾਂ ਭੇਜਣ ਨਾਲ ਸਾਨੂੰ %s ਸੁਧਾਰਨ ਲਈ ਮਦਦ ਮਿਲਦੀ ਹੈ।" +-" ਰਿਪੋਰਟ ਅਣਪਛਾਤੇ " ++"ਤਕਨੀਕੀ ਸਮੱਸਿਆਵਾਂ ਬਾਰੇ ਰਿਪੋਰਟਾਂ ਭੇਜਣ ਨਾਲ ਸਾਨੂੰ %s ਸੁਧਾਰਨ ਲਈ ਮਦਦ ਮਿਲਦੀ ਹੈ। ਰਿਪੋਰਟ ਅਣਪਛਾਤੇ " + "ਰੂਪ ਵਿੱਚ ਭੇਜੀਆਂ ਜਾਂਦੀਆਂ ਹਨ ਅਤੇ ਨਿੱਜੀ ਡਾਟੇ ਨੂੰ ਹਟਾਇਆ ਜਾਂਦਾ ਹੈ। %s" + + #: panels/diagnostics/cc-diagnostics-panel.ui:28 +@@ -1574,8 +1652,7 @@ msgid "" + "screen;lock;diagnostics;crash;private;recent;temporary;tmp;index;name;" + "network;identity;privacy;" + msgstr "" +-"ਸਕਰੀਨ;ਲਾਕ;ਜਾਂਚ;ਪੜਤਾਲ;ਪ੍ਰਾਈਵੇਟ;ਨਿੱਜੀ;ਆਰਜ਼ੀ;ਇੰਡੈਕਸ;ਨਾਂ;ਨੈੱਟਵਰਕ;ਪਛਾਣ;ਕਰੈਸ਼;ਤਾਜ਼ਾ;ਪਰਦ" +-"ੇਦਾਰੀ;" ++"ਸਕਰੀਨ;ਲਾਕ;ਜਾਂਚ;ਪੜਤਾਲ;ਪ੍ਰਾਈਵੇਟ;ਨਿੱਜੀ;ਆਰਜ਼ੀ;ਇੰਡੈਕਸ;ਨਾਂ;ਨੈੱਟਵਰਕ;ਪਛਾਣ;ਕਰੈਸ਼;ਤਾਜ਼ਾ;ਪਰਦੇਦਾਰੀ;" + + #: panels/display/cc-display-panel.c:1014 + #: panels/network/connection-editor/connection-editor.ui:27 +@@ -1624,8 +1701,7 @@ msgid "" + "Drag displays to match your physical display setup. Select a display to " + "change its settings." + msgstr "" +-"ਡਿਸਪਲੇਆਂ ਨੂੰ ਆਪਣੇ ਅਸਲ ਡਿਸਪਲੇਅ ਬਨਾਵਟ ਨਾਲ ਮਿਲਾਉਣ ਲਈ ਉਹਨਾਂ ਨੂੰ ਖਿਸਕਾਓ। ਡਿਸਪਲੇਅ" +-" ਦੀਆਂ ਸੈਟਿੰਗਾਂ " ++"ਡਿਸਪਲੇਆਂ ਨੂੰ ਆਪਣੇ ਅਸਲ ਡਿਸਪਲੇਅ ਬਨਾਵਟ ਨਾਲ ਮਿਲਾਉਣ ਲਈ ਉਹਨਾਂ ਨੂੰ ਖਿਸਕਾਓ। ਡਿਸਪਲੇਅ ਦੀਆਂ ਸੈਟਿੰਗਾਂ " + "ਨੂੰ ਬਦਲਣ ਲਈ ਉਸ ਨੂੰ ਚੁਣੋ।" + + #: panels/display/cc-display-panel.ui:250 +@@ -1722,8 +1798,7 @@ msgid "" + "Night light makes the screen color warmer. This can help to prevent eye " + "strain and sleeplessness." + msgstr "" +-"ਰਾਤ ਦੀ ਰੋਸ਼ਨੀ ਸਕਰੀਨ ਰੰਗਾਂ ਨੂੰ ਨਿੱਘਾ ਬਣਾਉਂਦੀ ਹੈ। ਇਸ ਅੱਖਾਂ ਉੱਤੇ ਜ਼ੋਰ ਪੈਣ ਅਤੇ ਨੀਂਦ" +-" ਟਲਣ ਤੋਂ ਰੋਕਣ ਲਈ " ++"ਰਾਤ ਦੀ ਰੋਸ਼ਨੀ ਸਕਰੀਨ ਰੰਗਾਂ ਨੂੰ ਨਿੱਘਾ ਬਣਾਉਂਦੀ ਹੈ। ਇਸ ਅੱਖਾਂ ਉੱਤੇ ਜ਼ੋਰ ਪੈਣ ਅਤੇ ਨੀਂਦ ਟਲਣ ਤੋਂ ਰੋਕਣ ਲਈ " + "ਮਦਦ ਕਰਦੀ ਹੈ।" + + #: panels/display/cc-night-light-page.ui:127 +@@ -1792,10 +1867,8 @@ msgid "" + "Panel;Projector;xrandr;Screen;Resolution;Refresh;Monitor;Night;Light;Blue;" + "redshift;color;sunset;sunrise;" + msgstr "" +-"ਪੈਨਲ;ਪਰੋਜੈਕਟਰ;xrandr;ਸਕਰੀਨ;ਰੈਜ਼ੋਲੂਸ਼ਨ;ਤਾਜ਼ਾ;ਮਾਨੀਟਰ;ਰਾਤ;ਰਾਤਰੀ;ਰੌਸ਼ਨੀ;ਪ੍ਰਕਾਸ਼;ਨੀਲਾ" +-";ਲਾਲ-" +-"ਪਰਿਵਰਤਨ;ਸੂਰਜ-ਚੜ੍ਹਨਾ;ਸੂਰਜ-ਲਹਿਣਾ;ਸੂਰਜ-ਡੁੱਬਣਾ;ਹਨੇਰਾ;ਰਾਤ-ਵੇਲਾ;ਚਾਨਣ;ਸਰਘੀ;ਤਰਕਾਲਾਂ;ਆਥ" +-"ਣ;" ++"ਪੈਨਲ;ਪਰੋਜੈਕਟਰ;xrandr;ਸਕਰੀਨ;ਰੈਜ਼ੋਲੂਸ਼ਨ;ਤਾਜ਼ਾ;ਮਾਨੀਟਰ;ਰਾਤ;ਰਾਤਰੀ;ਰੌਸ਼ਨੀ;ਪ੍ਰਕਾਸ਼;ਨੀਲਾ;ਲਾਲ-" ++"ਪਰਿਵਰਤਨ;ਸੂਰਜ-ਚੜ੍ਹਨਾ;ਸੂਰਜ-ਲਹਿਣਾ;ਸੂਰਜ-ਡੁੱਬਣਾ;ਹਨੇਰਾ;ਰਾਤ-ਵੇਲਾ;ਚਾਨਣ;ਸਰਘੀ;ਤਰਕਾਲਾਂ;ਆਥਣ;" + + #: panels/info-overview/cc-info-overview-panel.c:417 + #: panels/info-overview/cc-info-overview-panel.c:432 +@@ -1902,8 +1975,7 @@ msgid "" + "The device name is used to identify this device when it is viewed over the " + "network, or when pairing Bluetooth devices." + msgstr "" +-"ਡਿਵਾਈਸ ਨਾਂ ਨੂੰ ਇਸ ਡਿਵਾਈਸ ਦੀ ਪਛਾਣ ਕਰਨ ਲਈ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ, ਜਦੋਂ ਇਸ ਨੂੰ ਨੈੱਟਵਰਕ" +-" ਉੱਤੇ ਵੇਖਦੇ ਹੋ ਜਾਂ " ++"ਡਿਵਾਈਸ ਨਾਂ ਨੂੰ ਇਸ ਡਿਵਾਈਸ ਦੀ ਪਛਾਣ ਕਰਨ ਲਈ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ, ਜਦੋਂ ਇਸ ਨੂੰ ਨੈੱਟਵਰਕ ਉੱਤੇ ਵੇਖਦੇ ਹੋ ਜਾਂ " + "ਜਦੋਂ ਬਲੂਟੁੱਥ ਡਿਵਾਈਸਾਂ ਨਾਲ ਪੇਅਰ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।" + + #: panels/info-overview/cc-info-overview-panel.ui:234 +@@ -1928,8 +2000,7 @@ msgid "" + "device;system;information;hostname;memory;processor;version;default;" + "application;preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;" + msgstr "" +-"ਡਿਵਾਈਸ;ਡੀਵਾਈਸ;;ਜੰਤਰ;ਸਿਸਟਮ;ਜਾਣਕਾਰੀ;ਮੈਮੋਰੀ;ਪਰੋਸੈਸਰ;ਵਰਜ਼ਨ;ਪ੍ਰੋਸੈਸਰ;ਡਿਫਾਲਟ;ਐਪਲੀਕੇਸ" +-"਼ਨ;ਯੂਐਸਬੀ;" ++"ਡਿਵਾਈਸ;ਡੀਵਾਈਸ;;ਜੰਤਰ;ਸਿਸਟਮ;ਜਾਣਕਾਰੀ;ਮੈਮੋਰੀ;ਪਰੋਸੈਸਰ;ਵਰਜ਼ਨ;ਪ੍ਰੋਸੈਸਰ;ਡਿਫਾਲਟ;ਐਪਲੀਕੇਸ਼ਨ;ਯੂਐਸਬੀ;" + "ਡੀਵੀਡੀ;ਸੀਡੀ;ਆਡੀਓ;ਔਡੀਓ;ਵੀਡੀਓ;ਵਿਡੀਓ;ਡਿਸਕ;ਆਟੋਰਨ;ਮੀਡੀਆ;ਹਟਾਉਣਯੋਗ;ਯੰਤਰ;ਹੋਸਟਨੇਮ;" + + #: panels/keyboard/00-multimedia.xml.in:2 +@@ -2165,8 +2236,7 @@ msgid "" + "The alternate characters key can be used to enter additional characters. " + "These are sometimes printed as a third-option on your keyboard." + msgstr "" +-"ਬਦਲਵੀਂ ਅੱਖਰ ਸਵਿੱਚ ਨੂੰ ਹੋਰ ਅੱਖਰ ਦੇਣ ਲਈ ਵਰਤਿਆ ਜਾ ਸਕਦਾ ਹੈ। ਇਹਨਾਂ ਨੂੰ ਕਈ ਵਾਰ" +-" ਤੁਹਾਡੇ ਕੀਬੋਰਡ ਉੱਤੇ " ++"ਬਦਲਵੀਂ ਅੱਖਰ ਸਵਿੱਚ ਨੂੰ ਹੋਰ ਅੱਖਰ ਦੇਣ ਲਈ ਵਰਤਿਆ ਜਾ ਸਕਦਾ ਹੈ। ਇਹਨਾਂ ਨੂੰ ਕਈ ਵਾਰ ਤੁਹਾਡੇ ਕੀਬੋਰਡ ਉੱਤੇ " + "ਤੀਜੀ-ਚੋਣ ਵਜੋਂ ਛਾਪਿਆ ਗਿਆ ਹੁੰਦਾ ਹੈ।" + + #: panels/keyboard/cc-keyboard-panel.c:74 +@@ -2218,10 +2288,9 @@ msgid "" + "followed by C and o will enter ©, a followed by " + "' will enter á." + msgstr "" +-"ਮਿਸ਼ਰਿਤ ਸਵਿੱਚ ਕਈ ਕਿਸਮ ਦੇ ਵੱਖ-ਵੱਖ ਅੱਖਰ ਦੇਣ ਲਈ ਕੰਮ ਆਉਂਦੀ ਹੈ। ਇਹ ਵਰਤਣ ਲਈ" +-"ਤਦ ਲੜੀਵਾਰ ਅੱਖਰ ਦੇਣ ਲਈ ਬਣਾਓ ਨੂੰ ਦਬਾਓ। ਮਿਸਾਲ ਲਈ C ਅਤੇ o " +-"ਦੇ ਬਾਅਦ ਬਣਾਓ ਨਾਲ © ਪਵੇਗਾ, a ਤੇ ' ਦੇ ਬਾਅਦ ਬਣਾਓ " +-"ਦਬਾਉਣ ਨਾਲ á ਪਵੇਗਾ।" ++"ਮਿਸ਼ਰਿਤ ਸਵਿੱਚ ਕਈ ਕਿਸਮ ਦੇ ਵੱਖ-ਵੱਖ ਅੱਖਰ ਦੇਣ ਲਈ ਕੰਮ ਆਉਂਦੀ ਹੈ। ਇਹ ਵਰਤਣ ਲਈਤਦ ਲੜੀਵਾਰ ਅੱਖਰ ਦੇਣ " ++"ਲਈ ਬਣਾਓ ਨੂੰ ਦਬਾਓ। ਮਿਸਾਲ ਲਈ C ਅਤੇ o ਦੇ ਬਾਅਦ ਬਣਾਓ ਨਾਲ © ਪਵੇਗਾ, " ++"a ਤੇ ' ਦੇ ਬਾਅਦ ਬਣਾਓ ਦਬਾਉਣ ਨਾਲ á ਪਵੇਗਾ।" + + #: panels/keyboard/cc-keyboard-panel.c:98 + #| msgid "Caps" +@@ -2302,8 +2371,7 @@ msgid "" + "Resetting the shortcuts may affect your custom shortcuts. This cannot be " + "undone." + msgstr "" +-"ਸ਼ਾਰਟਕੱਟਾਂ ਨੂੰ ਮੁੜ-ਸੈੱਟ ਕਰਨ ਨਾਲ ਤੁਹਾਡੇ ਕਸਟਮ ਸ਼ਾਰਟਕੱਟਾਂ ਉੱਤੇ ਅਸਰ ਪੈ ਸਕਦਾ ਹੈ। ਇਸ" +-" ਨੂੰ ਵਾਪਸ ਨਹੀਂ " ++"ਸ਼ਾਰਟਕੱਟਾਂ ਨੂੰ ਮੁੜ-ਸੈੱਟ ਕਰਨ ਨਾਲ ਤੁਹਾਡੇ ਕਸਟਮ ਸ਼ਾਰਟਕੱਟਾਂ ਉੱਤੇ ਅਸਰ ਪੈ ਸਕਦਾ ਹੈ। ਇਸ ਨੂੰ ਵਾਪਸ ਨਹੀਂ " + "ਪਰਤਾਇਆ ਜਾ ਸਕਦਾ ਹੈ।" + + #: panels/keyboard/cc-keyboard-shortcut-dialog.c:433 +@@ -2352,9 +2420,7 @@ msgstr "ਕੋਈ ਕੀ-ਬੋਰਡ ਸ਼ਾਰਟਕੱਟ ਨਹੀਂ ਲੱ + #: panels/keyboard/cc-keyboard-shortcut-editor.c:391 + #, c-format + msgid "%s is already being used for %s. If you replace it, %s will be disabled" +-msgstr "" +-"%s ਨੂੰ ਪਹਿਲਾਂ ਹੀ %s ਨੂੰ ਵਰਤ ਰਿਹਾ ਹੈ। ਜੇ ਤੁਸੀਂ ਇਸ ਨੂੰ ਬਦਲਿਆ ਤਾਂ %s ਅਸਮਰੱਥ ਹੋ" +-" ਜਾਵੇਗਾ।" ++msgstr "%s ਨੂੰ ਪਹਿਲਾਂ ਹੀ %s ਨੂੰ ਵਰਤ ਰਿਹਾ ਹੈ। ਜੇ ਤੁਸੀਂ ਇਸ ਨੂੰ ਬਦਲਿਆ ਤਾਂ %s ਅਸਮਰੱਥ ਹੋ ਜਾਵੇਗਾ।" + + #: panels/keyboard/cc-keyboard-shortcut-editor.c:535 + msgid "Enter the new shortcut" +@@ -2431,8 +2497,7 @@ msgstr "ਕੀਬੋਰਡ ਸ਼ਾਰਟਕੱਟ ਵੇਖੋ ਤੇ ਬਦਲ + #: panels/keyboard/gnome-keyboard-panel.desktop.in.in:19 + msgid "" + "Shortcut;Workspace;Window;Resize;Zoom;Contrast;Input;Source;Lock;Volume;" +-msgstr "" +-"ਸ਼ਾਰਟਕੱਟ;ਵਰਕਸਪੇਸ;ਵਿੰਡੋ;ਮੁੜ-ਆਕਾਰ;ਰੀਸਾਈਜ਼;ਜ਼ੂਮ;ਕਨਟਰਾਸਟ;ਇਨਪੁਟ;ਸਰੋਤ;ਲਾਕ;ਵਾਲੀਅਮ;" ++msgstr "ਸ਼ਾਰਟਕੱਟ;ਵਰਕਸਪੇਸ;ਵਿੰਡੋ;ਮੁੜ-ਆਕਾਰ;ਰੀਸਾਈਜ਼;ਜ਼ੂਮ;ਕਨਟਰਾਸਟ;ਇਨਪੁਟ;ਸਰੋਤ;ਲਾਕ;ਵਾਲੀਅਮ;" + + #: panels/location/cc-location-panel.ui:31 + msgid "Location services turned off" +@@ -2447,8 +2512,7 @@ msgid "" + "Location services allow applications to know your location. Using Wi-Fi and " + "mobile broadband increases accuracy." + msgstr "" +-"ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਨੂੰ ਤੁਹਾਡੇ ਟਿਕਾਣੇ ਦਾ ਪਤਾ ਲਗਾਉਣ ਦੀ ਇਜਾਜ਼ਤ ਦਿੰਦੀਆਂ ਹਨ।" +-" ਸਟੀਕਤਾ " ++"ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਨੂੰ ਤੁਹਾਡੇ ਟਿਕਾਣੇ ਦਾ ਪਤਾ ਲਗਾਉਣ ਦੀ ਇਜਾਜ਼ਤ ਦਿੰਦੀਆਂ ਹਨ। ਸਟੀਕਤਾ " + "ਵਧਾਉਣ ਲਈ Wi-Fi ਅਤੇ ਮੋਬਾਈਲ ਬਰਾਂਡਬੈਂਡ ਨੂੰ ਵਰਤੋਂ।" + + #: panels/location/cc-location-panel.ui:81 +@@ -2480,8 +2544,8 @@ msgid "" + "Automatically locking the screen prevents others from accessing the computer " + "while you're away." + msgstr "" +-"ਆਪਣੇ-ਆਪ ਸਕਰੀਨ ਨੂੰ ਲਾਕ ਕਰਨ ਨਾਲ ਤੁਹਾਡੇ ਦੂਰ ਚਲੇ ਜਾਣ ਉੱਤੇ ਹੋਰਾਂ ਵਲੋਂ ਕੰਪਿਊਟਰ ਨੂੰ" +-" ਵਰਤਣ ਤੋਂ ਰੋਕਿਆ ਜਾਂਦਾ ਹੈ।" ++"ਆਪਣੇ-ਆਪ ਸਕਰੀਨ ਨੂੰ ਲਾਕ ਕਰਨ ਨਾਲ ਤੁਹਾਡੇ ਦੂਰ ਚਲੇ ਜਾਣ ਉੱਤੇ ਹੋਰਾਂ ਵਲੋਂ ਕੰਪਿਊਟਰ ਨੂੰ ਵਰਤਣ ਤੋਂ ਰੋਕਿਆ " ++"ਜਾਂਦਾ ਹੈ।" + + #: panels/lock/cc-lock-panel.ui:44 + msgid "Blank Screen Delay" +@@ -2515,9 +2579,7 @@ msgstr "ਨਵੇਂ _USB ਡਿਵਾਈਸਾਂ ਉੱਤੇ ਰੋਕ" + msgid "" + "Prevent new USB devices from interacting with the system when the screen is " + "locked." +-msgstr "" +-"ਜਦੋਂ ਸਕਰੀਨ ਲਾਕ ਹੋਵੇ ਤਾਂ ਨਵੇਂ USB ਡਿਵਾਈਸਾਂ ਨੂੰ ਸਿਸਟਮ ਨਾਲ ਤਾਲਮੇਲ ਕਰਨ ਤੋਂ ਰੋਕਦਾ" +-" ਹੈ।" ++msgstr "ਜਦੋਂ ਸਕਰੀਨ ਲਾਕ ਹੋਵੇ ਤਾਂ ਨਵੇਂ USB ਡਿਵਾਈਸਾਂ ਨੂੰ ਸਿਸਟਮ ਨਾਲ ਤਾਲਮੇਲ ਕਰਨ ਤੋਂ ਰੋਕਦਾ ਹੈ।" + + #. Translators: Option for "Lock screen after blank for" in "Screen Lock" dialog. + #: panels/lock/cc-lock-panel.ui:166 +@@ -2650,8 +2712,7 @@ msgid "" + "Disabling the microphone may cause some applications to not function " + "properly." + msgstr "" +-"ਮਾਈਕਰੋਫੋਨ ਦੀ ਵਰਤੋਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਨੂੰ ਆਡੀਓ ਰਿਕਾਰਡ ਕਰਨ ਤੇ ਸੁਣਨ ਲਈ ਸਹਿਮਤੀ ਦਿੰਦੀ ਹੈ।" +-" ਮਾਈਕਰੋਫੋਨ ਨੂੰ " ++"ਮਾਈਕਰੋਫੋਨ ਦੀ ਵਰਤੋਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਨੂੰ ਆਡੀਓ ਰਿਕਾਰਡ ਕਰਨ ਤੇ ਸੁਣਨ ਲਈ ਸਹਿਮਤੀ ਦਿੰਦੀ ਹੈ। ਮਾਈਕਰੋਫੋਨ ਨੂੰ " + "ਅਸਮਰੱਥ ਕਰਨ ਨਾਲ ਕੁਝ ਐਪਲੀਕੇਸ਼ਨਾਂ ਠੀਕ ਤਰ੍ਹਾਂ ਕੰਮ ਨਹੀਂ ਕਰ ਸਕਦੀਆਂ।" + + #: panels/microphone/cc-microphone-panel.ui:85 +@@ -2666,11 +2727,6 @@ msgstr "ਮਾਈਕਰੋਫ਼ੋਨ ਪਹੁੰਚ ਲਈ ਕੋਈ ਐਪ + msgid "Protect your conversations" + msgstr "ਤਹਾਡੀਆਂ ਗੱਲਾਂਬਾਤਾਂ ਸੁਰੱਖਿਅਤ ਕਰੋ" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "ਆਮ" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "ਪ੍ਰਾਇਮਰੀ ਬਟਨ" +@@ -2772,15 +2828,13 @@ msgstr "ਮਾਊਸ ਤੇ ਟੱਚਪੈਚ" + #: panels/mouse/gnome-mouse-panel.desktop.in.in:4 + msgid "" + "Change your mouse or touchpad sensitivity and select right or left-handed" +-msgstr "" +-"ਆਪਣੇ ਮਾਊਸ ਜਾਂ ਟੱਚਪੈਡ ਦੀ ਸੰਵੇਦਨਸ਼ੀਲਤਾ ਬਦਲੋ ਅਤੇ ਸੱਜੇ ਜਾਂ ਖੱਬੇ-ਹੱਥ ਦੀ ਚੋਣ ਕਰੋ" ++msgstr "ਆਪਣੇ ਮਾਊਸ ਜਾਂ ਟੱਚਪੈਡ ਦੀ ਸੰਵੇਦਨਸ਼ੀਲਤਾ ਬਦਲੋ ਅਤੇ ਸੱਜੇ ਜਾਂ ਖੱਬੇ-ਹੱਥ ਦੀ ਚੋਣ ਕਰੋ" + + #. Translators: Search terms to find the Mouse and Touchpad panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/mouse/gnome-mouse-panel.desktop.in.in:19 + msgid "Trackpad;Pointer;Click;Tap;Double;Button;Trackball;Scroll;" + msgstr "" +-"Trackpad;Pointer;Click;Tap;Double;Button;Trackball;ਟਰੈਕਪੈਂਡ;ਪੁਆਇੰਟਰ;ਕਲਿੱਕ;ਟੈਪ;" +-"ਡਬਲ;" ++"Trackpad;Pointer;Click;Tap;Double;Button;Trackball;ਟਰੈਕਪੈਂਡ;ਪੁਆਇੰਟਰ;ਕਲਿੱਕ;ਟੈਪ;ਡਬਲ;" + "ਬਟਨ;ਟਰੈਕਬਾਲ;Scroll;" + + #: panels/network/cc-network-panel.c:661 panels/network/cc-wifi-panel.ui:307 +@@ -2851,8 +2905,7 @@ msgid "" + "Turning on the hotspot will disconnect from %s, and it will not be possible " + "to access the internet through Wi-Fi." + msgstr "" +-"ਹਾਟਸਪਾਟ ਨੂੰ ਚਾਲੂ ਕਰਨ ਨਾਲ %s ਤੋਂ ਡਿਸ-ਕਨੈਕਟ ਕੀਤਾ ਜਾਵੇਗਾ ਅਤੇ Wi-Fi ਰਾਹੀਂ" +-" ਇੰਟਰਨੈੱਟ ਨਾਲ ਪਹੁੰਚ " ++"ਹਾਟਸਪਾਟ ਨੂੰ ਚਾਲੂ ਕਰਨ ਨਾਲ %s ਤੋਂ ਡਿਸ-ਕਨੈਕਟ ਕੀਤਾ ਜਾਵੇਗਾ ਅਤੇ Wi-Fi ਰਾਹੀਂ ਇੰਟਰਨੈੱਟ ਨਾਲ ਪਹੁੰਚ " + "ਸੰਭਵ ਨਹੀਂ ਹੋਵੇਗੀ।" + + #: panels/network/cc-wifi-hotspot-dialog.c:265 +@@ -2869,10 +2922,8 @@ msgid "" + "Wi-Fi network that they can connect to. To do this, you must have an " + "internet connection through a source other than Wi-Fi." + msgstr "" +-"Wi-Fi ਹਾਟਸਪਾਟ ਹੋਰਾਂ ਨੂੰ ਤੁਹਾਡੇ ਇੰਟਰਨੈੱਟ ਕਨੈਕਸ਼ਨ ਨੂੰ ਸਾਂਝਾ ਕਰਨ ਦਿੰਦਾ ਹੈ, ਜੋ ਕਿ" +-" Wi-Fi ਨੈੱਟਵਰਕ ਬਣਾ " +-"ਕੇ ਹੁੰਦਾ ਹੈ, ਜਿਸ ਨਾਲ ਉਹ ਕਨੈਕਟ ਹੋ ਸਕਦੇ ਹਨ। ਇਹ ਕਰਨ ਲਈ ਤੁਹਾਨੂੰ Wi-Fi ਤੋਂ ਬਿਨਾਂ" +-" ਕਿਸੇ ਹੋਰ ਸਰੋਤ " ++"Wi-Fi ਹਾਟਸਪਾਟ ਹੋਰਾਂ ਨੂੰ ਤੁਹਾਡੇ ਇੰਟਰਨੈੱਟ ਕਨੈਕਸ਼ਨ ਨੂੰ ਸਾਂਝਾ ਕਰਨ ਦਿੰਦਾ ਹੈ, ਜੋ ਕਿ Wi-Fi ਨੈੱਟਵਰਕ ਬਣਾ " ++"ਕੇ ਹੁੰਦਾ ਹੈ, ਜਿਸ ਨਾਲ ਉਹ ਕਨੈਕਟ ਹੋ ਸਕਦੇ ਹਨ। ਇਹ ਕਰਨ ਲਈ ਤੁਹਾਨੂੰ Wi-Fi ਤੋਂ ਬਿਨਾਂ ਕਿਸੇ ਹੋਰ ਸਰੋਤ " + "ਰਾਹੀਂ ਇੰਟਰਨੈੱਟ ਨਾਲ ਕਨੈਕਟ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ।" + + #: panels/network/cc-wifi-hotspot-dialog.ui:44 +@@ -2992,10 +3043,8 @@ msgid "" + "network device this connection is activated on. This feature is known as MAC " + "cloning or spoofing. Example: 00:11:22:33:44:55" + msgstr "" +-"ਇੱਥੇ ਦਿੱਤਾ ਮੈਕ (MAC) ਐਡਰੈੱਸ ਨੈੱਟਵਰਕ ਡਿਵਾਈਸ ਲਈ ਹਾਰਡਵੇਅਰ ਐਡਰੈੱਸ ਵਜੋਂ ਵਰਤਿਆ" +-" ਜਾਵੇਗਾ, ਜਿਸ ਲਈ ਇਸ " +-"ਕਨੈਕਸ਼ਨ ਐਕਟੀਵੇਟ ਕੀਤਾ ਗਿਆ ਹੈ। ਇਹ ਫੀਚਰ ਨੂੰ ਮੈਕ ਕਲੋਨਿੰਗ ਜਾਂ ਸਪੂਫਿੰਗ (spoofing)" +-" ਕਹਿੰਦੇ ਹਨ। " ++"ਇੱਥੇ ਦਿੱਤਾ ਮੈਕ (MAC) ਐਡਰੈੱਸ ਨੈੱਟਵਰਕ ਡਿਵਾਈਸ ਲਈ ਹਾਰਡਵੇਅਰ ਐਡਰੈੱਸ ਵਜੋਂ ਵਰਤਿਆ ਜਾਵੇਗਾ, ਜਿਸ ਲਈ ਇਸ " ++"ਕਨੈਕਸ਼ਨ ਐਕਟੀਵੇਟ ਕੀਤਾ ਗਿਆ ਹੈ। ਇਹ ਫੀਚਰ ਨੂੰ ਮੈਕ ਕਲੋਨਿੰਗ ਜਾਂ ਸਪੂਫਿੰਗ (spoofing) ਕਹਿੰਦੇ ਹਨ। " + "ਜਿਵੇਂ: 00:11:22:33:44:55" + + #: panels/network/connection-editor/ce-page.c:399 +@@ -3498,8 +3547,7 @@ msgstr "ਕੰਟਰੋਲ ਕਰੋ ਕਿ ਇੰਟਰਨੈੱਟ ਨਾਲ + #. Translators: Search terms to find the Network panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/network/gnome-network-panel.desktop.in.in:19 + msgid "Network;IP;LAN;Proxy;WAN;Broadband;Modem;Bluetooth;vpn;DNS;" +-msgstr "" +-"ਨੈੱਟਵਰਕ;ਆਈਪੀ;ਬਰਾਡਬੈਂਡ;ਮਾਡਮ;ਬਲੂਟੁੱਥ;ਬਲੂਟੁੱਥ;ਵੀਪੀਐਨ;ਪਰਾਕਸੀ;ਵੈਨ;ਮੌਡਮ;ਡੀਐਨਐਸ;" ++msgstr "ਨੈੱਟਵਰਕ;ਆਈਪੀ;ਬਰਾਡਬੈਂਡ;ਮਾਡਮ;ਬਲੂਟੁੱਥ;ਬਲੂਟੁੱਥ;ਵੀਪੀਐਨ;ਪਰਾਕਸੀ;ਵੈਨ;ਮੌਡਮ;ਡੀਐਨਐਸ;" + + #: panels/network/gnome-wifi-panel.desktop.in.in:4 + msgid "Control how you connect to Wi-Fi networks" +@@ -3545,8 +3593,7 @@ msgid "" + "Network details for the selected networks, including passwords and any " + "custom configuration will be lost." + msgstr "" +-"ਚੁਣੇ ਗਏ ਨੈੱਟਵਰਕਾਂ ਲਈ ਨੈੱਟਵਰਕ ਵੇਰਵਾ, ਜਿਸ ਵਿੱਚ ਪਾਸਵਰਡ ਅਤੇ ਹੋਰ ਪਸੰਦੀਦਾ ਸੰਰਚਨਾ" +-" ਦਿੱਤੀ ਸੀ, ਖਤਮ ਹੋ " ++"ਚੁਣੇ ਗਏ ਨੈੱਟਵਰਕਾਂ ਲਈ ਨੈੱਟਵਰਕ ਵੇਰਵਾ, ਜਿਸ ਵਿੱਚ ਪਾਸਵਰਡ ਅਤੇ ਹੋਰ ਪਸੰਦੀਦਾ ਸੰਰਚਨਾ ਦਿੱਤੀ ਸੀ, ਖਤਮ ਹੋ " + "ਜਾਵੇਗਾ।" + + #: panels/network/net-device-wifi.c:855 +@@ -3594,8 +3641,7 @@ msgstr "ਬੰਦ" + #: panels/network/net-proxy.c:112 + msgid "" + "Web Proxy Autodiscovery is used when a Configuration URL is not provided." +-msgstr "" +-"ਵੈੱਬ ਪਰਾਕਸੀ ਆਪੇ-ਆਪ ਖੋਜ ਵਰਤੀ ਜਾਂਦੀ ਹੈ, ਜਦੋਂ ਸੰਰਚਨਾ URL ਨਾ ਦਿੱਤਾ ਗਿਆ ਹੋਵੇ।" ++msgstr "ਵੈੱਬ ਪਰਾਕਸੀ ਆਪੇ-ਆਪ ਖੋਜ ਵਰਤੀ ਜਾਂਦੀ ਹੈ, ਜਦੋਂ ਸੰਰਚਨਾ URL ਨਾ ਦਿੱਤਾ ਗਿਆ ਹੋਵੇ।" + + #. TRANSLATORS: WPAD is bad: if you enable it on an untrusted + #. * network, then anyone else on that network can tell your +@@ -4166,8 +4212,7 @@ msgid "" + "\n" + "(You can password-protect your private key with openssl)" + msgstr "" +-"ਚੁਣੀ ਗਈ ਪ੍ਰਾਈਵੇਟ ਕੁੰਜੀ ਪਾਸਵਰਡ ਨਾਲ ਸੁਰੱਖਿਅਤ ਨਹੀਂ ਜਾਪਦੀ ਹੈ। ਇਹ ਤੁਹਾਡੀ ਸੁਰੱਖਿਅਤ" +-" ਸਨਦ ਨੂੰ ਖਤਰਾ " ++"ਚੁਣੀ ਗਈ ਪ੍ਰਾਈਵੇਟ ਕੁੰਜੀ ਪਾਸਵਰਡ ਨਾਲ ਸੁਰੱਖਿਅਤ ਨਹੀਂ ਜਾਪਦੀ ਹੈ। ਇਹ ਤੁਹਾਡੀ ਸੁਰੱਖਿਅਤ ਸਨਦ ਨੂੰ ਖਤਰਾ " + "ਪੈਦਾ ਕਰ ਸਕਦੀ ਹੈ। ਪਾਸਵਰਡ ਨਾਲ ਸੁਰੱਖਿਅਤ ਪ੍ਰਾਈਵੇਟ ਕੁੰਜੀ ਚੁਣੋ ਜੀ।\n" + "\n" + "(ਤੁਸੀਂ openssl ਨਾਲ ਪ੍ਰਾਈਵੇਟ ਕੁੰਜੀ ਪਾਸਵਰਡ ਸੁਰੱਖਿਅਤ ਕਰ ਸਕਦੇ ਹੋ)" +@@ -4301,8 +4346,7 @@ msgid "" + "invalid wep-key: wrong key length %zu. A key must be either of length 5/13 " + "(ascii) or 10/26 (hex)" + msgstr "" +-"ਅਵੈਧ wep-key: ਗ਼ਲਤ %zu ਕੁੰਜੀ ਲੰਬਾਈ। ਕੁੰਜੀ ਦੀ ਲੰਬਾਈ ਜਾਂ ਤਾਂ 5/13 (ascii) ਜਾਂ" +-" 10/26 " ++"ਅਵੈਧ wep-key: ਗ਼ਲਤ %zu ਕੁੰਜੀ ਲੰਬਾਈ। ਕੁੰਜੀ ਦੀ ਲੰਬਾਈ ਜਾਂ ਤਾਂ 5/13 (ascii) ਜਾਂ 10/26 " + "(ਹੈਕਸਾ) ਹੋ ਸਕਦੇ ਹਨ" + + #: panels/network/wireless-security/ws-wep-key.c:144 +@@ -4343,8 +4387,7 @@ msgid "" + "invalid wpa-psk: invalid key-length %zu. Must be [8,63] bytes or 64 hex " + "digits" + msgstr "" +-"ਅਵੈਧ wpa-psk: ਕੁੰਜੀ-ਲੰਬਾਈ %zu ਅਵੈਧ ਹੈ। ਜਾਂ ਤਾਂ [8,63] ਬਾਈਟ ਜਾਂ 64 ਹੈਕਸਾ-ਅੰਕ" +-" ਹੋਣੀ ਚਾਹੀਦੀ " ++"ਅਵੈਧ wpa-psk: ਕੁੰਜੀ-ਲੰਬਾਈ %zu ਅਵੈਧ ਹੈ। ਜਾਂ ਤਾਂ [8,63] ਬਾਈਟ ਜਾਂ 64 ਹੈਕਸਾ-ਅੰਕ ਹੋਣੀ ਚਾਹੀਦੀ " + "ਹੈ।" + + #: panels/network/wireless-security/ws-wpa-psk.c:86 +@@ -4373,8 +4416,7 @@ msgid "" + "Notifications will continue to appear in the notification list when popups " + "are disabled." + msgstr "" +-"ਜਦੋਂ ਪੋਪਅੱਪ ਅਸਮਰੱਥ ਕੀਤੇ ਜਾਂਦੇ ਹਨ ਤਾਂ ਨੋਟੀਫਿਕੇਸ਼ਨ ਸੂਚੀ ਵਿੱਚ ਨੋਟੀਫਿਕੇਸ਼ਨ ਦਿਖਾਈ" +-" ਦੇਣਾ ਜਾਰੀ ਰੱਖਣਗੇ।" ++"ਜਦੋਂ ਪੋਪਅੱਪ ਅਸਮਰੱਥ ਕੀਤੇ ਜਾਂਦੇ ਹਨ ਤਾਂ ਨੋਟੀਫਿਕੇਸ਼ਨ ਸੂਚੀ ਵਿੱਚ ਨੋਟੀਫਿਕੇਸ਼ਨ ਦਿਖਾਈ ਦੇਣਾ ਜਾਰੀ ਰੱਖਣਗੇ।" + + #. Popups here refers to message tray notifications in the middle of the screen. + #: panels/notifications/cc-app-notifications-dialog.ui:249 +@@ -4449,8 +4491,7 @@ msgstr "ਆਨਲਾਈਨ ਖਾਤੇ" + + #: panels/online-accounts/gnome-online-accounts-panel.desktop.in.in:4 + msgid "Connect to your online accounts and decide what to use them for" +-msgstr "" +-"ਆਪਣੇ ਆਨਲਾਈਨ ਖਾਤਿਆਂ ਨਾਲ ਕਨੈਕਟ ਹੋਵੋ ਅਤੇ ਫੈਸਲਾ ਕਰੋ ਕਿ ਉਹਨਾਂ ਨੂੰ ਕਿਸ ਲਈ ਵਰਤਣਾ ਹੈ" ++msgstr "ਆਪਣੇ ਆਨਲਾਈਨ ਖਾਤਿਆਂ ਨਾਲ ਕਨੈਕਟ ਹੋਵੋ ਅਤੇ ਫੈਸਲਾ ਕਰੋ ਕਿ ਉਹਨਾਂ ਨੂੰ ਕਿਸ ਲਈ ਵਰਤਣਾ ਹੈ" + + #. Translators: Search terms to find the Online Accounts panel. + #. Do NOT translate or localize the semicolons! +@@ -4461,8 +4502,7 @@ msgid "" + "Google;Facebook;Twitter;Yahoo;Web;Online;Chat;Calendar;Mail;Contact;ownCloud;" + "Kerberos;IMAP;SMTP;Pocket;ReadItLater;" + msgstr "" +-"ਗੂਗਲ;ਫੇਸਬੁੱਕ;ਟਵਿੱਟਰ;ਯਾਹੂ;ਵੈੱਬ;ਆਨਲਾਈਨ;ਗੱਲਬਾਤ;ਚੈਟ;ਕੈਲੰਡਰ;ਮੇਲ;ਸੰਪਰਕ;Google;Facebo" +-"ok;Twitter;" ++"ਗੂਗਲ;ਫੇਸਬੁੱਕ;ਟਵਿੱਟਰ;ਯਾਹੂ;ਵੈੱਬ;ਆਨਲਾਈਨ;ਗੱਲਬਾਤ;ਚੈਟ;ਕੈਲੰਡਰ;ਮੇਲ;ਸੰਪਰਕ;Google;Facebook;Twitter;" + "Yahoo;Web;Online;Chat;Calendar;Mail;Contact;ownCloud;Kerberos;IMAP;SMTP;" + "Packet;ReaditLater;" + +@@ -4780,8 +4820,7 @@ msgstr "ਮੋਬਾਇਲ ਬਰਾਡਬੈਂਡ(_M)" + + #: panels/power/cc-power-panel.ui:621 + msgid "Mobile broadband (LTE, 4G, 3G, etc.) can be turned off to save power." +-msgstr "" +-"ਊਰਜਾ ਬਚਾਉਣ ਲਈ ਮੋਬਾਇਲ ਬਰਾਡਬੈਂਡ (LTE, 4G, 3G, ਆਦਿ) ਨੂੰ ਬੰਦ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।" ++msgstr "ਊਰਜਾ ਬਚਾਉਣ ਲਈ ਮੋਬਾਇਲ ਬਰਾਡਬੈਂਡ (LTE, 4G, 3G, ਆਦਿ) ਨੂੰ ਬੰਦ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।" + + #: panels/power/cc-power-panel.ui:671 + msgid "_Bluetooth" +@@ -4874,8 +4913,8 @@ msgid "" + "Power;Sleep;Suspend;Hibernate;Battery;Brightness;Dim;Blank;Monitor;DPMS;Idle;" + "Energy;" + msgstr "" +-"ਸਕਰੀਨ;ਚਮਕ;ਵੇਹਲਾ;ਪਾਵਰ;ਸਲੀਪ;ਸਸਪੈਂਡ;ਹਾਈਬਰਨੇਟ;ਬੈਟਰੀ;ਵੇਹਲ;ਡਿਮ;ਖਾਲੀ;ਮਾਨੀਟਰ;ਡੀਪੀਐਮਐਸ;" +-"ਮੁਅੱਤਲ;ਊਰਜਾ;" ++"ਸਕਰੀਨ;ਚਮਕ;ਵੇਹਲਾ;ਪਾਵਰ;ਸਲੀਪ;ਸਸਪੈਂਡ;ਹਾਈਬਰਨੇਟ;ਬੈਟਰੀ;ਵੇਹਲ;ਡਿਮ;ਖਾਲੀ;ਮਾਨੀਟਰ;ਡੀਪੀਐਮਐਸ;ਮੁਅੱਤਲ;" ++"ਊਰਜਾ;" + + #: panels/printers/authentication-dialog.ui:11 + msgid " " +@@ -4920,8 +4959,7 @@ msgstr "ਪਰਿੰਟਰ" + + #: panels/printers/gnome-printers-panel.desktop.in.in:4 + msgid "Add printers, view printer jobs and decide how you want to print" +-msgstr "" +-"ਪਰਿੰਟਰ ਜੋੜੋ, ਪਰਿੰਟਰ ਜਾਬ ਵੇਖੋ ਅਤੇ ਤਹਿ ਕਰੋ ਤੁਸੀਂ ਕਿਵੇਂ ਪਰਿੰਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੈ" ++msgstr "ਪਰਿੰਟਰ ਜੋੜੋ, ਪਰਿੰਟਰ ਜਾਬ ਵੇਖੋ ਅਤੇ ਤਹਿ ਕਰੋ ਤੁਸੀਂ ਕਿਵੇਂ ਪਰਿੰਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੈ" + + #. Translators: Search terms to find the Printers panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! + #: panels/printers/gnome-printers-panel.desktop.in.in:16 +@@ -4954,8 +4992,7 @@ msgstr "ਨੈਟਵਰਕ ਐਡਰੈਸ ਦਿਓ ਜਾਂ ਪਰਿੰਟ + + #: panels/printers/new-printer-dialog.ui:356 + msgid "Enter username and password to view printers on Print Server." +-msgstr "" +-"ਪਰਿੰਟਰ ਸਰਵਰ ਉੱਤੇ ਪਰਿੰਟਰਾਂ ਨੂੰ ਵੇਖਣ ਲਈ ਆਪਣਾ ਵਰਤੋਂਕਾਰ-ਨਾਂ ਅਤੇ ਪਾਸਵਰਡ ਦਿਉ।" ++msgstr "ਪਰਿੰਟਰ ਸਰਵਰ ਉੱਤੇ ਪਰਿੰਟਰਾਂ ਨੂੰ ਵੇਖਣ ਲਈ ਆਪਣਾ ਵਰਤੋਂਕਾਰ-ਨਾਂ ਅਤੇ ਪਾਸਵਰਡ ਦਿਉ।" + + #. Translators: This is the title of the dialog. %s is the printer name. + #: panels/printers/pp-details-dialog.c:74 +@@ -5547,9 +5584,7 @@ msgstr "ਫਾਰਮੈਟ" + msgid "" + "Choose the format for numbers, dates and currencies. Changes take effect on " + "next login." +-msgstr "" +-"ਅੰਕਾਂ, ਤਾਰੀਖਾਂ ਤੇ ਕਰੰਸੀਆਂ ਲਈ ਫਾਰਮੈਟ ਚੁਣੋ। ਤਬਦੀਲੀਆਂ ਅਗਲੇ ਲਾਗਇਨ ਉੱਤੇ ਲਾਗੂ" +-" ਹੁੰਦੀਆਂ ਹਨ।" ++msgstr "ਅੰਕਾਂ, ਤਾਰੀਖਾਂ ਤੇ ਕਰੰਸੀਆਂ ਲਈ ਫਾਰਮੈਟ ਚੁਣੋ। ਤਬਦੀਲੀਆਂ ਅਗਲੇ ਲਾਗਇਨ ਉੱਤੇ ਲਾਗੂ ਹੁੰਦੀਆਂ ਹਨ।" + + #: panels/region/cc-format-chooser.ui:117 + msgid "Search locales..." +@@ -5643,9 +5678,7 @@ msgstr "ਫਾਰਮੈਟ(_F)" + + #: panels/region/cc-region-panel.ui:231 + msgid "Login settings are used by all users when logging into the system" +-msgstr "" +-"ਲਾਗਇਨ ਸੈਟਿੰਗਾਂ ਨੂੰ ਸਭ ਵਰਤੋਂਕਾਰਾਂ ਵਲੋਂ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ, ਜਦੋਂ ਸਿਸਟਮ ਵਿੱਚ ਲਾਗਇਨ" +-" ਕਰਦੇ ਹਨ" ++msgstr "ਲਾਗਇਨ ਸੈਟਿੰਗਾਂ ਨੂੰ ਸਭ ਵਰਤੋਂਕਾਰਾਂ ਵਲੋਂ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ, ਜਦੋਂ ਸਿਸਟਮ ਵਿੱਚ ਲਾਗਇਨ ਕਰਦੇ ਹਨ" + + #: panels/region/gnome-region-panel.desktop.in.in:3 + msgid "Region & Language" +@@ -5804,8 +5837,7 @@ msgid "" + "device;system;default;application;preferred;cd;dvd;usb;audio;video;disc;" + "removable;media;autorun;" + msgstr "" +-"ਡਿਵਾਈਸ;ਡੀਵਾਈਸ;ਯੰਤਰ;ਜੰਤਰ;ਡਿਫਾਲਟ;ਮੂਲ;ਐਪਲੀਕੇਸ਼ਨ;ਤਰਜੀਹੀ;ਪਸੰਦ;ਸੀਡੀ;ਡੀਵੀਡੀ;ਆਡੀਓ;ਯੂਐਸ" +-"ਬੀ;" ++"ਡਿਵਾਈਸ;ਡੀਵਾਈਸ;ਯੰਤਰ;ਜੰਤਰ;ਡਿਫਾਲਟ;ਮੂਲ;ਐਪਲੀਕੇਸ਼ਨ;ਤਰਜੀਹੀ;ਪਸੰਦ;ਸੀਡੀ;ਡੀਵੀਡੀ;ਆਡੀਓ;ਯੂਐਸਬੀ;" + "ਵੀਡੀਓ;ਹਟਾਉਣਯੋਗ;ਵਿਡੀਓ;ਮੀਡੀਆ;ਆਟੋ-ਰਨ;" + + #: panels/search/cc-search-locations-dialog.c:636 +@@ -5827,9 +5859,7 @@ msgstr "ਟਿਕਾਣਾ ਖੋਜ" + msgid "" + "Folders which are searched by system applications, such as Files, Photos and " + "Videos." +-msgstr "" +-"ਫੋਲਡਰ, ਜਿਹਨਾਂ ਨੂੰ ਸਿਸਟਮ ਐਪਲੀਕੇਸ਼ਨਾਂ, ਜਿਵੇਂ ਫਾਇਲਾਂ, ਫੋਟੋ ਅਤੇ ਵਿਡੀਓ ਵਲੋਂ ਖੋਜਿਆ" +-" ਜਾਂਦਾ ਹੈ।" ++msgstr "ਫੋਲਡਰ, ਜਿਹਨਾਂ ਨੂੰ ਸਿਸਟਮ ਐਪਲੀਕੇਸ਼ਨਾਂ, ਜਿਵੇਂ ਫਾਇਲਾਂ, ਫੋਟੋ ਅਤੇ ਵਿਡੀਓ ਵਲੋਂ ਖੋਜਿਆ ਜਾਂਦਾ ਹੈ।" + + #: panels/search/cc-search-locations-dialog.ui:52 + msgid "Places" +@@ -5860,8 +5890,7 @@ msgid "" + "Control which search results are shown in the Activities Overview. The order " + "of search results can also be changed by moving rows in the list." + msgstr "" +-"ਕੰਟਰੋਲ ਕਰੋ ਕਿ ਕਿਹੜੇ ਖੋਜ ਨਤੀਜਿਆ ਨੂੰ ਸਰਗਰਮੀ ਸਾਰ ਵਿੱਚ ਵਿਖਾਇਆ ਜਾਂਦਾ ਹੈ। ਖੋਜ" +-" ਨਤੀਜਿਆਂ ਦੀ ਲੜੀ ਨੂੰ " ++"ਕੰਟਰੋਲ ਕਰੋ ਕਿ ਕਿਹੜੇ ਖੋਜ ਨਤੀਜਿਆ ਨੂੰ ਸਰਗਰਮੀ ਸਾਰ ਵਿੱਚ ਵਿਖਾਇਆ ਜਾਂਦਾ ਹੈ। ਖੋਜ ਨਤੀਜਿਆਂ ਦੀ ਲੜੀ ਨੂੰ " + "ਸੂਚੀ ਵਿੱਚ ਕਤਾਰਾਂ ਰਾਹੀਂ ਹਿਲਾ ਕੇ ਵੀ ਬਦਲਿਆ ਜਾ ਸਕਦਾ ਹੈ।" + + #: panels/search/gnome-search-panel.desktop.in.in:4 +@@ -5873,8 +5902,7 @@ msgstr "ਕੰਟਰੋਲ ਕਰੋ ਕਿਹੜੀਆਂ ਐਪਲੀਕੇਸ਼ + #: panels/search/gnome-search-panel.desktop.in.in:19 + msgid "Search;Find;Index;Hide;Privacy;Results;" + msgstr "" +-"ਖੋਜ;ਲੱਭੋ;ਲੱਭਣਾ;ਇੰਡੈਕਸ;ਤਤਕਰਾ;ਪਰਾਈਵੇਸੀ;ਨਤੀਜੇ;Search;Find;Index;Hide;Privacy;Resu" +-"lts;" ++"ਖੋਜ;ਲੱਭੋ;ਲੱਭਣਾ;ਇੰਡੈਕਸ;ਤਤਕਰਾ;ਪਰਾਈਵੇਸੀ;ਨਤੀਜੇ;Search;Find;Index;Hide;Privacy;Results;" + + #. Label + #: panels/sharing/cc-sharing-networks.c:306 +@@ -5916,8 +5944,7 @@ msgid "" + "File Sharing allows you to share your Public folder with others on your " + "current network using: %s" + msgstr "" +-"ਫਾਇਲ ਸਾਂਝ ਤੁਹਾਨੂੰ ਤੁਹਾਡੇ ਪਬਲਿਕ ਫੋਲਡਰ ਨੂੰ ਹੋਰਾਂ ਨਾਲ ਤੁਹਾਡੇ ਮੌਜੂਦਾ ਨੈੱਟਵਰਕ ਉੱਤੇ" +-" ਦੀ ਵਰਤੋਂ ਨਾਲ ਸਾਂਝਾ " ++"ਫਾਇਲ ਸਾਂਝ ਤੁਹਾਨੂੰ ਤੁਹਾਡੇ ਪਬਲਿਕ ਫੋਲਡਰ ਨੂੰ ਹੋਰਾਂ ਨਾਲ ਤੁਹਾਡੇ ਮੌਜੂਦਾ ਨੈੱਟਵਰਕ ਉੱਤੇ ਦੀ ਵਰਤੋਂ ਨਾਲ ਸਾਂਝਾ " + "ਕਰਨ ਲਈ ਸਹਾਇਕ ਹੈ: %s" + + #. TRANSLATORS: %s is replaced with a link to a "ssh " command to run +@@ -5928,8 +5955,7 @@ msgid "" + "Shell command:\n" + "%s" + msgstr "" +-"ਜਦੋਂ ਰਿਮੋਟ ਲਾਗਇਨ ਸਮਰੱਥ ਹੁੰਦਾ ਹੈ ਤਾਂ ਰਿਮੋਟ ਵਰਤੋਂਕਾਰ ਨੂੰ ਸੁਰੱਖਿਅਤ ਸ਼ੈੱਲ ਕਮਾਂਡ" +-" ਰਾਹੀਂ ਕਨੈਕਟ ਹੋ ਸਕਦਾ " ++"ਜਦੋਂ ਰਿਮੋਟ ਲਾਗਇਨ ਸਮਰੱਥ ਹੁੰਦਾ ਹੈ ਤਾਂ ਰਿਮੋਟ ਵਰਤੋਂਕਾਰ ਨੂੰ ਸੁਰੱਖਿਅਤ ਸ਼ੈੱਲ ਕਮਾਂਡ ਰਾਹੀਂ ਕਨੈਕਟ ਹੋ ਸਕਦਾ " + "ਹੈ:\n" + "%s" + +@@ -5940,8 +5966,7 @@ msgid "" + "Screen sharing allows remote users to view or control your screen by " + "connecting to %s" + msgstr "" +-"ਸਕਰੀਨ ਸਾਂਝਾ ਕਰਨ ਨਾਲ ਰਿਮੋਟ ਵਰਤੋਂਕਾਰਾਂ ਨੂੰ ਆਪਣੀ ਸਕਰੀਨ ਵੇਖਣ ਜਾਂ ਕੰਟਰੋਲ ਦਿੱਤਾ" +-" ਜਾਂਦਾ ਹੈ, %s ਨਾਲ " ++"ਸਕਰੀਨ ਸਾਂਝਾ ਕਰਨ ਨਾਲ ਰਿਮੋਟ ਵਰਤੋਂਕਾਰਾਂ ਨੂੰ ਆਪਣੀ ਸਕਰੀਨ ਵੇਖਣ ਜਾਂ ਕੰਟਰੋਲ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ, %s ਨਾਲ " + "ਕਨੈਕਟ ਕਰਕੇ" + + #: panels/sharing/cc-sharing-panel.c:813 +@@ -6043,8 +6068,7 @@ msgid "" + "share;sharing;ssh;host;name;remote;desktop;media;audio;video;pictures;photos;" + "movies;server;renderer;" + msgstr "" +-"ਸਾਂਝਾ;ਸਾਂਝਾ ਕਰੋ;ਨਾਂ;ਨਾਮ;ਡੈਸਕਟਾਪ;ਮੀਡੀਆ;ਆਡੀਓ;ਵੀਡੀਓ;ਹੋਸਟ;ssh;ਰਿਮੋਟ;ਤਸਵੀਰ;ਫੋਟੋ;ਮੂਵ" +-"ੀ;ਸਰਵਰ;" ++"ਸਾਂਝਾ;ਸਾਂਝਾ ਕਰੋ;ਨਾਂ;ਨਾਮ;ਡੈਸਕਟਾਪ;ਮੀਡੀਆ;ਆਡੀਓ;ਵੀਡੀਓ;ਹੋਸਟ;ssh;ਰਿਮੋਟ;ਤਸਵੀਰ;ਫੋਟੋ;ਮੂਵੀ;ਸਰਵਰ;" + "ਰੈਂਡਰ;" + + #: panels/sharing/org.gnome.controlcenter.remote-login-helper.policy.in.in:11 +@@ -6161,9 +6185,7 @@ msgstr "ਸਾਊਂਡ ਲੈਵਲ, ਇੰਪੁੱਟ, ਆਉਟਪੁੱਟ + #: panels/sound/gnome-sound-panel.desktop.in.in:20 + msgid "" + "Card;Microphone;Volume;Fade;Balance;Bluetooth;Headset;Audio;Output;Input;" +-msgstr "" +-"ਕਾਰਡ;ਮਾਈਕਰੋਫੋਨ;ਵਾਲੀਅਮ;ਫੇਡ;ਬੈਲਨਸ;ਬਲਿਊਟੁੱਲ;ਹੈੱਡਸੈੱਟ;ਆਡੀਓ;ਆਉਟਪੁੱਟ;ਇੰਪੁੱਟ;ਇਨਪੁੱਟ;ਬ" +-"ਲੁਟੁੱਥ;" ++msgstr "ਕਾਰਡ;ਮਾਈਕਰੋਫੋਨ;ਵਾਲੀਅਮ;ਫੇਡ;ਬੈਲਨਸ;ਬਲਿਊਟੁੱਲ;ਹੈੱਡਸੈੱਟ;ਆਡੀਓ;ਆਉਟਪੁੱਟ;ਇੰਪੁੱਟ;ਇਨਪੁੱਟ;ਬਲੁਟੁੱਥ;" + + #: panels/thunderbolt/cc-bolt-device-dialog.c:94 + #: panels/thunderbolt/cc-bolt-device-entry.c:125 +@@ -6276,8 +6298,7 @@ msgstr "ਪਰਮਾਣਿਤ ਹੈ" + msgid "" + "The Thunderbolt subsystem (boltd) is not installed or not set up properly." + msgstr "" +-"ਥੰਡਰਬੋਲਟ ਸਬ-ਸਿਸਟਮ (boldtd) ਠੀਕ ਤਰ੍ਹਾਂ ਇੰਸਟਾਲ ਨਹੀਂ ਹੈ ਜਾਂ ਠੀਕ ਤਰ੍ਹਾਂ ਸੈਟ ਅੱਪ" +-" ਨਹੀਂ ਕੀਤਾ ਹੈ।" ++"ਥੰਡਰਬੋਲਟ ਸਬ-ਸਿਸਟਮ (boldtd) ਠੀਕ ਤਰ੍ਹਾਂ ਇੰਸਟਾਲ ਨਹੀਂ ਹੈ ਜਾਂ ਠੀਕ ਤਰ੍ਹਾਂ ਸੈਟ ਅੱਪ ਨਹੀਂ ਕੀਤਾ ਹੈ।" + + #: panels/thunderbolt/cc-bolt-panel.c:468 + msgid "" +@@ -6286,8 +6307,7 @@ msgid "" + "BIOS or is set to an unsupported security level in the BIOS." + msgstr "" + "ਥੰਡਰਬੋਲਟ ਖੋਜਿਆ ਨਹੀਂ ਜਾ ਸਕਿਆ।\n" +-"ਜਾਂ ਤਾਂ ਸਿਸਟਮ ਥੰਡਰਬੋਲਢ ਲਈ ਸਹਾਇਕ ਨਹੀ ਹੈ, ਇਹ BIOS ਵਿੱਚੋਂ ਅਸਮਰੱਥ ਕੀਤਾ ਹੋ ਸਕਦਾ ਹੈ" +-" ਜਾਂ BIOS " ++"ਜਾਂ ਤਾਂ ਸਿਸਟਮ ਥੰਡਰਬੋਲਢ ਲਈ ਸਹਾਇਕ ਨਹੀ ਹੈ, ਇਹ BIOS ਵਿੱਚੋਂ ਅਸਮਰੱਥ ਕੀਤਾ ਹੋ ਸਕਦਾ ਹੈ ਜਾਂ BIOS " + "ਵਿੱਚ ਗ਼ੈਰ-ਸਹਾਇਕ ਸੁਰੱਖਿਆ ਪੱਧਰ ਲਈ ਸੈੱਟ ਕੀਤਾ ਹੋ ਸਕਦਾ ਹੈ।" + + #: panels/thunderbolt/cc-bolt-panel.c:512 +@@ -6887,10 +6907,8 @@ msgid "" + "Bounce;Mouse;Double;click;Delay;Speed;Assist;Repeat;Blink;visual;hearing;" + "audio;typing;" + msgstr "" +-"ਕੀਬੋਰਡ;,ਮਾਊਸ;ਫੋਂਟ;ਟੈਕਸਟ;ਆਕਾਰ;ਕਰਸਰ;ਆਵਾਜ਼;ਸਾਊਂਡ;ਬਾਊਂਸ;ਕੀ-ਬੋਰਡ;ਸਵਿੱਚਾਂ,ਕੀ;ਅਸੈਸਬਲਿਟ" +-"ੀ;ਜ਼ੂਮ;ਡਬਲ " +-"ਕਲਿੱਕ;ਦੋਹਰਾ ਕਲਿੱਕ;ਦੇਰੀ;ਸਹਾਇਕ;ਰੀਡਰ;ਐਕਟਿਵਐਕਸ;ਹੌਲੀ;ਕਨਟਰਾਸਟ;ਦੁਹਰਾਉਣਾ;ਝਪਕਣਾ;ਦੁਹਰਾ;ਵ" +-"ੱਡੇ;ਵੱਡਾ;" ++"ਕੀਬੋਰਡ;,ਮਾਊਸ;ਫੋਂਟ;ਟੈਕਸਟ;ਆਕਾਰ;ਕਰਸਰ;ਆਵਾਜ਼;ਸਾਊਂਡ;ਬਾਊਂਸ;ਕੀ-ਬੋਰਡ;ਸਵਿੱਚਾਂ,ਕੀ;ਅਸੈਸਬਲਿਟੀ;ਜ਼ੂਮ;ਡਬਲ " ++"ਕਲਿੱਕ;ਦੋਹਰਾ ਕਲਿੱਕ;ਦੇਰੀ;ਸਹਾਇਕ;ਰੀਡਰ;ਐਕਟਿਵਐਕਸ;ਹੌਲੀ;ਕਨਟਰਾਸਟ;ਦੁਹਰਾਉਣਾ;ਝਪਕਣਾ;ਦੁਹਰਾ;ਵੱਡੇ;ਵੱਡਾ;" + "ਉੱਚ;ਹੋਰ ਵੱਡਾ;ਸਪੀਡ;ਗਤੀ;ਦਿੱਖ;ਸੁਣਨਾ;ਆਡੀਓ;ਲਿਖਣਾ;ਟਾਈਪ ਕਰਨਾ;ਟਾਈਪਿੰਗ;ਵਿਆਪਕ ਪਹੁੰਚ;" + + #: panels/usage/cc-usage-panel.c:154 +@@ -6927,10 +6945,8 @@ msgid "" + "shared between applications, and makes it easier to find files that you " + "might want to use." + msgstr "" +-"ਫਾਇਲ ਅਤੀਤ ਫਾਇਲਾਂ ਦੇ ਰਿਕਾਰਡ ਰੱਖਦਾ ਹੈ, ਜੋ ਤੁਸੀਂ ਵਰਤੇ ਚੁੱਕੇ ਹੋ। ਇਹ ਜਾਣਕਾਰੀ ਨੂੰ" +-" ਐਪਲੀਕੇਸ਼ਨਾਂ ਵਿਚਾਲੇ " +-"ਸਾਂਝਾ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਜਿਸ ਨਾਲ ਤੁਹਾਡੇ ਲਈ ਫਾਇਲਾਂ ਲੱਭਣੀਆਂ ਸੌਖੀਆਂ ਹੋ ਜਾਂਦੀਆਂ ਹਨ," +-" ਜਦੋਂ ਵਰਤੀਆਂ ਹੋਣ।" ++"ਫਾਇਲ ਅਤੀਤ ਫਾਇਲਾਂ ਦੇ ਰਿਕਾਰਡ ਰੱਖਦਾ ਹੈ, ਜੋ ਤੁਸੀਂ ਵਰਤੇ ਚੁੱਕੇ ਹੋ। ਇਹ ਜਾਣਕਾਰੀ ਨੂੰ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵਿਚਾਲੇ " ++"ਸਾਂਝਾ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਜਿਸ ਨਾਲ ਤੁਹਾਡੇ ਲਈ ਫਾਇਲਾਂ ਲੱਭਣੀਆਂ ਸੌਖੀਆਂ ਹੋ ਜਾਂਦੀਆਂ ਹਨ, ਜਦੋਂ ਵਰਤੀਆਂ ਹੋਣ।" + + #: panels/usage/cc-usage-panel.ui:56 + msgid "File H_istory" +@@ -6953,8 +6969,7 @@ msgid "" + "Trash and temporary files can sometimes include personal or sensitive " + "information. Automatically deleting them can help to protect privacy." + msgstr "" +-"ਰੱਦੀ ਅਤੇ ਆਰਜ਼ੀ ਫਾਇਲਾਂ ਕਈ ਵਾਰ ਨਿੱਜੀ ਅਤੇ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਰੱਖ ਸਕਦੀਆਂ ਹਨ। ਉਹਨਾਂ" +-" ਨੂੰ ਆਪਣੇ-ਆਪ " ++"ਰੱਦੀ ਅਤੇ ਆਰਜ਼ੀ ਫਾਇਲਾਂ ਕਈ ਵਾਰ ਨਿੱਜੀ ਅਤੇ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਰੱਖ ਸਕਦੀਆਂ ਹਨ। ਉਹਨਾਂ ਨੂੰ ਆਪਣੇ-ਆਪ " + "ਹਟਾਉਣ ਨਾਲ ਪਰਦੇਦਾਰੀ ਨੂੰ ਸੁਰੱਖਿਅਤ ਕਰਨ ਲਈ ਮਦਦ ਮਿਲ ਸਕਦੀ ਹੈ।" + + #: panels/usage/cc-usage-panel.ui:159 +@@ -7161,8 +7176,7 @@ msgid "" + "used on this device. You can also use this account to access company " + "resources on the internet." + msgstr "" +-"ਇੰਟਰਪਰਾਈਜ਼ ਲਾਗਇਨ ਮੌਜੂਦਾ ਕੇਂਦਰੀਕ੍ਰਿਤ ਵਰਤੋਂਕਾਰ ਅਕਾਊਂਟ ਨੂੰ ਇਹ ਜੰਤਰ ਉੱਤੇ ਵਰਤਣ ਲਈ" +-" ਸਹਾਇਕ ਹੈ। ਤੁਸੀਂ " ++"ਇੰਟਰਪਰਾਈਜ਼ ਲਾਗਇਨ ਮੌਜੂਦਾ ਕੇਂਦਰੀਕ੍ਰਿਤ ਵਰਤੋਂਕਾਰ ਅਕਾਊਂਟ ਨੂੰ ਇਹ ਜੰਤਰ ਉੱਤੇ ਵਰਤਣ ਲਈ ਸਹਾਇਕ ਹੈ। ਤੁਸੀਂ " + "ਇਸ ਅਕਾਊਂਟ ਨੂੰ ਇੰਟਰਨੈੱਟ ਉੱਤੇ ਕੰਪਨੀ ਦੇ ਸਰੋਤਾਂ ਤੱਕ ਪਹੁੰਚ ਲਈ ਵੀ ਵਰਤ ਸਕਦੇ ਹੋ।" + + #: panels/user-accounts/cc-add-user-dialog.ui:732 +@@ -7213,8 +7227,7 @@ msgid "" + "Do you want to delete your registered fingerprints so fingerprint login is " + "disabled?" + msgstr "" +-"ਕੀ ਤੁਸੀਂ ਆਪਣੇ ਰਜਿਸਟਰ ਕੀਤੇ ਫਿੰਗਰਪਰਿੰਟ ਹਟਾਉਣੇ ਚਾਹੁੰਦੇ ਹੋ ਤਾਂ ਕਿ ਫਿੰਗਰਪਰਿੰਟ" +-" ਲਾਗਇਨ ਨੂੰ ਆਯੋਗ ਕੀਤਾ " ++"ਕੀ ਤੁਸੀਂ ਆਪਣੇ ਰਜਿਸਟਰ ਕੀਤੇ ਫਿੰਗਰਪਰਿੰਟ ਹਟਾਉਣੇ ਚਾਹੁੰਦੇ ਹੋ ਤਾਂ ਕਿ ਫਿੰਗਰਪਰਿੰਟ ਲਾਗਇਨ ਨੂੰ ਆਯੋਗ ਕੀਤਾ " + "ਜਾ ਸਕੇ?" + + #. Translators: This is the empty state page label which states that there are no devices ready. +@@ -7247,9 +7260,8 @@ msgid "" + "Fingerprint login allows you to unlock and log into your computer with your " + "finger" + msgstr "" +-"ਫਿੰਗਰਪਰਿੰਟ ਲਾਗਇਨ ਤੁਹਾਨੂੰ ਆਪਣੇ ਕੰਪਿਊਟਰ ਨੂੰ ਅਣ-ਲਾਕ ਕਰਨ ਤੇ ਲਾਗਇਨ ਕਰਨ ਲਈ ਤੁਹਾਡੀ" +-" ਉਂਗਲ " +-"ਵਰਤਣ ਲਈ ਸਹਾਇਕ ਹੈ" ++"ਫਿੰਗਰਪਰਿੰਟ ਲਾਗਇਨ ਤੁਹਾਨੂੰ ਆਪਣੇ ਕੰਪਿਊਟਰ ਨੂੰ ਅਣ-ਲਾਕ ਕਰਨ ਤੇ ਲਾਗਇਨ ਕਰਨ ਲਈ ਤੁਹਾਡੀ ਉਂਗਲ ਵਰਤਣ ਲਈ " ++"ਸਹਾਇਕ ਹੈ" + + #: panels/user-accounts/cc-fingerprint-dialog.ui:352 + msgid "_Delete Fingerprints" +@@ -7400,8 +7412,7 @@ msgstr "ਦਾਖਲਾ ਰੋਕਣ ਲਈ ਫੇਲ੍ਹ: %s" + msgid "" + "Repeatedly lift and place your finger on the reader to enroll your " + "fingerprint" +-msgstr "" +-"ਆਪਣੇ ਫਿੰਗਰਪਰਿੰਟ ਨੂੰ ਦਾਖਲ ਕਰਨ ਲਈ ਰੀਡਰ ਉੱਤੇ ਆਪਣੀ ਉਂਗਲ ਨੂੰ ਲਗਾਤਾਰ ਚੱਕੋ ਅਤੇ ਰੱਖੋ" ++msgstr "ਆਪਣੇ ਫਿੰਗਰਪਰਿੰਟ ਨੂੰ ਦਾਖਲ ਕਰਨ ਲਈ ਰੀਡਰ ਉੱਤੇ ਆਪਣੀ ਉਂਗਲ ਨੂੰ ਲਗਾਤਾਰ ਚੱਕੋ ਅਤੇ ਰੱਖੋ" + + #. TRANSLATORS: This is the label for the button to enroll a new finger + #: panels/user-accounts/cc-fingerprint-dialog.c:1118 +@@ -7589,8 +7600,7 @@ msgid "" + "Deleting a user while they are logged in can leave the system in an " + "inconsistent state." + msgstr "" +-"ਜਦੋਂ ਵਰਤੋਂਕਾਰ ਲਾਗਇਨ ਹੋਵੇ ਤਾਂ ਉਸ ਨੂੰ ਹਟਾਉਣ ਨਾਲ ਸਿਸਟਮ ਖਰਾਬ ਹੋਣ ਦੀ ਹਾਲਤ 'ਚ ਆ" +-" ਸਕਦਾ ਹੈ।" ++"ਜਦੋਂ ਵਰਤੋਂਕਾਰ ਲਾਗਇਨ ਹੋਵੇ ਤਾਂ ਉਸ ਨੂੰ ਹਟਾਉਣ ਨਾਲ ਸਿਸਟਮ ਖਰਾਬ ਹੋਣ ਦੀ ਹਾਲਤ 'ਚ ਆ ਸਕਦਾ ਹੈ।" + + #: panels/user-accounts/cc-user-panel.c:624 + #, c-format +@@ -7602,8 +7612,7 @@ msgid "" + "It is possible to keep the home directory, mail spool and temporary files " + "around when deleting a user account." + msgstr "" +-"ਘਰ ਡਾਇਰੈਕਟਰੀ, ਮੇਲ ਸਪੂਲ ਅਤੇ ਆਰਜ਼ੀ ਫਾਇਲਾਂ ਨੂੰ ਰੱਖਣਾ ਸੰਭਵ ਹੈ, ਜਦੋਂ ਵਰਤੋਂਕਾਰ ਖਾਤਾ" +-" ਹਟਾਉਣਾ ਹੋਵੇ।" ++"ਘਰ ਡਾਇਰੈਕਟਰੀ, ਮੇਲ ਸਪੂਲ ਅਤੇ ਆਰਜ਼ੀ ਫਾਇਲਾਂ ਨੂੰ ਰੱਖਣਾ ਸੰਭਵ ਹੈ, ਜਦੋਂ ਵਰਤੋਂਕਾਰ ਖਾਤਾ ਹਟਾਉਣਾ ਹੋਵੇ।" + + #: panels/user-accounts/cc-user-panel.c:631 + msgid "_Delete Files" +@@ -7719,8 +7728,7 @@ msgid "" + "Administrators can add and remove other users, and can change settings for " + "all users." + msgstr "" +-"ਪਰਸ਼ਾਸ਼ਕ ਹੋਰ ਵਰਤੋਂਕਾਰਾਂ ਨੂੰ ਜੋੜ ਜਾਂ ਹਟਾ ਸਕਦੇ ਹਨ, ਅਤੇ ਸਾਰੇ ਵਰਤੋਂਕਾਰਾਂ ਲਈ" +-" ਸੈਟਿੰਗਾਂ ਬਦਲ ਸਕਦੇ ਹਨ।" ++"ਪਰਸ਼ਾਸ਼ਕ ਹੋਰ ਵਰਤੋਂਕਾਰਾਂ ਨੂੰ ਜੋੜ ਜਾਂ ਹਟਾ ਸਕਦੇ ਹਨ, ਅਤੇ ਸਾਰੇ ਵਰਤੋਂਕਾਰਾਂ ਲਈ ਸੈਟਿੰਗਾਂ ਬਦਲ ਸਕਦੇ ਹਨ।" + + #: panels/user-accounts/cc-user-panel.ui:333 + #| msgid "Controls" +@@ -7885,8 +7893,7 @@ msgid "" + "Try to avoid repeating the same type of character: you need to mix up " + "letters, numbers and punctuation." + msgstr "" +-"ਇੱਕੋ ਕਿਸਮ ਦੇ ਅੱਖਰ ਮੁੜ-ਵਰਤਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ: ਤੁਸੀਂ ਅੱਖਰਾਂ, ਅੰਕਾਂ ਅਤੇ ਵਿਰਾਮ" +-" ਚਿੰਨ੍ਹਾਂ ਨੂੰ ਮਿਲ ਸਕਦੇ ਹੋ।" ++"ਇੱਕੋ ਕਿਸਮ ਦੇ ਅੱਖਰ ਮੁੜ-ਵਰਤਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ: ਤੁਸੀਂ ਅੱਖਰਾਂ, ਅੰਕਾਂ ਅਤੇ ਵਿਰਾਮ ਚਿੰਨ੍ਹਾਂ ਨੂੰ ਮਿਲ ਸਕਦੇ ਹੋ।" + + #: panels/user-accounts/pw-utils.c:126 + msgctxt "Password hint" +@@ -7899,8 +7906,7 @@ msgid "" + "Password needs to be longer. Try to add more letters, numbers and " + "punctuation." + msgstr "" +-"ਪਾਸਵਰਡ ਹੋਰ ਲੰਮਾ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ। ਅੱਖਰ, ਅੰਕ ਅਤੇ ਵਿਰਾਮ-ਚਿੰਨ੍ਹ ਨੂੰ ਮਿਲਾ ਕੇ ਵਰਤ ਕੇ" +-" ਕੋਸ਼ਿਸ਼ ਕਰੋ।" ++"ਪਾਸਵਰਡ ਹੋਰ ਲੰਮਾ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ। ਅੱਖਰ, ਅੰਕ ਅਤੇ ਵਿਰਾਮ-ਚਿੰਨ੍ਹ ਨੂੰ ਮਿਲਾ ਕੇ ਵਰਤ ਕੇ ਕੋਸ਼ਿਸ਼ ਕਰੋ।" + + #: panels/user-accounts/pw-utils.c:130 + msgctxt "Password hint" +@@ -7967,8 +7973,7 @@ msgid "" + "The username should usually only consist of lower case letters from a-z, " + "digits and the following characters: - _" + msgstr "" +-"ਵਰਤੋਂਕਾਰ ਨਾਂ ਵਿੱਚ ਅਕਸਰ ਕੇਵਲ ਅੰਗਰੇਜ਼ੀ ਦੇ ਛੋਟੇ ਅੱਖਰ (a-z), ਅੰਕ, ਅਤੇ ਅੱਗੇ ਦਿੱਤੇ" +-" ਅੱਖਰ ਹੋ ਸਕਦੇ ਹਨ: - __" ++"ਵਰਤੋਂਕਾਰ ਨਾਂ ਵਿੱਚ ਅਕਸਰ ਕੇਵਲ ਅੰਗਰੇਜ਼ੀ ਦੇ ਛੋਟੇ ਅੱਖਰ (a-z), ਅੰਕ, ਅਤੇ ਅੱਗੇ ਦਿੱਤੇ ਅੱਖਰ ਹੋ ਸਕਦੇ ਹਨ: - __" + + #: panels/user-accounts/user-utils.c:436 + msgid "Sorry, that user name isn’t available. Please try another." +@@ -8000,8 +8005,7 @@ msgid "" + "To edit a shortcut, choose the “Send Keystroke” action, press the keyboard " + "shortcut button and hold down the new keys or press Backspace to clear." + msgstr "" +-"ਸ਼ਾਰਟਕੱਟ ਸੋਧਣ ਲਈ, ”ਕੀ-ਸਟੋਰਕ ਭੇਜੋ” ਕਾਰਵਾਈ ਚੁਣੋ, ਕੀਬੋਰਡ ਸ਼ਾਰਟਕੱਟ ਬਟਨ ਦੱਬੋ ਅਤੇ" +-" ਨਵੀਆਂ ਸਵਿੱਚਾਂ ਲਈ " ++"ਸ਼ਾਰਟਕੱਟ ਸੋਧਣ ਲਈ, ”ਕੀ-ਸਟੋਰਕ ਭੇਜੋ” ਕਾਰਵਾਈ ਚੁਣੋ, ਕੀਬੋਰਡ ਸ਼ਾਰਟਕੱਟ ਬਟਨ ਦੱਬੋ ਅਤੇ ਨਵੀਆਂ ਸਵਿੱਚਾਂ ਲਈ " + "ਹੋਲਡ ਕਰਕੇ ਰੱਖੋ ਜਾਂ ਬੈਕਸਪੇਸ ਸਾਫ਼ ਕਰਨ ਲਈ ਵਰਤੋਂ।" + + #: panels/wacom/calibrator/calibrator.ui:61 +@@ -8009,8 +8013,7 @@ msgid "" + "Please tap the target markers as they appear on screen to calibrate the " + "tablet." + msgstr "" +-"ਟਾਰਗੇਟ ਮਾਰਕਰ ਲਈ ਟੈਪ ਕਰੋ ਜਿਵੇਂ ਕਿ ਉਹ ਸਕਰੀਨ ਉੱਤੇ ਟੇਬਲੇਟ ਨੂੰ ਕੈਲੀਬਰੇਟ ਕਰਨ ਲਈ" +-" ਵੇਖਾਈ ਦਿੰਦਾ ਹੈ।" ++"ਟਾਰਗੇਟ ਮਾਰਕਰ ਲਈ ਟੈਪ ਕਰੋ ਜਿਵੇਂ ਕਿ ਉਹ ਸਕਰੀਨ ਉੱਤੇ ਟੇਬਲੇਟ ਨੂੰ ਕੈਲੀਬਰੇਟ ਕਰਨ ਲਈ ਵੇਖਾਈ ਦਿੰਦਾ ਹੈ।" + + #: panels/wacom/calibrator/calibrator.ui:78 + msgid "Mis-click detected, restarting…" +@@ -8269,8 +8272,7 @@ msgid "" + "may experience incorrect system behavior, data loss, and other unexpected " + "issues. " + msgstr "" +-"ਸੈਟਿੰਗਾਂ ਦਾ ਇਹ ਵਰਜ਼ਨ ਡਿਵੈਲਪਮੈਂਟ ਮਕਸਦ ਲਈ ਹੀ ਵਰਤਿਆ ਜਾਣਾ ਚਾਹੀਦਾ ਹੈ। ਤੁਹਾਨੂੰ ਕੁਝ" +-" ਗਲਤ ਸਿਸਟਮ " ++"ਸੈਟਿੰਗਾਂ ਦਾ ਇਹ ਵਰਜ਼ਨ ਡਿਵੈਲਪਮੈਂਟ ਮਕਸਦ ਲਈ ਹੀ ਵਰਤਿਆ ਜਾਣਾ ਚਾਹੀਦਾ ਹੈ। ਤੁਹਾਨੂੰ ਕੁਝ ਗਲਤ ਸਿਸਟਮ " + "ਰਵੱਈਏ, ਡਾਟਾ ਗੁਆਚਣ ਅਤੇ ਹੋਰ ਅਚਨਚੇਤ ਮਸਲਿਆਂ ਦਾ ਸਾਹਮਣਾ ਕਰਨਾ ਪੈ ਸਕਦਾ ਹੈ।" + + #: shell/cc-window.ui:330 +@@ -8321,8 +8323,7 @@ msgid "" + "The identifier for the last Settings panel to be opened. Unrecognised values " + "will be ignored and the first panel in the list selected." + msgstr "" +-"ਆਖਰੀ ਸੈਟਿੰਗਾਂ ਪੈਨਲ ਨੂੰ ਖੋਲ੍ਹਣ ਲਈ ਪਛਾਣਕਰਤਾ ਹੈ। ਬੇਪਛਾਣ ਮੁੱਲਾਂ ਨੂੰ ਅਣਡਿੱਠਾ ਕੀਤਾ" +-" ਜਾਵੇਗਾ ਅਤੇ ਸੂਚੀ " ++"ਆਖਰੀ ਸੈਟਿੰਗਾਂ ਪੈਨਲ ਨੂੰ ਖੋਲ੍ਹਣ ਲਈ ਪਛਾਣਕਰਤਾ ਹੈ। ਬੇਪਛਾਣ ਮੁੱਲਾਂ ਨੂੰ ਅਣਡਿੱਠਾ ਕੀਤਾ ਜਾਵੇਗਾ ਅਤੇ ਸੂਚੀ " + "ਵਿੱਚੋਂ ਪਹਿਲਾਂ ਪੈਨਲ ਚੁਣਿਆ ਜਾਂਦਾ ਹੈ।" + + #: shell/org.gnome.ControlCenter.gschema.xml:13 +@@ -8332,8 +8333,7 @@ msgstr "ਜਦੋਂ ਸੈਟਿੰਗਾਂ ਦੀ ਡਿਵੈਲਪਮੈਂ + #: shell/org.gnome.ControlCenter.gschema.xml:14 + msgid "" + "Whether Settings should show a warning when running a development build." +-msgstr "" +-"ਕੀ ਸੈਟਿੰਗਾਂ ਨੂੰ ਚੇਤਾਵਨੀ ਦਿਖਾਉਣੀ ਚਾਹੀਦੀ ਹੈ, ਜਦੋਂ ਡਿਵੈਲਪਮੈਂਟ ਬਿਲਡ ਚੱਲਦਾ ਹੋਵੇ।" ++msgstr "ਕੀ ਸੈਟਿੰਗਾਂ ਨੂੰ ਚੇਤਾਵਨੀ ਦਿਖਾਉਣੀ ਚਾਹੀਦੀ ਹੈ, ਜਦੋਂ ਡਿਵੈਲਪਮੈਂਟ ਬਿਲਡ ਚੱਲਦਾ ਹੋਵੇ।" + + #. translators: + #. * The number of sound outputs on a particular device +diff --git a/po/pl.po b/po/pl.po +index 7083f6ca6..143165b08 100644 +--- a/po/pl.po ++++ b/po/pl.po +@@ -9,8 +9,24 @@ + # Wojciech Szczęsny , 2013. + # Aviary.pl , 2007-2020. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# pl.po.multitasking (gnome-control-center) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-08 08:29+0000\n" ++"PO-Revision-Date: 2021-09-14 19:18+0200\n" ++"Last-Translator: Piotr Drąg \n" ++"Language-Team: Polish \n" ++"Language: pl\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " ++"|| n%100>=20) ? 1 : 2);\n" ++"#-#-#-#-# pl.po (gnome-control-center) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -25,6 +41,94 @@ msgstr "" + "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " + "|| n%100>=20) ? 1 : 2);\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Ogólne" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Aktywny róg" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Dotknięcie lewego górnego rogu otwiera ekran podglądu." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "Aktywne _krawędzie ekranu" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Przeciągnięcie okna do górnej, lewej lub prawej krawędzi ekranu zmienia jego " ++"rozmiar." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Obszary robocze" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Dynamiczne" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Automatycznie usuwa puste obszary robocze." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Stała liczba" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Można podać liczbę stałych obszarów roboczych." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Liczba obszarów roboczych" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Wiele monitorów" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "_Obszary robocze tylko na głównym ekranie" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "O_bszary robocze na wszystkich ekranach" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Przełączanie programów" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "_Programy ze wszystkich obszarów roboczych" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Progra_my tylko z obecnego obszaru roboczego" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Wielozadaniowość" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Zarządzanie preferencjami efektywności i wielozadaniowości" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"Wielozadaniowość;Multitasking;Efektywność;Produktywność;Dostosuj;" ++"Dostosowanie;Pulpit;Desktop;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Magistrala systemowa" +@@ -2646,11 +2750,6 @@ msgstr "Żadne programy nie poprosiły o dostęp do mikrofonu" + msgid "Protect your conversations" + msgstr "Ochrona rozmów" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Ogólne" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Przycisk podstawowy" +diff --git a/po/pt.po b/po/pt.po +index a63525f4a..a30a2848d 100644 +--- a/po/pt.po ++++ b/po/pt.po +@@ -1,3 +1,17 @@ ++# #-#-#-#-# pt.po.multitasking (3.8) #-#-#-#-# ++# gnome-control-center's Portuguese Translation ++# Copyright © 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 gnome-control-center ++# Distributed under the same licence as the gnome-control-center package ++# Duarte Loreto , 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014. ++# Nuno Ferreira , 1999. ++# António Lima , 2013. ++# Tiago Santos , 2014 - 2016. ++# Pedro Albuquerque , 2015. ++# Sérgio Cardeira , 2016. ++# Hugo Carvalho , 2021-2022. ++# Juliano de Souza Camargo , 2020-2022. ++# ++# #-#-#-#-# pt.po (3.8) #-#-#-#-# + # gnome-control-center's Portuguese Translation + # Copyright © 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 gnome-control-center + # Distributed under the same licence as the gnome-control-center package +@@ -9,8 +23,32 @@ + # Sérgio Cardeira , 2016. + # Juliano de Souza Camargo , 2020. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# pt.po.multitasking (3.8) #-#-#-#-#\n" ++"Project-Id-Version: 3.8\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2022-02-15 18:11+0000\n" ++"PO-Revision-Date: 2022-02-15 22:14+0000\n" ++"Last-Translator: Hugo Carvalho \n" ++"Language-Team: Portuguese < https://l10n.gnome.org/teams/pt/>\n" ++"Language: pt\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 3.0.1\n" ++"X-Language: pt_PT\n" ++"X-Source-Language: C\n" ++"X-Project-Style: gnome\n" ++"X-DL-Team: pt\n" ++"X-DL-Module: gnome-control-center\n" ++"X-DL-Branch: gnome-41\n" ++"X-DL-Domain: po\n" ++"X-DL-State: Translating\n" ++"#-#-#-#-# pt.po (3.8) #-#-#-#-#\n" + "Project-Id-Version: 3.8\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -28,6 +66,93 @@ msgstr "" + "X-Source-Language: C\n" + "X-Project-Style: gnome\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Geral" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "Canto ativo" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "" ++"Toque no canto superior esquerdo para abrir a Visão geral das Atividades." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "Margens de ecrã ativas" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Arraste janelas contra os lados ou a parte superior do ecrã para as " ++"redimensionar." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Áreas de trabalho" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "Áreas de trabalho _dinâmicas" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Remove automaticamente áreas de trabalho vazias." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "Número fixo de áreas de trabalho" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Especifique um número de áreas de trabalho permanentes." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Número de áreas de trabalho" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Multi-Monitor" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Áreas de trabalho apenas no ecrã _principal" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Áreas de trabalho em todos os ecrãs" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Comutação de aplicações" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Incluir aplicações de todas as áreas de trabalho" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Incluir apenas aplicações da área de trabalho atual" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Multitarefa" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Gerir preferências para produtividade e multitarefa" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "Multitasking;Multitask;Productivity;Customize;Desktop;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Barramento do sistema" +@@ -2638,11 +2763,6 @@ msgstr "Nenhuma aplicação requisitou acesso ao microfone" + msgid "Protect your conversations" + msgstr "Proteja suas conversas" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Geral" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Botão primário" +diff --git a/po/pt_BR.po b/po/pt_BR.po +index 0674b4d2c..675f9abbb 100644 +--- a/po/pt_BR.po ++++ b/po/pt_BR.po +@@ -1,3 +1,36 @@ ++# #-#-#-#-# pt_BR.po.multitasking (gnome-control-center) #-#-#-#-# ++# Brazilian Portuguese translation of GNOME Control Center. ++# Copyright (C) 2021 The GNOME Control Center authors. ++# This file is distributed under the same license as the gnome-control-center package. ++# Ivan Passos , 1999. ++# Sandro Nunes Henrique , 1999. ++# Gustavo Maciel Dias Vieira , 2000-2001. ++# Tiago Cardoso Menezes , 2003. ++# Evandro Fernandes Giovanini , 2004, 2006. ++# Alex Camacho Castilho , 2004. ++# Guilherme de S. Pastore , 2004-2005. ++# Leonardo Ferreira Fontenelle , 2006, 2008. ++# Luiz Armesto , 2007-2008. ++# Og Maciel , 2007, 2009-2011. ++# Washington Lins , 2007. ++# Raul Pereira , 2007. ++# Jonh Wendell , 2008, 2009 ++# Henrique P Machado , 2008-2009. ++# Fabrício Godoy , 2008. ++# Djavan Fagundes , 2008, 2009, 2011. ++# André Gondim , 2009. ++# Krix Apolinário , 2009, 2011. ++# Antonio Fernandes C. Neto , 2010, 2013. ++# Hugo Vaz Sampaio , 2010. ++# Djavan Fagundes , 2012. ++# Gustavo Marques , 2015, 2016. ++# Artur de Aquino Morais , 2016. ++# Georges Basile Stavracas Neto , 2013-2019. ++# Bruno Lopes , 2021. ++# Rafael Fontenelle , 2012-2021. ++# Enrico Nicoletto , 2012-2016, 2018-2019, 2021. ++# ++# #-#-#-#-# pt_BR.po (gnome-control-center) #-#-#-#-# + # Brazilian Portuguese translation of GNOME Control Center. + # Copyright (C) 1999-2021 The GNOME Control Center authors. + # This file is distributed under the same license as the gnome-control-center package. +@@ -29,8 +62,25 @@ + # Bruno Lopes , 2021. + # Rafael Fontenelle , 2012-2021. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# pt_BR.po.multitasking (gnome-control-center) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-11-13 18:02+0000\n" ++"PO-Revision-Date: 2021-11-23 04:32-0300\n" ++"Last-Translator: Rafael Fontenelle \n" ++"Language-Team: Brazilian Portuguese \n" ++"Language: pt_BR\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n > 1);\n" ++"X-Generator: Poedit 3.0\n" ++"X-Project-Style: gnome\n" ++"#-#-#-#-# pt_BR.po (gnome-control-center) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -46,6 +96,95 @@ msgstr "" + "X-Generator: Gtranslator 3.38.0\n" + "X-Project-Style: gnome\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Geral" ++ ++# Traduzido como "Canto ativo" conforme tradução do Módulo "gsettings-desktop-schemas" - Enrico. ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "Canto at_ivo" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Toque o canto superior esquerdo para abrir o Panorama de Atividades." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "Bordas de tela _ativas" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Arrasta janelas para as bordas de tela superior, esquerda e direita para " ++"redimensioná-las." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Espaços de trabalho" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "Espaços de trabalho _dinâmicos" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Remove automaticamente espaços de trabalho vazios." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "Número _fixo de espaços de trabalho" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Especifica um número permanente de espaços de trabalho." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Número de espaços de trabalho" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Multi-Monitor" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Espaços de trabalho somente na tela _principal" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Espaços de trabalho em todas as t_elas" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Alternador de aplicativos" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Incluir aplicativos de todos os es_paços de trabalho" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Incluir aplicativos somente do espaço de trabalho at_ual" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Multitarefas" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Gerencie preferências para produtividade e multitarefas" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"Multitarefa;Multitarefas;Produtividade;Personalizar;Customizar;Área de " ++"trabalho;Desktop;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Barramento de sistema" +@@ -2678,11 +2817,6 @@ msgstr "Nenhum aplicativo pediu por acesso ao microfone" + msgid "Protect your conversations" + msgstr "Projeta suas conversas" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Geral" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Botão primário" +diff --git a/po/ro.po b/po/ro.po +index d8a544dd2..f5755d4c5 100644 +--- a/po/ro.po ++++ b/po/ro.po +@@ -12,8 +12,27 @@ + # Lupescu Mircea , 2011. + # Jobava , 2015. + # Daniel Șerbănescu , 2011, 2016-2018, 2020. ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# ro.po.multitasking (gnome-control-center) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-08 08:29+0000\n" ++"PO-Revision-Date: 2021-09-09 13:24+0200\n" ++"Last-Translator: Florentina Mușat \n" ++"Language-Team: Romanian Gnome Team\n" ++"Language: ro\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " ++"20)) ? 1 : 2);\n" ++"X-Generator: Poedit 3.0\n" ++"X-Launchpad-Export-Date: 2014-07-13 17:08+0000\n" ++"X-Project-Style: gnome\n" ++"#-#-#-#-# ro.po (gnome-control-center) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -31,6 +50,98 @@ msgstr "" + "X-Launchpad-Export-Date: 2014-07-13 17:08+0000\n" + "X-Project-Style: gnome\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Generale" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "Colț _important" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "" ++"Atingeți colțul din dreapta sus pentru a deschide Vederea de ansamblu a " ++"Activităților." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "Margini de ecran _active" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Trageți ferestrele spre marginile de sus, stânga și dreapta pentru a le " ++"redimensiona." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Spații de lucru" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "Spații de lucru _dinamice" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Elimină automat spații de lucru goale." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "Spații de lucru _fixe" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Specifică un număr permanent de spații de lucru." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Număr de spații de lucru" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Monitoare multiple" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Spațiile de lucru doar pe afișajul _principal" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Spații de lucru pe toate _ecranele" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Schimbarea între aplicații" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Include aplicații de pe toate _spațiile de lucru" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Include aplicații numai de pe spațiul de lucru _curent" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Sarcini multiple" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "" ++"Administrează preferințele pentru productivitate și efectuarea de sarcini " ++"multiple" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"Multitasking;Multitask;Productivity;Customize;Desktop;Sarcini;Sarcini " ++"multiple;Productivitate;Personalizează;Personalizare;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Magistrala sistemului" +@@ -2655,11 +2766,6 @@ msgstr "Nu sunt aplicații care au cerut accesul la microfon" + msgid "Protect your conversations" + msgstr "Protejați conversațiile" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Generale" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Buton principal" +diff --git a/po/ru.po b/po/ru.po +index e1374c2fb..f338a0e5b 100644 +--- a/po/ru.po ++++ b/po/ru.po +@@ -19,8 +19,25 @@ + # Stas Solovey , 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020. + # Ivan Komaritsyn , 2017. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# ru.po.multitasking (ru) #-#-#-#-#\n" ++"Project-Id-Version: ru\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2022-01-19 02:03+0000\n" ++"PO-Revision-Date: 2022-01-21 23:50+0300\n" ++"Last-Translator: Aleksandr Melman \n" ++"Language-Team: Русский \n" ++"Language: ru\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" ++"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" ++"X-Generator: Poedit 3.0\n" ++"#-#-#-#-# ru.po (ru) #-#-#-#-#\n" + "Project-Id-Version: ru\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -36,6 +53,92 @@ msgstr "" + "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + "X-Generator: Poedit 2.2.4\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Общие" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Горячий угол" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Прикоснитесь к верхнему левому углу экрана, чтобы открыть Обзор." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Активные границы экрана" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Перетащите окна к верхней, левой или правой границе экрана, чтобы " ++"автоматически изменить размер." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Рабочие столы" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Автоматическое управление столами" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Автоматически убирать пустые столы." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Фиксированное количество столов" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Укажите количество столов, которое нужно вам постоянно." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Количество столов" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Для нескольких мониторов" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Рабочие столы только на _главном дисплее" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Рабочие столы на _всех дисплеях" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Переключение между приложениями" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Включать приложения со всех _столов" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Включать приложения _только с текущего стола" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Многозадачность" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Управляйте предпочтениями продуктивности и многозадачности" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "Многозадачность;Продуктивность;Фокус;Настройка;Рабочий стол;" ++ + #: panels/applications/cc-applications-panel.c:708 + msgid "System Bus" + msgstr "Системная шина" +@@ -2758,11 +2861,6 @@ msgstr "Нет приложений запросивших доступ к ми + msgid "Protect your conversations" + msgstr "Защитите ваш обмен сообщениями" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Общие" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Основная кнопка" +diff --git a/po/sk.po b/po/sk.po +index 49f9d06df..dc6448b2a 100644 +--- a/po/sk.po ++++ b/po/sk.po +@@ -1,3 +1,15 @@ ++# #-#-#-#-# sk.po.multitasking (gnome-control-center) #-#-#-#-# ++# Slovak translation for gnome-control-center. ++# Copyright (C) 2000-2005, 2007-2009, 2011-2013 Free Software Foundation, Inc. ++# This file is distributed under the same license as the gnome-control-center package. ++# Stanislav Višňovsky , 2000-2004. ++# Marcel Telka , 2005. ++# Peter Tuhársky , 2007. ++# Pavol Šimo , 2007-2011. ++# Pavol Klačanský , 2012, 2013. ++# Dušan Kazik , 2013-2021. ++# ++# #-#-#-#-# sk.po (gnome-control-center) #-#-#-#-# + # Slovak translation for gnome-control-center. + # Copyright (C) 2000-2005, 2007-2009, 2011-2013 Free Software Foundation, Inc. + # This file is distributed under the same license as the gnome-control-center package. +@@ -8,8 +20,25 @@ + # Pavol Klačanský , 2012, 2013. + # Dušan Kazik , 2013-2020. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# sk.po.multitasking (gnome-control-center) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-25 09:28+0000\n" ++"PO-Revision-Date: 2021-10-01 10:43+0200\n" ++"Last-Translator: Dušan Kazik \n" ++"Language-Team: Slovak \n" ++"Language: sk\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0\n" ++"X-Launchpad-Export-Date: 2012-10-06 09:48+0000\n" ++"X-Generator: Gtranslator 40.0\n" ++"#-#-#-#-# sk.po (gnome-control-center) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -25,6 +54,100 @@ msgstr "" + "X-Launchpad-Export-Date: 2012-10-06 09:48+0000\n" + "X-Generator: Poedit 2.4.1\n" + ++# GtkLabel label ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Všeobecné" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "Aktívny _roh" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Dotykom horného ľavého rohu otvoríte prehľad aktivít." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Aktívne rohy obrazovky" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Potiahnutím okien k hornej, ľavej a pravej hrane obrazovky mu zmeníte " ++"veľkosť." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Pracovné priestory" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Dynamické pracovné priestory" ++ ++# GtkLabel label ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++#| msgid "Automatically Delete Temporary _Files" ++msgid "Automatically removes empty workspaces." ++msgstr "Automaticky odstraňuje prázdne pracovné priestory." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Pevný počet pracovných priestorov" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Určí počet trvalých pracovných priestorov." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Počet pracovných priestorov" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Viacero monitorov" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Pracovné priestory iba na _hlavnom displeji" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Pracovné priestory na všetkých _displejoch" ++ ++# tab ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++#| msgctxt "Wacom action-type" ++#| msgid "Application defined" ++msgid "Application Switching" ++msgstr "Prepínanie aplikácií" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Zahrnúť aplikácie zo všetkých _pracovných priestorov" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Zahrnúť aplikácie iba z _aktuálneho pracovného priestoru" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Súbežná práca" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Spravuje predvoľby pre produktivitu a súbežnú prácu" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"multitasking;súbežná;práca;produktivita;prispôsobiť;prispôsobenie;pracovná;" ++"plocha;" ++ + #: panels/applications/cc-applications-panel.c:815 + msgid "System Bus" + msgstr "Zbernica systému" +@@ -2882,12 +3005,6 @@ msgstr "Žiadne aplikácie si nevyžiadali prístup k mikrofónu" + msgid "Protect your conversations" + msgstr "Ochráňte vaše konverzácie" + +-# GtkLabel label +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Všeobecné" +- + # GtkLabel label + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" +diff --git a/po/sl.po b/po/sl.po +index 37979ffb3..ddef4444a 100644 +--- a/po/sl.po ++++ b/po/sl.po +@@ -1,3 +1,14 @@ ++# #-#-#-#-# sl.po.multitasking (gnome-control-center master) #-#-#-#-# ++# Slovenian translations for gnome-control-center. ++# Copyright (C) 2009 gnome-control-center COPYRIGHT HOLDER ++# This file is distributed under the same license as the gnome-control-center package. ++# ++# Andraž Tori , 2004. ++# Matjaž Horvat , 2005–2006. ++# Matic Žgur , 2006–2007. ++# Matej Urbančič , + 2007–2021. ++# ++# #-#-#-#-# sl.po (gnome-control-center master) #-#-#-#-# + # Slovenian translations for gnome-control-center. + # Copyright (C) 2009 gnome-control-center COPYRIGHT HOLDER + # This file is distributed under the same license as the gnome-control-center package. +@@ -7,8 +18,26 @@ + # Matic Žgur , 2006–2007. + # Matej Urbančič , + 2007–2021. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# sl.po.multitasking (gnome-control-center master) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-14 17:58+0000\n" ++"PO-Revision-Date: 2021-09-14 21:19+0200\n" ++"Last-Translator: Matej Urbančič \n" ++"Language-Team: Slovenian GNOME Translation Team \n" ++"Language: sl_SI\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n" ++"%100==4 ? 3 : 0);\n" ++"X-Poedit-SourceCharset: utf-8\n" ++"X-Generator: Poedit 2.4.2\n" ++"#-#-#-#-# sl.po (gnome-control-center master) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center master\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -25,6 +54,94 @@ msgstr "" + "X-Poedit-SourceCharset: utf-8\n" + "X-Generator: Poedit 2.4.1\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Splošno" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Vroči kot" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Dotik levega zgornjega kota odpre pregled dejavnosti." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Dejavni robovi zaslona" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Dotik okna z zgornjim, levim ali desnim robom sproži dejanje prilagajanja " ++"velikosti okna." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Delovne površine" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Dinamične delovne površine" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Samodejno odstrani prazne delovne površine" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Določeno število delovnih površin" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Število števila prikazanih delovnih površin" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Število delovnih površin" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Podpora več monitorjem" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Delovne površine le na _osnovnem zaslonu" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "_Delovne površine naj bodo na vseh zaslonih" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Preklapljanje programov" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Vključi programe _vseh delovnih površin" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Vključi le programe s _trenutne delovne površine" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Večopravilnost" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Upravljanje nastavitev za učinkovito delo in večopravilnost" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"Multitasking;Multitask;Productivity;Customize;Desktop;Namizje;Večopravilnost;" ++"Učinkovitost;Prilagajanje;Delo;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Sistemsko vodilo" +@@ -2639,11 +2756,6 @@ msgstr "Ni programov, ki bi zahtevali dostop do mikrofona" + msgid "Protect your conversations" + msgstr "Zaščita pogovorov" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Splošno" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Osnovni gumb" +diff --git a/po/sr.po b/po/sr.po +index 446bffd8c..20893c6ea 100644 +--- a/po/sr.po ++++ b/po/sr.po +@@ -1,3 +1,15 @@ ++# #-#-#-#-# sr.po.multitasking (gnome-control-center) #-#-#-#-# ++# Serbian translation of gnome-control-center ++# Courtesy of Prevod.org team (http://prevod.org/) -- 2003–2021. ++# This file is distributed under the same license as the gnome-control-center package. ++# Вељко М. Станојевић ++# Данило Шеган , 2005. ++# Слободан Д. Средојевић , 2006. ++# Милош Поповић , 2010, 2011. ++# Марко М. Костић , 2016. ++# Борисав Живановић , 2017-2018. ++# Мирослав Николић , 2011–2021. ++# #-#-#-#-# sr.po (gnome-control-center) #-#-#-#-# + # Serbian translation of gnome-control-center + # Courtesy of Prevod.org team (http://prevod.org/) -- 2003—2021. + # This file is distributed under the same license as the gnome-control-center package. +@@ -8,8 +20,25 @@ + # Марко М. Костић , 2016. + # Борисав Живановић , 2017-2018. + # Мирослав Николић , 2011—2021. ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# sr.po.multitasking (gnome-control-center) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-24 15:42+0000\n" ++"PO-Revision-Date: 2021-09-26 08:19+0200\n" ++"Last-Translator: Мирослав Николић \n" ++"Language-Team: српски \n" ++"Language: sr\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : n" ++"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" ++"X-Project-Style: gnome\n" ++"#-#-#-#-# sr.po (gnome-control-center) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -25,6 +54,95 @@ msgstr "" + "%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + "X-Project-Style: gnome\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Опште" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "Врући у_гао" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Досегните горњи леви угао да бисте отворили преглед активности." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "Укључене ивице екран_а" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Повуците прозоре ка горњој, левој и десној ивици екрана да бисте променили " ++"величину." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Радни простори" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Динамички радни простори" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Самостално брише празне радне просторе." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Трајни радни простори" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Наведите број трајних радних простора." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Број радних простора" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Више екрана" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Радни _простори само на главном екрану" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Ра_дни простори на свим екранима" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Пребацивање програма" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Прикажи програме са свих _радних простора" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Прикажи програме _само са тренутног радног простора" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Упоредни рад" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Управљајте поставкама продуктивности и упоредног рада" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"Multitasking;Multitask;Productivity;Customize;Desktop;Упоредни рад;" ++"Вишеструки рад;Продуктивност;Прилагоди;Десктоп;Радна површ;Uporedni rad;" ++"Višestruki rad;Produktivnost;Prilagodi;Desktop;Radna površ;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Системска сабирница" +@@ -2672,11 +2790,6 @@ msgstr "Ниједан програм није затражио приступ + msgid "Protect your conversations" + msgstr "Заштитите ваше разговоре" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Опште" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Главно дугме" +diff --git a/po/sv.po b/po/sv.po +index 9d8665c7f..95239c1cb 100644 +--- a/po/sv.po ++++ b/po/sv.po +@@ -1,3 +1,19 @@ ++# #-#-#-#-# sv.po.multitasking (gnome-control-center) #-#-#-#-# ++# Swedish messages for gnome-control-center. ++# Copyright © 1998-2021 Free Software Foundation, Inc. ++# This file is distributed under the same license as the gnome-control-center package. ++# ++# Martin Wahlen , 1998, 1999. ++# Christian Rose , 2000, 2001, 2002, 2003, 2004, 2005. ++# Daniel Nylander , 2006, 2007, 2008, 2009, 2010, 2011, 2012. ++# Josef Andersson , 2014. ++# Åke Engelbrektson , 2014. ++# Anders Jonsson , 2015, 2016, 2017, 2018, 2019, 2020, 2021. ++# Mattias Eriksson , 2015. ++# Sebastian Rasmussen , 2015, 2016. ++# Luna Jernberg , 2020, 2021. ++# ++# #-#-#-#-# sv.po (gnome-control-center) #-#-#-#-# + # Swedish messages for gnome-control-center. + # Copyright © 1998-2021 Free Software Foundation, Inc. + # This file is distributed under the same license as the gnome-control-center package. +@@ -12,8 +28,24 @@ + # Sebastian Rasmussen , 2015, 2016. + # Luna Jernberg , 2020. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# sv.po.multitasking (gnome-control-center) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-08 08:29+0000\n" ++"PO-Revision-Date: 2021-09-08 20:14+0200\n" ++"Last-Translator: Luna Jernberg \n" ++"Language-Team: Swedish \n" ++"Language: sv\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 3.0\n" ++"#-#-#-#-# sv.po (gnome-control-center) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -28,6 +60,92 @@ msgstr "" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" + "X-Generator: Poedit 2.4.2\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Allmänt" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Hett hörn" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Rör det övre vänstra hörnet för att öppna översiktsvyn Aktiviteter." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Aktiva skärmkanter" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Dra fönster mot de övre, vänstra och högra skärmkanterna för att ändra " ++"storlek på dem." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Arbetsytor" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Dynamiska arbetsytor" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Ta automatiskt bort tomma arbetsytor." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Fast antal arbetsytor" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Ange ett antal permanenta arbetsytor." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "A_ntal arbetsytor" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Flera skärmar" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Arbetsytor bara på den _primära skärmen" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Arbetsytor på a_lla skärmar" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Programväxling" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Inkludera program från alla a_rbetsytor" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Inkludera endast program från den a_ktuella arbetsytan" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Multikörning" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Hantera inställningar för produktivitet och multikörning" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "Multitasking;Multitask;Multikörning;Produktivitet;Anpassa;Skrivbord;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Systembuss" +@@ -2624,11 +2742,6 @@ msgstr "Inga program har bett om åtkomst till mikrofonen" + msgid "Protect your conversations" + msgstr "Skydda dina konversationer" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Allmänt" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Primärknapp" +diff --git a/po/tr.po b/po/tr.po +index 51f147bf0..bd5cba02b 100644 +--- a/po/tr.po ++++ b/po/tr.po +@@ -1,3 +1,23 @@ ++# #-#-#-#-# tr.po.multitasking (gnome-control-center) #-#-#-#-# ++# Turkish translation of gnome-control-center. ++# ++# Copyright (C) 2000-2003, 2004, 2005, 2008, 2009, 2011 Free Software Foundation, Inc. ++# Copyright (C) 2012-2019 gnome-control-center'S COPYRIGHT HOLDER ++# This file is distributed under the same license as the gnome-control-center package. ++# ++# Nilgün Belma Bugüner , 2001. ++# Fatih Demir , 2000. ++# Baris Cicek , 2004, 2005, 2008, 2009. ++# Erçin EKER , 2011. ++# ztugcesirin , 2014. ++# Furkan Tokaç , 2017. ++# Furkan Ahmet Kara , 2018. ++# Çağatay Yiğit Şahin , 2018. ++# Sabri Ünal , 2014, 2019. ++# Muhammet Kara , 2011-2021. ++# Emin Tufan Çetin , 2013-2021. ++# ++# #-#-#-#-# tr.po (gnome-control-center) #-#-#-#-# + # Turkish translation of gnome-control-center. + # + # Copyright (C) 2000-2003, 2004, 2005, 2008, 2009, 2011 Free Software Foundation, Inc. +@@ -16,8 +36,24 @@ + # Sabri Ünal , 2014, 2019. + # Emin Tufan Çetin , 2013-2021. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# tr.po.multitasking (gnome-control-center) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-24 15:42+0000\n" ++"PO-Revision-Date: 2021-09-09 22:32+0300\n" ++"Last-Translator: Emin Tufan Çetin \n" ++"Language-Team: Turkish \n" ++"Language: tr\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=1; plural=0;\n" ++"X-Generator: Poedit 2.4.3\n" ++"#-#-#-#-# tr.po (gnome-control-center) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -32,6 +68,90 @@ msgstr "" + "Plural-Forms: nplurals=1; plural=0;\n" + "X-Generator: Poedit 2.4.2\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Genel" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Sıcak Köşe" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Etkinlikler Genel Görünümünü açmak için sol üst köşeye dokun." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Etkin Ekran Köşeleri" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "Pencereleri üste, sola ve sağa sürükleyerek yeniden boyutlandır." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Çalışma Alanları" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Dinamik çalışma alanları" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Boş çalışma alanlarını kendiliğinden kaldırır." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Belirli sayıda çalışma alanları" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Kalıcı çalışma alanı sayısını belirt." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "Çalışma Alanı _Sayısı" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Çoklu Monitör" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Çalışma alanları yalnızca _birincil ekranda" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Çalışma alanları tüm _ekranlarda" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Uygulama Geçişi" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Tüm _çalışma alanlarından uygulamaları içer" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Yalnızca _geçerli çalışma alanından uygulamaları içer" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Çoklu Görev" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Verimlilik ve çoklu görev için tercihleri yönet" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "Çoklugörev;Çoğulgörev;Verimlilik;Üretkenlik;Özelleştir;Masaüstü;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Sistem Veriyolu" +@@ -2629,11 +2749,6 @@ msgstr "Hiçbir Uygulama Mikrofon Erişimi İsteği Yapmadı" + msgid "Protect your conversations" + msgstr "Konuşmalarınızı koruyun" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Genel" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Birincil Düğme" +diff --git a/po/uk.po b/po/uk.po +index 3824c39e7..f65e39cdf 100644 +--- a/po/uk.po ++++ b/po/uk.po +@@ -5,10 +5,29 @@ + # Wanderlust , 2009. + # Daniel Korostil , 2013, 2014, 2015, 2016, 2017. + # Yuri Chornoivan , 2020, 2021. ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# uk.po.multitasking (gnome-control-center) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center\n" +-"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/issues\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-08 08:29+0000\n" ++"PO-Revision-Date: 2021-09-08 12:56+0300\n" ++"Last-Translator: Yuri Chornoivan \n" ++"Language-Team: Ukrainian \n" ++"Language: uk\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n" ++"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" ++"X-Generator: Lokalize 20.12.0\n" ++"X-Project-Style: gnome\n" ++"#-#-#-#-# uk.po (gnome-control-center) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" + "POT-Creation-Date: 2021-02-01 20:21+0000\n" + "PO-Revision-Date: 2021-02-02 09:00+0200\n" + "Last-Translator: Yuri Chornoivan \n" +@@ -17,10 +36,99 @@ msgstr "" + "MIME-Version: 1.0\n" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" +-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" ++"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" ++"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + "X-Generator: Lokalize 20.11.70\n" + "X-Project-Style: gnome\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "Загальне" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Гарячий кут" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Торкніться верхнього лівого кута, щоб відкрити огляд «Діяльності»." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Активні краї екрана" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Перетягніть вікна до верхнього, лівого або правого країв екрана, щоб змінити " ++"їхній розмір." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Робочі простори" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Динамічні робочі простори" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Автоматично вилучає порожні робочі простори." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Фіксована кількість робочих просторів" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Вкажіть кількість сталих робочих просторів." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "_Кількість робочих просторів" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Декілька моніторів" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Робочі простори _лише на основному дисплеї" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Робочі простори на усіх д_исплеях" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Перемикання програм" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Включити програми з усіх _робочих просторів" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Включити лише програми з пото_чного робочого простору" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Багатозадачність" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Керування параметрами продуктивності та багатозадачності" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"Multitasking;Multitask;Productivity;Customize;Desktop;багатозадачність;" ++"задача;завдання;продуктивність;налаштовування;налаштування;стільниця;" ++ + #: panels/applications/cc-applications-panel.c:823 + msgid "System Bus" + msgstr "Системна шина" +@@ -2639,11 +2747,6 @@ msgstr "Немає програм, які б надсилали запит що + msgid "Protect your conversations" + msgstr "Захистіть ваш обмін повідомленнями" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "Загальне" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "Основна кнопка" +@@ -3096,15 +3199,13 @@ msgstr "Адреса IP" + #: panels/network/net-device-ethernet.c:163 + #: panels/network/net-device-mobile.c:456 + msgid "DNS4" +-msgstr "" +-"DNS4" ++msgstr "DNS4" + + #: panels/network/connection-editor/ce-page-details.c:420 + #: panels/network/net-device-ethernet.c:164 + #: panels/network/net-device-mobile.c:457 + msgid "DNS6" +-msgstr "" +-"DNS6" ++msgstr "DNS6" + + #: panels/network/connection-editor/ce-page-details.c:423 + #: panels/network/connection-editor/ce-page-details.c:424 +diff --git a/po/vi.po b/po/vi.po +index 8baf230b2..1b51bad13 100644 +--- a/po/vi.po ++++ b/po/vi.po +@@ -1,3 +1,14 @@ ++# #-#-#-#-# vi.po.multitasking (gnome-control-center master) #-#-#-#-# ++# Vietnamese Translation for GNOME Control Center. ++# Bản dịch tiếng Việt dành cho GNOME Control Center. ++# Copyright © 2016 Free Software Foundation, Inc. ++# This file is distributed under the same license as the gnome-control-center package. ++# Nguyễn Thái Ngọc Duy , 2004,2007,2010-2013. ++# Clytie Siddall , 2005-2009. ++# Ngô Chin , 2011. ++# Trần Ngọc Quân , 2013-2018, 2021. ++# ++# #-#-#-#-# vi.po (gnome-control-center master) #-#-#-#-# + # Vietnamese Translation for GNOME Control Center. + # Bản dịch tiếng Việt dành cho GNOME Control Center. + # Copyright © 2016 Free Software Foundation, Inc. +@@ -7,8 +18,24 @@ + # Ngô Chin , 2011. + # Trần Ngọc Quân , 2013-2014, 2015, 2016, 2017, 2018. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# vi.po.multitasking (gnome-control-center master) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2021-09-27 07:48+0000\n" ++"PO-Revision-Date: 2021-09-28 14:47+0700\n" ++"Last-Translator: Trần Ngọc Quân \n" ++"Language-Team: Vietnamese \n" ++"Language: vi\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=1; plural=0;\n" ++"X-Generator: Gtranslator 3.38.0\n" ++"#-#-#-#-# vi.po (gnome-control-center master) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center master\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -23,6 +50,95 @@ msgstr "" + "Plural-Forms: nplurals=1; plural=0;\n" + "X-Generator: Gtranslator 2.91.7\n" + ++#. #-#-#-#-# vi.po.multitasking (gnome-control-center master) #-#-#-#-# ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++#: panels/mouse/gnome-mouse-properties.ui:45 ++msgid "General" ++msgstr "Chung" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "_Góc nóng" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "Di chuyển chuột đến góc trên-trái để mở “Tổng quan hoạt động”." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "_Kích hoạt cạnh màn hình" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "" ++"Kéo cửa sổ vào đỉnh, trái, và phải màn hình để thay đổi kích thước của chúng." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "Không gian làm việc" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "_Không gian làm việc động" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "Tự động xóa bỏ không gian làm việc trống rỗng." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "_Cố định số lượng không gian làm việc" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "Chỉ định số không gian làm việc cố định." ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "Số lượng _không gian làm việc" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "Đa màn hình" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "Không gian làm việc chỉ ở trên màn hình _chính" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "Hiển thị không gian làm việc trên mọ_i màn hình" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "Chuyển ứng dụng" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "Bao gồm các ứng dụng từ mọi _không gian việc" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "Bao gồm các ứng dụng _chỉ từ không gian việc hiện tại thôi" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "Đa nhiệm" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "Quản lý các tùy chỉnh cho năng suất và đa nhiệm" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"Multitasking;Multitask;Productivity;Customize;Desktop;Đa;nhiệm;Tùy;chọn;" ++"chỉnh;da nhiem;" ++ + #: panels/background/background.ui:49 + msgid "_Background" + msgstr "Ảnh _nền" +@@ -2003,10 +2119,6 @@ msgstr "" + "Trackpad;Pointer;Con;trỏ;tro;Click;Nhấn;Nhắp;Nhan;Nhap;Tap;Double;Dup;Button;" + "Nút;Nut;Trackball;Scroll;cuộn;cuon;" + +-#: panels/mouse/gnome-mouse-properties.ui:45 +-msgid "General" +-msgstr "Chung" +- + #: panels/mouse/gnome-mouse-properties.ui:83 + msgid "Primary Button" + msgstr "Nút chính" +diff --git a/po/zh_CN.po b/po/zh_CN.po +index ba8a7a8b7..285d6efbe 100644 +--- a/po/zh_CN.po ++++ b/po/zh_CN.po +@@ -1,3 +1,36 @@ ++# #-#-#-#-# zh_CN.po.multitasking (gnome-control-center 41.0) #-#-#-#-# ++# Simplified Chinese translation for gnome-control-center. ++# Copyright (C) 2001-2021 gnome-control-center's COPYRIGHT HOLDER ++# This file is distributed under the same license as gnome-control-center package. ++# Some translations are taken from tranditional Chinese translation. ++# by Abel Cheung , 2001. ++# He Qiangqiang , 2002. ++# Sun G11n , 2002. ++# Funda Wang , 2003-2006. ++# 甘露(Gan Lu) , 2009, 2013. ++# Deng Xiyue , 2009. ++# FujianWzh , 2009. ++# Tao Wei , 2009, 2010. ++# Xhacker Liu , 2010. ++# 朱涛 , 2010. ++# zhang ping , 2010. ++# 指冷玉笙寒 (dhyang) , 2011. ++# Lele Long , 2011. ++# Wind He , 2011. ++# bsfmig , 2012. ++# Cheng Lu , 2012. ++# YunQiang Su , 2011, 2013. ++# Wylmer Wang , 2011, 2012, 2014. ++# Tong Hui , 2014. ++# Eleanor Chen , 2014. ++# Aron Xu , 2010, 2011, 2012, 2013, 2014, 2015. ++# Mingye Wang , 2015. ++# Mingcong Bai , 2015, 2016, 2018. ++# Yuchen Guo , 2020. ++# Dingzhong Chen , 2016-2021. ++# Liu Tao , 2021. ++# ++# #-#-#-#-# zh_CN.po (gnome-control-center master) #-#-#-#-# + # Simplified Chinese translation for gnome-control-center. + # Copyright (C) 2001-2019 gnome-control-center's COPYRIGHT HOLDER + # This file is distributed under the same license as gnome-control-center package. +@@ -28,8 +61,24 @@ + # Dingzhong Chen , 2016-2019. + # Yuchen Guo , 2020. + # ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# zh_CN.po.multitasking (gnome-control-center 41.0) #-#-#-#-#\n" ++"Project-Id-Version: gnome-control-center 41.0\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" ++"issues\n" ++"POT-Creation-Date: 2022-02-07 20:42+0000\n" ++"PO-Revision-Date: 2022-02-07 16:11-0500\n" ++"Last-Translator: Boyuan Yang <073plan@gmail.com>\n" ++"Language-Team: Chinese - China \n" ++"Language: zh_CN\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=1; plural=0;\n" ++"X-Generator: Poedit 3.0.1\n" ++"#-#-#-#-# zh_CN.po (gnome-control-center master) #-#-#-#-#\n" + "Project-Id-Version: gnome-control-center master\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-control-center/" + "issues\n" +@@ -44,6 +93,92 @@ msgstr "" + "Plural-Forms: nplurals=1; plural=0;\n" + "X-Generator: Poedit 2.4.1\n" + ++#. FIXME ++#: panels/mouse/cc-mouse-panel.ui:37 ++#: panels/multitasking/cc-multitasking-panel.ui:31 ++msgid "General" ++msgstr "常规" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:56 ++msgid "_Hot Corner" ++msgstr "热区(_H)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:57 ++msgid "Touch the top-left corner to open the Activities Overview." ++msgstr "触碰屏幕左上角以打开活动概览界面。" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:84 ++msgid "_Active Screen Edges" ++msgstr "激活屏幕边缘(_A)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:85 ++msgid "" ++"Drag windows against the top, left, and right screen edges to resize them." ++msgstr "将窗口拖曳至顶部、底部、左侧和右侧边缘以更改其大小。" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:114 ++msgid "Workspaces" ++msgstr "工作空间" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:139 ++msgid "_Dynamic workspaces" ++msgstr "动态工作空间(_D)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:140 ++msgid "Automatically removes empty workspaces." ++msgstr "自动移除空的工作空间。" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:158 ++msgid "_Fixed number of workspaces" ++msgstr "固定数量的工作空间(_F)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:159 ++msgid "Specify a number of permanent workspaces." ++msgstr "指定永久存在的工作空间的数量。" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:179 ++msgid "_Number of Workspaces" ++msgstr "工作空间数量(_N)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:200 ++msgid "Multi-Monitor" ++msgstr "多显示器" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:225 ++msgid "Workspaces on _primary display only" ++msgstr "工作空间仅位于主显示器上(_P)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:252 ++msgid "Workspaces on all d_isplays" ++msgstr "工作空间位于所有显示器上(_I)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:282 ++msgid "Application Switching" ++msgstr "应用程序切换" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:307 ++msgid "Include applications from all _workspaces" ++msgstr "包括所有工作空间的应用程序(_W)" ++ ++#: panels/multitasking/cc-multitasking-panel.ui:325 ++msgid "Include applications from the _current workspace only" ++msgstr "仅包括当前工作空间中的应用程序(_C)" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:3 ++msgid "Multitasking" ++msgstr "多任务" ++ ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:4 ++msgid "Manage preferences for productivity and multitasking" ++msgstr "管理生产力和多任务的首选项" ++ ++#. Translators: Search terms to find the Search panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++#: panels/multitasking/gnome-multitasking-panel.desktop.in.in:15 ++msgid "Multitasking;Multitask;Productivity;Customize;Desktop;" ++msgstr "" ++"Multitasking;Multitask;Productivity;Customize;Desktop;多任务;多进程;生产力;自" ++"定义;桌面;" ++ + #: panels/applications/cc-applications-panel.c:815 + msgid "System Bus" + msgstr "系统总线" +@@ -2507,11 +2642,6 @@ msgstr "没有应用程序要求访问麦克风" + msgid "Protect your conversations" + msgstr "保护对话" + +-#. FIXME +-#: panels/mouse/cc-mouse-panel.ui:37 +-msgid "General" +-msgstr "常规" +- + #: panels/mouse/cc-mouse-panel.ui:75 + msgid "Primary Button" + msgstr "主按钮" +-- +2.34.1 + diff --git a/SOURCES/distro-logo.patch b/SOURCES/distro-logo.patch new file mode 100644 index 0000000..d59e43a --- /dev/null +++ b/SOURCES/distro-logo.patch @@ -0,0 +1,195 @@ +From 4369e31ec541172e1c0d7c64645c7990e413bbca Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Tue, 9 Mar 2021 14:51:54 -0600 +Subject: [PATCH 1/3] info-overview: add build option to control distributor + logo + +Currently, we display a 256x256 version of the OS icon from +/etc/os-release. This is too big for my taste, and it's also not +sufficient for distros that want to display a logo that is not an icon. +For instance, because we no longer display the operating system name +immediately beneath the logo, it may be desirable to use a logo variant +that includes text. This patch adds a meson build option that +distributions can use to override the logo. + +Because the logo might include text, distributions may want to vary the +logo used in dark mode. A subsequent commit will add a second option for +this. +--- + meson.build | 6 ++++++ + meson_options.txt | 1 + + panels/info-overview/cc-info-overview-panel.c | 4 ++++ + 3 files changed, 11 insertions(+) + +diff --git a/meson.build b/meson.build +index e8333c0da..1661caa4b 100644 +--- a/meson.build ++++ b/meson.build +@@ -50,6 +50,12 @@ foreach define: set_defines + config_h.set_quoted(define[0], define[1]) + endforeach + ++distributor_logo = get_option('distributor_logo') ++if (distributor_logo != '') ++ config_h.set_quoted('DISTRIBUTOR_LOGO', distributor_logo, ++ description: 'Define to absolute path of distributor logo') ++endif ++ + # meson does not support octal values, so it must be handled as a + # string. See: https://github.com/mesonbuild/meson/issues/2047 + config_h.set('USER_DIR_MODE', '0700', +diff --git a/meson_options.txt b/meson_options.txt +index 1b7b54810..93e551373 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -8,3 +8,4 @@ option('tracing', type: 'boolean', value: false, description: 'add extra debuggi + option('wayland', type: 'boolean', value: true, description: 'build with Wayland support') + option('profile', type: 'combo', choices: ['default','development'], value: 'default') + option('malcontent', type: 'boolean', value: false, description: 'build with malcontent support') ++option('distributor_logo', type: 'string', description: 'absolute path to distributor logo for the About panel') +diff --git a/panels/info-overview/cc-info-overview-panel.c b/panels/info-overview/cc-info-overview-panel.c +index bd0e07762..95a5904df 100644 +--- a/panels/info-overview/cc-info-overview-panel.c ++++ b/panels/info-overview/cc-info-overview-panel.c +@@ -869,6 +869,9 @@ cc_info_panel_row_activated_cb (CcInfoOverviewPanel *self, + static void + setup_os_logo (CcInfoOverviewPanel *panel) + { ++#ifdef DISTRIBUTOR_LOGO ++ gtk_image_set_from_file (panel->os_logo, DISTRIBUTOR_LOGO); ++#else + g_autofree char *logo_name = g_get_os_info ("LOGO"); + if (logo_name != NULL) + { +@@ -879,6 +882,7 @@ setup_os_logo (CcInfoOverviewPanel *panel) + { + gtk_image_set_from_resource (panel->os_logo, "/org/gnome/control-center/info-overview/GnomeLogoVerticalMedium.svg"); + } ++#endif + } + + static void +-- +GitLab + + +From f08669767ca87ff99fc08e1a7334c8f2e7f18f0b Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Tue, 9 Mar 2021 16:02:46 -0600 +Subject: [PATCH 2/3] info-overview: add build option to specify a dark mode + logo variant + +Let's allow distributions to specify a different logo to use when using +a dark GTK theme. This is best-effort only since it relies on the +convention that dark themes must end with "dark" and therefore will fail +for a theme named "midnight" or anything that doesn't match convention. +--- + meson.build | 5 ++++ + meson_options.txt | 1 + + panels/info-overview/cc-info-overview-panel.c | 27 +++++++++++++++++++ + 3 files changed, 33 insertions(+) + +diff --git a/meson.build b/meson.build +index 1661caa4b..124171626 100644 +--- a/meson.build ++++ b/meson.build +@@ -54,6 +54,11 @@ distributor_logo = get_option('distributor_logo') + if (distributor_logo != '') + config_h.set_quoted('DISTRIBUTOR_LOGO', distributor_logo, + description: 'Define to absolute path of distributor logo') ++ dark_mode_distributor_logo = get_option('dark_mode_distributor_logo') ++ if (dark_mode_distributor_logo != '') ++ config_h.set_quoted('DARK_MODE_DISTRIBUTOR_LOGO', dark_mode_distributor_logo, ++ description: 'Define to absolute path of distributor logo for use in dark mode') ++ endif + endif + + # meson does not support octal values, so it must be handled as a +diff --git a/meson_options.txt b/meson_options.txt +index 93e551373..5305c8606 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -9,3 +9,4 @@ option('wayland', type: 'boolean', value: true, description: 'build with Wayland + option('profile', type: 'combo', choices: ['default','development'], value: 'default') + option('malcontent', type: 'boolean', value: false, description: 'build with malcontent support') + option('distributor_logo', type: 'string', description: 'absolute path to distributor logo for the About panel') ++option('dark_mode_distributor_logo', type: 'string', description: 'absolute path to distributor logo dark mode variant') +diff --git a/panels/info-overview/cc-info-overview-panel.c b/panels/info-overview/cc-info-overview-panel.c +index 95a5904df..cb20e16b1 100644 +--- a/panels/info-overview/cc-info-overview-panel.c ++++ b/panels/info-overview/cc-info-overview-panel.c +@@ -866,10 +866,37 @@ cc_info_panel_row_activated_cb (CcInfoOverviewPanel *self, + open_software_update (self); + } + ++#ifdef DARK_MODE_DISTRIBUTOR_LOGO ++static gboolean ++is_dark_mode (CcInfoOverviewPanel *panel) ++{ ++ GdkScreen *screen; ++ GtkSettings *settings; ++ g_autofree char *theme_name = NULL; ++ ++ theme_name = g_strdup (g_getenv ("GTK_THEME")); ++ if (theme_name != NULL) ++ return g_str_has_suffix (theme_name, "dark"); ++ ++ screen = gtk_widget_get_screen (GTK_WIDGET (panel)); ++ settings = gtk_settings_get_for_screen (screen); ++ ++ g_object_get (settings, "gtk-theme-name", &theme_name, NULL); ++ return theme_name != NULL && g_str_has_suffix (theme_name, "dark"); ++} ++#endif ++ + static void + setup_os_logo (CcInfoOverviewPanel *panel) + { + #ifdef DISTRIBUTOR_LOGO ++#ifdef DARK_MODE_DISTRIBUTOR_LOGO ++ if (is_dark_mode (panel)) ++ { ++ gtk_image_set_from_file (panel->os_logo, DARK_MODE_DISTRIBUTOR_LOGO); ++ return; ++ } ++#endif + gtk_image_set_from_file (panel->os_logo, DISTRIBUTOR_LOGO); + #else + g_autofree char *logo_name = g_get_os_info ("LOGO"); +-- +GitLab + + +From c379ccc4e8f0bcdee78361f134ba29d3a25f7528 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Wed, 10 Mar 2021 11:30:57 -0600 +Subject: [PATCH 3/3] info-overview: reduce size of logo when using icon from + /etc/os-release + +When using the icon from /etc/os-release, display it as 128x128 rather +than 256x256. In distributions that don't ship a 128x128, such as +Fedora, this results in the 256x256 icon being scaled down to a +reasonable size. 256x256 is so large here as to be clearly undesirable. +128x128 is also the size that Ubuntu uses in its downstream patch. Might +as well reduce the need for patching as far as possible, even though +Fedora doesn't plan to use this codepath. +--- + panels/info-overview/cc-info-overview-panel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/panels/info-overview/cc-info-overview-panel.c b/panels/info-overview/cc-info-overview-panel.c +index cb20e16b1..3575b90c5 100644 +--- a/panels/info-overview/cc-info-overview-panel.c ++++ b/panels/info-overview/cc-info-overview-panel.c +@@ -903,7 +903,7 @@ setup_os_logo (CcInfoOverviewPanel *panel) + if (logo_name != NULL) + { + gtk_image_set_from_icon_name (panel->os_logo, logo_name, GTK_ICON_SIZE_INVALID); +- gtk_image_set_pixel_size (panel->os_logo, 256); ++ gtk_image_set_pixel_size (panel->os_logo, 128); + } + else + { +-- +GitLab + diff --git a/SOURCES/gnome-control-center-Drop-the-unused-build-dependency-on-Grilo.patch b/SOURCES/gnome-control-center-Drop-the-unused-build-dependency-on-Grilo.patch new file mode 100644 index 0000000..2287b1c --- /dev/null +++ b/SOURCES/gnome-control-center-Drop-the-unused-build-dependency-on-Grilo.patch @@ -0,0 +1,1385 @@ +From e2d3f71a37a7e587b0af2a9818377ec1ac098e79 Mon Sep 17 00:00:00 2001 +From: Debarshi Ray +Date: Tue, 20 Apr 2021 23:00:28 +0200 +Subject: [PATCH] background: Drop the unused build dependency on Grilo + +The code that uses Grilo to fetch the user's Flickr photos isn't +actually used by the Background panel, to the extent that the final +binary doesn't even link against Grilo. Getting rid of this unused code +will ensure that distributors aren't needlessly pulling in this +dependency. + +This patch has been customized for RHEL 9 to skip the .gitlab-ci.yml +file, which isn't part of the 'ninja dist' generated tarball. + +https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1345 +--- + build-aux/flatpak/org.gnome.Settings.json | 17 - + panels/background/bg-pictures-source.c | 855 ------------------ + panels/background/bg-pictures-source.h | 46 - + panels/background/cc-background-chooser.c | 1 - + panels/background/cc-background-grilo-miner.c | 315 ------- + panels/background/cc-background-grilo-miner.h | 31 - + panels/background/cc-background-panel.c | 2 - + panels/background/meson.build | 4 - + 8 files changed, 1271 deletions(-) + delete mode 100644 panels/background/bg-pictures-source.c + delete mode 100644 panels/background/bg-pictures-source.h + delete mode 100644 panels/background/cc-background-grilo-miner.c + delete mode 100644 panels/background/cc-background-grilo-miner.h + +diff --git a/build-aux/flatpak/org.gnome.Settings.json b/build-aux/flatpak/org.gnome.Settings.json +index 3e19894b0484..b64b4c2fdbc5 100644 +--- a/build-aux/flatpak/org.gnome.Settings.json ++++ b/build-aux/flatpak/org.gnome.Settings.json +@@ -485,23 +485,6 @@ + } + ] + }, +- { +- "name" : "grilo", +- "buildsystem" : "meson", +- "config-opts" : [ +- "-Denable-grl-pls=false", +- "-Denable-gtk-doc=false", +- "-Denable-introspection=false", +- "-Denable-test-ui=false", +- "-Denable-vala=false" +- ], +- "sources" : [ +- { +- "type" : "git", +- "url" : "https://gitlab.gnome.org/GNOME/grilo.git" +- } +- ] +- }, + { + "name" : "openldap", + "buildsystem" : "autotools", +diff --git a/panels/background/bg-pictures-source.c b/panels/background/bg-pictures-source.c +deleted file mode 100644 +index 3a3027b1391e..000000000000 +--- a/panels/background/bg-pictures-source.c ++++ /dev/null +@@ -1,855 +0,0 @@ +-/* bg-pictures-source.c */ +-/* +- * Copyright (C) 2010 Intel, Inc +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, see . +- * +- * Author: Thomas Wood +- * +- */ +- +-#include +- +-#include "bg-pictures-source.h" +- +-#include "cc-background-grilo-miner.h" +-#include "cc-background-item.h" +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#define ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_NAME "," \ +- G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," \ +- G_FILE_ATTRIBUTE_TIME_MODIFIED +- +-struct _BgPicturesSource +-{ +- BgSource parent_instance; +- +- GCancellable *cancellable; +- +- CcBackgroundGriloMiner *grl_miner; +- +- GFileMonitor *picture_dir_monitor; +- GFileMonitor *cache_dir_monitor; +- +- GHashTable *known_items; +-}; +- +-G_DEFINE_TYPE (BgPicturesSource, bg_pictures_source, BG_TYPE_SOURCE) +- +-const char * const content_types[] = { +- "image/png", +- "image/jp2", +- "image/jpeg", +- "image/bmp", +- "image/svg+xml", +- "image/x-portable-anymap", +- NULL +-}; +- +-const char * const screenshot_types[] = { +- "image/png", +- NULL +-}; +- +-static char *bg_pictures_source_get_unique_filename (const char *uri); +- +-static void picture_opened_for_read (GObject *source_object, GAsyncResult *res, gpointer user_data); +- +-static void +-bg_pictures_source_dispose (GObject *object) +-{ +- BgPicturesSource *source = BG_PICTURES_SOURCE (object); +- +- if (source->cancellable) +- { +- g_cancellable_cancel (source->cancellable); +- g_clear_object (&source->cancellable); +- } +- +- g_clear_object (&source->grl_miner); +- +- G_OBJECT_CLASS (bg_pictures_source_parent_class)->dispose (object); +-} +- +-static void +-bg_pictures_source_finalize (GObject *object) +-{ +- BgPicturesSource *bg_source = BG_PICTURES_SOURCE (object); +- +- g_clear_pointer (&bg_source->known_items, g_hash_table_destroy); +- +- g_clear_object (&bg_source->picture_dir_monitor); +- g_clear_object (&bg_source->cache_dir_monitor); +- +- G_OBJECT_CLASS (bg_pictures_source_parent_class)->finalize (object); +-} +- +-static void +-bg_pictures_source_class_init (BgPicturesSourceClass *klass) +-{ +- GObjectClass *object_class = G_OBJECT_CLASS (klass); +- +- object_class->dispose = bg_pictures_source_dispose; +- object_class->finalize = bg_pictures_source_finalize; +-} +- +-static void +-remove_placeholder (BgPicturesSource *bg_source, +- CcBackgroundItem *item) +-{ +- GListStore *store; +- guint i; +- +- store = bg_source_get_liststore (BG_SOURCE (bg_source)); +- +- for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (store)); i++) +- { +- g_autoptr(CcBackgroundItem) item_n = NULL; +- +- item_n = g_list_model_get_item (G_LIST_MODEL (store), i); +- +- if (item_n == item) +- { +- g_list_store_remove (store, i); +- break; +- } +- } +-} +- +-static gboolean +-picture_needs_rotation (GdkPixbuf *pixbuf) +-{ +- const gchar *str; +- +- str = gdk_pixbuf_get_option (pixbuf, "orientation"); +- if (str == NULL) +- return FALSE; +- +- if (*str == '5' || *str == '6' || *str == '7' || *str == '8') +- return TRUE; +- +- return FALSE; +-} +- +-static GdkPixbuf * +-swap_rotated_pixbuf (GdkPixbuf *pixbuf) +-{ +- GdkPixbuf *tmp_pixbuf; +- +- tmp_pixbuf = gdk_pixbuf_apply_embedded_orientation (pixbuf); +- if (tmp_pixbuf == NULL) +- return pixbuf; +- +- g_object_unref (pixbuf); +- return tmp_pixbuf; +-} +- +-static int +-sort_func (gconstpointer a, +- gconstpointer b, +- gpointer user_data) +-{ +- CcBackgroundItem *item_a; +- CcBackgroundItem *item_b; +- guint64 modified_a; +- guint64 modified_b; +- int retval; +- +- item_a = (CcBackgroundItem *) a; +- item_b = (CcBackgroundItem *) b; +- modified_a = cc_background_item_get_modified (item_a); +- modified_b = cc_background_item_get_modified (item_b); +- +- retval = modified_b - modified_a; +- +- return retval; +-} +- +-static void +-picture_scaled (GObject *source_object, +- GAsyncResult *res, +- gpointer user_data) +-{ +- BgPicturesSource *bg_source; +- CcBackgroundItem *item; +- g_autoptr(GError) error = NULL; +- g_autoptr(GdkPixbuf) pixbuf = NULL; +- const char *software; +- const char *uri; +- GListStore *store; +- cairo_surface_t *surface = NULL; +- int scale_factor; +- gboolean rotation_applied; +- +- item = g_object_get_data (source_object, "item"); +- pixbuf = gdk_pixbuf_new_from_stream_finish (res, &error); +- if (pixbuf == NULL) +- { +- if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) +- { +- g_warning ("Failed to load image: %s", error->message); +- remove_placeholder (BG_PICTURES_SOURCE (user_data), item); +- } +- +- return; +- } +- +- /* since we were not cancelled, we can now cast user_data +- * back to BgPicturesSource. +- */ +- bg_source = BG_PICTURES_SOURCE (user_data); +- store = bg_source_get_liststore (BG_SOURCE (bg_source)); +- uri = cc_background_item_get_uri (item); +- if (uri == NULL) +- uri = cc_background_item_get_source_url (item); +- +- /* Ignore screenshots */ +- software = gdk_pixbuf_get_option (pixbuf, "tEXt::Software"); +- if (software != NULL && +- g_str_equal (software, "gnome-screenshot")) +- { +- g_debug ("Ignored URL '%s' as it's a screenshot from gnome-screenshot", uri); +- remove_placeholder (BG_PICTURES_SOURCE (user_data), item); +- return; +- } +- +- /* Process embedded orientation */ +- rotation_applied = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "rotation-applied")); +- +- if (!rotation_applied && picture_needs_rotation (pixbuf)) +- { +- /* the width and height of pixbuf we requested are wrong for EXIF +- * orientations 5, 6, 7 and 8. the file has to be reloaded. */ +- g_autoptr(GFile) file = NULL; +- +- file = g_file_new_for_uri (uri); +- g_object_set_data (G_OBJECT (item), "needs-rotation", GINT_TO_POINTER (TRUE)); +- g_object_set_data_full (G_OBJECT (file), "item", g_object_ref (item), g_object_unref); +- g_file_read_async (G_FILE (file), G_PRIORITY_DEFAULT, +- bg_source->cancellable, +- picture_opened_for_read, bg_source); +- return; +- } +- +- pixbuf = swap_rotated_pixbuf (pixbuf); +- +- scale_factor = bg_source_get_scale_factor (BG_SOURCE (bg_source)); +- surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale_factor, NULL); +- cc_background_item_load (item, NULL); +- +- /* insert the item into the liststore */ +- g_list_store_insert_sorted (store, item, sort_func, bg_source); +- +- g_hash_table_insert (bg_source->known_items, +- bg_pictures_source_get_unique_filename (uri), +- GINT_TO_POINTER (TRUE)); +- +- g_clear_pointer (&surface, cairo_surface_destroy); +-} +- +-static void +-picture_opened_for_read (GObject *source_object, +- GAsyncResult *res, +- gpointer user_data) +-{ +- BgPicturesSource *bg_source; +- CcBackgroundItem *item; +- g_autoptr(GFileInputStream) stream = NULL; +- g_autoptr(GError) error = NULL; +- gint thumbnail_height; +- gint thumbnail_width; +- gboolean needs_rotation; +- +- item = g_object_get_data (source_object, "item"); +- stream = g_file_read_finish (G_FILE (source_object), res, &error); +- if (stream == NULL) +- { +- if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) +- { +- g_autofree gchar *filename = g_file_get_path (G_FILE (source_object)); +- g_warning ("Failed to load picture '%s': %s", filename, error->message); +- remove_placeholder (BG_PICTURES_SOURCE (user_data), item); +- } +- +- return; +- } +- +- /* since we were not cancelled, we can now cast user_data +- * back to BgPicturesSource. +- */ +- bg_source = BG_PICTURES_SOURCE (user_data); +- +- needs_rotation = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), "needs-rotation")); +- if (needs_rotation) +- { +- /* swap width and height for EXIF orientations that need it */ +- thumbnail_width = bg_source_get_thumbnail_height (BG_SOURCE (bg_source)); +- thumbnail_height = bg_source_get_thumbnail_width (BG_SOURCE (bg_source)); +- g_object_set_data (G_OBJECT (item), "rotation-applied", GINT_TO_POINTER (TRUE)); +- } +- else +- { +- thumbnail_width = bg_source_get_thumbnail_width (BG_SOURCE (bg_source)); +- thumbnail_height = bg_source_get_thumbnail_height (BG_SOURCE (bg_source)); +- } +- +- g_object_set_data_full (G_OBJECT (stream), "item", g_object_ref (item), g_object_unref); +- gdk_pixbuf_new_from_stream_at_scale_async (G_INPUT_STREAM (stream), +- thumbnail_width, thumbnail_height, +- TRUE, +- bg_source->cancellable, +- picture_scaled, bg_source); +-} +- +-static void +-picture_copied_for_read (GObject *source_object, +- GAsyncResult *res, +- gpointer user_data) +-{ +- BgPicturesSource *bg_source; +- CcBackgroundItem *item; +- g_autoptr(GError) error = NULL; +- GFile *thumbnail_file = G_FILE (source_object); +- GFile *native_file; +- +- if (!g_file_copy_finish (thumbnail_file, res, &error)) +- { +- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) +- return; +- else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) +- { +- g_autofree gchar *uri = NULL; +- +- uri = g_file_get_uri (thumbnail_file); +- g_warning ("Failed to download '%s': %s", uri, error->message); +- return; +- } +- } +- +- bg_source = BG_PICTURES_SOURCE (user_data); +- +- native_file = g_object_get_data (G_OBJECT (thumbnail_file), "native-file"); +- item = g_object_get_data (G_OBJECT (thumbnail_file), "item"); +- g_object_set_data_full (G_OBJECT (native_file), "item", g_object_ref (item), g_object_unref); +- g_file_read_async (native_file, +- G_PRIORITY_DEFAULT, +- bg_source->cancellable, +- picture_opened_for_read, +- bg_source); +-} +- +-static gboolean +-in_content_types (const char *content_type) +-{ +- guint i; +- for (i = 0; content_types[i]; i++) +- if (g_str_equal (content_types[i], content_type)) +- return TRUE; +- return FALSE; +-} +- +-static GFile * +-bg_pictures_source_get_cache_file (void) +-{ +- g_autofree gchar *path = NULL; +- GFile *file; +- +- path = bg_pictures_source_get_cache_path (); +- file = g_file_new_for_path (path); +- +- return file; +-} +- +-static gboolean +-add_single_file (BgPicturesSource *bg_source, +- GFile *file, +- const gchar *content_type, +- guint64 mtime) +-{ +- g_autoptr(CcBackgroundItem) item = NULL; +- CcBackgroundItemFlags flags = 0; +- g_autofree gchar *source_uri = NULL; +- g_autofree gchar *uri = NULL; +- gboolean needs_download; +- gboolean retval = FALSE; +- const gchar *pictures_path; +- g_autoptr(GFile) pictures_dir = NULL; +- g_autoptr(GFile) cache_dir = NULL; +- GrlMedia *media; +- +- /* find png and jpeg files */ +- if (!content_type) +- goto out; +- if (!in_content_types (content_type)) +- goto out; +- +- /* create a new CcBackgroundItem */ +- uri = g_file_get_uri (file); +- +- pictures_path = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES); +- if (pictures_path == NULL) +- pictures_path = g_get_home_dir (); +- pictures_dir = g_file_new_for_path (pictures_path); +- cache_dir = bg_pictures_source_get_cache_file (); +- needs_download = !g_file_has_parent (file, pictures_dir) && +- !g_file_has_parent (file, cache_dir); +- +- if (!needs_download) +- { +- source_uri = g_strdup (uri); +- flags |= CC_BACKGROUND_ITEM_HAS_URI; +- } +- else +- { +- source_uri = g_steal_pointer (&uri); +- } +- +- item = cc_background_item_new (uri); +- flags |= CC_BACKGROUND_ITEM_HAS_SHADING | CC_BACKGROUND_ITEM_HAS_PLACEMENT; +- g_object_set (G_OBJECT (item), +- "flags", flags, +- "shading", G_DESKTOP_BACKGROUND_SHADING_SOLID, +- "placement", G_DESKTOP_BACKGROUND_STYLE_ZOOM, +- "modified", mtime, +- "needs-download", needs_download, +- "source-url", source_uri, +- NULL); +- +- media = g_object_get_data (G_OBJECT (file), "grl-media"); +- if (media == NULL) +- { +- g_object_set_data_full (G_OBJECT (file), "item", g_object_ref (item), g_object_unref); +- g_file_read_async (file, G_PRIORITY_DEFAULT, +- bg_source->cancellable, +- picture_opened_for_read, bg_source); +- } +- else +- { +- g_autoptr(GFile) native_file = NULL; +- g_autoptr(GFile) thumbnail_file = NULL; +- g_autofree gchar *native_dir = NULL; +- g_autofree gchar *native_path = NULL; +- const gchar *title; +- const gchar *thumbnail_uri; +- +- title = grl_media_get_title (media); +- g_object_set (G_OBJECT (item), "name", title, NULL); +- +- thumbnail_uri = grl_media_get_thumbnail (media); +- thumbnail_file = g_file_new_for_uri (thumbnail_uri); +- +- native_path = gnome_desktop_thumbnail_path_for_uri (source_uri, GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE); +- native_file = g_file_new_for_path (native_path); +- +- native_dir = g_path_get_dirname (native_path); +- g_mkdir_with_parents (native_dir, USER_DIR_MODE); +- +- g_object_set_data_full (G_OBJECT (thumbnail_file), "item", g_object_ref (item), g_object_unref); +- g_object_set_data_full (G_OBJECT (thumbnail_file), +- "native-file", +- g_object_ref (native_file), +- g_object_unref); +- g_file_copy_async (thumbnail_file, +- native_file, +- G_FILE_COPY_ALL_METADATA, +- G_PRIORITY_DEFAULT, +- bg_source->cancellable, +- NULL, +- NULL, +- picture_copied_for_read, +- bg_source); +- } +- +- retval = TRUE; +- +- out: +- return retval; +-} +- +-static gboolean +-add_single_file_from_info (BgPicturesSource *bg_source, +- GFile *file, +- GFileInfo *info) +-{ +- const gchar *content_type; +- guint64 mtime; +- +- content_type = g_file_info_get_content_type (info); +- mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED); +- return add_single_file (bg_source, file, content_type, mtime); +-} +- +-static gboolean +-add_single_file_from_media (BgPicturesSource *bg_source, +- GFile *file, +- GrlMedia *media) +-{ +- GDateTime *mtime; +- const gchar *content_type; +- gint64 mtime_unix; +- +- content_type = grl_media_get_mime (media); +- +- /* only GRL_METADATA_KEY_CREATION_DATE is implemented in the Flickr +- * plugin, GRL_METADATA_KEY_MODIFICATION_DATE is not +- */ +- mtime = grl_media_get_creation_date (media); +- if (!mtime) +- mtime = grl_media_get_modification_date (media); +- if (mtime) +- mtime_unix = g_date_time_to_unix (mtime); +- else +- mtime_unix = g_get_real_time () / G_USEC_PER_SEC; +- +- return add_single_file (bg_source, file, content_type, (guint64) mtime_unix); +-} +- +-gboolean +-bg_pictures_source_add (BgPicturesSource *bg_source, +- const char *uri, +- GtkTreeRowReference **ret_row_ref) +-{ +- g_autoptr(GFile) file = NULL; +- GFileInfo *info; +- gboolean retval; +- +- file = g_file_new_for_uri (uri); +- info = g_file_query_info (file, ATTRIBUTES, G_FILE_QUERY_INFO_NONE, NULL, NULL); +- if (info == NULL) +- return FALSE; +- +- retval = add_single_file_from_info (bg_source, file, info); +- +- return retval; +-} +- +-gboolean +-bg_pictures_source_remove (BgPicturesSource *bg_source, +- const char *uri) +-{ +- GListStore *store; +- gboolean retval; +- guint i; +- +- retval = FALSE; +- store = bg_source_get_liststore (BG_SOURCE (bg_source)); +- +- for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (store)); i++) +- { +- g_autoptr(CcBackgroundItem) tmp_item = NULL; +- const char *tmp_uri; +- +- tmp_item = g_list_model_get_item (G_LIST_MODEL (store), i); +- tmp_uri = cc_background_item_get_uri (tmp_item); +- if (g_str_equal (tmp_uri, uri)) +- { +- char *uuid; +- uuid = bg_pictures_source_get_unique_filename (uri); +- g_hash_table_insert (bg_source->known_items, +- uuid, NULL); +- +- g_list_store_remove (store, i); +- retval = TRUE; +- break; +- } +- } +- return retval; +-} +- +-static int +-file_sort_func (gconstpointer a, +- gconstpointer b) +-{ +- GFileInfo *file_a = G_FILE_INFO (a); +- GFileInfo *file_b = G_FILE_INFO (b); +- guint64 modified_a, modified_b; +- +- modified_a = g_file_info_get_attribute_uint64 (file_a, G_FILE_ATTRIBUTE_TIME_MODIFIED); +- +- modified_b = g_file_info_get_attribute_uint64 (file_b, G_FILE_ATTRIBUTE_TIME_MODIFIED); +- +- return modified_b - modified_a; +-} +- +-static void +-file_info_async_ready (GObject *source, +- GAsyncResult *res, +- gpointer user_data) +-{ +- BgPicturesSource *bg_source; +- GList *files, *l; +- g_autoptr(GError) err = NULL; +- GFile *parent; +- +- files = g_file_enumerator_next_files_finish (G_FILE_ENUMERATOR (source), +- res, +- &err); +- if (err) +- { +- if (!g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) +- g_warning ("Could not get pictures file information: %s", err->message); +- +- g_list_foreach (files, (GFunc) g_object_unref, NULL); +- g_list_free (files); +- return; +- } +- +- bg_source = BG_PICTURES_SOURCE (user_data); +- +- parent = g_file_enumerator_get_container (G_FILE_ENUMERATOR (source)); +- +- files = g_list_sort (files, file_sort_func); +- +- /* iterate over the available files */ +- for (l = files; l; l = g_list_next (l)) +- { +- GFileInfo *info = l->data; +- g_autoptr(GFile) file = NULL; +- +- file = g_file_get_child (parent, g_file_info_get_name (info)); +- +- add_single_file_from_info (bg_source, file, info); +- } +- +- g_list_foreach (files, (GFunc) g_object_unref, NULL); +- g_list_free (files); +-} +- +-static void +-dir_enum_async_ready (GObject *s, +- GAsyncResult *res, +- gpointer user_data) +-{ +- BgPicturesSource *source = (BgPicturesSource *) user_data; +- g_autoptr(GFileEnumerator) enumerator = NULL; +- g_autoptr(GError) err = NULL; +- +- enumerator = g_file_enumerate_children_finish (G_FILE (s), res, &err); +- +- if (err) +- { +- if (!g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) +- g_warning ("Could not fill pictures source: %s", err->message); +- return; +- } +- +- /* get the files */ +- g_file_enumerator_next_files_async (enumerator, +- G_MAXINT, +- G_PRIORITY_LOW, +- source->cancellable, +- file_info_async_ready, +- user_data); +-} +- +-char * +-bg_pictures_source_get_cache_path (void) +-{ +- return g_build_filename (g_get_user_cache_dir (), +- "gnome-control-center", +- "backgrounds", +- NULL); +-} +- +-static char * +-bg_pictures_source_get_unique_filename (const char *uri) +-{ +- g_autoptr(GChecksum) csum = NULL; +- char *ret; +- +- csum = g_checksum_new (G_CHECKSUM_SHA256); +- g_checksum_update (csum, (guchar *) uri, -1); +- ret = g_strdup (g_checksum_get_string (csum)); +- +- return ret; +-} +- +-char * +-bg_pictures_source_get_unique_path (const char *uri) +-{ +- g_autoptr(GFile) parent = NULL; +- g_autoptr(GFile) file = NULL; +- g_autofree gchar *cache_path = NULL; +- g_autofree gchar *filename = NULL; +- +- cache_path = bg_pictures_source_get_cache_path (); +- parent = g_file_new_for_path (cache_path); +- +- filename = bg_pictures_source_get_unique_filename (uri); +- file = g_file_get_child (parent, filename); +- +- return g_file_get_path (file); +-} +- +-gboolean +-bg_pictures_source_is_known (BgPicturesSource *bg_source, +- const char *uri) +-{ +- g_autofree gchar *uuid = NULL; +- +- uuid = bg_pictures_source_get_unique_filename (uri); +- +- return GPOINTER_TO_INT (g_hash_table_lookup (bg_source->known_items, uuid)); +-} +- +-static void +-file_info_ready (GObject *object, +- GAsyncResult *res, +- gpointer user_data) +-{ +- GFileInfo *info; +- GError *error = NULL; +- GFile *file = G_FILE (object); +- +- info = g_file_query_info_finish (file, res, &error); +- +- if (!info) +- { +- if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) +- g_warning ("Problem looking up file info: %s", error->message); +- g_clear_error (&error); +- return; +- } +- +- add_single_file_from_info (BG_PICTURES_SOURCE (user_data), file, info); +-} +- +-static void +-file_added (GFile *file, +- BgPicturesSource *self) +-{ +- g_autofree gchar *uri = NULL; +- uri = g_file_get_uri (file); +- +- if (!bg_pictures_source_is_known (self, uri)) +- { +- g_file_query_info_async (file, +- ATTRIBUTES, +- G_FILE_QUERY_INFO_NONE, +- G_PRIORITY_LOW, +- NULL, +- file_info_ready, +- self); +- } +-} +- +-static void +-files_changed_cb (BgPicturesSource *self, +- GFile *file, +- GFile *other_file, +- GFileMonitorEvent event_type) +-{ +- g_autofree gchar *uri = NULL; +- +- switch (event_type) +- { +- case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: +- file_added (file, self); +- break; +- +- case G_FILE_MONITOR_EVENT_DELETED: +- uri = g_file_get_uri (file); +- bg_pictures_source_remove (self, uri); +- break; +- +- default: +- return; +- } +-} +- +-static GFileMonitor * +-monitor_path (BgPicturesSource *self, +- const char *path) +-{ +- GFileMonitor *monitor; +- g_autoptr(GFile) dir = NULL; +- +- g_mkdir_with_parents (path, USER_DIR_MODE); +- +- dir = g_file_new_for_path (path); +- g_file_enumerate_children_async (dir, +- ATTRIBUTES, +- G_FILE_QUERY_INFO_NONE, +- G_PRIORITY_LOW, self->cancellable, +- dir_enum_async_ready, self); +- +- monitor = g_file_monitor_directory (dir, +- G_FILE_MONITOR_NONE, +- self->cancellable, +- NULL); +- +- if (monitor) +- g_signal_connect_object (monitor, +- "changed", +- G_CALLBACK (files_changed_cb), +- self, G_CONNECT_SWAPPED); +- +- return monitor; +-} +- +-static void +-media_found_cb (BgPicturesSource *self, GrlMedia *media) +-{ +- g_autoptr(GFile) file = NULL; +- const gchar *uri; +- +- uri = grl_media_get_url (media); +- file = g_file_new_for_uri (uri); +- g_object_set_data_full (G_OBJECT (file), "grl-media", g_object_ref (media), g_object_unref); +- add_single_file_from_media (self, file, media); +-} +- +-static void +-bg_pictures_source_init (BgPicturesSource *self) +-{ +- const gchar *pictures_path; +- g_autofree gchar *cache_path = NULL; +- +- self->cancellable = g_cancellable_new (); +- self->known_items = g_hash_table_new_full (g_str_hash, +- g_str_equal, +- (GDestroyNotify) g_free, +- NULL); +- +- pictures_path = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES); +- if (pictures_path == NULL) +- pictures_path = g_get_home_dir (); +- +- self->picture_dir_monitor = monitor_path (self, pictures_path); +- +- cache_path = bg_pictures_source_get_cache_path (); +- self->cache_dir_monitor = monitor_path (self, cache_path); +- +- self->grl_miner = cc_background_grilo_miner_new (); +- g_signal_connect_object (self->grl_miner, "media-found", G_CALLBACK (media_found_cb), self, G_CONNECT_SWAPPED); +- cc_background_grilo_miner_start (self->grl_miner); +-} +- +-BgPicturesSource * +-bg_pictures_source_new (GtkWidget *widget) +-{ +- return g_object_new (BG_TYPE_PICTURES_SOURCE, "widget", widget, NULL); +-} +- +-const char * const * +-bg_pictures_get_support_content_types (void) +-{ +- return content_types; +-} +diff --git a/panels/background/bg-pictures-source.h b/panels/background/bg-pictures-source.h +deleted file mode 100644 +index f62cbe532e26..000000000000 +--- a/panels/background/bg-pictures-source.h ++++ /dev/null +@@ -1,46 +0,0 @@ +-/* bg-pictures-source.h */ +-/* +- * Copyright (C) 2010 Intel, Inc +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, see . +- * +- * Author: Thomas Wood +- * +- */ +- +-#pragma once +- +-#include +-#include "bg-source.h" +-#include "cc-background-item.h" +- +-G_BEGIN_DECLS +- +-#define BG_TYPE_PICTURES_SOURCE (bg_pictures_source_get_type ()) +-G_DECLARE_FINAL_TYPE (BgPicturesSource, bg_pictures_source, BG, PICTURES_SOURCE, BgSource) +- +-BgPicturesSource *bg_pictures_source_new (GtkWidget *widget); +-char *bg_pictures_source_get_cache_path (void); +-char *bg_pictures_source_get_unique_path(const char *uri); +-gboolean bg_pictures_source_add (BgPicturesSource *bg_source, +- const char *uri, +- GtkTreeRowReference **ret_row_ref); +-gboolean bg_pictures_source_remove (BgPicturesSource *bg_source, +- const char *uri); +-gboolean bg_pictures_source_is_known (BgPicturesSource *bg_source, +- const char *uri); +- +-const char * const * bg_pictures_get_support_content_types (void); +- +-G_END_DECLS +diff --git a/panels/background/cc-background-chooser.c b/panels/background/cc-background-chooser.c +index 6c8f56136271..04fd85c477aa 100644 +--- a/panels/background/cc-background-chooser.c ++++ b/panels/background/cc-background-chooser.c +@@ -25,7 +25,6 @@ + #include + + #include "bg-colors-source.h" +-#include "bg-pictures-source.h" + #include "bg-recent-source.h" + #include "bg-wallpapers-source.h" + #include "cc-background-chooser.h" +diff --git a/panels/background/cc-background-grilo-miner.c b/panels/background/cc-background-grilo-miner.c +deleted file mode 100644 +index 85c09daf6928..000000000000 +--- a/panels/background/cc-background-grilo-miner.c ++++ /dev/null +@@ -1,315 +0,0 @@ +-/* +- * Copyright (C) 2014 Red Hat, Inc. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, see . +- */ +- +-#include +- +-#include +-#include +- +-#define GOA_API_IS_SUBJECT_TO_CHANGE +-#include +- +-#include "bg-pictures-source.h" +-#include "cc-background-grilo-miner.h" +- +-struct _CcBackgroundGriloMiner +-{ +- GObject parent_instance; +- +- GCancellable *cancellable; +- GList *accounts; +-}; +- +-G_DEFINE_TYPE (CcBackgroundGriloMiner, cc_background_grilo_miner, G_TYPE_OBJECT) +- +-enum +-{ +- MEDIA_FOUND, +- LAST_SIGNAL +-}; +- +-static guint signals[LAST_SIGNAL] = { 0 }; +- +-#define REMOTE_ITEM_COUNT 50 +- +-static gchar * +-get_grilo_id (GoaObject *goa_object) +-{ +- GoaAccount *account; +- +- account = goa_object_peek_account (goa_object); +- return g_strdup_printf ("grl-flickr-%s", goa_account_get_id (account)); +-} +- +-static void +-is_online_data_cached (GObject *object, +- GAsyncResult *res, +- gpointer user_data) +-{ +- CcBackgroundGriloMiner *self; +- GError *error = NULL; +- GFileInfo *info = NULL; +- GFile *cache_file = G_FILE (object); +- GrlMedia *media; +- const gchar *uri; +- +- info = g_file_query_info_finish (cache_file, res, &error); +- if (info == NULL) +- { +- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) +- goto out; +- } +- +- self = CC_BACKGROUND_GRILO_MINER (user_data); +- +- media = g_object_get_data (G_OBJECT (cache_file), "grl-media"); +- uri = grl_media_get_url (media); +- +- if (info != NULL) +- { +- g_debug ("Ignored URL '%s' as it is already in the cache", uri); +- goto out; +- } +- +- g_signal_emit (self, signals[MEDIA_FOUND], 0, media); +- +- out: +- g_clear_object (&info); +- g_clear_error (&error); +-} +- +-static void +-searched_online_source (GrlSource *source, +- guint operation_id, +- GrlMedia *media, +- guint remaining, +- gpointer user_data, +- const GError *error) +-{ +- CcBackgroundGriloMiner *self = CC_BACKGROUND_GRILO_MINER (user_data); +- g_autoptr(GFile) cache_file = NULL; +- const gchar *uri; +- g_autofree gchar *cache_path = NULL; +- +- if (error != NULL) +- { +- const gchar *source_id; +- +- source_id = grl_source_get_id (source); +- g_warning ("Error searching %s: %s", source_id, error->message); +- grl_operation_cancel (operation_id); +- remaining = 0; +- goto out; +- } +- +- uri = grl_media_get_url (media); +- cache_path = bg_pictures_source_get_unique_path (uri); +- cache_file = g_file_new_for_path (cache_path); +- g_object_set_data_full (G_OBJECT (cache_file), "grl-media", media, g_object_unref); +- g_file_query_info_async (cache_file, +- G_FILE_ATTRIBUTE_STANDARD_TYPE, +- G_FILE_QUERY_INFO_NONE, +- G_PRIORITY_DEFAULT, +- self->cancellable, +- is_online_data_cached, +- self); +- +- out: +- if (remaining == 0) +- g_object_unref (self); +-} +- +-static void +-query_online_source (CcBackgroundGriloMiner *self, GrlSource *source) +-{ +- const GList *keys; +- GrlCaps *caps; +- GrlOperationOptions *options; +- +- keys = grl_source_supported_keys (source); +- caps = grl_source_get_caps (source, GRL_OP_BROWSE); +- options = grl_operation_options_new (caps); +- grl_operation_options_set_count (options, REMOTE_ITEM_COUNT); +- grl_operation_options_set_resolution_flags (options, GRL_RESOLVE_FAST_ONLY); +- grl_operation_options_set_type_filter (options, GRL_TYPE_FILTER_IMAGE); +- +- grl_source_search (source, NULL, keys, options, searched_online_source, g_object_ref (self)); +- g_object_unref (options); +-} +- +-static void +-add_online_source_cb (CcBackgroundGriloMiner *self, +- GrlSource *source) +-{ +- GList *l; +- gboolean found = FALSE; +- const gchar *source_id; +- +- source_id = grl_source_get_id (source); +- for (l = self->accounts; l != NULL && !found; l = l->next) +- { +- GoaObject *goa_object = GOA_OBJECT (l->data); +- g_autofree gchar *account_id = NULL; +- +- account_id = get_grilo_id (goa_object); +- if (g_strcmp0 (source_id, account_id) == 0) +- { +- query_online_source (self, source); +- found = TRUE; +- } +- } +-} +- +-static void +-client_async_ready (GObject *source, +- GAsyncResult *res, +- gpointer user_data) +-{ +- CcBackgroundGriloMiner *self; +- g_autoptr(GError) error = NULL; +- GList *accounts = NULL; +- GList *photo_accounts = NULL; +- GList *l; +- GoaClient *client = NULL; +- GrlRegistry *registry; +- +- client = goa_client_new_finish (res, &error); +- if (client == NULL) +- { +- if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) +- g_warning ("Failed to create GoaClient: %s", error->message); +- goto out; +- } +- +- self = CC_BACKGROUND_GRILO_MINER (user_data); +- +- accounts = goa_client_get_accounts (client); +- for (l = accounts; l != NULL; l = l->next) +- { +- GoaObject *goa_object = GOA_OBJECT (l->data); +- GoaAccount *account; +- GoaPhotos *photos; +- const gchar *provider_type; +- +- account = goa_object_peek_account (goa_object); +- provider_type = goa_account_get_provider_type (account); +- +- photos = goa_object_peek_photos (goa_object); +- if (photos != NULL && g_strcmp0 (provider_type, "flickr") == 0) +- photo_accounts = g_list_prepend (photo_accounts, g_object_ref (goa_object)); +- } +- +- if (photo_accounts == NULL) +- goto out; +- +- registry = grl_registry_get_default (); +- +- for (l = photo_accounts; l != NULL; l = l->next) +- { +- GoaObject *goa_object = GOA_OBJECT (l->data); +- GrlSource *source; +- g_autofree gchar *account_id = NULL; +- +- account_id = get_grilo_id (goa_object); +- source = grl_registry_lookup_source (registry, account_id); +- if (source != NULL) +- query_online_source (self, source); +- } +- +- self->accounts = photo_accounts; +- photo_accounts = NULL; +- +- g_signal_connect_object (registry, "source-added", G_CALLBACK (add_online_source_cb), self, G_CONNECT_SWAPPED); +- +- out: +- g_list_free_full (photo_accounts, g_object_unref); +- g_list_free_full (accounts, g_object_unref); +- g_clear_object (&client); +-} +- +-static void +-setup_online_accounts (CcBackgroundGriloMiner *self) +-{ +- goa_client_new (self->cancellable, client_async_ready, self); +-} +- +-static void +-cc_background_grilo_miner_dispose (GObject *object) +-{ +- CcBackgroundGriloMiner *self = CC_BACKGROUND_GRILO_MINER (object); +- +- if (self->cancellable) +- { +- g_cancellable_cancel (self->cancellable); +- g_clear_object (&self->cancellable); +- } +- +- if (self->accounts) +- { +- g_list_free_full (self->accounts, g_object_unref); +- self->accounts = NULL; +- } +- +- G_OBJECT_CLASS (cc_background_grilo_miner_parent_class)->dispose (object); +-} +- +-static void +-cc_background_grilo_miner_init (CcBackgroundGriloMiner *self) +-{ +- self->cancellable = g_cancellable_new (); +-} +- +-static void +-cc_background_grilo_miner_class_init (CcBackgroundGriloMinerClass *klass) +-{ +- g_autoptr(GError) error = NULL; +- GObjectClass *object_class = G_OBJECT_CLASS (klass); +- GrlRegistry *registry; +- +- object_class->dispose = cc_background_grilo_miner_dispose; +- +- signals[MEDIA_FOUND] = g_signal_new ("media-found", +- G_TYPE_FROM_CLASS (klass), +- G_SIGNAL_RUN_LAST, +- 0, /* class_offset */ +- NULL, /* accumulator */ +- NULL, /* accu_data */ +- g_cclosure_marshal_VOID__OBJECT, +- G_TYPE_NONE, +- 1, +- GRL_TYPE_MEDIA); +- +- grl_init (NULL, NULL); +- registry = grl_registry_get_default (); +- +- error = NULL; +- if (!grl_registry_load_all_plugins (registry, FALSE, &error) || +- !grl_registry_activate_plugin_by_id (registry, "grl-flickr", &error)) +- g_warning ("%s", error->message); +-} +- +-CcBackgroundGriloMiner * +-cc_background_grilo_miner_new (void) +-{ +- return g_object_new (CC_TYPE_BACKGROUND_GRILO_MINER, NULL); +-} +- +-void +-cc_background_grilo_miner_start (CcBackgroundGriloMiner *self) +-{ +- setup_online_accounts (self); +-} +diff --git a/panels/background/cc-background-grilo-miner.h b/panels/background/cc-background-grilo-miner.h +deleted file mode 100644 +index b018129aeba5..000000000000 +--- a/panels/background/cc-background-grilo-miner.h ++++ /dev/null +@@ -1,31 +0,0 @@ +-/* +- * Copyright (C) 2014 Red Hat, Inc. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, see . +- */ +- +-#pragma once +- +-#include +- +-G_BEGIN_DECLS +- +-#define CC_TYPE_BACKGROUND_GRILO_MINER (cc_background_grilo_miner_get_type ()) +-G_DECLARE_FINAL_TYPE (CcBackgroundGriloMiner, cc_background_grilo_miner, CC, BACKGROUND_GRILO_MINER, GObject); +- +-CcBackgroundGriloMiner *cc_background_grilo_miner_new (void); +- +-void cc_background_grilo_miner_start (CcBackgroundGriloMiner *self); +- +-G_END_DECLS +diff --git a/panels/background/cc-background-panel.c b/panels/background/cc-background-panel.c +index 29dedf1653ad..3e50f506b514 100644 +--- a/panels/background/cc-background-panel.c ++++ b/panels/background/cc-background-panel.c +@@ -35,8 +35,6 @@ + #include "cc-background-resources.h" + #include "cc-background-xml.h" + +-#include "bg-pictures-source.h" +- + #define WP_PATH_ID "org.gnome.desktop.background" + #define WP_LOCK_PATH_ID "org.gnome.desktop.screensaver" + #define WP_URI_KEY "picture-uri" +diff --git a/panels/background/meson.build b/panels/background/meson.build +index e9fa398d4ceb..eb5e9ec84625 100644 +--- a/panels/background/meson.build ++++ b/panels/background/meson.build +@@ -76,12 +76,10 @@ common_sources += gnome.compile_resources( + + sources = common_sources + files( + 'bg-colors-source.c', +- 'bg-pictures-source.c', + 'bg-recent-source.c', + 'bg-source.c', + 'bg-wallpapers-source.c', + 'cc-background-chooser.c', +- 'cc-background-grilo-miner.c', + 'cc-background-item.c', + 'cc-background-panel.c', + 'cc-background-preview.c', +@@ -91,10 +89,8 @@ sources = common_sources + files( + deps = common_deps + [ + gdk_pixbuf_dep, + gnome_desktop_dep, +- goa_dep, + libxml_dep, + dependency('cairo-gobject'), +- dependency('grilo-0.3', version: '>= 0.3.0') + ] + + cflags += [ +-- +2.30.2 + diff --git a/SOURCES/power-profiles-backport.patch b/SOURCES/power-profiles-backport.patch new file mode 100644 index 0000000..641beff --- /dev/null +++ b/SOURCES/power-profiles-backport.patch @@ -0,0 +1,5102 @@ +From 1e3569e2f6c2c418b84ea3aa6ce5f84166ec48a7 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Wed, 31 Mar 2021 11:06:44 +0200 +Subject: [PATCH 01/33] power: Fix possible assertion on startup + +When opening the Power panel, and if power-profiles-daemon isn't already +started, we'll be autostarting it, making it send signals about all the +changed properties, including "PerformanceInhibited" even if we +don't have a Performance row. + +Ignore the property change if we don't have a row for it rather than +asserting. + + #0 0x00007f73916bc292 in raise () from /lib64/libc.so.6 + #1 0x00007f73916a58a4 in abort () from /lib64/libc.so.6 + #2 0x00007f7393203ccc in g_assertion_message.cold () from /lib64/libglib-2.0.so.0 + #3 0x00007f739325f22f in g_assertion_message_expr () from /lib64/libglib-2.0.so.0 + #4 0x000055a4099e28ae in performance_profile_set_inhibited (self=0x55a40b37e320, self=0x55a40b37e320, performance_inhibited=) at ../panels/power/cc-power-panel.c:1366 + #5 power_profiles_properties_changed_cb (self=0x55a40b37e320, changed_properties=, invalidated_properties=, proxy=) at ../panels/power/cc-power-panel.c:1425 + #6 0x00007f7393332c2f in g_closure_invoke () from /lib64/libgobject-2.0.so.0 + #7 0x00007f739334eea6 in signal_emit_unlocked_R () from /lib64/libgobject-2.0.so.0 + +1362 { +1363 CcPowerProfileRow *row; +1364 +1365 row = self->power_profiles_row[CC_POWER_PROFILE_PERFORMANCE]; +1366 g_assert (row != NULL); +1367 cc_power_profile_row_set_performance_inhibited (row, performance_inhibited); +1368 } +--- + panels/power/cc-power-panel.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c +index c9c4705da..0b8226a29 100644 +--- a/panels/power/cc-power-panel.c ++++ b/panels/power/cc-power-panel.c +@@ -1363,7 +1363,8 @@ performance_profile_set_inhibited (CcPowerPanel *self, + CcPowerProfileRow *row; + + row = self->power_profiles_row[CC_POWER_PROFILE_PERFORMANCE]; +- g_assert (row != NULL); ++ if (!row) ++ return; + cc_power_profile_row_set_performance_inhibited (row, performance_inhibited); + } + +-- +2.32.0 + + +From da2248d43f519f13b57e89cdc80bbbfe346ad463 Mon Sep 17 00:00:00 2001 +From: Adrien Plazas +Date: Thu, 7 Jan 2021 14:00:15 +0100 +Subject: [PATCH 02/33] power: Simplifies keyboard navigation + +This drops the ability to loop through the page but significantly +simplifies the code. I think this is a good tradeoff as looping is a +rather unexpected behavior. +--- + panels/power/cc-power-panel.c | 70 ++--------------------------------- + 1 file changed, 4 insertions(+), 66 deletions(-) + +diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c +index 0b8226a29..1d31a8a83 100644 +--- a/panels/power/cc-power-panel.c ++++ b/panels/power/cc-power-panel.c +@@ -122,9 +122,6 @@ struct _CcPowerPanel + gboolean has_batteries; + char *chassis_type; + +- GList *boxes; +- GList *boxes_reverse; +- + GDBusProxy *bt_rfkill; + GDBusProxy *bt_properties; + +@@ -169,8 +166,6 @@ cc_power_panel_dispose (GObject *object) + #ifdef HAVE_NETWORK_MANAGER + g_clear_object (&self->nm_client); + #endif +- g_clear_pointer (&self->boxes, g_list_free); +- g_clear_pointer (&self->boxes_reverse, g_list_free); + if (self->iio_proxy_watch_id != 0) + g_bus_unwatch_name (self->iio_proxy_watch_id); + self->iio_proxy_watch_id = 0; +@@ -869,60 +864,12 @@ nm_client_ready_cb (GObject *source_object, + static gboolean + keynav_failed_cb (CcPowerPanel *self, GtkDirectionType direction, GtkWidget *list) + { +- GtkWidget *next_list = NULL; +- GList *item, *boxes_list; +- gdouble value, lower, upper, page; +- +- /* Find the list in the list of GtkListBoxes */ +- if (direction == GTK_DIR_DOWN) +- boxes_list = self->boxes; +- else +- boxes_list = self->boxes_reverse; +- +- item = g_list_find (boxes_list, list); +- g_assert (item); +- item = item->next; +- while (1) +- { +- if (item == NULL) +- item = boxes_list; +- +- /* Avoid looping */ +- if (item->data == list) +- break; +- +- if (gtk_widget_is_visible (item->data)) +- { +- next_list = item->data; +- break; +- } +- +- item = item->next; +- } +- +- if (next_list) +- { +- gtk_widget_child_focus (next_list, direction); +- return TRUE; +- } +- +- value = gtk_adjustment_get_value (self->focus_adjustment); +- lower = gtk_adjustment_get_lower (self->focus_adjustment); +- upper = gtk_adjustment_get_upper (self->focus_adjustment); +- page = gtk_adjustment_get_page_size (self->focus_adjustment); ++ if (direction != GTK_DIR_UP && direction != GTK_DIR_DOWN) ++ return FALSE; + +- if (direction == GTK_DIR_UP && value > lower) +- { +- gtk_adjustment_set_value (self->focus_adjustment, lower); +- return TRUE; +- } +- else if (direction == GTK_DIR_DOWN && value < upper - page) +- { +- gtk_adjustment_set_value (self->focus_adjustment, upper - page); +- return TRUE; +- } ++ direction == GTK_DIR_UP ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD; + +- return FALSE; ++ return gtk_widget_child_focus (GTK_WIDGET (self), direction); + } + + static void +@@ -1559,8 +1506,6 @@ setup_power_profiles (CcPowerPanel *self) + + gtk_widget_show (GTK_WIDGET (self->power_profile_section)); + +- self->boxes_reverse = g_list_prepend (self->boxes_reverse, self->power_profile_listbox); +- + props = g_variant_get_child_value (variant, 0); + performance_inhibited = variant_lookup_string (props, "PerformanceInhibited"); + active_profile = variant_lookup_string (props, "ActiveProfile"); +@@ -1780,7 +1725,6 @@ cc_power_panel_init (CcPowerPanel *self) + battery_label = g_markup_printf_escaped ("%s", _("Battery")); + gtk_label_set_markup (self->battery_heading, battery_label); + +- self->boxes_reverse = g_list_prepend (self->boxes_reverse, self->battery_listbox); + gtk_list_box_set_header_func (self->battery_listbox, + cc_list_box_update_header_func, + NULL, NULL); +@@ -1790,7 +1734,6 @@ cc_power_panel_init (CcPowerPanel *self) + device_label = g_markup_printf_escaped ("%s", _("Devices")); + gtk_label_set_markup (self->device_heading, device_label); + +- self->boxes_reverse = g_list_prepend (self->boxes_reverse, self->device_listbox); + gtk_list_box_set_header_func (self->device_listbox, + cc_list_box_update_header_func, + NULL, NULL); +@@ -1809,7 +1752,6 @@ cc_power_panel_init (CcPowerPanel *self) + + power_saving_label = g_strdup_printf ("%s", _("Power Saving")); + gtk_label_set_markup (self->power_saving_heading, power_saving_label); +- self->boxes_reverse = g_list_prepend (self->boxes_reverse, self->power_saving_listbox); + gtk_list_box_set_header_func (self->power_saving_listbox, + cc_list_box_update_header_func, + NULL, NULL); +@@ -1817,15 +1759,11 @@ cc_power_panel_init (CcPowerPanel *self) + + general_label = g_markup_printf_escaped ("%s", _("Suspend & Power Button")); + gtk_label_set_markup (self->general_heading, general_label); +- self->boxes_reverse = g_list_prepend (self->boxes_reverse, self->general_listbox); + gtk_list_box_set_header_func (self->general_listbox, + cc_list_box_update_header_func, + NULL, NULL); + setup_general_section (self); + +- self->boxes = g_list_copy (self->boxes_reverse); +- self->boxes = g_list_reverse (self->boxes); +- + /* populate batteries */ + g_signal_connect_object (self->up_client, "device-added", G_CALLBACK (up_client_device_added), self, G_CONNECT_SWAPPED); + g_signal_connect_object (self->up_client, "device-removed", G_CALLBACK (up_client_device_removed), self, G_CONNECT_SWAPPED); +-- +2.32.0 + + +From 25027f6c3c6928eeedb440fe2ca84412dae49ab2 Mon Sep 17 00:00:00 2001 +From: Adrien Plazas +Date: Fri, 8 Jan 2021 16:00:25 +0100 +Subject: [PATCH 03/33] power: Don't set the vadjustment + +This is useless as GtkScrolledwindow already does it on the viewport it +creates. +--- + panels/power/cc-power-panel.c | 9 --------- + panels/power/cc-power-panel.ui | 4 ++-- + 2 files changed, 2 insertions(+), 11 deletions(-) + +diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c +index 1d31a8a83..1a8cfa969 100644 +--- a/panels/power/cc-power-panel.c ++++ b/panels/power/cc-power-panel.c +@@ -91,8 +91,6 @@ struct _CcPowerPanel + GtkListBoxRow *kbd_brightness_row; + CcBrightnessScale *kbd_brightness_scale; + GtkSizeGroup *level_sizegroup; +- GtkScrolledWindow *main_scroll; +- HdyClamp *main_box; + GtkListBoxRow *mobile_row; + GtkSwitch *mobile_switch; + GtkComboBox *power_button_combo; +@@ -136,8 +134,6 @@ struct _CcPowerPanel + #ifdef HAVE_NETWORK_MANAGER + NMClient *nm_client; + #endif +- +- GtkAdjustment *focus_adjustment; + }; + + CC_PANEL_REGISTER (CcPowerPanel, cc_power_panel) +@@ -1661,8 +1657,6 @@ cc_power_panel_class_init (CcPowerPanelClass *klass) + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, kbd_brightness_row); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, kbd_brightness_scale); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, level_sizegroup); +- gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, main_scroll); +- gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, main_box); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, mobile_row); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, mobile_switch); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_button_combo); +@@ -1775,7 +1769,4 @@ cc_power_panel_init (CcPowerPanel *self) + G_CALLBACK (up_client_changed), self, G_CONNECT_SWAPPED); + } + up_client_changed (self); +- +- self->focus_adjustment = gtk_scrolled_window_get_vadjustment (self->main_scroll); +- gtk_container_set_focus_vadjustment (GTK_CONTAINER (self->main_box), self->focus_adjustment); + } +diff --git a/panels/power/cc-power-panel.ui b/panels/power/cc-power-panel.ui +index ea3cf9322..d3e200d93 100644 +--- a/panels/power/cc-power-panel.ui ++++ b/panels/power/cc-power-panel.ui +@@ -113,12 +113,12 @@ + True + False + +- ++ + True + False + never + +- ++ + True + 32 + 32 +-- +2.32.0 + + +From caf3d70a7004552e0bb382a1a1220cdac9c0c1f0 Mon Sep 17 00:00:00 2001 +From: Adrien Plazas +Date: Fri, 8 Jan 2021 16:12:56 +0100 +Subject: [PATCH 04/33] power: Use HdyComboRow for the Blank Screen row + +This simplifies the code a bit and modernizes the UI. +--- + panels/power/cc-power-panel.c | 110 ++++++++++++++++++++++++++------- + panels/power/cc-power-panel.ui | 88 ++------------------------ + 2 files changed, 92 insertions(+), 106 deletions(-) + +diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c +index 1a8cfa969..b046b2589 100644 +--- a/panels/power/cc-power-panel.c ++++ b/panels/power/cc-power-panel.c +@@ -73,7 +73,7 @@ struct _CcPowerPanel + GtkSizeGroup *battery_row_sizegroup; + GtkBox *battery_section; + GtkSizeGroup *battery_sizegroup; +- GtkListBoxRow *blank_screen_row; ++ HdyComboRow *blank_screen_row; + GtkListBoxRow *brightness_row; + CcBrightnessScale *brightness_scale; + GtkListBoxRow *bt_row; +@@ -87,7 +87,6 @@ struct _CcPowerPanel + GtkLabel *general_heading; + GtkListBox *general_listbox; + GtkBox *general_section; +- GtkComboBox *idle_delay_combo; + GtkListBoxRow *kbd_brightness_row; + CcBrightnessScale *kbd_brightness_scale; + GtkSizeGroup *level_sizegroup; +@@ -577,6 +576,49 @@ set_value_for_combo (GtkComboBox *combo_box, gint value) + gtk_combo_box_set_active_iter (combo_box, &new); + } + ++static void ++set_value_for_combo_row (HdyComboRow *combo_row, gint value) ++{ ++ gboolean insert = FALSE; ++ guint insert_before = 0; ++ guint i; ++ HdyValueObject *new; ++ GListModel *model; ++ gint value_last = 0; ++ g_autofree gchar *text = NULL; ++ ++ /* try to make the UI match the setting */ ++ model = hdy_combo_row_get_model (combo_row); ++ for (i = 0; i < g_list_model_get_n_items (model); i++) ++ { ++ HdyValueObject *value_object = g_list_model_get_item (model, i); ++ gint value_tmp = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (value_object), "value")); ++ if (value_tmp == value) ++ { ++ hdy_combo_row_set_selected_index (combo_row, i); ++ return; ++ } ++ ++ /* Insert before if the next value is larger or the value is lower ++ * again (i.e. "Never" is zero and last). */ ++ if (!insert && (value_tmp > value || value_last > value_tmp)) ++ { ++ insert = TRUE; ++ insert_before = i; ++ } ++ ++ value_last = value_tmp; ++ } ++ ++ /* The value is not listed, so add it at the best point (or the end). */ ++ text = cc_util_time_to_string_text (value * 1000); ++ new = hdy_value_object_new_string (text); ++ g_object_set_data (G_OBJECT (new), "value", ++ GUINT_TO_POINTER (value)); ++ g_list_store_insert (G_LIST_STORE (model), insert_before, new); ++ hdy_combo_row_set_selected_index (combo_row, insert_before); ++} ++ + static void + set_ac_battery_ui_mode (CcPowerPanel *self) + { +@@ -869,25 +911,18 @@ keynav_failed_cb (CcPowerPanel *self, GtkDirectionType direction, GtkWidget *lis + } + + static void +-idle_delay_combo_changed_cb (CcPowerPanel *self) ++blank_screen_row_changed_cb (CcPowerPanel *self) + { +- GtkTreeIter iter; +- GtkTreeModel *model; ++ GListModel *model; ++ gint selected_index; ++ HdyValueObject *value_object; + gint value; +- gboolean ret; + +- /* no selection */ +- ret = gtk_combo_box_get_active_iter (self->idle_delay_combo, &iter); +- if (!ret) +- return; ++ model = hdy_combo_row_get_model (self->blank_screen_row); ++ selected_index = hdy_combo_row_get_selected_index (self->blank_screen_row); ++ value_object = g_list_model_get_item (model, selected_index); ++ value = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (value_object), "value")); + +- /* get entry */ +- model = gtk_combo_box_get_model (self->idle_delay_combo); +- gtk_tree_model_get (model, &iter, +- 1, &value, +- -1); +- +- /* set both keys */ + g_settings_set_uint (self->session_settings, "idle-delay", value); + } + +@@ -1171,6 +1206,37 @@ has_kbd_brightness_cb (CcPowerPanel *self, + gtk_widget_set_visible (GTK_WIDGET (self->kbd_brightness_row), has_brightness); + } + ++static void ++populate_blank_screen_row (HdyComboRow *combo_row) ++{ ++ g_autoptr (GListStore) list_store = g_list_store_new (HDY_TYPE_VALUE_OBJECT); ++ gint minutes[] = { 1, 2, 3, 4, 5, 8, 10, 12, 15 }; ++ guint i; ++ g_autoptr (HdyValueObject) never_value_object = NULL; ++ ++ for (i = 0; i < G_N_ELEMENTS (minutes); i++) ++ { ++ gchar *text = NULL; ++ g_autoptr (HdyValueObject) value_object = NULL; ++ ++ /* Translators: Option for "Blank Screen" in "Power" panel */ ++ text = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%d minute", "%d minutes", minutes[i]), minutes[i]); ++ value_object = hdy_value_object_new_take_string (text); ++ ++ g_object_set_data (G_OBJECT (value_object), "value", GUINT_TO_POINTER (minutes[i] * 60)); ++ g_list_store_append (list_store, value_object); ++ } ++ ++ never_value_object = hdy_value_object_new_string (C_("Idle time", "Never")); ++ g_object_set_data (G_OBJECT (never_value_object), "value", GUINT_TO_POINTER (0)); ++ g_list_store_append (list_store, never_value_object); ++ ++ hdy_combo_row_bind_name_model (combo_row, ++ G_LIST_MODEL (list_store), ++ (HdyComboRowGetNameFunc) hdy_value_object_dup_string, ++ NULL, NULL); ++} ++ + static void + setup_power_saving (CcPowerPanel *self) + { +@@ -1191,10 +1257,11 @@ setup_power_saving (CcPowerPanel *self) + self->dim_screen_switch, "active", + G_SETTINGS_BIND_DEFAULT); + ++ g_signal_handlers_block_by_func (self->blank_screen_row, blank_screen_row_changed_cb, self); ++ populate_blank_screen_row (self->blank_screen_row); + value = g_settings_get_uint (self->session_settings, "idle-delay"); +- g_signal_handlers_block_by_func (self->idle_delay_combo, idle_delay_combo_changed_cb, self); +- set_value_for_combo (self->idle_delay_combo, value); +- g_signal_handlers_unblock_by_func (self->idle_delay_combo, idle_delay_combo_changed_cb, self); ++ set_value_for_combo_row (self->blank_screen_row, value); ++ g_signal_handlers_unblock_by_func (self->blank_screen_row, blank_screen_row_changed_cb, self); + + /* The default values for these settings are unfortunate for us; + * timeout == 0, action == suspend means 'do nothing' - just +@@ -1653,7 +1720,6 @@ cc_power_panel_class_init (CcPowerPanelClass *klass) + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, general_heading); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, general_listbox); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, general_section); +- gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, idle_delay_combo); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, kbd_brightness_row); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, kbd_brightness_scale); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, level_sizegroup); +@@ -1683,7 +1749,7 @@ cc_power_panel_class_init (CcPowerPanelClass *klass) + gtk_widget_class_bind_template_callback (widget_class, bt_switch_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, has_brightness_cb); + gtk_widget_class_bind_template_callback (widget_class, has_kbd_brightness_cb); +- gtk_widget_class_bind_template_callback (widget_class, idle_delay_combo_changed_cb); ++ gtk_widget_class_bind_template_callback (widget_class, blank_screen_row_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, keynav_failed_cb); + gtk_widget_class_bind_template_callback (widget_class, mobile_switch_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, power_button_combo_changed_cb); +diff --git a/panels/power/cc-power-panel.ui b/panels/power/cc-power-panel.ui +index d3e200d93..a9bb39b77 100644 +--- a/panels/power/cc-power-panel.ui ++++ b/panels/power/cc-power-panel.ui +@@ -51,56 +51,6 @@ + + + +- +- +- +- +- +- +- +- +- +- 1 minute +- 60 +- +- +- 2 minutes +- 120 +- +- +- 3 minutes +- 180 +- +- +- 4 minutes +- 240 +- +- +- 5 minutes +- 300 +- +- +- 8 minutes +- 480 +- +- +- 10 minutes +- 600 +- +- +- 12 minutes +- 720 +- +- +- 15 minutes +- 900 +- +- +- Never +- 0 +- +- +- + + + +@@ -447,41 +397,11 @@ + + + +- ++ + True +- False +- False +- +- +- True +- 12 +- 12 +- 12 +- +- +- True +- True +- True +- end +- _Blank Screen +- 6 +- 6 +- True +- 0 +- idle_delay_combo +- +- +- +- +- True +- center +- 0 +- idle_time_liststore +- +- +- +- +- ++ _Blank Screen ++ True ++ + + + +-- +2.32.0 + + +From 7dbe681401f3f487f1e752a0569cf3d743a74187 Mon Sep 17 00:00:00 2001 +From: Adrien Plazas +Date: Fri, 8 Jan 2021 16:17:42 +0100 +Subject: [PATCH 05/33] power: Use HdyComboRow for the Power Button Behavior + row + +This simplifies the code a bit and modernizes the UI. +--- + panels/power/cc-power-panel.c | 71 ++++++++++++++++++---------------- + panels/power/cc-power-panel.ui | 46 ++-------------------- + 2 files changed, 42 insertions(+), 75 deletions(-) + +diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c +index b046b2589..ea979cfc7 100644 +--- a/panels/power/cc-power-panel.c ++++ b/panels/power/cc-power-panel.c +@@ -92,9 +92,7 @@ struct _CcPowerPanel + GtkSizeGroup *level_sizegroup; + GtkListBoxRow *mobile_row; + GtkSwitch *mobile_switch; +- GtkComboBox *power_button_combo; +- GtkListStore *power_button_liststore; +- GtkListBoxRow *power_button_row; ++ HdyComboRow *power_button_row; + GtkLabel *power_profile_heading; + GtkListBox *power_profile_listbox; + GtkBox *power_profile_section; +@@ -927,25 +925,18 @@ blank_screen_row_changed_cb (CcPowerPanel *self) + } + + static void +-power_button_combo_changed_cb (CcPowerPanel *self) ++power_button_row_changed_cb (CcPowerPanel *self) + { +- GtkTreeIter iter; +- GtkTreeModel *model; ++ GListModel *model; ++ gint selected_index; ++ HdyValueObject *value_object; + gint value; +- gboolean ret; + +- /* no selection */ +- ret = gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self->power_button_combo), &iter); +- if (!ret) +- return; +- +- /* get entry */ +- model = gtk_combo_box_get_model (GTK_COMBO_BOX (self->power_button_combo)); +- gtk_tree_model_get (model, &iter, +- 1, &value, +- -1); ++ model = hdy_combo_row_get_model (self->power_button_row); ++ selected_index = hdy_combo_row_get_selected_index (self->power_button_row); ++ value_object = g_list_model_get_item (model, selected_index); ++ value = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (value_object), "value")); + +- /* set both keys */ + g_settings_set_enum (self->gsd_settings, "power-button-action", value); + } + +@@ -1048,10 +1039,11 @@ set_sleep_type (const GValue *value, + } + + static void +-populate_power_button_model (GtkTreeModel *model, +- gboolean can_suspend, +- gboolean can_hibernate) ++populate_power_button_row (HdyComboRow *combo_row, ++ gboolean can_suspend, ++ gboolean can_hibernate) + { ++ g_autoptr (GListStore) list_store = NULL; + struct { + char *name; + GsdPowerButtonActionType value; +@@ -1063,20 +1055,28 @@ populate_power_button_model (GtkTreeModel *model, + }; + guint i; + ++ list_store = g_list_store_new (HDY_TYPE_VALUE_OBJECT); + for (i = 0; i < G_N_ELEMENTS (actions); i++) + { ++ g_autoptr (HdyValueObject) value_object = NULL; ++ + if (!can_suspend && actions[i].value == GSD_POWER_BUTTON_ACTION_SUSPEND) + continue; + + if (!can_hibernate && actions[i].value == GSD_POWER_BUTTON_ACTION_HIBERNATE) + continue; + +- gtk_list_store_insert_with_values (GTK_LIST_STORE (model), +- NULL, -1, +- 0, _(actions[i].name), +- 1, actions[i].value, +- -1); ++ value_object = hdy_value_object_new_string (actions[i].name); ++ g_object_set_data (G_OBJECT (value_object), ++ "value", ++ GUINT_TO_POINTER (actions[i].value)); ++ g_list_store_append (list_store, value_object); + } ++ ++ hdy_combo_row_bind_name_model (combo_row, ++ G_LIST_MODEL (list_store), ++ (HdyComboRowGetNameFunc) hdy_value_object_dup_string, ++ NULL, NULL); + } + + #define NEVER 0 +@@ -1635,10 +1635,17 @@ setup_general_section (CcPowerPanel *self) + { + gtk_widget_show (GTK_WIDGET (self->power_button_row)); + +- populate_power_button_model (GTK_TREE_MODEL (self->power_button_liststore), can_suspend, can_hibernate); +- g_signal_handlers_block_by_func (self->power_button_combo, power_button_combo_changed_cb, self); +- set_value_for_combo (self->power_button_combo, g_settings_get_enum (self->gsd_settings, "power-button-action")); +- g_signal_handlers_unblock_by_func (self->power_button_combo, power_button_combo_changed_cb, self); ++ g_signal_handlers_block_by_func (self->power_button_row, ++ power_button_row_changed_cb, ++ self); ++ populate_power_button_row (self->power_button_row, ++ can_suspend, ++ can_hibernate); ++ set_value_for_combo_row (self->power_button_row, ++ g_settings_get_enum (self->gsd_settings, "power-button-action")); ++ g_signal_handlers_unblock_by_func (self->power_button_row, ++ power_button_row_changed_cb, ++ self); + + show_section = TRUE; + } +@@ -1725,8 +1732,6 @@ cc_power_panel_class_init (CcPowerPanelClass *klass) + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, level_sizegroup); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, mobile_row); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, mobile_switch); +- gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_button_combo); +- gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_button_liststore); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_button_row); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_profile_heading); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_profile_listbox); +@@ -1752,7 +1757,7 @@ cc_power_panel_class_init (CcPowerPanelClass *klass) + gtk_widget_class_bind_template_callback (widget_class, blank_screen_row_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, keynav_failed_cb); + gtk_widget_class_bind_template_callback (widget_class, mobile_switch_changed_cb); +- gtk_widget_class_bind_template_callback (widget_class, power_button_combo_changed_cb); ++ gtk_widget_class_bind_template_callback (widget_class, power_button_row_changed_cb); + gtk_widget_class_bind_template_callback (widget_class, power_profiles_row_activated_cb); + gtk_widget_class_bind_template_callback (widget_class, power_saving_listbox_row_activated_cb); + gtk_widget_class_bind_template_callback (widget_class, wifi_switch_changed_cb); +diff --git a/panels/power/cc-power-panel.ui b/panels/power/cc-power-panel.ui +index a9bb39b77..18fc0a8ac 100644 +--- a/panels/power/cc-power-panel.ui ++++ b/panels/power/cc-power-panel.ui +@@ -51,14 +51,6 @@ + + + +- +- +- +- +- +- +- +- + +-- +2.32.0 + + +From 58480754efd5fdc66db0940ce5c19abfbd2158b6 Mon Sep 17 00:00:00 2001 +From: Adrien Plazas +Date: Thu, 7 Jan 2021 14:37:56 +0100 +Subject: [PATCH 08/33] power: Fix the indentation + +The indentation was purposefully left incorrect in the previous commits +to ease the review of the actual changes, this fixes it. +--- + panels/power/cc-power-panel.ui | 426 ++++++++++++++++----------------- + 1 file changed, 213 insertions(+), 213 deletions(-) + +diff --git a/panels/power/cc-power-panel.ui b/panels/power/cc-power-panel.ui +index 26d6ffddc..8e999c6d5 100644 +--- a/panels/power/cc-power-panel.ui ++++ b/panels/power/cc-power-panel.ui +@@ -57,238 +57,238 @@ + + + True ++ ++ ++ True ++ Battery ++ ++ ++ ++ ++ ++ True ++ none ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ Devices ++ ++ ++ ++ ++ ++ True ++ none ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ Power Mode ++ Affects system performance and power usage. ++ ++ ++ ++ ++ ++ True ++ none ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ Power Saving ++ ++ ++ True ++ _Screen Brightness ++ True + +- ++ + True +- Battery +- +- +- +- +- +- True +- none +- +- +- +- +- +- +- ++ center ++ True ++ screen ++ + + ++ ++ ++ ++ ++ True ++ Automatic Brightness + +- ++ + True +- Devices +- +- +- +- +- +- True +- none +- +- +- +- +- +- +- ++ center ++ + + ++ ++ ++ ++ ++ True ++ _Keyboard Brightness ++ True + +- +- False +- Power Mode +- Affects system performance and power usage. +- +- +- +- +- +- True +- none +- +- +- +- +- +- +- +- ++ ++ True ++ center ++ True ++ kbd ++ + + ++ ++ ++ ++ ++ True ++ Dim Screen When Inactive ++ dim_screen_switch + +- ++ + True +- Power Saving +- +- +- True +- _Screen Brightness +- True +- +- +- True +- center +- True +- screen +- +- +- +- +- +- +- +- True +- Automatic Brightness +- +- +- True +- center +- +- +- +- +- +- +- +- True +- _Keyboard Brightness +- True +- +- +- True +- center +- True +- kbd +- +- +- +- +- +- +- +- True +- Dim Screen When Inactive +- dim_screen_switch +- +- +- True +- center +- +- +- +- +- +- +- True +- _Blank Screen +- True +- +- +- +- +- +- False +- _Automatic Suspend +- True +- True +- +- +- +- True +- end +- +- +- +- +- +- +- +- False +- _Wi-Fi +- Wi-Fi can be turned off to save power. +- True +- wifi_switch +- +- +- True +- center +- +- +- +- +- +- +- +- False +- _Mobile Broadband +- Mobile broadband (LTE, 4G, 3G, etc.) can be turned off to save power. +- True +- mobile_switch +- +- +- True +- center +- +- +- +- +- +- +- +- False +- _Bluetooth +- Bluetooth can be turned off to save power. +- True +- bt_switch +- +- +- True +- center +- +- +- +- +- ++ center + + ++ ++ ++ ++ ++ True ++ _Blank Screen ++ True ++ ++ ++ ++ ++ ++ False ++ _Automatic Suspend ++ True ++ True ++ ++ ++ ++ True ++ end ++ ++ ++ ++ ++ ++ ++ ++ False ++ _Wi-Fi ++ Wi-Fi can be turned off to save power. ++ True ++ wifi_switch ++ ++ ++ True ++ center ++ ++ ++ ++ ++ ++ ++ ++ False ++ _Mobile Broadband ++ Mobile broadband (LTE, 4G, 3G, etc.) can be turned off to save power. ++ True ++ mobile_switch ++ ++ ++ True ++ center ++ ++ ++ ++ ++ ++ ++ ++ False ++ _Bluetooth ++ Bluetooth can be turned off to save power. ++ True ++ bt_switch + +- ++ + True +- Suspend & Power Button +- +- +- False +- Po_wer Button Behavior +- True +- +- +- +- +- +- False +- Show Battery _Percentage +- True +- battery_percentage_switch +- +- +- True +- center +- +- +- +- ++ center ++ + + ++ ++ ++ ++ ++ ++ ++ True ++ Suspend & Power Button ++ ++ ++ False ++ Po_wer Button Behavior ++ True ++ ++ ++ ++ ++ ++ False ++ Show Battery _Percentage ++ True ++ battery_percentage_switch ++ ++ ++ True ++ center ++ ++ ++ ++ ++ ++ + + + +-- +2.32.0 + + +From 036545ebc5b3deba1d4bb4ac82dc102413804e83 Mon Sep 17 00:00:00 2001 +From: Adrien Plazas +Date: Fri, 8 Jan 2021 16:29:18 +0100 +Subject: [PATCH 09/33] power: Hide the icon of the battery row when unused + +This gives more room to the label. +--- + panels/power/cc-battery-row.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/panels/power/cc-battery-row.c b/panels/power/cc-battery-row.c +index 55d7584d7..f6faca0c1 100644 +--- a/panels/power/cc-battery-row.c ++++ b/panels/power/cc-battery-row.c +@@ -275,7 +275,12 @@ cc_battery_row_new (UpDevice *device, + + /* Icon */ + if (is_kind_battery && icon_name != NULL && icon_name[0] != '\0') +- gtk_image_set_from_icon_name (self->icon, icon_name, GTK_ICON_SIZE_BUTTON); ++ { ++ gtk_image_set_from_icon_name (self->icon, icon_name, GTK_ICON_SIZE_BUTTON); ++ gtk_widget_show (GTK_WIDGET (self->icon)); ++ } ++ else ++ gtk_widget_hide (GTK_WIDGET (self->icon)); + + /* Percentage label */ + if (battery_level == UP_DEVICE_LEVEL_NONE) +@@ -347,4 +352,4 @@ UpDeviceKind + cc_battery_row_get_kind (CcBatteryRow *self) + { + return self->kind; +-} +\ No newline at end of file ++} +-- +2.32.0 + + +From c4849778de730f37618120dbdd37f30515ecc77a Mon Sep 17 00:00:00 2001 +From: Adrien Plazas +Date: Fri, 8 Jan 2021 16:30:12 +0100 +Subject: [PATCH 10/33] power: Ellipsize the labels of the battery row + +This helps the window fit any size, including the narrow one of phones. +--- + panels/power/cc-battery-row.ui | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/panels/power/cc-battery-row.ui b/panels/power/cc-battery-row.ui +index 932e5d39f..dec97a9fe 100644 +--- a/panels/power/cc-battery-row.ui ++++ b/panels/power/cc-battery-row.ui +@@ -28,6 +28,8 @@ + + + True ++ end ++ 0 + + + +@@ -79,6 +81,8 @@ + + + True ++ end ++ 0 + + + +-- +2.32.0 + + +From 33d672d634a9e1d8a2cfa74dc4d503fb6f170ea1 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Thu, 15 Jul 2021 13:08:05 +0200 +Subject: [PATCH 11/33] power: Fix keynav not working +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +gnome-control-center/panels/power/cc-power-panel.c: In function ‘keynav_failed_cb’: +gnome-control-center/panels/power/cc-power-panel.c:892:50: warning: statement with no effect [-Wunused-value] + 892 | direction == GTK_DIR_UP ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~ +--- + panels/power/cc-power-panel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c +index 96558c778..d31d16d22 100644 +--- a/panels/power/cc-power-panel.c ++++ b/panels/power/cc-power-panel.c +@@ -888,7 +888,7 @@ keynav_failed_cb (CcPowerPanel *self, GtkDirectionType direction, GtkWidget *lis + if (direction != GTK_DIR_UP && direction != GTK_DIR_DOWN) + return FALSE; + +- direction == GTK_DIR_UP ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD; ++ direction = GTK_DIR_UP ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD; + + return gtk_widget_child_focus (GTK_WIDGET (self), direction); + } +-- +2.32.0 + + +From 35b621ce5191461b16eefcb5e677496c0c48638c Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Thu, 15 Jul 2021 13:46:19 +0200 +Subject: [PATCH 12/33] power: Simplify emptying listbox + +We do that in a few places. +--- + panels/power/cc-power-panel.c | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) + +diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c +index d31d16d22..5d57afe59 100644 +--- a/panels/power/cc-power-panel.c ++++ b/panels/power/cc-power-panel.c +@@ -242,25 +242,29 @@ add_device (CcPowerPanel *self, UpDevice *device) + } + + static void +-up_client_changed (CcPowerPanel *self) ++empty_listbox (GtkListBox *listbox) + { +- g_autoptr(GList) battery_children = NULL; +- g_autoptr(GList) device_children = NULL; ++ g_autoptr(GList) children = NULL; + GList *l; ++ ++ children = gtk_container_get_children (GTK_CONTAINER (listbox)); ++ for (l = children; l != NULL; l = l->next) ++ gtk_container_remove (GTK_CONTAINER (listbox), l->data); ++} ++ ++static void ++up_client_changed (CcPowerPanel *self) ++{ + gint i; + UpDeviceKind kind; + guint n_batteries; + gboolean on_ups; + g_autoptr(UpDevice) composite = NULL; + +- battery_children = gtk_container_get_children (GTK_CONTAINER (self->battery_listbox)); +- for (l = battery_children; l != NULL; l = l->next) +- gtk_container_remove (GTK_CONTAINER (self->battery_listbox), l->data); ++ empty_listbox (self->battery_listbox); + gtk_widget_hide (GTK_WIDGET (self->battery_section)); + +- device_children = gtk_container_get_children (GTK_CONTAINER (self->device_listbox)); +- for (l = device_children; l != NULL; l = l->next) +- gtk_container_remove (GTK_CONTAINER (self->device_listbox), l->data); ++ empty_listbox (self->device_listbox); + gtk_widget_hide (GTK_WIDGET (self->device_section)); + + #ifdef TEST_FAKE_DEVICES +-- +2.32.0 + + +From 7915830b4d8b691f4def35c83c06a658f5b14ac1 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Thu, 15 Jul 2021 14:39:58 +0200 +Subject: [PATCH 13/33] power: Add new power profile info row widget + +--- + panels/power/cc-power-panel.c | 1 + + panels/power/cc-power-profile-info-row.c | 67 ++++++++++ + panels/power/cc-power-profile-info-row.h | 36 ++++++ + panels/power/cc-power-profile-info-row.ui | 44 +++++++ + panels/power/icons/info-symbolic.svg | 150 ++++++++++++++++++++++ + panels/power/icons/meson.build | 5 + + panels/power/meson.build | 1 + + panels/power/power.gresource.xml | 1 + + 8 files changed, 305 insertions(+) + create mode 100644 panels/power/cc-power-profile-info-row.c + create mode 100644 panels/power/cc-power-profile-info-row.h + create mode 100644 panels/power/cc-power-profile-info-row.ui + create mode 100644 panels/power/icons/info-symbolic.svg + +diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c +index 5d57afe59..8acf62dee 100644 +--- a/panels/power/cc-power-panel.c ++++ b/panels/power/cc-power-panel.c +@@ -35,6 +35,7 @@ + #include "cc-battery-row.h" + #include "cc-brightness-scale.h" + #include "cc-power-profile-row.h" ++#include "cc-power-profile-info-row.h" + #include "cc-power-panel.h" + #include "cc-power-resources.h" + #include "cc-util.h" +diff --git a/panels/power/cc-power-profile-info-row.c b/panels/power/cc-power-profile-info-row.c +new file mode 100644 +index 000000000..92bb78834 +--- /dev/null ++++ b/panels/power/cc-power-profile-info-row.c +@@ -0,0 +1,67 @@ ++/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-list-row.c ++ * ++ * Copyright 2020 Red Hat Inc. ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Bastien Nocera ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#undef G_LOG_DOMAIN ++#define G_LOG_DOMAIN "cc-power-profile-info-row" ++ ++#include ++ ++#include ++#include "cc-power-profile-info-row.h" ++ ++struct _CcPowerProfileInfoRow ++{ ++ GtkListBoxRow parent_instance; ++ ++ GtkLabel *title_label; ++}; ++ ++G_DEFINE_TYPE (CcPowerProfileInfoRow, cc_power_profile_info_row, GTK_TYPE_LIST_BOX_ROW) ++ ++static void ++cc_power_profile_info_row_class_init (CcPowerProfileInfoRowClass *klass) ++{ ++ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); ++ ++ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/power/cc-power-profile-info-row.ui"); ++ ++ gtk_widget_class_bind_template_child (widget_class, CcPowerProfileInfoRow, title_label); ++} ++ ++static void ++cc_power_profile_info_row_init (CcPowerProfileInfoRow *self) ++{ ++ gtk_widget_init_template (GTK_WIDGET (self)); ++} ++ ++CcPowerProfileInfoRow * ++cc_power_profile_info_row_new (const char *text) ++{ ++ CcPowerProfileInfoRow *self; ++ ++ self = g_object_new (CC_TYPE_POWER_PROFILE_INFO_ROW, NULL); ++ gtk_label_set_markup (self->title_label, text); ++ ++ return self; ++} +diff --git a/panels/power/cc-power-profile-info-row.h b/panels/power/cc-power-profile-info-row.h +new file mode 100644 +index 000000000..52d055ab2 +--- /dev/null ++++ b/panels/power/cc-power-profile-info-row.h +@@ -0,0 +1,36 @@ ++/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-list-row.h ++ * ++ * Copyright 2020 Red Hat Inc ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Bastien Nocera ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#pragma once ++ ++#include ++ ++G_BEGIN_DECLS ++ ++#define CC_TYPE_POWER_PROFILE_INFO_ROW (cc_power_profile_info_row_get_type()) ++G_DECLARE_FINAL_TYPE (CcPowerProfileInfoRow, cc_power_profile_info_row, CC, POWER_PROFILE_INFO_ROW, GtkListBoxRow) ++ ++CcPowerProfileInfoRow *cc_power_profile_info_row_new (const char *text); ++ ++G_END_DECLS +diff --git a/panels/power/cc-power-profile-info-row.ui b/panels/power/cc-power-profile-info-row.ui +new file mode 100644 +index 000000000..d9291ff16 +--- /dev/null ++++ b/panels/power/cc-power-profile-info-row.ui +@@ -0,0 +1,44 @@ ++ ++ ++ ++ ++ +diff --git a/panels/power/icons/info-symbolic.svg b/panels/power/icons/info-symbolic.svg +new file mode 100644 +index 000000000..502a98a50 +--- /dev/null ++++ b/panels/power/icons/info-symbolic.svg +@@ -0,0 +1,150 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/panels/power/icons/meson.build b/panels/power/icons/meson.build +index 8165371ea..c56bc65b7 100644 +--- a/panels/power/icons/meson.build ++++ b/panels/power/icons/meson.build +@@ -13,3 +13,8 @@ foreach icon_size: icon_sizes + install_dir: join_paths(control_center_icondir, 'hicolor', icon_size, 'apps') + ) + endforeach ++ ++install_data( ++ 'info-symbolic.svg', ++ install_dir: join_paths(control_center_icondir, 'hicolor', 'scalable', 'status') ++) +diff --git a/panels/power/meson.build b/panels/power/meson.build +index 625059dd2..af04b98ed 100644 +--- a/panels/power/meson.build ++++ b/panels/power/meson.build +@@ -22,6 +22,7 @@ sources = files( + 'cc-brightness-scale.c', + 'cc-power-panel.c', + 'cc-power-profile-row.c', ++ 'cc-power-profile-info-row.c' + ) + + sources += gnome.mkenums_simple( +diff --git a/panels/power/power.gresource.xml b/panels/power/power.gresource.xml +index 31e92b415..5a33c8e60 100644 +--- a/panels/power/power.gresource.xml ++++ b/panels/power/power.gresource.xml +@@ -4,6 +4,7 @@ + cc-battery-row.ui + cc-power-panel.ui + cc-power-profile-row.ui ++ cc-power-profile-info-row.ui + battery-levels.css + power-profiles.css + +-- +2.32.0 + + +From 1a80fda8cdbd2226a5663f0fa572dd72210722a6 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Fri, 2 Apr 2021 13:10:19 +0200 +Subject: [PATCH 14/33] power: Handle new power-profiles-daemon API + +Handle the new PerformanceDegraded property to replace +PerformanceInhibited. +--- + panels/power/cc-power-panel.c | 53 +++++++++++++++++++++++++++++++--- + panels/power/cc-power-panel.ui | 11 +++++++ + 2 files changed, 60 insertions(+), 4 deletions(-) + +diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c +index 8acf62dee..51196a8c4 100644 +--- a/panels/power/cc-power-panel.c ++++ b/panels/power/cc-power-panel.c +@@ -89,6 +89,7 @@ struct _CcPowerPanel + GtkSwitch *mobile_switch; + HdyComboRow *power_button_row; + GtkListBox *power_profile_listbox; ++ GtkListBox *power_profile_info_listbox; + HdyPreferencesGroup *power_profile_section; + GtkSizeGroup *row_sizegroup; + GtkComboBox *suspend_on_battery_delay_combo; +@@ -119,6 +120,7 @@ struct _CcPowerPanel + guint power_profiles_prop_id; + CcPowerProfileRow *power_profiles_row[NUM_CC_POWER_PROFILES]; + gboolean power_profiles_in_update; ++ gboolean has_performance_degraded; + + #ifdef HAVE_NETWORK_MANAGER + NMClient *nm_client; +@@ -1365,6 +1367,37 @@ performance_profile_set_inhibited (CcPowerPanel *self, + cc_power_profile_row_set_performance_inhibited (row, performance_inhibited); + } + ++static void ++performance_profile_set_degraded (CcPowerPanel *self) ++{ ++ g_autoptr(GVariant) variant = NULL; ++ const char *degraded, *text; ++ CcPowerProfileInfoRow *row; ++ ++ empty_listbox (self->power_profile_info_listbox); ++ gtk_widget_hide (GTK_WIDGET (self->power_profile_info_listbox)); ++ ++ variant = g_dbus_proxy_get_cached_property (self->power_profiles_proxy, "PerformanceDegraded"); ++ if (!variant) ++ return; ++ degraded = g_variant_get_string (variant, NULL); ++ if (*degraded == '\0') ++ return; ++ ++ gtk_widget_show (GTK_WIDGET (self->power_profile_info_listbox)); ++ ++ if (g_str_equal (degraded, "high-operating-temperature")) ++ text = _("Performance mode temporarily disabled due to high operating temperature."); ++ else if (g_str_equal (degraded, "lap-detected")) ++ text = _("Lap detected: performance mode temporarily disabled. Move the device to a stable surface to restore."); ++ else ++ text = _("Performance mode temporarily disabled."); ++ ++ row = cc_power_profile_info_row_new (text); ++ gtk_widget_show (GTK_WIDGET (row)); ++ gtk_container_add (GTK_CONTAINER (self->power_profile_info_listbox), GTK_WIDGET (row)); ++} ++ + static void + power_profiles_row_activated_cb (GtkListBox *box, + GtkListBoxRow *box_row, +@@ -1420,8 +1453,13 @@ power_profiles_properties_changed_cb (CcPowerPanel *self, + { + if (g_strcmp0 (key, "PerformanceInhibited") == 0) + { +- performance_profile_set_inhibited (self, +- g_variant_get_string (value, NULL)); ++ if (!self->has_performance_degraded) ++ performance_profile_set_inhibited (self, ++ g_variant_get_string (value, NULL)); ++ } ++ else if (g_strcmp0 (key, "PerformanceDegraded") == 0) ++ { ++ performance_profile_set_degraded (self); + } + else if (g_strcmp0 (key, "ActiveProfile") == 0) + { +@@ -1504,7 +1542,8 @@ setup_power_profiles (CcPowerPanel *self) + g_autoptr(GVariant) props = NULL; + guint i, num_children; + g_autoptr(GError) error = NULL; +- const char *performance_inhibited; ++ const char *performance_inhibited = NULL; ++ const char *performance_degraded; + const char *active_profile; + g_autoptr(GVariant) profiles = NULL; + GtkRadioButton *last_button; +@@ -1557,7 +1596,12 @@ setup_power_profiles (CcPowerPanel *self) + gtk_widget_show (GTK_WIDGET (self->power_profile_section)); + + props = g_variant_get_child_value (variant, 0); +- performance_inhibited = variant_lookup_string (props, "PerformanceInhibited"); ++ performance_degraded = variant_lookup_string (props, "PerformanceDegraded"); ++ self->has_performance_degraded = performance_degraded != NULL; ++ if (performance_degraded == NULL) ++ performance_inhibited = variant_lookup_string (props, "PerformanceInhibited"); ++ else ++ performance_profile_set_degraded (self); + active_profile = variant_lookup_string (props, "ActiveProfile"); + + last_button = NULL; +@@ -1715,6 +1759,7 @@ cc_power_panel_class_init (CcPowerPanelClass *klass) + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, mobile_switch); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_button_row); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_profile_listbox); ++ gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_profile_info_listbox); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, power_profile_section); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, row_sizegroup); + gtk_widget_class_bind_template_child (widget_class, CcPowerPanel, suspend_on_battery_delay_combo); +diff --git a/panels/power/cc-power-panel.ui b/panels/power/cc-power-panel.ui +index 8e999c6d5..d8283c556 100644 +--- a/panels/power/cc-power-panel.ui ++++ b/panels/power/cc-power-panel.ui +@@ -123,6 +123,17 @@ + + + ++ ++ ++ False ++ none ++ 12 ++ ++ ++ ++ + + + +-- +2.32.0 + + +From 7254da88faa5cebd43db735746eb20b2b548a462 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Fri, 16 Jul 2021 10:00:12 +0200 +Subject: [PATCH 15/33] power: Prepare for adding more power profile info boxes + +Rename and re-indent the code that adds the power profile info boxes to +prepare for adding more info boxes when needed. +--- + panels/power/cc-power-panel.c | 46 ++++++++++++++++++----------------- + 1 file changed, 24 insertions(+), 22 deletions(-) + +diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c +index 51196a8c4..1869be065 100644 +--- a/panels/power/cc-power-panel.c ++++ b/panels/power/cc-power-panel.c +@@ -1368,34 +1368,35 @@ performance_profile_set_inhibited (CcPowerPanel *self, + } + + static void +-performance_profile_set_degraded (CcPowerPanel *self) ++power_profile_update_info_boxes (CcPowerPanel *self) + { +- g_autoptr(GVariant) variant = NULL; +- const char *degraded, *text; ++ g_autoptr(GVariant) degraded_variant = NULL; ++ const char *degraded = NULL; + CcPowerProfileInfoRow *row; + + empty_listbox (self->power_profile_info_listbox); + gtk_widget_hide (GTK_WIDGET (self->power_profile_info_listbox)); + +- variant = g_dbus_proxy_get_cached_property (self->power_profiles_proxy, "PerformanceDegraded"); +- if (!variant) +- return; +- degraded = g_variant_get_string (variant, NULL); +- if (*degraded == '\0') +- return; ++ degraded_variant = g_dbus_proxy_get_cached_property (self->power_profiles_proxy, "PerformanceDegraded"); ++ if (degraded_variant) ++ degraded = g_variant_get_string (degraded_variant, NULL); ++ if (degraded && *degraded != '\0') ++ { ++ const char *text; + +- gtk_widget_show (GTK_WIDGET (self->power_profile_info_listbox)); ++ gtk_widget_show (GTK_WIDGET (self->power_profile_info_listbox)); + +- if (g_str_equal (degraded, "high-operating-temperature")) +- text = _("Performance mode temporarily disabled due to high operating temperature."); +- else if (g_str_equal (degraded, "lap-detected")) +- text = _("Lap detected: performance mode temporarily disabled. Move the device to a stable surface to restore."); +- else +- text = _("Performance mode temporarily disabled."); ++ if (g_str_equal (degraded, "high-operating-temperature")) ++ text = _("Performance mode temporarily disabled due to high operating temperature."); ++ else if (g_str_equal (degraded, "lap-detected")) ++ text = _("Lap detected: performance mode temporarily disabled. Move the device to a stable surface to restore."); ++ else ++ text = _("Performance mode temporarily disabled."); + +- row = cc_power_profile_info_row_new (text); +- gtk_widget_show (GTK_WIDGET (row)); +- gtk_container_add (GTK_CONTAINER (self->power_profile_info_listbox), GTK_WIDGET (row)); ++ row = cc_power_profile_info_row_new (text); ++ gtk_widget_show (GTK_WIDGET (row)); ++ gtk_container_add (GTK_CONTAINER (self->power_profile_info_listbox), GTK_WIDGET (row)); ++ } + } + + static void +@@ -1459,7 +1460,7 @@ power_profiles_properties_changed_cb (CcPowerPanel *self, + } + else if (g_strcmp0 (key, "PerformanceDegraded") == 0) + { +- performance_profile_set_degraded (self); ++ power_profile_update_info_boxes (self); + } + else if (g_strcmp0 (key, "ActiveProfile") == 0) + { +@@ -1600,8 +1601,6 @@ setup_power_profiles (CcPowerPanel *self) + self->has_performance_degraded = performance_degraded != NULL; + if (performance_degraded == NULL) + performance_inhibited = variant_lookup_string (props, "PerformanceInhibited"); +- else +- performance_profile_set_degraded (self); + active_profile = variant_lookup_string (props, "ActiveProfile"); + + last_button = NULL; +@@ -1649,6 +1648,9 @@ setup_power_profiles (CcPowerPanel *self) + + self->power_profiles_prop_id = g_signal_connect_object (G_OBJECT (self->power_profiles_proxy), "g-properties-changed", + G_CALLBACK (power_profiles_properties_changed_cb), self, G_CONNECT_SWAPPED); ++ ++ if (self->has_performance_degraded) ++ power_profile_update_info_boxes (self); + } + + static void +-- +2.32.0 + + +From 173904b7eeea145c38065939a1dd8a408745f3c9 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Fri, 16 Jul 2021 10:07:28 +0200 +Subject: [PATCH 16/33] power: Move variant_lookup_string() helper function + +--- + panels/power/cc-power-panel.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c +index 1869be065..4633627c2 100644 +--- a/panels/power/cc-power-panel.c ++++ b/panels/power/cc-power-panel.c +@@ -1343,6 +1343,18 @@ setup_power_saving (CcPowerPanel *self) + #endif + } + ++static const char * ++variant_lookup_string (GVariant *dict, ++ const char *key) ++{ ++ GVariant *variant; ++ ++ variant = g_variant_lookup_value (dict, key, G_VARIANT_TYPE_STRING); ++ if (!variant) ++ return NULL; ++ return g_variant_get_string (variant, NULL); ++} ++ + static void + performance_profile_set_active (CcPowerPanel *self, + const char *profile_str) +@@ -1427,18 +1439,6 @@ perf_profile_list_box_sort (GtkListBoxRow *row1, + return 0; + } + +-static const char * +-variant_lookup_string (GVariant *dict, +- const char *key) +-{ +- GVariant *variant; +- +- variant = g_variant_lookup_value (dict, key, G_VARIANT_TYPE_STRING); +- if (!variant) +- return NULL; +- return g_variant_get_string (variant, NULL); +-} +- + static void + power_profiles_properties_changed_cb (CcPowerPanel *self, + GVariant *changed_properties, +-- +2.32.0 + + +From f49c47787de81fa39f100f3903d2d886905cd4c7 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Fri, 16 Jul 2021 11:01:52 +0200 +Subject: [PATCH 17/33] power: Show power profile info boxes for profile holds + +Applications can request that power-profiles-daemon "hold" a particular +power profile for the duration of a task or event, such as launching a +taxing application, or saving power because of low battery. + +Show those holds in the same type of info boxes we already use to show +"degraded" performance. + +See https://gitlab.freedesktop.org/hadess/power-profiles-daemon/-/merge_requests/46 +--- + panels/power/cc-power-panel.c | 77 ++++++++++++++++++++++++++++++++++- + 1 file changed, 76 insertions(+), 1 deletion(-) + +diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c +index 4633627c2..4f1989cdf 100644 +--- a/panels/power/cc-power-panel.c ++++ b/panels/power/cc-power-panel.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + + #ifdef HAVE_NETWORK_MANAGER +@@ -1383,12 +1384,25 @@ static void + power_profile_update_info_boxes (CcPowerPanel *self) + { + g_autoptr(GVariant) degraded_variant = NULL; ++ g_autoptr(GVariant) holds_variant = NULL; ++ g_autoptr(GVariant) profile_variant = NULL; ++ guint i, num_children; + const char *degraded = NULL; ++ const char *profile; + CcPowerProfileInfoRow *row; ++ int next_insert = 0; + + empty_listbox (self->power_profile_info_listbox); + gtk_widget_hide (GTK_WIDGET (self->power_profile_info_listbox)); + ++ profile_variant = g_dbus_proxy_get_cached_property (self->power_profiles_proxy, "ActiveProfile"); ++ if (!profile_variant) ++ { ++ g_warning ("No 'ActiveProfile' property on power-profiles-daemon service"); ++ return; ++ } ++ profile = g_variant_get_string (profile_variant, NULL); ++ + degraded_variant = g_dbus_proxy_get_cached_property (self->power_profiles_proxy, "PerformanceDegraded"); + if (degraded_variant) + degraded = g_variant_get_string (degraded_variant, NULL); +@@ -1408,6 +1422,66 @@ power_profile_update_info_boxes (CcPowerPanel *self) + row = cc_power_profile_info_row_new (text); + gtk_widget_show (GTK_WIDGET (row)); + gtk_container_add (GTK_CONTAINER (self->power_profile_info_listbox), GTK_WIDGET (row)); ++ if (g_str_equal (profile, "performance")) ++ next_insert = 1; ++ } ++ ++ holds_variant = g_dbus_proxy_get_cached_property (self->power_profiles_proxy, "ActiveProfileHolds"); ++ if (!holds_variant) ++ { ++ g_warning ("No 'ActiveProfileHolds' property on power-profiles-daemon service"); ++ return; ++ } ++ ++ num_children = g_variant_n_children (holds_variant); ++ for (i = 0; i < num_children; i++) ++ { ++ g_autoptr(GDesktopAppInfo) app_info = NULL; ++ g_autoptr(GVariant) hold_variant = NULL; ++ g_autofree char *text = NULL; ++ const char *app_id, *held_profile, *reason, *name; ++ ++ hold_variant = g_variant_get_child_value (holds_variant, i); ++ if (!hold_variant || !g_variant_is_of_type (hold_variant, G_VARIANT_TYPE ("a{sv}"))) ++ continue; ++ ++ app_id = variant_lookup_string (hold_variant, "ApplicationId"); ++ if (!app_id) ++ continue; ++ app_info = g_desktop_app_info_new (app_id); ++ name = app_info ? g_app_info_get_name (G_APP_INFO (app_info)) : app_id; ++ held_profile = variant_lookup_string (hold_variant, "Profile"); ++ reason = variant_lookup_string (hold_variant, "Reason"); ++ g_debug ("Adding info row for %s hold by %s: %s", held_profile, app_id, reason); ++ ++ if (g_strcmp0 (held_profile, "power-saver") == 0 && ++ g_strcmp0 (app_id, "org.gnome.SettingsDaemon.Power") == 0) ++ { ++ text = g_strdup (_("Low battery: power saver enabled. Previous mode will be restored when battery is sufficiently charged.")); ++ } ++ else ++ { ++ switch (cc_power_profile_from_str (held_profile)) ++ { ++ case CC_POWER_PROFILE_POWER_SAVER: ++ /* translators: "%s" is an application name */ ++ text = g_strdup_printf (_("Power Saver mode activated by “%s”."), name); ++ break; ++ case CC_POWER_PROFILE_PERFORMANCE: ++ /* translators: "%s" is an application name */ ++ text = g_strdup_printf (_("Performance mode activated by “%s”."), name); ++ break; ++ default: ++ g_assert_not_reached (); ++ } ++ } ++ ++ row = cc_power_profile_info_row_new (text); ++ gtk_widget_show (GTK_WIDGET (row)); ++ if (g_strcmp0 (held_profile, profile) != 0) ++ gtk_list_box_insert (GTK_LIST_BOX (self->power_profile_info_listbox), GTK_WIDGET (row), -1); ++ else ++ gtk_list_box_insert (GTK_LIST_BOX (self->power_profile_info_listbox), GTK_WIDGET (row), next_insert); + } + } + +@@ -1458,7 +1532,8 @@ power_profiles_properties_changed_cb (CcPowerPanel *self, + performance_profile_set_inhibited (self, + g_variant_get_string (value, NULL)); + } +- else if (g_strcmp0 (key, "PerformanceDegraded") == 0) ++ else if (g_strcmp0 (key, "PerformanceDegraded") == 0 || ++ g_strcmp0 (key, "ActiveProfileHolds") == 0) + { + power_profile_update_info_boxes (self); + } +-- +2.32.0 + + +From d7cabb849c425fd84e85a981bcd56a6df1d87868 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Fri, 16 Jul 2021 11:32:37 +0200 +Subject: [PATCH 18/33] power: Tweak power profile info boxes horizontal + spacing + +A bit too much whitespace around the info icon. +--- + panels/power/cc-power-profile-info-row.ui | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/panels/power/cc-power-profile-info-row.ui b/panels/power/cc-power-profile-info-row.ui +index d9291ff16..bc49a24ac 100644 +--- a/panels/power/cc-power-profile-info-row.ui ++++ b/panels/power/cc-power-profile-info-row.ui +@@ -8,16 +8,16 @@ + + True + horizontal +- 12 +- 12 ++ 8 ++ 8 + 8 + 8 +- 12 ++ 8 + + + True + 6 +- 18 ++ 6 + info-symbolic + 5 + + + +-- +2.32.0 + + +From 254a9bfa8ac8be8403d0258742f0c3f8c8db9633 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Wed, 4 Aug 2021 11:26:33 +0200 +Subject: [PATCH 30/33] power: Remove icons from power profiles + +They were originally included was to educate users about what the icons +mean, for when they appeared in the top bar. However, since we no +longer plan on showing the status icon in the top bar, it's not so +important that people learn the meaning of the icons. + +See https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1421 +--- + panels/power/cc-power-profile-row.c | 13 +------------ + panels/power/cc-power-profile-row.ui | 15 +-------------- + 2 files changed, 2 insertions(+), 26 deletions(-) + +diff --git a/panels/power/cc-power-profile-row.c b/panels/power/cc-power-profile-row.c +index ee66bdfd0..a8458c366 100644 +--- a/panels/power/cc-power-profile-row.c ++++ b/panels/power/cc-power-profile-row.c +@@ -35,7 +35,6 @@ struct _CcPowerProfileRow + GtkListBoxRow parent_instance; + + GtkRadioButton *button; +- GtkImage *icon_image; + GtkLabel *subtitle_label; + GtkLabel *title_label; + +@@ -106,7 +105,6 @@ cc_power_profile_row_class_init (CcPowerProfileRowClass *klass) + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/power/cc-power-profile-row.ui"); + + gtk_widget_class_bind_template_child (widget_class, CcPowerProfileRow, button); +- gtk_widget_class_bind_template_child (widget_class, CcPowerProfileRow, icon_image); + gtk_widget_class_bind_template_child (widget_class, CcPowerProfileRow, subtitle_label); + gtk_widget_class_bind_template_child (widget_class, CcPowerProfileRow, title_label); + +@@ -175,7 +173,7 @@ CcPowerProfileRow * + cc_power_profile_row_new (CcPowerProfile power_profile) + { + CcPowerProfileRow *self; +- const char *text, *subtext, *icon_name, *class_name; ++ const char *text, *subtext; + + self = g_object_new (CC_TYPE_POWER_PROFILE_ROW, NULL); + +@@ -185,20 +183,14 @@ cc_power_profile_row_new (CcPowerProfile power_profile) + case CC_POWER_PROFILE_PERFORMANCE: + text = _("Performance"); + subtext = _("High performance and power usage."); +- icon_name = "power-profile-performance-symbolic"; +- class_name = "performance"; + break; + case CC_POWER_PROFILE_BALANCED: + text = _("Balanced Power"); + subtext = _("Standard performance and power usage."); +- icon_name = "power-profile-balanced-symbolic"; +- class_name = NULL; + break; + case CC_POWER_PROFILE_POWER_SAVER: + text = _("Power Saver"); + subtext = _("Reduced performance and power usage."); +- icon_name = "power-profile-power-saver-symbolic"; +- class_name = "low-power"; + break; + default: + g_assert_not_reached (); +@@ -206,9 +198,6 @@ cc_power_profile_row_new (CcPowerProfile power_profile) + + gtk_label_set_markup (self->title_label, text); + gtk_label_set_markup (self->subtitle_label, subtext); +- gtk_image_set_from_icon_name (self->icon_image, icon_name, GTK_ICON_SIZE_MENU); +- if (class_name != NULL) +- gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (self->icon_image)), class_name); + + return self; + } +diff --git a/panels/power/cc-power-profile-row.ui b/panels/power/cc-power-profile-row.ui +index 64516edf3..1391093ba 100644 +--- a/panels/power/cc-power-profile-row.ui ++++ b/panels/power/cc-power-profile-row.ui +@@ -28,19 +28,6 @@ + 2 + + +- +- +- True +- 6 +- +- +- +- 1 +- 0 +- +- + + + True +@@ -53,7 +40,7 @@ + 6 + + +- 2 ++ 1 + 0 + + +-- +2.32.0 + + +From 96efcd2835a46b8009b5f6524a2d37089f40dd44 Mon Sep 17 00:00:00 2001 +From: Allan Day +Date: Wed, 4 Aug 2021 11:28:14 +0200 +Subject: [PATCH 31/33] power: Align power profile info boxes with profiles + text + +See https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1421 +--- + panels/power/cc-power-profile-info-row.ui | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/panels/power/cc-power-profile-info-row.ui b/panels/power/cc-power-profile-info-row.ui +index 6f411c688..34807c38c 100644 +--- a/panels/power/cc-power-profile-info-row.ui ++++ b/panels/power/cc-power-profile-info-row.ui +@@ -8,11 +8,11 @@ + + True + horizontal +- 8 ++ 4 + 8 + 8 + 8 +- 8 ++ 4 + + + True +-- +2.32.0 + + +From 618e269230a71ae3ac84a35daaf15ad3db38f459 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Thu, 5 Aug 2021 15:24:58 +0200 +Subject: [PATCH 32/33] power: Change "Balanced" power profile label + +https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4530#note_1241985 +--- + panels/power/cc-power-profile-row.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/panels/power/cc-power-profile-row.c b/panels/power/cc-power-profile-row.c +index a8458c366..9d7f1fe6b 100644 +--- a/panels/power/cc-power-profile-row.c ++++ b/panels/power/cc-power-profile-row.c +@@ -185,7 +185,7 @@ cc_power_profile_row_new (CcPowerProfile power_profile) + subtext = _("High performance and power usage."); + break; + case CC_POWER_PROFILE_BALANCED: +- text = _("Balanced Power"); ++ text = _("Balanced"); + subtext = _("Standard performance and power usage."); + break; + case CC_POWER_PROFILE_POWER_SAVER: +-- +2.32.0 + + +From 98ed744dcefd8c4d8398b1489d0c583a4d5787d9 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Thu, 5 Aug 2021 15:24:58 +0200 +Subject: [PATCH 33/33] power: Update power profile labels + +Use "Balanced" instead of "Balanced Power", and make sure to add a +context for all the profiles for translators. + +https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4530#note_1243075 +--- + panels/power/cc-power-profile-row.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/panels/power/cc-power-profile-row.c b/panels/power/cc-power-profile-row.c +index 9d7f1fe6b..f290caa10 100644 +--- a/panels/power/cc-power-profile-row.c ++++ b/panels/power/cc-power-profile-row.c +@@ -181,15 +181,15 @@ cc_power_profile_row_new (CcPowerProfile power_profile) + switch (self->power_profile) + { + case CC_POWER_PROFILE_PERFORMANCE: +- text = _("Performance"); ++ text = C_("Power profile", "Performance"); + subtext = _("High performance and power usage."); + break; + case CC_POWER_PROFILE_BALANCED: +- text = _("Balanced"); ++ text = C_("Power profile", "Balanced"); + subtext = _("Standard performance and power usage."); + break; + case CC_POWER_PROFILE_POWER_SAVER: +- text = _("Power Saver"); ++ text = C_("Power profile", "Power Saver"); + subtext = _("Reduced performance and power usage."); + break; + default: +-- +2.32.0 + diff --git a/SOURCES/rpminspect-desktop-fixes.patch b/SOURCES/rpminspect-desktop-fixes.patch new file mode 100644 index 0000000..cc235d2 --- /dev/null +++ b/SOURCES/rpminspect-desktop-fixes.patch @@ -0,0 +1,64 @@ +diff -up gnome-control-center-40.0/panels/bluetooth/gnome-bluetooth-panel.desktop.in.in.rpminspect-desktop-fixes gnome-control-center-40.0/panels/bluetooth/gnome-bluetooth-panel.desktop.in.in +--- gnome-control-center-40.0/panels/bluetooth/gnome-bluetooth-panel.desktop.in.in.rpminspect-desktop-fixes 2022-02-02 14:10:24.722557740 +0100 ++++ gnome-control-center-40.0/panels/bluetooth/gnome-bluetooth-panel.desktop.in.in 2022-02-02 14:10:41.756366100 +0100 +@@ -2,7 +2,7 @@ + Name=Bluetooth + Comment=Turn Bluetooth on and off and connect your devices + # Translators: Do NOT translate or transliterate this text (this is an icon file name)! +-Icon=bluetooth ++Icon=bluetooth-symbolic + Exec=gnome-control-center bluetooth + Terminal=false + Type=Application +diff -up gnome-control-center-40.0/panels/location/gnome-location-panel.desktop.in.in.rpminspect-desktop-fixes gnome-control-center-40.0/panels/location/gnome-location-panel.desktop.in.in +--- gnome-control-center-40.0/panels/location/gnome-location-panel.desktop.in.in.rpminspect-desktop-fixes 2022-02-02 14:11:08.849061293 +0100 ++++ gnome-control-center-40.0/panels/location/gnome-location-panel.desktop.in.in 2022-02-02 14:11:20.606929011 +0100 +@@ -4,7 +4,7 @@ Comment=Protect your location informatio + Exec=gnome-control-center location + # FIXME + # Translators: Do NOT translate or transliterate this text (this is an icon file name)! +-Icon=location-services-active ++Icon=location-services-active-symbolic + Terminal=false + Type=Application + NoDisplay=true +diff -up gnome-control-center-40.0/panels/microphone/gnome-microphone-panel.desktop.in.in.rpminspect-desktop-fixes gnome-control-center-40.0/panels/microphone/gnome-microphone-panel.desktop.in.in +--- gnome-control-center-40.0/panels/microphone/gnome-microphone-panel.desktop.in.in.rpminspect-desktop-fixes 2022-02-02 14:12:15.652309721 +0100 ++++ gnome-control-center-40.0/panels/microphone/gnome-microphone-panel.desktop.in.in 2022-02-02 14:12:28.849161249 +0100 +@@ -4,7 +4,7 @@ Comment=Protect your conversations + Exec=gnome-control-center microphone + # FIXME + # Translators: Do NOT translate or transliterate this text (this is an icon file name)! +-Icon=audio-input-microphone ++Icon=audio-input-microphone-symbolic + Terminal=false + Type=Application + NoDisplay=true +diff -up gnome-control-center-40.0/panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in.rpminspect-desktop-fixes gnome-control-center-40.0/panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in +--- gnome-control-center-40.0/panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in.rpminspect-desktop-fixes 2022-02-02 14:12:50.891913256 +0100 ++++ gnome-control-center-40.0/panels/thunderbolt/gnome-thunderbolt-panel.desktop.in.in 2022-02-02 14:12:59.811812903 +0100 +@@ -3,7 +3,7 @@ Name=Thunderbolt + Comment=Manage Thunderbolt devices + Exec=gnome-control-center thunderbolt + # Translators: Do NOT translate or transliterate this text (this is an icon file name)! +-Icon=thunderbolt ++Icon=thunderbolt-symbolic + Terminal=false + Type=Application + NoDisplay=true +diff -up gnome-control-center-40.0/panels/wwan/gnome-wwan-panel.desktop.in.in.rpminspect-desktop-fixes gnome-control-center-40.0/panels/wwan/gnome-wwan-panel.desktop.in.in +--- gnome-control-center-40.0/panels/wwan/gnome-wwan-panel.desktop.in.in.rpminspect-desktop-fixes 2022-02-02 14:09:27.862197449 +0100 ++++ gnome-control-center-40.0/panels/wwan/gnome-wwan-panel.desktop.in.in 2022-02-02 14:13:34.301424876 +0100 +@@ -4,11 +4,10 @@ Comment=Configure Telephony and mobile d + Exec=gnome-control-center wwan + # FIXME + # Translators: Do NOT translate or transliterate this text (this is an icon file name)! +-Icon=network-cellular-signal-excellent ++Icon=network-cellular-signal-excellent-symbolic + Terminal=false + Type=Application + NoDisplay=true +-StartupNotify=true + Categories=GNOME;GTK;Settings;X-GNOME-NetworkSettings;HardwareSettings;X-GNOME-Settings-Panel;X-GNOME-ConnectivitySettings; + OnlyShowIn=GNOME;Unity; + StartupNotify=true diff --git a/SOURCES/subscription-manager-support.patch b/SOURCES/subscription-manager-support.patch new file mode 100644 index 0000000..7af3186 --- /dev/null +++ b/SOURCES/subscription-manager-support.patch @@ -0,0 +1,2564 @@ +From 9849810143193393bbf6fecfca2b415a4c58e147 Mon Sep 17 00:00:00 2001 +From: Kalev Lember +Date: Fri, 28 Jun 2019 17:14:36 +0200 +Subject: [PATCH 1/2] info-overview: Add subscription manager integration + +--- + panels/info-overview/cc-info-overview-panel.c | 190 ++++++ + .../info-overview/cc-info-overview-panel.ui | 10 + + panels/info-overview/cc-subscription-common.h | 34 + + .../cc-subscription-details-dialog.c | 578 ++++++++++++++++ + .../cc-subscription-details-dialog.h | 33 + + .../cc-subscription-details-dialog.ui | 425 ++++++++++++ + .../cc-subscription-register-dialog.c | 416 ++++++++++++ + .../cc-subscription-register-dialog.h | 33 + + .../cc-subscription-register-dialog.ui | 623 ++++++++++++++++++ + .../info-overview/info-overview.gresource.xml | 2 + + panels/info-overview/meson.build | 6 +- + po/POTFILES.in | 4 + + 12 files changed, 2353 insertions(+), 1 deletion(-) + create mode 100644 panels/info-overview/cc-subscription-common.h + create mode 100644 panels/info-overview/cc-subscription-details-dialog.c + create mode 100644 panels/info-overview/cc-subscription-details-dialog.h + create mode 100644 panels/info-overview/cc-subscription-details-dialog.ui + create mode 100644 panels/info-overview/cc-subscription-register-dialog.c + create mode 100644 panels/info-overview/cc-subscription-register-dialog.h + create mode 100644 panels/info-overview/cc-subscription-register-dialog.ui + +diff --git a/panels/info-overview/cc-info-overview-panel.c b/panels/info-overview/cc-info-overview-panel.c +index b20e5c1f7..99c8b20d7 100644 +--- a/panels/info-overview/cc-info-overview-panel.c ++++ b/panels/info-overview/cc-info-overview-panel.c +@@ -26,6 +26,9 @@ + #include "cc-os-release.h" + + #include "cc-info-overview-resources.h" ++#include "cc-subscription-common.h" ++#include "cc-subscription-details-dialog.h" ++#include "cc-subscription-register-dialog.h" + #include "info-cleanup.h" + + #include +@@ -74,8 +77,13 @@ struct _CcInfoOverviewPanel + CcListRow *os_type_row; + CcListRow *processor_row; + CcListRow *software_updates_row; ++ CcListRow *subscription_row; + CcListRow *virtualization_row; + CcListRow *windowing_system_row; ++ ++ /* Subscription */ ++ GCancellable *subscription_cancellable; ++ GDBusProxy *subscription_proxy; + }; + + typedef struct +@@ -770,6 +778,156 @@ info_overview_panel_setup_overview (CcInfoOverviewPanel *self) + cc_list_row_set_secondary_markup (self->graphics_row, graphics_hardware_string); + } + ++static void ++reload_subscription_status (CcInfoOverviewPanel *self) ++{ ++ GsdSubmanSubscriptionStatus status; ++ gboolean registered; ++ gboolean updates; ++ ++ if (self->subscription_proxy == NULL) ++ { ++ gtk_widget_hide (GTK_WIDGET (self->subscription_row)); ++ return; ++ } ++ ++ if (!get_subscription_status (self->subscription_proxy, &status)) ++ { ++ gtk_widget_hide (GTK_WIDGET (self->subscription_row)); ++ return; ++ } ++ ++ switch (status) ++ { ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN: ++ registered = FALSE; ++ updates = FALSE; ++ gtk_widget_set_sensitive (GTK_WIDGET (self->software_updates_row), FALSE); ++ break; ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED: ++ registered = TRUE; ++ updates = TRUE; ++ gtk_widget_set_sensitive (GTK_WIDGET (self->software_updates_row), TRUE); ++ break; ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID: ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID: ++ registered = TRUE; ++ updates = TRUE; ++ gtk_widget_set_sensitive (GTK_WIDGET (self->software_updates_row), TRUE); ++ break; ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID: ++ registered = TRUE; ++ updates = FALSE; ++ gtk_widget_set_sensitive (GTK_WIDGET (self->software_updates_row), FALSE); ++ break; ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS: ++ registered = FALSE; ++ updates = FALSE; ++ gtk_widget_set_sensitive (GTK_WIDGET (self->software_updates_row), FALSE); ++ break; ++ default: ++ g_assert_not_reached (); ++ break; ++ } ++ ++ if (registered) ++ { ++ if (updates) ++ cc_list_row_set_secondary_label (self->software_updates_row, _("System is registered and able to receive software updates.")); ++ else ++ cc_list_row_set_secondary_label (self->software_updates_row, _("System is registered but is unable to receive all software updates.")); ++ ++ cc_list_row_set_secondary_label (self->subscription_row, _("Registered System")); ++ g_object_set_data (G_OBJECT (self->subscription_row), "is-registered", GINT_TO_POINTER (TRUE)); ++ } ++ else ++ { ++ cc_list_row_set_secondary_label (self->software_updates_row, _("Register this system to receive software updates.")); ++ cc_list_row_set_secondary_label (self->subscription_row, _("System Not Registered")); ++ g_object_set_data (G_OBJECT (self->subscription_row), "is-registered", GINT_TO_POINTER (FALSE)); ++ } ++} ++ ++static void ++open_subscription_details_dialog (CcInfoOverviewPanel *self) ++{ ++ CcSubscriptionDetailsDialog *dialog; ++ GtkWindow *toplevel; ++ CcShell *shell; ++ ++ g_assert (CC_IS_INFO_OVERVIEW_PANEL (self)); ++ ++ dialog = cc_subscription_details_dialog_new (self->subscription_proxy, ++ self->subscription_cancellable); ++ ++ shell = cc_panel_get_shell (CC_PANEL (self)); ++ toplevel = GTK_WINDOW (cc_shell_get_toplevel (shell)); ++ gtk_window_set_transient_for (GTK_WINDOW (self->hostname_editor), toplevel); ++ ++ gtk_dialog_run (GTK_DIALOG (dialog)); ++ gtk_widget_destroy (GTK_WIDGET (dialog)); ++} ++ ++static void ++open_subscription_register_dialog (CcInfoOverviewPanel *self) ++{ ++ CcSubscriptionRegisterDialog *dialog; ++ GtkWindow *toplevel; ++ CcShell *shell; ++ ++ g_assert (CC_IS_INFO_OVERVIEW_PANEL (self)); ++ ++ dialog = cc_subscription_register_dialog_new (self->subscription_proxy, ++ self->subscription_cancellable); ++ ++ shell = cc_panel_get_shell (CC_PANEL (self)); ++ toplevel = GTK_WINDOW (cc_shell_get_toplevel (shell)); ++ gtk_window_set_transient_for (GTK_WINDOW (self->hostname_editor), toplevel); ++ ++ gtk_dialog_run (GTK_DIALOG (dialog)); ++ gtk_widget_destroy (GTK_WIDGET (dialog)); ++} ++ ++static void ++on_subscription_status_changed (GDBusProxy *proxy, ++ GVariant *changed_properties, ++ GStrv invalidated_properties, ++ CcInfoOverviewPanel *self) ++{ ++ g_cancellable_cancel (self->subscription_cancellable); ++ g_object_unref (self->subscription_cancellable); ++ ++ self->subscription_cancellable = g_cancellable_new (); ++ ++ reload_subscription_status (self); ++} ++ ++static void ++info_overview_panel_setup_subscriptions (CcInfoOverviewPanel *self) ++{ ++ g_autoptr(GError) error = NULL; ++ ++ self->subscription_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, ++ G_DBUS_PROXY_FLAGS_NONE, ++ NULL, ++ "org.gnome.SettingsDaemon.Subscription", ++ "/org/gnome/SettingsDaemon/Subscription", ++ "org.gnome.SettingsDaemon.Subscription", ++ NULL, &error); ++ if (error != NULL) ++ { ++ g_debug ("Unable to create a proxy for org.gnome.SettingsDaemon.Subscription: %s", ++ error->message); ++ reload_subscription_status (self); ++ return; ++ } ++ ++ g_signal_connect (self->subscription_proxy, "g-properties-changed", ++ G_CALLBACK (on_subscription_status_changed), self); ++ ++ reload_subscription_status (self); ++} ++ + static gboolean + does_gnome_software_exist (void) + { +@@ -860,6 +1018,15 @@ cc_info_panel_row_activated_cb (CcInfoOverviewPanel *self, + open_hostname_edit_dialog (self); + else if (row == self->software_updates_row) + open_software_update (self); ++ else if (row == self->subscription_row) ++ { ++ gboolean registered = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (row), "is-registered")); ++ ++ if (registered) ++ open_subscription_details_dialog (self); ++ else ++ open_subscription_register_dialog (self); ++ } + } + + #ifdef DARK_MODE_DISTRIBUTOR_LOGO +@@ -908,11 +1075,30 @@ setup_os_logo (CcInfoOverviewPanel *panel) + #endif + } + ++static void ++cc_info_overview_panel_finalize (GObject *object) ++{ ++ CcInfoOverviewPanel *self = (CcInfoOverviewPanel *) object; ++ ++ if (self->subscription_cancellable) ++ { ++ g_cancellable_cancel (self->subscription_cancellable); ++ g_clear_object (&self->subscription_cancellable); ++ } ++ ++ g_clear_object (&self->subscription_proxy); ++ ++ G_OBJECT_CLASS (cc_info_overview_panel_parent_class)->finalize (object); ++} ++ + static void + cc_info_overview_panel_class_init (CcInfoOverviewPanelClass *klass) + { ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + ++ object_class->finalize = cc_info_overview_panel_finalize; ++ + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/info-overview/cc-info-overview-panel.ui"); + + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, device_name_entry); +@@ -932,6 +1118,7 @@ cc_info_overview_panel_class_init (CcInfoOverviewPanelClass *klass) + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, processor_row); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, rename_button); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, software_updates_row); ++ gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, subscription_row); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, virtualization_row); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, windowing_system_row); + +@@ -951,11 +1138,14 @@ cc_info_overview_panel_init (CcInfoOverviewPanel *self) + + g_resources_register (cc_info_overview_get_resource ()); + ++ self->subscription_cancellable = g_cancellable_new (); ++ + if (!does_gnome_software_exist () && !does_gpk_update_viewer_exist ()) + gtk_widget_hide (GTK_WIDGET (self->software_updates_row)); + + info_overview_panel_setup_overview (self); + info_overview_panel_setup_virt (self); ++ info_overview_panel_setup_subscriptions (self); + + setup_os_logo (self); + } +diff --git a/panels/info-overview/cc-info-overview-panel.ui b/panels/info-overview/cc-info-overview-panel.ui +index 2f5d3cf8b..ddd2cf614 100644 +--- a/panels/info-overview/cc-info-overview-panel.ui ++++ b/panels/info-overview/cc-info-overview-panel.ui +@@ -179,6 +179,16 @@ + + + ++ ++ ++ ++ True ++ Subscription ++ System Not Registered ++ go-next-symbolic ++ ++ ++ + + + +diff --git a/panels/info-overview/cc-subscription-common.h b/panels/info-overview/cc-subscription-common.h +new file mode 100644 +index 000000000..034d64181 +--- /dev/null ++++ b/panels/info-overview/cc-subscription-common.h +@@ -0,0 +1,34 @@ ++#ifndef CC_SUBSCRIPTION_COMMON_H ++#define CC_SUBSCRIPTION_COMMON_H ++ ++typedef enum { ++ GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN, ++ GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID, ++ GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID, ++ GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED, ++ GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID, ++ GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS, ++ GSD_SUBMAN_SUBSCRIPTION_STATUS_LAST ++} GsdSubmanSubscriptionStatus; ++ ++static inline gboolean ++get_subscription_status (GDBusProxy *subscription_proxy, ++ GsdSubmanSubscriptionStatus *status) ++{ ++ g_autoptr(GVariant) status_variant = NULL; ++ guint32 u; ++ ++ status_variant = g_dbus_proxy_get_cached_property (subscription_proxy, "SubscriptionStatus"); ++ if (!status_variant) ++ { ++ g_debug ("Unable to get SubscriptionStatus property"); ++ return FALSE; ++ } ++ ++ g_variant_get (status_variant, "u", &u); ++ *status = u; ++ ++ return TRUE; ++} ++ ++#endif +diff --git a/panels/info-overview/cc-subscription-details-dialog.c b/panels/info-overview/cc-subscription-details-dialog.c +new file mode 100644 +index 000000000..15da1d911 +--- /dev/null ++++ b/panels/info-overview/cc-subscription-details-dialog.c +@@ -0,0 +1,578 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- ++ * ++ * Copyright 2019 Red Hat, Inc, ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ * ++ * Written by: Kalev Lember ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++ ++#include "cc-subscription-details-dialog.h" ++#include "cc-subscription-common.h" ++ ++#define DBUS_TIMEOUT 300000 /* 5 minutes */ ++ ++typedef enum { ++ DIALOG_STATE_SHOW_DETAILS, ++ DIALOG_STATE_SUBSCRIBE, ++ DIALOG_STATE_SUBSCRIBING, ++ DIALOG_STATE_UNREGISTER, ++ DIALOG_STATE_UNREGISTERING ++} DialogState; ++ ++struct _CcSubscriptionDetailsDialog ++{ ++ GtkDialog parent_instance; ++ ++ DialogState state; ++ GCancellable *cancellable; ++ GDBusProxy *subscription_proxy; ++ GPtrArray *products; ++ ++ /* template widgets */ ++ GtkButton *back_button; ++ GtkSpinner *spinner; ++ GtkStack *header_stack; ++ GtkButton *header_subscribe_button; ++ GtkButton *header_unregister_button; ++ GtkRevealer *notification_revealer; ++ GtkLabel *error_label; ++ GtkStack *stack; ++ GtkStack *status_stack; ++ GtkBox *products_box1; ++ GtkBox *products_box2; ++ GtkBox *products_box3; ++ GtkButton *subscribe_button; ++ GtkSeparator *separator; ++ GtkButton *unregister_button; ++}; ++ ++G_DEFINE_TYPE (CcSubscriptionDetailsDialog, cc_subscription_details_dialog, GTK_TYPE_DIALOG); ++ ++static void reload_installed_products (CcSubscriptionDetailsDialog *self); ++ ++typedef struct ++{ ++ gchar *product_name; ++ gchar *product_id; ++ gchar *version; ++ gchar *arch; ++ gchar *status; ++ gchar *starts; ++ gchar *ends; ++} ProductData; ++ ++static void ++product_data_free (ProductData *product) ++{ ++ g_free (product->product_name); ++ g_free (product->product_id); ++ g_free (product->version); ++ g_free (product->arch); ++ g_free (product->status); ++ g_free (product->starts); ++ g_free (product->ends); ++ g_free (product); ++} ++ ++G_DEFINE_AUTOPTR_CLEANUP_FUNC (ProductData, product_data_free); ++ ++static void ++add_product_row (GtkGrid *product_grid, const gchar *name, const gchar *value, gint top_attach) ++{ ++ GtkWidget *w; ++ ++ w = gtk_label_new (name); ++ gtk_style_context_add_class (gtk_widget_get_style_context (w), "dim-label"); ++ gtk_grid_attach (product_grid, w, 0, top_attach, 1, 1); ++ gtk_widget_set_halign (w, GTK_ALIGN_END); ++ gtk_widget_show (w); ++ ++ if (value == NULL) ++ value = _("Unknown"); ++ ++ w = gtk_label_new (value); ++ gtk_grid_attach (product_grid, w, 1, top_attach, 1, 1); ++ gtk_widget_set_halign (w, GTK_ALIGN_START); ++ gtk_widget_set_hexpand (w, TRUE); ++ gtk_widget_show (w); ++} ++ ++static GtkWidget * ++add_product (CcSubscriptionDetailsDialog *self, ProductData *product, GsdSubmanSubscriptionStatus status) ++{ ++ GtkGrid *product_grid; ++ const gchar *status_text; ++ ++ if (g_strcmp0 (product->status, "subscribed") == 0) ++ status_text = _("Subscribed"); ++ else if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED) ++ status_text = _("No Specific Subscription"); ++ else ++ status_text = _("Not Subscribed"); ++ ++ product_grid = GTK_GRID (gtk_grid_new ()); ++ gtk_grid_set_column_spacing (product_grid, 12); ++ gtk_grid_set_row_spacing (product_grid, 6); ++ gtk_widget_set_margin_top (GTK_WIDGET (product_grid), 18); ++ gtk_widget_set_margin_bottom (GTK_WIDGET (product_grid), 12); ++ gtk_widget_show (GTK_WIDGET (product_grid)); ++ ++ add_product_row (product_grid, _("Product Name"), product->product_name, 0); ++ add_product_row (product_grid, _("Product ID"), product->product_id, 1); ++ add_product_row (product_grid, _("Version"), product->version, 2); ++ add_product_row (product_grid, _("Arch"), product->arch, 3); ++ add_product_row (product_grid, _("Status"), status_text, 4); ++ ++ if (product->starts[0] != '\0' && product->ends[0] != '\0') ++ { ++ add_product_row (product_grid, _("Starts"), product->starts, 5); ++ add_product_row (product_grid, _("Ends"), product->ends, 6); ++ } ++ ++ return GTK_WIDGET (product_grid); ++} ++ ++static void ++remove_all_children (GtkContainer *container) ++{ ++ g_autoptr(GList) list = gtk_container_get_children (container); ++ ++ for (GList *l = list; l != NULL; l = l->next) ++ gtk_container_remove (container, (GtkWidget *) l->data); ++} ++ ++static void ++dialog_reload (CcSubscriptionDetailsDialog *self) ++{ ++ GtkHeaderBar *header = GTK_HEADER_BAR (gtk_dialog_get_header_bar (GTK_DIALOG (self))); ++ GsdSubmanSubscriptionStatus status = GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; ++ ++ reload_installed_products (self); ++ ++ switch (self->state) ++ { ++ case DIALOG_STATE_SHOW_DETAILS: ++ gtk_header_bar_set_show_close_button (header, TRUE); ++ ++ gtk_window_set_title (GTK_WINDOW (self), _("Registration Details")); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->header_unregister_button), TRUE); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->header_subscribe_button), TRUE); ++ ++ gtk_widget_hide (GTK_WIDGET (self->back_button)); ++ gtk_widget_hide (GTK_WIDGET (self->header_stack)); ++ ++ gtk_stack_set_visible_child_name (self->stack, "show-details"); ++ break; ++ ++ case DIALOG_STATE_SUBSCRIBE: ++ gtk_header_bar_set_show_close_button (header, FALSE); ++ gtk_stack_set_visible_child_name (self->header_stack, "subscribe"); ++ gtk_window_set_title (GTK_WINDOW (self), _("Subscribe System")); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->header_subscribe_button), TRUE); ++ ++ gtk_widget_show (GTK_WIDGET (self->back_button)); ++ ++ gtk_stack_set_visible_child_name (self->header_stack, "subscribe"); ++ gtk_widget_show (GTK_WIDGET (self->header_stack)); ++ ++ gtk_stack_set_visible_child_name (self->stack, "subscribe"); ++ break; ++ ++ case DIALOG_STATE_SUBSCRIBING: ++ gtk_header_bar_set_show_close_button (header, FALSE); ++ gtk_window_set_title (GTK_WINDOW (self), _("Looking For Available Subscriptions…")); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->header_subscribe_button), FALSE); ++ ++ gtk_widget_show (GTK_WIDGET (self->back_button)); ++ ++ gtk_stack_set_visible_child_name (self->header_stack, "subscribe"); ++ gtk_widget_show (GTK_WIDGET (self->header_stack)); ++ ++ gtk_stack_set_visible_child_name (self->stack, "subscribe"); ++ break; ++ ++ case DIALOG_STATE_UNREGISTER: ++ gtk_header_bar_set_show_close_button (header, FALSE); ++ ++ gtk_window_set_title (GTK_WINDOW (self), _("Unregister System")); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->header_unregister_button), TRUE); ++ ++ gtk_widget_show (GTK_WIDGET (self->back_button)); ++ ++ gtk_stack_set_visible_child_name (self->header_stack, "unregister"); ++ gtk_widget_show (GTK_WIDGET (self->header_stack)); ++ ++ gtk_stack_set_visible_child_name (self->stack, "unregister"); ++ break; ++ ++ case DIALOG_STATE_UNREGISTERING: ++ gtk_header_bar_set_show_close_button (header, FALSE); ++ ++ gtk_window_set_title (GTK_WINDOW (self), _("Unregistering System…")); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->header_unregister_button), FALSE); ++ ++ gtk_widget_show (GTK_WIDGET (self->back_button)); ++ ++ gtk_stack_set_visible_child_name (self->header_stack, "unregister"); ++ gtk_widget_show (GTK_WIDGET (self->header_stack)); ++ ++ gtk_stack_set_visible_child_name (self->stack, "unregister"); ++ break; ++ ++ default: ++ g_assert_not_reached (); ++ break; ++ } ++ ++ remove_all_children (GTK_CONTAINER (self->products_box1)); ++ remove_all_children (GTK_CONTAINER (self->products_box2)); ++ remove_all_children (GTK_CONTAINER (self->products_box3)); ++ ++ if (self->products == NULL || self->products->len == 0) ++ { ++ /* the widgets are duplicate to allow sliding between two stack pages */ ++ GtkWidget *w1 = gtk_label_new (_("No installed products detected.")); ++ GtkWidget *w2 = gtk_label_new (_("No installed products detected.")); ++ GtkWidget *w3 = gtk_label_new (_("No installed products detected.")); ++ gtk_widget_show (w1); ++ gtk_widget_show (w2); ++ gtk_widget_show (w3); ++ gtk_container_add (GTK_CONTAINER (self->products_box1), w1); ++ gtk_container_add (GTK_CONTAINER (self->products_box2), w2); ++ gtk_container_add (GTK_CONTAINER (self->products_box3), w3); ++ gtk_stack_set_visible_child_name (self->status_stack, "no-installed-products"); ++ ++ gtk_widget_hide (GTK_WIDGET (self->subscribe_button)); ++ gtk_widget_hide (GTK_WIDGET (self->separator)); ++ return; ++ } ++ ++ get_subscription_status (self->subscription_proxy, &status); ++ ++ for (guint i = 0; i < self->products->len; i++) ++ { ++ ProductData *product = g_ptr_array_index (self->products, i); ++ /* the widgets are duplicate to allow sliding between two stack pages */ ++ GtkWidget *w1 = add_product (self, product, status); ++ GtkWidget *w2 = add_product (self, product, status); ++ GtkWidget *w3 = add_product (self, product, status); ++ gtk_container_add (GTK_CONTAINER (self->products_box1), w1); ++ gtk_container_add (GTK_CONTAINER (self->products_box2), w2); ++ gtk_container_add (GTK_CONTAINER (self->products_box3), w3); ++ } ++ ++ switch (status) ++ { ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID: ++ gtk_stack_set_visible_child_name (self->status_stack, "fully-subscribed"); ++ gtk_widget_hide (GTK_WIDGET (self->subscribe_button)); ++ break; ++ ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID: ++ gtk_stack_set_visible_child_name (self->status_stack, "partly-subscribed"); ++ gtk_widget_show (GTK_WIDGET (self->subscribe_button)); ++ break; ++ ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED: ++ gtk_stack_set_visible_child_name (self->status_stack, "subscription-not-needed"); ++ gtk_widget_hide (GTK_WIDGET (self->subscribe_button)); ++ break; ++ ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN: ++ default: ++ gtk_stack_set_visible_child_name (self->status_stack, "not-subscribed"); ++ gtk_widget_show (GTK_WIDGET (self->subscribe_button)); ++ break; ++ } ++ ++ gtk_widget_set_visible (GTK_WIDGET (self->separator), ++ gtk_widget_get_visible (GTK_WIDGET (self->subscribe_button))); ++ ++} ++ ++static ProductData * ++parse_product_variant (GVariant *product_variant) ++{ ++ g_autoptr(ProductData) product = g_new0 (ProductData, 1); ++ g_auto(GVariantDict) dict; ++ ++ g_variant_dict_init (&dict, product_variant); ++ ++ g_variant_dict_lookup (&dict, "product-name", "s", &product->product_name); ++ g_variant_dict_lookup (&dict, "product-id", "s", &product->product_id); ++ g_variant_dict_lookup (&dict, "version", "s", &product->version); ++ g_variant_dict_lookup (&dict, "arch", "s", &product->arch); ++ g_variant_dict_lookup (&dict, "status", "s", &product->status); ++ g_variant_dict_lookup (&dict, "starts", "s", &product->starts); ++ g_variant_dict_lookup (&dict, "ends", "s", &product->ends); ++ ++ return g_steal_pointer (&product); ++} ++ ++static void ++reload_installed_products (CcSubscriptionDetailsDialog *self) ++{ ++ GVariantIter iter_array; ++ GVariant *child; ++ g_autoptr(GError) error = NULL; ++ g_autoptr(GVariant) installed_products_variant = NULL; ++ ++ installed_products_variant = g_dbus_proxy_get_cached_property (self->subscription_proxy, "InstalledProducts"); ++ if (installed_products_variant == NULL) ++ { ++ g_debug ("Unable to get InstalledProducts dbus property"); ++ return; ++ } ++ ++ g_ptr_array_set_size (self->products, 0); ++ ++ g_variant_iter_init (&iter_array, installed_products_variant); ++ while ((child = g_variant_iter_next_value (&iter_array)) != NULL) ++ { ++ g_autoptr(GVariant) product_variant = g_steal_pointer (&child); ++ g_ptr_array_add (self->products, parse_product_variant (product_variant)); ++ } ++} ++ ++static void ++subscription_done_cb (GObject *source_object, ++ GAsyncResult *res, ++ gpointer user_data) ++{ ++ CcSubscriptionDetailsDialog *self = (CcSubscriptionDetailsDialog *) user_data; ++ g_autoptr(GVariant) results = NULL; ++ g_autoptr(GError) error = NULL; ++ ++ results = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), ++ res, ++ &error); ++ if (results == NULL) ++ { ++ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) ++ return; ++ ++ g_dbus_error_strip_remote_error (error); ++ gtk_label_set_text (self->error_label, error->message); ++ gtk_revealer_set_reveal_child (self->notification_revealer, TRUE); ++ ++ gtk_spinner_stop (self->spinner); ++ ++ self->state = DIALOG_STATE_SUBSCRIBE; ++ dialog_reload (self); ++ return; ++ } ++ ++ gtk_spinner_stop (self->spinner); ++ ++ self->state = DIALOG_STATE_SHOW_DETAILS; ++ dialog_reload (self); ++} ++ ++static void ++header_subscribe_button_clicked_cb (CcSubscriptionDetailsDialog *self) ++{ ++ gtk_spinner_start (self->spinner); ++ ++ self->state = DIALOG_STATE_SUBSCRIBING; ++ dialog_reload (self); ++ ++ g_dbus_proxy_call (self->subscription_proxy, ++ "Attach", ++ NULL, ++ G_DBUS_CALL_FLAGS_NONE, ++ DBUS_TIMEOUT, ++ self->cancellable, ++ subscription_done_cb, ++ self); ++} ++ ++static void ++unregistration_done_cb (GObject *source_object, ++ GAsyncResult *res, ++ gpointer user_data) ++{ ++ CcSubscriptionDetailsDialog *self = (CcSubscriptionDetailsDialog *) user_data; ++ g_autoptr(GVariant) results = NULL; ++ g_autoptr(GError) error = NULL; ++ ++ results = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), ++ res, ++ &error); ++ if (results == NULL) ++ { ++ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) ++ return; ++ ++ g_dbus_error_strip_remote_error (error); ++ gtk_label_set_text (self->error_label, error->message); ++ gtk_revealer_set_reveal_child (self->notification_revealer, TRUE); ++ ++ gtk_spinner_stop (self->spinner); ++ ++ self->state = DIALOG_STATE_UNREGISTER; ++ dialog_reload (self); ++ return; ++ } ++ ++ gtk_spinner_stop (self->spinner); ++ ++ gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_ACCEPT); ++} ++ ++static void ++header_unregister_button_clicked_cb (CcSubscriptionDetailsDialog *self) ++{ ++ gtk_spinner_start (self->spinner); ++ ++ self->state = DIALOG_STATE_UNREGISTERING; ++ dialog_reload (self); ++ ++ g_dbus_proxy_call (self->subscription_proxy, ++ "Unregister", ++ NULL, ++ G_DBUS_CALL_FLAGS_NONE, ++ DBUS_TIMEOUT, ++ self->cancellable, ++ unregistration_done_cb, ++ self); ++} ++ ++static void ++back_button_clicked_cb (CcSubscriptionDetailsDialog *self) ++{ ++ gtk_spinner_stop (self->spinner); ++ ++ self->state = DIALOG_STATE_SHOW_DETAILS; ++ dialog_reload (self); ++} ++ ++static void ++subscribe_button_clicked_cb (CcSubscriptionDetailsDialog *self) ++{ ++ self->state = DIALOG_STATE_SUBSCRIBE; ++ dialog_reload (self); ++} ++ ++static void ++unregister_button_clicked_cb (CcSubscriptionDetailsDialog *self) ++{ ++ self->state = DIALOG_STATE_UNREGISTER; ++ dialog_reload (self); ++} ++ ++static void ++dismiss_notification (CcSubscriptionDetailsDialog *self) ++{ ++ gtk_revealer_set_reveal_child (self->notification_revealer, FALSE); ++} ++ ++static void ++cc_subscription_details_dialog_init (CcSubscriptionDetailsDialog *self) ++{ ++ gtk_widget_init_template (GTK_WIDGET (self)); ++ ++ self->products = g_ptr_array_new_with_free_func ((GDestroyNotify) product_data_free); ++ self->state = DIALOG_STATE_SHOW_DETAILS; ++} ++ ++static void ++cc_subscription_details_dialog_dispose (GObject *obj) ++{ ++ CcSubscriptionDetailsDialog *self = (CcSubscriptionDetailsDialog *) obj; ++ ++ g_cancellable_cancel (self->cancellable); ++ g_clear_object (&self->cancellable); ++ g_clear_object (&self->subscription_proxy); ++ ++ G_OBJECT_CLASS (cc_subscription_details_dialog_parent_class)->dispose (obj); ++} ++ ++static void ++cc_subscription_details_dialog_finalize (GObject *obj) ++{ ++ CcSubscriptionDetailsDialog *self = (CcSubscriptionDetailsDialog *) obj; ++ ++ g_clear_pointer (&self->products, g_ptr_array_unref); ++ ++ G_OBJECT_CLASS (cc_subscription_details_dialog_parent_class)->finalize (obj); ++} ++ ++static void ++cc_subscription_details_dialog_class_init (CcSubscriptionDetailsDialogClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); ++ ++ object_class->dispose = cc_subscription_details_dialog_dispose; ++ object_class->finalize = cc_subscription_details_dialog_finalize; ++ ++ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/info-overview/cc-subscription-details-dialog.ui"); ++ ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, back_button); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, spinner); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, header_stack); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, header_subscribe_button); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, header_unregister_button); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, notification_revealer); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, error_label); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, stack); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, status_stack); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, products_box1); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, products_box2); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, products_box3); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, subscribe_button); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, separator); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionDetailsDialog, unregister_button); ++ ++ gtk_widget_class_bind_template_callback (widget_class, back_button_clicked_cb); ++ gtk_widget_class_bind_template_callback (widget_class, header_subscribe_button_clicked_cb); ++ gtk_widget_class_bind_template_callback (widget_class, header_unregister_button_clicked_cb); ++ gtk_widget_class_bind_template_callback (widget_class, subscribe_button_clicked_cb); ++ gtk_widget_class_bind_template_callback (widget_class, unregister_button_clicked_cb); ++ gtk_widget_class_bind_template_callback (widget_class, dismiss_notification); ++} ++ ++static void ++on_dialog_cancelled (CcSubscriptionDetailsDialog *self) ++{ ++ gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_CLOSE); ++} ++ ++CcSubscriptionDetailsDialog * ++cc_subscription_details_dialog_new (GDBusProxy *subscription_proxy, ++ GCancellable *cancellable) ++{ ++ CcSubscriptionDetailsDialog *self; ++ ++ self = g_object_new (CC_TYPE_SUBSCRIPTION_DETAILS_DIALOG, "use-header-bar", TRUE, NULL); ++ self->subscription_proxy = g_object_ref (subscription_proxy); ++ self->cancellable = g_object_ref (cancellable); ++ ++ g_signal_connect_object (G_OBJECT (self->cancellable), ++ "cancelled", ++ G_CALLBACK (on_dialog_cancelled), ++ self, ++ G_CONNECT_SWAPPED); ++ ++ dialog_reload (self); ++ ++ return self; ++} +diff --git a/panels/info-overview/cc-subscription-details-dialog.h b/panels/info-overview/cc-subscription-details-dialog.h +new file mode 100644 +index 000000000..f14dd157b +--- /dev/null ++++ b/panels/info-overview/cc-subscription-details-dialog.h +@@ -0,0 +1,33 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- ++ * ++ * Copyright 2019 Red Hat, Inc, ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ * ++ * Written by: Kalev Lember ++ */ ++ ++#pragma once ++ ++#include ++ ++G_BEGIN_DECLS ++ ++#define CC_TYPE_SUBSCRIPTION_DETAILS_DIALOG (cc_subscription_details_dialog_get_type ()) ++G_DECLARE_FINAL_TYPE (CcSubscriptionDetailsDialog, cc_subscription_details_dialog, CC, SUBSCRIPTION_DETAILS_DIALOG, GtkDialog) ++ ++CcSubscriptionDetailsDialog *cc_subscription_details_dialog_new (GDBusProxy *subscription_proxy, ++ GCancellable *cancellable); ++ ++G_END_DECLS +diff --git a/panels/info-overview/cc-subscription-details-dialog.ui b/panels/info-overview/cc-subscription-details-dialog.ui +new file mode 100644 +index 000000000..6cdfc1220 +--- /dev/null ++++ b/panels/info-overview/cc-subscription-details-dialog.ui +@@ -0,0 +1,425 @@ ++ ++ ++ ++ +diff --git a/panels/info-overview/cc-subscription-register-dialog.c b/panels/info-overview/cc-subscription-register-dialog.c +new file mode 100644 +index 000000000..6867a976b +--- /dev/null ++++ b/panels/info-overview/cc-subscription-register-dialog.c +@@ -0,0 +1,416 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- ++ * ++ * Copyright 2019 Red Hat, Inc, ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ * ++ * Written by: Kalev Lember ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++ ++#include "cc-subscription-register-dialog.h" ++ ++#define DBUS_TIMEOUT 300000 /* 5 minutes */ ++#define SERVER_URL "subscription.rhsm.redhat.com" ++ ++typedef enum { ++ DIALOG_STATE_REGISTER, ++ DIALOG_STATE_REGISTERING ++} DialogState; ++ ++static void dialog_validate (CcSubscriptionRegisterDialog *self); ++ ++struct _CcSubscriptionRegisterDialog ++{ ++ GtkDialog parent_instance; ++ ++ DialogState state; ++ GCancellable *cancellable; ++ GDBusProxy *subscription_proxy; ++ gboolean valid; ++ ++ /* template widgets */ ++ GtkSpinner *spinner; ++ GtkButton *register_button; ++ GtkRevealer *notification_revealer; ++ GtkLabel *error_label; ++ GtkRadioButton *default_url_radio; ++ GtkRadioButton *custom_url_radio; ++ GtkRadioButton *register_radio; ++ GtkRadioButton *register_with_activation_keys_radio; ++ GtkStack *stack; ++ GtkGrid *register_grid; ++ GtkGrid *register_with_activation_keys_grid; ++ GtkEntry *url_label; ++ GtkEntry *url_entry; ++ GtkEntry *login_entry; ++ GtkEntry *password_entry; ++ GtkEntry *activation_keys_entry; ++ GtkLabel *organization_label; ++ GtkEntry *organization_entry; ++ GtkEntry *organization_entry_with_activation_keys; ++}; ++ ++G_DEFINE_TYPE (CcSubscriptionRegisterDialog, cc_subscription_register_dialog, GTK_TYPE_DIALOG); ++ ++static void ++dialog_reload (CcSubscriptionRegisterDialog *self) ++{ ++ gboolean sensitive; ++ gboolean url_entry_enabled; ++ ++ switch (self->state) ++ { ++ case DIALOG_STATE_REGISTER: ++ gtk_window_set_title (GTK_WINDOW (self), _("Register System")); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->register_button), self->valid); ++ ++ sensitive = TRUE; ++ break; ++ ++ case DIALOG_STATE_REGISTERING: ++ gtk_window_set_title (GTK_WINDOW (self), _("Registering System…")); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->register_button), FALSE); ++ ++ sensitive = FALSE; ++ break; ++ ++ default: ++ g_assert_not_reached (); ++ break; ++ } ++ ++ url_entry_enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->custom_url_radio)); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->url_entry), sensitive && url_entry_enabled); ++ ++ gtk_widget_set_sensitive (GTK_WIDGET (self->default_url_radio), sensitive); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->custom_url_radio), sensitive); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->register_radio), sensitive); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->register_with_activation_keys_radio), sensitive); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->login_entry), sensitive); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->password_entry), sensitive); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->activation_keys_entry), sensitive); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->password_entry), sensitive); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->organization_entry), sensitive); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->organization_entry_with_activation_keys), sensitive); ++} ++ ++static void ++custom_url_radio_toggled_cb (CcSubscriptionRegisterDialog *self) ++{ ++ gboolean active; ++ ++ active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->custom_url_radio)); ++ if (active) ++ { ++ gtk_widget_set_sensitive (GTK_WIDGET (self->url_entry), TRUE); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->url_label), TRUE); ++ ++ gtk_entry_set_text (self->url_entry, ""); ++ gtk_widget_grab_focus (GTK_WIDGET (self->url_entry)); ++ } ++ else ++ { ++ gtk_widget_set_sensitive (GTK_WIDGET (self->url_entry), FALSE); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->url_label), FALSE); ++ ++ gtk_entry_set_text (self->url_entry, SERVER_URL); ++ } ++ ++ dialog_validate (self); ++} ++ ++static void ++register_with_activation_keys_radio_toggled_cb (CcSubscriptionRegisterDialog *self) ++{ ++ gint active; ++ ++ active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->register_with_activation_keys_radio)); ++ if (active) ++ { ++ gtk_stack_set_visible_child_name (self->stack, "register-with-activation-keys"); ++ gtk_widget_grab_focus (GTK_WIDGET (self->activation_keys_entry)); ++ } ++ else ++ { ++ gtk_stack_set_visible_child_name (self->stack, "register"); ++ gtk_widget_grab_focus (GTK_WIDGET (self->login_entry)); ++ } ++ ++ dialog_validate (self); ++} ++ ++static void ++dialog_validate (CcSubscriptionRegisterDialog *self) ++{ ++ gboolean valid_url = TRUE; ++ gboolean valid_login = TRUE; ++ gboolean valid_password = TRUE; ++ gboolean valid_activation_keys = TRUE; ++ gboolean valid_organization = TRUE; ++ ++ /* require url when custom url radio is selected */ ++ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->custom_url_radio))) ++ { ++ const gchar *url; ++ ++ url = gtk_entry_get_text (self->url_entry); ++ valid_url = url != NULL && strlen (url) != 0; ++ } ++ ++ /* activation keys radio selected */ ++ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->register_with_activation_keys_radio))) ++ { ++ const gchar *activation_keys; ++ const gchar *organization; ++ ++ /* require activation keys */ ++ activation_keys = gtk_entry_get_text (self->activation_keys_entry); ++ valid_activation_keys = activation_keys != NULL && strlen (activation_keys) != 0; ++ ++ /* organization is required when using activation keys */ ++ organization = gtk_entry_get_text (self->organization_entry_with_activation_keys); ++ valid_organization = organization != NULL && strlen (organization) != 0; ++ ++ /* username/password radio selected */ ++ } ++ else ++ { ++ const gchar *login; ++ const gchar *password; ++ ++ /* require login */ ++ login = gtk_entry_get_text (self->login_entry); ++ valid_login = login != NULL && strlen (login) != 0; ++ ++ /* require password */ ++ password = gtk_entry_get_text (self->password_entry); ++ valid_password = password != NULL && strlen (password) != 0; ++ } ++ ++ self->valid = valid_url && valid_login && valid_password && valid_activation_keys && valid_organization; ++ gtk_widget_set_sensitive (GTK_WIDGET (self->register_button), self->valid); ++} ++ ++static void ++registration_done_cb (GObject *source_object, ++ GAsyncResult *res, ++ gpointer user_data) ++{ ++ CcSubscriptionRegisterDialog *self = (CcSubscriptionRegisterDialog *) user_data; ++ g_autoptr(GVariant) results = NULL; ++ g_autoptr(GError) error = NULL; ++ ++ results = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), ++ res, ++ &error); ++ if (results == NULL) ++ { ++ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) ++ return; ++ ++ g_dbus_error_strip_remote_error (error); ++ gtk_label_set_text (self->error_label, error->message); ++ gtk_revealer_set_reveal_child (self->notification_revealer, TRUE); ++ ++ gtk_spinner_stop (self->spinner); ++ ++ self->state = DIALOG_STATE_REGISTER; ++ dialog_reload (self); ++ return; ++ } ++ ++ gtk_spinner_stop (self->spinner); ++ gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_ACCEPT); ++ return; ++} ++ ++static void ++subscription_register_with_activation_keys (CcSubscriptionRegisterDialog *self) ++{ ++ g_autoptr(GVariantBuilder) options_builder = NULL; ++ const gchar *hostname; ++ const gchar *organization; ++ const gchar *activation_keys; ++ ++ hostname = gtk_entry_get_text (self->url_entry); ++ organization = gtk_entry_get_text (self->organization_entry_with_activation_keys); ++ activation_keys = gtk_entry_get_text (self->activation_keys_entry); ++ ++ options_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); ++ g_variant_builder_add (options_builder, "{sv}", "kind", g_variant_new_string ("key")); ++ g_variant_builder_add (options_builder, "{sv}", "hostname", g_variant_new_string (hostname)); ++ g_variant_builder_add (options_builder, "{sv}", "organisation", g_variant_new_string (organization)); ++ g_variant_builder_add (options_builder, "{sv}", "activation-key", g_variant_new_string (activation_keys)); ++ ++ g_dbus_proxy_call (self->subscription_proxy, ++ "Register", ++ g_variant_new ("(a{sv})", ++ options_builder), ++ G_DBUS_CALL_FLAGS_NONE, ++ DBUS_TIMEOUT, ++ self->cancellable, ++ registration_done_cb, ++ self); ++} ++ ++static void ++subscription_register_with_username (CcSubscriptionRegisterDialog *self) ++{ ++ g_autoptr(GVariantBuilder) options_builder = NULL; ++ const gchar *hostname; ++ const gchar *organization; ++ const gchar *username; ++ const gchar *password; ++ ++ hostname = gtk_entry_get_text (self->url_entry); ++ organization = gtk_entry_get_text (self->organization_entry); ++ username = gtk_entry_get_text (self->login_entry); ++ password = gtk_entry_get_text (self->password_entry); ++ ++ options_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); ++ g_variant_builder_add (options_builder, "{sv}", "kind", g_variant_new_string ("username")); ++ g_variant_builder_add (options_builder, "{sv}", "hostname", g_variant_new_string (hostname)); ++ g_variant_builder_add (options_builder, "{sv}", "organisation", g_variant_new_string (organization)); ++ g_variant_builder_add (options_builder, "{sv}", "username", g_variant_new_string (username)); ++ g_variant_builder_add (options_builder, "{sv}", "password", g_variant_new_string (password)); ++ ++ g_dbus_proxy_call (self->subscription_proxy, ++ "Register", ++ g_variant_new ("(a{sv})", options_builder), ++ G_DBUS_CALL_FLAGS_NONE, ++ DBUS_TIMEOUT, ++ self->cancellable, ++ registration_done_cb, ++ self); ++} ++ ++static void ++register_button_clicked_cb (CcSubscriptionRegisterDialog *self) ++{ ++ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->register_with_activation_keys_radio))) ++ subscription_register_with_activation_keys (self); ++ else ++ subscription_register_with_username (self); ++ ++ gtk_spinner_start (self->spinner); ++ ++ self->state = DIALOG_STATE_REGISTERING; ++ dialog_reload (self); ++} ++ ++static void ++dismiss_notification (CcSubscriptionRegisterDialog *self) ++{ ++ gtk_revealer_set_reveal_child (self->notification_revealer, FALSE); ++} ++ ++static void ++cc_subscription_register_dialog_init (CcSubscriptionRegisterDialog *self) ++{ ++ gtk_widget_init_template (GTK_WIDGET (self)); ++ ++ self->state = DIALOG_STATE_REGISTER; ++ ++ gtk_entry_set_text (self->url_entry, SERVER_URL); ++ gtk_widget_grab_focus (GTK_WIDGET (self->login_entry)); ++ dialog_validate (self); ++ dialog_reload (self); ++} ++ ++static void ++cc_subscription_register_dialog_dispose (GObject *obj) ++{ ++ CcSubscriptionRegisterDialog *self = (CcSubscriptionRegisterDialog *) obj; ++ ++ g_cancellable_cancel (self->cancellable); ++ g_clear_object (&self->cancellable); ++ g_clear_object (&self->subscription_proxy); ++ ++ G_OBJECT_CLASS (cc_subscription_register_dialog_parent_class)->dispose (obj); ++} ++ ++static void ++cc_subscription_register_dialog_finalize (GObject *obj) ++{ ++ G_OBJECT_CLASS (cc_subscription_register_dialog_parent_class)->finalize (obj); ++} ++ ++static void ++cc_subscription_register_dialog_class_init (CcSubscriptionRegisterDialogClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); ++ ++ object_class->dispose = cc_subscription_register_dialog_dispose; ++ object_class->finalize = cc_subscription_register_dialog_finalize; ++ ++ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/info-overview/cc-subscription-register-dialog.ui"); ++ ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, spinner); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, register_button); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, notification_revealer); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, error_label); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, default_url_radio); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, custom_url_radio); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, register_radio); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, register_with_activation_keys_radio); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, stack); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, register_grid); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, register_with_activation_keys_grid); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, url_label); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, url_entry); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, login_entry); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, password_entry); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, activation_keys_entry); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, organization_label); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, organization_entry); ++ gtk_widget_class_bind_template_child (widget_class, CcSubscriptionRegisterDialog, organization_entry_with_activation_keys); ++ ++ gtk_widget_class_bind_template_callback (widget_class, dialog_validate); ++ gtk_widget_class_bind_template_callback (widget_class, register_button_clicked_cb); ++ gtk_widget_class_bind_template_callback (widget_class, dismiss_notification); ++ gtk_widget_class_bind_template_callback (widget_class, custom_url_radio_toggled_cb); ++ gtk_widget_class_bind_template_callback (widget_class, register_with_activation_keys_radio_toggled_cb); ++} ++ ++static void ++on_dialog_cancelled (CcSubscriptionRegisterDialog *self) ++{ ++ gtk_dialog_response (GTK_DIALOG (self), GTK_RESPONSE_CLOSE); ++} ++ ++CcSubscriptionRegisterDialog * ++cc_subscription_register_dialog_new (GDBusProxy *subscription_proxy, ++ GCancellable *cancellable) ++{ ++ CcSubscriptionRegisterDialog *self; ++ ++ self = g_object_new (CC_TYPE_SUBSCRIPTION_REGISTER_DIALOG, "use-header-bar", TRUE, NULL); ++ self->subscription_proxy = g_object_ref (subscription_proxy); ++ self->cancellable = g_object_ref (cancellable); ++ ++ g_signal_connect_object (G_OBJECT (self->cancellable), ++ "cancelled", ++ G_CALLBACK (on_dialog_cancelled), ++ self, ++ G_CONNECT_SWAPPED); ++ ++ return self; ++} +diff --git a/panels/info-overview/cc-subscription-register-dialog.h b/panels/info-overview/cc-subscription-register-dialog.h +new file mode 100644 +index 000000000..31c254084 +--- /dev/null ++++ b/panels/info-overview/cc-subscription-register-dialog.h +@@ -0,0 +1,33 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- ++ * ++ * Copyright 2019 Red Hat, Inc, ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ * ++ * Written by: Kalev Lember ++ */ ++ ++#pragma once ++ ++#include ++ ++G_BEGIN_DECLS ++ ++#define CC_TYPE_SUBSCRIPTION_REGISTER_DIALOG (cc_subscription_register_dialog_get_type ()) ++G_DECLARE_FINAL_TYPE (CcSubscriptionRegisterDialog, cc_subscription_register_dialog, CC, SUBSCRIPTION_REGISTER_DIALOG, GtkDialog) ++ ++CcSubscriptionRegisterDialog *cc_subscription_register_dialog_new (GDBusProxy *subscription_proxy, ++ GCancellable *cancellable); ++ ++G_END_DECLS +diff --git a/panels/info-overview/cc-subscription-register-dialog.ui b/panels/info-overview/cc-subscription-register-dialog.ui +new file mode 100644 +index 000000000..21e317b41 +--- /dev/null ++++ b/panels/info-overview/cc-subscription-register-dialog.ui +@@ -0,0 +1,623 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ horizontal ++ ++ ++ ++ ++ ++ +diff --git a/panels/info-overview/info-overview.gresource.xml b/panels/info-overview/info-overview.gresource.xml +index 83806e0ad..e68944931 100644 +--- a/panels/info-overview/info-overview.gresource.xml ++++ b/panels/info-overview/info-overview.gresource.xml +@@ -2,6 +2,8 @@ + + + cc-info-overview-panel.ui ++ cc-subscription-details-dialog.ui ++ cc-subscription-register-dialog.ui + GnomeLogoVerticalMedium.svg + + +diff --git a/panels/info-overview/meson.build b/panels/info-overview/meson.build +index 14663f24c..1c9adb35c 100644 +--- a/panels/info-overview/meson.build ++++ b/panels/info-overview/meson.build +@@ -24,12 +24,16 @@ cflags += [ + + sources = files( + 'cc-info-overview-panel.c', ++ 'cc-subscription-details-dialog.c', ++ 'cc-subscription-register-dialog.c', + 'info-cleanup.c' + ) + + resource_data = files( + 'GnomeLogoVerticalMedium.svg', +- 'cc-info-overview-panel.ui' ++ 'cc-info-overview-panel.ui', ++ 'cc-subscription-details-dialog.ui', ++ 'cc-subscription-register-dialog.ui' + ) + + sources += gnome.compile_resources( +diff --git a/po/POTFILES.in b/po/POTFILES.in +index 5f7e8d49a..6063b50dd 100644 +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -50,6 +50,10 @@ panels/display/cc-night-light-page.ui + panels/display/gnome-display-panel.desktop.in.in + panels/info-overview/cc-info-overview-panel.c + panels/info-overview/cc-info-overview-panel.ui ++panels/info-overview/cc-subscription-details-dialog.c ++panels/info-overview/cc-subscription-details-dialog.ui ++panels/info-overview/cc-subscription-register-dialog.c ++panels/info-overview/cc-subscription-register-dialog.ui + panels/info-overview/gnome-info-overview-panel.desktop.in.in + panels/keyboard/00-multimedia.xml.in + panels/keyboard/01-input-sources.xml.in +-- +2.31.1 + + +From 785dae8f28a08f492da1053b55a601cdcec9233e Mon Sep 17 00:00:00 2001 +From: Kalev Lember +Date: Tue, 7 Sep 2021 13:13:08 +0200 +Subject: [PATCH 2/2] info-overview: Add desktop file keywords for subscription + support + +--- + panels/info-overview/gnome-info-overview-panel.desktop.in.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/panels/info-overview/gnome-info-overview-panel.desktop.in.in b/panels/info-overview/gnome-info-overview-panel.desktop.in.in +index 06abbdc19..2bfff8483 100644 +--- a/panels/info-overview/gnome-info-overview-panel.desktop.in.in ++++ b/panels/info-overview/gnome-info-overview-panel.desktop.in.in +@@ -19,4 +19,4 @@ X-GNOME-Bugzilla-Version=@VERSION@ + # The list MUST also end with a semicolon! + # "Preferred Applications" is the old name for the preference, so make + # sure that you use the same "translation" for those keywords +-Keywords=device;system;information;hostname;memory;processor;version;default;application;preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun; ++Keywords=device;system;information;hostname;memory;processor;version;default;application;preferred;cd;dvd;usb;audio;video;disc;removable;media;autorun;register;registration;subscribe;subscription; +-- +2.31.1 + diff --git a/SOURCES/wwan-backport-gnome-40.patch b/SOURCES/wwan-backport-gnome-40.patch new file mode 100644 index 0000000..408607a --- /dev/null +++ b/SOURCES/wwan-backport-gnome-40.patch @@ -0,0 +1,9200 @@ +From aa65caa35ae1c69b8b6644c1a72eb8110500e7e0 Mon Sep 17 00:00:00 2001 +From: Mohammed Sadiq +Date: Fri, 4 Oct 2019 12:27:26 +0530 +Subject: [PATCH 1/7] common: Add polkit rules for modem management + +--- + panels/common/gnome-control-center.rules.in | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/panels/common/gnome-control-center.rules.in b/panels/common/gnome-control-center.rules.in +index 971ffac63..22cf785e0 100644 +--- a/panels/common/gnome-control-center.rules.in ++++ b/panels/common/gnome-control-center.rules.in +@@ -1,6 +1,7 @@ + polkit.addRule(function(action, subject) { + if ((action.id == "org.freedesktop.locale1.set-locale" || + action.id == "org.freedesktop.locale1.set-keyboard" || ++ action.id == "org.freedesktop.ModemManager1.Device.Control" || + action.id == "org.freedesktop.hostname1.set-static-hostname" || + action.id == "org.freedesktop.hostname1.set-hostname" || + action.id == "org.gnome.controlcenter.datetime.configure") && +-- +2.32.0 + + +From 2b863f51831bc09d3ef56d16858724191ac9095c Mon Sep 17 00:00:00 2001 +From: Mohammed Sadiq +Date: Fri, 4 Oct 2019 22:16:23 +0530 +Subject: [PATCH 2/7] wwan: Add new panel for modem management + +The panel supports 2G/3G/4G GSM/LTE modems. CDMA2000 Modems are not supported. +If a supported modem is present, the panel will be shown and the modem will be +handled, else, network-panel shall manage the modem as it did in the past. + +If more than one modem with data enabled is present, the user is allowed to set +priority of one SIM over the other (the priority is for SIM, not modem). + +Fixes https://gitlab.gnome.org/GNOME/gnome-control-center/issues/132 +--- + meson.build | 4 + + panels/meson.build | 3 +- + panels/wwan/cc-wwan-apn-dialog.c | 424 ++++++ + panels/wwan/cc-wwan-apn-dialog.h | 40 + + panels/wwan/cc-wwan-apn-dialog.ui | 249 ++++ + panels/wwan/cc-wwan-data.c | 1446 ++++++++++++++++++++ + panels/wwan/cc-wwan-data.h | 93 ++ + panels/wwan/cc-wwan-details-dialog.c | 257 ++++ + panels/wwan/cc-wwan-details-dialog.h | 40 + + panels/wwan/cc-wwan-details-dialog.ui | 320 +++++ + panels/wwan/cc-wwan-device-page.c | 634 +++++++++ + panels/wwan/cc-wwan-device-page.h | 42 + + panels/wwan/cc-wwan-device-page.ui | 270 ++++ + panels/wwan/cc-wwan-device.c | 1355 ++++++++++++++++++ + panels/wwan/cc-wwan-device.h | 152 ++ + panels/wwan/cc-wwan-errors-private.h | 104 ++ + panels/wwan/cc-wwan-mode-dialog.c | 327 +++++ + panels/wwan/cc-wwan-mode-dialog.h | 40 + + panels/wwan/cc-wwan-mode-dialog.ui | 57 + + panels/wwan/cc-wwan-network-dialog.c | 443 ++++++ + panels/wwan/cc-wwan-network-dialog.h | 40 + + panels/wwan/cc-wwan-network-dialog.ui | 188 +++ + panels/wwan/cc-wwan-panel.c | 929 +++++++++++++ + panels/wwan/cc-wwan-panel.h | 36 + + panels/wwan/cc-wwan-panel.ui | 336 +++++ + panels/wwan/cc-wwan-sim-lock-dialog.c | 310 +++++ + panels/wwan/cc-wwan-sim-lock-dialog.h | 40 + + panels/wwan/cc-wwan-sim-lock-dialog.ui | 306 +++++ + panels/wwan/gnome-wwan-panel.desktop.in.in | 16 + + panels/wwan/meson.build | 61 + + panels/wwan/wwan.gresource.xml | 12 + + shell/cc-panel-list.c | 1 + + shell/cc-panel-loader.c | 9 + + 33 files changed, 8583 insertions(+), 1 deletion(-) + create mode 100644 panels/wwan/cc-wwan-apn-dialog.c + create mode 100644 panels/wwan/cc-wwan-apn-dialog.h + create mode 100644 panels/wwan/cc-wwan-apn-dialog.ui + create mode 100644 panels/wwan/cc-wwan-data.c + create mode 100644 panels/wwan/cc-wwan-data.h + create mode 100644 panels/wwan/cc-wwan-details-dialog.c + create mode 100644 panels/wwan/cc-wwan-details-dialog.h + create mode 100644 panels/wwan/cc-wwan-details-dialog.ui + create mode 100644 panels/wwan/cc-wwan-device-page.c + create mode 100644 panels/wwan/cc-wwan-device-page.h + create mode 100644 panels/wwan/cc-wwan-device-page.ui + create mode 100644 panels/wwan/cc-wwan-device.c + create mode 100644 panels/wwan/cc-wwan-device.h + create mode 100644 panels/wwan/cc-wwan-errors-private.h + create mode 100644 panels/wwan/cc-wwan-mode-dialog.c + create mode 100644 panels/wwan/cc-wwan-mode-dialog.h + create mode 100644 panels/wwan/cc-wwan-mode-dialog.ui + create mode 100644 panels/wwan/cc-wwan-network-dialog.c + create mode 100644 panels/wwan/cc-wwan-network-dialog.h + create mode 100644 panels/wwan/cc-wwan-network-dialog.ui + create mode 100644 panels/wwan/cc-wwan-panel.c + create mode 100644 panels/wwan/cc-wwan-panel.h + create mode 100644 panels/wwan/cc-wwan-panel.ui + create mode 100644 panels/wwan/cc-wwan-sim-lock-dialog.c + create mode 100644 panels/wwan/cc-wwan-sim-lock-dialog.h + create mode 100644 panels/wwan/cc-wwan-sim-lock-dialog.ui + create mode 100644 panels/wwan/gnome-wwan-panel.desktop.in.in + create mode 100644 panels/wwan/meson.build + create mode 100644 panels/wwan/wwan.gresource.xml + +diff --git a/meson.build b/meson.build +index 900216962..75487603b 100644 +--- a/meson.build ++++ b/meson.build +@@ -228,6 +228,10 @@ config_h.set('BUILD_NETWORK', host_is_linux, + description: 'Define to 1 to build the Network panel') + config_h.set('HAVE_NETWORK_MANAGER', host_is_linux, + description: 'Define to 1 if NetworkManager is available') ++config_h.set('BUILD_WWAN', host_is_linux, ++ description: 'Define to 1 to build the WWan panel') ++config_h.set('HAVE_WWAN', host_is_linux, ++ description: 'Define to 1 if WWan is available') + + if host_is_linux_not_s390 + # gnome-bluetooth +diff --git a/panels/meson.build b/panels/meson.build +index 2f4fdc5e3..9b9fc34f4 100644 +--- a/panels/meson.build ++++ b/panels/meson.build +@@ -26,7 +26,8 @@ panels = [ + 'sound', + 'universal-access', + 'usage', +- 'user-accounts' ++ 'user-accounts', ++ 'wwan', + ] + + if host_is_linux +diff --git a/panels/wwan/cc-wwan-apn-dialog.c b/panels/wwan/cc-wwan-apn-dialog.c +new file mode 100644 +index 000000000..bc5fde283 +--- /dev/null ++++ b/panels/wwan/cc-wwan-apn-dialog.c +@@ -0,0 +1,424 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-apn-dialog.c ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#undef G_LOG_DOMAIN ++#define G_LOG_DOMAIN "cc-wwan-apn-dialog" ++ ++#include ++#include ++#include ++ ++#include "cc-wwan-device.h" ++#include "cc-wwan-data.h" ++#include "list-box-helper.h" ++#include "cc-wwan-apn-dialog.h" ++#include "cc-wwan-resources.h" ++ ++/** ++ * @short_description: Dialog to manage Internet Access Points ++ */ ++ ++struct _CcWwanApnDialog ++{ ++ GtkDialog parent_instance; ++ ++ GtkButton *add_button; ++ GtkButton *back_button; ++ GtkButton *save_button; ++ GtkEntry *apn_entry; ++ GtkEntry *name_entry; ++ GtkEntry *password_entry; ++ GtkEntry *username_entry; ++ GtkGrid *apn_edit_view; ++ GtkListBox *apn_list; ++ GtkRadioButton *apn_radio_button; ++ GtkScrolledWindow *apn_list_view; ++ GtkStack *apn_settings_stack; ++ ++ CcWwanData *wwan_data; ++ CcWwanDataApn *apn_to_save; /* The APN currently being edited */ ++ CcWwanDevice *device; ++ ++ gboolean enable_data; ++ gboolean enable_roaming; ++}; ++ ++G_DEFINE_TYPE (CcWwanApnDialog, cc_wwan_apn_dialog, GTK_TYPE_DIALOG) ++ ++ ++enum { ++ PROP_0, ++ PROP_DEVICE, ++ N_PROPS ++}; ++ ++static GParamSpec *properties[N_PROPS]; ++ ++#define CC_TYPE_WWAN_APN_ROW (cc_wwan_apn_row_get_type()) ++G_DECLARE_FINAL_TYPE (CcWwanApnRow, cc_wwan_apn_row, CC, WWAN_APN_ROW, GtkListBoxRow) ++ ++struct _CcWwanApnRow ++{ ++ GtkListBoxRow parent_instance; ++ GtkRadioButton *radio_button; ++ CcWwanDataApn *apn; ++}; ++ ++G_DEFINE_TYPE (CcWwanApnRow, cc_wwan_apn_row, GTK_TYPE_LIST_BOX_ROW) ++ ++static void ++cc_wwan_apn_row_finalize (GObject *object) ++{ ++ CcWwanApnRow *row = (CcWwanApnRow *)object; ++ ++ g_clear_object (&row->apn); ++ ++ G_OBJECT_CLASS (cc_wwan_apn_row_parent_class)->finalize (object); ++} ++ ++static void ++cc_wwan_apn_row_class_init (CcWwanApnRowClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->finalize = cc_wwan_apn_row_finalize; ++} ++ ++static void ++cc_wwan_apn_row_init (CcWwanApnRow *row) ++{ ++} ++ ++static void ++cc_wwan_apn_back_clicked_cb (CcWwanApnDialog *self) ++{ ++ GtkWidget *view; ++ ++ view = gtk_stack_get_visible_child (self->apn_settings_stack); ++ ++ if (view == GTK_WIDGET (self->apn_edit_view)) ++ { ++ gtk_widget_hide (GTK_WIDGET (self->save_button)); ++ gtk_widget_show (GTK_WIDGET (self->add_button)); ++ gtk_stack_set_visible_child (self->apn_settings_stack, ++ GTK_WIDGET (self->apn_list_view)); ++ } ++ else ++ { ++ gtk_widget_hide (GTK_WIDGET (self)); ++ } ++} ++ ++static void ++cc_wwan_apn_add_clicked_cb (CcWwanApnDialog *self) ++{ ++ gtk_entry_set_text (self->name_entry, ""); ++ gtk_entry_set_text (self->apn_entry, ""); ++ gtk_entry_set_text (self->username_entry, ""); ++ gtk_entry_set_text (self->password_entry, ""); ++ ++ gtk_widget_hide (GTK_WIDGET (self->add_button)); ++ gtk_widget_show (GTK_WIDGET (self->save_button)); ++ self->apn_to_save = NULL; ++ gtk_stack_set_visible_child (self->apn_settings_stack, ++ GTK_WIDGET (self->apn_edit_view)); ++} ++ ++static void ++cc_wwan_apn_save_clicked_cb (CcWwanApnDialog *self) ++{ ++ const gchar *name, *apn_name; ++ CcWwanDataApn *apn; ++ ++ apn = self->apn_to_save; ++ self->apn_to_save = NULL; ++ ++ name = gtk_entry_get_text (self->name_entry); ++ apn_name = gtk_entry_get_text (self->apn_entry); ++ ++ if (!apn) ++ apn = cc_wwan_data_apn_new (); ++ ++ cc_wwan_data_apn_set_name (apn, name); ++ cc_wwan_data_apn_set_apn (apn, apn_name); ++ cc_wwan_data_apn_set_username (apn, gtk_entry_get_text (self->username_entry)); ++ cc_wwan_data_apn_set_password (apn, gtk_entry_get_text (self->password_entry)); ++ ++ cc_wwan_data_save_apn (self->wwan_data, apn, NULL, NULL, NULL); ++ ++ gtk_widget_hide (GTK_WIDGET (self->save_button)); ++ gtk_stack_set_visible_child (self->apn_settings_stack, ++ GTK_WIDGET (self->apn_list_view)); ++} ++ ++static void ++cc_wwan_apn_entry_changed_cb (CcWwanApnDialog *self) ++{ ++ GtkWidget *widget; ++ const gchar *str; ++ gboolean valid_name, valid_apn; ++ ++ widget = GTK_WIDGET (self->name_entry); ++ str = gtk_entry_get_text (self->name_entry); ++ valid_name = str && *str; ++ ++ if (valid_name) ++ gtk_style_context_remove_class (gtk_widget_get_style_context (widget), "error"); ++ else ++ gtk_style_context_add_class (gtk_widget_get_style_context (widget), "error"); ++ ++ widget = GTK_WIDGET (self->apn_entry); ++ str = gtk_entry_get_text (self->apn_entry); ++ valid_apn = str && *str; ++ ++ if (valid_apn) ++ gtk_style_context_remove_class (gtk_widget_get_style_context (widget), "error"); ++ else ++ gtk_style_context_add_class (gtk_widget_get_style_context (widget), "error"); ++ ++ gtk_widget_set_sensitive (GTK_WIDGET (self->save_button), valid_name && valid_apn); ++} ++ ++static void ++cc_wwan_apn_activated_cb (CcWwanApnDialog *self, ++ CcWwanApnRow *row) ++{ ++ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (row->radio_button), TRUE); ++} ++ ++static void ++cc_wwan_apn_changed_cb (CcWwanApnDialog *self, ++ GtkWidget *widget) ++{ ++ CcWwanApnRow *row; ++ ++ if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) ++ return; ++ ++ widget = gtk_widget_get_ancestor (widget, CC_TYPE_WWAN_APN_ROW); ++ row = CC_WWAN_APN_ROW (widget); ++ ++ if (cc_wwan_data_set_default_apn (self->wwan_data, row->apn)) ++ cc_wwan_data_save_settings (self->wwan_data, NULL, NULL, NULL); ++} ++ ++static void ++cc_wwan_apn_edit_clicked_cb (CcWwanApnDialog *self, ++ GtkButton *button) ++{ ++ CcWwanDataApn *apn; ++ CcWwanApnRow *row; ++ GtkWidget *widget; ++ ++ widget = gtk_widget_get_ancestor (GTK_WIDGET (button), CC_TYPE_WWAN_APN_ROW); ++ row = CC_WWAN_APN_ROW (widget); ++ apn = row->apn; ++ self->apn_to_save = apn; ++ ++ gtk_widget_show (GTK_WIDGET (self->save_button)); ++ gtk_widget_hide (GTK_WIDGET (self->add_button)); ++ ++ gtk_entry_set_text (self->name_entry, cc_wwan_data_apn_get_name (apn)); ++ gtk_entry_set_text (self->apn_entry, cc_wwan_data_apn_get_apn (apn)); ++ gtk_entry_set_text (self->username_entry, cc_wwan_data_apn_get_username (apn)); ++ gtk_entry_set_text (self->password_entry, cc_wwan_data_apn_get_password (apn)); ++ ++ gtk_stack_set_visible_child (self->apn_settings_stack, ++ GTK_WIDGET (self->apn_edit_view)); ++} ++ ++static GtkWidget * ++cc_wwan_apn_dialog_row_new (CcWwanDataApn *apn, ++ CcWwanApnDialog *self) ++{ ++ CcWwanApnRow *row; ++ GtkWidget *grid, *name_label, *apn_label, *radio, *edit_button; ++ GtkStyleContext *context; ++ ++ row = g_object_new (CC_TYPE_WWAN_APN_ROW, NULL); ++ ++ grid = g_object_new (GTK_TYPE_GRID, ++ "margin-top", 6, ++ "margin-bottom", 6, ++ "margin-start", 6, ++ "margin-end", 6, ++ NULL); ++ ++ radio = gtk_radio_button_new_from_widget (self->apn_radio_button); ++ row->radio_button = GTK_RADIO_BUTTON (radio); ++ gtk_widget_set_margin_end (radio, 12); ++ gtk_grid_attach (GTK_GRID (grid), radio, 0, 0, 1, 2); ++ row->apn = g_object_ref (apn); ++ ++ if (cc_wwan_data_get_default_apn (self->wwan_data) == apn) ++ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); ++ g_signal_connect_object (radio, "toggled", ++ G_CALLBACK (cc_wwan_apn_changed_cb), ++ self, G_CONNECT_SWAPPED); ++ ++ name_label = gtk_label_new (cc_wwan_data_apn_get_name (apn)); ++ gtk_widget_set_halign (name_label, GTK_ALIGN_START); ++ gtk_widget_set_hexpand (name_label, TRUE); ++ gtk_grid_attach (GTK_GRID (grid), name_label, 1, 0, 1, 1); ++ ++ apn_label = gtk_label_new (cc_wwan_data_apn_get_apn (apn)); ++ gtk_widget_set_halign (apn_label, GTK_ALIGN_START); ++ context = gtk_widget_get_style_context (apn_label); ++ gtk_style_context_add_class (context, "dim-label"); ++ gtk_grid_attach (GTK_GRID (grid), apn_label, 1, 1, 1, 1); ++ ++ edit_button = gtk_button_new_from_icon_name ("emblem-system-symbolic", ++ GTK_ICON_SIZE_BUTTON); ++ g_signal_connect_object (edit_button, "clicked", ++ G_CALLBACK (cc_wwan_apn_edit_clicked_cb), ++ self, G_CONNECT_SWAPPED); ++ gtk_grid_attach (GTK_GRID (grid), edit_button, 2, 0, 1, 2); ++ ++ gtk_container_add (GTK_CONTAINER (row), grid); ++ gtk_widget_show_all (GTK_WIDGET (row)); ++ ++ return GTK_WIDGET (row); ++} ++ ++static void ++cc_wwan_apn_dialog_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ CcWwanApnDialog *self = (CcWwanApnDialog *)object; ++ ++ switch (prop_id) ++ { ++ case PROP_DEVICE: ++ self->device = g_value_dup_object (value); ++ break; ++ ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } ++} ++ ++static void ++cc_wwan_apn_dialog_constructed (GObject *object) ++{ ++ CcWwanApnDialog *self = (CcWwanApnDialog *)object; ++ ++ G_OBJECT_CLASS (cc_wwan_apn_dialog_parent_class)->constructed (object); ++ ++ self->wwan_data = cc_wwan_device_get_data (self->device); ++ ++ gtk_list_box_bind_model (self->apn_list, ++ cc_wwan_data_get_apn_list (self->wwan_data), ++ (GtkListBoxCreateWidgetFunc)cc_wwan_apn_dialog_row_new, ++ self, NULL); ++} ++ ++static void ++cc_wwan_apn_dialog_dispose (GObject *object) ++{ ++ CcWwanApnDialog *self = (CcWwanApnDialog *)object; ++ ++ g_clear_object (&self->device); ++ ++ G_OBJECT_CLASS (cc_wwan_apn_dialog_parent_class)->dispose (object); ++} ++ ++ ++static void ++cc_wwan_apn_dialog_show (GtkWidget *widget) ++{ ++ CcWwanApnDialog *self = (CcWwanApnDialog *)widget; ++ ++ gtk_widget_show (GTK_WIDGET (self->add_button)); ++ gtk_widget_hide (GTK_WIDGET (self->save_button)); ++ gtk_stack_set_visible_child (self->apn_settings_stack, ++ GTK_WIDGET (self->apn_list_view)); ++ ++ GTK_WIDGET_CLASS (cc_wwan_apn_dialog_parent_class)->show (widget); ++} ++ ++static void ++cc_wwan_apn_dialog_class_init (CcWwanApnDialogClass *klass) ++{ ++ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->set_property = cc_wwan_apn_dialog_set_property; ++ object_class->constructed = cc_wwan_apn_dialog_constructed; ++ object_class->dispose = cc_wwan_apn_dialog_dispose; ++ ++ widget_class->show = cc_wwan_apn_dialog_show; ++ ++ properties[PROP_DEVICE] = ++ g_param_spec_object ("device", ++ "Device", ++ "The WWAN Device", ++ CC_TYPE_WWAN_DEVICE, ++ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); ++ ++ g_object_class_install_properties (object_class, N_PROPS, properties); ++ ++ gtk_widget_class_set_template_from_resource (widget_class, ++ "/org/gnome/control-center/wwan/cc-wwan-apn-dialog.ui"); ++ ++ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, add_button); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, apn_edit_view); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, apn_entry); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, apn_list); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, apn_list_view); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, apn_radio_button); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, apn_settings_stack); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, back_button); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, name_entry); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, password_entry); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, save_button); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanApnDialog, username_entry); ++ ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_apn_back_clicked_cb); ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_apn_add_clicked_cb); ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_apn_save_clicked_cb); ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_apn_entry_changed_cb); ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_apn_activated_cb); ++} ++ ++static void ++cc_wwan_apn_dialog_init (CcWwanApnDialog *self) ++{ ++ gtk_widget_init_template (GTK_WIDGET (self)); ++} ++ ++CcWwanApnDialog * ++cc_wwan_apn_dialog_new (GtkWindow *parent_window, ++ CcWwanDevice *device) ++{ ++ g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL); ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (device), NULL); ++ ++ return g_object_new (CC_TYPE_WWAN_APN_DIALOG, ++ "transient-for", parent_window, ++ "use-header-bar", 1, ++ "device", device, ++ NULL); ++} +diff --git a/panels/wwan/cc-wwan-apn-dialog.h b/panels/wwan/cc-wwan-apn-dialog.h +new file mode 100644 +index 000000000..0e9885836 +--- /dev/null ++++ b/panels/wwan/cc-wwan-apn-dialog.h +@@ -0,0 +1,40 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-apn-dialog.h ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#pragma once ++ ++#include ++#include ++ ++#include "cc-wwan-device.h" ++ ++G_BEGIN_DECLS ++ ++#define CC_TYPE_WWAN_APN_DIALOG (cc_wwan_apn_dialog_get_type()) ++G_DECLARE_FINAL_TYPE (CcWwanApnDialog, cc_wwan_apn_dialog, CC, WWAN_APN_DIALOG, GtkDialog) ++ ++CcWwanApnDialog *cc_wwan_apn_dialog_new (GtkWindow *parent_window, ++ CcWwanDevice *device); ++ ++G_END_DECLS +diff --git a/panels/wwan/cc-wwan-apn-dialog.ui b/panels/wwan/cc-wwan-apn-dialog.ui +new file mode 100644 +index 000000000..fb8432bc6 +--- /dev/null ++++ b/panels/wwan/cc-wwan-apn-dialog.ui +@@ -0,0 +1,249 @@ ++ ++ ++ ++ ++ ++ ++ +diff --git a/panels/wwan/cc-wwan-data.c b/panels/wwan/cc-wwan-data.c +new file mode 100644 +index 000000000..0be8f3403 +--- /dev/null ++++ b/panels/wwan/cc-wwan-data.c +@@ -0,0 +1,1446 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-data.c ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#undef G_LOG_DOMAIN ++#define G_LOG_DOMAIN "cc-wwan-data" ++ ++#ifdef HAVE_CONFIG_H ++# include ++#endif ++ ++#define _GNU_SOURCE ++#include ++#include ++#include ++ ++#include "cc-wwan-data.h" ++ ++/** ++ * @short_description: Device Internet Data Object ++ * @include: "cc-wwan-device-data.h" ++ * ++ * #CcWwanData represents the data object of the given ++ * #CcWwanDevice. Please note that while #CcWWanDevice ++ * is bound to the hardware device, #CcWwanData may also ++ * depend on the inserted SIM (if supported). So the state ++ * of #CcWwanData changes when SIM is changed. ++ */ ++ ++/* Priority for connections. larger the number, lower the priority */ ++#define CC_WWAN_DNS_PRIORITY_LOW (20) ++#define CC_WWAN_DNS_PRIORITY_HIGH (15) ++ ++/* These are to be set as route metric */ ++#define CC_WWAN_ROUTE_PRIORITY_LOW (1050) ++#define CC_WWAN_ROUTE_PRIORITY_HIGH (1040) ++ ++struct _CcWwanData ++{ ++ GObject parent_instance; ++ ++ MMObject *mm_object; ++ MMModem *modem; ++ MMSim *sim; ++ gchar *sim_id; ++ ++ gchar *operator_code; /* MCCMNC */ ++ GError *error; ++ ++ NMClient *nm_client; ++ NMDevice *nm_device; ++ NMAMobileProvidersDatabase *apn_db; ++ NMAMobileProvider *apn_provider; ++ CcWwanDataApn *default_apn; ++ CcWwanDataApn *old_default_apn; ++ GListStore *apn_list; ++ NMActiveConnection *active_connection; ++ ++ gint priority; ++ gboolean data_enabled; /* autoconnect enabled */ ++ gboolean home_only; /* Data roaming */ ++}; ++ ++G_DEFINE_TYPE (CcWwanData, cc_wwan_data, G_TYPE_OBJECT) ++ ++/* ++ * Default Access Point Settings Logic: ++ * For a provided SIM, all the APNs available from NetworkManager ++ * that matches the given SIM identifier (ICCID, available via ++ * mm_sim_get_identifier() or similar gdbus API) is loaded for ++ * the Device (In NetworkManager, it is saved as ‘sim-id’, if ++ * present). At a time, only one connection will be bound to ++ * a device. If there are more than one match, the item with ++ * the highest ‘route-metric’ is taken. If more matches are ++ * still available, the first item is chosen. ++ * ++ * Populating All available APNs: ++ * All Possible APNs for the given sim are populated the following ++ * way (A list of all the following avoiding duplicates) ++ * 1. The above mentioned “Default Access Point Settings Logic” ++ * 2. Get All saved Network Manager connections with the ++ * provided MCCMNC of the given SIM ++ * 3. Get All possible APNs for the MCCMNC from mobile-provider-info ++ * ++ * Testing if data is enabled: ++ * Check if any of the items from step 1 have ‘autoconnect’ set ++ * ++ * Checking/Setting current SIM for data (in case of multiple SIM): ++ * Since other networks (like wifi, ethernet) should have higher ++ * priorities we use a negative number for priority. ++ * 1. All APNs by default have priority CC_WWAN_APN_PRIORITY_LOW ++ * 2. APN of selected SIM for active data have priority of ++ * CC_WWAN_APN_PRIORITY_HIGH ++ * ++ * XXX: Since users may create custom APNs via nmtui or like tools ++ * we may have to check if there are some inconsistencies with APNs ++ * available in NetworkManager, and ask user if they have to reset ++ * the APNs that have invalid settings (basically, we care only APNs ++ * that are set to have ‘autoconnect’ enabled, and all we need is to ++ * disable autoconnect). We won’t interfere CDMA/EVDO networks. ++ */ ++struct _CcWwanDataApn { ++ GObject parent_instance; ++ ++ /* Set if the APN is from the mobile-provider-info database */ ++ NMAMobileAccessMethod *access_method; ++ ++ /* Set if the APN is saved in NetworkManager */ ++ NMConnection *nm_connection; ++ NMRemoteConnection *remote_connection; ++ ++ gboolean modified; ++}; ++ ++G_DEFINE_TYPE (CcWwanDataApn, cc_wwan_data_apn, G_TYPE_OBJECT) ++ ++enum { ++ PROP_0, ++ PROP_ERROR, ++ PROP_ENABLED, ++ N_PROPS ++}; ++ ++static GParamSpec *properties[N_PROPS]; ++ ++static void ++wwan_data_apn_reset (CcWwanDataApn *apn) ++{ ++ if (!apn) ++ return; ++ ++ g_clear_object (&apn->nm_connection); ++ g_clear_object (&apn->remote_connection); ++} ++ ++static NMConnection * ++wwan_data_get_nm_connection (CcWwanDataApn *apn) ++{ ++ NMConnection *connection; ++ NMSetting *setting; ++ g_autofree gchar *uuid = NULL; ++ ++ if (apn->nm_connection) ++ return apn->nm_connection; ++ ++ if (apn->remote_connection) ++ return NM_CONNECTION (apn->remote_connection); ++ ++ connection = nm_simple_connection_new (); ++ apn->nm_connection = connection; ++ ++ setting = nm_setting_connection_new (); ++ uuid = nm_utils_uuid_generate (); ++ g_object_set (setting, ++ NM_SETTING_CONNECTION_UUID, uuid, ++ NM_SETTING_CONNECTION_TYPE, NM_SETTING_GSM_SETTING_NAME, ++ NULL); ++ nm_connection_add_setting (connection, setting); ++ ++ setting = nm_setting_serial_new (); ++ nm_connection_add_setting (connection, setting); ++ ++ setting = nm_setting_ip4_config_new (); ++ g_object_set (setting, NM_SETTING_IP_CONFIG_METHOD, "auto", NULL); ++ nm_connection_add_setting (connection, setting); ++ ++ nm_connection_add_setting (connection, nm_setting_gsm_new ()); ++ nm_connection_add_setting (connection, nm_setting_ppp_new ()); ++ ++ return apn->nm_connection; ++} ++ ++static gboolean ++wwan_data_apn_are_same (NMRemoteConnection *remote_connection, ++ NMAMobileAccessMethod *access_method) ++{ ++ NMConnection *connection; ++ NMSetting *setting; ++ ++ if (!remote_connection) ++ return FALSE; ++ ++ connection = NM_CONNECTION (remote_connection); ++ setting = NM_SETTING (nm_connection_get_setting_gsm (connection)); ++ ++ if (g_strcmp0 (nma_mobile_access_method_get_3gpp_apn (access_method), ++ nm_setting_gsm_get_apn (NM_SETTING_GSM (setting))) != 0) ++ return FALSE; ++ ++ if (g_strcmp0 (nma_mobile_access_method_get_username (access_method), ++ nm_setting_gsm_get_username (NM_SETTING_GSM (setting))) != 0) ++ return FALSE; ++ ++ if (g_strcmp0 (nma_mobile_access_method_get_password (access_method), ++ nm_setting_gsm_get_password (NM_SETTING_GSM (setting))) != 0) ++ return FALSE; ++ ++ return TRUE; ++} ++ ++static CcWwanDataApn * ++wwan_data_find_matching_apn (CcWwanData *self, ++ NMAMobileAccessMethod *access_method) ++{ ++ CcWwanDataApn *apn; ++ guint i, n_items; ++ ++ n_items = g_list_model_get_n_items (G_LIST_MODEL (self->apn_list)); ++ ++ for (i = 0; i < n_items; i++) ++ { ++ apn = g_list_model_get_item (G_LIST_MODEL (self->apn_list), i); ++ ++ if (apn->access_method == access_method) ++ return apn; ++ ++ if (wwan_data_apn_are_same (apn->remote_connection, ++ access_method)) ++ return apn; ++ ++ g_object_unref (apn); ++ } ++ ++ return NULL; ++} ++ ++static gboolean ++wwan_data_nma_method_is_mms (NMAMobileAccessMethod *method) ++{ ++ const char *str; ++ ++ str = nma_mobile_access_method_get_3gpp_apn (method); ++ if (str && strcasestr (str, "mms")) ++ return TRUE; ++ ++ str = nma_mobile_access_method_get_name (method); ++ if (str && strcasestr (str, "mms")) ++ return TRUE; ++ ++ return FALSE; ++} ++ ++static void ++wwan_data_update_apn_list_db (CcWwanData *self) ++{ ++ GSList *apn_methods = NULL, *l; ++ g_autoptr(GError) error = NULL; ++ guint i = 0; ++ ++ if (!self->sim || !self->operator_code) ++ return; ++ ++ if (!self->apn_list) ++ self->apn_list = g_list_store_new (CC_TYPE_WWAN_DATA_APN); ++ ++ if (!self->apn_db) ++ self->apn_db = nma_mobile_providers_database_new_sync (NULL, NULL, NULL, &error); ++ ++ if (error) ++ { ++ g_warning ("%s", error->message); ++ return; ++ } ++ ++ if (!self->apn_provider) ++ self->apn_provider = nma_mobile_providers_database_lookup_3gpp_mcc_mnc (self->apn_db, ++ self->operator_code); ++ ++ if (self->apn_provider) ++ apn_methods = nma_mobile_provider_get_methods (self->apn_provider); ++ ++ for (l = apn_methods; l; l = l->next, i++) ++ { ++ g_autoptr(CcWwanDataApn) apn = NULL; ++ ++ /* We don’t list MMS APNs */ ++ if (wwan_data_nma_method_is_mms (l->data)) ++ continue; ++ ++ apn = wwan_data_find_matching_apn (self, l->data); ++ ++ /* Prepend the item in order */ ++ if (!apn) ++ { ++ apn = cc_wwan_data_apn_new (); ++ g_list_store_insert (self->apn_list, i, apn); ++ } ++ ++ apn->access_method = l->data; ++ } ++} ++ ++static void ++wwan_data_update_apn_list (CcWwanData *self) ++{ ++ const GPtrArray *nm_connections; ++ guint i; ++ ++ if (self->apn_list || !self->sim) ++ return; ++ ++ if (!self->apn_list) ++ self->apn_list = g_list_store_new (CC_TYPE_WWAN_DATA_APN); ++ ++ if (self->nm_device) ++ { ++ nm_connections = nm_device_get_available_connections (self->nm_device); ++ ++ for (i = 0; i < nm_connections->len; i++) ++ { ++ g_autoptr(CcWwanDataApn) apn = NULL; ++ ++ apn = cc_wwan_data_apn_new (); ++ apn->remote_connection = g_object_ref (nm_connections->pdata[i]); ++ g_list_store_append (self->apn_list, apn); ++ ++ /* Load the default APN */ ++ if (!self->default_apn && self->sim_id) ++ { ++ NMSettingConnection *connection_setting; ++ NMSettingIPConfig *ip_setting; ++ NMSettingGsm *setting; ++ NMConnection *connection; ++ const gchar *sim_id; ++ ++ connection = NM_CONNECTION (apn->remote_connection); ++ setting = nm_connection_get_setting_gsm (connection); ++ connection_setting = nm_connection_get_setting_connection (connection); ++ sim_id = nm_setting_gsm_get_sim_id (setting); ++ ++ if (sim_id && *sim_id && g_str_equal (sim_id, self->sim_id)) ++ { ++ self->default_apn = apn; ++ self->home_only = nm_setting_gsm_get_home_only (setting); ++ self->data_enabled = nm_setting_connection_get_autoconnect (connection_setting); ++ ++ /* If any of the APN has a high priority, the device have high priority */ ++ ip_setting = nm_connection_get_setting_ip4_config (connection); ++ if (nm_setting_ip_config_get_route_metric (ip_setting) == CC_WWAN_ROUTE_PRIORITY_HIGH) ++ self->priority = CC_WWAN_APN_PRIORITY_HIGH; ++ } ++ } ++ } ++ } ++} ++ ++static void ++wwan_device_state_changed_cb (CcWwanData *self) ++{ ++ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ENABLED]); ++} ++ ++static void ++cc_wwan_data_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec) ++{ ++ CcWwanData *self = (CcWwanData *)object; ++ ++ switch (prop_id) ++ { ++ case PROP_ERROR: ++ g_value_set_boolean (value, self->error != NULL); ++ break; ++ ++ case PROP_ENABLED: ++ g_value_set_boolean (value, cc_wwan_data_get_enabled (self)); ++ break; ++ ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } ++} ++ ++static void ++cc_wwan_data_dispose (GObject *object) ++{ ++ CcWwanData *self = (CcWwanData *)object; ++ ++ g_clear_pointer (&self->sim_id, g_free); ++ g_clear_pointer (&self->operator_code, g_free); ++ g_clear_error (&self->error); ++ g_clear_object (&self->apn_list); ++ g_clear_object (&self->modem); ++ g_clear_object (&self->mm_object); ++ g_clear_object (&self->nm_client); ++ g_clear_object (&self->active_connection); ++ g_clear_object (&self->apn_db); ++ ++ G_OBJECT_CLASS (cc_wwan_data_parent_class)->dispose (object); ++} ++ ++static void ++cc_wwan_data_class_init (CcWwanDataClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->get_property = cc_wwan_data_get_property; ++ object_class->dispose = cc_wwan_data_dispose; ++ ++ properties[PROP_ERROR] = ++ g_param_spec_boolean ("error", ++ "Error", ++ "Set if some Error occurs", ++ FALSE, ++ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); ++ ++ properties[PROP_ENABLED] = ++ g_param_spec_boolean ("enabled", ++ "Enabled", ++ "Get if the data is enabled", ++ FALSE, ++ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); ++ ++ g_object_class_install_properties (object_class, N_PROPS, properties); ++} ++ ++static void ++cc_wwan_data_init (CcWwanData *self) ++{ ++ self->home_only = TRUE; ++ self->priority = CC_WWAN_APN_PRIORITY_LOW; ++} ++ ++/** ++ * cc_wwan_data_new: ++ * @mm_object: An #MMObject ++ * @nm_client: An #NMClient ++ * ++ * Create a new device data representing the given ++ * @mm_object. If @mm_object isn’t a 3G/CDMA/LTE ++ * modem, %NULL will be returned ++ * ++ * Returns: A #CcWwanData or %NULL. ++ */ ++CcWwanData * ++cc_wwan_data_new (MMObject *mm_object, ++ NMClient *nm_client) ++{ ++ CcWwanData *self; ++ NMDevice *nm_device = NULL; ++ g_autoptr(MMModem) modem = NULL; ++ NMDeviceModemCapabilities capabilities = 0; ++ ++ g_return_val_if_fail (MM_IS_OBJECT (mm_object), NULL); ++ g_return_val_if_fail (NM_CLIENT (nm_client), NULL); ++ ++ modem = mm_object_get_modem (mm_object); ++ ++ if (modem) ++ nm_device = nm_client_get_device_by_iface (nm_client, ++ mm_modem_get_primary_port (modem)); ++ ++ if (NM_IS_DEVICE_MODEM (nm_device)) ++ capabilities = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (nm_device)); ++ ++ if (!(capabilities & (NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS ++ | NM_DEVICE_MODEM_CAPABILITY_LTE))) ++ return NULL; ++ ++ self = g_object_new (CC_TYPE_WWAN_DATA, NULL); ++ ++ self->nm_client = g_object_ref (nm_client); ++ self->mm_object = g_object_ref (mm_object); ++ self->modem = g_steal_pointer (&modem); ++ self->sim = mm_modem_get_sim_sync (self->modem, NULL, NULL); ++ self->sim_id = mm_sim_dup_identifier (self->sim); ++ self->operator_code = mm_sim_dup_operator_identifier (self->sim); ++ self->nm_device = g_object_ref (nm_device); ++ self->active_connection = nm_device_get_active_connection (nm_device); ++ ++ if (!self->operator_code) ++ { ++ MMModem3gpp *modem_3gpp; ++ ++ modem_3gpp = mm_object_peek_modem_3gpp (mm_object); ++ if (modem_3gpp) ++ self->operator_code = mm_modem_3gpp_dup_operator_code (modem_3gpp); ++ } ++ ++ if (self->active_connection) ++ g_object_ref (self->active_connection); ++ ++ g_signal_connect_object (self->nm_device, "notify::state", ++ G_CALLBACK (wwan_device_state_changed_cb), ++ self, G_CONNECT_SWAPPED); ++ ++ wwan_data_update_apn_list (self); ++ wwan_data_update_apn_list_db (self); ++ ++ return self; ++} ++ ++GError * ++cc_wwan_data_get_error (CcWwanData *self) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DATA (self), NULL); ++ ++ return self->error; ++} ++ ++const gchar * ++cc_wwan_data_get_simple_html_error (CcWwanData *self) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DATA (self), NULL); ++ ++ if (!self->error) ++ return NULL; ++ ++ if (g_error_matches (self->error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) ++ return _("Operation Cancelled"); ++ ++ if (g_error_matches (self->error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED)) ++ return _("Error: Access denied changing settings"); ++ ++ if (self->error->domain == MM_MOBILE_EQUIPMENT_ERROR) ++ return _("Error: Mobile Equipment Error"); ++ ++ return NULL; ++} ++ ++GListModel * ++cc_wwan_data_get_apn_list (CcWwanData *self) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DATA (self), NULL); ++ ++ if (!self->apn_list) ++ wwan_data_update_apn_list (self); ++ ++ return G_LIST_MODEL (self->apn_list); ++} ++ ++static gboolean ++wwan_data_apn_is_new (CcWwanDataApn *apn) ++{ ++ return apn->remote_connection == NULL; ++} ++ ++static void ++wwan_data_update_apn (CcWwanData *self, ++ CcWwanDataApn *apn, ++ NMConnection *connection) ++{ ++ NMSetting *setting; ++ const gchar *name, *username, *password, *apn_name; ++ gint dns_priority, route_metric; ++ ++ setting = NM_SETTING (nm_connection_get_setting_connection (connection)); ++ ++ g_object_set (setting, ++ NM_SETTING_CONNECTION_AUTOCONNECT, self->data_enabled, ++ NULL); ++ ++ setting = NM_SETTING (nm_connection_get_setting_gsm (connection)); ++ ++ g_object_set (setting, ++ NM_SETTING_GSM_HOME_ONLY, self->home_only, ++ NULL); ++ ++ setting = NM_SETTING (nm_connection_get_setting_ip4_config (connection)); ++ if (self->priority == CC_WWAN_APN_PRIORITY_HIGH && ++ self->default_apn == apn) ++ { ++ dns_priority = CC_WWAN_DNS_PRIORITY_HIGH; ++ route_metric = CC_WWAN_ROUTE_PRIORITY_HIGH; ++ } ++ else ++ { ++ dns_priority = CC_WWAN_DNS_PRIORITY_LOW; ++ route_metric = CC_WWAN_ROUTE_PRIORITY_LOW; ++ } ++ ++ g_object_set (setting, ++ NM_SETTING_IP_CONFIG_DNS_PRIORITY, dns_priority, ++ NM_SETTING_IP_CONFIG_ROUTE_METRIC, (gint64)route_metric, ++ NULL); ++ ++ if (apn->access_method && !apn->remote_connection) ++ { ++ name = nma_mobile_access_method_get_name (apn->access_method); ++ username = nma_mobile_access_method_get_username (apn->access_method); ++ password = nma_mobile_access_method_get_password (apn->access_method); ++ apn_name = nma_mobile_access_method_get_3gpp_apn (apn->access_method); ++ } ++ else ++ { ++ return; ++ } ++ ++ setting = NM_SETTING (nm_connection_get_setting_gsm (connection)); ++ g_object_set (setting, ++ NM_SETTING_GSM_USERNAME, username, ++ NM_SETTING_GSM_PASSWORD, password, ++ NM_SETTING_GSM_APN, apn_name, ++ NULL); ++ ++ setting = NM_SETTING (nm_connection_get_setting_connection (connection)); ++ ++ g_object_set (setting, ++ NM_SETTING_CONNECTION_ID, name, ++ NULL); ++} ++ ++static gint ++wwan_data_get_apn_index (CcWwanData *self, ++ CcWwanDataApn *apn) ++{ ++ GListModel *model; ++ guint i, n_items; ++ ++ model = G_LIST_MODEL (self->apn_list); ++ n_items = g_list_model_get_n_items (model); ++ ++ for (i = 0; i < n_items; i++) ++ { ++ g_autoptr(CcWwanDataApn) cached_apn = NULL; ++ ++ cached_apn = g_list_model_get_item (model, i); ++ ++ if (apn == cached_apn) ++ return i; ++ } ++ ++ return -1; ++} ++ ++static void ++cc_wwan_data_connection_updated_cb (GObject *object, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ CcWwanData *self; ++ CcWwanDataApn *apn; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; ++ ++ self = g_task_get_source_object (G_TASK (task)); ++ apn = g_task_get_task_data (G_TASK (task)); ++ ++ nm_remote_connection_commit_changes_finish (apn->remote_connection, ++ result, &error); ++ if (!error) ++ { ++ guint apn_index; ++ apn_index = wwan_data_get_apn_index (self, apn); ++ ++ if (apn_index >= 0) ++ g_list_model_items_changed (G_LIST_MODEL (self->apn_list), ++ apn_index, 1, 1); ++ else ++ g_warning ("APN ‘%s’ not in APN list", ++ cc_wwan_data_apn_get_name (apn)); ++ ++ apn->modified = FALSE; ++ g_task_return_boolean (task, TRUE); ++ } ++ else ++ { ++ g_task_return_error (task, g_steal_pointer (&error)); ++ } ++} ++ ++static void ++cc_wwan_data_new_connection_added_cb (GObject *object, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ CcWwanData *self; ++ CcWwanDataApn *apn; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; ++ ++ self = g_task_get_source_object (G_TASK (task)); ++ apn = g_task_get_task_data (G_TASK (task)); ++ apn->remote_connection = nm_client_add_connection_finish (self->nm_client, ++ result, &error); ++ if (!error) ++ { ++ apn->modified = FALSE; ++ ++ /* If APN has access method, it’s already on the list */ ++ if (!apn->access_method) ++ { ++ g_list_store_append (self->apn_list, apn); ++ g_object_unref (apn); ++ } ++ ++ g_task_return_pointer (task, apn, NULL); ++ } ++ else ++ { ++ g_task_return_error (task, g_steal_pointer (&error)); ++ } ++} ++ ++void ++cc_wwan_data_save_apn (CcWwanData *self, ++ CcWwanDataApn *apn, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data) ++{ ++ NMConnection *connection = NULL; ++ g_autoptr(GTask) task = NULL; ++ ++ g_return_if_fail (CC_IS_WWAN_DATA (self)); ++ g_return_if_fail (CC_IS_WWAN_DATA_APN (apn)); ++ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); ++ ++ task = g_task_new (self, cancellable, callback, user_data); ++ g_task_set_task_data (task, apn, NULL); ++ ++ connection = wwan_data_get_nm_connection (apn); ++ ++ /* If the item has a remote connection, it should already be saved. ++ * We should save it again only if it got modified */ ++ if (apn->remote_connection && !apn->modified) ++ { ++ g_task_return_pointer (task, apn, NULL); ++ return; ++ } ++ ++ wwan_data_update_apn (self, apn, connection); ++ if (wwan_data_apn_is_new (apn)) ++ { ++ nm_client_add_connection_async (self->nm_client, apn->nm_connection, ++ TRUE, cancellable, ++ cc_wwan_data_new_connection_added_cb, ++ g_steal_pointer (&task)); ++ } ++ else ++ { ++ nm_remote_connection_commit_changes_async (apn->remote_connection, TRUE, ++ cancellable, ++ cc_wwan_data_connection_updated_cb, ++ g_steal_pointer (&task)); ++ } ++} ++ ++CcWwanDataApn * ++cc_wwan_data_save_apn_finish (CcWwanData *self, ++ GAsyncResult *result, ++ GError **error) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DATA (self), NULL); ++ g_return_val_if_fail (G_IS_TASK (result), NULL); ++ ++ return g_task_propagate_pointer (G_TASK (result), error); ++} ++ ++static void ++cc_wwan_data_activated_cb (GObject *object, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ CcWwanData *self; ++ NMActiveConnection *connection; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; ++ ++ self = g_task_get_source_object (G_TASK (task)); ++ connection = nm_client_activate_connection_finish (self->nm_client, ++ result, &error); ++ if (connection) ++ { ++ g_set_object (&self->active_connection, connection); ++ g_task_return_boolean (task, TRUE); ++ } ++ else ++ { ++ g_task_return_error (task, g_steal_pointer (&error)); ++ } ++ ++ if (error) ++ g_warning ("Error: %s", error->message); ++} ++ ++static void ++cc_wwan_data_settings_saved_cb (GObject *object, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ CcWwanData *self; ++ GCancellable *cancellable; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; ++ ++ self = g_task_get_source_object (G_TASK (task)); ++ cancellable = g_task_get_cancellable (G_TASK (task)); ++ ++ if (!cc_wwan_data_save_apn_finish (self, result, &error)) ++ { ++ g_task_return_error (task, g_steal_pointer (&error)); ++ return; ++ } ++ ++ self->default_apn->modified = FALSE; ++ ++ if (self->data_enabled) ++ { ++ nm_client_activate_connection_async (self->nm_client, ++ NM_CONNECTION (self->default_apn->remote_connection), ++ self->nm_device, ++ NULL, cancellable, ++ cc_wwan_data_activated_cb, ++ g_steal_pointer (&task)); ++ } ++ else ++ { ++ if (nm_device_disconnect (self->nm_device, cancellable, &error)) ++ { ++ g_clear_object (&self->active_connection); ++ g_task_return_boolean (task, TRUE); ++ } ++ else ++ { ++ g_task_return_error (task, g_steal_pointer (&error)); ++ } ++ } ++} ++ ++/** ++ * cc_wwan_data_save_settings: ++ * @cancellable: (nullable): a #GCancellable or %NULL ++ * @callback: a #GAsyncReadyCallback, or %NULL ++ * @user_data: closure data for @callback ++ * ++ * Save default settings to disk and apply changes. ++ * If the default APN has data enabled, the data is ++ * activated after the settings are saved. ++ * ++ * It’s a programmer error to call this function without ++ * a default APN set. ++ * Finish with cc_wwan_data_save_settings_finish(). ++ */ ++void ++cc_wwan_data_save_settings (CcWwanData *self, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data) ++{ ++ NMConnection *connection; ++ NMSetting *setting; ++ g_autoptr(GTask) task = NULL; ++ ++ g_return_if_fail (CC_IS_WWAN_DATA (self)); ++ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); ++ g_return_if_fail (self->default_apn != NULL); ++ ++ task = g_task_new (self, cancellable, callback, user_data); ++ ++ /* Reset old settings to default value */ ++ if (self->old_default_apn && self->old_default_apn->remote_connection) ++ { ++ connection = NM_CONNECTION (self->old_default_apn->remote_connection); ++ ++ setting = NM_SETTING (nm_connection_get_setting_gsm (connection)); ++ g_object_set (G_OBJECT (setting), ++ NM_SETTING_GSM_HOME_ONLY, TRUE, ++ NM_SETTING_GSM_SIM_ID, NULL, ++ NULL); ++ ++ setting = NM_SETTING (nm_connection_get_setting_ip4_config (connection)); ++ g_object_set (setting, ++ NM_SETTING_IP_CONFIG_DNS_PRIORITY, CC_WWAN_DNS_PRIORITY_LOW, ++ NM_SETTING_IP_CONFIG_ROUTE_METRIC, (gint64)CC_WWAN_ROUTE_PRIORITY_LOW, ++ NULL); ++ ++ setting = NM_SETTING (nm_connection_get_setting_connection (connection)); ++ g_object_set (G_OBJECT (setting), ++ NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, ++ NULL); ++ ++ nm_remote_connection_commit_changes (NM_REMOTE_CONNECTION (connection), ++ TRUE, cancellable, NULL); ++ self->old_default_apn->modified = FALSE; ++ self->old_default_apn = NULL; ++ } ++ ++ self->default_apn->modified = TRUE; ++ connection = wwan_data_get_nm_connection (self->default_apn); ++ ++ setting = NM_SETTING (nm_connection_get_setting_gsm (connection)); ++ g_object_set (G_OBJECT (setting), ++ NM_SETTING_GSM_HOME_ONLY, self->home_only, ++ NM_SETTING_GSM_SIM_ID, self->sim_id, ++ NULL); ++ ++ cc_wwan_data_save_apn (self, self->default_apn, cancellable, ++ cc_wwan_data_settings_saved_cb, ++ g_steal_pointer (&task)); ++} ++ ++gboolean ++cc_wwan_data_save_settings_finish (CcWwanData *self, ++ GAsyncResult *result, ++ GError **error) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DATA (self), FALSE); ++ g_return_val_if_fail (G_IS_TASK (result), FALSE); ++ ++ return g_task_propagate_boolean (G_TASK (result), error); ++} ++ ++gboolean ++cc_wwan_data_delete_apn (CcWwanData *self, ++ CcWwanDataApn *apn, ++ GCancellable *cancellable, ++ GError **error) ++{ ++ NMRemoteConnection *connection = NULL; ++ gboolean ret = FALSE; ++ gint apn_index; ++ ++ g_return_val_if_fail (CC_IS_WWAN_DATA (self), FALSE); ++ g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE); ++ g_return_val_if_fail (CC_IS_WWAN_DATA_APN (apn), FALSE); ++ g_return_val_if_fail (error != NULL, FALSE); ++ ++ apn_index = wwan_data_get_apn_index (self, apn); ++ if (apn_index == -1) ++ { ++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, ++ "APN not found for the connection"); ++ return FALSE; ++ } ++ ++ connection = g_steal_pointer (&apn->remote_connection); ++ wwan_data_apn_reset (apn); ++ ++ if (connection) ++ ret = nm_remote_connection_delete (connection, cancellable, error); ++ ++ if (!ret) ++ { ++ apn->remote_connection = connection; ++ *error = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, ++ "Deleting APN from NetworkManager failed"); ++ return ret; ++ } ++ ++ g_object_unref (connection); ++ ++ /* We remove the item only if it's not in the mobile provider database */ ++ if (!apn->access_method) ++ { ++ if (self->default_apn == apn) ++ self->default_apn = NULL; ++ ++ g_list_store_remove (self->apn_list, apn_index); ++ ++ return TRUE; ++ } ++ ++ *error = g_error_new (G_IO_ERROR, G_IO_ERROR_READ_ONLY, ++ "Deleting APN from NetworkManager failed"); ++ return FALSE; ++} ++ ++CcWwanDataApn * ++cc_wwan_data_get_default_apn (CcWwanData *self) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DATA (self), NULL); ++ ++ return self->default_apn; ++} ++ ++gboolean ++cc_wwan_data_set_default_apn (CcWwanData *self, ++ CcWwanDataApn *apn) ++{ ++ NMConnection *connection; ++ NMSetting *setting; ++ ++ g_return_val_if_fail (CC_IS_WWAN_DATA (self), FALSE); ++ g_return_val_if_fail (CC_IS_WWAN_DATA_APN (apn), FALSE); ++ g_return_val_if_fail (self->sim_id != NULL, FALSE); ++ ++ if (self->default_apn == apn) ++ return FALSE; ++ ++ /* ++ * APNs are bound to the SIM, not the modem device. ++ * This will let the APN work if the same SIM inserted ++ * in a different device, and not enable data if a ++ * different SIM is inserted to the modem. ++ */ ++ apn->modified = TRUE; ++ self->old_default_apn = self->default_apn; ++ self->default_apn = apn; ++ connection = wwan_data_get_nm_connection (apn); ++ setting = NM_SETTING (nm_connection_get_setting_gsm (connection)); ++ g_object_set (G_OBJECT (setting), ++ NM_SETTING_GSM_SIM_ID, self->sim_id, NULL); ++ ++ return TRUE; ++} ++ ++gboolean ++cc_wwan_data_get_enabled (CcWwanData *self) ++{ ++ NMSettingConnection *setting; ++ NMConnection *connection; ++ NMDeviceState state; ++ ++ g_return_val_if_fail (CC_IS_WWAN_DATA (self), FALSE); ++ ++ state = nm_device_get_state (self->nm_device); ++ ++ if (state == NM_DEVICE_STATE_DISCONNECTED || ++ state == NM_DEVICE_STATE_DEACTIVATING) ++ if (nm_device_get_state_reason (self->nm_device) == NM_DEVICE_STATE_REASON_USER_REQUESTED) ++ return FALSE; ++ ++ if (nm_device_get_active_connection (self->nm_device) != NULL) ++ return TRUE; ++ ++ if (!self->default_apn || !self->default_apn->remote_connection) ++ return FALSE; ++ ++ connection = NM_CONNECTION (self->default_apn->remote_connection); ++ setting = nm_connection_get_setting_connection (connection); ++ ++ return nm_setting_connection_get_autoconnect (setting); ++} ++ ++/** ++ * cc_wwan_data_set_enabled: ++ * @self: A #CcWwanData ++ * @enable_data: whether to enable data ++ * ++ * Enable data for the device. The settings is ++ * saved to disk only after a default APN is set. ++ * ++ * If the data is enabled, the device will automatically ++ * turn data on everytime the same SIM is available. ++ * The data set is bound to the SIM, not the modem device. ++ * ++ * Use @cc_wwan_data_save_apn() with the default APN ++ * to save the changes and really enable/disable data. ++ */ ++void ++cc_wwan_data_set_enabled (CcWwanData *self, ++ gboolean enable_data) ++{ ++ g_return_if_fail (CC_IS_WWAN_DATA (self)); ++ ++ self->data_enabled = !!enable_data; ++ ++ if (self->default_apn) ++ self->default_apn->modified = TRUE; ++} ++ ++gboolean ++cc_wwan_data_get_roaming_enabled (CcWwanData *self) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DATA (self), FALSE); ++ ++ if (!self->default_apn) ++ return FALSE; ++ ++ return !self->home_only; ++} ++ ++/** ++ * cc_wwan_data_apn_set_roaming_enabled: ++ * @self: A #CcWwanData ++ * @enable_roaming: whether to enable roaming or not ++ * ++ * Enable roaming for the device. The settings is ++ * saved to disk only after a default APN is set. ++ * ++ * Use @cc_wwan_data_save_apn() with the default APN ++ * to save the changes and really enable/disable data. ++ */ ++void ++cc_wwan_data_set_roaming_enabled (CcWwanData *self, ++ gboolean enable_roaming) ++{ ++ g_return_if_fail (CC_IS_WWAN_DATA (self)); ++ ++ self->home_only = !enable_roaming; ++ ++ if (self->default_apn) ++ self->default_apn->modified = TRUE; ++} ++ ++static void ++cc_wwan_data_apn_finalize (GObject *object) ++{ ++ CcWwanDataApn *apn = CC_WWAN_DATA_APN (object); ++ ++ wwan_data_apn_reset (apn); ++ g_clear_pointer (&apn->access_method, ++ nma_mobile_access_method_unref); ++ ++ G_OBJECT_CLASS (cc_wwan_data_parent_class)->finalize (object); ++} ++ ++static void ++cc_wwan_data_apn_class_init (CcWwanDataApnClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->finalize = cc_wwan_data_apn_finalize; ++} ++ ++static void ++cc_wwan_data_apn_init (CcWwanDataApn *apn) ++{ ++} ++ ++CcWwanDataApn * ++cc_wwan_data_apn_new (void) ++{ ++ return g_object_new (CC_TYPE_WWAN_DATA_APN, NULL); ++} ++ ++/** ++ * cc_wwan_data_apn_get_name: ++ * @apn: A #CcWwanDataApn ++ * ++ * Get the Name of @apn ++ * ++ * Returns: (transfer none): The Name of @apn ++ */ ++const gchar * ++cc_wwan_data_apn_get_name (CcWwanDataApn *apn) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DATA_APN (apn), ""); ++ ++ if (apn->remote_connection) ++ return nm_connection_get_id (NM_CONNECTION (apn->remote_connection)); ++ ++ if (apn->access_method) ++ return nma_mobile_access_method_get_name (apn->access_method); ++ ++ return ""; ++} ++ ++/** ++ * cc_wwan_data_apn_set_name: ++ * @apn: A #CcWwanDataApn ++ * @name: The name to be given for APN, should not ++ * be empty ++ * ++ * Set the name of @apn to be @name. ++ * ++ * @apn is only modified, use @cc_wwan_data_save_apn() ++ * to save the changes. ++ */ ++void ++cc_wwan_data_apn_set_name (CcWwanDataApn *apn, ++ const gchar *name) ++{ ++ NMConnection *connection; ++ NMSettingConnection *setting; ++ ++ g_return_if_fail (CC_IS_WWAN_DATA_APN (apn)); ++ g_return_if_fail (name != NULL); ++ g_return_if_fail (*name != '\0'); ++ ++ if (g_str_equal (cc_wwan_data_apn_get_name (apn), name)) ++ return; ++ ++ apn->modified = TRUE; ++ connection = wwan_data_get_nm_connection (apn); ++ setting = nm_connection_get_setting_connection (connection); ++ g_object_set (G_OBJECT (setting), ++ NM_SETTING_CONNECTION_ID, name, ++ NULL); ++} ++ ++/** ++ * cc_wwan_data_apn_get_apn: ++ * @apn: A #CcWwanDataApn ++ * ++ * Get the APN of @apn ++ * ++ * Returns: (transfer none): The APN of @apn ++ */ ++const gchar * ++cc_wwan_data_apn_get_apn (CcWwanDataApn *apn) ++{ ++ const gchar *apn_name = ""; ++ ++ g_return_val_if_fail (CC_IS_WWAN_DATA_APN (apn), ""); ++ ++ if (apn->remote_connection) ++ { ++ NMSettingGsm *setting; ++ ++ setting = nm_connection_get_setting_gsm (NM_CONNECTION (apn->remote_connection)); ++ apn_name = nm_setting_gsm_get_apn (setting); ++ } ++ else if (apn->access_method) ++ { ++ apn_name = nma_mobile_access_method_get_3gpp_apn (apn->access_method); ++ } ++ ++ return apn_name ? apn_name : ""; ++} ++ ++/** ++ * cc_wwan_data_apn_set_apn: ++ * @apn: A #CcWwanDataApn ++ * @apn_name: The apn to be used, should not be ++ * empty ++ * ++ * Set the APN of @apn to @apn_name. @apn_name is ++ * usually a URL like “example.com” or a simple string ++ * like “internet” ++ * ++ * @apn is only modified, use @cc_wwan_data_save_apn() ++ * to save the changes. ++ */ ++void ++cc_wwan_data_apn_set_apn (CcWwanDataApn *apn, ++ const gchar *apn_name) ++{ ++ NMConnection *connection; ++ NMSettingGsm *setting; ++ ++ g_return_if_fail (CC_IS_WWAN_DATA_APN (apn)); ++ g_return_if_fail (apn_name != NULL); ++ g_return_if_fail (*apn_name != '\0'); ++ ++ if (g_str_equal (cc_wwan_data_apn_get_apn (apn), apn_name)) ++ return; ++ ++ apn->modified = TRUE; ++ connection = wwan_data_get_nm_connection (apn); ++ setting = nm_connection_get_setting_gsm (connection); ++ g_object_set (G_OBJECT (setting), ++ NM_SETTING_GSM_APN, apn_name, ++ NULL); ++} ++ ++/** ++ * cc_wwan_data_apn_get_username: ++ * @apn: A #CcWwanDataApn ++ * ++ * Get the Username of @apn ++ * ++ * Returns: (transfer none): The Username of @apn ++ */ ++const gchar * ++cc_wwan_data_apn_get_username (CcWwanDataApn *apn) ++{ ++ const gchar *username = ""; ++ ++ g_return_val_if_fail (CC_IS_WWAN_DATA_APN (apn), ""); ++ ++ if (apn->remote_connection) ++ { ++ NMSettingGsm *setting; ++ ++ setting = nm_connection_get_setting_gsm (NM_CONNECTION (apn->remote_connection)); ++ username = nm_setting_gsm_get_username (setting); ++ } ++ else if (apn->access_method) ++ { ++ username = nma_mobile_access_method_get_username (apn->access_method); ++ } ++ ++ return username ? username : ""; ++} ++ ++/** ++ * cc_wwan_data_apn_set_username: ++ * @apn: A #CcWwanDataAPN ++ * @username: The username to be used ++ * ++ * Set the Username of @apn to @username. ++ * ++ * @apn is only modified, use @cc_wwan_data_save_apn() ++ * to save the changes. ++ */ ++void ++cc_wwan_data_apn_set_username (CcWwanDataApn *apn, ++ const gchar *username) ++{ ++ NMConnection *connection; ++ NMSettingGsm *setting; ++ ++ g_return_if_fail (CC_IS_WWAN_DATA_APN (apn)); ++ ++ if (username && !*username) ++ username = NULL; ++ ++ if (g_strcmp0 (cc_wwan_data_apn_get_username (apn), username) == 0) ++ return; ++ ++ apn->modified = TRUE; ++ connection = wwan_data_get_nm_connection (apn); ++ setting = nm_connection_get_setting_gsm (connection); ++ g_object_set (G_OBJECT (setting), ++ NM_SETTING_GSM_USERNAME, username, ++ NULL); ++} ++ ++/** ++ * cc_wwan_data_apn_get_password: ++ * @apn: A #CcWwanDataApn ++ * ++ * Get the Password of @apn ++ * ++ * Returns: (transfer none): The Password of @apn ++ */ ++const gchar * ++cc_wwan_data_apn_get_password (CcWwanDataApn *apn) ++{ ++ const gchar *password = ""; ++ ++ g_return_val_if_fail (CC_IS_WWAN_DATA_APN (apn), ""); ++ ++ if (NM_IS_REMOTE_CONNECTION (apn->remote_connection)) ++ { ++ g_autoptr(GVariant) secrets = NULL; ++ g_autoptr(GError) error = NULL; ++ ++ secrets = nm_remote_connection_get_secrets (NM_REMOTE_CONNECTION (apn->remote_connection), ++ "gsm", NULL, &error); ++ ++ if (!error) ++ nm_connection_update_secrets (NM_CONNECTION (apn->remote_connection), ++ "gsm", secrets, &error); ++ ++ if (error) ++ { ++ g_warning ("Error: %s", error->message); ++ return ""; ++ } ++ } ++ ++ if (apn->remote_connection) ++ { ++ NMSettingGsm *setting; ++ ++ setting = nm_connection_get_setting_gsm (NM_CONNECTION (apn->remote_connection)); ++ password = nm_setting_gsm_get_password (setting); ++ } ++ else if (apn->access_method) ++ { ++ password = nma_mobile_access_method_get_password (apn->access_method); ++ } ++ ++ return password ? password : ""; ++ ++ if (apn->remote_connection) ++ nm_connection_clear_secrets (NM_CONNECTION (apn->remote_connection)); ++} ++ ++/** ++ * cc_wwan_data_apn_set_password: ++ * @apn: A #CcWwanDataApn ++ * @password: The password to be used ++ * ++ * Set the Password of @apn to @password. ++ * ++ * @apn is only modified, use @cc_wwan_data_save_apn() ++ * to save the changes. ++ */ ++void ++cc_wwan_data_apn_set_password (CcWwanDataApn *apn, ++ const gchar *password) ++{ ++ NMConnection *connection; ++ NMSettingGsm *setting; ++ ++ g_return_if_fail (CC_IS_WWAN_DATA_APN (apn)); ++ ++ if (password && !*password) ++ password = NULL; ++ ++ if (g_strcmp0 (cc_wwan_data_apn_get_password (apn), password) == 0) ++ return; ++ ++ apn->modified = TRUE; ++ connection = wwan_data_get_nm_connection (apn); ++ setting = nm_connection_get_setting_gsm (connection); ++ g_object_set (G_OBJECT (setting), ++ NM_SETTING_GSM_PASSWORD, password, ++ NULL); ++} ++ ++gint ++cc_wwan_data_get_priority (CcWwanData *self) ++{ ++ CcWwanDataApn *apn; ++ NMSettingIPConfig *setting; ++ ++ g_return_val_if_fail (CC_IS_WWAN_DATA (self), ++ CC_WWAN_APN_PRIORITY_LOW); ++ ++ apn = self->default_apn; ++ ++ if (!apn || !apn->remote_connection) ++ return CC_WWAN_APN_PRIORITY_LOW; ++ ++ setting = nm_connection_get_setting_ip4_config (NM_CONNECTION (apn->remote_connection)); ++ ++ /* Lower the number, higher the priority */ ++ if (nm_setting_ip_config_get_route_metric (setting) <= CC_WWAN_ROUTE_PRIORITY_HIGH) ++ return CC_WWAN_APN_PRIORITY_HIGH; ++ else ++ return CC_WWAN_APN_PRIORITY_LOW; ++} ++ ++void ++cc_wwan_data_set_priority (CcWwanData *self, ++ int priority) ++{ ++ g_return_if_fail (CC_IS_WWAN_DATA (self)); ++ g_return_if_fail (priority == CC_WWAN_APN_PRIORITY_LOW || ++ priority == CC_WWAN_APN_PRIORITY_HIGH); ++ ++ if (self->priority == priority) ++ return; ++ ++ self->priority = priority; ++ ++ if (self->default_apn) ++ self->default_apn->modified = TRUE; ++} +diff --git a/panels/wwan/cc-wwan-data.h b/panels/wwan/cc-wwan-data.h +new file mode 100644 +index 000000000..9572b862d +--- /dev/null ++++ b/panels/wwan/cc-wwan-data.h +@@ -0,0 +1,93 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-data.h ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#pragma once ++ ++#include ++#include ++#include ++ ++G_BEGIN_DECLS ++ ++#define CC_WWAN_APN_PRIORITY_LOW (1) ++#define CC_WWAN_APN_PRIORITY_HIGH (2) ++ ++#define CC_TYPE_WWAN_DATA_APN (cc_wwan_data_apn_get_type()) ++G_DECLARE_FINAL_TYPE (CcWwanDataApn, cc_wwan_data_apn, CC, WWAN_DATA_APN, GObject) ++ ++#define CC_TYPE_WWAN_DATA (cc_wwan_data_get_type()) ++G_DECLARE_FINAL_TYPE (CcWwanData, cc_wwan_data, CC, WWAN_DATA, GObject) ++ ++CcWwanData *cc_wwan_data_new (MMObject *mm_object, ++ NMClient *nm_client); ++GError *cc_wwan_data_get_error (CcWwanData *self); ++const gchar *cc_wwan_data_get_simple_html_error (CcWwanData *self); ++GListModel *cc_wwan_data_get_apn_list (CcWwanData *self); ++void cc_wwan_data_save_apn (CcWwanData *self, ++ CcWwanDataApn *apn, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data); ++CcWwanDataApn *cc_wwan_data_save_apn_finish (CcWwanData *self, ++ GAsyncResult *result, ++ GError **error); ++void cc_wwan_data_save_settings (CcWwanData *self, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data); ++gboolean cc_wwan_data_save_settings_finish (CcWwanData *self, ++ GAsyncResult *result, ++ GError **error); ++gboolean cc_wwan_data_delete_apn (CcWwanData *self, ++ CcWwanDataApn *apn, ++ GCancellable *cancellable, ++ GError **error); ++gboolean cc_wwan_data_set_default_apn (CcWwanData *self, ++ CcWwanDataApn *apn); ++CcWwanDataApn *cc_wwan_data_get_default_apn (CcWwanData *self); ++gboolean cc_wwan_data_get_enabled (CcWwanData *self); ++void cc_wwan_data_set_enabled (CcWwanData *self, ++ gboolean enabled); ++gboolean cc_wwan_data_get_roaming_enabled (CcWwanData *self); ++void cc_wwan_data_set_roaming_enabled (CcWwanData *self, ++ gboolean enable_roaming); ++ ++CcWwanDataApn *cc_wwan_data_apn_new (void); ++const gchar *cc_wwan_data_apn_get_name (CcWwanDataApn *apn); ++void cc_wwan_data_apn_set_name (CcWwanDataApn *apn, ++ const gchar *name); ++const gchar *cc_wwan_data_apn_get_apn (CcWwanDataApn *apn); ++void cc_wwan_data_apn_set_apn (CcWwanDataApn *apn, ++ const gchar *apn_name); ++const gchar *cc_wwan_data_apn_get_username (CcWwanDataApn *apn); ++void cc_wwan_data_apn_set_username (CcWwanDataApn *apn, ++ const gchar *username); ++const gchar *cc_wwan_data_apn_get_password (CcWwanDataApn *apn); ++void cc_wwan_data_apn_set_password (CcWwanDataApn *apn, ++ const gchar *password); ++gint cc_wwan_data_get_priority (CcWwanData *self); ++void cc_wwan_data_set_priority (CcWwanData *self, ++ int priority); ++ ++G_END_DECLS +diff --git a/panels/wwan/cc-wwan-details-dialog.c b/panels/wwan/cc-wwan-details-dialog.c +new file mode 100644 +index 000000000..59e8dc361 +--- /dev/null ++++ b/panels/wwan/cc-wwan-details-dialog.c +@@ -0,0 +1,257 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-network-dialog.c ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#undef G_LOG_DOMAIN ++#define G_LOG_DOMAIN "cc-wwan-details-dialog" ++ ++#include ++#include ++#include ++ ++#include "list-box-helper.h" ++#include "cc-wwan-details-dialog.h" ++#include "cc-wwan-resources.h" ++ ++/** ++ * @short_description: Dialog to Show Device Details ++ */ ++ ++struct _CcWwanDetailsDialog ++{ ++ GtkDialog parent_instance; ++ ++ GtkLabel *device_identifier; ++ GtkLabel *device_model; ++ GtkLabel *firmware_version; ++ GtkLabel *identifier_label; ++ GtkLabel *manufacturer; ++ GtkLabel *network_status; ++ GtkLabel *network_type; ++ GtkLabel *operator_name; ++ GtkLabel *own_numbers; ++ GtkLabel *signal_strength; ++ ++ CcWwanDevice *device; ++}; ++ ++G_DEFINE_TYPE (CcWwanDetailsDialog, cc_wwan_details_dialog, GTK_TYPE_DIALOG) ++ ++ ++enum { ++ PROP_0, ++ PROP_DEVICE, ++ N_PROPS ++}; ++ ++static GParamSpec *properties[N_PROPS]; ++ ++static void ++cc_wwan_details_update_network_status (CcWwanDetailsDialog *self) ++{ ++ CcWwanState state; ++ ++ g_assert (CC_IS_WWAN_DETAILS_DIALOG (self)); ++ ++ state = cc_wwan_device_get_network_state (self->device); ++ ++ switch (state) ++ { ++ case CC_WWAN_REGISTRATION_STATE_IDLE: ++ gtk_label_set_label (self->network_status, _("Not Registered")); ++ break; ++ ++ case CC_WWAN_REGISTRATION_STATE_REGISTERED: ++ gtk_label_set_label (self->network_status, _("Registered")); ++ break; ++ ++ case CC_WWAN_REGISTRATION_STATE_ROAMING: ++ gtk_label_set_label (self->network_status, _("Roaming")); ++ break; ++ ++ case CC_WWAN_REGISTRATION_STATE_SEARCHING: ++ gtk_label_set_label (self->network_status, _("Searching")); ++ break; ++ ++ case CC_WWAN_REGISTRATION_STATE_DENIED: ++ gtk_label_set_label (self->network_status, _("Denied")); ++ break; ++ ++ default: ++ gtk_label_set_label (self->network_status, _("Unknown")); ++ break; ++ } ++} ++ ++static void ++cc_wwan_details_signal_changed_cb (CcWwanDetailsDialog *self) ++{ ++ g_autofree gchar *network_type_string = NULL; ++ g_autofree gchar *signal_string = NULL; ++ const gchar *operator_name; ++ ++ g_assert (CC_IS_WWAN_DETAILS_DIALOG (self)); ++ ++ operator_name = cc_wwan_device_get_operator_name (self->device); ++ if (operator_name) ++ gtk_label_set_label (self->operator_name, operator_name); ++ ++ network_type_string = cc_wwan_device_dup_network_type_string (self->device); ++ if (network_type_string) ++ gtk_label_set_label (self->network_type, network_type_string); ++ ++ signal_string = cc_wwan_device_dup_signal_string (self->device); ++ if (signal_string) ++ gtk_label_set_label (self->signal_strength, signal_string); ++ ++ cc_wwan_details_update_network_status (self); ++} ++ ++static void ++cc_wwan_details_update_hardware_details (CcWwanDetailsDialog *self) ++{ ++ const gchar *str; ++ ++ g_assert (CC_IS_WWAN_DETAILS_DIALOG (self)); ++ ++ str = cc_wwan_device_get_manufacturer (self->device); ++ if (str) ++ gtk_label_set_label (self->manufacturer, str); ++ ++ str = cc_wwan_device_get_model (self->device); ++ if (str) ++ gtk_label_set_label (self->device_model, str); ++ ++ str = cc_wwan_device_get_firmware_version (self->device); ++ if (str) ++ gtk_label_set_label (self->firmware_version, str); ++ ++ str = cc_wwan_device_get_identifier (self->device); ++ if (str) ++ gtk_label_set_label (self->device_identifier, str); ++} ++ ++static void ++cc_wwan_details_dialog_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ CcWwanDetailsDialog *self = CC_WWAN_DETAILS_DIALOG (object); ++ ++ switch (prop_id) ++ { ++ case PROP_DEVICE: ++ self->device = g_value_dup_object (value); ++ break; ++ ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } ++} ++ ++static void ++cc_wwan_details_dialog_constructed (GObject *object) ++{ ++ CcWwanDetailsDialog *self = CC_WWAN_DETAILS_DIALOG (object); ++ g_autofree char *numbers = NULL; ++ ++ G_OBJECT_CLASS (cc_wwan_details_dialog_parent_class)->constructed (object); ++ ++ g_signal_connect_object (self->device, "notify::signal", ++ G_CALLBACK (cc_wwan_details_signal_changed_cb), ++ self, G_CONNECT_SWAPPED); ++ ++ numbers = cc_wwan_device_dup_own_numbers (self->device); ++ gtk_widget_set_visible (GTK_WIDGET (self->own_numbers), !!numbers); ++ ++ if (numbers) ++ gtk_label_set_text (self->own_numbers, numbers); ++ ++ cc_wwan_details_signal_changed_cb (self); ++ cc_wwan_details_update_hardware_details (self); ++} ++ ++static void ++cc_wwan_details_dialog_dispose (GObject *object) ++{ ++ CcWwanDetailsDialog *self = CC_WWAN_DETAILS_DIALOG (object); ++ ++ g_clear_object (&self->device); ++ ++ G_OBJECT_CLASS (cc_wwan_details_dialog_parent_class)->dispose (object); ++} ++ ++static void ++cc_wwan_details_dialog_class_init (CcWwanDetailsDialogClass *klass) ++{ ++ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->set_property = cc_wwan_details_dialog_set_property; ++ object_class->constructed = cc_wwan_details_dialog_constructed; ++ object_class->dispose = cc_wwan_details_dialog_dispose; ++ ++ properties[PROP_DEVICE] = ++ g_param_spec_object ("device", ++ "Device", ++ "The WWAN Device", ++ CC_TYPE_WWAN_DEVICE, ++ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); ++ ++ g_object_class_install_properties (object_class, N_PROPS, properties); ++ ++ gtk_widget_class_set_template_from_resource (widget_class, ++ "/org/gnome/control-center/wwan/cc-wwan-details-dialog.ui"); ++ ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, device_identifier); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, device_model); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, firmware_version); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, identifier_label); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, manufacturer); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, network_status); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, network_type); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, operator_name); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, own_numbers); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDetailsDialog, signal_strength); ++} ++ ++static void ++cc_wwan_details_dialog_init (CcWwanDetailsDialog *self) ++{ ++ gtk_widget_init_template (GTK_WIDGET (self)); ++} ++ ++CcWwanDetailsDialog * ++cc_wwan_details_dialog_new (GtkWindow *parent_window, ++ CcWwanDevice *device) ++{ ++ g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL); ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (device), NULL); ++ ++ return g_object_new (CC_TYPE_WWAN_DETAILS_DIALOG, ++ "transient-for", parent_window, ++ "use-header-bar", 1, ++ "device", device, ++ NULL); ++} +diff --git a/panels/wwan/cc-wwan-details-dialog.h b/panels/wwan/cc-wwan-details-dialog.h +new file mode 100644 +index 000000000..7e7812cde +--- /dev/null ++++ b/panels/wwan/cc-wwan-details-dialog.h +@@ -0,0 +1,40 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-details-dialog.h ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#pragma once ++ ++#include ++#include ++ ++#include "cc-wwan-device.h" ++ ++G_BEGIN_DECLS ++ ++#define CC_TYPE_WWAN_DETAILS_DIALOG (cc_wwan_details_dialog_get_type()) ++G_DECLARE_FINAL_TYPE (CcWwanDetailsDialog, cc_wwan_details_dialog, CC, WWAN_DETAILS_DIALOG, GtkDialog) ++ ++CcWwanDetailsDialog *cc_wwan_details_dialog_new (GtkWindow *parent_window, ++ CcWwanDevice *device); ++ ++G_END_DECLS +diff --git a/panels/wwan/cc-wwan-details-dialog.ui b/panels/wwan/cc-wwan-details-dialog.ui +new file mode 100644 +index 000000000..042d3ee33 +--- /dev/null ++++ b/panels/wwan/cc-wwan-details-dialog.ui +@@ -0,0 +1,320 @@ ++ ++ ++ ++ +diff --git a/panels/wwan/cc-wwan-device-page.c b/panels/wwan/cc-wwan-device-page.c +new file mode 100644 +index 000000000..0a04d3379 +--- /dev/null ++++ b/panels/wwan/cc-wwan-device-page.c +@@ -0,0 +1,634 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-device-page.c ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#undef G_LOG_DOMAIN ++#define G_LOG_DOMAIN "cc-wwan-device-page" ++ ++#include ++#include ++#include ++#define GCR_API_SUBJECT_TO_CHANGE ++#include ++ ++#include "list-box-helper.h" ++#include "cc-list-row.h" ++#include "cc-wwan-data.h" ++#include "cc-wwan-mode-dialog.h" ++#include "cc-wwan-network-dialog.h" ++#include "cc-wwan-details-dialog.h" ++#include "cc-wwan-sim-lock-dialog.h" ++#include "cc-wwan-apn-dialog.h" ++#include "cc-wwan-device-page.h" ++#include "cc-wwan-resources.h" ++ ++#include "shell/cc-application.h" ++#include "shell/cc-debug.h" ++#include "shell/cc-object-storage.h" ++ ++/** ++ * @short_description: Device settings page ++ * @include: "cc-wwan-device-page.h" ++ * ++ * The Device page allows users to configure device ++ * settings. Please note that there is no one-to-one ++ * maping for a device settings page and a physical ++ * device. Say, if a device have two SIM card slots, ++ * there should be two device pages, one for each SIM. ++ */ ++ ++struct _CcWwanDevicePage ++{ ++ GtkBox parent_instance; ++ ++ GtkListBox *advanced_settings_list; ++ CcListRow *apn_settings_row; ++ CcListRow *data_enable_row; ++ CcListRow *data_roaming_row; ++ GtkListBox *data_settings_list; ++ CcListRow *details_row; ++ GtkStack *main_stack; ++ CcListRow *network_mode_row; ++ CcListRow *network_name_row; ++ GtkListBox *network_settings_list; ++ CcListRow *sim_lock_row; ++ GtkButton *unlock_button; ++ ++ GtkLabel *notification_label; ++ ++ CcWwanDevice *device; ++ CcWwanData *wwan_data; ++ GDBusProxy *wwan_proxy; ++ ++ CcWwanApnDialog *apn_dialog; ++ CcWwanDetailsDialog *details_dialog; ++ CcWwanModeDialog *network_mode_dialog; ++ CcWwanNetworkDialog *network_dialog; ++ CcWwanSimLockDialog *sim_lock_dialog; ++ ++ gint sim_index; ++ /* Set if a change is triggered in a signal’s callback, ++ * to avoid re-triggering of callback. This is used ++ * instead of blocking handlers where the signal may be ++ * emitted async and the block/unblock may not work right ++ */ ++ gboolean is_self_change; ++ gboolean is_retry; ++}; ++ ++G_DEFINE_TYPE (CcWwanDevicePage, cc_wwan_device_page, GTK_TYPE_BOX) ++ ++enum { ++ PROP_0, ++ PROP_DEVICE, ++ N_PROPS ++}; ++ ++static GParamSpec *properties[N_PROPS]; ++ ++static void ++wwan_data_show_apn_dialog (CcWwanDevicePage *self) ++{ ++ GtkWindow *top_level; ++ ++ top_level = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))); ++ ++ if (!self->apn_dialog) ++ self->apn_dialog = cc_wwan_apn_dialog_new (top_level, self->device); ++ ++ gtk_widget_show (GTK_WIDGET (self->apn_dialog)); ++} ++ ++static GcrPrompt * ++cc_wwan_device_page_new_prompt (CcWwanDevicePage *self, ++ MMModemLock lock) ++{ ++ GcrPrompt *prompt; ++ g_autoptr(GError) error = NULL; ++ g_autofree gchar *description = NULL; ++ g_autofree gchar *warning = NULL; ++ const gchar *message = NULL; ++ guint num; ++ ++ prompt = GCR_PROMPT (gcr_system_prompt_open (-1, NULL, &error)); ++ ++ if (error) ++ { ++ g_warning ("Error opening Prompt: %s", error->message); ++ return NULL; ++ } ++ ++ gcr_prompt_set_title (prompt, _("Unlock SIM card")); ++ gcr_prompt_set_continue_label (prompt, _("Unlock")); ++ gcr_prompt_set_cancel_label (prompt, _("Cancel")); ++ ++ if (lock == MM_MODEM_LOCK_SIM_PIN) ++ { ++ description = g_strdup_printf (_("Please provide PIN code for SIM %d"), self->sim_index); ++ message = _("Enter PIN to unlock your SIM card"); ++ } ++ else if (lock == MM_MODEM_LOCK_SIM_PUK) ++ { ++ description = g_strdup_printf (_("Please provide PUK code for SIM %d"), self->sim_index); ++ message = _("Enter PUK to unlock your SIM card"); ++ } ++ else ++ { ++ g_warn_if_reached (); ++ g_object_unref (prompt); ++ ++ return NULL; ++ } ++ ++ gcr_prompt_set_description (prompt, description); ++ gcr_prompt_set_message (prompt, message); ++ ++ num = cc_wwan_device_get_unlock_retries (self->device, lock); ++ ++ if (num != MM_UNLOCK_RETRIES_UNKNOWN) ++ { ++ if (self->is_retry) ++ warning = g_strdup_printf (ngettext ("Wrong password entered. You have %1$u try left", ++ "Wrong password entered. You have %1$u tries left", num), num); ++ else ++ warning = g_strdup_printf (ngettext ("You have %u try left", ++ "You have %u tries left", num), num); ++ } ++ else if (self->is_retry) ++ { ++ warning = g_strdup (_("Wrong password entered.")); ++ } ++ ++ gcr_prompt_set_warning (prompt, warning); ++ ++ return prompt; ++} ++ ++static void ++wwan_update_unlock_button (CcWwanDevicePage *self) ++{ ++ gtk_button_set_label (self->unlock_button, _("Unlock")); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->unlock_button), TRUE); ++} ++ ++static void ++cc_wwan_device_page_unlocked_cb (GObject *object, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ CcWwanDevicePage *self = user_data; ++ wwan_update_unlock_button (self); ++} ++ ++static void ++wwan_device_unlock_clicked_cb (CcWwanDevicePage *self) ++{ ++ g_autoptr(GError) error = NULL; ++ GcrPrompt *prompt; ++ const gchar *password, *warning; ++ const gchar *pin = ""; ++ const gchar *puk = ""; ++ MMModemLock lock; ++ ++ lock = cc_wwan_device_get_lock (self->device); ++ password = ""; ++ ++ if (lock != MM_MODEM_LOCK_SIM_PIN && ++ lock != MM_MODEM_LOCK_SIM_PUK) ++ g_return_if_reached (); ++ ++ if (lock == MM_MODEM_LOCK_SIM_PUK) ++ { ++ prompt = cc_wwan_device_page_new_prompt (self, lock); ++ ++ warning = _("PUK code should be an 8 digit number"); ++ while (password && !cc_wwan_device_pin_valid (password, lock)) ++ { ++ password = gcr_prompt_password (prompt, NULL, &error); ++ gcr_prompt_set_warning (prompt, warning); ++ } ++ ++ puk = g_strdup (password); ++ password = ""; ++ gcr_prompt_close (prompt); ++ g_object_unref (prompt); ++ ++ if (error) ++ g_warning ("Error: %s", error->message); ++ ++ /* Error or User cancelled PUK */ ++ if (!puk) ++ return; ++ } ++ ++ prompt = cc_wwan_device_page_new_prompt (self, MM_MODEM_LOCK_SIM_PIN); ++ if (lock == MM_MODEM_LOCK_SIM_PUK) ++ { ++ gcr_prompt_set_password_new (prompt, TRUE); ++ gcr_prompt_set_message (prompt, _("Enter New PIN")); ++ gcr_prompt_set_warning (prompt, ""); ++ } ++ ++ warning = _("PIN code should be a 4-8 digit number"); ++ while (password && !cc_wwan_device_pin_valid (password, MM_MODEM_LOCK_SIM_PIN)) ++ { ++ password = gcr_prompt_password (prompt, NULL, &error); ++ gcr_prompt_set_warning (prompt, warning); ++ } ++ ++ pin = g_strdup (password); ++ gcr_prompt_close (prompt); ++ g_object_unref (prompt); ++ ++ if (error) ++ g_warning ("Error: %s", error->message); ++ ++ /* Error or User cancelled PIN */ ++ if (!pin) ++ return; ++ ++ gtk_button_set_label (self->unlock_button, _("Unlocking...")); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->unlock_button), FALSE); ++ ++ if (lock == MM_MODEM_LOCK_SIM_PIN) ++ cc_wwan_device_send_pin (self->device, pin, ++ NULL, /* cancellable */ ++ cc_wwan_device_page_unlocked_cb, ++ self); ++ else if (lock == MM_MODEM_LOCK_SIM_PUK) ++ { ++ cc_wwan_device_send_puk (self->device, puk, pin, ++ NULL, /* Cancellable */ ++ cc_wwan_device_page_unlocked_cb, ++ self); ++ } ++ else ++ { ++ g_warn_if_reached (); ++ } ++} ++ ++static void ++wwan_data_settings_changed_cb (CcWwanDevicePage *self, ++ GParamSpec *pspec, ++ CcListRow *data_row) ++{ ++ gboolean active; ++ ++ if (self->is_self_change) ++ { ++ self->is_self_change = FALSE; ++ return; ++ } ++ ++ if (cc_wwan_data_get_default_apn (self->wwan_data) == NULL) ++ wwan_data_show_apn_dialog (self); ++ ++ /* The user dismissed the dialog for selecting default APN */ ++ if (cc_wwan_data_get_default_apn (self->wwan_data) == NULL) ++ { ++ self->is_self_change = TRUE; ++ gtk_widget_activate (GTK_WIDGET (data_row)); ++ ++ return; ++ } ++ ++ active = cc_list_row_get_active (data_row); ++ ++ if (data_row == self->data_enable_row) ++ cc_wwan_data_set_enabled (self->wwan_data, active); ++ else ++ cc_wwan_data_set_roaming_enabled (self->wwan_data, active); ++ ++ cc_wwan_data_save_settings (self->wwan_data, NULL, NULL, NULL); ++} ++ ++static void ++wwan_network_settings_activated_cb (CcWwanDevicePage *self, ++ CcListRow *row) ++{ ++ GtkWidget *dialog; ++ GtkWindow *top_level; ++ ++ top_level = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))); ++ ++ if (row == self->network_mode_row) ++ { ++ if (!self->network_mode_dialog) ++ self->network_mode_dialog = cc_wwan_mode_dialog_new (top_level, self->device); ++ ++ dialog = GTK_WIDGET (self->network_mode_dialog); ++ } ++ else if (row == self->network_name_row) ++ { ++ if (!self->network_dialog) ++ self->network_dialog = cc_wwan_network_dialog_new (top_level, self->device); ++ ++ dialog = GTK_WIDGET (self->network_dialog); ++ } ++ else ++ { ++ return; ++ } ++ ++ gtk_widget_show (dialog); ++} ++ ++static void ++wwan_advanced_settings_activated_cb (CcWwanDevicePage *self, ++ CcListRow *row) ++{ ++ GtkWindow *top_level; ++ ++ top_level = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))); ++ ++ if (row == self->sim_lock_row) ++ { ++ if (!self->sim_lock_dialog) ++ self->sim_lock_dialog = cc_wwan_sim_lock_dialog_new (top_level, self->device); ++ gtk_widget_show (GTK_WIDGET (self->sim_lock_dialog)); ++ } ++ else if (row == self->details_row) ++ { ++ if (!self->details_dialog) ++ self->details_dialog = cc_wwan_details_dialog_new (top_level, self->device); ++ gtk_widget_show (GTK_WIDGET (self->details_dialog)); ++ } ++ else if (row == self->apn_settings_row) ++ { ++ wwan_data_show_apn_dialog (self); ++ } ++ else ++ { ++ g_return_if_reached (); ++ } ++} ++ ++static void ++cc_wwan_device_page_update_data (CcWwanDevicePage *self) ++{ ++ gboolean has_data; ++ ++ if (self->wwan_data == cc_wwan_device_get_data (self->device)) ++ return; ++ ++ self->wwan_data = cc_wwan_device_get_data (self->device); ++ has_data = self->wwan_data != NULL; ++ ++ gtk_widget_set_sensitive (GTK_WIDGET (self->data_settings_list), has_data); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->apn_settings_row), has_data); ++ ++ if (!has_data) ++ return; ++ ++ g_signal_handlers_block_by_func (self->data_roaming_row, ++ wwan_data_settings_changed_cb, self); ++ g_signal_handlers_block_by_func (self->data_enable_row, ++ wwan_data_settings_changed_cb, self); ++ ++ g_object_set (self->data_roaming_row, "active", ++ cc_wwan_data_get_roaming_enabled (self->wwan_data), NULL); ++ ++ g_object_set (self->data_enable_row, "active", ++ cc_wwan_data_get_enabled (self->wwan_data), NULL); ++ ++ g_signal_handlers_unblock_by_func (self->data_roaming_row, ++ wwan_data_settings_changed_cb, self); ++ g_signal_handlers_unblock_by_func (self->data_enable_row, ++ wwan_data_settings_changed_cb, self); ++} ++ ++static void ++cc_wwan_device_page_update (CcWwanDevicePage *self) ++{ ++ GtkStack *main_stack; ++ MMModemLock lock; ++ ++ main_stack = self->main_stack; ++ if (!cc_wwan_device_has_sim (self->device)) ++ gtk_stack_set_visible_child_name (main_stack, "no-sim-view"); ++ else if ((lock = cc_wwan_device_get_lock (self->device)) == MM_MODEM_LOCK_SIM_PIN || ++ lock == MM_MODEM_LOCK_SIM_PUK) ++ gtk_stack_set_visible_child_name (main_stack, "sim-lock-view"); ++ else ++ gtk_stack_set_visible_child_name (main_stack, "settings-view"); ++} ++ ++static void ++cc_wwan_locks_changed_cb (CcWwanDevicePage *self) ++{ ++ const gchar *label; ++ ++ if (cc_wwan_device_get_sim_lock (self->device)) ++ label = _("Enabled"); ++ else ++ label = _("Disabled"); ++ ++ cc_list_row_set_secondary_label (self->sim_lock_row, label); ++ cc_wwan_device_page_update (self); ++} ++ ++static void ++cc_wwan_device_page_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ CcWwanDevicePage *self = (CcWwanDevicePage *)object; ++ ++ switch (prop_id) ++ { ++ case PROP_DEVICE: ++ self->device = g_value_dup_object (value); ++ break; ++ ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } ++} ++ ++static void ++cc_wwan_device_page_constructed (GObject *object) ++{ ++ CcWwanDevicePage *self = (CcWwanDevicePage *)object; ++ ++ G_OBJECT_CLASS (cc_wwan_device_page_parent_class)->constructed (object); ++ ++ cc_wwan_device_page_update_data (self); ++ ++ g_object_bind_property (self->device, "operator-name", ++ self->network_name_row, "secondary-label", ++ G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE); ++ ++ g_object_bind_property (self->device, "network-mode", ++ self->network_mode_row, "secondary-label", ++ G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE); ++ ++ g_signal_connect_object (self->device, "notify::enabled-locks", ++ (GCallback)cc_wwan_locks_changed_cb, ++ self, G_CONNECT_SWAPPED); ++ ++ g_signal_connect_object (self->device, "notify::has-data", ++ (GCallback)cc_wwan_device_page_update_data, ++ self, G_CONNECT_SWAPPED); ++ ++ cc_wwan_device_page_update (self); ++ cc_wwan_locks_changed_cb (self); ++} ++ ++static void ++cc_wwan_device_page_dispose (GObject *object) ++{ ++ CcWwanDevicePage *self = (CcWwanDevicePage *)object; ++ ++ g_clear_pointer ((GtkWidget **)&self->apn_dialog, gtk_widget_destroy); ++ g_clear_pointer ((GtkWidget **)&self->details_dialog, gtk_widget_destroy); ++ g_clear_pointer ((GtkWidget **)&self->network_mode_dialog, gtk_widget_destroy); ++ g_clear_pointer ((GtkWidget **)&self->network_dialog, gtk_widget_destroy); ++ g_clear_pointer ((GtkWidget **)&self->sim_lock_dialog, gtk_widget_destroy); ++ ++ g_clear_object (&self->wwan_proxy); ++ g_clear_object (&self->device); ++ ++ G_OBJECT_CLASS (cc_wwan_device_page_parent_class)->dispose (object); ++} ++ ++static void ++cc_wwan_device_page_class_init (CcWwanDevicePageClass *klass) ++{ ++ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->set_property = cc_wwan_device_page_set_property; ++ object_class->constructed = cc_wwan_device_page_constructed; ++ object_class->dispose = cc_wwan_device_page_dispose; ++ ++ g_type_ensure (CC_TYPE_WWAN_DEVICE); ++ ++ properties[PROP_DEVICE] = ++ g_param_spec_object ("device", ++ "Device", ++ "The WWAN Device", ++ CC_TYPE_WWAN_DEVICE, ++ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); ++ ++ g_object_class_install_properties (object_class, N_PROPS, properties); ++ ++ gtk_widget_class_set_template_from_resource (widget_class, ++ "/org/gnome/control-center/wwan/cc-wwan-device-page.ui"); ++ ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, advanced_settings_list); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, apn_settings_row); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, data_enable_row); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, data_roaming_row); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, data_settings_list); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, details_row); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, main_stack); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, network_mode_row); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, network_name_row); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, network_settings_list); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, sim_lock_row); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanDevicePage, unlock_button); ++ ++ gtk_widget_class_bind_template_callback (widget_class, wwan_device_unlock_clicked_cb); ++ gtk_widget_class_bind_template_callback (widget_class, wwan_data_settings_changed_cb); ++ gtk_widget_class_bind_template_callback (widget_class, wwan_network_settings_activated_cb); ++ gtk_widget_class_bind_template_callback (widget_class, wwan_advanced_settings_activated_cb); ++} ++ ++static void ++cc_wwan_device_page_init (CcWwanDevicePage *self) ++{ ++ gtk_widget_init_template (GTK_WIDGET (self)); ++ ++ gtk_list_box_set_header_func (self->data_settings_list, ++ cc_list_box_update_header_func, ++ NULL, NULL); ++ ++ gtk_list_box_set_header_func (self->network_settings_list, ++ cc_list_box_update_header_func, ++ NULL, NULL); ++ ++ gtk_list_box_set_header_func (self->advanced_settings_list, ++ cc_list_box_update_header_func, ++ NULL, NULL); ++} ++ ++static void ++cc_wwan_error_changed_cb (CcWwanDevicePage *self) ++{ ++ const gchar *message; ++ ++ message = cc_wwan_device_get_simple_error (self->device); ++ ++ if (!message) ++ return; ++ ++ /* ++ * The label is first set to empty, which will result in ++ * the revealer to be closed. Then the real label is ++ * set. This will animate the revealer which can bring ++ * the user's attention. ++ */ ++ gtk_label_set_label (self->notification_label, ""); ++ gtk_label_set_label (self->notification_label, message); ++} ++ ++CcWwanDevicePage * ++cc_wwan_device_page_new (CcWwanDevice *device, ++ GtkWidget *notification_label) ++{ ++ CcWwanDevicePage *self; ++ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (device), NULL); ++ ++ self = g_object_new (CC_TYPE_WWAN_DEVICE_PAGE, ++ "device", device, ++ NULL); ++ ++ self->notification_label = GTK_LABEL (notification_label); ++ ++ g_signal_connect_object (self->device, "notify::error", ++ G_CALLBACK (cc_wwan_error_changed_cb), ++ self, G_CONNECT_SWAPPED); ++ ++ return self; ++} ++ ++CcWwanDevice * ++cc_wwan_device_page_get_device (CcWwanDevicePage *self) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE_PAGE (self), NULL); ++ ++ return self->device; ++} ++ ++void ++cc_wwan_device_page_set_sim_index (CcWwanDevicePage *self, ++ gint sim_index) ++{ ++ g_return_if_fail (CC_IS_WWAN_DEVICE_PAGE (self)); ++ g_return_if_fail (sim_index >= 1); ++ ++ self->sim_index = sim_index; ++} +diff --git a/panels/wwan/cc-wwan-device-page.h b/panels/wwan/cc-wwan-device-page.h +new file mode 100644 +index 000000000..923346a89 +--- /dev/null ++++ b/panels/wwan/cc-wwan-device-page.h +@@ -0,0 +1,42 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-device-page.h ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#pragma once ++ ++#include ++ ++#include "cc-wwan-device.h" ++ ++G_BEGIN_DECLS ++ ++#define CC_TYPE_WWAN_DEVICE_PAGE (cc_wwan_device_page_get_type()) ++G_DECLARE_FINAL_TYPE (CcWwanDevicePage, cc_wwan_device_page, CC, WWAN_DEVICE_PAGE, GtkBox) ++ ++CcWwanDevicePage *cc_wwan_device_page_new (CcWwanDevice *device, ++ GtkWidget *notification_label); ++CcWwanDevice *cc_wwan_device_page_get_device (CcWwanDevicePage *self); ++void cc_wwan_device_page_set_sim_index (CcWwanDevicePage *self, ++ gint sim_index); ++ ++G_END_DECLS +diff --git a/panels/wwan/cc-wwan-device-page.ui b/panels/wwan/cc-wwan-device-page.ui +new file mode 100644 +index 000000000..f77bd707d +--- /dev/null ++++ b/panels/wwan/cc-wwan-device-page.ui +@@ -0,0 +1,270 @@ ++ ++ ++ ++ ++ both ++ ++ ++ ++ ++ ++ ++ +diff --git a/panels/wwan/cc-wwan-device.c b/panels/wwan/cc-wwan-device.c +new file mode 100644 +index 000000000..31baff95c +--- /dev/null ++++ b/panels/wwan/cc-wwan-device.c +@@ -0,0 +1,1355 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-device.c ++ * ++ * Copyright 2019-2020 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#undef G_LOG_DOMAIN ++#define G_LOG_DOMAIN "cc-wwan-device" ++ ++#ifdef HAVE_CONFIG_H ++# include "config.h" ++#endif ++ ++#include ++#include ++#if defined(HAVE_NETWORK_MANAGER) && defined(BUILD_NETWORK) ++# include ++# include ++#endif ++ ++#include "cc-wwan-errors-private.h" ++#include "cc-wwan-device.h" ++ ++/** ++ * @short_description: Device Object ++ * @include: "cc-wwan-device.h" ++ */ ++ ++struct _CcWwanDevice ++{ ++ GObject parent_instance; ++ ++ MMObject *mm_object; ++ MMModem *modem; ++ MMSim *sim; ++ MMModem3gpp *modem_3gpp; ++ ++ const char *operator_code; /* MCCMNC */ ++ GError *error; ++ ++ /* Building with NetworkManager is optional, ++ * so #NMclient type can’t be used here. ++ */ ++ GObject *nm_client; /* An #NMClient */ ++ CcWwanData *wwan_data; ++ ++ gulong modem_3gpp_id; ++ gulong modem_3gpp_locks_id; ++ ++ /* Enabled locks like PIN, PIN2, PUK, etc. */ ++ MMModem3gppFacility locks; ++ ++ CcWwanState registration_state; ++ gboolean network_is_manual; ++}; ++ ++G_DEFINE_TYPE (CcWwanDevice, cc_wwan_device, G_TYPE_OBJECT) ++ ++ ++enum { ++ PROP_0, ++ PROP_OPERATOR_NAME, ++ PROP_ENABLED_LOCKS, ++ PROP_ERROR, ++ PROP_HAS_DATA, ++ PROP_NETWORK_MODE, ++ PROP_REGISTRATION_STATE, ++ PROP_SIGNAL, ++ PROP_UNLOCK_REQUIRED, ++ N_PROPS ++}; ++ ++static GParamSpec *properties[N_PROPS]; ++ ++static void ++cc_wwan_device_state_changed_cb (CcWwanDevice *self) ++{ ++ MMModem3gppRegistrationState state; ++ ++ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_OPERATOR_NAME]); ++ ++ state = mm_modem_3gpp_get_registration_state (self->modem_3gpp); ++ ++ switch (state) ++ { ++ case MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN: ++ self->registration_state = CC_WWAN_REGISTRATION_STATE_UNKNOWN; ++ break; ++ ++ case MM_MODEM_3GPP_REGISTRATION_STATE_DENIED: ++ self->registration_state = CC_WWAN_REGISTRATION_STATE_DENIED; ++ break; ++ ++ case MM_MODEM_3GPP_REGISTRATION_STATE_IDLE: ++ self->registration_state = CC_WWAN_REGISTRATION_STATE_IDLE; ++ break; ++ ++ case MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING: ++ self->registration_state = CC_WWAN_REGISTRATION_STATE_SEARCHING; ++ break; ++ ++ case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING: ++ self->registration_state = CC_WWAN_REGISTRATION_STATE_ROAMING; ++ break; ++ ++ default: ++ self->registration_state = CC_WWAN_REGISTRATION_STATE_REGISTERED; ++ break; ++ } ++ ++ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_REGISTRATION_STATE]); ++} ++ ++static void ++cc_wwan_device_locks_changed_cb (CcWwanDevice *self) ++{ ++ self->locks = mm_modem_3gpp_get_enabled_facility_locks (self->modem_3gpp); ++ ++ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ENABLED_LOCKS]); ++} ++ ++static void ++cc_wwan_device_3gpp_changed_cb (CcWwanDevice *self) ++{ ++ gulong handler_id = 0; ++ ++ if (self->modem_3gpp_id) ++ g_signal_handler_disconnect (self->modem_3gpp, self->modem_3gpp_id); ++ self->modem_3gpp_id = 0; ++ ++ if (self->modem_3gpp_locks_id) ++ g_signal_handler_disconnect (self->modem_3gpp, self->modem_3gpp_locks_id); ++ self->modem_3gpp_locks_id = 0; ++ ++ g_clear_object (&self->modem_3gpp); ++ self->modem_3gpp = mm_object_get_modem_3gpp (self->mm_object); ++ ++ if (self->modem_3gpp) ++ { ++ handler_id = g_signal_connect_object (self->modem_3gpp, "notify::registration-state", ++ G_CALLBACK (cc_wwan_device_state_changed_cb), ++ self, G_CONNECT_SWAPPED); ++ self->modem_3gpp_id = handler_id; ++ ++ handler_id = g_signal_connect_object (self->modem_3gpp, "notify::enabled-facility-locks", ++ G_CALLBACK (cc_wwan_device_locks_changed_cb), ++ self, G_CONNECT_SWAPPED); ++ self->modem_3gpp_locks_id = handler_id; ++ cc_wwan_device_locks_changed_cb (self); ++ cc_wwan_device_state_changed_cb (self); ++ } ++} ++ ++static void ++cc_wwan_device_signal_quality_changed_cb (CcWwanDevice *self) ++{ ++ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SIGNAL]); ++} ++ ++static void ++cc_wwan_device_mode_changed_cb (CcWwanDevice *self) ++{ ++ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_NETWORK_MODE]); ++} ++ ++static void ++wwan_device_emit_data_changed (CcWwanDevice *self) ++{ ++ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HAS_DATA]); ++} ++ ++static void ++cc_wwan_device_unlock_required_cb (CcWwanDevice *self) ++{ ++ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_UNLOCK_REQUIRED]); ++} ++ ++#if defined(HAVE_NETWORK_MANAGER) && defined(BUILD_NETWORK) ++static void ++cc_wwan_device_nm_changed_cb (CcWwanDevice *self, ++ GParamSpec *pspec, ++ NMClient *client) ++{ ++ gboolean nm_is_running; ++ ++ nm_is_running = nm_client_get_nm_running (client); ++ ++ if (!nm_is_running && self->wwan_data != NULL) ++ { ++ g_clear_object (&self->wwan_data); ++ wwan_device_emit_data_changed (self); ++ } ++} ++ ++static void ++cc_wwan_device_nm_device_added_cb (CcWwanDevice *self, ++ NMDevice *nm_device) ++{ ++ if (!NM_IS_DEVICE_MODEM (nm_device)) ++ return; ++ ++ if(!self->sim || !cc_wwan_device_is_nm_device (self, G_OBJECT (nm_device))) ++ return; ++ ++ self->wwan_data = cc_wwan_data_new (self->mm_object, ++ NM_CLIENT (self->nm_client)); ++ ++ if (self->wwan_data) ++ { ++ g_signal_connect_object (self->wwan_data, "notify::enabled", ++ G_CALLBACK (wwan_device_emit_data_changed), ++ self, G_CONNECT_SWAPPED); ++ wwan_device_emit_data_changed (self); ++ } ++} ++#endif ++ ++static void ++cc_wwan_device_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec) ++{ ++ CcWwanDevice *self = (CcWwanDevice *)object; ++ MMModemMode allowed, preferred; ++ ++ switch (prop_id) ++ { ++ case PROP_OPERATOR_NAME: ++ g_value_set_string (value, cc_wwan_device_get_operator_name (self)); ++ break; ++ ++ case PROP_ERROR: ++ g_value_set_boolean (value, self->error != NULL); ++ break; ++ ++ case PROP_HAS_DATA: ++ g_value_set_boolean (value, self->wwan_data != NULL); ++ break; ++ ++ case PROP_ENABLED_LOCKS: ++ g_value_set_int (value, self->locks); ++ break; ++ ++ case PROP_NETWORK_MODE: ++ if (cc_wwan_device_get_current_mode (self, &allowed, &preferred)) ++ g_value_take_string (value, cc_wwan_device_get_string_from_mode (self, allowed, preferred)); ++ break; ++ ++ case PROP_REGISTRATION_STATE: ++ g_value_set_int (value, self->registration_state); ++ break; ++ ++ case PROP_UNLOCK_REQUIRED: ++ g_value_set_int (value, cc_wwan_device_get_lock (self)); ++ break; ++ ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } ++} ++ ++static void ++cc_wwan_device_dispose (GObject *object) ++{ ++ CcWwanDevice *self = (CcWwanDevice *)object; ++ ++ g_clear_error (&self->error); ++ g_clear_object (&self->modem); ++ g_clear_object (&self->mm_object); ++ g_clear_object (&self->sim); ++ g_clear_object (&self->modem_3gpp); ++ ++ g_clear_object (&self->nm_client); ++ g_clear_object (&self->wwan_data); ++ ++ G_OBJECT_CLASS (cc_wwan_device_parent_class)->dispose (object); ++} ++ ++static void ++cc_wwan_device_class_init (CcWwanDeviceClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->get_property = cc_wwan_device_get_property; ++ object_class->dispose = cc_wwan_device_dispose; ++ ++ properties[PROP_OPERATOR_NAME] = ++ g_param_spec_string ("operator-name", ++ "Operator Name", ++ "Operator Name the device is connected to", ++ NULL, ++ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); ++ ++ properties[PROP_ENABLED_LOCKS] = ++ g_param_spec_int ("enabled-locks", ++ "Enabled Locks", ++ "Locks Enabled in Modem", ++ MM_MODEM_3GPP_FACILITY_NONE, ++ MM_MODEM_3GPP_FACILITY_CORP_PERS, ++ MM_MODEM_3GPP_FACILITY_NONE, ++ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); ++ ++ properties[PROP_ERROR] = ++ g_param_spec_boolean ("error", ++ "Error", ++ "Set if some Error occurs", ++ FALSE, ++ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); ++ ++ properties[PROP_HAS_DATA] = ++ g_param_spec_boolean ("has-data", ++ "has-data", ++ "Data for the device", ++ FALSE, ++ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); ++ ++ properties[PROP_NETWORK_MODE] = ++ g_param_spec_string ("network-mode", ++ "Network Mode", ++ "A String representing preferred network mode", ++ NULL, ++ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); ++ ++ properties[PROP_REGISTRATION_STATE] = ++ g_param_spec_int ("registration-state", ++ "Registration State", ++ "The current network registration state", ++ CC_WWAN_REGISTRATION_STATE_UNKNOWN, ++ CC_WWAN_REGISTRATION_STATE_DENIED, ++ CC_WWAN_REGISTRATION_STATE_UNKNOWN, ++ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); ++ ++ properties[PROP_UNLOCK_REQUIRED] = ++ g_param_spec_int ("unlock-required", ++ "Unlock Required", ++ "The Modem lock status changed", ++ MM_MODEM_LOCK_UNKNOWN, ++ MM_MODEM_LOCK_PH_NETSUB_PUK, ++ MM_MODEM_LOCK_UNKNOWN, ++ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); ++ ++ properties[PROP_SIGNAL] = ++ g_param_spec_int ("signal", ++ "Signal", ++ "Get Device Signal", ++ 0, 100, 0, ++ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); ++ ++ g_object_class_install_properties (object_class, N_PROPS, properties); ++} ++ ++static void ++cc_wwan_device_init (CcWwanDevice *self) ++{ ++} ++ ++/** ++ * cc_wwan_device_new: ++ * @mm_object: (transfer full): An #MMObject ++ * ++ * Create a new device representing the given ++ * @mm_object. ++ * ++ * Returns: A #CcWwanDevice ++ */ ++CcWwanDevice * ++cc_wwan_device_new (MMObject *mm_object, ++ GObject *nm_client) ++{ ++ CcWwanDevice *self; ++ ++ g_return_val_if_fail (MM_IS_OBJECT (mm_object), NULL); ++#if defined(HAVE_NETWORK_MANAGER) && defined(BUILD_NETWORK) ++ g_return_val_if_fail (NM_IS_CLIENT (nm_client), NULL); ++#else ++ g_return_val_if_fail (!nm_client, NULL); ++#endif ++ ++ self = g_object_new (CC_TYPE_WWAN_DEVICE, NULL); ++ ++ self->mm_object = g_object_ref (mm_object); ++ self->modem = mm_object_get_modem (mm_object); ++ self->sim = mm_modem_get_sim_sync (self->modem, NULL, NULL); ++ g_set_object (&self->nm_client, nm_client); ++ if (self->sim) ++ { ++ self->operator_code = mm_sim_get_operator_identifier (self->sim); ++#if defined(HAVE_NETWORK_MANAGER) && defined(BUILD_NETWORK) ++ self->wwan_data = cc_wwan_data_new (mm_object, ++ NM_CLIENT (self->nm_client)); ++#endif ++ } ++ ++ g_signal_connect_object (self->mm_object, "notify::unlock-required", ++ G_CALLBACK (cc_wwan_device_unlock_required_cb), ++ self, G_CONNECT_SWAPPED); ++ if (self->wwan_data) ++ g_signal_connect_object (self->wwan_data, "notify::enabled", ++ G_CALLBACK (wwan_device_emit_data_changed), ++ self, G_CONNECT_SWAPPED); ++ ++#if defined(HAVE_NETWORK_MANAGER) && defined(BUILD_NETWORK) ++ g_signal_connect_object (self->nm_client, "notify::nm-running" , ++ G_CALLBACK (cc_wwan_device_nm_changed_cb), self, ++ G_CONNECT_SWAPPED); ++ ++ g_signal_connect_object (self->nm_client, "device-added", ++ G_CALLBACK (cc_wwan_device_nm_device_added_cb), ++ self, G_CONNECT_SWAPPED); ++#endif ++ ++ g_signal_connect_object (self->mm_object, "notify::modem3gpp", ++ G_CALLBACK (cc_wwan_device_3gpp_changed_cb), ++ self, G_CONNECT_SWAPPED); ++ g_signal_connect_object (self->modem, "notify::signal-quality", ++ G_CALLBACK (cc_wwan_device_signal_quality_changed_cb), ++ self, G_CONNECT_SWAPPED); ++ ++ cc_wwan_device_3gpp_changed_cb (self); ++ g_signal_connect_object (self->modem, "notify::current-modes", ++ G_CALLBACK (cc_wwan_device_mode_changed_cb), ++ self, G_CONNECT_SWAPPED); ++ ++ return self; ++} ++ ++gboolean ++cc_wwan_device_has_sim (CcWwanDevice *self) ++{ ++ MMModemStateFailedReason state_reason; ++ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE); ++ ++ state_reason = mm_modem_get_state_failed_reason (self->modem); ++ ++ if (state_reason == MM_MODEM_STATE_FAILED_REASON_SIM_MISSING) ++ return FALSE; ++ ++ return TRUE; ++} ++ ++/** ++ * cc_wwan_device_get_lock: ++ * @self: a #CcWwanDevice ++ * ++ * Get the active device lock that is required to ++ * be unlocked for accessing device features. ++ * ++ * Returns: %TRUE if PIN enabled, %FALSE otherwise. ++ */ ++MMModemLock ++cc_wwan_device_get_lock (CcWwanDevice *self) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), MM_MODEM_LOCK_UNKNOWN); ++ ++ return mm_modem_get_unlock_required (self->modem); ++} ++ ++ ++/** ++ * cc_wwan_device_get_sim_lock: ++ * @self: a #CcWwanDevice ++ * ++ * Get if SIM lock with PIN is enabled. SIM PIN ++ * enabled doesn’t mean that SIM is locked. ++ * See cc_wwan_device_get_lock(). ++ * ++ * Returns: %TRUE if PIN enabled, %FALSE otherwise. ++ */ ++gboolean ++cc_wwan_device_get_sim_lock (CcWwanDevice *self) ++{ ++ gboolean sim_lock; ++ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE); ++ ++ sim_lock = self->locks & MM_MODEM_3GPP_FACILITY_SIM; ++ ++ return !!sim_lock; ++} ++ ++guint ++cc_wwan_device_get_unlock_retries (CcWwanDevice *self, ++ MMModemLock lock) ++{ ++ MMUnlockRetries *retries; ++ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), 0); ++ ++ retries = mm_modem_get_unlock_retries (self->modem); ++ ++ return mm_unlock_retries_get (retries, lock); ++} ++ ++static void ++cc_wwan_device_pin_sent_cb (GObject *object, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ CcWwanDevice *self; ++ MMSim *sim = (MMSim *)object; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; ++ ++ if (!mm_sim_send_pin_finish (sim, result, &error)) ++ { ++ self = g_task_get_source_object (G_TASK (task)); ++ ++ g_clear_error (&self->error); ++ self->error = g_error_copy (error); ++ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]); ++ ++ g_task_return_error (task, g_steal_pointer (&error)); ++ } ++ else ++ { ++ g_task_return_boolean (task, TRUE); ++ } ++} ++ ++void ++cc_wwan_device_send_pin (CcWwanDevice *self, ++ const gchar *pin, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data) ++{ ++ g_autoptr(GTask) task = NULL; ++ ++ g_return_if_fail (CC_IS_WWAN_DEVICE (self)); ++ g_return_if_fail (MM_IS_SIM (self->sim)); ++ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); ++ g_return_if_fail (pin && *pin); ++ ++ task = g_task_new (self, cancellable, callback, user_data); ++ ++ mm_sim_send_pin (self->sim, pin, cancellable, ++ cc_wwan_device_pin_sent_cb, ++ g_steal_pointer (&task)); ++} ++ ++gboolean ++cc_wwan_device_send_pin_finish (CcWwanDevice *self, ++ GAsyncResult *result, ++ GError **error) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE); ++ g_return_val_if_fail (G_IS_TASK (result), FALSE); ++ ++ return g_task_propagate_boolean (G_TASK (result), error); ++} ++ ++static void ++cc_wwan_device_puk_sent_cb (GObject *object, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ CcWwanDevice *self; ++ MMSim *sim = (MMSim *)object; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; ++ ++ if (!mm_sim_send_puk_finish (sim, result, &error)) ++ { ++ self = g_task_get_source_object (G_TASK (task)); ++ ++ g_clear_error (&self->error); ++ self->error = g_error_copy (error); ++ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]); ++ ++ g_task_return_error (task, g_steal_pointer (&error)); ++ } ++ else ++ { ++ g_task_return_boolean (task, TRUE); ++ } ++} ++ ++void ++cc_wwan_device_send_puk (CcWwanDevice *self, ++ const gchar *puk, ++ const gchar *pin, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data) ++{ ++ g_autoptr(GTask) task = NULL; ++ ++ g_return_if_fail (CC_IS_WWAN_DEVICE (self)); ++ g_return_if_fail (MM_IS_SIM (self->sim)); ++ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); ++ g_return_if_fail (puk && *puk); ++ g_return_if_fail (pin && *pin); ++ ++ task = g_task_new (self, cancellable, callback, user_data); ++ ++ mm_sim_send_puk (self->sim, puk, pin, cancellable, ++ cc_wwan_device_puk_sent_cb, ++ g_steal_pointer (&task)); ++} ++ ++gboolean ++cc_wwan_device_send_puk_finish (CcWwanDevice *self, ++ GAsyncResult *result, ++ GError **error) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE); ++ g_return_val_if_fail (G_IS_TASK (result), FALSE); ++ ++ return g_task_propagate_boolean (G_TASK (result), error); ++} ++ ++static void ++cc_wwan_device_enable_pin_cb (GObject *object, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ CcWwanDevice *self; ++ MMSim *sim = (MMSim *)object; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; ++ ++ if (!mm_sim_enable_pin_finish (sim, result, &error)) ++ { ++ self = g_task_get_source_object (G_TASK (task)); ++ ++ g_clear_error (&self->error); ++ self->error = g_error_copy (error); ++ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]); ++ ++ g_task_return_error (task, g_steal_pointer (&error)); ++ } ++ else ++ { ++ g_task_return_boolean (task, TRUE); ++ } ++} ++ ++void ++cc_wwan_device_enable_pin (CcWwanDevice *self, ++ const gchar *pin, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data) ++{ ++ g_autoptr(GTask) task = NULL; ++ ++ g_return_if_fail (CC_IS_WWAN_DEVICE (self)); ++ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); ++ g_return_if_fail (pin && *pin); ++ ++ task = g_task_new (self, cancellable, callback, user_data); ++ ++ mm_sim_enable_pin (self->sim, pin, cancellable, ++ cc_wwan_device_enable_pin_cb, ++ g_steal_pointer (&task)); ++} ++ ++gboolean ++cc_wwan_device_enable_pin_finish (CcWwanDevice *self, ++ GAsyncResult *result, ++ GError **error) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE); ++ g_return_val_if_fail (G_IS_TASK (result), FALSE); ++ ++ return g_task_propagate_boolean (G_TASK (result), error); ++} ++ ++static void ++cc_wwan_device_disable_pin_cb (GObject *object, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ CcWwanDevice *self; ++ MMSim *sim = (MMSim *)object; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; ++ ++ if (!mm_sim_disable_pin_finish (sim, result, &error)) ++ { ++ self = g_task_get_source_object (G_TASK (task)); ++ ++ g_clear_error (&self->error); ++ self->error = g_error_copy (error); ++ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]); ++ ++ g_task_return_error (task, g_steal_pointer (&error)); ++ } ++ else ++ { ++ g_task_return_boolean (task, TRUE); ++ } ++} ++ ++void ++cc_wwan_device_disable_pin (CcWwanDevice *self, ++ const gchar *pin, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data) ++{ ++ g_autoptr(GTask) task = NULL; ++ ++ g_return_if_fail (CC_IS_WWAN_DEVICE (self)); ++ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); ++ g_return_if_fail (pin && *pin); ++ ++ task = g_task_new (self, cancellable, callback, user_data); ++ ++ mm_sim_disable_pin (self->sim, pin, cancellable, ++ cc_wwan_device_disable_pin_cb, ++ g_steal_pointer (&task)); ++} ++ ++gboolean ++cc_wwan_device_disable_pin_finish (CcWwanDevice *self, ++ GAsyncResult *result, ++ GError **error) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE); ++ g_return_val_if_fail (G_IS_TASK (result), FALSE); ++ ++ return g_task_propagate_boolean (G_TASK (result), error); ++} ++ ++static void ++cc_wwan_device_change_pin_cb (GObject *object, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ CcWwanDevice *self; ++ MMSim *sim = (MMSim *)object; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; ++ ++ if (!mm_sim_change_pin_finish (sim, result, &error)) ++ { ++ self = g_task_get_source_object (G_TASK (task)); ++ ++ g_clear_error (&self->error); ++ self->error = g_error_copy (error); ++ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]); ++ ++ g_task_return_error (task, g_steal_pointer (&error)); ++ } ++ else ++ { ++ g_task_return_boolean (task, TRUE); ++ } ++} ++ ++void ++cc_wwan_device_change_pin (CcWwanDevice *self, ++ const gchar *old_pin, ++ const gchar *new_pin, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data) ++{ ++ g_autoptr(GTask) task = NULL; ++ ++ g_return_if_fail (CC_IS_WWAN_DEVICE (self)); ++ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); ++ g_return_if_fail (old_pin && *old_pin); ++ g_return_if_fail (new_pin && *new_pin); ++ ++ task = g_task_new (self, cancellable, callback, user_data); ++ ++ mm_sim_change_pin (self->sim, old_pin, new_pin, cancellable, ++ cc_wwan_device_change_pin_cb, ++ g_steal_pointer (&task)); ++} ++ ++gboolean ++cc_wwan_device_change_pin_finish (CcWwanDevice *self, ++ GAsyncResult *result, ++ GError **error) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE); ++ g_return_val_if_fail (G_IS_TASK (result), FALSE); ++ ++ return g_task_propagate_boolean (G_TASK (result), error); ++} ++ ++static void ++cc_wwan_device_network_mode_set_cb (GObject *object, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ CcWwanDevice *self; ++ MMModem *modem = (MMModem *)object; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; ++ ++ if (!mm_modem_set_current_modes_finish (modem, result, &error)) ++ { ++ self = g_task_get_source_object (G_TASK (task)); ++ ++ g_clear_error (&self->error); ++ self->error = g_error_copy (error); ++ g_warning ("Error: %s", error->message); ++ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]); ++ ++ g_task_return_error (task, g_steal_pointer (&error)); ++ } ++ else ++ { ++ g_task_return_boolean (task, TRUE); ++ } ++} ++ ++/** ++ * cc_wwan_device_set_network_mode: ++ * @self: a #CcWwanDevice ++ * @allowed: The allowed #MMModemModes ++ * @preferred: The preferred #MMModemMode ++ * @cancellable: (nullable): a #GCancellable or %NULL ++ * @callback: (nullable): a #GAsyncReadyCallback or %NULL ++ * @user_data: (nullable): closure data for @callback ++ * ++ * Asynchronously set preferred network mode. ++ * ++ * Call @cc_wwan_device_set_current_mode_finish() ++ * in @callback to get the result of operation. ++ */ ++void ++cc_wwan_device_set_current_mode (CcWwanDevice *self, ++ MMModemMode allowed, ++ MMModemMode preferred, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data) ++{ ++ g_autoptr(GTask) task = NULL; ++ GPermission *permission; ++ g_autoptr(GError) error = NULL; ++ ++ g_return_if_fail (CC_IS_WWAN_DEVICE (self)); ++ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); ++ ++ task = g_task_new (self, cancellable, callback, user_data); ++ permission = polkit_permission_new_sync ("org.freedesktop.ModemManager1.Device.Control", ++ NULL, cancellable, &error); ++ if (permission) ++ g_task_set_task_data (task, permission, g_object_unref); ++ ++ if (error) ++ g_warning ("error: %s", error->message); ++ ++ if (error) ++ { ++ g_task_return_error (task, g_steal_pointer (&error)); ++ } ++ else if (!g_permission_get_allowed (permission)) ++ { ++ error = g_error_new (G_IO_ERROR, ++ G_IO_ERROR_PERMISSION_DENIED, ++ "Access Denied"); ++ g_clear_error (&self->error); ++ self->error = g_error_copy (error); ++ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]); ++ ++ g_task_return_error (task, g_steal_pointer (&error)); ++ } ++ else ++ { ++ mm_modem_set_current_modes (self->modem, allowed, preferred, ++ cancellable, cc_wwan_device_network_mode_set_cb, ++ g_steal_pointer (&task)); ++ } ++} ++ ++/** ++ * cc_wwan_device_set_current_mode_finish: ++ * @self: a #CcWwanDevice ++ * @result: a #GAsyncResult ++ * @error: a location for #GError or %NULL ++ * ++ * Get the status whether setting network mode ++ * succeeded ++ * ++ * Returns: %TRUE if network mode was successfully set, ++ * %FALSE otherwise. ++ */ ++gboolean ++cc_wwan_device_set_current_mode_finish (CcWwanDevice *self, ++ GAsyncResult *result, ++ GError **error) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE); ++ g_return_val_if_fail (G_IS_TASK (result), FALSE); ++ ++ return g_task_propagate_boolean (G_TASK (result), error); ++} ++ ++gboolean ++cc_wwan_device_get_current_mode (CcWwanDevice *self, ++ MMModemMode *allowed, ++ MMModemMode *preferred) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE); ++ ++ return mm_modem_get_current_modes (self->modem, allowed, preferred); ++} ++ ++gboolean ++cc_wwan_device_is_auto_network (CcWwanDevice *self) ++{ ++ /* ++ * XXX: ModemManager Doesn’t have a true API to check ++ * if registration is automatic or manual. So Let’s ++ * do some guess work. ++ */ ++ if (self->registration_state == CC_WWAN_REGISTRATION_STATE_DENIED) ++ return FALSE; ++ ++ return !self->network_is_manual; ++} ++ ++CcWwanState ++cc_wwan_device_get_network_state (CcWwanDevice *self) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), 0); ++ ++ return self->registration_state; ++} ++ ++gboolean ++cc_wwan_device_get_supported_modes (CcWwanDevice *self, ++ MMModemMode *allowed, ++ MMModemMode *preferred) ++{ ++ g_autofree MMModemModeCombination *modes = NULL; ++ guint n_modes, i; ++ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE); ++ ++ if (!mm_modem_get_supported_modes (self->modem, &modes, &n_modes)) ++ return FALSE; ++ ++ if (allowed) ++ *allowed = 0; ++ if (preferred) ++ *preferred = 0; ++ ++ for (i = 0; i < n_modes; i++) ++ { ++ if (allowed) ++ *allowed = *allowed | modes[i].allowed; ++ if (preferred) ++ *preferred = *preferred | modes[i].preferred; ++ } ++ ++ return TRUE; ++} ++ ++#define APPEND_MODE_TO_STRING(_str, _now, _preferred, _mode_str) do { \ ++ if (_str->len > 0) \ ++ g_string_append (_str, ", "); \ ++ g_string_append (_str, _mode_str); \ ++ if (_preferred == _now) \ ++ g_string_append (_str, _(" (Preferred)")); \ ++ } while (0) ++ ++gchar * ++cc_wwan_device_get_string_from_mode (CcWwanDevice *self, ++ MMModemMode allowed, ++ MMModemMode preferred) ++{ ++ GString *str; ++ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL); ++ g_return_val_if_fail (allowed != 0, NULL); ++ ++ str = g_string_sized_new (10); ++ ++ if (allowed & MM_MODEM_MODE_2G) ++ APPEND_MODE_TO_STRING (str, MM_MODEM_MODE_2G, preferred, "2G"); ++ if (allowed & MM_MODEM_MODE_3G) ++ APPEND_MODE_TO_STRING (str, MM_MODEM_MODE_3G, preferred, "3G"); ++ if (allowed & MM_MODEM_MODE_4G) ++ APPEND_MODE_TO_STRING (str, MM_MODEM_MODE_4G, preferred, "4G"); ++ ++ if (allowed == MM_MODEM_MODE_2G || ++ allowed == MM_MODEM_MODE_3G || ++ allowed == MM_MODEM_MODE_4G) ++ g_string_append (str, _(" Only")); ++ ++ if (str->len == 0) ++ return g_string_free (str, TRUE); ++ else ++ return g_string_free (str, FALSE); ++} ++#undef APPEND_MODE_TO_STRING ++ ++static void ++wwan_network_list_free (GList *network_list) ++{ ++ g_list_free_full (network_list, (GDestroyNotify)mm_modem_3gpp_network_free); ++} ++ ++static void ++cc_wwan_device_scan_complete_cb (GObject *object, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ MMModem3gpp *modem_3gpp = (MMModem3gpp *)object; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; ++ GList *network_list; ++ ++ network_list = mm_modem_3gpp_scan_finish (modem_3gpp, result, &error); ++ ++ if (error) ++ g_task_return_error (task, g_steal_pointer (&error)); ++ else ++ g_task_return_pointer (task, network_list, (GDestroyNotify)wwan_network_list_free); ++} ++ ++void ++cc_wwan_device_scan_networks (CcWwanDevice *self, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data) ++{ ++ g_autoptr(GTask) task = NULL; ++ ++ g_return_if_fail (CC_IS_WWAN_DEVICE (self)); ++ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); ++ ++ task = g_task_new (self, cancellable, callback, user_data); ++ ++ mm_modem_3gpp_scan (self->modem_3gpp, cancellable, ++ cc_wwan_device_scan_complete_cb, ++ g_steal_pointer (&task)); ++} ++ ++GList * ++cc_wwan_device_scan_networks_finish (CcWwanDevice *self, ++ GAsyncResult *result, ++ GError **error) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE); ++ g_return_val_if_fail (G_IS_TASK (result), FALSE); ++ ++ return g_task_propagate_pointer (G_TASK (result), error); ++} ++ ++static void ++cc_wwan_device_register_network_complete_cb (GObject *object, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ CcWwanDevice *self; ++ MMModem3gpp *modem_3gpp = (MMModem3gpp *)object; ++ g_autoptr(GTask) task = user_data; ++ g_autoptr(GError) error = NULL; ++ ++ if (!mm_modem_3gpp_register_finish (modem_3gpp, result, &error)) ++ { ++ self = g_task_get_source_object (G_TASK (task)); ++ ++ g_clear_error (&self->error); ++ self->error = g_error_copy (error); ++ g_warning ("Error: %s", error->message); ++ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ERROR]); ++ ++ g_task_return_error (task, g_steal_pointer (&error)); ++ } ++ else ++ { ++ g_task_return_boolean (task, TRUE); ++ } ++} ++ ++void ++cc_wwan_device_register_network (CcWwanDevice *self, ++ const gchar *network_id, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data) ++{ ++ g_autoptr(GTask) task = NULL; ++ ++ g_return_if_fail (CC_IS_WWAN_DEVICE (self)); ++ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); ++ ++ task = g_task_new (self, cancellable, callback, user_data); ++ ++ if (network_id && *network_id) ++ self->network_is_manual = TRUE; ++ else ++ self->network_is_manual = FALSE; ++ ++ mm_modem_3gpp_register (self->modem_3gpp, network_id, cancellable, ++ cc_wwan_device_register_network_complete_cb, ++ g_steal_pointer (&task)); ++} ++ ++gboolean ++cc_wwan_device_register_network_finish (CcWwanDevice *self, ++ GAsyncResult *result, ++ GError **error) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), FALSE); ++ g_return_val_if_fail (G_IS_TASK (result), FALSE); ++ ++ return g_task_propagate_boolean (G_TASK (result), error); ++} ++ ++/** ++ * cc_wwan_device_get_operator_name: ++ * @self: a #CcWwanDevice ++ * ++ * Get the human readable network operator name ++ * currently the device is connected to. ++ * ++ * Returns: (nullable): The operator name or %NULL ++ */ ++const gchar * ++cc_wwan_device_get_operator_name (CcWwanDevice *self) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL); ++ ++ if (!self->modem_3gpp) ++ return NULL; ++ ++ return mm_modem_3gpp_get_operator_name (self->modem_3gpp); ++} ++ ++gchar * ++cc_wwan_device_dup_own_numbers (CcWwanDevice *self) ++{ ++ const char *const *own_numbers; ++ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL); ++ ++ own_numbers = mm_modem_get_own_numbers (self->modem); ++ ++ if (!own_numbers) ++ return NULL; ++ ++ return g_strjoinv ("\n", (char **)own_numbers); ++} ++ ++gchar * ++cc_wwan_device_dup_network_type_string (CcWwanDevice *self) ++{ ++ MMModemAccessTechnology type; ++ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL); ++ ++ type = mm_modem_get_access_technologies (self->modem); ++ ++ return mm_modem_access_technology_build_string_from_mask (type); ++} ++ ++gchar * ++cc_wwan_device_dup_signal_string (CcWwanDevice *self) ++{ ++ MMModemSignal *modem_signal; ++ MMSignal *signal; ++ GString *str; ++ gdouble value; ++ gboolean recent; ++ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL); ++ ++ modem_signal = mm_object_peek_modem_signal (self->mm_object); ++ ++ if (!modem_signal) ++ return g_strdup_printf ("%d%%", mm_modem_get_signal_quality (self->modem, &recent)); ++ ++ str = g_string_new (""); ++ ++ /* Adapted from ModemManager mmcli-modem-signal.c */ ++ signal = mm_modem_signal_peek_cdma (modem_signal); ++ if (signal) ++ { ++ if ((value = mm_signal_get_rssi (signal)) != MM_SIGNAL_UNKNOWN) ++ g_string_append_printf (str, "rssi: %.2g dBm ", value); ++ if ((value = mm_signal_get_ecio (signal)) != MM_SIGNAL_UNKNOWN) ++ g_string_append_printf (str, "ecio: %.2g dBm ", value); ++ } ++ ++ signal = mm_modem_signal_peek_evdo (modem_signal); ++ if (signal) ++ { ++ if ((value = mm_signal_get_rssi (signal)) != MM_SIGNAL_UNKNOWN) ++ g_string_append_printf (str, "rssi: %.2g dBm ", value); ++ if ((value = mm_signal_get_ecio (signal)) != MM_SIGNAL_UNKNOWN) ++ g_string_append_printf (str, "ecio: %.2g dBm ", value); ++ if ((value = mm_signal_get_sinr (signal)) != MM_SIGNAL_UNKNOWN) ++ g_string_append_printf (str, "sinr: %.2g dB ", value); ++ if ((value = mm_signal_get_io (signal)) != MM_SIGNAL_UNKNOWN) ++ g_string_append_printf (str, "io: %.2g dBm ", value); ++ } ++ ++ signal = mm_modem_signal_peek_gsm (modem_signal); ++ if (signal) ++ if ((value = mm_signal_get_rssi (signal)) != MM_SIGNAL_UNKNOWN) ++ g_string_append_printf (str, "rssi: %.2g dBm ", value); ++ ++ signal = mm_modem_signal_peek_umts (modem_signal); ++ if (signal) ++ { ++ if ((value = mm_signal_get_rssi (signal)) != MM_SIGNAL_UNKNOWN) ++ g_string_append_printf (str, "rssi: %.2g dBm ", value); ++ if ((value = mm_signal_get_rscp (signal)) != MM_SIGNAL_UNKNOWN) ++ g_string_append_printf (str, "rscp: %.2g dBm ", value); ++ if ((value = mm_signal_get_ecio (signal)) != MM_SIGNAL_UNKNOWN) ++ g_string_append_printf (str, "ecio: %.2g dBm ", value); ++ } ++ ++ signal = mm_modem_signal_peek_lte (modem_signal); ++ if (signal) ++ { ++ if ((value = mm_signal_get_rssi (signal)) != MM_SIGNAL_UNKNOWN) ++ g_string_append_printf (str, "rssi: %.2g dBm ", value); ++ if ((value = mm_signal_get_rsrq (signal)) != MM_SIGNAL_UNKNOWN) ++ g_string_append_printf (str, "rsrq: %.2g dB ", value); ++ if ((value = mm_signal_get_rsrp (signal)) != MM_SIGNAL_UNKNOWN) ++ g_string_append_printf (str, "rsrp: %.2g dBm ", value); ++ if ((value = mm_signal_get_snr (signal)) != MM_SIGNAL_UNKNOWN) ++ g_string_append_printf (str, "snr: %.2g dB ", value); ++ } ++ ++ return g_string_free (str, FALSE); ++} ++ ++const gchar * ++cc_wwan_device_get_manufacturer (CcWwanDevice *self) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL); ++ ++ return mm_modem_get_manufacturer (self->modem); ++} ++ ++const gchar * ++cc_wwan_device_get_model (CcWwanDevice *self) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL); ++ ++ return mm_modem_get_model (self->modem); ++} ++ ++const gchar * ++cc_wwan_device_get_firmware_version (CcWwanDevice *self) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL); ++ ++ return mm_modem_get_revision (self->modem); ++} ++ ++const gchar * ++cc_wwan_device_get_identifier (CcWwanDevice *self) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL); ++ ++ return mm_modem_get_equipment_identifier (self->modem); ++} ++ ++const gchar * ++cc_wwan_device_get_simple_error (CcWwanDevice *self) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL); ++ ++ if (!self->error) ++ return NULL; ++ ++ return cc_wwan_error_get_message (self->error); ++} ++ ++gboolean ++cc_wwan_device_is_nm_device (CcWwanDevice *self, ++ GObject *nm_device) ++{ ++#if defined(HAVE_NETWORK_MANAGER) && defined(BUILD_NETWORK) ++ g_return_val_if_fail (NM_IS_DEVICE (nm_device), FALSE); ++ ++ return g_str_equal (mm_modem_get_primary_port (self->modem), ++ nm_device_get_iface (NM_DEVICE (nm_device))); ++#else ++ return FALSE; ++#endif ++} ++ ++const gchar * ++cc_wwan_device_get_path (CcWwanDevice *self) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), ""); ++ ++ return mm_object_get_path (self->mm_object); ++} ++ ++CcWwanData * ++cc_wwan_device_get_data (CcWwanDevice *self) ++{ ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL); ++ ++ return self->wwan_data; ++} ++ ++gboolean ++cc_wwan_device_pin_valid (const gchar *password, ++ MMModemLock lock) ++{ ++ size_t len; ++ ++ g_return_val_if_fail (lock == MM_MODEM_LOCK_SIM_PIN || ++ lock == MM_MODEM_LOCK_SIM_PIN2 || ++ lock == MM_MODEM_LOCK_SIM_PUK || ++ lock == MM_MODEM_LOCK_SIM_PUK2, FALSE); ++ if (!password) ++ return FALSE; ++ ++ len = strlen (password); ++ ++ if (len < 4 || len > 8) ++ return FALSE; ++ ++ if (strspn (password, "0123456789") != len) ++ return FALSE; ++ ++ /* ++ * XXX: Can PUK code be something other than 8 digits? ++ * 3GPP standard seems mum on this ++ */ ++ if (lock == MM_MODEM_LOCK_SIM_PUK || ++ lock == MM_MODEM_LOCK_SIM_PUK2) ++ if (len != 8) ++ return FALSE; ++ ++ return TRUE; ++} +diff --git a/panels/wwan/cc-wwan-device.h b/panels/wwan/cc-wwan-device.h +new file mode 100644 +index 000000000..e484bcf30 +--- /dev/null ++++ b/panels/wwan/cc-wwan-device.h +@@ -0,0 +1,152 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-device.h ++ * ++ * Copyright 2019-2020 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#pragma once ++ ++#include ++#include ++ ++#if defined(HAVE_NETWORK_MANAGER) && defined(BUILD_NETWORK) ++# include "cc-wwan-data.h" ++#endif ++ ++G_BEGIN_DECLS ++ ++typedef enum ++{ ++ CC_WWAN_REGISTRATION_STATE_UNKNOWN, ++ CC_WWAN_REGISTRATION_STATE_IDLE, ++ CC_WWAN_REGISTRATION_STATE_REGISTERED, ++ CC_WWAN_REGISTRATION_STATE_ROAMING, ++ CC_WWAN_REGISTRATION_STATE_SEARCHING, ++ CC_WWAN_REGISTRATION_STATE_DENIED ++} CcWwanState; ++ ++typedef struct _CcWwanData CcWwanData; ++ ++#define CC_TYPE_WWAN_DEVICE (cc_wwan_device_get_type()) ++G_DECLARE_FINAL_TYPE (CcWwanDevice, cc_wwan_device, CC, WWAN_DEVICE, GObject) ++ ++CcWwanDevice *cc_wwan_device_new (MMObject *mm_object, ++ GObject *nm_client); ++gboolean cc_wwan_device_has_sim (CcWwanDevice *self); ++MMModemLock cc_wwan_device_get_lock (CcWwanDevice *self); ++gboolean cc_wwan_device_get_sim_lock (CcWwanDevice *self); ++guint cc_wwan_device_get_unlock_retries (CcWwanDevice *self, ++ MMModemLock lock); ++void cc_wwan_device_enable_pin (CcWwanDevice *self, ++ const gchar *pin, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data); ++gboolean cc_wwan_device_enable_pin_finish (CcWwanDevice *self, ++ GAsyncResult *result, ++ GError **error); ++void cc_wwan_device_disable_pin (CcWwanDevice *self, ++ const gchar *pin, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data); ++gboolean cc_wwan_device_disable_pin_finish (CcWwanDevice *self, ++ GAsyncResult *result, ++ GError **error); ++void cc_wwan_device_send_pin (CcWwanDevice *self, ++ const gchar *pin, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data); ++gboolean cc_wwan_device_send_pin_finish (CcWwanDevice *self, ++ GAsyncResult *result, ++ GError **error); ++void cc_wwan_device_send_puk (CcWwanDevice *self, ++ const gchar *puk, ++ const gchar *pin, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data); ++gboolean cc_wwan_device_send_puk_finish (CcWwanDevice *self, ++ GAsyncResult *result, ++ GError **error); ++void cc_wwan_device_change_pin (CcWwanDevice *self, ++ const gchar *old_pin, ++ const gchar *new_pin, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data); ++gboolean cc_wwan_device_change_pin_finish (CcWwanDevice *self, ++ GAsyncResult *result, ++ GError **error); ++const gchar *cc_wwan_device_get_operator_name (CcWwanDevice *self); ++gchar *cc_wwan_device_dup_own_numbers (CcWwanDevice *self); ++gchar *cc_wwan_device_dup_network_type_string (CcWwanDevice *self); ++gchar *cc_wwan_device_dup_signal_string (CcWwanDevice *self); ++const gchar *cc_wwan_device_get_manufacturer (CcWwanDevice *self); ++const gchar *cc_wwan_device_get_model (CcWwanDevice *self); ++const gchar *cc_wwan_device_get_firmware_version (CcWwanDevice *self); ++const gchar *cc_wwan_device_get_identifier (CcWwanDevice *self); ++gboolean cc_wwan_device_get_current_mode (CcWwanDevice *self, ++ MMModemMode *allowed, ++ MMModemMode *preferred); ++gboolean cc_wwan_device_is_auto_network (CcWwanDevice *self); ++CcWwanState cc_wwan_device_get_network_state (CcWwanDevice *self); ++gboolean cc_wwan_device_get_supported_modes (CcWwanDevice *self, ++ MMModemMode *allowed, ++ MMModemMode *preferred); ++void cc_wwan_device_set_current_mode (CcWwanDevice *self, ++ MMModemMode allowed, ++ MMModemMode preferred, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data); ++gboolean cc_wwan_device_set_current_mode_finish (CcWwanDevice *self, ++ GAsyncResult *result, ++ GError **error); ++gchar *cc_wwan_device_get_string_from_mode (CcWwanDevice *self, ++ MMModemMode allowed, ++ MMModemMode preferred); ++void cc_wwan_device_scan_networks (CcWwanDevice *self, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data); ++GList *cc_wwan_device_scan_networks_finish (CcWwanDevice *self, ++ GAsyncResult *result, ++ GError **error); ++void cc_wwan_device_register_network (CcWwanDevice *self, ++ const gchar *network_id, ++ GCancellable *cancellable, ++ GAsyncReadyCallback callback, ++ gpointer user_data); ++gboolean cc_wwan_device_register_network_finish (CcWwanDevice *self, ++ GAsyncResult *result, ++ GError **error); ++const gchar *cc_wwan_device_get_simple_error (CcWwanDevice *self); ++GSList *cc_wwan_device_get_apn_list (CcWwanDevice *self); ++gboolean cc_wwan_device_is_nm_device (CcWwanDevice *self, ++ GObject *nm_device); ++const gchar *cc_wwan_device_get_path (CcWwanDevice *self); ++CcWwanData *cc_wwan_device_get_data (CcWwanDevice *self); ++gboolean cc_wwan_device_pin_valid (const gchar *password, ++ MMModemLock lock); ++ ++G_END_DECLS +diff --git a/panels/wwan/cc-wwan-errors-private.h b/panels/wwan/cc-wwan-errors-private.h +new file mode 100644 +index 000000000..761b82f35 +--- /dev/null ++++ b/panels/wwan/cc-wwan-errors-private.h +@@ -0,0 +1,104 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-errors-private.h ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * Modified from mm-error-helpers.c from ModemManager ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#pragma once ++ ++#include ++#include ++#include ++ ++typedef struct { ++ guint code; ++ const gchar *message; ++} ErrorTable; ++ ++ ++static ErrorTable me_errors[] = { ++ { MM_MOBILE_EQUIPMENT_ERROR_PHONE_FAILURE, N_("Phone failure") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_NO_CONNECTION, N_("No connection to phone") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_LINK_RESERVED, N_("Phone-adaptor link reserved") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_NOT_ALLOWED, N_("Operation not allowed") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED, N_("Operation not supported") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_PH_SIM_PIN, N_("PH-SIM PIN required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_PH_FSIM_PIN, N_("PH-FSIM PIN required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_PH_FSIM_PUK, N_("PH-FSIM PUK required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_SIM_NOT_INSERTED, N_("SIM not inserted") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN, N_("SIM PIN required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_SIM_PUK, N_("SIM PUK required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_SIM_FAILURE, N_("SIM failure") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_SIM_BUSY, N_("SIM busy") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_SIM_WRONG, N_("SIM wrong") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_INCORRECT_PASSWORD, N_("Incorrect password") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN2, N_("SIM PIN2 required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_SIM_PUK2, N_("SIM PUK2 required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_MEMORY_FULL, N_("Memory full") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_INVALID_INDEX, N_("Invalid index") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_NOT_FOUND, N_("Not found") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_MEMORY_FAILURE, N_("Memory failure") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_NO_NETWORK, N_("No network service") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT, N_("Network timeout") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_NOT_ALLOWED, N_("Network not allowed - emergency calls only") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_PIN, N_("Network personalization PIN required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_PUK, N_("Network personalization PUK required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_SUBSET_PIN, N_("Network subset personalization PIN required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_SUBSET_PUK, N_("Network subset personalization PUK required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_SERVICE_PIN, N_("Service provider personalization PIN required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_SERVICE_PUK, N_("Service provider personalization PUK required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_CORP_PIN, N_("Corporate personalization PIN required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_CORP_PUK, N_("Corporate personalization PUK required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN, N_("Unknown error") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_ILLEGAL_MS, N_("Illegal MS") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_ILLEGAL_ME, N_("Illegal ME") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_NOT_ALLOWED, N_("GPRS services not allowed") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_PLMN_NOT_ALLOWED, N_("PLMN not allowed") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_LOCATION_NOT_ALLOWED, N_("Location area not allowed") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_ROAMING_NOT_ALLOWED, N_("Roaming not allowed in this location area") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_OPTION_NOT_SUPPORTED, N_("Service option not supported") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_OPTION_NOT_SUBSCRIBED, N_("Requested service option not subscribed") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_OPTION_OUT_OF_ORDER, N_("Service option temporarily out of order") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_UNKNOWN, N_("Unspecified GPRS error") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_PDP_AUTH_FAILURE, N_("PDP authentication failure") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_INVALID_MOBILE_CLASS, N_("Invalid mobile class") }, ++}; ++ ++static inline const gchar * ++cc_wwan_error_get_message (GError *error) ++{ ++ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) ++ return _("Action Cancelled"); ++ ++ if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED)) ++ return _("Access denied"); ++ ++ if (error->domain != MM_MOBILE_EQUIPMENT_ERROR) ++ return error->message; ++ ++ for (guint i = 0; i < G_N_ELEMENTS (me_errors); i++) ++ if (me_errors[i].code == error->code) ++ return _(me_errors[i].message); ++ ++ return _("Unknown Error"); ++} +diff --git a/panels/wwan/cc-wwan-mode-dialog.c b/panels/wwan/cc-wwan-mode-dialog.c +new file mode 100644 +index 000000000..e5917a41c +--- /dev/null ++++ b/panels/wwan/cc-wwan-mode-dialog.c +@@ -0,0 +1,327 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-mode-dialog.c ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#undef G_LOG_DOMAIN ++#define G_LOG_DOMAIN "cc-network-mode-dialog" ++ ++#include ++#include ++#include ++ ++#include "list-box-helper.h" ++#include "cc-wwan-mode-dialog.h" ++#include "cc-wwan-resources.h" ++ ++/** ++ * @short_description: WWAN network type selection dialog ++ */ ++ ++#define CC_TYPE_WWAN_MODE_ROW (cc_wwan_mode_row_get_type()) ++G_DECLARE_FINAL_TYPE (CcWwanModeRow, cc_wwan_mode_row, CC, WWAN_MODE_ROW, GtkListBoxRow) ++ ++struct _CcWwanModeDialog ++{ ++ GtkDialog parent_instance; ++ ++ CcWwanDevice *device; ++ GtkListBox *network_mode_list; ++ CcWwanModeRow *selected_row; ++ ++ MMModemMode preferred; ++ MMModemMode allowed; ++ MMModemMode new_allowed; ++ MMModemMode new_preferred; ++}; ++ ++G_DEFINE_TYPE (CcWwanModeDialog, cc_wwan_mode_dialog, GTK_TYPE_DIALOG) ++ ++ ++enum { ++ PROP_0, ++ PROP_DEVICE, ++ N_PROPS ++}; ++ ++static GParamSpec *properties[N_PROPS]; ++ ++struct _CcWwanModeRow ++{ ++ GtkListBoxRow parent_instance; ++ GtkImage *ok_emblem; ++ MMModemMode allowed; ++ MMModemMode preferred; ++}; ++ ++G_DEFINE_TYPE (CcWwanModeRow, cc_wwan_mode_row, GTK_TYPE_LIST_BOX_ROW) ++ ++static void ++cc_wwan_mode_row_class_init (CcWwanModeRowClass *klass) ++{ ++} ++ ++static void ++cc_wwan_mode_row_init (CcWwanModeRow *row) ++{ ++} ++ ++static void ++cc_wwan_mode_changed_cb (CcWwanModeDialog *self, ++ CcWwanModeRow *row) ++{ ++ g_assert (CC_IS_WWAN_MODE_DIALOG (self)); ++ g_assert (CC_IS_WWAN_MODE_ROW (row)); ++ ++ if (row == self->selected_row) ++ return; ++ ++ gtk_widget_show (GTK_WIDGET (row->ok_emblem)); ++ ++ if (self->selected_row) ++ gtk_widget_hide (GTK_WIDGET (self->selected_row->ok_emblem)); ++ ++ self->selected_row = row; ++} ++ ++static void ++cc_wwan_mode_dialog_ok_clicked_cb (CcWwanModeDialog *self) ++{ ++ g_assert (CC_IS_WWAN_MODE_DIALOG (self)); ++ ++ if (self->selected_row) ++ { ++ cc_wwan_device_set_current_mode (self->device, ++ self->selected_row->allowed, ++ self->selected_row->preferred, ++ NULL, NULL, NULL); ++ } ++ else ++ { ++ g_return_if_reached (); ++ } ++ ++ gtk_widget_hide (GTK_WIDGET (self)); ++} ++ ++static GtkWidget * ++cc_wwan_mode_dialog_row_new (CcWwanModeDialog *self, ++ MMModemMode allowed, ++ MMModemMode preferred) ++{ ++ CcWwanModeRow *row; ++ GtkWidget *box, *label, *image; ++ g_autofree gchar *mode = NULL; ++ ++ g_assert (CC_WWAN_MODE_DIALOG (self)); ++ ++ row = g_object_new (CC_TYPE_WWAN_MODE_ROW, NULL); ++ row->allowed = allowed; ++ row->preferred = preferred; ++ ++ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); ++ gtk_widget_show (box); ++ g_object_set (box, "margin", 18, NULL); ++ gtk_container_add (GTK_CONTAINER (row), box); ++ ++ mode = cc_wwan_device_get_string_from_mode (self->device, allowed, preferred); ++ label = gtk_label_new (mode); ++ gtk_widget_show (label); ++ gtk_widget_set_hexpand (label, TRUE); ++ gtk_widget_set_halign (label, GTK_ALIGN_START); ++ gtk_container_add (GTK_CONTAINER (box), label); ++ ++ /* image should be hidden by default */ ++ image = gtk_image_new_from_icon_name ("emblem-ok-symbolic", GTK_ICON_SIZE_BUTTON); ++ gtk_container_add (GTK_CONTAINER (box), image); ++ row->ok_emblem = GTK_IMAGE (image); ++ ++ return GTK_WIDGET (row); ++} ++ ++static void ++cc_wwan_mode_dialog_update (CcWwanModeDialog *self) ++{ ++ MMModemMode allowed; ++ MMModemMode modes[][2] = { ++ {MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G}, ++ {MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, 0}, ++ {MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, MM_MODEM_MODE_4G}, ++ {MM_MODEM_MODE_3G | MM_MODEM_MODE_4G, 0}, ++ {MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, MM_MODEM_MODE_3G}, ++ {MM_MODEM_MODE_2G | MM_MODEM_MODE_3G, 0}, ++ {MM_MODEM_MODE_4G, 0}, ++ {MM_MODEM_MODE_3G, 0}, ++ {MM_MODEM_MODE_2G, 0}, ++ }; ++ size_t i; ++ ++ g_assert (CC_IS_WWAN_MODE_DIALOG (self)); ++ ++ if (!cc_wwan_device_get_supported_modes (self->device, &allowed, NULL)) ++ { ++ g_warning ("No modes supported by modem"); ++ return; ++ } ++ ++ for (i = 0; i < G_N_ELEMENTS (modes); i++) ++ { ++ GtkWidget *row; ++ ++ if ((modes[i][0] & allowed) != modes[i][0]) ++ continue; ++ ++ if (modes[i][1] && !(modes[i][1] & allowed)) ++ continue; ++ ++ row = cc_wwan_mode_dialog_row_new (self, modes[i][0], modes[i][1]); ++ gtk_widget_show (row); ++ gtk_container_add (GTK_CONTAINER (self->network_mode_list), row); ++ } ++} ++ ++static void ++cc_wwan_mode_dialog_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ CcWwanModeDialog *self = CC_WWAN_MODE_DIALOG (object); ++ ++ switch (prop_id) ++ { ++ case PROP_DEVICE: ++ self->device = g_value_dup_object (value); ++ break; ++ ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } ++} ++ ++static void ++cc_wwan_mode_dialog_constructed (GObject *object) ++{ ++ CcWwanModeDialog *self = CC_WWAN_MODE_DIALOG (object); ++ ++ G_OBJECT_CLASS (cc_wwan_mode_dialog_parent_class)->constructed (object); ++ ++ if(!cc_wwan_device_get_current_mode (self->device, &self->allowed, &self->preferred)) ++ g_warning ("Can't get allowed and preferred wwan modes"); ++ ++ cc_wwan_mode_dialog_update (self); ++} ++ ++static void ++cc_wwan_mode_dialog_dispose (GObject *object) ++{ ++ CcWwanModeDialog *self = CC_WWAN_MODE_DIALOG (object); ++ ++ g_clear_object (&self->device); ++ ++ G_OBJECT_CLASS (cc_wwan_mode_dialog_parent_class)->dispose (object); ++} ++ ++static void ++cc_wwan_mode_dialog_update_mode (CcWwanModeRow *row, ++ CcWwanModeDialog *self) ++{ ++ if (self->allowed == row->allowed && self->preferred == row->preferred) ++ { ++ self->selected_row = row; ++ gtk_widget_show (GTK_WIDGET (row->ok_emblem)); ++ } ++ else ++ gtk_widget_hide (GTK_WIDGET (row->ok_emblem)); ++} ++ ++static void ++cc_wwan_mode_dialog_show (GtkWidget *widget) ++{ ++ CcWwanModeDialog *self = CC_WWAN_MODE_DIALOG (widget); ++ ++ if(!cc_wwan_device_get_current_mode (self->device, &self->allowed, &self->preferred)) ++ { ++ g_warning ("Can't get allowed and preferred wwan modes"); ++ goto end; ++ } ++ ++ gtk_container_foreach (GTK_CONTAINER (self->network_mode_list), ++ (GtkCallback)cc_wwan_mode_dialog_update_mode, ++ self); ++ end: ++ GTK_WIDGET_CLASS (cc_wwan_mode_dialog_parent_class)->show (widget); ++} ++ ++static void ++cc_wwan_mode_dialog_class_init (CcWwanModeDialogClass *klass) ++{ ++ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->set_property = cc_wwan_mode_dialog_set_property; ++ object_class->constructed = cc_wwan_mode_dialog_constructed; ++ object_class->dispose = cc_wwan_mode_dialog_dispose; ++ ++ widget_class->show = cc_wwan_mode_dialog_show; ++ ++ properties[PROP_DEVICE] = ++ g_param_spec_object ("device", ++ "Device", ++ "The WWAN Device", ++ CC_TYPE_WWAN_DEVICE, ++ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); ++ ++ g_object_class_install_properties (object_class, N_PROPS, properties); ++ ++ gtk_widget_class_set_template_from_resource (widget_class, ++ "/org/gnome/control-center/wwan/cc-wwan-mode-dialog.ui"); ++ ++ gtk_widget_class_bind_template_child (widget_class, CcWwanModeDialog, network_mode_list); ++ ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_mode_changed_cb); ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_mode_dialog_ok_clicked_cb); ++} ++ ++static void ++cc_wwan_mode_dialog_init (CcWwanModeDialog *self) ++{ ++ gtk_widget_init_template (GTK_WIDGET (self)); ++ ++ gtk_list_box_set_header_func (self->network_mode_list, ++ cc_list_box_update_header_func, ++ NULL, NULL); ++} ++ ++CcWwanModeDialog * ++cc_wwan_mode_dialog_new (GtkWindow *parent_window, ++ CcWwanDevice *device) ++{ ++ g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL); ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (device), NULL); ++ ++ return g_object_new (CC_TYPE_WWAN_MODE_DIALOG, ++ "transient-for", parent_window, ++ "use-header-bar", 1, ++ "device", device, ++ NULL); ++} +diff --git a/panels/wwan/cc-wwan-mode-dialog.h b/panels/wwan/cc-wwan-mode-dialog.h +new file mode 100644 +index 000000000..2399f0b7b +--- /dev/null ++++ b/panels/wwan/cc-wwan-mode-dialog.h +@@ -0,0 +1,40 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-mode-dialog.h ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#pragma once ++ ++#include ++#include ++ ++#include "cc-wwan-device.h" ++ ++G_BEGIN_DECLS ++ ++#define CC_TYPE_WWAN_MODE_DIALOG (cc_wwan_mode_dialog_get_type()) ++G_DECLARE_FINAL_TYPE (CcWwanModeDialog, cc_wwan_mode_dialog, CC, WWAN_MODE_DIALOG, GtkDialog) ++ ++CcWwanModeDialog *cc_wwan_mode_dialog_new (GtkWindow *parent_window, ++ CcWwanDevice *device); ++ ++G_END_DECLS +diff --git a/panels/wwan/cc-wwan-mode-dialog.ui b/panels/wwan/cc-wwan-mode-dialog.ui +new file mode 100644 +index 000000000..e0a924a39 +--- /dev/null ++++ b/panels/wwan/cc-wwan-mode-dialog.ui +@@ -0,0 +1,57 @@ ++ ++ ++ ++ +diff --git a/panels/wwan/cc-wwan-network-dialog.c b/panels/wwan/cc-wwan-network-dialog.c +new file mode 100644 +index 000000000..1c8883b88 +--- /dev/null ++++ b/panels/wwan/cc-wwan-network-dialog.c +@@ -0,0 +1,443 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-network-dialog.c ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#undef G_LOG_DOMAIN ++#define G_LOG_DOMAIN "cc-wwan-network-dialog" ++ ++#include ++#include ++#include ++ ++#include "list-box-helper.h" ++#include "cc-list-row.h" ++#include "cc-wwan-errors-private.h" ++#include "cc-wwan-network-dialog.h" ++#include "cc-wwan-resources.h" ++ ++/** ++ * @short_description: WWAN network operator selection dialog ++ */ ++ ++#define CC_TYPE_WWAN_NETWORK_ROW (cc_wwan_network_row_get_type()) ++G_DECLARE_FINAL_TYPE (CcWwanNetworkRow, cc_wwan_network_row, CC, WWAN_NETWORK_ROW, GtkListBoxRow) ++ ++struct _CcWwanNetworkDialog ++{ ++ GtkDialog parent_instance; ++ ++ CcListRow *automatic_row; ++ GtkButton *button_apply; ++ GtkSpinner *loading_spinner; ++ GtkBox *network_search_title; ++ GtkLabel *notification_label; ++ GtkRevealer *notification_revealer; ++ GtkListBox *operator_list_box; ++ GtkButton *refresh_button; ++ ++ CcWwanDevice *device; ++ GList *operator_list; ++ ++ CcWwanNetworkRow *selected_row; ++ ++ GCancellable *search_cancellable; ++ ++ guint revealer_timeout_id; ++ gboolean no_update_network; ++}; ++ ++G_DEFINE_TYPE (CcWwanNetworkDialog, cc_wwan_network_dialog, GTK_TYPE_DIALOG) ++ ++ ++enum { ++ PROP_0, ++ PROP_DEVICE, ++ N_PROPS ++}; ++ ++static GParamSpec *properties[N_PROPS]; ++ ++struct _CcWwanNetworkRow ++{ ++ GtkListBoxRow parent_instance; ++ GtkImage *ok_emblem; ++ gchar *operator_code; ++}; ++ ++G_DEFINE_TYPE (CcWwanNetworkRow, cc_wwan_network_row, GTK_TYPE_LIST_BOX_ROW) ++ ++static void ++cc_wwan_network_row_finalize (GObject *object) ++{ ++ CcWwanNetworkRow *row = (CcWwanNetworkRow *)object; ++ ++ g_free (row->operator_code); ++ ++ G_OBJECT_CLASS (cc_wwan_network_row_parent_class)->finalize (object); ++} ++ ++static void ++cc_wwan_network_row_class_init (CcWwanNetworkRowClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->finalize = cc_wwan_network_row_finalize; ++} ++ ++static void ++cc_wwan_network_row_init (CcWwanNetworkRow *row) ++{ ++} ++ ++static void ++cc_wwan_on_notification_closed (CcWwanNetworkDialog *self, ++ GtkWidget *button) ++{ ++ g_assert (CC_IS_WWAN_NETWORK_DIALOG (self)); ++ ++ gtk_revealer_set_reveal_child (GTK_REVEALER (self->notification_revealer), FALSE); ++ ++ if (self->revealer_timeout_id != 0) ++ g_source_remove (self->revealer_timeout_id); ++ ++ self->revealer_timeout_id = 0; ++} ++ ++static gboolean ++cc_wwan_on_notification_timeout (gpointer user_data) ++{ ++ cc_wwan_on_notification_closed (user_data, NULL); ++ ++ return G_SOURCE_REMOVE; ++} ++ ++static void ++cc_wwan_network_changed_cb (CcWwanNetworkDialog *self, ++ CcWwanNetworkRow *row) ++{ ++ if (row == self->selected_row) ++ return; ++ ++ gtk_widget_set_sensitive (GTK_WIDGET (self->button_apply), TRUE); ++ gtk_widget_show (GTK_WIDGET (row->ok_emblem)); ++ ++ if (self->selected_row) ++ gtk_widget_hide (GTK_WIDGET (self->selected_row->ok_emblem)); ++ ++ self->selected_row = row; ++} ++ ++/* ++ * cc_wwan_network_dialog_row_new: ++ * @self: a #CcWwanNetworkDialog ++ * @operator_name: (transfer full): The long operator name ++ * @operator_id: (transfer full): operator id ++ */ ++static CcWwanNetworkRow * ++cc_wwan_network_dialog_row_new (CcWwanNetworkDialog *self, ++ const gchar *operator_name, ++ const gchar *operator_code) ++{ ++ CcWwanNetworkRow *row; ++ GtkWidget *box, *label, *image; ++ ++ row = g_object_new (CC_TYPE_WWAN_NETWORK_ROW, NULL); ++ ++ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); ++ gtk_widget_show (box); ++ g_object_set (box, "margin", 18, NULL); ++ gtk_container_add (GTK_CONTAINER (row), box); ++ ++ label = gtk_label_new (operator_name); ++ gtk_widget_show (label); ++ gtk_widget_set_hexpand (label, TRUE); ++ gtk_widget_set_halign (label, GTK_ALIGN_START); ++ gtk_container_add (GTK_CONTAINER (box), label); ++ ++ image = gtk_image_new_from_icon_name ("emblem-ok-symbolic", GTK_ICON_SIZE_BUTTON); ++ row->ok_emblem = GTK_IMAGE (image); ++ gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (row->ok_emblem)); ++ ++ row->operator_code = g_strdup (operator_code); ++ ++ return row; ++} ++ ++static void ++cc_wwan_network_dialog_update_current_network (CcWwanNetworkDialog *self) ++{ ++ CcWwanNetworkRow *row; ++ const gchar *operator_name; ++ ++ operator_name = cc_wwan_device_get_operator_name (self->device); ++ ++ if (!operator_name || operator_name[0] == '\0') ++ return; ++ ++ gtk_container_foreach (GTK_CONTAINER (self->operator_list_box), ++ (GtkCallback)gtk_widget_destroy, NULL); ++ ++ row = cc_wwan_network_dialog_row_new (self, operator_name, ""); ++ self->selected_row = row; ++ gtk_container_add (GTK_CONTAINER (self->operator_list_box), GTK_WIDGET (row)); ++ gtk_widget_show_all (GTK_WIDGET (self->operator_list_box)); ++} ++ ++static void ++cc_wwan_network_dialog_update (CcWwanNetworkDialog *self) ++{ ++ CcWwanNetworkRow *row; ++ GList *item; ++ const gchar *operator_code, *operator_name; ++ ++ gtk_container_foreach (GTK_CONTAINER (self->operator_list_box), ++ (GtkCallback)gtk_widget_destroy, NULL); ++ ++ for (item = self->operator_list; item; item = item->next) ++ { ++ operator_code = mm_modem_3gpp_network_get_operator_code (item->data); ++ operator_name = mm_modem_3gpp_network_get_operator_long (item->data); ++ ++ row = cc_wwan_network_dialog_row_new (self, operator_name, operator_code); ++ gtk_widget_show (GTK_WIDGET (row)); ++ gtk_container_add (GTK_CONTAINER (self->operator_list_box), GTK_WIDGET (row)); ++ } ++} ++ ++static void ++cc_wwan_network_scan_complete_cb (GObject *object, ++ GAsyncResult *result, ++ gpointer user_data) ++{ ++ g_autoptr(CcWwanNetworkDialog) self = user_data; ++ g_autoptr(GError) error = NULL; ++ ++ if (self->operator_list) ++ g_list_free_full (self->operator_list, (GDestroyNotify)mm_modem_3gpp_network_free); ++ ++ gtk_widget_set_sensitive (GTK_WIDGET (self->refresh_button), TRUE); ++ gtk_spinner_stop (self->loading_spinner); ++ self->operator_list = cc_wwan_device_scan_networks_finish (self->device, result, &error); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->operator_list_box), !error); ++ ++ if (!error) ++ { ++ cc_wwan_network_dialog_update (self); ++ gtk_widget_show (GTK_WIDGET (self->operator_list_box)); ++ } ++ else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) ++ { ++ self->no_update_network = TRUE; ++ gtk_widget_activate (GTK_WIDGET (self->automatic_row)); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->operator_list_box), FALSE); ++ ++ gtk_label_set_label (self->notification_label, ++ cc_wwan_error_get_message (error)); ++ gtk_revealer_set_reveal_child (self->notification_revealer, TRUE); ++ self->revealer_timeout_id = g_timeout_add_seconds (5, cc_wwan_on_notification_timeout, self); ++ ++ gtk_widget_show (GTK_WIDGET (self->operator_list_box)); ++ g_warning ("Error: scanning networks failed: %s", error->message); ++ } ++} ++ ++static void ++cc_wwan_network_dialog_refresh_networks (CcWwanNetworkDialog *self) ++{ ++ gtk_widget_set_sensitive (GTK_WIDGET (self->refresh_button), FALSE); ++ gtk_spinner_start (self->loading_spinner); ++ cc_wwan_device_scan_networks (self->device, self->search_cancellable, ++ (GAsyncReadyCallback)cc_wwan_network_scan_complete_cb, ++ g_object_ref (self)); ++} ++ ++static void ++cc_wwan_network_dialog_apply_clicked_cb (CcWwanNetworkDialog *self) ++{ ++ gboolean is_auto; ++ ++ g_assert (CC_IS_WWAN_NETWORK_DIALOG (self)); ++ ++ is_auto = cc_list_row_get_active (self->automatic_row); ++ ++ if (is_auto) ++ cc_wwan_device_register_network (self->device, "", NULL, NULL, NULL); ++ else if (self->selected_row) ++ cc_wwan_device_register_network (self->device, self->selected_row->operator_code, NULL, NULL, self); ++ else ++ g_warn_if_reached (); ++ ++ gtk_widget_hide (GTK_WIDGET (self)); ++} ++ ++static void ++cc_wwan_auto_network_changed_cb (CcWwanNetworkDialog *self, ++ GParamSpec *pspec, ++ CcListRow *auto_network_row) ++{ ++ gboolean is_auto; ++ ++ g_assert (CC_IS_WWAN_NETWORK_DIALOG (self)); ++ g_assert (CC_IS_LIST_ROW (auto_network_row)); ++ ++ is_auto = cc_list_row_get_active (auto_network_row); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->button_apply), is_auto); ++ ++ if (self->no_update_network) ++ { ++ self->no_update_network = FALSE; ++ return; ++ } ++ ++ self->selected_row = NULL; ++ gtk_widget_set_visible (GTK_WIDGET (self->network_search_title), !is_auto); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->operator_list_box), !is_auto); ++ gtk_widget_hide (GTK_WIDGET (self->operator_list_box)); ++ ++ if (is_auto) ++ { ++ g_cancellable_cancel (self->search_cancellable); ++ g_cancellable_reset (self->search_cancellable); ++ } ++ else ++ { ++ cc_wwan_network_dialog_refresh_networks (self); ++ } ++} ++ ++static void ++cc_wwan_network_dialog_show (GtkWidget *widget) ++{ ++ CcWwanNetworkDialog *self = (CcWwanNetworkDialog *)widget; ++ gboolean is_auto; ++ ++ is_auto = cc_wwan_device_is_auto_network (self->device); ++ ++ g_object_set (self->automatic_row, "active", is_auto, NULL); ++ ++ cc_wwan_network_dialog_update_current_network (self); ++ ++ GTK_WIDGET_CLASS (cc_wwan_network_dialog_parent_class)->show (widget); ++} ++ ++static void ++cc_wwan_network_dialog_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ CcWwanNetworkDialog *self = (CcWwanNetworkDialog *)object; ++ ++ switch (prop_id) ++ { ++ case PROP_DEVICE: ++ self->device = g_value_dup_object (value); ++ break; ++ ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } ++} ++ ++static void ++cc_wwan_network_dialog_dispose (GObject *object) ++{ ++ CcWwanNetworkDialog *self = (CcWwanNetworkDialog *)object; ++ ++ if (self->revealer_timeout_id != 0) ++ g_source_remove (self->revealer_timeout_id); ++ ++ self->revealer_timeout_id = 0; ++ ++ g_cancellable_cancel (self->search_cancellable); ++ ++ g_clear_object (&self->search_cancellable); ++ g_clear_object (&self->device); ++ ++ G_OBJECT_CLASS (cc_wwan_network_dialog_parent_class)->dispose (object); ++} ++ ++static void ++cc_wwan_network_dialog_class_init (CcWwanNetworkDialogClass *klass) ++{ ++ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->set_property = cc_wwan_network_dialog_set_property; ++ object_class->dispose = cc_wwan_network_dialog_dispose; ++ ++ widget_class->show = cc_wwan_network_dialog_show; ++ ++ properties[PROP_DEVICE] = ++ g_param_spec_object ("device", ++ "Device", ++ "The WWAN Device", ++ CC_TYPE_WWAN_DEVICE, ++ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); ++ ++ g_object_class_install_properties (object_class, N_PROPS, properties); ++ ++ gtk_widget_class_set_template_from_resource (widget_class, ++ "/org/gnome/control-center/wwan/cc-wwan-network-dialog.ui"); ++ ++ gtk_widget_class_bind_template_child (widget_class, CcWwanNetworkDialog, automatic_row); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanNetworkDialog, button_apply); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanNetworkDialog, loading_spinner); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanNetworkDialog, network_search_title); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanNetworkDialog, notification_label); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanNetworkDialog, notification_revealer); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanNetworkDialog, operator_list_box); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanNetworkDialog, refresh_button); ++ ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_network_changed_cb); ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_on_notification_closed); ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_auto_network_changed_cb); ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_network_dialog_refresh_networks); ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_network_dialog_apply_clicked_cb); ++} ++ ++static void ++cc_wwan_network_dialog_init (CcWwanNetworkDialog *self) ++{ ++ gtk_widget_init_template (GTK_WIDGET (self)); ++ ++ self->search_cancellable = g_cancellable_new (); ++ ++ gtk_list_box_set_header_func (self->operator_list_box, ++ cc_list_box_update_header_func, ++ NULL, NULL); ++} ++ ++CcWwanNetworkDialog * ++cc_wwan_network_dialog_new (GtkWindow *parent_window, ++ CcWwanDevice *device) ++{ ++ g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL); ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (device), NULL); ++ ++ return g_object_new (CC_TYPE_WWAN_NETWORK_DIALOG, ++ "transient-for", parent_window, ++ "use-header-bar", 1, ++ "device", device, ++ NULL); ++} +diff --git a/panels/wwan/cc-wwan-network-dialog.h b/panels/wwan/cc-wwan-network-dialog.h +new file mode 100644 +index 000000000..1818a0876 +--- /dev/null ++++ b/panels/wwan/cc-wwan-network-dialog.h +@@ -0,0 +1,40 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-network-dialog.h ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#pragma once ++ ++#include ++#include ++ ++#include "cc-wwan-device.h" ++ ++G_BEGIN_DECLS ++ ++#define CC_TYPE_WWAN_NETWORK_DIALOG (cc_wwan_network_dialog_get_type()) ++G_DECLARE_FINAL_TYPE (CcWwanNetworkDialog, cc_wwan_network_dialog, CC, WWAN_NETWORK_DIALOG, GtkDialog) ++ ++CcWwanNetworkDialog *cc_wwan_network_dialog_new (GtkWindow *parent_window, ++ CcWwanDevice *device); ++ ++G_END_DECLS +diff --git a/panels/wwan/cc-wwan-network-dialog.ui b/panels/wwan/cc-wwan-network-dialog.ui +new file mode 100644 +index 000000000..03223b333 +--- /dev/null ++++ b/panels/wwan/cc-wwan-network-dialog.ui +@@ -0,0 +1,188 @@ ++ ++ ++ ++ +diff --git a/panels/wwan/cc-wwan-panel.c b/panels/wwan/cc-wwan-panel.c +new file mode 100644 +index 000000000..963c46900 +--- /dev/null ++++ b/panels/wwan/cc-wwan-panel.c +@@ -0,0 +1,929 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-panel.c ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#undef G_LOG_DOMAIN ++#define G_LOG_DOMAIN "cc-wwan-panel" ++ ++#include ++#include ++#include ++ ++#include "cc-wwan-device.h" ++#include "cc-wwan-data.h" ++#include "cc-wwan-device-page.h" ++#include "cc-wwan-panel.h" ++#include "cc-wwan-resources.h" ++ ++#include "shell/cc-application.h" ++#include "shell/cc-debug.h" ++#include "shell/cc-object-storage.h" ++ ++typedef enum { ++ OPERATION_NULL, ++ OPERATION_SHOW_DEVICE, ++} CmdlineOperation; ++ ++struct _CcWwanPanel ++{ ++ CcPanel parent_instance; ++ ++ GtkListBox *data_select_listbox; ++ GtkPopover *data_select_popover; ++ GtkLabel *data_sim_label; ++ GtkListBox *data_sim_select_listbox; ++ GtkStack *devices_stack; ++ GtkStackSwitcher *devices_switcher; ++ GtkSwitch *enable_switch; ++ GtkStack *main_stack; ++ GtkRevealer *multi_device_revealer; ++ GtkLabel *notification_label; ++ GtkRevealer *notification_revealer; ++ ++ GDBusProxy *rfkill_proxy; ++ MMManager *mm_manager; ++ NMClient *nm_client; ++ ++ /* The default device that will be used for data */ ++ CcWwanDevice *data_device; ++ GListStore *devices; ++ GListStore *data_devices; ++ GCancellable *cancellable; ++ ++ CmdlineOperation arg_operation; ++ char *arg_device; ++ ++ guint revealer_timeout_id; ++}; ++ ++enum { ++ PROP_0, ++ PROP_PARAMETERS ++}; ++ ++G_DEFINE_TYPE (CcWwanPanel, cc_wwan_panel, CC_TYPE_PANEL) ++ ++ ++#define CC_TYPE_DATA_DEVICE_ROW (cc_data_device_row_get_type()) ++G_DECLARE_FINAL_TYPE (CcDataDeviceRow, cc_data_device_row, CC, DATA_DEVICE_ROW, GtkListBoxRow) ++ ++struct _CcDataDeviceRow ++{ ++ GtkListBoxRow parent_instance; ++ ++ GtkImage *ok_emblem; ++ CcWwanDevice *device; ++}; ++ ++G_DEFINE_TYPE (CcDataDeviceRow, cc_data_device_row, GTK_TYPE_LIST_BOX_ROW) ++ ++static void ++cc_data_device_row_class_init (CcDataDeviceRowClass *klass) ++{ ++} ++ ++static void ++cc_data_device_row_init (CcDataDeviceRow *row) ++{ ++} ++ ++static CmdlineOperation ++cmdline_operation_from_string (const gchar *str) ++{ ++ if (g_strcmp0 (str, "show-device") == 0) ++ return OPERATION_SHOW_DEVICE; ++ ++ g_warning ("Invalid additional argument %s", str); ++ return OPERATION_NULL; ++} ++ ++static void ++reset_command_line_args (CcWwanPanel *self) ++{ ++ self->arg_operation = OPERATION_NULL; ++ g_clear_pointer (&self->arg_device, g_free); ++} ++ ++static gboolean ++verify_argv (CcWwanPanel *self, ++ const char **args) ++{ ++ switch (self->arg_operation) ++ { ++ case OPERATION_SHOW_DEVICE: ++ if (self->arg_device == NULL) ++ { ++ g_warning ("Operation %s requires an object path", args[0]); ++ return FALSE; ++ } ++ default: ++ return TRUE; ++ } ++} ++ ++static void ++handle_argv (CcWwanPanel *self) ++{ ++ if (self->arg_operation == OPERATION_SHOW_DEVICE && ++ self->arg_operation) ++ { ++ g_autoptr(GList) pages = NULL; ++ ++ pages = gtk_container_get_children (GTK_CONTAINER (self->devices_stack)); ++ ++ for (GList *page = pages; page; page = page->next) ++ { ++ CcWwanDevice *device; ++ ++ device = cc_wwan_device_page_get_device (page->data); ++ ++ if (g_strcmp0 (cc_wwan_device_get_path (device), self->arg_device) == 0) ++ { ++ gtk_stack_set_visible_child (GTK_STACK (self->devices_stack), page->data); ++ g_debug ("Opening device %s", self->arg_device); ++ reset_command_line_args (self); ++ return; ++ } ++ } ++ } ++} ++ ++static gboolean ++wwan_panel_device_is_supported (GDBusObject *object) ++{ ++ MMObject *mm_object; ++ MMModem *modem; ++ MMModemCapability capability; ++ ++ g_assert (G_IS_DBUS_OBJECT (object)); ++ ++ mm_object = MM_OBJECT (object); ++ modem = mm_object_get_modem (mm_object); ++ capability = mm_modem_get_current_capabilities (modem); ++ ++ /* We Support only GSM/3G/LTE devices */ ++ if (capability & (MM_MODEM_CAPABILITY_GSM_UMTS | ++ MM_MODEM_CAPABILITY_LTE | ++ MM_MODEM_CAPABILITY_LTE_ADVANCED)) ++ return TRUE; ++ ++ return FALSE; ++} ++ ++static gint ++wwan_model_get_item_index (GListModel *model, ++ gpointer item) ++{ ++ guint i, n_items; ++ ++ g_assert (G_IS_LIST_MODEL (model)); ++ g_assert (G_IS_OBJECT (item)); ++ ++ n_items = g_list_model_get_n_items (model); ++ ++ for (i = 0; i < n_items; i++) ++ { ++ g_autoptr(GObject) object = NULL; ++ ++ object = g_list_model_get_item (model, i); ++ ++ if (object == item) ++ return i; ++ } ++ ++ return -1; ++} ++ ++static CcWwanDevice * ++wwan_model_get_item_from_mm_object (GListModel *model, ++ MMObject *mm_object) ++{ ++ const gchar *modem_path, *device_path; ++ guint i, n_items; ++ ++ n_items = g_list_model_get_n_items (model); ++ modem_path = mm_object_get_path (mm_object); ++ ++ for (i = 0; i < n_items; i++) ++ { ++ g_autoptr(CcWwanDevice) device = NULL; ++ ++ device = g_list_model_get_item (model, i); ++ device_path = cc_wwan_device_get_path (device); ++ ++ if (g_str_equal (modem_path, device_path)) ++ return g_steal_pointer (&device); ++ } ++ ++ return NULL; ++} ++ ++static CcDataDeviceRow * ++cc_data_device_row_new (CcWwanDevice *device, ++ CcWwanPanel *self) ++{ ++ CcDataDeviceRow *row; ++ GtkWidget *box, *label, *image; ++ g_autofree gchar *operator = NULL; ++ gint index; ++ ++ row = g_object_new (CC_TYPE_DATA_DEVICE_ROW, NULL); ++ row->device = device; ++ ++ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); ++ gtk_widget_show (box); ++ g_object_set (box, "margin", 12, NULL); ++ gtk_container_add (GTK_CONTAINER (row), box); ++ ++ index = wwan_model_get_item_index (G_LIST_MODEL (self->devices), device); ++ operator = g_strdup_printf ("SIM %d", index + 1); ++ label = gtk_label_new (operator); ++ gtk_widget_show (label); ++ gtk_container_add (GTK_CONTAINER (box), label); ++ ++ image = gtk_image_new_from_icon_name ("emblem-ok-symbolic", GTK_ICON_SIZE_BUTTON); ++ row->ok_emblem = GTK_IMAGE (image); ++ gtk_container_add (GTK_CONTAINER (box), image); ++ ++ return row; ++} ++ ++static void ++wwan_notification_close_clicked_cb (CcWwanPanel *self) ++{ ++ gtk_revealer_set_reveal_child (self->notification_revealer, FALSE); ++ ++ if (self->revealer_timeout_id != 0) ++ g_source_remove (self->revealer_timeout_id); ++ ++ self->revealer_timeout_id = 0; ++} ++ ++static void ++wwan_data_selector_clicked_cb (CcWwanPanel *self) ++{ ++ if (gtk_widget_is_visible (GTK_WIDGET (self->data_select_popover))) ++ gtk_popover_popdown (self->data_select_popover); ++ else ++ gtk_popover_popup (self->data_select_popover); ++} ++ ++static void ++cc_wwan_panel_update_data_selection (CcDataDeviceRow *row, ++ CcWwanPanel *self) ++{ ++ if (self->data_device == row->device) ++ { ++ g_autofree gchar *str = NULL; ++ gint i; ++ ++ i = wwan_model_get_item_index (G_LIST_MODEL (self->devices), row->device); ++ g_assert (i >= 0); ++ ++ /* Human index starts from 1 */ ++ str = g_strdup_printf ("SIM %d", i + 1); ++ gtk_label_set_label (self->data_sim_label, str); ++ ++ gtk_widget_show (GTK_WIDGET (row->ok_emblem)); ++ } ++ else ++ { ++ gtk_widget_hide (GTK_WIDGET (row->ok_emblem)); ++ } ++} ++ ++static void ++cc_wwan_data_item_activate_cb (CcWwanPanel *self, ++ CcDataDeviceRow *row) ++{ ++ CcWwanData *data; ++ ++ gtk_popover_popdown (self->data_select_popover); ++ ++ if (row->device == self->data_device) ++ return; ++ ++ /* Set lower priority for previously selected APN */ ++ data = cc_wwan_device_get_data (self->data_device); ++ cc_wwan_data_set_priority (data, CC_WWAN_APN_PRIORITY_LOW); ++ cc_wwan_data_save_settings (data, NULL, NULL, NULL); ++ ++ /* Set high priority for currently selected APN */ ++ data = cc_wwan_device_get_data (row->device); ++ cc_wwan_data_set_priority (data, CC_WWAN_APN_PRIORITY_HIGH); ++ cc_wwan_data_save_settings (data, NULL, NULL, NULL); ++ ++ self->data_device = row->device; ++ gtk_container_foreach (GTK_CONTAINER (self->data_select_listbox), ++ (GtkCallback) cc_wwan_panel_update_data_selection, self); ++} ++ ++static void ++wwan_on_airplane_off_clicked_cb (CcWwanPanel *self) ++{ ++ g_debug ("Airplane Mode Off clicked, disabling airplane mode"); ++ g_dbus_proxy_call (self->rfkill_proxy, ++ "org.freedesktop.DBus.Properties.Set", ++ g_variant_new_parsed ("('org.gnome.SettingsDaemon.Rfkill'," ++ "'AirplaneMode', %v)", ++ g_variant_new_boolean (FALSE)), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, ++ self->cancellable, ++ NULL, ++ NULL); ++} ++ ++static gboolean ++cc_wwan_panel_get_cached_dbus_property (GDBusProxy *proxy, ++ const gchar *property) ++{ ++ g_autoptr(GVariant) result = NULL; ++ ++ g_assert (G_IS_DBUS_PROXY (proxy)); ++ g_assert (property && *property); ++ ++ result = g_dbus_proxy_get_cached_property (proxy, property); ++ g_assert (!result || g_variant_is_of_type (result, G_VARIANT_TYPE_BOOLEAN)); ++ ++ return result ? g_variant_get_boolean (result) : FALSE; ++} ++ ++static void ++cc_wwan_panel_update_view (CcWwanPanel *self) ++{ ++ gboolean has_airplane, is_airplane = FALSE, enabled = FALSE; ++ ++ has_airplane = cc_wwan_panel_get_cached_dbus_property (self->rfkill_proxy, "HasAirplaneMode"); ++ has_airplane &= cc_wwan_panel_get_cached_dbus_property (self->rfkill_proxy, "ShouldShowAirplaneMode"); ++ ++ if (has_airplane) ++ { ++ is_airplane = cc_wwan_panel_get_cached_dbus_property (self->rfkill_proxy, "AirplaneMode"); ++ is_airplane |= cc_wwan_panel_get_cached_dbus_property (self->rfkill_proxy, "HardwareAirplaneMode"); ++ } ++ ++ if (self->nm_client) ++ enabled = nm_client_wwan_get_enabled (self->nm_client); ++ ++ if (has_airplane && is_airplane) ++ gtk_stack_set_visible_child_name (self->main_stack, "airplane-mode"); ++ else if (enabled && g_list_model_get_n_items (G_LIST_MODEL (self->devices)) > 0) ++ gtk_stack_set_visible_child_name (self->main_stack, "device-settings"); ++ else ++ gtk_stack_set_visible_child_name (self->main_stack, "no-wwan-devices"); ++ ++ gtk_widget_set_sensitive (GTK_WIDGET (self->enable_switch), !is_airplane); ++ ++ if (enabled) ++ gtk_revealer_set_reveal_child (self->multi_device_revealer, ++ g_list_model_get_n_items (G_LIST_MODEL (self->devices)) > 1); ++} ++ ++static void ++cc_wwan_panel_on_notification_closed (CcWwanPanel *self, ++ GtkWidget *button) ++{ ++ gtk_revealer_set_reveal_child (self->notification_revealer, FALSE); ++ ++ if (self->revealer_timeout_id != 0) ++ g_source_remove (self->revealer_timeout_id); ++ ++ self->revealer_timeout_id = 0; ++} ++ ++static gboolean ++cc_wwan_panel_on_notification_timeout (gpointer user_data) ++{ ++ cc_wwan_panel_on_notification_closed (user_data, NULL); ++ ++ return G_SOURCE_REMOVE; ++} ++ ++static void ++cc_wwan_panel_notification_changed_cb (CcWwanPanel *self) ++{ ++ const gchar *label; ++ ++ label = gtk_label_get_label (self->notification_label); ++ ++ if (label && *label) ++ { ++ gtk_revealer_set_reveal_child (self->notification_revealer, TRUE); ++ self->revealer_timeout_id = g_timeout_add_seconds (5, cc_wwan_panel_on_notification_timeout, self); ++ } ++ else ++ { ++ cc_wwan_panel_on_notification_closed (self, NULL); ++ } ++} ++ ++static void ++cc_wwan_panel_add_device (CcWwanPanel *self, ++ CcWwanDevice *device) ++{ ++ CcWwanDevicePage *device_page; ++ g_autofree gchar *operator_name = NULL; ++ g_autofree gchar *stack_name = NULL; ++ guint n_items; ++ ++ g_list_store_append (self->devices, device); ++ ++ n_items = g_list_model_get_n_items (G_LIST_MODEL (self->devices)); ++ operator_name = g_strdup_printf (_("SIM %d"), n_items); ++ stack_name = g_strdup_printf ("sim-%d", n_items); ++ ++ device_page = cc_wwan_device_page_new (device, GTK_WIDGET (self->notification_label)); ++ cc_wwan_device_page_set_sim_index (device_page, n_items); ++ gtk_stack_add_titled (self->devices_stack, ++ GTK_WIDGET (device_page), stack_name, operator_name); ++} ++ ++static void ++cc_wwan_panel_update_page_title (CcWwanDevicePage *device_page, ++ CcWwanPanel *self) ++{ ++ g_autofree gchar *title = NULL; ++ g_autofree gchar *name = NULL; ++ CcWwanDevice *device; ++ GtkWidget *parent; ++ gint index; ++ ++ device = cc_wwan_device_page_get_device (device_page); ++ ++ parent = gtk_widget_get_parent (GTK_WIDGET (device_page)); ++ index = wwan_model_get_item_index (G_LIST_MODEL (self->devices), device); ++ ++ if (index == -1) ++ g_return_if_reached (); ++ ++ /* index starts with 0, but we need human readable index to be 1+ */ ++ cc_wwan_device_page_set_sim_index (device_page, index + 1); ++ title = g_strdup_printf (_("SIM %d"), index + 1); ++ name = g_strdup_printf ("sim-%d", index + 1); ++ gtk_container_child_set (GTK_CONTAINER (parent), ++ GTK_WIDGET (device_page), ++ "title", title, ++ "name", name, ++ NULL); ++} ++ ++static void ++cc_wwan_panel_remove_mm_object (CcWwanPanel *self, ++ MMObject *mm_object) ++{ ++ g_autoptr(CcWwanDevice) device = NULL; ++ GtkWidget *device_page; ++ g_autofree gchar *stack_name = NULL; ++ guint n_items; ++ gint index; ++ ++ device = wwan_model_get_item_from_mm_object (G_LIST_MODEL (self->devices), mm_object); ++ ++ if (!device) ++ return; ++ ++ index = wwan_model_get_item_index (G_LIST_MODEL (self->data_devices), device); ++ if (index != -1) ++ g_list_store_remove (self->data_devices, index); ++ ++ index = wwan_model_get_item_index (G_LIST_MODEL (self->devices), device); ++ if (index == -1) ++ return; ++ ++ g_list_store_remove (self->devices, index); ++ stack_name = g_strdup_printf ("sim-%d", index + 1); ++ device_page = gtk_stack_get_child_by_name (self->devices_stack, stack_name); ++ gtk_container_remove (GTK_CONTAINER (self->devices_stack), device_page); ++ ++ n_items = g_list_model_get_n_items (G_LIST_MODEL (self->data_devices)); ++ g_list_model_items_changed (G_LIST_MODEL (self->data_devices), 0, n_items, n_items); ++ gtk_container_foreach (GTK_CONTAINER (self->devices_stack), ++ (GtkCallback)cc_wwan_panel_update_page_title, ++ self); ++} ++ ++static void ++cc_wwan_panel_update_data_connections (CcWwanPanel *self) ++{ ++ CcWwanData *device_data, *active_data = NULL; ++ guint n_items; ++ gint i; ++ ++ /* ++ * We can’t predict the order in which the data of device is enabled. ++ * But we have to keep data store in the same order as device store. ++ * So let’s remove every data device and re-add. ++ */ ++ g_list_store_remove_all (self->data_devices); ++ n_items = g_list_model_get_n_items (G_LIST_MODEL (self->devices)); ++ ++ for (i = 0; i < n_items; i++) ++ { ++ g_autoptr(CcWwanDevice) device = NULL; ++ ++ device = g_list_model_get_item (G_LIST_MODEL (self->devices), i); ++ device_data = cc_wwan_device_get_data (device); ++ ++ if (!device_data) ++ continue; ++ ++ if ((!active_data || ++ cc_wwan_data_get_priority (device_data) > cc_wwan_data_get_priority (active_data)) && ++ cc_wwan_data_get_enabled (device_data)) ++ { ++ active_data = device_data; ++ self->data_device = device; ++ } ++ ++ if (cc_wwan_data_get_enabled (device_data)) ++ g_list_store_append (self->data_devices, device); ++ } ++ ++ gtk_widget_set_sensitive (GTK_WIDGET (self->data_sim_select_listbox), ++ g_list_model_get_n_items (G_LIST_MODEL (self->data_devices)) > 1); ++ if (active_data) ++ gtk_container_foreach (GTK_CONTAINER (self->data_select_listbox), ++ (GtkCallback)cc_wwan_panel_update_data_selection, self); ++ else ++ gtk_label_set_label (self->data_sim_label, ""); ++} ++ ++static void ++cc_wwan_panel_update_devices (CcWwanPanel *self) ++{ ++ GList *devices, *iter; ++ ++ devices = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (self->mm_manager)); ++ ++ for (iter = devices; iter; iter = iter->next) ++ { ++ MMObject *mm_object = iter->data; ++ CcWwanDevice *device; ++ ++ if(!wwan_panel_device_is_supported (iter->data)) ++ continue; ++ ++ device = cc_wwan_device_new (mm_object, G_OBJECT (self->nm_client)); ++ cc_wwan_panel_add_device (self, device); ++ g_signal_connect_object (device, "notify::has-data", ++ G_CALLBACK (cc_wwan_panel_update_data_connections), ++ self, G_CONNECT_SWAPPED); ++ ++ if (cc_wwan_device_get_data (device)) ++ g_list_store_append (self->data_devices, device); ++ } ++ ++ cc_wwan_panel_update_data_connections (self); ++ handle_argv (self); ++} ++ ++static void ++wwan_panel_device_added_cb (CcWwanPanel *self, ++ GDBusObject *object) ++{ ++ CcWwanDevice *device; ++ ++ if(!wwan_panel_device_is_supported (object)) ++ return; ++ ++ device = cc_wwan_device_new (MM_OBJECT (object), G_OBJECT (self->nm_client)); ++ cc_wwan_panel_add_device (self, device); ++ g_signal_connect_object (device, "notify::has-data", ++ G_CALLBACK (cc_wwan_panel_update_data_connections), ++ self, G_CONNECT_SWAPPED); ++ cc_wwan_panel_update_view (self); ++ handle_argv (self); ++} ++ ++static void ++wwan_panel_device_removed_cb (CcWwanPanel *self, ++ GDBusObject *object) ++{ ++ if (!wwan_panel_device_is_supported (object)) ++ return; ++ ++ cc_wwan_panel_remove_mm_object (self, MM_OBJECT (object)); ++ ++ gtk_revealer_set_reveal_child (self->multi_device_revealer, ++ g_list_model_get_n_items (G_LIST_MODEL (self->devices)) > 1); ++} ++ ++static GPtrArray * ++variant_av_to_string_array (GVariant *array) ++{ ++ GVariant *v; ++ GPtrArray *strv; ++ GVariantIter iter; ++ gsize count; ++ ++ count = g_variant_iter_init (&iter, array); ++ strv = g_ptr_array_sized_new (count + 1); ++ ++ while (g_variant_iter_next (&iter, "v", &v)) ++ { ++ g_ptr_array_add (strv, (gpointer)g_variant_get_string (v, NULL)); ++ g_variant_unref (v); ++ } ++ g_ptr_array_add (strv, NULL); /* NULL-terminate the strv data array */ ++ ++ return strv; ++} ++ ++static void ++cc_wwan_panel_set_property (GObject *object, ++ guint property_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ CcWwanPanel *self = CC_WWAN_PANEL (object); ++ ++ switch (property_id) ++ { ++ case PROP_PARAMETERS: ++ { ++ GVariant *parameters; ++ ++ reset_command_line_args (self); ++ ++ parameters = g_value_get_variant (value); ++ if (parameters) ++ { ++ g_autoptr(GPtrArray) array = NULL; ++ const gchar **args; ++ ++ array = variant_av_to_string_array (parameters); ++ args = (const gchar **) array->pdata; ++ ++ g_debug ("Invoked with operation %s", args[0]); ++ ++ if (args[0]) ++ self->arg_operation = cmdline_operation_from_string (args[0]); ++ if (args[0] && args[1]) ++ self->arg_device = g_strdup (args[1]); ++ ++ if (!verify_argv (self, (const char **) args)) ++ { ++ reset_command_line_args (self); ++ return; ++ } ++ g_debug ("Calling handle_argv() after setting property"); ++ handle_argv (self); ++ } ++ break; ++ } ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); ++ } ++} ++ ++static void ++cc_wwan_panel_constructed (GObject *object) ++{ ++ CcWwanPanel *self = (CcWwanPanel *)object; ++ ++ G_OBJECT_CLASS (cc_wwan_panel_parent_class)->constructed (object); ++ ++ cc_shell_embed_widget_in_header (cc_panel_get_shell (CC_PANEL (self)), ++ GTK_WIDGET (self->enable_switch), GTK_POS_RIGHT); ++ ++ if (self->nm_client) ++ { ++ g_object_bind_property (self->nm_client, "wwan-enabled", ++ self->enable_switch, "active", ++ G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); ++ } ++} ++ ++static void ++cc_wwan_panel_dispose (GObject *object) ++{ ++ CcWwanPanel *self = (CcWwanPanel *)object; ++ ++ if (self->revealer_timeout_id != 0) ++ g_source_remove (self->revealer_timeout_id); ++ ++ self->revealer_timeout_id = 0; ++ ++ g_cancellable_cancel (self->cancellable); ++ ++ g_clear_object (&self->devices); ++ g_clear_object (&self->data_devices); ++ g_clear_object (&self->mm_manager); ++ g_clear_object (&self->nm_client); ++ g_clear_object (&self->cancellable); ++ g_clear_object (&self->rfkill_proxy); ++ g_clear_pointer (&self->arg_device, g_free); ++ ++ G_OBJECT_CLASS (cc_wwan_panel_parent_class)->dispose (object); ++} ++ ++static void ++cc_wwan_panel_class_init (CcWwanPanelClass *klass) ++{ ++ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->set_property = cc_wwan_panel_set_property; ++ object_class->constructed = cc_wwan_panel_constructed; ++ object_class->dispose = cc_wwan_panel_dispose; ++ ++ g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters"); ++ ++ gtk_widget_class_set_template_from_resource (widget_class, ++ "/org/gnome/control-center/wwan/cc-wwan-panel.ui"); ++ ++ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, data_select_listbox); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, data_select_popover); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, data_sim_label); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, data_sim_select_listbox); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, devices_stack); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, devices_switcher); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, enable_switch); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, main_stack); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, multi_device_revealer); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, notification_label); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanPanel, notification_revealer); ++ ++ gtk_widget_class_bind_template_callback (widget_class, wwan_on_airplane_off_clicked_cb); ++ gtk_widget_class_bind_template_callback (widget_class, wwan_notification_close_clicked_cb); ++ gtk_widget_class_bind_template_callback (widget_class, wwan_data_selector_clicked_cb); ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_data_item_activate_cb); ++} ++ ++static void ++cc_wwan_panel_init (CcWwanPanel *self) ++{ ++ g_autoptr(GError) error = NULL; ++ ++ g_resources_register (cc_wwan_get_resource ()); ++ ++ gtk_widget_init_template (GTK_WIDGET (self)); ++ ++ self->cancellable = g_cancellable_new (); ++ self->devices = g_list_store_new (CC_TYPE_WWAN_DEVICE); ++ self->data_devices = g_list_store_new (CC_TYPE_WWAN_DEVICE); ++ gtk_list_box_bind_model (GTK_LIST_BOX (self->data_select_listbox), ++ G_LIST_MODEL (self->data_devices), ++ (GtkListBoxCreateWidgetFunc) cc_data_device_row_new, ++ self, NULL); ++ ++ g_signal_connect_object (self->notification_label, "notify::label", ++ G_CALLBACK (cc_wwan_panel_notification_changed_cb), ++ self, G_CONNECT_SWAPPED); ++ ++ if (cc_object_storage_has_object (CC_OBJECT_NMCLIENT)) ++ { ++ self->nm_client = cc_object_storage_get_object (CC_OBJECT_NMCLIENT); ++ g_signal_connect_object (self->nm_client, ++ "notify::wwan-enabled", ++ G_CALLBACK (cc_wwan_panel_update_view), ++ self, G_CONNECT_SWAPPED); ++ ++ } ++ else ++ { ++ g_warn_if_reached (); ++ } ++ ++ if (cc_object_storage_has_object ("CcObjectStorage::mm-manager")) ++ { ++ self->mm_manager = cc_object_storage_get_object ("CcObjectStorage::mm-manager"); ++ ++ g_signal_connect_object (self->mm_manager, "object-added", ++ G_CALLBACK (wwan_panel_device_added_cb), ++ self, G_CONNECT_SWAPPED); ++ g_signal_connect_object (self->mm_manager, "object-removed", ++ G_CALLBACK (wwan_panel_device_removed_cb), ++ self, G_CONNECT_SWAPPED); ++ ++ cc_wwan_panel_update_devices (self); ++ } ++ else ++ { ++ g_warn_if_reached (); ++ } ++ ++ /* Acquire Airplane Mode proxy */ ++ self->rfkill_proxy = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SESSION, ++ G_DBUS_PROXY_FLAGS_NONE, ++ "org.gnome.SettingsDaemon.Rfkill", ++ "/org/gnome/SettingsDaemon/Rfkill", ++ "org.gnome.SettingsDaemon.Rfkill", ++ self->cancellable, ++ &error); ++ ++ if (error) ++ { ++ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) ++ g_printerr ("Error creating rfkill proxy: %s\n", error->message); ++ } ++ else ++ { ++ g_signal_connect_object (self->rfkill_proxy, ++ "g-properties-changed", ++ G_CALLBACK (cc_wwan_panel_update_view), ++ self, G_CONNECT_SWAPPED); ++ ++ cc_wwan_panel_update_view (self); ++ } ++} ++ ++static void ++wwan_update_panel_visibility (MMManager *mm_manager) ++{ ++ CcApplication *application; ++ GList *devices; ++ gboolean has_wwan; ++ ++ g_assert (MM_IS_MANAGER (mm_manager)); ++ ++ CC_TRACE_MSG ("Updating WWAN panel visibility"); ++ ++ has_wwan = FALSE; ++ devices = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (mm_manager)); ++ ++ for (GList *item = devices; item != NULL; item = item->next) ++ { ++ if(wwan_panel_device_is_supported (item->data)) ++ { ++ has_wwan = TRUE; ++ break; ++ } ++ } ++ ++ /* Set the new visibility */ ++ application = CC_APPLICATION (g_application_get_default ()); ++ cc_shell_model_set_panel_visibility (cc_application_get_model (application), ++ "wwan", ++ has_wwan ? CC_PANEL_VISIBLE : CC_PANEL_VISIBLE_IN_SEARCH); ++ ++ g_debug ("WWAN panel visible: %s", has_wwan ? "yes" : "no"); ++ ++ g_list_free_full (devices, (GDestroyNotify)g_object_unref); ++} ++ ++void ++cc_wwan_panel_static_init_func (void) ++{ ++ g_autoptr(GDBusConnection) system_bus = NULL; ++ g_autoptr(MMManager) mm_manager = NULL; ++ g_autoptr(GError) error = NULL; ++ ++ /* ++ * There could be other modems that are only handled by rfkill, ++ * and not available via ModemManager. But as this panel ++ * makes use of ModemManager APIs, we only care devices ++ * supported by ModemManager. ++ */ ++ system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); ++ if (system_bus == NULL) ++ g_warning ("Error connecting to system D-Bus: %s", error->message); ++ else ++ mm_manager = mm_manager_new_sync (system_bus, ++ G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, ++ NULL, &error); ++ ++ if (mm_manager == NULL) ++ { ++ CcApplication *application; ++ ++ g_warning ("Error connecting to ModemManager: %s", error->message); ++ ++ application = CC_APPLICATION (g_application_get_default ()); ++ cc_shell_model_set_panel_visibility (cc_application_get_model (application), ++ "wwan", FALSE); ++ return; ++ } ++ else ++ { ++ cc_object_storage_add_object ("CcObjectStorage::mm-manager", mm_manager); ++ } ++ ++ g_debug ("Monitoring ModemManager for WWAN devices"); ++ ++ g_signal_connect (mm_manager, "object-added", G_CALLBACK (wwan_update_panel_visibility), NULL); ++ g_signal_connect (mm_manager, "object-removed", G_CALLBACK (wwan_update_panel_visibility), NULL); ++ ++ wwan_update_panel_visibility (mm_manager); ++} +diff --git a/panels/wwan/cc-wwan-panel.h b/panels/wwan/cc-wwan-panel.h +new file mode 100644 +index 000000000..57d2dae26 +--- /dev/null ++++ b/panels/wwan/cc-wwan-panel.h +@@ -0,0 +1,36 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-panel.h ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#pragma once ++ ++#include ++ ++G_BEGIN_DECLS ++ ++#define CC_TYPE_WWAN_PANEL (cc_wwan_panel_get_type()) ++G_DECLARE_FINAL_TYPE (CcWwanPanel, cc_wwan_panel, CC, WWAN_PANEL, CcPanel) ++ ++void cc_wwan_panel_static_init_func (void); ++ ++G_END_DECLS +diff --git a/panels/wwan/cc-wwan-panel.ui b/panels/wwan/cc-wwan-panel.ui +new file mode 100644 +index 000000000..5258c42c3 +--- /dev/null ++++ b/panels/wwan/cc-wwan-panel.ui +@@ -0,0 +1,336 @@ ++ ++ ++ ++ ++ ++ bottom ++ popover_arrow ++ ++ ++ 1 ++ none ++ ++ ++ ++ ++ ++ ++ ++ 1 ++ ++ ++ Enable Mobile Network ++ ++ ++ ++ +diff --git a/panels/wwan/cc-wwan-sim-lock-dialog.c b/panels/wwan/cc-wwan-sim-lock-dialog.c +new file mode 100644 +index 000000000..14adbf415 +--- /dev/null ++++ b/panels/wwan/cc-wwan-sim-lock-dialog.c +@@ -0,0 +1,310 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-network-dialog.c ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#undef G_LOG_DOMAIN ++#define G_LOG_DOMAIN "cc-wwan-sim-lock-dialog" ++ ++#include ++#include ++#include ++ ++#include "list-box-helper.h" ++#include "cc-list-row.h" ++#include "cc-wwan-sim-lock-dialog.h" ++#include "cc-wwan-resources.h" ++ ++/** ++ * @short_description: Dialog to manage SIM Locks like PIN ++ */ ++ ++#define PIN_MINIMUM_LENGTH 4 ++#define PIN_MAXIMUM_LENGTH 8 ++ ++struct _CcWwanSimLockDialog ++{ ++ GtkDialog parent_instance; ++ ++ CcWwanDevice *device; ++ ++ GtkButton *apply_button; ++ GtkStack *button_stack; ++ GtkGrid *lock_change_grid; ++ CcListRow *lock_row; ++ GtkEntry *new_pin_entry; ++ GtkButton *next_button; ++ GtkEntry *pin_confirm_entry; ++ GtkEntry *pin_entry; ++ GtkStack *pin_settings_stack; ++}; ++ ++G_DEFINE_TYPE (CcWwanSimLockDialog, cc_wwan_sim_lock_dialog, GTK_TYPE_DIALOG) ++ ++ ++enum { ++ PROP_0, ++ PROP_DEVICE, ++ N_PROPS ++}; ++ ++static GParamSpec *properties[N_PROPS]; ++ ++static void ++cc_wwan_sim_lock_changed_cb (CcWwanSimLockDialog *self) ++{ ++ gboolean row_enabled, lock_enabled; ++ ++ lock_enabled = cc_wwan_device_get_sim_lock (self->device); ++ row_enabled = cc_list_row_get_active (self->lock_row); ++ ++ gtk_widget_set_sensitive (GTK_WIDGET (self->next_button), lock_enabled != row_enabled); ++ gtk_widget_set_visible (GTK_WIDGET (self->lock_change_grid), row_enabled && lock_enabled); ++} ++ ++static void ++cc_wwan_pin_next_clicked_cb (CcWwanSimLockDialog *self) ++{ ++ gtk_stack_set_visible_child_name (self->pin_settings_stack, "pin-entry"); ++ gtk_entry_set_text (self->pin_entry, ""); ++ ++ gtk_widget_set_sensitive (GTK_WIDGET (self->apply_button), FALSE); ++ gtk_stack_set_visible_child (self->button_stack, ++ GTK_WIDGET (self->apply_button)); ++} ++ ++static void ++cc_wwan_pin_apply_clicked_cb (CcWwanSimLockDialog *self) ++{ ++ const gchar *pin, *new_pin; ++ gboolean row_enabled, lock_enabled; ++ ++ gtk_widget_hide (GTK_WIDGET (self)); ++ ++ lock_enabled = cc_wwan_device_get_sim_lock (self->device); ++ row_enabled = cc_list_row_get_active (self->lock_row); ++ pin = gtk_entry_get_text (self->pin_entry); ++ new_pin = gtk_entry_get_text (self->new_pin_entry); ++ ++ if (lock_enabled != row_enabled) ++ { ++ if (row_enabled) ++ cc_wwan_device_enable_pin (self->device, pin, NULL, NULL, NULL); ++ else ++ cc_wwan_device_disable_pin (self->device, pin, NULL, NULL, NULL); ++ ++ return; ++ } ++ ++ cc_wwan_device_change_pin (self->device, pin, new_pin, NULL, NULL, NULL); ++} ++ ++static void ++cc_wwan_pin_entry_text_inserted_cb (CcWwanSimLockDialog *self, ++ gchar *new_text, ++ gint new_text_length, ++ gpointer position, ++ GtkEditable *editable) ++{ ++ size_t digit_end; ++ size_t len; ++ ++ if (!new_text || !*new_text) ++ return; ++ ++ if (new_text_length == 1 && g_ascii_isdigit (*new_text)) ++ return; ++ ++ if (new_text_length == -1) ++ len = strlen (new_text); ++ else ++ len = new_text_length; ++ ++ if (len == 1 && g_ascii_isdigit (*new_text)) ++ return; ++ ++ digit_end = strspn (new_text, "1234567890"); ++ ++ /* The maximum length possible for PIN is 8 */ ++ if (len <= 8 && digit_end == len) ++ return; ++ ++ g_signal_stop_emission_by_name (editable, "insert-text"); ++ gtk_widget_error_bell (GTK_WIDGET (editable)); ++} ++ ++static void ++cc_wwan_pin_entry_changed_cb (CcWwanSimLockDialog *self) ++{ ++ const gchar *new_pin, *confirm_pin; ++ ++ new_pin = gtk_entry_get_text (self->new_pin_entry); ++ confirm_pin = gtk_entry_get_text (self->pin_confirm_entry); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->next_button), FALSE); ++ ++ /* A PIN should have a minimum length of 4 */ ++ if (!new_pin || !confirm_pin || strlen (new_pin) < 4) ++ return; ++ ++ if (g_str_equal (new_pin, confirm_pin)) ++ gtk_widget_set_sensitive (GTK_WIDGET (self->next_button), TRUE); ++} ++ ++ ++static void ++cc_wwan_pin_entered_cb (CcWwanSimLockDialog *self) ++{ ++ const gchar *pin; ++ gsize len; ++ gboolean enable_apply; ++ ++ pin = gtk_entry_get_text (self->pin_entry); ++ ++ if (!pin || !*pin) ++ { ++ gtk_widget_set_sensitive (GTK_WIDGET (self->apply_button), FALSE); ++ return; ++ } ++ ++ len = strlen (pin); ++ enable_apply = len >= PIN_MINIMUM_LENGTH && len <= PIN_MAXIMUM_LENGTH; ++ ++ gtk_widget_set_sensitive (GTK_WIDGET (self->apply_button), enable_apply); ++} ++ ++static void ++cc_wwan_sim_lock_dialog_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ CcWwanSimLockDialog *self = (CcWwanSimLockDialog *)object; ++ ++ switch (prop_id) ++ { ++ case PROP_DEVICE: ++ self->device = g_value_dup_object (value); ++ break; ++ ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ } ++} ++ ++static void ++cc_wwan_sim_lock_dialog_show (GtkWidget *widget) ++{ ++ CcWwanSimLockDialog *self = (CcWwanSimLockDialog *)widget; ++ gboolean lock_enabled; ++ ++ gtk_entry_set_text (self->pin_entry, ""); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->next_button), FALSE); ++ gtk_widget_set_sensitive (GTK_WIDGET (self->apply_button), FALSE); ++ ++ lock_enabled = cc_wwan_device_get_sim_lock (self->device); ++ g_object_set (self->lock_row, "active", lock_enabled, NULL); ++ gtk_widget_set_visible (GTK_WIDGET (self->lock_change_grid), lock_enabled); ++ ++ gtk_widget_set_sensitive (GTK_WIDGET (self->next_button), FALSE); ++ gtk_stack_set_visible_child (self->button_stack, ++ GTK_WIDGET (self->next_button)); ++ gtk_button_set_label (self->apply_button, _("_Set")); ++ ++ gtk_stack_set_visible_child_name (self->pin_settings_stack, "pin-settings"); ++ ++ gtk_entry_set_text (self->pin_entry, ""); ++ gtk_entry_set_text (self->new_pin_entry, ""); ++ gtk_entry_set_text (self->pin_confirm_entry, ""); ++ ++ GTK_WIDGET_CLASS (cc_wwan_sim_lock_dialog_parent_class)->show (widget); ++} ++ ++static void ++cc_wwan_sim_lock_dialog_dispose (GObject *object) ++{ ++ CcWwanSimLockDialog *self = (CcWwanSimLockDialog *)object; ++ ++ g_clear_object (&self->device); ++ ++ G_OBJECT_CLASS (cc_wwan_sim_lock_dialog_parent_class)->dispose (object); ++} ++ ++static void ++cc_wwan_sim_lock_dialog_class_init (CcWwanSimLockDialogClass *klass) ++{ ++ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->set_property = cc_wwan_sim_lock_dialog_set_property; ++ object_class->dispose = cc_wwan_sim_lock_dialog_dispose; ++ ++ widget_class->show = cc_wwan_sim_lock_dialog_show; ++ ++ properties[PROP_DEVICE] = ++ g_param_spec_object ("device", ++ "Device", ++ "The WWAN Device", ++ CC_TYPE_WWAN_DEVICE, ++ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); ++ ++ g_object_class_install_properties (object_class, N_PROPS, properties); ++ ++ gtk_widget_class_set_template_from_resource (widget_class, ++ "/org/gnome/control-center/wwan/cc-wwan-sim-lock-dialog.ui"); ++ ++ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, apply_button); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, button_stack); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, lock_change_grid); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, lock_row); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, new_pin_entry); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, next_button); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, pin_confirm_entry); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, pin_entry); ++ gtk_widget_class_bind_template_child (widget_class, CcWwanSimLockDialog, pin_settings_stack); ++ ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_sim_lock_changed_cb); ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_pin_next_clicked_cb); ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_pin_apply_clicked_cb); ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_pin_entry_text_inserted_cb); ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_pin_entry_changed_cb); ++ gtk_widget_class_bind_template_callback (widget_class, cc_wwan_pin_entered_cb); ++} ++ ++static void ++cc_wwan_sim_lock_dialog_init (CcWwanSimLockDialog *self) ++{ ++ gtk_widget_init_template (GTK_WIDGET (self)); ++} ++ ++CcWwanSimLockDialog * ++cc_wwan_sim_lock_dialog_new (GtkWindow *parent_window, ++ CcWwanDevice *device) ++{ ++ g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL); ++ g_return_val_if_fail (CC_IS_WWAN_DEVICE (device), NULL); ++ ++ return g_object_new (CC_TYPE_WWAN_SIM_LOCK_DIALOG, ++ "transient-for", parent_window, ++ "use-header-bar", 1, ++ "device", device, ++ NULL); ++} +diff --git a/panels/wwan/cc-wwan-sim-lock-dialog.h b/panels/wwan/cc-wwan-sim-lock-dialog.h +new file mode 100644 +index 000000000..b6d1d5a9e +--- /dev/null ++++ b/panels/wwan/cc-wwan-sim-lock-dialog.h +@@ -0,0 +1,40 @@ ++/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* cc-wwan-sim-lock-dialog.h ++ * ++ * Copyright 2019 Purism SPC ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Author(s): ++ * Mohammed Sadiq ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++#pragma once ++ ++#include ++#include ++ ++#include "cc-wwan-device.h" ++ ++G_BEGIN_DECLS ++ ++#define CC_TYPE_WWAN_SIM_LOCK_DIALOG (cc_wwan_sim_lock_dialog_get_type()) ++G_DECLARE_FINAL_TYPE (CcWwanSimLockDialog, cc_wwan_sim_lock_dialog, CC, WWAN_SIM_LOCK_DIALOG, GtkDialog) ++ ++CcWwanSimLockDialog *cc_wwan_sim_lock_dialog_new (GtkWindow *parent_window, ++ CcWwanDevice *device); ++ ++G_END_DECLS +diff --git a/panels/wwan/cc-wwan-sim-lock-dialog.ui b/panels/wwan/cc-wwan-sim-lock-dialog.ui +new file mode 100644 +index 000000000..48a946be4 +--- /dev/null ++++ b/panels/wwan/cc-wwan-sim-lock-dialog.ui +@@ -0,0 +1,306 @@ ++ ++ ++ ++ +diff --git a/panels/wwan/gnome-wwan-panel.desktop.in.in b/panels/wwan/gnome-wwan-panel.desktop.in.in +new file mode 100644 +index 000000000..351a8edde +--- /dev/null ++++ b/panels/wwan/gnome-wwan-panel.desktop.in.in +@@ -0,0 +1,16 @@ ++[Desktop Entry] ++Name=Mobile Network ++Comment=Configure Telephony and mobile data connections ++Exec=gnome-control-center wwan ++# FIXME ++# Translators: Do NOT translate or transliterate this text (this is an icon file name)! ++Icon=network-cellular-signal-excellent ++Terminal=false ++Type=Application ++NoDisplay=true ++StartupNotify=true ++Categories=GNOME;GTK;Settings;X-GNOME-NetworkSettings;HardwareSettings;X-GNOME-Settings-Panel;X-GNOME-ConnectivitySettings; ++OnlyShowIn=GNOME;Unity; ++StartupNotify=true ++# Translators: Search terms to find the WWAN panel. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon! ++Keywords=cellular;wwan;telephony;sim;mobile; +diff --git a/panels/wwan/meson.build b/panels/wwan/meson.build +new file mode 100644 +index 000000000..8c1b02f26 +--- /dev/null ++++ b/panels/wwan/meson.build +@@ -0,0 +1,61 @@ ++gcr_dep = [dependency('gcr-3')] ++ ++deps = common_deps + network_manager_deps + gcr_dep + [polkit_gobject_dep] ++panels_list += cappletname ++desktop = 'gnome-@0@-panel.desktop'.format(cappletname) ++ ++desktop_in = configure_file( ++ input : desktop + '.in.in', ++ output : desktop + '.in', ++ configuration : desktop_conf ++) ++ ++i18n.merge_file( ++ desktop, ++ type : 'desktop', ++ input : desktop_in, ++ output : desktop, ++ po_dir : po_dir, ++ install : true, ++ install_dir : control_center_desktopdir ++) ++ ++sources = files( ++ 'cc-wwan-panel.c', ++ 'cc-wwan-device.c', ++ 'cc-wwan-data.c', ++ 'cc-wwan-device-page.c', ++ 'cc-wwan-mode-dialog.c', ++ 'cc-wwan-network-dialog.c', ++ 'cc-wwan-details-dialog.c', ++ 'cc-wwan-sim-lock-dialog.c', ++ 'cc-wwan-apn-dialog.c', ++) ++ ++resource_data = files( ++ 'cc-wwan-panel.ui', ++ 'cc-wwan-device-page.ui', ++ 'cc-wwan-mode-dialog.ui', ++ 'cc-wwan-network-dialog.ui', ++ 'cc-wwan-details-dialog.ui', ++ 'cc-wwan-sim-lock-dialog.ui', ++ 'cc-wwan-apn-dialog.ui', ++) ++ ++sources += gnome.compile_resources( ++ 'cc-' + cappletname + '-resources', ++ cappletname + '.gresource.xml', ++ c_name : 'cc_' + cappletname, ++ dependencies : resource_data, ++ export : true ++) ++ ++cflags += '-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir) ++ ++panels_libs += static_library( ++ cappletname, ++ sources : sources, ++ include_directories : [ top_inc, common_inc ], ++ dependencies : deps, ++ c_args : cflags ++) +diff --git a/panels/wwan/wwan.gresource.xml b/panels/wwan/wwan.gresource.xml +new file mode 100644 +index 000000000..f128a164a +--- /dev/null ++++ b/panels/wwan/wwan.gresource.xml +@@ -0,0 +1,12 @@ ++ ++ ++ ++ cc-wwan-panel.ui ++ cc-wwan-device-page.ui ++ cc-wwan-mode-dialog.ui ++ cc-wwan-network-dialog.ui ++ cc-wwan-details-dialog.ui ++ cc-wwan-sim-lock-dialog.ui ++ cc-wwan-apn-dialog.ui ++ ++ +diff --git a/shell/cc-panel-list.c b/shell/cc-panel-list.c +index e23da0b87..e6659b789 100644 +--- a/shell/cc-panel-list.c ++++ b/shell/cc-panel-list.c +@@ -381,6 +381,7 @@ static const gchar * const panel_order[] = { + /* Main page */ + "wifi", + "network", ++ "wwan", + "mobile-broadband", + "bluetooth", + "background", +diff --git a/shell/cc-panel-loader.c b/shell/cc-panel-loader.c +index f20384394..65b6555a1 100644 +--- a/shell/cc-panel-loader.c ++++ b/shell/cc-panel-loader.c +@@ -64,6 +64,9 @@ extern GType cc_user_panel_get_type (void); + #ifdef BUILD_WACOM + extern GType cc_wacom_panel_get_type (void); + #endif /* BUILD_WACOM */ ++#ifdef BUILD_WWAN ++extern GType cc_wwan_panel_get_type (void); ++#endif /* BUILD_WWAN */ + extern GType cc_location_panel_get_type (void); + extern GType cc_camera_panel_get_type (void); + extern GType cc_microphone_panel_get_type (void); +@@ -79,6 +82,9 @@ extern void cc_wifi_panel_static_init_func (void); + #ifdef BUILD_WACOM + extern void cc_wacom_panel_static_init_func (void); + #endif /* BUILD_WACOM */ ++#ifdef BUILD_WWAN ++extern void cc_wwan_panel_static_init_func (void); ++#endif /* BUILD_WWAN */ + + #define PANEL_TYPE(name, get_type, init_func) { name, get_type, init_func } + +@@ -129,6 +135,9 @@ static CcPanelLoaderVtable default_panels[] = + #ifdef BUILD_WACOM + PANEL_TYPE("wacom", cc_wacom_panel_get_type, cc_wacom_panel_static_init_func), + #endif ++#ifdef BUILD_WWAN ++ PANEL_TYPE("wwan", cc_wwan_panel_get_type, cc_wwan_panel_static_init_func), ++#endif + }; + + /* Override for the panel vtable. When NULL, the default_panels will +-- +2.32.0 + + +From 610bf914b5c745c87b0be5c827515e82c07317f9 Mon Sep 17 00:00:00 2001 +From: Mohammed Sadiq +Date: Fri, 4 Oct 2019 16:02:23 +0530 +Subject: [PATCH 3/7] network: Don't show modems supported by cellular panel + +Cellular panel is already handling it +--- + panels/network/cc-network-panel.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/panels/network/cc-network-panel.c b/panels/network/cc-network-panel.c +index 01b164ea0..bd4e55df8 100644 +--- a/panels/network/cc-network-panel.c ++++ b/panels/network/cc-network-panel.c +@@ -382,6 +382,27 @@ update_bluetooth_section (CcNetworkPanel *self) + gtk_widget_set_visible (self->container_bluetooth, self->bluetooth_devices->len > 0); + } + ++static gboolean ++wwan_panel_supports_modem (GDBusObject *object) ++{ ++ MMObject *mm_object; ++ MMModem *modem; ++ MMModemCapability capability, supported_capabilities; ++ ++ g_assert (G_IS_DBUS_OBJECT (object)); ++ ++ supported_capabilities = MM_MODEM_CAPABILITY_GSM_UMTS | MM_MODEM_CAPABILITY_LTE; ++#if MM_CHECK_VERSION (1,14,0) ++ supported_capabilities |= MM_MODEM_CAPABILITY_5GNR; ++#endif ++ ++ mm_object = MM_OBJECT (object); ++ modem = mm_object_get_modem (mm_object); ++ capability = mm_modem_get_current_capabilities (modem); ++ ++ return capability & supported_capabilities; ++} ++ + static void + panel_add_device (CcNetworkPanel *self, NMDevice *device) + { +@@ -425,6 +446,10 @@ panel_add_device (CcNetworkPanel *self, NMDevice *device) + nm_device_get_udi (device)); + return; + } ++ ++ /* This will be handled by cellular panel */ ++ if (wwan_panel_supports_modem (modem_object)) ++ return; + } + + device_mobile = net_device_mobile_new (self->client, device, modem_object); +-- +2.32.0 + + +From b7a3b8b84641fdc600cc2ab3683da57023ef5e65 Mon Sep 17 00:00:00 2001 +From: Kyle Rankin +Date: Fri, 21 Feb 2020 01:28:13 +0000 +Subject: [PATCH 4/7] Lower WWAN DNS Priority + +The current DNS priority settings for WWAN were set far too low. Most +connections (including WiFi) do not set DNS priority (set to 0) and per +https://developer.gnome.org/NetworkManager/stable/nm-settings.html : + +"A lower value is better (higher priority). Zero selects a globally +configured default value. If the latter is missing or zero too, it +defaults to 50 for VPNs and 100 for other connections." + +By setting both the "low" and "high" settings to 15 and 20 respectively, +the WWAN DNS servers were always appearing above WiFi, even though WiFi +had routing priority. This caused latency and other problems when the +wwan connection was slow because the system would query those DNS +servers before WiFi ones. Beyond that, it would even cause WWAN to +override VPN DNS settings which isn't what we want. + +This change puts the "low priority" setting above the default 100 that +connections get when they don't otherwise set a priority, and the "high +priority" slightly below 100. I did this instead of setting the values +to 0 because I noticed that NM doesn't seem to be aware it should +prioritize WiFi in that case so WWAN DNS servers were still sometimes +taking precedence. +--- + panels/wwan/cc-wwan-data.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/panels/wwan/cc-wwan-data.c b/panels/wwan/cc-wwan-data.c +index 0be8f3403..4062d78fd 100644 +--- a/panels/wwan/cc-wwan-data.c ++++ b/panels/wwan/cc-wwan-data.c +@@ -47,9 +47,20 @@ + * of #CcWwanData changes when SIM is changed. + */ + +-/* Priority for connections. larger the number, lower the priority */ +-#define CC_WWAN_DNS_PRIORITY_LOW (20) +-#define CC_WWAN_DNS_PRIORITY_HIGH (15) ++/* ++ * Priority for connections. The larger the number, the lower the priority ++ * https://developer.gnome.org/NetworkManager/stable/nm-settings.html: ++ * ++ * A lower value is better (higher priority). Zero selects a globally ++ * configured default value. If the latter is missing or zero too, it ++ * defaults to 50 for VPNs and 100 for other connections. ++ * ++ * Since WiFi and other network connections will likely get the default ++ * setting of 100, set WWAN DNS priorities higher than the default, with ++ * room to allow multiple modems to set priority above/below each other. ++ */ ++#define CC_WWAN_DNS_PRIORITY_LOW (120) ++#define CC_WWAN_DNS_PRIORITY_HIGH (115) + + /* These are to be set as route metric */ + #define CC_WWAN_ROUTE_PRIORITY_LOW (1050) +-- +2.32.0 + + +From 0f38f32b98ae946b8259e3232e311d4f743acaba Mon Sep 17 00:00:00 2001 +From: Sebastian Krzyszkowiak +Date: Mon, 6 Jul 2020 04:33:30 +0200 +Subject: [PATCH 5/7] wwan: Fix signal strength display when extended signal + retrieval is disabled + +MMModemSignal interface is used to retrieve extended signal information that +requires periodic polling. Therefore, it needs to be manually enabled in order +to use. There if a fallback to use mm_modem_get_signal_quality when MMModemSignal +interface is unavailable, but it didn't check whether it's actually enabled, +leaving the UI with empty label. +--- + panels/wwan/cc-wwan-device.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/panels/wwan/cc-wwan-device.c b/panels/wwan/cc-wwan-device.c +index 31baff95c..55a627a5a 100644 +--- a/panels/wwan/cc-wwan-device.c ++++ b/panels/wwan/cc-wwan-device.c +@@ -1183,12 +1183,16 @@ cc_wwan_device_dup_signal_string (CcWwanDevice *self) + GString *str; + gdouble value; + gboolean recent; ++ guint refresh_rate; + + g_return_val_if_fail (CC_IS_WWAN_DEVICE (self), NULL); + + modem_signal = mm_object_peek_modem_signal (self->mm_object); + +- if (!modem_signal) ++ if (modem_signal) ++ refresh_rate = mm_modem_signal_get_rate (modem_signal); ++ ++ if (!modem_signal || !refresh_rate) + return g_strdup_printf ("%d%%", mm_modem_get_signal_quality (self->modem, &recent)); + + str = g_string_new (""); +-- +2.32.0 + + +From 99bbe06a25a523898dde7370274430e7502be53e Mon Sep 17 00:00:00 2001 +From: Mohammed Sadiq +Date: Sat, 14 Aug 2021 13:39:33 +0530 +Subject: [PATCH 6/7] wwan: Fix a typo + +Fixes https://gitlab.gnome.org/GNOME/gnome-control-center/-/commit/dc840f0aec346f3fb297789eb1641255574c47a4#note_1249116 +--- + panels/wwan/cc-wwan-apn-dialog.ui | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/panels/wwan/cc-wwan-apn-dialog.ui b/panels/wwan/cc-wwan-apn-dialog.ui +index fb8432bc6..9ac07ce38 100644 +--- a/panels/wwan/cc-wwan-apn-dialog.ui ++++ b/panels/wwan/cc-wwan-apn-dialog.ui +@@ -211,7 +211,7 @@ + 1 + end + center +- Passsword ++ Password + +-- +2.32.0 + + +From b1cf8916b2569aa6c3b7f724eff37f198ed37b73 Mon Sep 17 00:00:00 2001 +From: Mohammed Sadiq +Date: Sat, 14 Aug 2021 13:54:33 +0530 +Subject: [PATCH 7/7] wwan: Avoid translation of some strings + +Many strings are not shown in the UI. Let's not overwhelm translators +--- + panels/wwan/cc-wwan-errors-private.h | 50 ++++++++++++++-------------- + 1 file changed, 25 insertions(+), 25 deletions(-) + +diff --git a/panels/wwan/cc-wwan-errors-private.h b/panels/wwan/cc-wwan-errors-private.h +index 761b82f35..076482d1f 100644 +--- a/panels/wwan/cc-wwan-errors-private.h ++++ b/panels/wwan/cc-wwan-errors-private.h +@@ -39,12 +39,12 @@ typedef struct { + static ErrorTable me_errors[] = { + { MM_MOBILE_EQUIPMENT_ERROR_PHONE_FAILURE, N_("Phone failure") }, + { MM_MOBILE_EQUIPMENT_ERROR_NO_CONNECTION, N_("No connection to phone") }, +- { MM_MOBILE_EQUIPMENT_ERROR_LINK_RESERVED, N_("Phone-adaptor link reserved") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_LINK_RESERVED, "Phone-adaptor link reserved" }, + { MM_MOBILE_EQUIPMENT_ERROR_NOT_ALLOWED, N_("Operation not allowed") }, + { MM_MOBILE_EQUIPMENT_ERROR_NOT_SUPPORTED, N_("Operation not supported") }, +- { MM_MOBILE_EQUIPMENT_ERROR_PH_SIM_PIN, N_("PH-SIM PIN required") }, +- { MM_MOBILE_EQUIPMENT_ERROR_PH_FSIM_PIN, N_("PH-FSIM PIN required") }, +- { MM_MOBILE_EQUIPMENT_ERROR_PH_FSIM_PUK, N_("PH-FSIM PUK required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_PH_SIM_PIN, "PH-SIM PIN required" }, ++ { MM_MOBILE_EQUIPMENT_ERROR_PH_FSIM_PIN, "PH-FSIM PIN required" }, ++ { MM_MOBILE_EQUIPMENT_ERROR_PH_FSIM_PUK, "PH-FSIM PUK required" }, + { MM_MOBILE_EQUIPMENT_ERROR_SIM_NOT_INSERTED, N_("SIM not inserted") }, + { MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN, N_("SIM PIN required") }, + { MM_MOBILE_EQUIPMENT_ERROR_SIM_PUK, N_("SIM PUK required") }, +@@ -54,34 +54,34 @@ static ErrorTable me_errors[] = { + { MM_MOBILE_EQUIPMENT_ERROR_INCORRECT_PASSWORD, N_("Incorrect password") }, + { MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN2, N_("SIM PIN2 required") }, + { MM_MOBILE_EQUIPMENT_ERROR_SIM_PUK2, N_("SIM PUK2 required") }, +- { MM_MOBILE_EQUIPMENT_ERROR_MEMORY_FULL, N_("Memory full") }, +- { MM_MOBILE_EQUIPMENT_ERROR_INVALID_INDEX, N_("Invalid index") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_MEMORY_FULL, "Memory full" }, ++ { MM_MOBILE_EQUIPMENT_ERROR_INVALID_INDEX, "Invalid index" }, + { MM_MOBILE_EQUIPMENT_ERROR_NOT_FOUND, N_("Not found") }, +- { MM_MOBILE_EQUIPMENT_ERROR_MEMORY_FAILURE, N_("Memory failure") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_MEMORY_FAILURE, "Memory failure" }, + { MM_MOBILE_EQUIPMENT_ERROR_NO_NETWORK, N_("No network service") }, + { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_TIMEOUT, N_("Network timeout") }, +- { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_NOT_ALLOWED, N_("Network not allowed - emergency calls only") }, +- { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_PIN, N_("Network personalization PIN required") }, +- { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_PUK, N_("Network personalization PUK required") }, +- { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_SUBSET_PIN, N_("Network subset personalization PIN required") }, +- { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_SUBSET_PUK, N_("Network subset personalization PUK required") }, +- { MM_MOBILE_EQUIPMENT_ERROR_SERVICE_PIN, N_("Service provider personalization PIN required") }, +- { MM_MOBILE_EQUIPMENT_ERROR_SERVICE_PUK, N_("Service provider personalization PUK required") }, +- { MM_MOBILE_EQUIPMENT_ERROR_CORP_PIN, N_("Corporate personalization PIN required") }, +- { MM_MOBILE_EQUIPMENT_ERROR_CORP_PUK, N_("Corporate personalization PUK required") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_NOT_ALLOWED, "Network not allowed - emergency calls only" }, ++ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_PIN, "Network personalization PIN required" }, ++ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_PUK, "Network personalization PUK required" }, ++ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_SUBSET_PIN, "Network subset personalization PIN required" }, ++ { MM_MOBILE_EQUIPMENT_ERROR_NETWORK_SUBSET_PUK, "Network subset personalization PUK required" }, ++ { MM_MOBILE_EQUIPMENT_ERROR_SERVICE_PIN, "Service provider personalization PIN required" }, ++ { MM_MOBILE_EQUIPMENT_ERROR_SERVICE_PUK, "Service provider personalization PUK required" }, ++ { MM_MOBILE_EQUIPMENT_ERROR_CORP_PIN, "Corporate personalization PIN required" }, ++ { MM_MOBILE_EQUIPMENT_ERROR_CORP_PUK, "Corporate personalization PUK required" }, + { MM_MOBILE_EQUIPMENT_ERROR_UNKNOWN, N_("Unknown error") }, +- { MM_MOBILE_EQUIPMENT_ERROR_GPRS_ILLEGAL_MS, N_("Illegal MS") }, +- { MM_MOBILE_EQUIPMENT_ERROR_GPRS_ILLEGAL_ME, N_("Illegal ME") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_ILLEGAL_MS, "Illegal MS" }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_ILLEGAL_ME, "Illegal ME" }, + { MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_NOT_ALLOWED, N_("GPRS services not allowed") }, +- { MM_MOBILE_EQUIPMENT_ERROR_GPRS_PLMN_NOT_ALLOWED, N_("PLMN not allowed") }, +- { MM_MOBILE_EQUIPMENT_ERROR_GPRS_LOCATION_NOT_ALLOWED, N_("Location area not allowed") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_PLMN_NOT_ALLOWED, "PLMN not allowed" }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_LOCATION_NOT_ALLOWED, "Location area not allowed" }, + { MM_MOBILE_EQUIPMENT_ERROR_GPRS_ROAMING_NOT_ALLOWED, N_("Roaming not allowed in this location area") }, +- { MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_OPTION_NOT_SUPPORTED, N_("Service option not supported") }, +- { MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_OPTION_NOT_SUBSCRIBED, N_("Requested service option not subscribed") }, +- { MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_OPTION_OUT_OF_ORDER, N_("Service option temporarily out of order") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_OPTION_NOT_SUPPORTED, "Service option not supported" }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_OPTION_NOT_SUBSCRIBED, "Requested service option not subscribed" }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_SERVICE_OPTION_OUT_OF_ORDER, "Service option temporarily out of order" }, + { MM_MOBILE_EQUIPMENT_ERROR_GPRS_UNKNOWN, N_("Unspecified GPRS error") }, +- { MM_MOBILE_EQUIPMENT_ERROR_GPRS_PDP_AUTH_FAILURE, N_("PDP authentication failure") }, +- { MM_MOBILE_EQUIPMENT_ERROR_GPRS_INVALID_MOBILE_CLASS, N_("Invalid mobile class") }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_PDP_AUTH_FAILURE, "PDP authentication failure" }, ++ { MM_MOBILE_EQUIPMENT_ERROR_GPRS_INVALID_MOBILE_CLASS, "Invalid mobile class" }, + }; + + static inline const gchar * +-- +2.32.0 + diff --git a/SPECS/gnome-control-center.spec b/SPECS/gnome-control-center.spec new file mode 100644 index 0000000..0043b91 --- /dev/null +++ b/SPECS/gnome-control-center.spec @@ -0,0 +1,540 @@ +%define gnome_online_accounts_version 3.25.3 +%define glib2_version 2.56.0 +%define gnome_desktop_version 3.35.4 +%define gsd_version 3.35.0 +%define gsettings_desktop_schemas_version 3.37.1 +%define upower_version 0.99.8 +%define gtk3_version 3.22.20 +%define cheese_version 3.28.0 +%define gnome_bluetooth_version 3.18.2 +%define nm_version 1.24 +%define power_profiles_daemon_version 0.9.0 + +%global tarball_version %%(echo %{version} | tr '~' '.') + +Name: gnome-control-center +Version: 40.0 +Release: 23%{?dist} +Summary: Utilities to configure the GNOME desktop + +License: GPLv2+ and CC-BY-SA +URL: http://www.gnome.org +Source0: https://download.gnome.org/sources/gnome-control-center/40/gnome-control-center-%{tarball_version}.tar.xz + +# https://gitlab.gnome.org/GNOME/gnome-control-center/-/merge_requests/965 +Patch0: distro-logo.patch + +# Customized for RHEL 9 to skip the .gitlab-ci.yml file +# https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1345 +# https://bugzilla.redhat.com/show_bug.cgi?id=1952274 +Patch1: gnome-control-center-Drop-the-unused-build-dependency-on-Grilo.patch +Patch2: power-profiles-backport.patch +Patch3: wwan-backport-gnome-40.patch +Patch4: subscription-manager-support.patch +Patch5: application-use-icon-name-that-exists.patch +Patch6: backport-multitasking-panel.patch +Patch7: rpminspect-desktop-fixes.patch + +# Backport monitor config policy (#2046159) +Patch8: 0001-display-Only-display-configuration-options-if-apply-.patch + +# Workaround for libnma not handling OWE https://gitlab.gnome.org/GNOME/libnma/-/issues/9 +Patch9: 0001-network-Fix-OWE-settings.patch + +BuildRequires: chrpath +BuildRequires: cups-devel +BuildRequires: desktop-file-utils +BuildRequires: docbook-style-xsl libxslt +BuildRequires: gcc +BuildRequires: gettext +BuildRequires: meson +BuildRequires: pkgconfig(accountsservice) +BuildRequires: pkgconfig(cheese) >= %{cheese_version} +BuildRequires: pkgconfig(cheese-gtk) +BuildRequires: pkgconfig(clutter-gtk-1.0) +BuildRequires: pkgconfig(colord) +BuildRequires: pkgconfig(colord-gtk) +BuildRequires: pkgconfig(gdk-pixbuf-2.0) +BuildRequires: pkgconfig(gdk-wayland-3.0) +BuildRequires: pkgconfig(gio-2.0) >= %{glib2_version} +BuildRequires: pkgconfig(gnome-desktop-3.0) >= %{gnome_desktop_version} +BuildRequires: pkgconfig(gnome-settings-daemon) >= %{gsd_version} +BuildRequires: pkgconfig(goa-1.0) >= %{gnome_online_accounts_version} +BuildRequires: pkgconfig(goa-backend-1.0) +BuildRequires: pkgconfig(gsettings-desktop-schemas) >= %{gsettings_desktop_schemas_version} +BuildRequires: pkgconfig(gsound) +BuildRequires: pkgconfig(gtk+-3.0) >= %{gtk3_version} +BuildRequires: pkgconfig(gudev-1.0) +BuildRequires: pkgconfig(ibus-1.0) +BuildRequires: pkgconfig(libcanberra-gtk3) +BuildRequires: pkgconfig(libgtop-2.0) +BuildRequires: pkgconfig(libhandy-1) +BuildRequires: pkgconfig(libnm) >= %{nm_version} +BuildRequires: pkgconfig(libnma) +BuildRequires: pkgconfig(libpulse) +BuildRequires: pkgconfig(libpulse-mainloop-glib) +BuildRequires: pkgconfig(libsecret-1) +BuildRequires: pkgconfig(libsoup-2.4) +BuildRequires: pkgconfig(libxml-2.0) +BuildRequires: pkgconfig(mm-glib) +BuildRequires: pkgconfig(polkit-gobject-1) +BuildRequires: pkgconfig(pwquality) +BuildRequires: pkgconfig(smbclient) +BuildRequires: pkgconfig(upower-glib) >= %{upower_version} +BuildRequires: pkgconfig(x11) +BuildRequires: pkgconfig(xi) +BuildRequires: pkgconfig(udisks2) +BuildRequires: pkgconfig(gcr-3) +%ifnarch s390 s390x +BuildRequires: pkgconfig(gnome-bluetooth-1.0) >= %{gnome_bluetooth_version} +BuildRequires: pkgconfig(libwacom) +%endif + +# Versioned library deps +Requires: cheese-libs%{?_isa} >= %{cheese_version} +Requires: glib2%{?_isa} >= %{glib2_version} +Requires: gnome-desktop3%{?_isa} >= %{gnome_desktop_version} +Requires: gnome-online-accounts%{?_isa} >= %{gnome_online_accounts_version} +Requires: gnome-settings-daemon%{?_isa} >= %{gsd_version} +# For g-s-d subscription manager patches +Requires: gnome-settings-daemon%{?_isa} >= 40.0.1-4 +Requires: gsettings-desktop-schemas%{?_isa} >= %{gsettings_desktop_schemas_version} +Requires: gtk3%{?_isa} >= %{gtk3_version} +Requires: upower%{?_isa} >= %{upower_version} +Requires: power-profiles-daemon >= %{power_profiles_daemon_version} +%ifnarch s390 s390x +Requires: gnome-bluetooth%{?_isa} >= 1:%{gnome_bluetooth_version} +%endif + +Requires: %{name}-filesystem = %{version}-%{release} +# For user accounts +Requires: accountsservice +Requires: alsa-lib +# For the thunderbolt panel +Recommends: bolt +# For the color panel +Requires: colord +# For the printers panel +Requires: cups-pk-helper +Requires: dbus +# For the info/details panel +Requires: glx-utils +# For the user languages +Requires: iso-codes +# For the network panel +Recommends: NetworkManager-wifi +Recommends: nm-connection-editor +# For Show Details in the color panel +Recommends: gnome-color-manager +# For the sharing panel +Recommends: gnome-remote-desktop +%if 0%{?fedora} +Recommends: rygel +%endif +# For the info/details panel +Recommends: switcheroo-control +# For the keyboard panel +Requires: /usr/bin/gkbd-keyboard-display +%if 0%{?fedora} >= 35 || 0%{?rhel} >= 9 +# For the power panel +Recommends: power-profiles-daemon +%endif + +# Renamed in F28 +Provides: control-center = 1:%{version}-%{release} +Provides: control-center%{?_isa} = 1:%{version}-%{release} +Obsoletes: control-center < 1:%{version}-%{release} + +%description +This package contains configuration utilities for the GNOME desktop, which +allow to configure accessibility options, desktop fonts, keyboard and mouse +properties, sound setup, desktop theme and background, user interface +properties, screen resolution, and other settings. + +%package filesystem +Summary: GNOME Control Center directories +# NOTE: this is an "inverse dep" subpackage. It gets pulled in +# NOTE: by the main package and MUST not depend on the main package +BuildArch: noarch +# Renamed in F28 +Provides: control-center-filesystem = 1:%{version}-%{release} +Obsoletes: control-center-filesystem < 1:%{version}-%{release} + +%description filesystem +The GNOME control-center provides a number of extension points +for applications. This package contains directories where applications +can install configuration files that are picked up by the control-center +utilities. + +%prep +%autosetup -p1 -n gnome-control-center-%{tarball_version} + +%build +%meson \ + -Ddocumentation=true \ +%if 0%{?fedora} + -Ddistributor_logo=%{_datadir}/pixmaps/fedora_logo_med.png \ + -Ddark_mode_distributor_logo=%{_datadir}/pixmaps/fedora_whitelogo_med.png \ +%endif +%if 0%{?rhel} + -Ddistributor_logo=%{_datadir}/pixmaps/fedora-logo.png \ + -Ddark_mode_distributor_logo=%{_datadir}/pixmaps/system-logo-white.png \ +%endif + %{nil} +%meson_build + +%install +%meson_install + +# We do want this +mkdir -p $RPM_BUILD_ROOT%{_datadir}/gnome/wm-properties + +# We don't want these +rm -rf $RPM_BUILD_ROOT%{_datadir}/gnome/autostart +rm -rf $RPM_BUILD_ROOT%{_datadir}/gnome/cursor-fonts + +# Remove rpath +chrpath --delete $RPM_BUILD_ROOT%{_bindir}/gnome-control-center + +%find_lang %{name} --all-name --with-gnome + +%files -f %{name}.lang +%license COPYING +%doc NEWS README.md +%{_bindir}/gnome-control-center +%{_datadir}/applications/*.desktop +%{_datadir}/bash-completion/completions/gnome-control-center +%{_datadir}/dbus-1/services/org.gnome.ControlCenter.SearchProvider.service +%{_datadir}/dbus-1/services/org.gnome.ControlCenter.service +%{_datadir}/gettext/ +%{_datadir}/glib-2.0/schemas/org.gnome.ControlCenter.gschema.xml +%{_datadir}/gnome-control-center/keybindings/*.xml +%{_datadir}/gnome-control-center/pixmaps +%{_datadir}/gnome-shell/search-providers/gnome-control-center-search-provider.ini +%{_datadir}/icons/hicolor/*/*/* +%{_datadir}/man/man1/gnome-control-center.1* +%{_datadir}/metainfo/gnome-control-center.appdata.xml +%{_datadir}/pixmaps/faces +%{_datadir}/pkgconfig/gnome-keybindings.pc +%{_datadir}/polkit-1/actions/org.gnome.controlcenter.*.policy +%{_datadir}/polkit-1/rules.d/gnome-control-center.rules +%{_datadir}/sounds/gnome/default/*/*.ogg +%{_libexecdir}/cc-remote-login-helper +%{_libexecdir}/gnome-control-center-search-provider +%{_libexecdir}/gnome-control-center-print-renderer + +%files filesystem +%dir %{_datadir}/gnome-control-center +%dir %{_datadir}/gnome-control-center/keybindings +%dir %{_datadir}/gnome/wm-properties + +%changelog +* Mon Mar 14 2022 Felipe Borges - 40.0-23 +- Backport translations for Multitasking panel +- Make Multitasking panel capable of handling Right-to-Left locales + Resolves: #2049524 + +* Thu Feb 24 2022 Benjamin Berg - 40.0-22 +- Work around libnma not handling OWE + Resolves: #2058163 + +* Fri Feb 04 2022 Jonas Ådahl - 40.0-21 +- Backport monitor config policy + Resolves: #2046159 + +* Wed Feb 02 2022 Tomas Popela - 40.0-20 +- Fix rpminspect desktop files warnings +- Resolves: #2041348 + +* Fri Jan 28 2022 Felipe Borges - 40.0-19 +- Backport Multitasking panel +- Resolves: #2047723 + +* Thu Jan 20 2022 Felipe Borges - 40.0-18 +- Fix typo in the previous patch +- Resolves: #2041348 + +* Fri Jan 14 2022 Felipe Borges - 40.0-17 +- Set an existing Icon name in the Applications' panel desktop file +- Resolves: #2041348 + +* Tue Sep 07 2021 Kalev Lember - 40.0-16 +- Add desktop file keywords for subscription support +- Resolves: #1937113 + +* Thu Sep 02 2021 Kalev Lember - 40.0-15 +- Forward port subscription manager support from RHEL 8 +- Resolves: #1937113 + +* Wed Aug 25 2021 Carlos Garnacho - 40.0-14 +- Backport WWAN panel + Resolves: #1995559 + +* Fri Aug 20 2021 Carlos Garnacho - 40.0.13 +- Backport power profile changes + Resolves: #1994475 + +* Mon Aug 09 2021 Mohan Boddu - 40.0-12 +- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags + Related: rhbz#1991688 + +* Tue Apr 27 2021 Debarshi Ray - 40.0-11 +- Drop the unused build dependency on Grilo +Resolves: #1952274 + +* Thu Apr 15 2021 Mohan Boddu - 40.0-10 +- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 + +* Fri Apr 02 2021 Kalev Lember - 40.0-9 +- Only enable power-profiles-daemon on F35+ and RHEL 9+ + +* Wed Mar 31 2021 Pete Walter - 40.0-8 +- Add back power-profiles-daemon once more + +* Wed Mar 31 2021 Michael Catanzaro - 40.0-7 +- Drop Recommends: power-profiles-daemon for F34 + +* Tue Mar 30 2021 Pete Walter - 40.0-6 +- Use recommends for a few more things + +* Tue Mar 30 2021 Bastien Nocera - 40.0-4 +- Drag power-profiles-daemon in for the power panel + +* Mon Mar 29 2021 Michael Catanzaro - 40.0-3 +- Update Fedora logos to larger versions + +* Wed Mar 24 2021 Kalev Lember - 40.0-2 +- Rebuilt + +* Mon Mar 22 2021 Kalev Lember - 40.0-1 +- Update to 40.0 + +* Mon Mar 15 2021 Kalev Lember - 40~rc-1 +- Update to 40.rc + +* Wed Mar 10 2021 Michael Catanzaro - 40~beta-5 +- Refresh distro logo patch +- Drop Recommends: vino, let vino die! + +* Sun Mar 07 2021 Igor Raits - 40~beta-4 +- Fix modifications of the networks (Fixes: RHBZ#1932674) + +* Wed Feb 24 2021 Felipe Borges - 40~beta-3 +- Include missing patch from 40~beta-2 + +* Tue Feb 23 2021 Felipe Borges - 40~beta-2 +- Fix error preventing the Region & Language panel from loading + +* Sun Feb 21 2021 Kalev Lember - 40~beta-1 +- Update to 40.beta + +* Mon Feb 15 2021 Kalev Lember - 3.38.4-1 +- Update to 3.38.4 + +* Tue Jan 26 2021 Fedora Release Engineering - 3.38.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Sat Jan 16 2021 Kalev Lember - 3.38.3-1 +- Update to 3.38.3 + +* Fri Nov 20 2020 Kalev Lember - 3.38.2-2 +- search: Check for either tracker 2.x or 3.x schemas + +* Fri Nov 20 2020 Kalev Lember - 3.38.2-1 +- Update to 3.38.2 + +* Tue Oct 13 2020 Kalev Lember - 3.38.1-2 +- Add Recommends: nm-connection-editor for the network panel (#1887891) + +* Mon Oct 5 2020 Kalev Lember - 3.38.1-1 +- Update to 3.38.1 + +* Sat Sep 19 2020 Yaroslav Fedevych - 3.38.0-2 +- Specify the minimum libnm version needed to build the package + +* Sat Sep 12 2020 Kalev Lember - 3.38.0-1 +- Update to 3.38.0 + +* Sun Sep 06 2020 Kalev Lember - 3.37.92-1 +- Update to 3.37.92 + +* Mon Aug 17 2020 Kalev Lember - 3.37.90-1 +- Update to 3.37.90 + +* Tue Aug 04 2020 Michael Catanzaro - 3.37.3-4 +- Add Recommends: gnome-color-manager for the color panel + +* Sat Aug 01 2020 Fedora Release Engineering - 3.37.3-3 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Mon Jul 27 2020 Fedora Release Engineering - 3.37.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Mon Jul 20 2020 Kalev Lember - 3.37.3-1 +- Update to 3.37.3 + +* Mon Jul 20 2020 Kalev Lember - 3.36.4-1 +- Update to 3.36.4 + +* Wed Jun 03 2020 Kalev Lember - 3.36.3-1 +- Update to 3.36.3 + +* Fri May 01 2020 Kalev Lember - 3.36.2-1 +- Update to 3.36.2 + +* Tue Apr 28 2020 Felipe Borges - 3.36.1-2 +- Add "Model" row info for Lenovo devices + +* Fri Mar 27 2020 Kalev Lember - 3.36.1-1 +- Update to 3.36.1 + +* Thu Mar 19 2020 Michael Catanzaro - 3.36.0-3 +- No changes, bump revision to maintain upgrade path from F32 + +* Mon Mar 16 2020 Michael Catanzaro - 3.36.0-2 +- Update distro-logo.patch to use fedora_vertical version of logo. + +* Sat Mar 07 2020 Kalev Lember - 3.36.0-1 +- Update to 3.36.0 + +* Mon Mar 02 2020 Kalev Lember - 3.35.92-1 +- Update to 3.35.92 + +* Mon Feb 17 2020 Kalev Lember - 3.35.91-1 +- Update to 3.35.91 + +* Mon Feb 03 2020 Bastien Nocera - 3.35.90-1 ++ gnome-control-center-3.35.90-1 +- Update to 3.35.90 + +* Tue Jan 28 2020 Fedora Release Engineering - 3.34.2-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Thu Jan 16 2020 Kalev Lember - 3.34.2-3 +- Backport a patch to fix the build with latest libgnome-desktop + +* Mon Dec 09 2019 Michael Catanzaro - 3.34.2-2 +- Drop nm-connection-editor requires, per gnome-control-center#512 +- To edit mobile broadband connections, install nm-connection-editor + +* Wed Nov 27 2019 Kalev Lember - 3.34.2-1 +- Update to 3.34.2 + +* Thu Oct 10 2019 Adam Williamson - 3.34.1-4 +- Add patch to fix crash when selecting display with no modes (rhbz#1756553) + +* Wed Oct 09 2019 Felipe Borges - 3.34.1-3 +- Add patch to fix parsing of addresses while adding printers (rhbz#1750394) + +* Mon Oct 07 2019 Benjamin Berg - 3.34.1-2 +- Add patch to fix resetting of system wide format locale (rhbz#1759221) + +* Mon Oct 07 2019 Kalev Lember - 3.34.1-1 +- Update to 3.34.1 + +* Sat Oct 05 2019 Michael Catanzaro - 3.34.0.1-3 +- Add patch to fix editing wired connection settings (rhbz#1750805) +- Remove broken remote printers patch + +* Wed Oct 02 2019 Michael Catanzaro - 3.34.0.1-2 +- Add patch to fix crash when configuring remote printers + +* Mon Sep 09 2019 Kalev Lember - 3.34.0.1-1 +- Update to 3.34.0.1 + +* Mon Sep 09 2019 Kalev Lember - 3.34.0-1 +- Update to 3.34.0 + +* Mon Aug 12 2019 Kalev Lember - 3.33.90-1 +- Update to 3.33.90 + +* Thu Jul 25 2019 Fedora Release Engineering - 3.33.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Sun Jul 21 2019 Kalev Lember - 3.33.3-2 +- Remove libXxf86misc-devel BuildRequires as the package no longer exists + +* Wed Jun 19 2019 Kalev Lember - 3.33.3-1 +- Update to 3.33.3 + +* Fri May 24 2019 Kalev Lember - 3.32.2-1 +- Update to 3.32.2 + +* Tue Apr 16 2019 Adam Williamson - 3.32.1-2 +- Rebuild with Meson fix for #1699099 + +* Fri Mar 29 2019 Kalev Lember - 3.32.1-1 +- Update to 3.32.1 + +* Mon Mar 11 2019 Kalev Lember - 3.32.0.1-1 +- Update to 3.32.0.1 + +* Mon Mar 11 2019 Kalev Lember - 3.32.0-1 +- Update to 3.32.0 + +* Mon Mar 04 2019 Kalev Lember - 3.31.92-1 +- Update to 3.31.92 + +* Sat Feb 23 2019 Kevin Fenzi - 3.31.90-2 +- Add https://gitlab.gnome.org/GNOME/gnome-control-center/merge_requests/387.patch + to fix udisks crash + +* Thu Feb 07 2019 Kalev Lember - 3.31.90-1 +- Update to 3.31.90 + +* Thu Jan 31 2019 Fedora Release Engineering - 3.31.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Wed Jan 09 2019 Kalev Lember - 3.31.4-1 +- Update to 3.31.4 + +* Tue Nov 20 2018 Pete Walter - 3.30.2-3 +- Recommend gnome-remote-desktop for the sharing panel + +* Sat Nov 17 2018 Pete Walter - 3.30.2-2 +- Change bolt requires to recommends (#1643709) +- Change rygel requires to recommends + +* Thu Nov 01 2018 Kalev Lember - 3.30.2-1 +- Update to 3.30.2 + +* Thu Oct 11 2018 David Herrmann - 3.30.1-4 +- Reduce 'dbus-x11' dependency to 'dbus'. The xinit scripts are no longer the + canonical way to start dbus, but the 'dbus' package is nowadays required to + provide a user and system bus to its dependents. + +* Wed Oct 10 2018 Benjamin Berg - 3.30.1-3 +- Add patch to improve background loading. The patch is not acceptable + upstream as is, but is also a good improvement on the current situation + (#1631002) + +* Sun Oct 07 2018 Kalev Lember - 3.30.1-2 +- Backport an upstream fix for a crash in the online accounts panel + +* Wed Sep 26 2018 Kalev Lember - 3.30.1-1 +- Update to 3.30.1 + +* Thu Sep 06 2018 Kalev Lember - 3.30.0-1 +- Update to 3.30.0 + +* Sun Aug 12 2018 Kalev Lember - 3.29.90-1 +- Update to 3.29.90 + +* Fri Jul 13 2018 Fedora Release Engineering - 3.28.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Tue May 29 2018 Kalev Lember - 3.28.2-1 +- Update to 3.28.2 + +* Wed May 23 2018 Pete Walter - 3.28.1-4 +- Change NetworkManager-wifi requires to recommends (#1478661) + +* Tue May 22 2018 Ray Strode - 3.28.1-3 +- Change vino requires to a vino recommends + +* Fri Apr 13 2018 Kalev Lember - 3.28.1-2 +- Backport new thunderbolt panel + +* Tue Apr 10 2018 Pete Walter - 3.28.1-1 +- Rename control-center to gnome-control-center