diff options
Diffstat (limited to 'panels/info-overview/cc-info-overview-panel.c')
-rw-r--r-- | panels/info-overview/cc-info-overview-panel.c | 993 |
1 files changed, 993 insertions, 0 deletions
diff --git a/panels/info-overview/cc-info-overview-panel.c b/panels/info-overview/cc-info-overview-panel.c new file mode 100644 index 0000000..1ae5c7a --- /dev/null +++ b/panels/info-overview/cc-info-overview-panel.c @@ -0,0 +1,993 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2019 Purism SPC + * Copyright (C) 2017 Mohammed Sadiq <sadiq@sadiqpk.org> + * Copyright (C) 2010 Red Hat, Inc + * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com> + * + * 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 <http://www.gnu.org/licenses/>. + * + */ + +#include <config.h> + +#include "cc-hostname-entry.h" +#include "shell/cc-object-storage.h" + +#include "cc-info-overview-resources.h" +#include "info-cleanup.h" + +#include <glib.h> +#include <glib/gi18n.h> +#include <gio/gio.h> +#include <gio/gunixmounts.h> +#include <gio/gdesktopappinfo.h> + +#include <glibtop/fsusage.h> +#include <glibtop/mountlist.h> +#include <glibtop/mem.h> +#include <glibtop/sysinfo.h> +#include <udisks/udisks.h> +#include <gudev/gudev.h> + +#include <gdk/gdk.h> + +#ifdef GDK_WINDOWING_WAYLAND +#include <gdk/wayland/gdkwayland.h> +#endif +#ifdef GDK_WINDOWING_X11 +#include <gdk/x11/gdkx.h> +#endif + +#include "cc-list-row.h" +#include "cc-info-overview-panel.h" + +struct _CcInfoOverviewPanel +{ + CcPanel parent_instance; + + GtkEntry *device_name_entry; + GtkWidget *rename_button; + CcListRow *disk_row; + CcListRow *gnome_version_row; + CcListRow *graphics_row; + CcListRow *hardware_model_row; + GtkDialog *hostname_editor; + CcHostnameEntry *hostname_entry; + CcListRow *hostname_row; + CcListRow *memory_row; + GtkPicture *os_logo; + CcListRow *os_name_row; + CcListRow *os_build_row; + CcListRow *os_type_row; + CcListRow *processor_row; + AdwActionRow *software_updates_row; + CcListRow *virtualization_row; + CcListRow *windowing_system_row; +}; + +G_DEFINE_TYPE (CcInfoOverviewPanel, cc_info_overview_panel, CC_TYPE_PANEL) + +static char * +get_renderer_from_session (void) +{ + g_autoptr(GDBusProxy) session_proxy = NULL; + g_autoptr(GVariant) renderer_variant = NULL; + char *renderer; + g_autoptr(GError) error = NULL; + + session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.gnome.SessionManager", + "/org/gnome/SessionManager", + "org.gnome.SessionManager", + NULL, &error); + if (error != NULL) + { + g_warning ("Unable to connect to create a proxy for org.gnome.SessionManager: %s", + error->message); + return NULL; + } + + renderer_variant = g_dbus_proxy_get_cached_property (session_proxy, "Renderer"); + + if (!renderer_variant) + { + g_warning ("Unable to retrieve org.gnome.SessionManager.Renderer property"); + return NULL; + } + + renderer = info_cleanup (g_variant_get_string (renderer_variant, NULL)); + + return renderer; +} + +/* @env is an array of strings with each pair of strings being the + * key followed by the value */ +static char * +get_renderer_from_helper (const char **env) +{ + int status; + char *argv[] = { LIBEXECDIR "/gnome-control-center-print-renderer", NULL }; + g_auto(GStrv) envp = NULL; + g_autofree char *renderer = NULL; + g_autoptr(GError) error = NULL; + + g_debug ("About to launch '%s'", argv[0]); + + if (env != NULL) + { + guint i; + g_debug ("With environment:"); + envp = g_get_environ (); + for (i = 0; env != NULL && env[i] != NULL; i = i + 2) + { + g_debug (" %s = %s", env[i], env[i+1]); + envp = g_environ_setenv (envp, env[i], env[i+1], TRUE); + } + } + else + { + g_debug ("No additional environment variables"); + } + + if (!g_spawn_sync (NULL, (char **) argv, envp, 0, NULL, NULL, &renderer, NULL, &status, &error)) + { + g_debug ("Failed to get GPU: %s", error->message); + return NULL; + } + + if (!g_spawn_check_wait_status (status, NULL)) + return NULL; + + if (renderer == NULL || *renderer == '\0') + return NULL; + + return info_cleanup (renderer); +} + +typedef struct { + char *name; + gboolean is_default; +} GpuData; + +static int +gpu_data_sort (gconstpointer a, gconstpointer b) +{ + GpuData *gpu_a = (GpuData *) a; + GpuData *gpu_b = (GpuData *) b; + + if (gpu_a->is_default) + return 1; + if (gpu_b->is_default) + return -1; + return 0; +} + +static void +gpu_data_free (GpuData *data) +{ + g_free (data->name); + g_free (data); +} + +static char * +get_renderer_from_switcheroo (void) +{ + g_autoptr(GDBusProxy) switcheroo_proxy = NULL; + g_autoptr(GVariant) variant = NULL; + g_autoptr(GError) error = NULL; + GString *renderers_string; + guint i, num_children; + GSList *renderers, *l; + + switcheroo_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "net.hadess.SwitcherooControl", + "/net/hadess/SwitcherooControl", + "net.hadess.SwitcherooControl", + NULL, &error); + if (switcheroo_proxy == NULL) + { + g_debug ("Unable to connect to create a proxy for net.hadess.SwitcherooControl: %s", + error->message); + return NULL; + } + + variant = g_dbus_proxy_get_cached_property (switcheroo_proxy, "GPUs"); + + if (!variant) + { + g_debug ("Unable to retrieve net.hadess.SwitcherooControl.GPUs property, the daemon is likely not running"); + return NULL; + } + + renderers_string = g_string_new (NULL); + num_children = g_variant_n_children (variant); + renderers = NULL; + for (i = 0; i < num_children; i++) + { + g_autoptr(GVariant) gpu; + g_autoptr(GVariant) name = NULL; + g_autoptr(GVariant) env = NULL; + g_autoptr(GVariant) default_variant = NULL; + const char *name_s; + g_autofree const char **env_s = NULL; + gsize env_len; + g_autofree char *renderer = NULL; + GpuData *gpu_data; + + gpu = g_variant_get_child_value (variant, i); + if (!gpu || + !g_variant_is_of_type (gpu, G_VARIANT_TYPE ("a{s*}"))) + continue; + + name = g_variant_lookup_value (gpu, "Name", NULL); + env = g_variant_lookup_value (gpu, "Environment", NULL); + if (!name || !env) + continue; + name_s = g_variant_get_string (name, NULL); + g_debug ("Getting renderer from helper for GPU '%s'", name_s); + env_s = g_variant_get_strv (env, &env_len); + if (env_s != NULL && env_len % 2 != 0) + { + g_autofree char *debug = NULL; + debug = g_strjoinv ("\n", (char **) env_s); + g_warning ("Invalid environment returned from switcheroo:\n%s", debug); + g_clear_pointer (&env_s, g_free); + } + + renderer = get_renderer_from_helper (env_s); + default_variant = g_variant_lookup_value (gpu, "Default", NULL); + + /* We could give up if we don't have a renderer, but that + * might just mean gnome-session isn't installed. We fall back + * to the device name in udev instead, which is better than nothing */ + + gpu_data = g_new0 (GpuData, 1); + gpu_data->name = g_strdup (renderer ? renderer : name_s); + gpu_data->is_default = default_variant ? g_variant_get_boolean (default_variant) : FALSE; + renderers = g_slist_prepend (renderers, gpu_data); + } + + renderers = g_slist_sort (renderers, gpu_data_sort); + for (l = renderers; l != NULL; l = l->next) + { + GpuData *data = l->data; + if (renderers_string->len > 0) + g_string_append (renderers_string, " / "); + g_string_append (renderers_string, data->name); + } + g_slist_free_full (renderers, (GDestroyNotify) gpu_data_free); + + if (renderers_string->len == 0) + { + g_string_free (renderers_string, TRUE); + return NULL; + } + + return g_string_free (renderers_string, FALSE); +} + +static gchar * +get_graphics_hardware_string (void) +{ + g_autofree char *discrete_renderer = NULL; + g_autofree char *renderer = NULL; + + renderer = get_renderer_from_switcheroo (); + if (!renderer) + renderer = get_renderer_from_session (); + if (!renderer) + renderer = get_renderer_from_helper (NULL); + if (!renderer) + return g_strdup (_("Unknown")); + return g_strdup (renderer); +} + +static char * +get_os_name (void) +{ + g_autofree gchar *name = NULL; + g_autofree gchar *version_id = NULL; + g_autofree gchar *pretty_name = NULL; + + name = g_get_os_info (G_OS_INFO_KEY_NAME); + version_id = g_get_os_info (G_OS_INFO_KEY_VERSION_ID); + pretty_name = g_get_os_info (G_OS_INFO_KEY_PRETTY_NAME); + + if (pretty_name) + return g_steal_pointer (&pretty_name); + else if (name && version_id) + return g_strdup_printf ("%s %s", name, version_id); + else + return g_strdup (_("Unknown")); +} + +static char * +get_os_build_id (void) +{ + char *build_id = NULL; + + build_id = g_get_os_info ("BUILD_ID"); + + return build_id; +} + +static char * +get_os_type (void) +{ + if (GLIB_SIZEOF_VOID_P == 8) + /* translators: This is the type of architecture for the OS */ + return g_strdup_printf (_("64-bit")); + else + /* translators: This is the type of architecture for the OS */ + return g_strdup_printf (_("32-bit")); +} + +static void +get_primary_disc_info (CcInfoOverviewPanel *self) +{ + g_autoptr(UDisksClient) client = NULL; + GDBusObjectManager *manager; + g_autolist(GDBusObject) objects = NULL; + GList *l; + guint64 total_size; + g_autoptr(GError) error = NULL; + + total_size = 0; + + client = udisks_client_new_sync (NULL, &error); + if (client == NULL) + { + g_warning ("Unable to get UDisks client: %s. Disk information will not be available.", + error->message); + cc_list_row_set_secondary_label (self->disk_row, _("Unknown")); + return; + } + + manager = udisks_client_get_object_manager (client); + objects = g_dbus_object_manager_get_objects (manager); + + for (l = objects; l != NULL; l = l->next) + { + UDisksDrive *drive; + drive = udisks_object_peek_drive (UDISKS_OBJECT (l->data)); + + /* Skip removable devices */ + if (drive == NULL || + udisks_drive_get_removable (drive) || + udisks_drive_get_ejectable (drive)) + { + continue; + } + + total_size += udisks_drive_get_size (drive); + } + + if (total_size > 0) + { + g_autofree gchar *size = g_format_size (total_size); + cc_list_row_set_secondary_label (self->disk_row, size); + } + else + { + cc_list_row_set_secondary_label (self->disk_row, _("Unknown")); + } +} + +static void +get_hardware_model (CcInfoOverviewPanel *self) +{ + g_autoptr(GDBusProxy) hostnamed_proxy = NULL; + g_autoptr(GVariant) vendor_variant = NULL; + g_autoptr(GVariant) model_variant = NULL; + const char *vendor_string, *model_string; + g_autoptr(GError) error = NULL; + + hostnamed_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.freedesktop.hostname1", + "/org/freedesktop/hostname1", + "org.freedesktop.hostname1", + NULL, + &error); + if (hostnamed_proxy == NULL) + { + g_debug ("Couldn't get hostnamed to start, bailing: %s", error->message); + return; + } + + vendor_variant = g_dbus_proxy_get_cached_property (hostnamed_proxy, "HardwareVendor"); + if (!vendor_variant) + { + g_debug ("Unable to retrieve org.freedesktop.hostname1.HardwareVendor property"); + return; + } + + model_variant = g_dbus_proxy_get_cached_property (hostnamed_proxy, "HardwareModel"); + if (!model_variant) + { + g_debug ("Unable to retrieve org.freedesktop.hostname1.HardwareModel property"); + return; + } + + vendor_string = g_variant_get_string (vendor_variant, NULL), + model_string = g_variant_get_string (model_variant, NULL); + + if (vendor_string && g_strcmp0 (vendor_string, "") != 0) + { + g_autofree gchar *vendor_model = NULL; + + vendor_model = g_strdup_printf ("%s %s", vendor_string, model_string); + + cc_list_row_set_secondary_label (self->hardware_model_row, vendor_model); + gtk_widget_set_visible (GTK_WIDGET (self->hardware_model_row), TRUE); + } +} + +static char * +get_cpu_info (const glibtop_sysinfo *info) +{ + g_autoptr(GHashTable) counts = NULL; + g_autoptr(GString) cpu = NULL; + GHashTableIter iter; + gpointer key, value; + int i; + int j; + + counts = g_hash_table_new (g_str_hash, g_str_equal); + + /* count duplicates */ + for (i = 0; i != info->ncpu; ++i) + { + const char * const keys[] = { "model name", "cpu", "Processor" }; + char *model; + int *count; + + model = NULL; + + for (j = 0; model == NULL && j != G_N_ELEMENTS (keys); ++j) + { + model = g_hash_table_lookup (info->cpuinfo[i].values, + keys[j]); + } + + if (model == NULL) + continue; + + count = g_hash_table_lookup (counts, model); + if (count == NULL) + g_hash_table_insert (counts, model, GINT_TO_POINTER (1)); + else + g_hash_table_replace (counts, model, GINT_TO_POINTER (GPOINTER_TO_INT (count) + 1)); + } + + cpu = g_string_new (NULL); + g_hash_table_iter_init (&iter, counts); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + g_autofree char *cleanedup = NULL; + int count; + + count = GPOINTER_TO_INT (value); + cleanedup = info_cleanup ((const char *) key); + if (cpu->len != 0) + g_string_append_printf (cpu, " "); + if (count > 1) + g_string_append_printf (cpu, "%s \303\227 %d", cleanedup, count); + else + g_string_append_printf (cpu, "%s", cleanedup); + } + + return g_strdup (cpu->str); +} + +static struct { + const char *id; + const char *display; +} const virt_tech[] = { + { "kvm", "KVM" }, + { "qemu", "QEmu" }, + { "vmware", "VMware" }, + { "microsoft", "Microsoft" }, + { "oracle", "Oracle" }, + { "xen", "Xen" }, + { "bochs", "Bochs" }, + { "chroot", "chroot" }, + { "openvz", "OpenVZ" }, + { "lxc", "LXC" }, + { "lxc-libvirt", "LXC (libvirt)" }, + { "systemd-nspawn", "systemd (nspawn)" } +}; + +static void +set_virtualization_label (CcInfoOverviewPanel *self, + const char *virt) +{ + const char *display_name; + guint i; + + if (virt == NULL || *virt == '\0') + { + gtk_widget_hide (GTK_WIDGET (self->virtualization_row)); + return; + } + + gtk_widget_show (GTK_WIDGET (self->virtualization_row)); + + display_name = NULL; + for (i = 0; i < G_N_ELEMENTS (virt_tech); i++) + { + if (g_str_equal (virt_tech[i].id, virt)) + { + display_name = _(virt_tech[i].display); + break; + } + } + + cc_list_row_set_secondary_label (self->virtualization_row, display_name ? display_name : virt); +} + +static void +info_overview_panel_setup_virt (CcInfoOverviewPanel *self) +{ + g_autoptr(GError) error = NULL; + g_autoptr(GDBusProxy) systemd_proxy = NULL; + g_autoptr(GVariant) variant = NULL; + GVariant *inner; + + systemd_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1", + NULL, + &error); + + if (systemd_proxy == NULL) + { + g_debug ("systemd not available, bailing: %s", error->message); + set_virtualization_label (self, NULL); + return; + } + + variant = g_dbus_proxy_call_sync (systemd_proxy, + "org.freedesktop.DBus.Properties.Get", + g_variant_new ("(ss)", "org.freedesktop.systemd1.Manager", "Virtualization"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (variant == NULL) + { + g_debug ("Failed to get property '%s': %s", "Virtualization", error->message); + set_virtualization_label (self, NULL); + return; + } + + g_variant_get (variant, "(v)", &inner); + set_virtualization_label (self, g_variant_get_string (inner, NULL)); +} + +static const char * +get_windowing_system (void) +{ + GdkDisplay *display; + + display = gdk_display_get_default (); + +#if defined(GDK_WINDOWING_X11) + if (GDK_IS_X11_DISPLAY (display)) + return _("X11"); +#endif /* GDK_WINDOWING_X11 */ +#if defined(GDK_WINDOWING_WAYLAND) + if (GDK_IS_WAYLAND_DISPLAY (display)) + return _("Wayland"); +#endif /* GDK_WINDOWING_WAYLAND */ + return C_("Windowing system (Wayland, X11, or Unknown)", "Unknown"); +} + +static guint64 +get_ram_size_libgtop (void) +{ + glibtop_mem mem; + + glibtop_get_mem (&mem); + return mem.total; +} + +static guint64 +get_ram_size_dmi (void) +{ + g_autoptr(GUdevClient) client = NULL; + g_autoptr(GUdevDevice) dmi = NULL; + const gchar * const subsystems[] = {"dmi", NULL }; + guint64 ram_total = 0; + guint64 num_ram; + guint i; + + client = g_udev_client_new (subsystems); + dmi = g_udev_client_query_by_sysfs_path (client, "/sys/devices/virtual/dmi/id"); + if (!dmi) + return 0; + num_ram = g_udev_device_get_property_as_uint64 (dmi, "MEMORY_ARRAY_NUM_DEVICES"); + for (i = 0; i < num_ram ; i++) { + g_autofree char *prop = NULL; + + prop = g_strdup_printf ("MEMORY_DEVICE_%d_SIZE", i); + ram_total += g_udev_device_get_property_as_uint64 (dmi, prop); + } + return ram_total; +} + +static char * +get_gnome_version (GDBusProxy *proxy) +{ + g_autoptr(GVariant) variant = NULL; + const char *gnome_version = NULL; + if (!proxy) + return NULL; + + variant = g_dbus_proxy_get_cached_property (proxy, "ShellVersion"); + if (!variant) + return NULL; + + gnome_version = g_variant_get_string (variant, NULL); + if (!gnome_version || *gnome_version == '\0') + return NULL; + return g_strdup (gnome_version); +} + +static void +shell_proxy_ready (GObject *source, + GAsyncResult *res, + CcInfoOverviewPanel *self) +{ + g_autoptr(GDBusProxy) proxy = NULL; + g_autoptr(GError) error = NULL; + g_autoptr(GVariant) variant = NULL; + g_autofree char *gnome_version = NULL; + + proxy = cc_object_storage_create_dbus_proxy_finish (res, &error); + if (!proxy) + { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + g_warning ("Failed to contact gnome-shell: %s", error->message); + } + + gnome_version = get_gnome_version (proxy); + + if (!gnome_version) + { + /* translators: this is the placeholder string when the GNOME Shell + * version couldn't be loaded, eg. “GNOME Version: Not Available” */ + cc_list_row_set_secondary_label (self->gnome_version_row, _("Not Available")); + } + else + { + cc_list_row_set_secondary_label (self->gnome_version_row, gnome_version); + } +} + +static void +info_overview_panel_setup_overview (CcInfoOverviewPanel *self) +{ + g_autofree gchar *gnome_version = NULL; + guint64 ram_size; + const glibtop_sysinfo *info; + g_autofree char *memory_text = NULL; + g_autofree char *cpu_text = NULL; + g_autofree char *os_type_text = NULL; + g_autofree char *os_name_text = NULL; + g_autofree char *os_build_text = NULL; + g_autofree gchar *graphics_hardware_string = NULL; + + cc_object_storage_create_dbus_proxy (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + "org.gnome.Shell", + "/org/gnome/Shell", + "org.gnome.Shell", + cc_panel_get_cancellable (CC_PANEL (self)), + (GAsyncReadyCallback) shell_proxy_ready, + self); + + get_hardware_model (self); + + ram_size = get_ram_size_dmi (); + if (ram_size == 0) + ram_size = get_ram_size_libgtop (); + memory_text = g_format_size_full (ram_size, G_FORMAT_SIZE_IEC_UNITS); + cc_list_row_set_secondary_label (self->memory_row, memory_text); + + info = glibtop_get_sysinfo (); + + cpu_text = get_cpu_info (info); + cc_list_row_set_secondary_markup (self->processor_row, cpu_text); + + graphics_hardware_string = get_graphics_hardware_string (); + cc_list_row_set_secondary_markup (self->graphics_row, graphics_hardware_string); + + get_primary_disc_info (self); + + os_name_text = get_os_name (); + cc_list_row_set_secondary_label (self->os_name_row, os_name_text); + + os_build_text = get_os_build_id (); + cc_list_row_set_secondary_label (self->os_build_row, os_build_text); + gtk_widget_set_visible (GTK_WIDGET (self->os_build_row), os_build_text != NULL); + + os_type_text = get_os_type (); + cc_list_row_set_secondary_label (self->os_type_row, os_type_text); + + cc_list_row_set_secondary_label (self->windowing_system_row, get_windowing_system ()); +} + +static gboolean +does_gnome_software_allow_updates (void) +{ + const gchar *schema_id = "org.gnome.software"; + GSettingsSchemaSource *source; + g_autoptr(GSettingsSchema) schema = NULL; + g_autoptr(GSettings) settings = NULL; + + source = g_settings_schema_source_get_default (); + + if (source == NULL) + return FALSE; + + schema = g_settings_schema_source_lookup (source, schema_id, FALSE); + + if (schema == NULL) + return FALSE; + + settings = g_settings_new (schema_id); + return g_settings_get_boolean (settings, "allow-updates"); +} + +static gboolean +does_gnome_software_exist (void) +{ + g_autofree gchar *path = g_find_program_in_path ("gnome-software"); + return path != NULL; +} + +static gboolean +does_gpk_update_viewer_exist (void) +{ + g_autofree gchar *path = g_find_program_in_path ("gpk-update-viewer"); + return path != NULL; +} + +static void +open_software_update (CcInfoOverviewPanel *self) +{ + g_autoptr(GError) error = NULL; + gboolean ret; + char *argv[3]; + + if (does_gnome_software_exist ()) + { + argv[0] = "gnome-software"; + argv[1] = "--mode=updates"; + argv[2] = NULL; + } + else + { + argv[0] = "gpk-update-viewer"; + argv[1] = NULL; + } + ret = g_spawn_async (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error); + if (!ret) + g_warning ("Failed to spawn %s: %s", argv[0], error->message); +} + +static void +on_device_name_entry_changed (CcInfoOverviewPanel *self) +{ + const gchar *current_hostname, *new_hostname; + + current_hostname = gtk_editable_get_text (GTK_EDITABLE (self->hostname_entry)); + new_hostname = gtk_editable_get_text (GTK_EDITABLE (self->device_name_entry)); + gtk_widget_set_sensitive (self->rename_button, + g_strcmp0 (current_hostname, new_hostname) != 0); +} + +static void +update_device_name (CcInfoOverviewPanel *self) +{ + const gchar *hostname; + + /* We simply change the CcHostnameEntry text. CcHostnameEntry + * listens to changes and updates hostname on change. + */ + hostname = gtk_editable_get_text (GTK_EDITABLE (self->device_name_entry)); + gtk_editable_set_text (GTK_EDITABLE (self->hostname_entry), hostname); +} + +static void +on_hostname_editor_dialog_response_cb (GtkDialog *dialog, + gint response, + CcInfoOverviewPanel *self) +{ + if (response == GTK_RESPONSE_APPLY) + { + update_device_name (self); + } + + gtk_window_close (GTK_WINDOW (dialog)); +} + +static void +on_device_name_entry_activated_cb (CcInfoOverviewPanel *self) +{ + update_device_name (self); + gtk_window_close (GTK_WINDOW (self->hostname_editor)); +} + +static void +open_hostname_edit_dialog (CcInfoOverviewPanel *self) +{ + GtkWindow *toplevel; + CcShell *shell; + const gchar *hostname; + + g_assert (CC_IS_INFO_OVERVIEW_PANEL (self)); + + 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); + + hostname = gtk_editable_get_text (GTK_EDITABLE (self->hostname_entry)); + gtk_editable_set_text (GTK_EDITABLE (self->device_name_entry), hostname); + gtk_widget_grab_focus (GTK_WIDGET (self->device_name_entry)); + + gtk_window_present (GTK_WINDOW (self->hostname_editor)); + +} + +static void +cc_info_panel_row_activated_cb (CcInfoOverviewPanel *self, + AdwActionRow *row) +{ + g_assert (CC_IS_INFO_OVERVIEW_PANEL (self)); + g_assert (ADW_IS_ACTION_ROW (row)); + + if (row == ADW_ACTION_ROW (self->hostname_row)) + open_hostname_edit_dialog (self); + else if (row == self->software_updates_row) + open_software_update (self); +} + +#if !defined(DISTRIBUTOR_LOGO) || defined(DARK_MODE_DISTRIBUTOR_LOGO) +static gboolean +use_dark_theme (CcInfoOverviewPanel *panel) +{ + AdwStyleManager *style_manager = adw_style_manager_get_default (); + + return adw_style_manager_get_dark (style_manager); +} +#endif + +static void +setup_os_logo (CcInfoOverviewPanel *panel) +{ +#ifdef DISTRIBUTOR_LOGO +#ifdef DARK_MODE_DISTRIBUTOR_LOGO + if (use_dark_theme (panel)) + { + gtk_picture_set_filename (panel->os_logo, DARK_MODE_DISTRIBUTOR_LOGO); + return; + } +#endif + gtk_picture_set_filename (panel->os_logo, DISTRIBUTOR_LOGO); + return; +#else + GtkIconTheme *icon_theme; + g_autofree char *logo_name = g_get_os_info ("LOGO"); + g_autoptr(GtkIconPaintable) icon_paintable = NULL; + g_autoptr(GPtrArray) array = NULL; + g_autoptr(GIcon) icon = NULL; + gboolean dark; + + dark = use_dark_theme (panel); + if (logo_name == NULL) + logo_name = g_strdup ("gnome-logo"); + + array = g_ptr_array_new_with_free_func (g_free); + if (dark) + g_ptr_array_add (array, (gpointer) g_strdup_printf ("%s-text-dark", logo_name)); + g_ptr_array_add (array, (gpointer) g_strdup_printf ("%s-text", logo_name)); + if (dark) + g_ptr_array_add (array, (gpointer) g_strdup_printf ("%s-dark", logo_name)); + g_ptr_array_add (array, (gpointer) g_strdup_printf ("%s", logo_name)); + + icon = g_themed_icon_new_from_names ((char **) array->pdata, array->len); + icon_theme = gtk_icon_theme_get_for_display (gdk_display_get_default ()); + icon_paintable = gtk_icon_theme_lookup_by_gicon (icon_theme, icon, + 192, + gtk_widget_get_scale_factor (GTK_WIDGET (panel)), + gtk_widget_get_direction (GTK_WIDGET (panel)), + 0); + gtk_picture_set_paintable (panel->os_logo, GDK_PAINTABLE (icon_paintable)); +#endif +} + +static void +cc_info_overview_panel_class_init (CcInfoOverviewPanelClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + 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); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, disk_row); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, gnome_version_row); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, graphics_row); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, hardware_model_row); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, hostname_editor); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, hostname_entry); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, hostname_row); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, memory_row); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, os_logo); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, os_name_row); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, os_build_row); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, os_type_row); + 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, virtualization_row); + gtk_widget_class_bind_template_child (widget_class, CcInfoOverviewPanel, windowing_system_row); + + gtk_widget_class_bind_template_callback (widget_class, cc_info_panel_row_activated_cb); + gtk_widget_class_bind_template_callback (widget_class, on_device_name_entry_changed); + gtk_widget_class_bind_template_callback (widget_class, on_device_name_entry_activated_cb); + gtk_widget_class_bind_template_callback (widget_class, on_hostname_editor_dialog_response_cb); + + g_type_ensure (CC_TYPE_LIST_ROW); + g_type_ensure (CC_TYPE_HOSTNAME_ENTRY); +} + +static void +cc_info_overview_panel_init (CcInfoOverviewPanel *self) +{ + AdwStyleManager *style_manager; + + gtk_widget_init_template (GTK_WIDGET (self)); + + g_resources_register (cc_info_overview_get_resource ()); + + if ((!does_gnome_software_exist () || !does_gnome_software_allow_updates ()) && !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); + + style_manager = adw_style_manager_get_default (); + g_signal_connect_swapped (style_manager, "notify::dark", G_CALLBACK (setup_os_logo), self); + setup_os_logo (self); +} + +GtkWidget * +cc_info_overview_panel_new (void) +{ + return g_object_new (CC_TYPE_INFO_OVERVIEW_PANEL, + NULL); +} |