gnome-control-center/panels/info/cc-info-panel.c
Bastien Nocera 3686cf7eb8 shell: Make all control-center plugins static
This makes loading faster, with less I/O, avoids unnecessary
code duplication (around 1k lines shaved), and ensures that
all the panels link and work appropriately.

By the same token, it will stop external panels from being
created, and loaded.

https://bugzilla.gnome.org/show_bug.cgi?id=690036
2012-12-11 17:07:39 +01:00

2112 lines
60 KiB
C

/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <config.h>
#include "cc-info-panel.h"
#include <polkit/polkit.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 "hostname-helper.h"
#include "gsd-disk-space-helper.h"
/* Autorun options */
#define PREF_MEDIA_AUTORUN_NEVER "autorun-never"
#define PREF_MEDIA_AUTORUN_X_CONTENT_START_APP "autorun-x-content-start-app"
#define PREF_MEDIA_AUTORUN_X_CONTENT_IGNORE "autorun-x-content-ignore"
#define PREF_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER "autorun-x-content-open-folder"
#define CUSTOM_ITEM_ASK "cc-item-ask"
#define CUSTOM_ITEM_DO_NOTHING "cc-item-do-nothing"
#define CUSTOM_ITEM_OPEN_FOLDER "cc-item-open-folder"
#define MEDIA_HANDLING_SCHEMA "org.gnome.desktop.media-handling"
/* Session */
#define GNOME_SESSION_MANAGER_SCHEMA "org.gnome.desktop.session"
#define KEY_SESSION_NAME "session-name"
#define SET_HOSTNAME_TIMEOUT 1
#define WID(w) (GtkWidget *) gtk_builder_get_object (self->priv->builder, w)
CC_PANEL_REGISTER (CcInfoPanel, cc_info_panel)
#define INFO_PANEL_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_INFO_PANEL, CcInfoPanelPrivate))
typedef struct {
/* Will be one of the other two below, or "Unknown" */
const char *hardware_string;
char *xorg_vesa_hardware;
char *glx_renderer;
} GraphicsData;
typedef enum {
PK_NOT_AVAILABLE,
UPDATES_AVAILABLE,
UPDATES_NOT_AVAILABLE,
CHECKING_UPDATES
} UpdatesState;
typedef struct
{
const char *content_type;
const char *label;
/* A pattern used to filter supported mime types
when changing preferred applications. NULL
means no other types should be changed */
const char *extra_type_filter;
} DefaultAppData;
struct _CcInfoPanelPrivate
{
GtkBuilder *builder;
char *gnome_version;
char *gnome_distributor;
char *gnome_date;
UpdatesState updates_state;
gboolean is_fallback;
/* Free space */
GList *primary_mounts;
guint64 total_bytes;
GCancellable *cancellable;
/* Media */
GSettings *media_settings;
GtkWidget *other_application_combo;
GDBusConnection *session_bus;
GDBusProxy *pk_proxy;
GDBusProxy *pk_transaction_proxy;
GDBusProxy *hostnamed_proxy;
guint set_hostname_timeout_source_id;
GraphicsData *graphics_data;
};
static void get_primary_disc_info_start (CcInfoPanel *self);
static void refresh_update_button (CcInfoPanel *self);
static void info_panel_set_hostname (CcInfoPanel *self);
typedef struct
{
char *major;
char *minor;
char *micro;
char *distributor;
char *date;
char **current;
} VersionData;
static void
version_start_element_handler (GMarkupParseContext *ctx,
const char *element_name,
const char **attr_names,
const char **attr_values,
gpointer user_data,
GError **error)
{
VersionData *data = user_data;
if (g_str_equal (element_name, "platform"))
data->current = &data->major;
else if (g_str_equal (element_name, "minor"))
data->current = &data->minor;
else if (g_str_equal (element_name, "micro"))
data->current = &data->micro;
else if (g_str_equal (element_name, "distributor"))
data->current = &data->distributor;
else if (g_str_equal (element_name, "date"))
data->current = &data->date;
else
data->current = NULL;
}
static void
version_end_element_handler (GMarkupParseContext *ctx,
const char *element_name,
gpointer user_data,
GError **error)
{
VersionData *data = user_data;
data->current = NULL;
}
static void
version_text_handler (GMarkupParseContext *ctx,
const char *text,
gsize text_len,
gpointer user_data,
GError **error)
{
VersionData *data = user_data;
if (data->current != NULL)
*data->current = g_strstrip (g_strdup (text));
}
static gboolean
load_gnome_version (char **version,
char **distributor,
char **date)
{
GMarkupParser version_parser = {
version_start_element_handler,
version_end_element_handler,
version_text_handler,
NULL,
NULL,
};
GError *error;
GMarkupParseContext *ctx;
char *contents;
gsize length;
VersionData *data;
gboolean ret;
ret = FALSE;
error = NULL;
if (!g_file_get_contents (DATADIR "/gnome/gnome-version.xml",
&contents,
&length,
&error))
return FALSE;
data = g_new0 (VersionData, 1);
ctx = g_markup_parse_context_new (&version_parser, 0, data, NULL);
if (!g_markup_parse_context_parse (ctx, contents, length, &error))
{
g_warning ("Invalid version file: '%s'", error->message);
}
else
{
if (version != NULL)
*version = g_strdup_printf ("%s.%s.%s", data->major, data->minor, data->micro);
if (distributor != NULL)
*distributor = g_strdup (data->distributor);
if (date != NULL)
*date = g_strdup (data->date);
ret = TRUE;
}
g_markup_parse_context_free (ctx);
g_free (data->major);
g_free (data->minor);
g_free (data->micro);
g_free (data->distributor);
g_free (data->date);
g_free (data);
g_free (contents);
return ret;
};
typedef struct
{
char *regex;
char *replacement;
} ReplaceStrings;
static char *
prettify_info (const char *info)
{
char *pretty;
int i;
static const ReplaceStrings rs[] = {
{ "Mesa DRI ", ""},
{ "Intel[(]R[)]", "Intel<sup>\302\256</sup>"},
{ "Core[(]TM[)]", "Core<sup>\342\204\242</sup>"},
{ "Atom[(]TM[)]", "Atom<sup>\342\204\242</sup>"},
{ "Graphics Controller", "Graphics"},
};
pretty = g_markup_escape_text (info, -1);
for (i = 0; i < G_N_ELEMENTS (rs); i++)
{
GError *error;
GRegex *re;
char *new;
error = NULL;
re = g_regex_new (rs[i].regex, 0, 0, &error);
if (re == NULL)
{
g_warning ("Error building regex: %s", error->message);
g_error_free (error);
continue;
}
new = g_regex_replace_literal (re,
pretty,
-1,
0,
rs[i].replacement,
0,
&error);
g_regex_unref (re);
if (error != NULL)
{
g_warning ("Error replacing %s: %s", rs[i].regex, error->message);
g_error_free (error);
continue;
}
g_free (pretty);
pretty = new;
}
return pretty;
}
static void
graphics_data_free (GraphicsData *gdata)
{
g_free (gdata->xorg_vesa_hardware);
g_free (gdata->glx_renderer);
g_slice_free (GraphicsData, gdata);
}
static char *
get_graphics_data_glx_renderer (void)
{
GError *error;
GRegex *re;
GMatchInfo *match_info;
char *output;
char *result;
GString *info;
info = g_string_new (NULL);
error = NULL;
g_spawn_command_line_sync ("glxinfo -l", &output, NULL, NULL, &error);
if (error != NULL)
{
g_warning ("Unable to get graphics info: %s", error->message);
g_error_free (error);
return NULL;
}
re = g_regex_new ("^OpenGL renderer string: (.+)$", G_REGEX_MULTILINE, 0, &error);
if (re == NULL)
{
g_warning ("Error building regex: %s", error->message);
g_error_free (error);
goto out;
}
g_regex_match (re, output, 0, &match_info);
while (g_match_info_matches (match_info))
{
char *device;
device = g_match_info_fetch (match_info, 1);
g_string_append_printf (info, "%s ", device);
g_free (device);
g_match_info_next (match_info, NULL);
}
g_match_info_free (match_info);
g_regex_unref (re);
out:
g_free (output);
result = prettify_info (info->str);
g_string_free (info, TRUE);
return result;
}
static char *
get_graphics_data_xorg_vesa_hardware (void)
{
char *display_num;
char *log_path;
char *log_contents;
gsize log_len;
GError *error = NULL;
GRegex *re;
GMatchInfo *match;
char *result = NULL;
{
const char *display;
display = g_getenv ("DISPLAY");
if (!display)
return NULL;
re = g_regex_new ("^:([0-9]+)", 0, 0, NULL);
g_assert (re != NULL);
g_regex_match (re, display, 0, &match);
if (!g_match_info_matches (match))
{
g_regex_unref (re);
g_match_info_free (match);
return NULL;
}
display_num = g_match_info_fetch (match, 1);
g_regex_unref (re);
re = NULL;
g_match_info_free (match);
match = NULL;
}
log_path = g_strdup_printf ("/var/log/Xorg.%s.log", display_num);
g_free (display_num);
log_contents = NULL;
g_file_get_contents (log_path, &log_contents, &log_len, &error);
g_free (log_path);
if (!log_contents)
return NULL;
re = g_regex_new ("VESA VBE OEM Product: (.*)$", G_REGEX_MULTILINE, 0, NULL);
g_assert (re != NULL);
g_regex_match (re, log_contents, 0, &match);
if (g_match_info_matches (match))
{
char *tmp;
char *pretty_tmp;
tmp = g_match_info_fetch (match, 1);
pretty_tmp = prettify_info (tmp);
g_free (tmp);
result = g_strdup_printf ("VESA: %s", pretty_tmp);
g_free (pretty_tmp);
}
g_match_info_free (match);
g_regex_unref (re);
return result;
}
static GraphicsData *
get_graphics_data (void)
{
GraphicsData *result;
result = g_slice_new0 (GraphicsData);
result->glx_renderer = get_graphics_data_glx_renderer ();
result->xorg_vesa_hardware = get_graphics_data_xorg_vesa_hardware ();
if (result->xorg_vesa_hardware != NULL)
result->hardware_string = result->xorg_vesa_hardware;
else if (result->glx_renderer != NULL)
result->hardware_string = result->glx_renderer;
else
result->hardware_string = _("Unknown");
return result;
}
static gboolean
set_hostname_timeout (CcInfoPanel *self)
{
self->priv->set_hostname_timeout_source_id = 0;
info_panel_set_hostname (self);
return FALSE;
}
static void
remove_hostname_timeout (CcInfoPanel *panel)
{
CcInfoPanelPrivate *priv = panel->priv;
if (priv->set_hostname_timeout_source_id)
g_source_remove (priv->set_hostname_timeout_source_id);
priv->set_hostname_timeout_source_id = 0;
}
static void
reset_hostname_timeout (CcInfoPanel *panel)
{
remove_hostname_timeout (panel);
panel->priv->set_hostname_timeout_source_id = g_timeout_add_seconds (SET_HOSTNAME_TIMEOUT,
(GSourceFunc) set_hostname_timeout,
panel);
}
static void
cc_info_panel_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
switch (property_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
cc_info_panel_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
switch (property_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
cc_info_panel_dispose (GObject *object)
{
CcInfoPanelPrivate *priv = CC_INFO_PANEL (object)->priv;
if (priv->set_hostname_timeout_source_id)
{
remove_hostname_timeout (CC_INFO_PANEL (object));
set_hostname_timeout (CC_INFO_PANEL (object));
}
if (priv->builder != NULL)
{
g_object_unref (priv->builder);
priv->builder = NULL;
}
if (priv->pk_proxy != NULL)
{
g_object_unref (priv->pk_proxy);
priv->pk_proxy = NULL;
}
if (priv->pk_transaction_proxy != NULL)
{
g_object_unref (priv->pk_transaction_proxy);
priv->pk_transaction_proxy = NULL;
}
if (priv->graphics_data != NULL)
{
graphics_data_free (priv->graphics_data);
priv->graphics_data = NULL;
}
G_OBJECT_CLASS (cc_info_panel_parent_class)->dispose (object);
}
static void
cc_info_panel_finalize (GObject *object)
{
CcInfoPanelPrivate *priv = CC_INFO_PANEL (object)->priv;
g_clear_pointer (&priv->cancellable, g_cancellable_cancel);
g_free (priv->gnome_version);
g_free (priv->gnome_date);
g_free (priv->gnome_distributor);
g_clear_object (&priv->hostnamed_proxy);
g_clear_object (&priv->media_settings);
G_OBJECT_CLASS (cc_info_panel_parent_class)->finalize (object);
}
static void
cc_info_panel_class_init (CcInfoPanelClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (klass, sizeof (CcInfoPanelPrivate));
object_class->get_property = cc_info_panel_get_property;
object_class->set_property = cc_info_panel_set_property;
object_class->dispose = cc_info_panel_dispose;
object_class->finalize = cc_info_panel_finalize;
}
static char *
get_os_type (void)
{
int bits;
char *buffer;
char *name;
char *result;
name = NULL;
if (g_file_get_contents ("/etc/os-release", &buffer, NULL, NULL))
{
char *start, *end;
start = end = NULL;
if ((start = strstr (buffer, "PRETTY_NAME=\"")) != NULL)
{
start += strlen ("PRETTY_NAME=\"");
end = strchr (start, '"');
}
if (start != NULL && end != NULL)
{
name = g_strndup (start, end - start);
}
g_free (buffer);
}
if (GLIB_SIZEOF_VOID_P == 8)
bits = 64;
else
bits = 32;
/* translators: This is the name of the OS, followed by the type
* of architecture, for example:
* "Fedora 18 (Spherical Cow) 64-bit" or "Ubuntu (Oneric Ocelot) 32-bit" */
if (name)
result = g_strdup_printf (_("%s %d-bit"), name, bits);
else
result = g_strdup_printf (_("%d-bit"), bits);
g_free (name);
return result;
}
static void
query_done (GFile *file,
GAsyncResult *res,
CcInfoPanel *self)
{
GFileInfo *info;
GError *error = NULL;
self->priv->cancellable = NULL;
info = g_file_query_filesystem_info_finish (file, res, &error);
if (info != NULL)
{
self->priv->total_bytes += g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE);
g_object_unref (info);
}
else
{
char *path;
path = g_file_get_path (file);
g_warning ("Failed to get filesystem free space for '%s': %s", path, error->message);
g_free (path);
g_error_free (error);
}
/* And onto the next element */
get_primary_disc_info_start (self);
}
static void
get_primary_disc_info_start (CcInfoPanel *self)
{
GUnixMountEntry *mount;
GFile *file;
if (self->priv->primary_mounts == NULL)
{
char *size;
GtkWidget *widget;
size = g_format_size (self->priv->total_bytes);
widget = WID ("disk_label");
gtk_label_set_text (GTK_LABEL (widget), size);
g_free (size);
return;
}
mount = self->priv->primary_mounts->data;
self->priv->primary_mounts = g_list_remove (self->priv->primary_mounts, mount);
file = g_file_new_for_path (g_unix_mount_get_mount_path (mount));
g_unix_mount_free (mount);
self->priv->cancellable = g_cancellable_new ();
g_file_query_filesystem_info_async (file,
G_FILE_ATTRIBUTE_FILESYSTEM_SIZE,
0,
self->priv->cancellable,
(GAsyncReadyCallback) query_done,
self);
g_object_unref (file);
}
static void
get_primary_disc_info (CcInfoPanel *self)
{
GList *points;
GList *p;
points = g_unix_mount_points_get (NULL);
for (p = points; p != NULL; p = p->next)
{
GUnixMountEntry *mount = p->data;
const char *mount_path;
mount_path = g_unix_mount_get_mount_path (mount);
if (gsd_should_ignore_unix_mount (mount) ||
gsd_is_removable_mount (mount) ||
g_str_has_prefix (mount_path, "/media/") ||
g_str_has_prefix (mount_path, g_get_home_dir ()))
{
g_unix_mount_free (mount);
continue;
}
self->priv->primary_mounts = g_list_prepend (self->priv->primary_mounts, mount);
}
g_list_free (points);
get_primary_disc_info_start (self);
}
static char *
remove_duplicate_whitespace (const char *old)
{
char *new;
GRegex *re;
GError *error;
error = NULL;
re = g_regex_new ("[ \t\n\r]+", G_REGEX_MULTILINE, 0, &error);
if (re == NULL)
{
g_warning ("Error building regex: %s", error->message);
g_error_free (error);
return g_strdup (old);
}
new = g_regex_replace (re,
old,
-1,
0,
" ",
0,
&error);
g_regex_unref (re);
if (new == NULL)
{
g_warning ("Error replacing string: %s", error->message);
g_error_free (error);
return g_strdup (old);
}
return new;
}
static char *
get_cpu_info (const glibtop_sysinfo *info)
{
GHashTable *counts;
GString *cpu;
char *ret;
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))
{
char *stripped;
int count;
count = GPOINTER_TO_INT (value);
stripped = remove_duplicate_whitespace ((const char *)key);
if (count > 1)
g_string_append_printf (cpu, "%s \303\227 %d ", stripped, count);
else
g_string_append_printf (cpu, "%s ", stripped);
g_free (stripped);
}
g_hash_table_destroy (counts);
ret = prettify_info (cpu->str);
g_string_free (cpu, TRUE);
return ret;
}
static void
on_section_changed (GtkTreeSelection *selection,
gpointer data)
{
CcInfoPanel *self = CC_INFO_PANEL (data);
GtkTreeIter iter;
GtkTreeModel *model;
GtkTreePath *path;
gint *indices;
int index;
if (!gtk_tree_selection_get_selected (selection, &model, &iter))
return;
path = gtk_tree_model_get_path (model, &iter);
indices = gtk_tree_path_get_indices (path);
index = indices[0];
if (index >= 0)
{
g_object_set (G_OBJECT (WID ("notebook")),
"page", index, NULL);
}
gtk_tree_path_free (path);
}
static void
info_panel_setup_graphics (CcInfoPanel *self)
{
GtkWidget *widget;
widget = WID ("graphics_driver_label");
gtk_label_set_markup (GTK_LABEL (widget), self->priv->graphics_data->hardware_string);
}
static void
move_one_up (GtkWidget *table,
GtkWidget *child)
{
int top_attach, bottom_attach;
gtk_container_child_get (GTK_CONTAINER (table),
child,
"top-attach", &top_attach,
"bottom-attach", &bottom_attach,
NULL);
gtk_container_child_set (GTK_CONTAINER (table),
child,
"top-attach", top_attach - 1,
"bottom-attach", bottom_attach - 1,
NULL);
}
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 (CcInfoPanel *self,
const char *virt)
{
const char *display_name;
GtkWidget *widget;
guint i;
if (virt == NULL || *virt == '\0')
{
gtk_widget_hide (WID ("virt_type_label"));
gtk_widget_hide (WID ("label18"));
move_one_up (WID("table1"), WID("label8"));
move_one_up (WID("table1"), WID("disk_label"));
return;
}
display_name = NULL;
for (i = 0; i < G_N_ELEMENTS (virt_tech); i++)
{
if (g_str_equal (virt_tech[i].id, virt) == 0)
{
display_name = _(virt_tech[i].display);
break;
}
}
widget = WID ("virt_type_label");
gtk_label_set_text (GTK_LABEL (widget), display_name ? display_name : virt);
}
static void
info_panel_setup_virt (CcInfoPanel *self)
{
GError *error = NULL;
GDBusProxy *systemd_proxy;
GVariant *variant;
GVariant *inner;
char *str;
str = NULL;
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);
g_error_free (error);
goto bail;
}
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);
g_error_free (error);
g_object_unref (systemd_proxy);
goto bail;
}
g_variant_get (variant, "(v)", &inner);
str = g_variant_dup_string (inner, NULL);
g_variant_unref (variant);
g_object_unref (systemd_proxy);
bail:
set_virtualization_label (self, str);
g_free (str);
}
static void
default_app_changed (GtkAppChooserButton *button,
CcInfoPanel *self)
{
GAppInfo *info;
GError *error = NULL;
DefaultAppData *app_data;
int i;
info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (button));
app_data = g_object_get_data (G_OBJECT (button), "cc-default-app-data");
if (g_app_info_set_as_default_for_type (info, app_data->content_type, &error) == FALSE)
{
g_warning ("Failed to set '%s' as the default application for '%s': %s",
g_app_info_get_name (info), app_data->content_type, error->message);
g_error_free (error);
error = NULL;
}
if (app_data->extra_type_filter)
{
const char *const *mime_types;
GPatternSpec *pattern;
pattern = g_pattern_spec_new (app_data->extra_type_filter);
mime_types = g_app_info_get_supported_types (info);
for (i = 0; mime_types[i]; i++)
{
if (!g_pattern_match_string (pattern, mime_types[i]))
continue;
if (g_app_info_set_as_default_for_type (info, mime_types[i], &error) == FALSE)
{
g_warning ("Failed to set '%s' as the default application for secondary "
"content type '%s': %s",
g_app_info_get_name (info), mime_types[i], error->message);
g_error_free (error);
}
}
g_pattern_spec_free (pattern);
}
g_object_unref (info);
}
static void
info_panel_setup_default_app (CcInfoPanel *self,
DefaultAppData *data,
guint left_attach,
guint top_attach)
{
GtkWidget *button;
GtkWidget *grid;
GtkWidget *label;
grid = WID ("default_apps_grid");
button = gtk_app_chooser_button_new (data->content_type);
g_object_set_data (G_OBJECT (button), "cc-default-app-data", data);
gtk_app_chooser_button_set_show_default_item (GTK_APP_CHOOSER_BUTTON (button), TRUE);
gtk_grid_attach (GTK_GRID (grid), button, left_attach, top_attach,
1, 1);
g_signal_connect (G_OBJECT (button), "changed",
G_CALLBACK (default_app_changed), self);
gtk_widget_show (button);
label = WID(data->label);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), button);
}
static DefaultAppData preferred_app_infos[] = {
/* for web, we need to support text/html,
application/xhtml+xml and x-scheme-handler/https,
hence the "*" pattern
*/
{ "x-scheme-handler/http", "web-label", "*" },
{ "x-scheme-handler/mailto", "mail-label", NULL },
{ "text/calendar", "calendar-label", NULL },
{ "audio/x-vorbis+ogg", "music-label", "audio/*" },
{ "video/x-ogm+ogg", "video-label", "video/*" },
{ "image/jpeg", "photos-label", "image/*" }
};
static void
info_panel_setup_default_apps (CcInfoPanel *self)
{
int i;
for (i = 0; i < G_N_ELEMENTS(preferred_app_infos); i++)
{
info_panel_setup_default_app (self, &preferred_app_infos[i],
1, i);
}
}
static char **
remove_elem_from_str_array (char **v,
const char *s)
{
GPtrArray *array;
guint idx;
array = g_ptr_array_new ();
for (idx = 0; v[idx] != NULL; idx++) {
if (g_strcmp0 (v[idx], s) == 0) {
continue;
}
g_ptr_array_add (array, v[idx]);
}
g_ptr_array_add (array, NULL);
g_free (v);
return (char **) g_ptr_array_free (array, FALSE);
}
static char **
add_elem_to_str_array (char **v,
const char *s)
{
GPtrArray *array;
guint idx;
array = g_ptr_array_new ();
for (idx = 0; v[idx] != NULL; idx++) {
g_ptr_array_add (array, v[idx]);
}
g_ptr_array_add (array, g_strdup (s));
g_ptr_array_add (array, NULL);
g_free (v);
return (char **) g_ptr_array_free (array, FALSE);
}
static int
media_panel_g_strv_find (char **strv,
const char *find_me)
{
guint index;
g_return_val_if_fail (find_me != NULL, -1);
for (index = 0; strv[index] != NULL; ++index) {
if (g_strcmp0 (strv[index], find_me) == 0) {
return index;
}
}
return -1;
}
static void
autorun_get_preferences (CcInfoPanel *self,
const char *x_content_type,
gboolean *pref_start_app,
gboolean *pref_ignore,
gboolean *pref_open_folder)
{
char **x_content_start_app;
char **x_content_ignore;
char **x_content_open_folder;
g_return_if_fail (pref_start_app != NULL);
g_return_if_fail (pref_ignore != NULL);
g_return_if_fail (pref_open_folder != NULL);
*pref_start_app = FALSE;
*pref_ignore = FALSE;
*pref_open_folder = FALSE;
x_content_start_app = g_settings_get_strv (self->priv->media_settings,
PREF_MEDIA_AUTORUN_X_CONTENT_START_APP);
x_content_ignore = g_settings_get_strv (self->priv->media_settings,
PREF_MEDIA_AUTORUN_X_CONTENT_IGNORE);
x_content_open_folder = g_settings_get_strv (self->priv->media_settings,
PREF_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER);
if (x_content_start_app != NULL) {
*pref_start_app = media_panel_g_strv_find (x_content_start_app, x_content_type) != -1;
}
if (x_content_ignore != NULL) {
*pref_ignore = media_panel_g_strv_find (x_content_ignore, x_content_type) != -1;
}
if (x_content_open_folder != NULL) {
*pref_open_folder = media_panel_g_strv_find (x_content_open_folder, x_content_type) != -1;
}
g_strfreev (x_content_ignore);
g_strfreev (x_content_start_app);
g_strfreev (x_content_open_folder);
}
static void
autorun_set_preferences (CcInfoPanel *self,
const char *x_content_type,
gboolean pref_start_app,
gboolean pref_ignore,
gboolean pref_open_folder)
{
char **x_content_start_app;
char **x_content_ignore;
char **x_content_open_folder;
g_assert (x_content_type != NULL);
x_content_start_app = g_settings_get_strv (self->priv->media_settings,
PREF_MEDIA_AUTORUN_X_CONTENT_START_APP);
x_content_ignore = g_settings_get_strv (self->priv->media_settings,
PREF_MEDIA_AUTORUN_X_CONTENT_IGNORE);
x_content_open_folder = g_settings_get_strv (self->priv->media_settings,
PREF_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER);
x_content_start_app = remove_elem_from_str_array (x_content_start_app, x_content_type);
if (pref_start_app) {
x_content_start_app = add_elem_to_str_array (x_content_start_app, x_content_type);
}
g_settings_set_strv (self->priv->media_settings,
PREF_MEDIA_AUTORUN_X_CONTENT_START_APP, (const gchar * const*) x_content_start_app);
x_content_ignore = remove_elem_from_str_array (x_content_ignore, x_content_type);
if (pref_ignore) {
x_content_ignore = add_elem_to_str_array (x_content_ignore, x_content_type);
}
g_settings_set_strv (self->priv->media_settings,
PREF_MEDIA_AUTORUN_X_CONTENT_IGNORE, (const gchar * const*) x_content_ignore);
x_content_open_folder = remove_elem_from_str_array (x_content_open_folder, x_content_type);
if (pref_open_folder) {
x_content_open_folder = add_elem_to_str_array (x_content_open_folder, x_content_type);
}
g_settings_set_strv (self->priv->media_settings,
PREF_MEDIA_AUTORUN_X_CONTENT_OPEN_FOLDER, (const gchar * const*) x_content_open_folder);
g_strfreev (x_content_open_folder);
g_strfreev (x_content_ignore);
g_strfreev (x_content_start_app);
}
static void
custom_item_activated_cb (GtkAppChooserButton *button,
const gchar *item,
gpointer user_data)
{
CcInfoPanel *self = user_data;
gchar *content_type;
content_type = gtk_app_chooser_get_content_type (GTK_APP_CHOOSER (button));
if (g_strcmp0 (item, CUSTOM_ITEM_ASK) == 0) {
autorun_set_preferences (self, content_type,
FALSE, FALSE, FALSE);
} else if (g_strcmp0 (item, CUSTOM_ITEM_OPEN_FOLDER) == 0) {
autorun_set_preferences (self, content_type,
FALSE, FALSE, TRUE);
} else if (g_strcmp0 (item, CUSTOM_ITEM_DO_NOTHING) == 0) {
autorun_set_preferences (self, content_type,
FALSE, TRUE, FALSE);
}
g_free (content_type);
}
static void
combo_box_changed_cb (GtkComboBox *combo_box,
gpointer user_data)
{
CcInfoPanel *self = user_data;
GAppInfo *info;
gchar *content_type;
info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (combo_box));
if (info == NULL)
return;
content_type = gtk_app_chooser_get_content_type (GTK_APP_CHOOSER (combo_box));
autorun_set_preferences (self, content_type,
TRUE, FALSE, FALSE);
g_app_info_set_as_default_for_type (info, content_type, NULL);
g_object_unref (info);
g_free (content_type);
}
static void
prepare_combo_box (CcInfoPanel *self,
GtkWidget *combo_box,
const gchar *heading)
{
GtkAppChooserButton *app_chooser = GTK_APP_CHOOSER_BUTTON (combo_box);
gboolean pref_ask;
gboolean pref_start_app;
gboolean pref_ignore;
gboolean pref_open_folder;
GAppInfo *info;
gchar *content_type;
content_type = gtk_app_chooser_get_content_type (GTK_APP_CHOOSER (app_chooser));
/* fetch preferences for this content type */
autorun_get_preferences (self, content_type,
&pref_start_app, &pref_ignore, &pref_open_folder);
pref_ask = !pref_start_app && !pref_ignore && !pref_open_folder;
info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (combo_box));
/* append the separator only if we have >= 1 apps in the chooser */
if (info != NULL) {
gtk_app_chooser_button_append_separator (app_chooser);
g_object_unref (info);
}
gtk_app_chooser_button_append_custom_item (app_chooser, CUSTOM_ITEM_ASK,
_("Ask what to do"),
NULL);
gtk_app_chooser_button_append_custom_item (app_chooser, CUSTOM_ITEM_DO_NOTHING,
_("Do nothing"),
NULL);
gtk_app_chooser_button_append_custom_item (app_chooser, CUSTOM_ITEM_OPEN_FOLDER,
_("Open folder"),
NULL);
gtk_app_chooser_button_set_show_dialog_item (app_chooser, TRUE);
gtk_app_chooser_button_set_heading (app_chooser, _(heading));
if (pref_ask) {
gtk_app_chooser_button_set_active_custom_item (app_chooser, CUSTOM_ITEM_ASK);
} else if (pref_ignore) {
gtk_app_chooser_button_set_active_custom_item (app_chooser, CUSTOM_ITEM_DO_NOTHING);
} else if (pref_open_folder) {
gtk_app_chooser_button_set_active_custom_item (app_chooser, CUSTOM_ITEM_OPEN_FOLDER);
}
g_signal_connect (app_chooser, "changed",
G_CALLBACK (combo_box_changed_cb), self);
g_signal_connect (app_chooser, "custom-item-activated",
G_CALLBACK (custom_item_activated_cb), self);
g_free (content_type);
}
static void
other_type_combo_box_changed (GtkComboBox *combo_box,
CcInfoPanel *self)
{
GtkTreeIter iter;
GtkTreeModel *model;
char *x_content_type;
GtkWidget *action_container;
GtkWidget *action_label;
x_content_type = NULL;
if (!gtk_combo_box_get_active_iter (combo_box, &iter)) {
return;
}
model = gtk_combo_box_get_model (combo_box);
if (model == NULL) {
return;
}
gtk_tree_model_get (model, &iter,
1, &x_content_type,
-1);
action_container = GTK_WIDGET (gtk_builder_get_object (self->priv->builder,
"media_other_action_container"));
if (self->priv->other_application_combo != NULL) {
gtk_widget_destroy (self->priv->other_application_combo);
}
self->priv->other_application_combo = gtk_app_chooser_button_new (x_content_type);
gtk_box_pack_start (GTK_BOX (action_container), self->priv->other_application_combo, TRUE, TRUE, 0);
prepare_combo_box (self, self->priv->other_application_combo, NULL);
gtk_widget_show (self->priv->other_application_combo);
action_label = GTK_WIDGET (gtk_builder_get_object (self->priv->builder,
"media_other_action_label"));
gtk_label_set_mnemonic_widget (GTK_LABEL (action_label), self->priv->other_application_combo);
g_free (x_content_type);
}
static void
on_extra_options_dialog_response (GtkWidget *dialog,
int response,
CcInfoPanel *self)
{
gtk_widget_hide (dialog);
if (self->priv->other_application_combo != NULL) {
gtk_widget_destroy (self->priv->other_application_combo);
self->priv->other_application_combo = NULL;
}
}
static void
on_extra_options_button_clicked (GtkWidget *button,
CcInfoPanel *self)
{
GtkWidget *dialog;
GtkWidget *combo_box;
dialog = GTK_WIDGET (gtk_builder_get_object (self->priv->builder, "extra_options_dialog"));
combo_box = GTK_WIDGET (gtk_builder_get_object (self->priv->builder, "media_other_type_combobox"));
gtk_window_set_transient_for (GTK_WINDOW (dialog),
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))));
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_window_set_title (GTK_WINDOW (dialog), _("Other Media"));
g_signal_connect (dialog,
"response",
G_CALLBACK (on_extra_options_dialog_response),
self);
g_signal_connect (dialog,
"delete-event",
G_CALLBACK (gtk_widget_hide_on_delete),
NULL);
/* update other_application_combo */
other_type_combo_box_changed (GTK_COMBO_BOX (combo_box), self);
gtk_window_present (GTK_WINDOW (dialog));
}
static void
info_panel_setup_media (CcInfoPanel *self)
{
guint n;
GList *l, *content_types;
GtkWidget *other_type_combo_box;
GtkWidget *extras_button;
GtkListStore *other_type_list_store;
GtkCellRenderer *renderer;
GtkTreeIter iter;
GtkBuilder *builder = self->priv->builder;
struct {
const gchar *widget_name;
const gchar *content_type;
const gchar *heading;
} const defs[] = {
{ "media_audio_cdda_combobox", "x-content/audio-cdda", N_("Select an application for audio CDs") },
{ "media_video_dvd_combobox", "x-content/video-dvd", N_("Select an application for video DVDs") },
{ "media_music_player_combobox", "x-content/audio-player", N_("Select an application to run when a music player is connected") },
{ "media_dcf_combobox", "x-content/image-dcf", N_("Select an application to run when a camera is connected") },
{ "media_software_combobox", "x-content/unix-software", N_("Select an application for software CDs") },
};
struct {
const gchar *content_type;
const gchar *description;
} const other_defs[] = {
/* translators: these strings are duplicates of shared-mime-info
* strings, just here to fix capitalization of the English originals.
* If the shared-mime-info translation works for your language,
* simply leave these untranslated.
*/
{ "x-content/audio-dvd", N_("audio DVD") },
{ "x-content/blank-bd", N_("blank Blu-ray disc") },
{ "x-content/blank-cd", N_("blank CD disc") },
{ "x-content/blank-dvd", N_("blank DVD disc") },
{ "x-content/blank-hddvd", N_("blank HD DVD disc") },
{ "x-content/video-bluray", N_("Blu-ray video disc") },
{ "x-content/ebook-reader", N_("e-book reader") },
{ "x-content/video-hddvd", N_("HD DVD video disc") },
{ "x-content/image-picturecd", N_("Picture CD") },
{ "x-content/video-svcd", N_("Super Video CD") },
{ "x-content/video-vcd", N_("Video CD") },
{ "x-content/win32-software", N_("Windows software") },
{ "x-content/software", N_("Software") }
};
for (n = 0; n < G_N_ELEMENTS (defs); n++) {
prepare_combo_box (self,
GTK_WIDGET (gtk_builder_get_object (builder, defs[n].widget_name)),
defs[n].heading);
}
other_type_combo_box = GTK_WIDGET (gtk_builder_get_object (builder, "media_other_type_combobox"));
other_type_list_store = gtk_list_store_new (2,
G_TYPE_STRING,
G_TYPE_STRING);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (other_type_list_store),
1, GTK_SORT_ASCENDING);
content_types = g_content_types_get_registered ();
for (l = content_types; l != NULL; l = l->next) {
char *content_type = l->data;
char *description = NULL;
if (!g_str_has_prefix (content_type, "x-content/"))
continue;
for (n = 0; n < G_N_ELEMENTS (defs); n++) {
if (g_content_type_is_a (content_type, defs[n].content_type)) {
goto skip;
}
}
for (n = 0; n < G_N_ELEMENTS (other_defs); n++) {
if (strcmp (content_type, other_defs[n].content_type) == 0) {
const gchar *s = other_defs[n].description;
if (s == _(s))
description = g_content_type_get_description (content_type);
else
description = g_strdup (_(s));
break;
}
}
if (description == NULL) {
g_debug ("Content type '%s' is missing from the info panel", content_type);
description = g_content_type_get_description (content_type);
}
gtk_list_store_append (other_type_list_store, &iter);
gtk_list_store_set (other_type_list_store, &iter,
0, description,
1, content_type,
-1);
g_free (description);
skip:
;
}
g_list_free_full (content_types, g_free);
gtk_combo_box_set_model (GTK_COMBO_BOX (other_type_combo_box),
GTK_TREE_MODEL (other_type_list_store));
renderer = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (other_type_combo_box), renderer, TRUE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (other_type_combo_box), renderer,
"text", 0,
NULL);
g_signal_connect (other_type_combo_box,
"changed",
G_CALLBACK (other_type_combo_box_changed),
self);
gtk_combo_box_set_active (GTK_COMBO_BOX (other_type_combo_box), 0);
extras_button = GTK_WIDGET (gtk_builder_get_object (builder, "extra_options_button"));
g_signal_connect (extras_button,
"clicked",
G_CALLBACK (on_extra_options_button_clicked),
self);
g_settings_bind (self->priv->media_settings,
PREF_MEDIA_AUTORUN_NEVER,
gtk_builder_get_object (self->priv->builder, "media_autorun_never_checkbutton"),
"active",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind (self->priv->media_settings,
PREF_MEDIA_AUTORUN_NEVER,
GTK_WIDGET (gtk_builder_get_object (self->priv->builder, "media_handling_vbox")),
"sensitive",
G_SETTINGS_BIND_INVERT_BOOLEAN);
}
static void
info_panel_setup_selector (CcInfoPanel *self)
{
GtkTreeView *view;
GtkListStore *model;
GtkTreeSelection *selection;
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
GtkTreeIter iter;
int section_name_column = 0;
view = GTK_TREE_VIEW (WID ("overview_treeview"));
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
model = gtk_list_store_new (1, G_TYPE_STRING);
gtk_tree_view_set_model (view, GTK_TREE_MODEL (model));
g_object_unref (model);
renderer = gtk_cell_renderer_text_new ();
gtk_cell_renderer_set_padding (renderer, 4, 4);
g_object_set (renderer,
"width-chars", 20,
"ellipsize", PANGO_ELLIPSIZE_END,
NULL);
column = gtk_tree_view_column_new_with_attributes (_("Section"),
renderer,
"text", section_name_column,
NULL);
gtk_tree_view_append_column (view, column);
gtk_list_store_append (model, &iter);
gtk_list_store_set (model, &iter, section_name_column,
_("Overview"),
-1);
gtk_tree_selection_select_iter (selection, &iter);
gtk_list_store_append (model, &iter);
gtk_list_store_set (model, &iter, section_name_column,
_("Default Applications"),
-1);
gtk_list_store_append (model, &iter);
gtk_list_store_set (model, &iter, section_name_column,
_("Removable Media"),
-1);
gtk_list_store_append (model, &iter);
gtk_list_store_set (model, &iter, section_name_column,
_("Graphics"),
-1);
g_signal_connect (selection, "changed",
G_CALLBACK (on_section_changed), self);
on_section_changed (selection, self);
gtk_widget_show_all (GTK_WIDGET (view));
}
static char *
get_hostname_property (CcInfoPanel *self,
const char *property)
{
GVariant *variant;
char *str;
variant = g_dbus_proxy_get_cached_property (self->priv->hostnamed_proxy,
property);
if (!variant)
{
GError *error = NULL;
GVariant *inner;
/* Work around systemd-hostname not sending us back
* the property value when changing values */
variant = g_dbus_proxy_call_sync (self->priv->hostnamed_proxy,
"org.freedesktop.DBus.Properties.Get",
g_variant_new ("(ss)", "org.freedesktop.hostname1", property),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (variant == NULL)
{
g_warning ("Failed to get property '%s': %s", property, error->message);
g_error_free (error);
return NULL;
}
g_variant_get (variant, "(v)", &inner);
str = g_variant_dup_string (inner, NULL);
g_variant_unref (variant);
}
else
{
str = g_variant_dup_string (variant, NULL);
g_variant_unref (variant);
}
return str;
}
static char *
info_panel_get_hostname (CcInfoPanel *self)
{
char *str;
str = get_hostname_property (self, "PrettyHostname");
/* Empty strings means that we need to fallback */
if (str != NULL &&
*str == '\0')
{
g_free (str);
str = get_hostname_property (self, "Hostname");
}
return str;
}
static void
info_panel_set_hostname (CcInfoPanel *self)
{
char *hostname;
GVariant *variant;
GError *error = NULL;
const gchar *text;
text = gtk_entry_get_text (GTK_ENTRY (WID ("name_entry")));
g_debug ("Setting PrettyHostname to '%s'", text);
variant = g_dbus_proxy_call_sync (self->priv->hostnamed_proxy,
"SetPrettyHostname",
g_variant_new ("(sb)", text, FALSE),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, &error);
if (variant == NULL)
{
g_warning ("Could not set PrettyHostname: %s", error->message);
g_error_free (error);
error = NULL;
}
else
{
g_variant_unref (variant);
}
/* Set the static and transient hostname */
hostname = pretty_hostname_to_static (text, FALSE);
g_assert (hostname);
g_debug ("Setting StaticHostname to '%s'", hostname);
variant = g_dbus_proxy_call_sync (self->priv->hostnamed_proxy,
"SetStaticHostname",
g_variant_new ("(sb)", hostname, FALSE),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, &error);
if (variant == NULL)
{
g_warning ("Could not set StaticHostname: %s", error->message);
g_error_free (error);
}
else
{
g_variant_unref (variant);
}
g_debug ("Setting Hostname to '%s'", hostname);
variant = g_dbus_proxy_call_sync (self->priv->hostnamed_proxy,
"SetHostname",
g_variant_new ("(sb)", hostname, FALSE),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, &error);
if (variant == NULL)
{
g_warning ("Could not set Hostname: %s", error->message);
g_error_free (error);
}
else
{
g_variant_unref (variant);
}
g_free (hostname);
}
static void
text_changed_cb (GtkEntry *entry,
CcInfoPanel *self)
{
reset_hostname_timeout (self);
}
static void
info_panel_setup_hostname (CcInfoPanel *self,
GPermission *permission)
{
char *str;
GtkWidget *entry;
GError *error = NULL;
if (permission == NULL)
{
g_debug ("Will not show hostname, hostnamed not installed");
return;
}
entry = WID ("name_entry");
if (g_permission_get_allowed (permission))
gtk_widget_set_sensitive (entry, TRUE);
else
g_debug ("Not allowed to change the hostname");
self->priv->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);
/* This could only happen if the policy file was installed
* but not hostnamed, which points to a system bug */
if (self->priv->hostnamed_proxy == NULL)
{
g_debug ("Couldn't get hostnamed to start, bailing: %s", error->message);
g_error_free (error);
return;
}
gtk_widget_show (WID ("label4"));
gtk_widget_show (entry);
str = info_panel_get_hostname (self);
if (str != NULL)
gtk_entry_set_text (GTK_ENTRY (entry), str);
else
gtk_entry_set_text (GTK_ENTRY (entry), "");
g_free (str);
g_signal_connect (G_OBJECT (entry), "changed",
G_CALLBACK (text_changed_cb), self);
}
static void
info_panel_setup_overview (CcInfoPanel *self)
{
GtkWidget *widget;
gboolean res;
glibtop_mem mem;
const glibtop_sysinfo *info;
char *text;
GPermission *permission;
permission = polkit_permission_new_sync ("org.freedesktop.hostname1.set-static-hostname", NULL, NULL, NULL);
/* Is hostnamed installed? */
info_panel_setup_hostname (self, permission);
res = load_gnome_version (&self->priv->gnome_version,
&self->priv->gnome_distributor,
&self->priv->gnome_date);
if (res)
{
widget = WID ("version_label");
text = g_strdup_printf (_("Version %s"), self->priv->gnome_version);
gtk_label_set_text (GTK_LABEL (widget), text);
g_free (text);
}
glibtop_get_mem (&mem);
text = g_format_size_full (mem.total, G_FORMAT_SIZE_IEC_UNITS);
widget = WID ("memory_label");
gtk_label_set_text (GTK_LABEL (widget), text ? text : "");
g_free (text);
info = glibtop_get_sysinfo ();
widget = WID ("processor_label");
text = get_cpu_info (info);
gtk_label_set_markup (GTK_LABEL (widget), text ? text : "");
g_free (text);
widget = WID ("os_type_label");
text = get_os_type ();
gtk_label_set_text (GTK_LABEL (widget), text ? text : "");
g_free (text);
get_primary_disc_info (self);
widget = WID ("graphics_label");
gtk_label_set_markup (GTK_LABEL (widget), self->priv->graphics_data->hardware_string);
widget = WID ("info_vbox");
gtk_widget_reparent (widget, (GtkWidget *) self);
refresh_update_button (self);
}
static void
refresh_update_button (CcInfoPanel *self)
{
GtkWidget *widget;
widget = WID ("updates_button");
if (widget == NULL)
return;
switch (self->priv->updates_state)
{
case PK_NOT_AVAILABLE:
gtk_widget_set_visible (widget, FALSE);
break;
case UPDATES_AVAILABLE:
gtk_widget_set_sensitive (widget, TRUE);
gtk_button_set_label (GTK_BUTTON (widget), _("Install Updates"));
break;
case UPDATES_NOT_AVAILABLE:
gtk_widget_set_sensitive (widget, FALSE);
gtk_button_set_label (GTK_BUTTON (widget), _("System Up-To-Date"));
break;
case CHECKING_UPDATES:
gtk_widget_set_sensitive (widget, FALSE);
gtk_button_set_label (GTK_BUTTON (widget), _("Checking for Updates"));
break;
}
}
static void
on_pk_transaction_signal (GDBusProxy *proxy,
char *sender_name,
char *signal_name,
GVariant *parameters,
CcInfoPanel *self)
{
if (g_strcmp0 (signal_name, "Package") == 0)
{
self->priv->updates_state = UPDATES_AVAILABLE;
}
else if (g_strcmp0 (signal_name, "Finished") == 0)
{
if (self->priv->updates_state == CHECKING_UPDATES)
self->priv->updates_state = UPDATES_NOT_AVAILABLE;
refresh_update_button (self);
}
else if (g_strcmp0 (signal_name, "ErrorCode") == 0)
{
self->priv->updates_state = PK_NOT_AVAILABLE;
refresh_update_button (self);
}
else if (g_strcmp0 (signal_name, "Destroy") == 0)
{
g_object_unref (self->priv->pk_transaction_proxy);
self->priv->pk_transaction_proxy = NULL;
}
}
static void
on_pk_get_updates_ready (GObject *source,
GAsyncResult *res,
CcInfoPanel *self)
{
GError *error;
GVariant *result;
error = NULL;
result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
if (result == NULL)
{
g_warning ("Error getting PackageKit updates list: %s", error->message);
g_error_free (error);
return;
}
}
static void
on_pk_get_tid_ready (GObject *source,
GAsyncResult *res,
CcInfoPanel *self)
{
GError *error;
GVariant *result;
char *tid;
error = NULL;
result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error);
if (result == NULL)
{
if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN) == FALSE)
g_warning ("Error getting PackageKit transaction ID: %s", error->message);
g_error_free (error);
return;
}
g_variant_get (result, "(o)", &tid);
self->priv->pk_transaction_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
"org.freedesktop.PackageKit",
tid,
"org.freedesktop.PackageKit.Transaction",
NULL,
NULL);
g_free (tid);
g_variant_unref (result);
if (self->priv->pk_transaction_proxy == NULL)
{
g_warning ("Unable to get PackageKit transaction proxy object");
return;
}
g_signal_connect (self->priv->pk_transaction_proxy,
"g-signal",
G_CALLBACK (on_pk_transaction_signal),
self);
g_dbus_proxy_call (self->priv->pk_transaction_proxy,
"GetUpdates",
g_variant_new ("(t)", 1), /* PK_FILTER_ENUM_NONE */
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
(GAsyncReadyCallback) on_pk_get_updates_ready,
self);
}
static void
refresh_updates (CcInfoPanel *self)
{
self->priv->updates_state = CHECKING_UPDATES;
refresh_update_button (self);
g_assert (self->priv->pk_proxy != NULL);
g_dbus_proxy_call (self->priv->pk_proxy,
"CreateTransaction",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
(GAsyncReadyCallback) on_pk_get_tid_ready,
self);
}
static void
on_pk_signal (GDBusProxy *proxy,
char *sender_name,
char *signal_name,
GVariant *parameters,
CcInfoPanel *self)
{
if (g_strcmp0 (signal_name, "UpdatesChanged") == 0)
{
refresh_updates (self);
}
}
static void
on_updates_button_clicked (GtkWidget *widget,
CcInfoPanel *self)
{
GError *error;
error = NULL;
g_spawn_command_line_async ("gpk-update-viewer", &error);
if (error != NULL)
{
g_warning ("unable to launch Software Updates: %s", error->message);
g_error_free (error);
}
}
static void
got_pk_proxy_cb (GObject *source_object,
GAsyncResult *res,
CcInfoPanel *self)
{
GError *error = NULL;
GVariant *v;
guint32 major, minor, micro;
self->priv->pk_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
if (self->priv->pk_proxy == NULL)
{
g_warning ("Unable to get PackageKit proxy object: %s", error->message);
g_error_free (error);
self->priv->updates_state = PK_NOT_AVAILABLE;
refresh_update_button (self);
return;
}
v = g_dbus_proxy_get_cached_property (self->priv->pk_proxy, "VersionMajor");
g_variant_get (v, "u", &major);
g_variant_unref (v);
v = g_dbus_proxy_get_cached_property (self->priv->pk_proxy, "VersionMinor");
g_variant_get (v, "u", &minor);
g_variant_unref (v);
v = g_dbus_proxy_get_cached_property (self->priv->pk_proxy, "VersionMicro");
g_variant_get (v, "u", &micro);
g_variant_unref (v);
if (major != 0 || minor != 8)
{
g_warning ("PackageKit version %u.%u.%u not supported", major, minor, micro);
g_clear_object (&self->priv->pk_proxy);
self->priv->updates_state = PK_NOT_AVAILABLE;
refresh_update_button (self);
}
else
{
g_signal_connect (self->priv->pk_proxy,
"g-signal",
G_CALLBACK (on_pk_signal),
self);
refresh_updates (self);
}
}
static void
info_panel_setup_updates (CcInfoPanel *self)
{
self->priv->updates_state = CHECKING_UPDATES;
refresh_update_button (self);
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
"org.freedesktop.PackageKit",
"/org/freedesktop/PackageKit",
"org.freedesktop.PackageKit",
NULL,
(GAsyncReadyCallback) got_pk_proxy_cb,
self);
}
static void
cc_info_panel_init (CcInfoPanel *self)
{
GError *error = NULL;
GtkWidget *widget;
self->priv = INFO_PANEL_PRIVATE (self);
self->priv->builder = gtk_builder_new ();
self->priv->media_settings = g_settings_new (MEDIA_HANDLING_SCHEMA);
self->priv->session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
g_assert (self->priv->session_bus);
if (gtk_builder_add_from_file (self->priv->builder,
GNOMECC_UI_DIR "/info.ui",
&error) == 0)
{
g_warning ("Could not load interface file: %s", error->message);
g_error_free (error);
return;
}
self->priv->graphics_data = get_graphics_data ();
widget = WID ("updates_button");
g_signal_connect (widget, "clicked", G_CALLBACK (on_updates_button_clicked), self);
info_panel_setup_updates (self);
info_panel_setup_selector (self);
info_panel_setup_overview (self);
info_panel_setup_default_apps (self);
info_panel_setup_media (self);
info_panel_setup_graphics (self);
info_panel_setup_virt (self);
}