summaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorMatej Urbančič <mateju@svn.gnome.org>2018-05-15 21:03:11 +0200
committerMatej Urbančič <mateju@svn.gnome.org>2018-05-15 21:03:11 +0200
commit2acb520fc9b19118107916b4c89a041d1651df4d (patch)
treede915d27698f0f0ee89862dfce8c103c157df952 /shell
parent2da5fd3b3dfb4a0f2885349dad2a8e2cc063119c (diff)
parentf4433b3766bab48b85ae0e42e3e704bb7f380663 (diff)
downloadgnome-control-center-2acb520fc9b19118107916b4c89a041d1651df4d.tar.gz
Merge branch 'master' of gitlab.gnome.org:GNOME/gnome-control-center
Diffstat (limited to 'shell')
-rw-r--r--shell/cc-application.c19
-rw-r--r--shell/cc-debug.h.in229
-rw-r--r--shell/cc-editable-entry.c644
-rw-r--r--shell/cc-editable-entry.h83
-rw-r--r--shell/cc-hostname-entry.c288
-rw-r--r--shell/cc-hostname-entry.h33
-rw-r--r--shell/cc-log.c107
-rw-r--r--shell/cc-log.h (renamed from shell/hostname-helper.h)22
-rw-r--r--shell/cc-object-storage.c438
-rw-r--r--shell/cc-object-storage.h65
-rw-r--r--shell/cc-panel-list.c1
-rw-r--r--shell/cc-panel-loader.c6
-rw-r--r--shell/cc-shell-log.c62
-rw-r--r--shell/cc-shell-log.h32
-rw-r--r--shell/cc-shell-model.c61
-rw-r--r--shell/cc-shell-model.h67
-rw-r--r--shell/cc-window.c170
-rw-r--r--shell/hostname-helper.c221
-rw-r--r--shell/hostnames-test.txt11
-rw-r--r--shell/list-box-helper.c153
-rw-r--r--shell/list-box-helper.h37
-rw-r--r--shell/meson.build128
-rw-r--r--shell/org.gnome.ControlCenter.gschema.xml7
-rw-r--r--shell/ssids-test.txt3
-rw-r--r--shell/test-hostname.c136
-rw-r--r--shell/window.ui13
26 files changed, 1151 insertions, 1885 deletions
diff --git a/shell/cc-application.c b/shell/cc-application.c
index 8beb61714..3f828f3a6 100644
--- a/shell/cc-application.c
+++ b/shell/cc-application.c
@@ -26,8 +26,9 @@
#include <gio/gio.h>
#include "cc-application.h"
+#include "cc-log.h"
+#include "cc-object-storage.h"
#include "cc-panel-loader.h"
-#include "cc-shell-log.h"
#include "cc-window.h"
#if defined(HAVE_WACOM) || defined(HAVE_CHEESE)
@@ -157,7 +158,9 @@ cc_application_command_line (GApplication *application,
options = g_application_command_line_get_options_dict (command_line);
debug = g_variant_dict_contains (options, "verbose");
- cc_shell_log_set_debug (debug);
+
+ if (debug)
+ cc_log_init ();
gtk_window_present (GTK_WINDOW (self->window));
@@ -264,6 +267,15 @@ cc_application_startup (GApplication *application)
self->window = cc_window_new (GTK_APPLICATION (application));
}
+static void
+cc_application_finalize (GObject *object)
+{
+ /* Destroy the object storage cache when finalizing */
+ cc_object_storage_destroy ();
+
+ G_OBJECT_CLASS (cc_application_parent_class)->finalize (object);
+}
+
static GObject *
cc_application_constructor (GType type,
guint n_construct_params,
@@ -289,6 +301,7 @@ cc_application_class_init (CcApplicationClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GApplicationClass *application_class = G_APPLICATION_CLASS (klass);
+ object_class->finalize = cc_application_finalize;
object_class->constructor = cc_application_constructor;
application_class->activate = cc_application_activate;
application_class->startup = cc_application_startup;
@@ -299,6 +312,8 @@ cc_application_class_init (CcApplicationClass *klass)
static void
cc_application_init (CcApplication *self)
{
+ cc_object_storage_initialize ();
+
g_application_add_main_option_entries (G_APPLICATION (self), all_options);
}
diff --git a/shell/cc-debug.h.in b/shell/cc-debug.h.in
new file mode 100644
index 000000000..226f82e03
--- /dev/null
+++ b/shell/cc-debug.h.in
@@ -0,0 +1,229 @@
+/* cc-debug.h.in
+ *
+ * Copyright © 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.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/>.
+ */
+
+#pragma once
+
+#include <glib.h>
+
+/**
+ * SECTION:cc-debug
+ * @short_description: Debugging macros
+ * @title:Debugging
+ * @stability:stable
+ *
+ * Macros used for tracing and debugging code. These
+ * are only valid when Settings is compiled with tracing
+ * suppoer (pass `--enable-tracing` to the configure
+ * script to do that).
+ */
+
+G_BEGIN_DECLS
+
+#ifndef CC_ENABLE_TRACE
+# define CC_ENABLE_TRACE @ENABLE_TRACING@
+#endif
+#if CC_ENABLE_TRACE != 1
+# undef CC_ENABLE_TRACE
+#endif
+
+/**
+ * CC_LOG_LEVEL_TRACE: (skip)
+ */
+#ifndef CC_LOG_LEVEL_TRACE
+# define CC_LOG_LEVEL_TRACE ((GLogLevelFlags)(1 << G_LOG_LEVEL_USER_SHIFT))
+#endif
+
+#ifdef CC_ENABLE_TRACE
+
+/**
+ * CC_TRACE_MSG:
+ * @fmt: printf-like format of the message
+ * @...: arguments for @fmt
+ *
+ * Prints a trace message.
+ */
+# define CC_TRACE_MSG(fmt, ...) \
+ g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, " MSG: %s():%d: " fmt, \
+ G_STRFUNC, __LINE__, ##__VA_ARGS__)
+
+/**
+ * CC_PROBE:
+ *
+ * Prints a probing message. Put this macro in the code when
+ * you want to check the program reaches a certain section
+ * of code.
+ */
+# define CC_PROBE \
+ g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, "PROBE: %s():%d", \
+ G_STRFUNC, __LINE__)
+
+/**
+ * CC_TODO:
+ * @_msg: the message to print
+ *
+ * Prints a TODO message.
+ */
+# define CC_TODO(_msg) \
+ g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, " TODO: %s():%d: %s", \
+ G_STRFUNC, __LINE__, _msg)
+
+/**
+ * CC_ENTRY:
+ *
+ * Prints an entry message. This shouldn't be used in
+ * critical functions. Place this at the beggining of
+ * the function, before any assertion.
+ */
+# define CC_ENTRY \
+ g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, "ENTRY: %s():%d", \
+ G_STRFUNC, __LINE__)
+
+/**
+ * CC_EXIT:
+ *
+ * Prints an exit message. This shouldn't be used in
+ * critical functions. Place this at the end of
+ * the function, after any relevant code. If the
+ * function returns something, use CC_RETURN()
+ * instead.
+ */
+# define CC_EXIT \
+ G_STMT_START { \
+ g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, " EXIT: %s():%d", \
+ G_STRFUNC, __LINE__); \
+ return; \
+ } G_STMT_END
+
+/**
+ * CC_GOTO:
+ * @_l: goto tag
+ *
+ * Logs a goto jump.
+ */
+# define CC_GOTO(_l) \
+ G_STMT_START { \
+ g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, " GOTO: %s():%d ("#_l")",\
+ G_STRFUNC, __LINE__); \
+ goto _l; \
+ } G_STMT_END
+
+/**
+ * CC_RETURN:
+ * @_r: the return value.
+ *
+ * Prints an exit message, and returns @_r. See #CC_EXIT.
+ */
+# define CC_RETURN(_r) \
+ G_STMT_START { \
+ g_log(G_LOG_DOMAIN, CC_LOG_LEVEL_TRACE, " EXIT: %s():%d ", \
+ G_STRFUNC, __LINE__); \
+ return _r; \
+ } G_STMT_END
+
+#else
+
+/**
+ * CC_TODO:
+ * @_msg: the message to print
+ *
+ * Prints a TODO message.
+ */
+# define CC_TODO(_msg)
+
+/**
+ * CC_PROBE:
+ *
+ * Prints a probing message.
+ */
+# define CC_PROBE
+
+/**
+ * CC_TRACE_MSG:
+ * @fmt: printf-like format of the message
+ * @...: arguments for @fmt
+ *
+ * Prints a trace message.
+ */
+# define CC_TRACE_MSG(fmt, ...)
+
+/**
+ * CC_ENTRY:
+ *
+ * Prints a probing message. This shouldn't be used in
+ * critical functions. Place this at the beggining of
+ * the function, before any assertion.
+ */
+# define CC_ENTRY
+
+/**
+ * CC_GOTO:
+ * @_l: goto tag
+ *
+ * Logs a goto jump.
+ */
+# define CC_GOTO(_l) goto _l
+
+/**
+ * CC_EXIT:
+ *
+ * Prints an exit message. This shouldn't be used in
+ * critical functions. Place this at the end of
+ * the function, after any relevant code. If the
+ * function returns somethin, use CC_RETURN()
+ * instead.
+ */
+# define CC_EXIT return
+
+/**
+ * CC_RETURN:
+ * @_r: the return value.
+ *
+ * Prints an exit message, and returns @_r. See #CC_EXIT.
+ */
+# define CC_RETURN(_r) return _r
+#endif
+
+/**
+ * _CC_BUG: (skip)
+ */
+#define _CC_BUG(Component, Description, File, Line, Func, ...) \
+ G_STMT_START { \
+ g_printerr ("-----------------------------------------------------------------\n"); \
+ g_printerr ("You've found a bug in Settings or one of its dependent libraries.\n"); \
+ g_printerr ("Please help us help you by filing a bug report at:\n"); \
+ g_printerr ("\n"); \
+ g_printerr ("@BUGREPORT_URL@&component=%s\n", Component); \
+ g_printerr ("\n"); \
+ g_printerr ("%s:%d in function %s()\n", File, Line, Func); \
+ g_printerr ("\n"); \
+ g_printerr (Description"\n", ##__VA_ARGS__); \
+ g_printerr ("-----------------------------------------------------------------\n"); \
+ } G_STMT_END
+
+/**
+ * CC_BUG:
+ * @Component: the component
+ * @Description: the description
+ * @...: extra arguments
+ *
+ * Logs a bug-friendly message.
+ */
+#define CC_BUG(Component, Description, ...) \
+ _CC_BUG(Component, Description, __FILE__, __LINE__, G_STRFUNC, ##__VA_ARGS__)
+
+G_END_DECLS
diff --git a/shell/cc-editable-entry.c b/shell/cc-editable-entry.c
deleted file mode 100644
index 8c81fc112..000000000
--- a/shell/cc-editable-entry.c
+++ /dev/null
@@ -1,644 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
- *
- * Copyright 2009-2010 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 <http://www.gnu.org/licenses/>.
- *
- * Written by: Matthias Clasen <mclasen@redhat.com>
- */
-
-#include <gdk/gdkkeysyms.h>
-#include "cc-editable-entry.h"
-
-#define EMPTY_TEXT "\xe2\x80\x94"
-
-struct _CcEditableEntryPrivate {
- GtkStack *stack;
- GtkLabel *label;
- GtkButton *button;
- GtkEntry *entry;
-
- gchar *text;
- gboolean editable;
- gboolean selectable;
- gint weight;
- gboolean weight_set;
- gdouble scale;
- gboolean scale_set;
- gint width_chars;
- gint max_width_chars;
- PangoEllipsizeMode ellipsize;
-
- gboolean in_stop_editing;
-};
-
-#define CC_EDITABLE_ENTRY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CC_TYPE_EDITABLE_ENTRY, CcEditableEntryPrivate))
-
-enum {
- PROP_0,
- PROP_TEXT,
- PROP_EDITABLE,
- PROP_SELECTABLE,
- PROP_SCALE,
- PROP_SCALE_SET,
- PROP_WEIGHT,
- PROP_WEIGHT_SET,
- PROP_WIDTH_CHARS,
- PROP_MAX_WIDTH_CHARS,
- PROP_ELLIPSIZE
-};
-
-enum {
- EDITING_DONE,
- LAST_SIGNAL
-};
-
-#define PAGE_LABEL "_label"
-#define PAGE_BUTTON "_button"
-#define PAGE_ENTRY "_entry"
-
-static guint signals [LAST_SIGNAL] = { 0, };
-
-G_DEFINE_TYPE (CcEditableEntry, cc_editable_entry, GTK_TYPE_BIN);
-
-void
-cc_editable_entry_set_text (CcEditableEntry *e,
- const gchar *text)
-{
- CcEditableEntryPrivate *priv;
- gchar *tmp;
- GtkWidget *label;
-
- priv = e->priv;
-
- tmp = g_strdup (text);
- g_free (priv->text);
- priv->text = tmp;
-
- gtk_entry_set_text (priv->entry, tmp);
-
- if (tmp == NULL || tmp[0] == '\0')
- tmp = EMPTY_TEXT;
-
- gtk_label_set_text (priv->label, tmp);
- label = gtk_bin_get_child (GTK_BIN (priv->button));
- gtk_label_set_text (GTK_LABEL (label), tmp);
-
- g_object_notify (G_OBJECT (e), "text");
-}
-
-const gchar *
-cc_editable_entry_get_text (CcEditableEntry *e)
-{
- return e->priv->text;
-}
-
-void
-cc_editable_entry_set_editable (CcEditableEntry *e,
- gboolean editable)
-{
- CcEditableEntryPrivate *priv;
-
- priv = e->priv;
-
- if (priv->editable != editable) {
- priv->editable = editable;
-
- gtk_stack_set_visible_child_name (e->priv->stack, editable ? PAGE_BUTTON : PAGE_LABEL);
-
- g_object_notify (G_OBJECT (e), "editable");
- }
-}
-
-gboolean
-cc_editable_entry_get_editable (CcEditableEntry *e)
-{
- return e->priv->editable;
-}
-
-void
-cc_editable_entry_set_selectable (CcEditableEntry *e,
- gboolean selectable)
-{
- CcEditableEntryPrivate *priv;
-
- priv = e->priv;
-
- if (priv->selectable != selectable) {
- priv->selectable = selectable;
-
- gtk_label_set_selectable (priv->label, selectable);
-
- g_object_notify (G_OBJECT (e), "selectable");
- }
-}
-
-gboolean
-cc_editable_entry_get_selectable (CcEditableEntry *e)
-{
- return e->priv->selectable;
-}
-
-
-static void
-update_fonts (CcEditableEntry *e)
-{
- PangoAttrList *attrs;
- PangoAttribute *attr;
- GtkWidget *label;
-
- CcEditableEntryPrivate *priv = e->priv;
-
- attrs = pango_attr_list_new ();
- if (priv->scale_set) {
- attr = pango_attr_scale_new (priv->scale);
- pango_attr_list_insert (attrs, attr);
- }
- if (priv->weight_set) {
- attr = pango_attr_weight_new (priv->weight);
- pango_attr_list_insert (attrs, attr);
- }
-
- gtk_label_set_attributes (priv->label, attrs);
-
- label = gtk_bin_get_child (GTK_BIN (priv->button));
- gtk_label_set_attributes (GTK_LABEL (label), attrs);
- gtk_entry_set_attributes (priv->entry, attrs);
-
- pango_attr_list_unref (attrs);
-}
-
-void
-cc_editable_entry_set_weight (CcEditableEntry *e,
- gint weight)
-{
- CcEditableEntryPrivate *priv = e->priv;
-
- if (priv->weight == weight && priv->weight_set)
- return;
-
- priv->weight = weight;
- priv->weight_set = TRUE;
-
- update_fonts (e);
-
- g_object_notify (G_OBJECT (e), "weight");
- g_object_notify (G_OBJECT (e), "weight-set");
-}
-
-gint
-cc_editable_entry_get_weight (CcEditableEntry *e)
-{
- return e->priv->weight;
-}
-
-void
-cc_editable_entry_set_scale (CcEditableEntry *e,
- gdouble scale)
-{
- CcEditableEntryPrivate *priv = e->priv;
-
- if (priv->scale == scale && priv->scale_set)
- return;
-
- priv->scale = scale;
- priv->scale_set = TRUE;
-
- update_fonts (e);
-
- g_object_notify (G_OBJECT (e), "scale");
- g_object_notify (G_OBJECT (e), "scale-set");
-}
-
-gdouble
-cc_editable_entry_get_scale (CcEditableEntry *e)
-{
- return e->priv->scale;
-}
-
-void
-cc_editable_entry_set_width_chars (CcEditableEntry *e,
- gint n_chars)
-{
- CcEditableEntryPrivate *priv = e->priv;
- GtkWidget *label;
-
- if (priv->width_chars != n_chars) {
- label = gtk_bin_get_child (GTK_BIN (priv->button));
-
- gtk_entry_set_width_chars (priv->entry, n_chars);
- gtk_label_set_width_chars (priv->label, n_chars);
- gtk_label_set_width_chars (GTK_LABEL (label), n_chars);
-
- priv->width_chars = n_chars;
- g_object_notify (G_OBJECT (e), "width-chars");
- gtk_widget_queue_resize (GTK_WIDGET (priv->entry));
- gtk_widget_queue_resize (GTK_WIDGET (priv->label));
- gtk_widget_queue_resize (GTK_WIDGET (label));
- }
-}
-
-gint
-cc_editable_entry_get_width_chars (CcEditableEntry *e)
-{
- return e->priv->width_chars;
-}
-
-void
-cc_editable_entry_set_max_width_chars (CcEditableEntry *e,
- gint n_chars)
-{
- CcEditableEntryPrivate *priv = e->priv;
- GtkWidget *label;
-
- if (priv->max_width_chars != n_chars) {
- label = gtk_bin_get_child (GTK_BIN (priv->button));
- gtk_label_set_max_width_chars (priv->label, n_chars);
- gtk_label_set_max_width_chars (GTK_LABEL (label), n_chars);
-
- priv->max_width_chars = n_chars;
- g_object_notify (G_OBJECT (e), "max-width-chars");
- gtk_widget_queue_resize (GTK_WIDGET (priv->entry));
- gtk_widget_queue_resize (GTK_WIDGET (priv->label));
- gtk_widget_queue_resize (GTK_WIDGET (label));
- }
-}
-
-gint
-cc_editable_entry_get_max_width_chars (CcEditableEntry *e)
-{
- return e->priv->max_width_chars;
-}
-
-void
-cc_editable_entry_set_ellipsize (CcEditableEntry *e,
- PangoEllipsizeMode mode)
-{
- CcEditableEntryPrivate *priv = e->priv;
- GtkWidget *label;
-
- if ((PangoEllipsizeMode) priv->ellipsize != mode) {
- label = gtk_bin_get_child (GTK_BIN (priv->button));
- gtk_label_set_ellipsize (priv->label, mode);
- gtk_label_set_ellipsize (GTK_LABEL (label), mode);
-
- priv->ellipsize = mode;
- g_object_notify (G_OBJECT (e), "ellipsize");
- gtk_widget_queue_resize (GTK_WIDGET (priv->label));
- gtk_widget_queue_resize (GTK_WIDGET (label));
- }
-}
-
-PangoEllipsizeMode
-cc_editable_entry_get_ellipsize (CcEditableEntry *e)
-{
- return e->priv->ellipsize;
-}
-
-static void
-cc_editable_entry_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- CcEditableEntry *e = CC_EDITABLE_ENTRY (object);
-
- switch (prop_id) {
- case PROP_TEXT:
- cc_editable_entry_set_text (e, g_value_get_string (value));
- break;
- case PROP_EDITABLE:
- cc_editable_entry_set_editable (e, g_value_get_boolean (value));
- break;
- case PROP_SELECTABLE:
- cc_editable_entry_set_selectable (e, g_value_get_boolean (value));
- break;
- case PROP_WEIGHT:
- cc_editable_entry_set_weight (e, g_value_get_int (value));
- break;
- case PROP_WEIGHT_SET:
- e->priv->weight_set = g_value_get_boolean (value);
- break;
- case PROP_SCALE:
- cc_editable_entry_set_scale (e, g_value_get_double (value));
- break;
- case PROP_SCALE_SET:
- e->priv->scale_set = g_value_get_boolean (value);
- break;
- case PROP_WIDTH_CHARS:
- cc_editable_entry_set_width_chars (e, g_value_get_int (value));
- break;
- case PROP_MAX_WIDTH_CHARS:
- cc_editable_entry_set_max_width_chars (e, g_value_get_int (value));
- break;
- case PROP_ELLIPSIZE:
- cc_editable_entry_set_ellipsize (e, g_value_get_enum (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-cc_editable_entry_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- CcEditableEntry *e = CC_EDITABLE_ENTRY (object);
-
- switch (prop_id) {
- case PROP_TEXT:
- g_value_set_string (value,
- cc_editable_entry_get_text (e));
- break;
- case PROP_EDITABLE:
- g_value_set_boolean (value,
- cc_editable_entry_get_editable (e));
- break;
- case PROP_SELECTABLE:
- g_value_set_boolean (value,
- cc_editable_entry_get_selectable (e));
- break;
- case PROP_WEIGHT:
- g_value_set_int (value,
- cc_editable_entry_get_weight (e));
- break;
- case PROP_WEIGHT_SET:
- g_value_set_boolean (value, e->priv->weight_set);
- break;
- case PROP_SCALE:
- g_value_set_double (value,
- cc_editable_entry_get_scale (e));
- break;
- case PROP_SCALE_SET:
- g_value_set_boolean (value, e->priv->scale_set);
- break;
- case PROP_WIDTH_CHARS:
- g_value_set_int (value,
- cc_editable_entry_get_width_chars (e));
- break;
- case PROP_MAX_WIDTH_CHARS:
- g_value_set_int (value,
- cc_editable_entry_get_max_width_chars (e));
- break;
- case PROP_ELLIPSIZE:
- g_value_set_enum (value,
- cc_editable_entry_get_ellipsize (e));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-cc_editable_entry_finalize (GObject *object)
-{
- CcEditableEntry *e = (CcEditableEntry*)object;
-
- g_free (e->priv->text);
-
- G_OBJECT_CLASS (cc_editable_entry_parent_class)->finalize (object);
-}
-
-static void
-cc_editable_entry_class_init (CcEditableEntryClass *class)
-{
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS (class);
-
- object_class->set_property = cc_editable_entry_set_property;
- object_class->get_property = cc_editable_entry_get_property;
- object_class->finalize = cc_editable_entry_finalize;
-
- signals[EDITING_DONE] =
- g_signal_new ("editing-done",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (CcEditableEntryClass, editing_done),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- g_object_class_install_property (object_class, PROP_TEXT,
- g_param_spec_string ("text",
- "Text", "The text of the button",
- NULL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_EDITABLE,
- g_param_spec_boolean ("editable",
- "Editable", "Whether the text can be edited",
- FALSE,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_SELECTABLE,
- g_param_spec_boolean ("selectable",
- "Selectable", "Whether the text can be selected by mouse",
- FALSE,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_WEIGHT,
- g_param_spec_int ("weight",
- "Font Weight", "The font weight to use",
- 0, G_MAXINT, PANGO_WEIGHT_NORMAL,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_WEIGHT_SET,
- g_param_spec_boolean ("weight-set",
- "Font Weight Set", "Whether a font weight is set",
- FALSE,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_SCALE,
- g_param_spec_double ("scale",
- "Font Scale", "The font scale to use",
- 0.0, G_MAXDOUBLE, 1.0,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_SCALE_SET,
- g_param_spec_boolean ("scale-set",
- "Font Scale Set", "Whether a font scale is set",
- FALSE,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_WIDTH_CHARS,
- g_param_spec_int ("width-chars",
- "Width In Characters", "The desired width of the editable entry, in characters",
- -1, G_MAXINT, -1,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_MAX_WIDTH_CHARS,
- g_param_spec_int ("max-width-chars",
- "Maximum Width In Characters","The desired maximum width of the editable entry, in characters",
- -1, G_MAXINT, -1,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (object_class, PROP_ELLIPSIZE,
- g_param_spec_enum ("ellipsize",
- "Ellipsize", "The preferred place to ellipsize the string, if the editable entry does not have enough room to display the entire string",
- PANGO_TYPE_ELLIPSIZE_MODE, PANGO_ELLIPSIZE_NONE,
- G_PARAM_READWRITE));
-
- g_type_class_add_private (class, sizeof (CcEditableEntryPrivate));
-}
-
-static void
-start_editing (CcEditableEntry *e)
-{
- gtk_stack_set_visible_child_name (e->priv->stack, PAGE_ENTRY);
- gtk_widget_grab_focus (GTK_WIDGET (e->priv->entry));
-}
-
-static void
-stop_editing (CcEditableEntry *e)
-{
- gboolean has_focus;
-
- /* Avoid launching another "editing-done" signal
- * caused by the notebook page change */
- if (e->priv->in_stop_editing)
- return;
-
- e->priv->in_stop_editing = TRUE;
- has_focus = gtk_widget_has_focus (GTK_WIDGET (e->priv->entry));
- gtk_stack_set_visible_child_name (e->priv->stack, PAGE_BUTTON);
- if (has_focus)
- gtk_widget_grab_focus (GTK_WIDGET (e->priv->button));
-
- cc_editable_entry_set_text (e, gtk_entry_get_text (e->priv->entry));
- g_signal_emit (e, signals[EDITING_DONE], 0);
- e->priv->in_stop_editing = FALSE;
-}
-
-static void
-cancel_editing (CcEditableEntry *e)
-{
- gtk_entry_set_text (e->priv->entry, cc_editable_entry_get_text (e));
- gtk_stack_set_visible_child_name (e->priv->stack, PAGE_BUTTON);
- gtk_widget_grab_focus (GTK_WIDGET (e->priv->button));
-}
-
-static void
-button_clicked (GtkWidget *widget,
- CcEditableEntry *e)
-{
- start_editing (e);
-}
-
-static void
-entry_activated (GtkWidget *widget,
- CcEditableEntry *e)
-{
- stop_editing (e);
-}
-
-static gboolean
-entry_focus_out (GtkWidget *widget,
- GdkEventFocus *event,
- CcEditableEntry *e)
-{
- stop_editing (e);
- return FALSE;
-}
-
-static gboolean
-entry_key_press (GtkWidget *widget,
- GdkEventKey *event,
- CcEditableEntry *e)
-{
- if (event->keyval == GDK_KEY_Escape) {
- cancel_editing (e);
- }
- return FALSE;
-}
-
-static void
-update_button_padding (CcEditableEntry *e, gpointer user_data)
-{
- CcEditableEntryPrivate *priv = e->priv;
- GtkStyleContext *context;
- GtkStateFlags state;
- GtkBorder padding, border;
- gint margin;
-
- context = gtk_widget_get_style_context (GTK_WIDGET (priv->button));
- state = gtk_style_context_get_state (context);
-
- gtk_style_context_get_padding (context, state, &padding);
- gtk_style_context_get_border (context, state, &border);
-
- margin = padding.left + border.left;
- gtk_widget_set_margin_start (GTK_WIDGET (priv->label), margin);
- gtk_widget_set_margin_end (GTK_WIDGET (priv->label), margin);
-}
-
-static void
-cc_editable_entry_init (CcEditableEntry *e)
-{
- CcEditableEntryPrivate *priv;
-
- priv = e->priv = CC_EDITABLE_ENTRY_GET_PRIVATE (e);
-
- priv->weight = PANGO_WEIGHT_NORMAL;
- priv->weight_set = FALSE;
- priv->scale = 1.0;
- priv->scale_set = FALSE;
- priv->width_chars = -1;
- priv->max_width_chars = -1;
- priv->ellipsize = PANGO_ELLIPSIZE_NONE;
- priv->stack = GTK_STACK (gtk_stack_new ());
-
- /* Label */
- priv->label = (GtkLabel*)gtk_label_new (EMPTY_TEXT);
- g_object_set (G_OBJECT (priv->label), "xalign", 0.0, NULL);
- gtk_stack_add_named (priv->stack, GTK_WIDGET (priv->label), PAGE_LABEL);
-
- /* Button */
- priv->button = (GtkButton*)gtk_button_new_with_label (EMPTY_TEXT);
- gtk_widget_set_receives_default ((GtkWidget*)priv->button, TRUE);
- gtk_button_set_relief (priv->button, GTK_RELIEF_NONE);
- g_object_set (G_OBJECT (gtk_bin_get_child (GTK_BIN (priv->button))), "xalign", 0.0, NULL);
-
- gtk_stack_add_named (priv->stack, GTK_WIDGET (priv->button), PAGE_BUTTON);
- g_signal_connect (priv->button, "clicked", G_CALLBACK (button_clicked), e);
-
- /* Entry */
- priv->entry = (GtkEntry*)gtk_entry_new ();
- gtk_stack_add_named (priv->stack, GTK_WIDGET (priv->entry), PAGE_ENTRY);
-
- g_signal_connect (priv->entry, "activate", G_CALLBACK (entry_activated), e);
- g_signal_connect (priv->entry, "focus-out-event", G_CALLBACK (entry_focus_out), e);
- g_signal_connect (priv->entry, "key-press-event", G_CALLBACK (entry_key_press), e);
-
- g_signal_connect (e, "style-updated", G_CALLBACK (update_button_padding), NULL);
-
- gtk_container_add (GTK_CONTAINER (e), (GtkWidget*)priv->stack);
-
- gtk_widget_show ((GtkWidget*)priv->stack);
- gtk_widget_show ((GtkWidget*)priv->label);
- gtk_widget_show ((GtkWidget*)priv->button);
- gtk_widget_show ((GtkWidget*)priv->entry);
-
- gtk_stack_set_visible_child_name (e->priv->stack, PAGE_LABEL);
-}
-
-GtkWidget *
-cc_editable_entry_new (void)
-{
- return (GtkWidget *) g_object_new (CC_TYPE_EDITABLE_ENTRY, NULL);
-}
diff --git a/shell/cc-editable-entry.h b/shell/cc-editable-entry.h
deleted file mode 100644
index 9d61c5480..000000000
--- a/shell/cc-editable-entry.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
- *
- * Copyright 2009-2010 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 <http://www.gnu.org/licenses/>.
- *
- * Written by: Matthias Clasen <mclasen@redhat.com>
- */
-
-#ifndef _CC_EDITABLE_ENTRY_H_
-#define _CC_EDITABLE_ENTRY_H_
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define CC_TYPE_EDITABLE_ENTRY cc_editable_entry_get_type()
-
-#define CC_EDITABLE_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CC_TYPE_EDITABLE_ENTRY, CcEditableEntry))
-#define CC_EDITABLE_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CC_TYPE_EDITABLE_ENTRY, CcEditableEntryClass))
-#define CC_IS_EDITABLE_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CC_TYPE_EDITABLE_ENTRY))
-#define CC_IS_EDITABLE_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CC_TYPE_EDITABLE_ENTRY))
-#define CC_EDITABLE_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CC_TYPE_EDITABLE_ENTRY, CcEditableEntryClass))
-
-typedef struct _CcEditableEntry CcEditableEntry;
-typedef struct _CcEditableEntryClass CcEditableEntryClass;
-typedef struct _CcEditableEntryPrivate CcEditableEntryPrivate;
-
-struct _CcEditableEntry
-{
- GtkAlignment parent;
-
- CcEditableEntryPrivate *priv;
-};
-
-struct _CcEditableEntryClass
-{
- GtkAlignmentClass parent_class;
-
- void (* editing_done) (CcEditableEntry *entry);
-};
-
-GType cc_editable_entry_get_type (void) G_GNUC_CONST;
-GtkWidget *cc_editable_entry_new (void);
-void cc_editable_entry_set_text (CcEditableEntry *entry,
- const gchar *text);
-const gchar *cc_editable_entry_get_text (CcEditableEntry *entry);
-void cc_editable_entry_set_editable (CcEditableEntry *entry,
- gboolean editable);
-gboolean cc_editable_entry_get_editable (CcEditableEntry *entry);
-void cc_editable_entry_set_selectable (CcEditableEntry *entry,
- gboolean selectable);
-gboolean cc_editable_entry_get_selectable (CcEditableEntry *entry);
-void cc_editable_entry_set_weight (CcEditableEntry *entry,
- gint weight);
-gint cc_editable_entry_get_weight (CcEditableEntry *entry);
-void cc_editable_entry_set_scale (CcEditableEntry *entry,
- gdouble scale);
-gdouble cc_editable_entry_get_scale (CcEditableEntry *entry);
-void cc_editable_entry_set_width_chars (CcEditableEntry *entry,
- gint n_chars);
-gint cc_editable_entry_get_width_chars (CcEditableEntry *entry);
-void cc_editable_entry_set_max_width_chars (CcEditableEntry *entry,
- gint n_chars);
-gint cc_editable_entry_get_max_width_chars (CcEditableEntry *entry);
-void cc_editable_entry_set_ellipsize (CcEditableEntry *entry,
- PangoEllipsizeMode mode);
-PangoEllipsizeMode cc_editable_entry_get_ellipsize (CcEditableEntry *entry);
-
-G_END_DECLS
-
-#endif /* _CC_EDITABLE_ENTRY_H_ */
diff --git a/shell/cc-hostname-entry.c b/shell/cc-hostname-entry.c
deleted file mode 100644
index 0b0d6d10c..000000000
--- a/shell/cc-hostname-entry.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
- *
- * Copyright (C) 2013 Intel, Inc
- * Copyright (C) 2011,2012 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-
-#include "cc-hostname-entry.h"
-#include "hostname-helper.h"
-
-#include <polkit/polkit.h>
-
-struct _CcHostnameEntry
-{
- GtkEntry parent;
-
- GDBusProxy *hostnamed_proxy;
- guint set_hostname_timeout_source_id;
-};
-
-G_DEFINE_TYPE (CcHostnameEntry, cc_hostname_entry, GTK_TYPE_ENTRY)
-
-#define SET_HOSTNAME_TIMEOUT 1
-
-static void
-cc_hostname_entry_set_hostname (CcHostnameEntry *self)
-{
- char *hostname;
- GVariant *variant;
- GError *error = NULL;
- const gchar *text;
-
- text = gtk_entry_get_text (GTK_ENTRY (self));
-
- g_debug ("Setting PrettyHostname to '%s'", text);
- variant = g_dbus_proxy_call_sync (self->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 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->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_free (hostname);
-}
-
-static char *
-get_hostname_property (CcHostnameEntry *self,
- const char *property)
-{
- GVariant *variant;
- char *str;
-
- if (!self->hostnamed_proxy)
- return g_strdup ("");
-
- variant = g_dbus_proxy_get_cached_property (self->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->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 *
-cc_hostname_entry_get_display_hostname (CcHostnameEntry *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 gboolean
-set_hostname_timeout (CcHostnameEntry *self)
-{
- self->set_hostname_timeout_source_id = 0;
-
- cc_hostname_entry_set_hostname (self);
-
- return FALSE;
-}
-
-static void
-remove_hostname_timeout (CcHostnameEntry *self)
-{
- if (self->set_hostname_timeout_source_id)
- g_source_remove (self->set_hostname_timeout_source_id);
-
- self->set_hostname_timeout_source_id = 0;
-}
-
-static void
-reset_hostname_timeout (CcHostnameEntry *self)
-{
- remove_hostname_timeout (self);
-
- self->set_hostname_timeout_source_id = g_timeout_add_seconds (SET_HOSTNAME_TIMEOUT,
- (GSourceFunc) set_hostname_timeout,
- self);
-}
-
-static void
-text_changed_cb (CcHostnameEntry *entry)
-{
- reset_hostname_timeout (entry);
-}
-
-static void
-cc_hostname_entry_dispose (GObject *object)
-{
- CcHostnameEntry *self = CC_HOSTNAME_ENTRY (object);
-
- if (self->set_hostname_timeout_source_id)
- {
- remove_hostname_timeout (self);
- set_hostname_timeout (self);
- }
-
- g_clear_object (&self->hostnamed_proxy);
-
- G_OBJECT_CLASS (cc_hostname_entry_parent_class)->dispose (object);
-}
-
-static void
-cc_hostname_entry_constructed (GObject *object)
-{
- CcHostnameEntry *self = CC_HOSTNAME_ENTRY (object);
- GPermission *permission;
- GError *error = NULL;
- char *str;
-
- permission = polkit_permission_new_sync ("org.freedesktop.hostname1.set-static-hostname",
- NULL, NULL, NULL);
-
- /* Is hostnamed installed? */
- if (permission == NULL)
- {
- g_debug ("Will not show hostname, hostnamed not installed");
-
- gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
-
- return;
- }
-
- if (g_permission_get_allowed (permission))
- gtk_widget_set_sensitive (GTK_WIDGET (self), TRUE);
- else
- {
- g_debug ("Not allowed to change the hostname");
- gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE);
- }
-
- gtk_widget_set_sensitive (GTK_WIDGET (self),
- g_permission_get_allowed (permission));
-
- self->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->hostnamed_proxy == NULL)
- {
- g_debug ("Couldn't get hostnamed to start, bailing: %s", error->message);
- g_error_free (error);
- return;
- }
-
- str = cc_hostname_entry_get_display_hostname (CC_HOSTNAME_ENTRY (self));
-
- if (str != NULL)
- gtk_entry_set_text (GTK_ENTRY (self), str);
- else
- gtk_entry_set_text (GTK_ENTRY (self), "");
- g_free (str);
-
- g_signal_connect (G_OBJECT (self), "changed", G_CALLBACK (text_changed_cb), self);
-}
-
-static void
-cc_hostname_entry_class_init (CcHostnameEntryClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->constructed = cc_hostname_entry_constructed;
- object_class->dispose = cc_hostname_entry_dispose;
-}
-
-static void
-cc_hostname_entry_init (CcHostnameEntry *self)
-{
-}
-
-CcHostnameEntry *
-cc_hostname_entry_new (void)
-{
- return g_object_new (CC_TYPE_HOSTNAME_ENTRY, NULL);
-}
-
-gchar*
-cc_hostname_entry_get_hostname (CcHostnameEntry *entry)
-{
- return get_hostname_property (entry, "Hostname");
-}
diff --git a/shell/cc-hostname-entry.h b/shell/cc-hostname-entry.h
deleted file mode 100644
index a48177961..000000000
--- a/shell/cc-hostname-entry.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
- *
- * Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-#pragma once
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define CC_TYPE_HOSTNAME_ENTRY (cc_hostname_entry_get_type())
-
-G_DECLARE_FINAL_TYPE (CcHostnameEntry, cc_hostname_entry, CC, HOSTNAME_ENTRY, GtkEntry)
-
-CcHostnameEntry *cc_hostname_entry_new (void);
-gchar* cc_hostname_entry_get_hostname (CcHostnameEntry *entry);
-
-G_END_DECLS
diff --git a/shell/cc-log.c b/shell/cc-log.c
new file mode 100644
index 000000000..5f6645cbe
--- /dev/null
+++ b/shell/cc-log.c
@@ -0,0 +1,107 @@
+/* cc-shell-log.c
+ *
+ * Copyright © 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.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 "cc-debug.h"
+#include "cc-log.h"
+
+#include <unistd.h>
+#include <glib.h>
+
+G_LOCK_DEFINE_STATIC (channel_lock);
+
+GIOChannel *standard_channel = NULL;
+
+static const gchar* ignored_domains[] =
+{
+ "GdkPixbuf",
+ NULL
+};
+
+static const gchar *
+log_level_str (GLogLevelFlags log_level)
+{
+ switch (((gulong)log_level & G_LOG_LEVEL_MASK))
+ {
+ case G_LOG_LEVEL_ERROR: return " \033[1;31mERROR\033[0m";
+ case G_LOG_LEVEL_CRITICAL: return "\033[1;35mCRITICAL\033[0m";
+ case G_LOG_LEVEL_WARNING: return " \033[1;33mWARNING\033[0m";
+ case G_LOG_LEVEL_MESSAGE: return " \033[1;34mMESSAGE\033[0m";
+ case G_LOG_LEVEL_INFO: return " \033[1;32mINFO\033[0m";
+ case G_LOG_LEVEL_DEBUG: return " \033[1;32mDEBUG\033[0m";
+ case CC_LOG_LEVEL_TRACE: return " \033[1;36mTRACE\033[0m";
+ default: return " UNKNOWN";
+ }
+}
+
+static void
+log_handler (const gchar *domain,
+ GLogLevelFlags log_level,
+ const gchar *message,
+ gpointer user_data)
+{
+ GTimeVal tv;
+ struct tm tt;
+ time_t t;
+ const gchar *level;
+ gchar ftime[32];
+ gchar *buffer;
+
+ /* Skip ignored log domains */
+ if (domain && g_strv_contains (ignored_domains, domain))
+ return;
+
+ level = log_level_str (log_level);
+ g_get_current_time (&tv);
+ t = (time_t) tv.tv_sec;
+ tt = *localtime (&t);
+ strftime (ftime, sizeof (ftime), "%H:%M:%S", &tt);
+ buffer = g_strdup_printf ("%s.%04ld %24s: %s: %s\n",
+ ftime,
+ tv.tv_usec / 1000,
+ domain,
+ level,
+ message);
+
+ /* Safely write to the channel */
+ G_LOCK (channel_lock);
+
+ g_io_channel_write_chars (standard_channel, buffer, -1, NULL, NULL);
+ g_io_channel_flush (standard_channel, NULL);
+
+ G_UNLOCK (channel_lock);
+
+ g_free (buffer);
+}
+
+void
+cc_log_init (void)
+{
+ static gsize initialized = FALSE;
+
+ if (g_once_init_enter (&initialized))
+ {
+ standard_channel = g_io_channel_unix_new (STDOUT_FILENO);
+
+ g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
+
+ g_log_set_default_handler (log_handler, NULL);
+
+ g_once_init_leave (&initialized, TRUE);
+ }
+}
+
diff --git a/shell/hostname-helper.h b/shell/cc-log.h
index 9f96c12f9..2d04c0ba7 100644
--- a/shell/hostname-helper.h
+++ b/shell/cc-log.h
@@ -1,9 +1,10 @@
-/*
- * Copyright (C) 2011 Red Hat, Inc
+/* cc-log.h
*
- * This program is free software; you can redistribute it and/or modify
+ * Copyright © 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.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
+ * 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,
@@ -12,10 +13,13 @@
* 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/>.
- *
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-char *pretty_hostname_to_static (const char *pretty,
- gboolean for_display);
-char *pretty_hostname_to_ssid (const char *pretty);
+#pragma once
+
+G_BEGIN_DECLS
+
+void cc_log_init (void);
+
+G_END_DECLS
diff --git a/shell/cc-object-storage.c b/shell/cc-object-storage.c
new file mode 100644
index 000000000..46038cc34
--- /dev/null
+++ b/shell/cc-object-storage.c
@@ -0,0 +1,438 @@
+/* cc-object-storage.h
+ *
+ * Copyright 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.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/>.
+ */
+
+#define G_LOG_DOMAIN "cc-object-storage"
+
+#include "cc-object-storage.h"
+
+struct _CcObjectStorage
+{
+ GObject parent_instance;
+
+ GHashTable *id_to_object;
+};
+
+G_DEFINE_TYPE (CcObjectStorage, cc_object_storage, G_TYPE_OBJECT)
+
+/* Singleton instance */
+CcObjectStorage *_instance = NULL;
+
+/* GTask API to create a new D-Bus proxy */
+typedef struct
+{
+ GBusType bus_type;
+ GDBusProxyFlags flags;
+ gchar *name;
+ gchar *path;
+ gchar *interface;
+ gboolean cached;
+} TaskData;
+
+static TaskData*
+task_data_new (GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *path,
+ const gchar *interface)
+{
+ TaskData *data = g_slice_new (TaskData);
+ data->bus_type = bus_type;
+ data->flags =flags;
+ data->name = g_strdup (name);
+ data->path = g_strdup (path);
+ data->interface = g_strdup (interface);
+ data->cached = FALSE;
+
+ return data;
+}
+
+static void
+task_data_free (TaskData *data)
+{
+ g_free (data->name);
+ g_free (data->path);
+ g_free (data->interface);
+ g_slice_free (TaskData, data);
+}
+
+static void
+create_dbus_proxy_in_thread_cb (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ g_autoptr(GDBusProxy) proxy = NULL;
+ g_autoptr(GError) local_error = NULL;
+ TaskData *data = task_data;
+
+ proxy = g_dbus_proxy_new_for_bus_sync (data->bus_type,
+ data->flags,
+ NULL,
+ data->name,
+ data->path,
+ data->interface,
+ cancellable,
+ &local_error);
+
+ if (local_error)
+ {
+ g_task_return_error (task, local_error);
+ return;
+ }
+
+ g_task_return_pointer (task, g_object_ref (g_steal_pointer (&proxy)), g_object_unref);
+}
+
+static void
+cc_object_storage_finalize (GObject *object)
+{
+ CcObjectStorage *self = (CcObjectStorage *)object;
+
+ g_debug ("Destroying cached objects");
+
+ g_clear_pointer (&self->id_to_object, g_hash_table_destroy);
+
+ G_OBJECT_CLASS (cc_object_storage_parent_class)->finalize (object);
+}
+
+static void
+cc_object_storage_class_init (CcObjectStorageClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = cc_object_storage_finalize;
+}
+
+static void
+cc_object_storage_init (CcObjectStorage *self)
+{
+ self->id_to_object = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+}
+
+/**
+ * cc_object_storage_has_object:
+ * @key: the unique string identifier of the object
+ *
+ * Checks whether there is an object associated with @key.
+ *
+ * Returns: %TRUE if the object is stored, %FALSE otherwise.
+ */
+gboolean
+cc_object_storage_has_object (const gchar *key)
+{
+ g_assert (CC_IS_OBJECT_STORAGE (_instance));
+ g_assert (key != NULL);
+
+ return g_hash_table_contains (_instance->id_to_object, key);
+}
+
+/**
+ * cc_object_storage_add_object:
+ * @key: the unique string identifier of the object
+ * @object: (type GObject): the object to be stored
+ *
+ * Adds @object to the object storage. It is a programming error to try to
+ * add an object that was already added.
+ *
+ * @object must be a GObject.
+ *
+ * Always check if the object is stored with cc_object_storage_has_object()
+ * before calling this function.
+ */
+void
+cc_object_storage_add_object (const gchar *key,
+ gpointer object)
+{
+ /* Trying to add an object that was already added is a hard error. Each
+ * object must be added once, and only once, over the entire lifetime
+ * of the application.
+ */
+ g_assert (CC_IS_OBJECT_STORAGE (_instance));
+ g_assert (key != NULL);
+ g_assert (G_IS_OBJECT (object));
+ g_assert (!g_hash_table_contains (_instance->id_to_object, key));
+
+ g_debug ("Adding object %s (%s → %p) to the storage",
+ g_type_name (G_OBJECT_TYPE (object)),
+ key,
+ object);
+
+ g_hash_table_insert (_instance->id_to_object, g_strdup (key), g_object_ref (object));
+}
+
+/**
+ * cc_object_storage_get_object:
+ * @key: the unique string identifier of the object
+ *
+ * Retrieves the object associated with @key. It is a programming error to
+ * try to retrieve an object before adding it.
+ *
+ * Always check if the object is stored with cc_object_storage_has_object()
+ * before calling this function.
+ *
+ * Returns: (transfer full): the GObject associated with @key.
+ */
+gpointer
+cc_object_storage_get_object (const gchar *key)
+{
+ /* Trying to peek an object that was not yet added is a hard error. Users
+ * of this API need to first check if the object is available with
+ * cc_object_storage_has_object().
+ */
+ g_assert (CC_IS_OBJECT_STORAGE (_instance));
+ g_assert (key != NULL);
+ g_assert (g_hash_table_contains (_instance->id_to_object, key));
+
+ return g_object_ref (g_hash_table_lookup (_instance->id_to_object, key));
+}
+
+/**
+ * cc_object_storage_create_dbus_proxy_sync:
+ * @name: the D-Bus name
+ * @flags: the D-Bus proxy flags
+ * @path: the D-Bus object path
+ * @interface: the D-Bus interface name
+ * @cancellable: (nullable): #GCancellable to cancel the operation
+ * @error: (nullable): return location for a #GError
+ *
+ * Synchronously create a #GDBusProxy with @name, @path and @interface,
+ * stores it in the cache, and returns the newly created proxy.
+ *
+ * If a proxy with that signature is already created, it will be used
+ * instead of creating a new one.
+ *
+ * Returns: (transfer full)(nullable): the new #GDBusProxy.
+ */
+gpointer
+cc_object_storage_create_dbus_proxy_sync (GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *path,
+ const gchar *interface,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autoptr(GDBusProxy) proxy = NULL;
+ g_autoptr(GError) local_error = NULL;
+ g_autofree gchar *key = NULL;
+
+ g_assert (CC_IS_OBJECT_STORAGE (_instance));
+ g_assert (name && *name);
+ g_assert (path && *path);
+ g_assert (interface && *interface);
+ g_assert (!error || !*error);
+
+ key = g_strdup_printf ("CcObjectStorage::dbus-proxy(%s,%s,%s)", name, path, interface);
+
+ /* Check if a DBus proxy with that signature is already available; if it is,
+ * return that instead of a new one.
+ */
+ if (g_hash_table_contains (_instance->id_to_object, key))
+ return cc_object_storage_get_object (key);
+
+ proxy = g_dbus_proxy_new_for_bus_sync (bus_type,
+ flags,
+ NULL,
+ name,
+ path,
+ interface,
+ cancellable,
+ &local_error);
+
+ if (local_error)
+ {
+ g_propagate_error (error, g_steal_pointer (&local_error));
+ return NULL;
+ }
+
+ /* Store the newly created D-Bus proxy */
+ cc_object_storage_add_object (key, proxy);
+
+ return g_steal_pointer (&proxy);
+}
+
+
+/**
+ * cc_object_storage_create_dbus_proxy:
+ * @name: the D-Bus name
+ * @flags: the D-Bus proxy flags
+ * @path: the D-Bus object path
+ * @interface: the D-Bus interface name
+ * @cancellable: (nullable): #GCancellable to cancel the operation
+ * @callback: callback for when the async operation is finished
+ * @user_data: user data for @callback
+ *
+ * Asynchronously create a #GDBusProxy with @name, @path and @interface.
+ *
+ * If a proxy with that signature is already created, it will be used instead of
+ * creating a new one.
+ *
+ * It is a programming error to create the an identical proxy while asynchronously
+ * creating one. Not cancelling this operation will result in an assertion failure
+ * when calling cc_object_storage_create_dbus_proxy_finish().
+ */
+void
+cc_object_storage_create_dbus_proxy (GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *path,
+ const gchar *interface,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+ g_autofree gchar *key = NULL;
+ TaskData *data = NULL;
+
+ g_assert (CC_IS_OBJECT_STORAGE (_instance));
+ g_assert (name && *name);
+ g_assert (path && *path);
+ g_assert (interface && *interface);
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ data = task_data_new (bus_type, flags, name, path, interface);
+
+ task = g_task_new (_instance, cancellable, callback, user_data);
+ g_task_set_source_tag (task, cc_object_storage_create_dbus_proxy);
+ g_task_set_task_data (task, data, (GDestroyNotify) task_data_free);
+
+ /* Check if the D-Bus proxy is already created */
+ key = g_strdup_printf ("CcObjectStorage::dbus-proxy(%s,%s,%s)", name, path, interface);
+
+ if (g_hash_table_contains (_instance->id_to_object, key))
+ {
+ /* Mark this GTask as already cached, so we can call the right assertions
+ * on the callback
+ * */
+ data->cached = TRUE;
+
+ g_debug ("Found in cache the D-Bus proxy %s", key);
+
+ g_task_return_pointer (task, cc_object_storage_get_object (key), g_object_unref);
+ return;
+ }
+
+ g_task_run_in_thread (task, create_dbus_proxy_in_thread_cb);
+}
+
+/**
+ * cc_object_storage_create_dbus_proxy_finish:
+ * @result:
+ * @error: (nullable): return location for a #GError
+ *
+ * Finishes a D-Bus proxy creation started by cc_object_storage_create_dbus_proxy().
+ *
+ * Synchronously create a #GDBusProxy with @name, @path and @interface,
+ * stores it in the cache, and returns the newly created proxy.
+ *
+ * If a proxy with that signature is already created, it will be used
+ * instead of creating a new one.
+ *
+ * Returns: (transfer full)(nullable): the new #GDBusProxy.
+ */
+gpointer
+cc_object_storage_create_dbus_proxy_finish (GAsyncResult *result,
+ GError **error)
+{
+ g_autoptr(GDBusProxy) proxy = NULL;
+ g_autoptr(GError) local_error = NULL;
+ g_autofree gchar *key = NULL;
+ TaskData *task_data;
+ GTask *task;
+
+ task = G_TASK (result);
+
+ g_assert (task && G_TASK (result));
+ g_assert (!error || !*error);
+
+ task_data = g_task_get_task_data (task);
+
+ key = g_strdup_printf ("CcObjectStorage::dbus-proxy(%s,%s,%s)",
+ task_data->name,
+ task_data->path,
+ task_data->interface);
+
+ /* Either we have the object stored right when trying to create it - in which case,
+ * task_data->cached == TRUE and cc_object_storage_has_object (key) == TRUE - or we
+ * didn't have a cached proxy before, and we shouldn't have it now.
+ *
+ * This is to force consumers of this code to *never* try to create the same D-Bus
+ * proxy asynchronously multiple times. Trying to do so is considered a programming
+ * error.
+ */
+ g_assert (task_data != NULL);
+ g_assert (task_data->cached == cc_object_storage_has_object (key));
+
+ /* Retrieve the newly created proxy */
+ proxy = g_task_propagate_pointer (task, &local_error);
+
+ /* If the proxy is not cached, do the normal caching routine */
+ if (local_error)
+ {
+ g_propagate_error (error, g_steal_pointer (&local_error));
+ return NULL;
+ }
+
+ /* If the proxy is already cached, destroy the newly created and used the cached proxy
+ * instead.
+ */
+ if (cc_object_storage_has_object (key))
+ return cc_object_storage_get_object (key);
+
+ /* Store the newly created D-Bus proxy */
+ cc_object_storage_add_object (key, proxy);
+
+ return g_steal_pointer (&proxy);
+}
+
+/**
+ * cc_object_storage_init:
+ *
+ * Initializes the single CcObjectStorage. This must be called only once,
+ * and before every other method of this object.
+ */
+void
+cc_object_storage_initialize (void)
+{
+ g_assert (_instance == NULL);
+
+ if (g_once_init_enter (&_instance))
+ {
+ CcObjectStorage *instance = g_object_new (CC_TYPE_OBJECT_STORAGE, NULL);
+
+ g_debug ("Initializing object storage");
+
+ g_once_init_leave (&_instance, instance);
+ }
+}
+
+/**
+ * cc_object_storage_destroy:
+ *
+ * Destroys the instance of #CcObjectStorage. This must be called only
+ * once during the application lifetime. It is a programming error to
+ * call this function multiple times
+ */
+void
+cc_object_storage_destroy (void)
+{
+ g_assert (_instance != NULL);
+
+ g_clear_object (&_instance);
+}
diff --git a/shell/cc-object-storage.h b/shell/cc-object-storage.h
new file mode 100644
index 000000000..efea0e294
--- /dev/null
+++ b/shell/cc-object-storage.h
@@ -0,0 +1,65 @@
+/* cc-object-storage.h
+ *
+ * Copyright 2018 Georges Basile Stavracas Neto <georges.stavracas@gmail.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/>.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+/* Default storage keys */
+#define CC_OBJECT_NMCLIENT "CcObjectStorage::nm-client"
+
+
+#define CC_TYPE_OBJECT_STORAGE (cc_object_storage_get_type())
+
+G_DECLARE_FINAL_TYPE (CcObjectStorage, cc_object_storage, CC, OBJECT_STORAGE, GObject)
+
+gboolean cc_object_storage_has_object (const gchar *key);
+
+void cc_object_storage_add_object (const gchar *key,
+ gpointer object);
+
+gpointer cc_object_storage_get_object (const gchar *key);
+
+gpointer cc_object_storage_create_dbus_proxy_sync (GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *path,
+ const gchar *interface,
+ GCancellable *cancellable,
+ GError **error);
+
+void cc_object_storage_create_dbus_proxy (GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *path,
+ const gchar *interface,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gpointer cc_object_storage_create_dbus_proxy_finish (GAsyncResult *result,
+ GError **error);
+
+void cc_object_storage_initialize (void);
+
+void cc_object_storage_destroy (void);
+
+G_END_DECLS
diff --git a/shell/cc-panel-list.c b/shell/cc-panel-list.c
index 0fd093cf9..f5b83509d 100644
--- a/shell/cc-panel-list.c
+++ b/shell/cc-panel-list.c
@@ -294,6 +294,7 @@ static const gchar * const panel_order[] = {
"mouse",
"printers",
"removable-media",
+ "thunderbolt",
"wacom",
"color",
diff --git a/shell/cc-panel-loader.c b/shell/cc-panel-loader.c
index df3a8020c..55492ef98 100644
--- a/shell/cc-panel-loader.c
+++ b/shell/cc-panel-loader.c
@@ -54,6 +54,9 @@ extern GType cc_region_panel_get_type (void);
extern GType cc_search_panel_get_type (void);
extern GType cc_sharing_panel_get_type (void);
extern GType cc_sound_panel_get_type (void);
+#ifdef BUILD_THUNDERBOLT
+extern GType cc_bolt_panel_get_type (void);
+#endif /* BUILD_THUNDERBOLT */
extern GType cc_ua_panel_get_type (void);
extern GType cc_user_panel_get_type (void);
#ifdef BUILD_WACOM
@@ -99,6 +102,9 @@ static struct {
PANEL_TYPE("search", cc_search_panel_get_type ),
PANEL_TYPE("sharing", cc_sharing_panel_get_type ),
PANEL_TYPE("sound", cc_sound_panel_get_type ),
+#ifdef BUILD_THUNDERBOLT
+ PANEL_TYPE("thunderbolt", cc_bolt_panel_get_type ),
+#endif
PANEL_TYPE("universal-access", cc_ua_panel_get_type ),
PANEL_TYPE("user-accounts", cc_user_panel_get_type ),
#ifdef BUILD_WACOM
diff --git a/shell/cc-shell-log.c b/shell/cc-shell-log.c
deleted file mode 100644
index 14a122722..000000000
--- a/shell/cc-shell-log.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2009 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-
-#include "config.h"
-
-#include <glib.h>
-#include <glib/gstdio.h>
-
-#include "cc-shell-log.h"
-
-static int log_levels = G_LOG_LEVEL_CRITICAL |
- G_LOG_LEVEL_ERROR |
- G_LOG_LEVEL_WARNING |
- G_LOG_LEVEL_MESSAGE |
- G_LOG_LEVEL_INFO |
- G_LOG_LEVEL_DEBUG;
-
-static void
-cc_shell_log_default_handler (const gchar *log_domain,
- GLogLevelFlags log_level,
- const gchar *message,
- gpointer unused_data)
-{
- if ((log_level & log_levels) == 0)
- return;
-
- g_log_default_handler (log_domain, log_level, message, unused_data);
-}
-
-void
-cc_shell_log_init (void)
-{
- g_log_set_default_handler (cc_shell_log_default_handler, NULL);
-}
-
-void
-cc_shell_log_set_debug (gboolean debug)
-{
-
- if (debug) {
- g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
- log_levels |= (G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO);
- g_debug ("Enabling debugging");
- }
-}
diff --git a/shell/cc-shell-log.h b/shell/cc-shell-log.h
deleted file mode 100644
index 132a19dcf..000000000
--- a/shell/cc-shell-log.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2009 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef __CC_SHELL_LOG_H
-#define __CC_SHELL_LOG_H
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-void cc_shell_log_init (void);
-void cc_shell_log_set_debug (gboolean debug);
-
-G_END_DECLS
-
-#endif /* __CC_SHELL_LOG_H */
diff --git a/shell/cc-shell-model.c b/shell/cc-shell-model.c
index 55f3e3c82..4dcddba45 100644
--- a/shell/cc-shell-model.c
+++ b/shell/cc-shell-model.c
@@ -19,23 +19,25 @@
* Author: Thomas Wood <thos@gnome.org>
*/
+#include "cc-shell-model.h"
+#include "cc-util.h"
+
#include <string.h>
#include <gio/gdesktopappinfo.h>
-#include "cc-shell-model.h"
-#include "cc-util.h"
-
#define GNOME_SETTINGS_PANEL_ID_KEY "X-GNOME-Settings-Panel"
#define GNOME_SETTINGS_PANEL_CATEGORY GNOME_SETTINGS_PANEL_ID_KEY
#define GNOME_SETTINGS_PANEL_ID_KEYWORDS "Keywords"
-struct _CcShellModelPrivate
+struct _CcShellModel
{
- gchar **sort_terms;
+ GtkListStore parent;
+
+ GStrv sort_terms;
};
-G_DEFINE_TYPE_WITH_PRIVATE (CcShellModel, cc_shell_model, GTK_TYPE_LIST_STORE)
+G_DEFINE_TYPE (CcShellModel, cc_shell_model, GTK_TYPE_LIST_STORE)
static gint
sort_by_name (GtkTreeModel *model,
@@ -224,20 +226,19 @@ cc_shell_model_sort_func (GtkTreeModel *model,
gpointer data)
{
CcShellModel *self = data;
- CcShellModelPrivate *priv = self->priv;
- if (!priv->sort_terms || !priv->sort_terms[0])
+ if (!self->sort_terms || !self->sort_terms[0])
return sort_by_name (model, a, b);
else
- return sort_with_terms (model, a, b, priv->sort_terms);
+ return sort_with_terms (model, a, b, self->sort_terms);
}
static void
cc_shell_model_finalize (GObject *object)
{
- CcShellModelPrivate *priv = CC_SHELL_MODEL (object)->priv;;
+ CcShellModel *self = CC_SHELL_MODEL (object);
- g_strfreev (priv->sort_terms);
+ g_clear_pointer (&self->sort_terms, g_strfreev);
G_OBJECT_CLASS (cc_shell_model_parent_class)->finalize (object);
}
@@ -245,9 +246,8 @@ cc_shell_model_finalize (GObject *object)
static void
cc_shell_model_class_init (CcShellModelClass *klass)
{
- GObjectClass *gobject_class;
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = cc_shell_model_finalize;
}
@@ -257,8 +257,6 @@ cc_shell_model_init (CcShellModel *self)
GType types[] = {G_TYPE_STRING, G_TYPE_STRING, G_TYPE_APP_INFO, G_TYPE_STRING,
G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_ICON, G_TYPE_STRV};
- self->priv = cc_shell_model_get_instance_private (self);
-
gtk_list_store_set_column_types (GTK_LIST_STORE (self),
N_COLS, types);
@@ -328,6 +326,30 @@ cc_shell_model_add_item (CcShellModel *model,
}
gboolean
+cc_shell_model_has_panel (CcShellModel *model,
+ const char *id)
+{
+ GtkTreeIter iter;
+ gboolean valid;
+
+ g_assert (id);
+
+ valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter);
+ while (valid)
+ {
+ g_autofree gchar *panel_id = NULL;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, COL_ID, &panel_id, -1);
+ if (g_str_equal (id, panel_id))
+ return TRUE;
+
+ valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter);
+ }
+
+ return FALSE;
+}
+
+gboolean
cc_shell_model_iter_matches_search (CcShellModel *model,
GtkTreeIter *iter,
const char *term)
@@ -366,13 +388,14 @@ void
cc_shell_model_set_sort_terms (CcShellModel *self,
gchar **terms)
{
- CcShellModelPrivate *priv = self->priv;
+ g_return_if_fail (CC_IS_SHELL_MODEL (self));
- g_strfreev (priv->sort_terms);
- priv->sort_terms = g_strdupv (terms);
+ g_clear_pointer (&self->sort_terms, g_strfreev);
+ self->sort_terms = g_strdupv (terms);
/* trigger a re-sort */
gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (self),
cc_shell_model_sort_func,
- self, NULL);
+ self,
+ NULL);
}
diff --git a/shell/cc-shell-model.h b/shell/cc-shell-model.h
index 259407109..b0fe50ff6 100644
--- a/shell/cc-shell-model.h
+++ b/shell/cc-shell-model.h
@@ -18,9 +18,7 @@
* Author: Thomas Wood <thos@gnome.org>
*/
-
-#ifndef _CC_SHELL_MODEL_H
-#define _CC_SHELL_MODEL_H
+#pragma once
#include <gtk/gtk.h>
@@ -28,31 +26,10 @@ G_BEGIN_DECLS
#define CC_TYPE_SHELL_MODEL cc_shell_model_get_type()
-#define CC_SHELL_MODEL(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
- CC_TYPE_SHELL_MODEL, CcShellModel))
-
-#define CC_SHELL_MODEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), \
- CC_TYPE_SHELL_MODEL, CcShellModelClass))
-
-#define CC_IS_SHELL_MODEL(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
- CC_TYPE_SHELL_MODEL))
-
-#define CC_IS_SHELL_MODEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), \
- CC_TYPE_SHELL_MODEL))
+G_DECLARE_FINAL_TYPE (CcShellModel, cc_shell_model, CC, SHELL_MODEL, GtkListStore)
-#define CC_SHELL_MODEL_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), \
- CC_TYPE_SHELL_MODEL, CcShellModelClass))
-
-typedef struct _CcShellModel CcShellModel;
-typedef struct _CcShellModelClass CcShellModelClass;
-typedef struct _CcShellModelPrivate CcShellModelPrivate;
-
-typedef enum {
+typedef enum
+{
CC_CATEGORY_CONNECTIVITY,
CC_CATEGORY_PERSONALIZATION,
CC_CATEGORY_ACCOUNT,
@@ -77,34 +54,22 @@ enum
N_COLS
};
-struct _CcShellModel
-{
- GtkListStore parent;
- CcShellModelPrivate *priv;
-};
+CcShellModel* cc_shell_model_new (void);
-struct _CcShellModelClass
-{
- GtkListStoreClass parent_class;
-};
+void cc_shell_model_add_item (CcShellModel *model,
+ CcPanelCategory category,
+ GAppInfo *appinfo,
+ const char *id);
-GType cc_shell_model_get_type (void) G_GNUC_CONST;
+gboolean cc_shell_model_has_panel (CcShellModel *model,
+ const char *id);
-CcShellModel *cc_shell_model_new (void);
+gboolean cc_shell_model_iter_matches_search (CcShellModel *model,
+ GtkTreeIter *iter,
+ const char *term);
-void cc_shell_model_add_item (CcShellModel *model,
- CcPanelCategory category,
- GAppInfo *appinfo,
- const char *id);
-
-gboolean cc_shell_model_iter_matches_search (CcShellModel *model,
- GtkTreeIter *iter,
- const char *term);
-
-void cc_shell_model_set_sort_terms (CcShellModel *model,
- gchar **terms);
+void cc_shell_model_set_sort_terms (CcShellModel *model,
+ GStrv terms);
G_END_DECLS
-
-#endif /* _CC_SHELL_MODEL_H */
diff --git a/shell/cc-window.c b/shell/cc-window.c
index f7593dc55..50d3995d7 100644
--- a/shell/cc-window.c
+++ b/shell/cc-window.c
@@ -20,6 +20,8 @@
* Author: Thomas Wood <thos@gnome.org>
*/
+#define G_LOG_DOMAIN "cc-window"
+
#include <config.h>
#include "cc-window.h"
@@ -31,6 +33,7 @@
#include <gdk/gdkkeysyms.h>
#include <gdk/gdkx.h>
#include <string.h>
+#include <time.h>
#include "cc-panel.h"
#include "cc-shell.h"
@@ -62,6 +65,7 @@ struct _CcWindow
GtkWidget *search_entry;
GtkWidget *lock_button;
GtkWidget *current_panel_box;
+ GtkWidget *development_warning_dialog;
GtkWidget *current_panel;
char *current_panel_id;
GQueue *previous_panels;
@@ -88,8 +92,49 @@ enum
};
/* Auxiliary methods */
-static const gchar *
-get_icon_name_from_g_icon (GIcon *gicon)
+static gboolean
+in_flatpak_sandbox (void)
+{
+ return g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS);
+}
+
+static void
+add_development_build_css (CcWindow *self)
+{
+ g_autoptr(GtkCssProvider) provider = NULL;
+ g_autoptr(GError) error = NULL;
+
+ /* This CSS snipped is added on development builds of GNOME Settings. It is
+ * not meant to be beautiful (althout it is) and is only supposed to integrate
+ * with Adwaita light (although it integrates well with dark too).
+ */
+
+ const gchar *development_build_css =
+ "window.development-version headerbar {\n"
+ " background: @theme_bg_color linear-gradient(to top,\n"
+ " alpha(@theme_selected_bg_color, 0.34),\n"
+ " alpha(@theme_selected_bg_color, 0.27) 2px,\n"
+ " alpha(@theme_selected_bg_color, 0.20) 3px);\n"
+ "}";
+
+ gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (self)), "development-version");
+
+ provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_data (provider, development_build_css, -1, &error);
+
+ if (error)
+ {
+ g_error ("Failed to load CSS: %s", error->message);
+ return;
+ }
+
+ gtk_style_context_add_provider_for_screen (gtk_widget_get_screen (GTK_WIDGET (self)),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+}
+
+static gchar *
+get_symbolic_icon_name_from_g_icon (GIcon *gicon)
{
const gchar * const *names;
GtkIconTheme *icon_theme;
@@ -103,8 +148,11 @@ get_icon_name_from_g_icon (GIcon *gicon)
for (i = 0; names[i] != NULL; i++)
{
- if (gtk_icon_theme_has_icon (icon_theme, names[i]))
- return names[i];
+ g_autofree gchar *name = NULL;
+ name = g_strdup_printf ("%s-symbolic", names[i]);
+
+ if (gtk_icon_theme_has_icon (icon_theme, name))
+ return g_steal_pointer (&name);
}
return NULL;
@@ -117,14 +165,20 @@ activate_panel (CcWindow *self,
const gchar *name,
GIcon *gicon)
{
+ g_autoptr (GTimer) timer = NULL;
GtkWidget *box, *title_widget;
- const gchar *icon_name;
+ gdouble ellapsed_time;
if (!id)
return FALSE;
+ timer = g_timer_new ();
+
g_settings_set_string (self->settings, "last-panel", id);
+ /* Begin the profile */
+ g_timer_start (timer);
+
self->current_panel = GTK_WIDGET (cc_panel_loader_load_by_name (CC_SHELL (self), id, parameters));
cc_shell_set_active_panel (CC_SHELL (self), CC_PANEL (self->current_panel));
gtk_widget_show (self->current_panel);
@@ -144,18 +198,21 @@ activate_panel (CcWindow *self,
gtk_stack_set_visible_child_name (GTK_STACK (self->stack), id);
/* set the title of the window */
- icon_name = get_icon_name_from_g_icon (gicon);
-
gtk_window_set_role (GTK_WINDOW (self), id);
gtk_header_bar_set_title (GTK_HEADER_BAR (self->panel_headerbar), name);
- gtk_window_set_default_icon_name (icon_name);
- gtk_window_set_icon_name (GTK_WINDOW (self), icon_name);
title_widget = cc_panel_get_title_widget (CC_PANEL (self->current_panel));
gtk_header_bar_set_custom_title (GTK_HEADER_BAR (self->panel_headerbar), title_widget);
self->current_panel_box = box;
+ /* Finish profiling */
+ g_timer_stop (timer);
+
+ ellapsed_time = g_timer_elapsed (timer, NULL);
+
+ g_debug ("Time to open panel '%s': %lfs", name, ellapsed_time);
+
return TRUE;
}
@@ -253,9 +310,8 @@ setup_model (CcWindow *shell)
g_autofree gchar *name = NULL;
g_autofree gchar *description = NULL;
g_autofree gchar *id = NULL;
- g_autofree gchar *symbolic_icon = NULL;
+ g_autofree gchar *icon_name = NULL;
g_autofree GStrv keywords = NULL;
- const gchar *icon_name;
gtk_tree_model_get (model, &iter,
COL_CATEGORY, &category,
@@ -266,8 +322,7 @@ setup_model (CcWindow *shell)
COL_KEYWORDS, &keywords,
-1);
- icon_name = get_icon_name_from_g_icon (icon);
- symbolic_icon = g_strdup_printf ("%s-symbolic", icon_name);
+ icon_name = get_symbolic_icon_name_from_g_icon (icon);
cc_panel_list_add_panel (CC_PANEL_LIST (shell->panel_list),
category,
@@ -275,7 +330,7 @@ setup_model (CcWindow *shell)
name,
description,
keywords,
- symbolic_icon);
+ icon_name);
valid = gtk_tree_model_iter_next (model, &iter);
}
@@ -288,12 +343,15 @@ set_active_panel_from_id (CcShell *shell,
GVariant *parameters,
GError **error)
{
+ g_autoptr(GIcon) gicon = NULL;
+ g_autofree gchar *name = NULL;
GtkTreeIter iter;
- gboolean iter_valid;
- gchar *name = NULL;
- GIcon *gicon = NULL;
- CcWindow *self = CC_WINDOW (shell);
GtkWidget *old_panel;
+ CcWindow *self;
+ gboolean iter_valid;
+ gboolean activated;
+
+ self = CC_WINDOW (shell);
/* When loading the same panel again, just set its parameters */
if (g_strcmp0 (self->current_panel_id, start_id) == 0)
@@ -332,26 +390,25 @@ set_active_panel_from_id (CcShell *shell,
if (!name)
{
g_warning ("Could not find settings panel \"%s\"", start_id);
+ return TRUE;
}
- else if (!activate_panel (CC_WINDOW (shell), start_id, parameters, name, gicon))
- {
- /* Failed to activate the panel for some reason,
- * let's keep the old panel around instead */
- }
- else
- {
- /* Successful activation */
- g_free (self->current_panel_id);
- self->current_panel_id = g_strdup (start_id);
- if (old_panel)
- gtk_container_remove (GTK_CONTAINER (self->stack), old_panel);
+ /* Activate the panel */
+ activated = activate_panel (CC_WINDOW (shell), start_id, parameters, name, gicon);
- cc_panel_list_set_active_panel (CC_PANEL_LIST (self->panel_list), start_id);
- }
+ /* Failed to activate the panel for some reason, let's keep the old
+ * panel around instead */
+ if (!activated)
+ return TRUE;
- g_clear_pointer (&name, g_free);
- g_clear_object (&gicon);
+ /* Successful activation */
+ g_free (self->current_panel_id);
+ self->current_panel_id = g_strdup (start_id);
+
+ if (old_panel)
+ gtk_container_remove (GTK_CONTAINER (self->stack), old_panel);
+
+ cc_panel_list_set_active_panel (CC_PANEL_LIST (self->panel_list), start_id);
return TRUE;
}
@@ -370,13 +427,10 @@ set_active_panel (CcWindow *shell,
/* set the new panel */
if (panel)
- {
- shell->active_panel = g_object_ref (panel);
- }
+ shell->active_panel = g_object_ref (panel);
else
- {
- shell_show_overview_page (shell);
- }
+ shell_show_overview_page (shell);
+
g_object_notify (G_OBJECT (shell), "active-panel");
}
}
@@ -568,6 +622,17 @@ split_decorations_cb (GtkSettings *settings,
gtk_header_bar_set_decoration_layout (GTK_HEADER_BAR (self->panel_headerbar), layout_end);
}
+static void
+on_development_warning_dialog_responded_cb (GtkWidget *dialog,
+ gint response,
+ CcWindow *self)
+{
+ g_debug ("Disabling development build warning dialog");
+ g_settings_set_boolean (self->settings, "show-development-warning", FALSE);
+
+ gtk_widget_hide (dialog);
+}
+
/* CcShell implementation */
static gboolean
cc_window_set_active_panel_from_id (CcShell *shell,
@@ -606,6 +671,19 @@ cc_shell_iface_init (CcShellInterface *iface)
iface->get_toplevel = cc_window_get_toplevel;
}
+/* GtkWidget overrides */
+static void
+cc_window_map (GtkWidget *widget)
+{
+ CcWindow *self = (CcWindow *) widget;
+
+ GTK_WIDGET_CLASS (cc_window_parent_class)->map (widget);
+
+ /* Show a warning for Flatpak builds */
+ if (in_flatpak_sandbox () && g_settings_get_boolean (self->settings, "show-development-warning"))
+ gtk_window_present (GTK_WINDOW (self->development_warning_dialog));
+}
+
/* GObject Implementation */
static void
cc_window_get_property (GObject *object,
@@ -683,10 +761,13 @@ cc_window_class_init (CcWindowClass *klass)
object_class->dispose = cc_window_dispose;
object_class->finalize = cc_window_finalize;
+ widget_class->map = cc_window_map;
+
g_object_class_override_property (object_class, PROP_ACTIVE_PANEL, "active-panel");
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/ControlCenter/gtk/window.ui");
+ gtk_widget_class_bind_template_child (widget_class, CcWindow, development_warning_dialog);
gtk_widget_class_bind_template_child (widget_class, CcWindow, header);
gtk_widget_class_bind_template_child (widget_class, CcWindow, header_box);
gtk_widget_class_bind_template_child (widget_class, CcWindow, header_sizegroup);
@@ -702,6 +783,7 @@ cc_window_class_init (CcWindowClass *klass)
gtk_widget_class_bind_template_child (widget_class, CcWindow, top_right_box);
gtk_widget_class_bind_template_callback (widget_class, gdk_window_set_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_development_warning_dialog_responded_cb);
gtk_widget_class_bind_template_callback (widget_class, panel_list_view_changed_cb);
gtk_widget_class_bind_template_callback (widget_class, previous_button_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, search_entry_activate_cb);
@@ -744,10 +826,14 @@ cc_window_init (CcWindow *self)
/* After everything is loaded, select the last used panel, if any,
* or the first visible panel */
id = g_settings_get_string (self->settings, "last-panel");
- if (id != NULL && *id != '\0')
+ if (id != NULL && cc_shell_model_has_panel (CC_SHELL_MODEL (self->store), id))
cc_panel_list_set_active_panel (CC_PANEL_LIST (self->panel_list), id);
else
cc_panel_list_activate (CC_PANEL_LIST (self->panel_list));
+
+ /* Add a custom CSS class on development builds */
+ if (in_flatpak_sandbox ())
+ add_development_build_css (self);
}
CcWindow *
@@ -779,4 +865,4 @@ cc_window_set_search_item (CcWindow *center,
gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (center->search_bar), TRUE);
gtk_entry_set_text (GTK_ENTRY (center->search_entry), search);
gtk_editable_set_position (GTK_EDITABLE (center->search_entry), -1);
-} \ No newline at end of file
+}
diff --git a/shell/hostname-helper.c b/shell/hostname-helper.c
deleted file mode 100644
index df596975e..000000000
--- a/shell/hostname-helper.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2011 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <glib.h>
-#include <glib/gi18n.h>
-#include <string.h>
-
-#include "hostname-helper.h"
-
-static char *
-allowed_chars (void)
-{
- GString *s;
- char i;
-
- s = g_string_new (NULL);
- for (i = 'a'; i <= 'z'; i++)
- g_string_append_c (s, i);
- for (i = 'A'; i <= 'Z'; i++)
- g_string_append_c (s, i);
- for (i = '0'; i <= '9'; i++)
- g_string_append_c (s, i);
- g_string_append_c (s, '-');
-
- return g_string_free (s, FALSE);
-}
-
-static char *
-remove_leading_dashes (char *input)
-{
- char *start;
-
- for (start = input; *start && (*start == '-'); start++)
- ;
-
- g_memmove (input, start, strlen (start) + 1);
-
- return input;
-}
-
-static gboolean
-is_empty (const char *input)
-{
- if (input == NULL ||
- *input == '\0')
- return TRUE;
- return FALSE;
-}
-
-static char *
-remove_trailing_dashes (char *input)
-{
- int len;
-
- len = strlen (input);
- while (len--) {
- if (input[len] == '-')
- input[len] = '\0';
- else
- break;
- }
- return input;
-}
-
-static char *
-remove_apostrophes (char *input)
-{
- char *apo;
-
- while ((apo = strchr (input, '\'')) != NULL)
- g_memmove (apo, apo + 1, strlen (apo));
- return input;
-}
-
-static char *
-remove_duplicate_dashes (char *input)
-{
- char *dashes;
-
- while ((dashes = strstr (input, "--")) != NULL)
- g_memmove (dashes, dashes + 1, strlen (dashes));
- return input;
-}
-
-#define CHECK if (is_empty (result)) goto bail
-
-char *
-pretty_hostname_to_static (const char *pretty,
- gboolean for_display)
-{
- char *result;
- char *valid_chars;
- char *composed;
-
- g_return_val_if_fail (pretty != NULL, NULL);
- g_return_val_if_fail (g_utf8_validate (pretty, -1, NULL), NULL);
-
- g_debug ("Input: '%s'", pretty);
-
- composed = g_utf8_normalize (pretty, -1, G_NORMALIZE_ALL_COMPOSE);
- g_debug ("\tcomposed: '%s'", composed);
- /* Transform the pretty hostname to ASCII */
- result = g_str_to_ascii (composed, NULL);
- g_debug ("\ttranslit: '%s'", result);
- g_free (composed);
-
- CHECK;
-
- /* Remove apostrophes */
- result = remove_apostrophes (result);
- g_debug ("\tapostrophes: '%s'", result);
-
- CHECK;
-
- /* Remove all the not-allowed chars */
- valid_chars = allowed_chars ();
- result = g_strcanon (result, valid_chars, '-');
- g_free (valid_chars);
- g_debug ("\tcanon: '%s'", result);
-
- CHECK;
-
- /* Remove the leading dashes */
- result = remove_leading_dashes (result);
- g_debug ("\tleading: '%s'", result);
-
- CHECK;
-
- /* Remove trailing dashes */
- result = remove_trailing_dashes (result);
- g_debug ("\ttrailing: '%s'", result);
-
- CHECK;
-
- /* Remove duplicate dashes */
- result = remove_duplicate_dashes (result);
- g_debug ("\tduplicate: '%s'", result);
-
- CHECK;
-
- /* Lower case */
- if (!for_display) {
- char *tmp;
-
- tmp = g_ascii_strdown (result, -1);
- g_free (result);
- result = tmp;
- }
-
- return result;
-
-bail:
- g_free (result);
- return g_strdup ("localhost");
-}
-#undef CHECK
-
-/* Max length of an SSID in bytes */
-#define SSID_MAX_LEN 32
-char *
-pretty_hostname_to_ssid (const char *pretty)
-{
- const char *p, *prev;
- char *ret = NULL;
-
- if (pretty == NULL || *pretty == '\0') {
- pretty = g_get_host_name ();
- if (g_strcmp0 (pretty, "localhost") == 0)
- pretty = NULL;
- }
-
- if (pretty == NULL) {
- /* translators: This is the default hotspot name, need to be less than 32-bytes */
- ret = g_strdup (C_("hotspot", "Hotspot"));
- g_assert (strlen (ret) <= SSID_MAX_LEN);
- return ret;
- }
-
- g_return_val_if_fail (g_utf8_validate (pretty, -1, NULL), NULL);
-
- p = pretty;
- prev = NULL;
- while ((p = g_utf8_find_next_char (p, NULL)) != NULL) {
- if (p == prev)
- break;
-
- if (p - pretty > SSID_MAX_LEN) {
- ret = g_strndup (pretty, prev - pretty);
- break;
- }
- if (p - pretty == SSID_MAX_LEN) {
- ret = g_strndup (pretty, p - pretty);
- break;
- }
-
- if (*p == '\0')
- break;
-
- prev = p;
- }
-
- if (ret == NULL)
- ret = g_strdup (pretty);
-
- return ret;
-}
diff --git a/shell/hostnames-test.txt b/shell/hostnames-test.txt
deleted file mode 100644
index 5a31ce28b..000000000
--- a/shell/hostnames-test.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-# Pretty hostname, tab, display hostname, tab, real hostname
-Lennart's PC Lennarts-PC lennarts-pc
-Müllers Computer Mullers-Computer mullers-computer
-Voran! Voran voran
-Es war einmal ein Männlein Es-war-einmal-ein-Mannlein es-war-einmal-ein-mannlein
-Jawoll. Ist doch wahr! Jawoll-Ist-doch-wahr jawoll-ist-doch-wahr
-レナート localhost localhost
-!!! localhost localhost
-...zack!!! zack!... zack-zack zack-zack
-Bãstien's computer... Foo-bar Bastiens-computer-Foo-bar bastiens-computer-foo-bar
- localhost localhost
diff --git a/shell/list-box-helper.c b/shell/list-box-helper.c
deleted file mode 100644
index 415cdde94..000000000
--- a/shell/list-box-helper.c
+++ /dev/null
@@ -1,153 +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 <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "list-box-helper.h"
-
-#define MAX_ROWS_VISIBLE 5
-
-struct _CcListBoxRow
-{
- GtkListBoxRow parent_instance;
-};
-G_DEFINE_TYPE (CcListBoxRow, cc_list_box_row, GTK_TYPE_LIST_BOX_ROW)
-enum
-{
- BOX_ROW_ACTIVATED,
- LAST_BOX_ROW_SIGNAL
-};
-static guint cc_list_box_row_signals[LAST_BOX_ROW_SIGNAL] = { 0 };
-static void
-cc_list_box_row_class_init (CcListBoxRowClass *klass)
-{
- cc_list_box_row_signals[BOX_ROW_ACTIVATED] =
- g_signal_new ("activated",
- CC_TYPE_LIST_BOX_ROW,
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE, 0);
-}
-static void cc_list_box_row_init (CcListBoxRow *self) {}
-
-struct _CcListBox
-{
- GtkListBox parent_instance;
-};
-G_DEFINE_TYPE (CcListBox, cc_list_box, GTK_TYPE_LIST_BOX)
-static void
-cc_list_box_row_activated (GtkListBox *box, GtkListBoxRow *row)
-{
- if (CC_IS_LIST_BOX_ROW (row))
- g_signal_emit (row, cc_list_box_row_signals[BOX_ROW_ACTIVATED], 0);
-}
-static void
-cc_list_box_class_init (CcListBoxClass *klass)
-{
- GtkListBoxClass *parent_class = GTK_LIST_BOX_CLASS (klass);
- parent_class->row_activated = cc_list_box_row_activated;
-}
-static void cc_list_box_init (CcListBox *self) {}
-
-
-void
-cc_list_box_update_header_func (GtkListBoxRow *row,
- GtkListBoxRow *before,
- gpointer user_data)
-{
- GtkWidget *current;
-
- if (before == NULL)
- {
- gtk_list_box_row_set_header (row, NULL);
- return;
- }
-
- current = gtk_list_box_row_get_header (row);
- if (current == NULL)
- {
- current = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
- gtk_widget_show (current);
- gtk_list_box_row_set_header (row, current);
- }
-}
-
-void
-cc_list_box_adjust_scrolling (GtkListBox *listbox)
-{
- GtkWidget *scrolled_window;
- GList *children;
- guint n_rows, num_max_rows;
-
- scrolled_window = g_object_get_data (G_OBJECT (listbox), "cc-scrolling-scrolled-window");
- if (!scrolled_window)
- return;
-
- children = gtk_container_get_children (GTK_CONTAINER (listbox));
- n_rows = g_list_length (children);
-
- num_max_rows = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (listbox), "cc-max-rows-visible"));
-
- if (n_rows >= num_max_rows)
- {
- gint total_row_height = 0;
- GList *l;
- guint i;
-
- for (l = children, i = 0; l != NULL && i < num_max_rows; l = l->next, i++) {
- gint row_height;
- gtk_widget_get_preferred_height (GTK_WIDGET (l->data), &row_height, NULL);
- total_row_height += row_height;
- }
-
- gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (scrolled_window), total_row_height);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- }
- else
- {
- gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (scrolled_window), -1);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
- GTK_POLICY_NEVER, GTK_POLICY_NEVER);
- }
-
- g_list_free (children);
-}
-
-void
-cc_list_box_setup_scrolling (GtkListBox *listbox,
- guint num_max_rows)
-{
- GtkWidget *parent;
- GtkWidget *scrolled_window;
-
- parent = gtk_widget_get_parent (GTK_WIDGET (listbox));
- scrolled_window = gtk_scrolled_window_new (NULL, NULL);
- gtk_widget_show (scrolled_window);
-
- g_object_ref (listbox);
- gtk_container_remove (GTK_CONTAINER (parent), GTK_WIDGET (listbox));
- gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (listbox));
- g_object_unref (listbox);
-
- gtk_container_add (GTK_CONTAINER (parent), scrolled_window);
-
- if (num_max_rows == 0)
- num_max_rows = MAX_ROWS_VISIBLE;
-
- g_object_set_data (G_OBJECT (listbox), "cc-scrolling-scrolled-window", scrolled_window);
- g_object_set_data (G_OBJECT (listbox), "cc-max-rows-visible", GUINT_TO_POINTER (num_max_rows));
-}
diff --git a/shell/list-box-helper.h b/shell/list-box-helper.h
deleted file mode 100644
index c2a0acc97..000000000
--- a/shell/list-box-helper.h
+++ /dev/null
@@ -1,37 +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 <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <gtk/gtk.h>
-
-#define CC_TYPE_LIST_BOX_ROW (cc_list_box_row_get_type ())
-G_DECLARE_FINAL_TYPE (CcListBoxRow, cc_list_box_row, CC, LIST_BOX_ROW, GtkListBoxRow)
-
-#define CC_TYPE_LIST_BOX (cc_list_box_get_type ())
-G_DECLARE_FINAL_TYPE (CcListBox, cc_list_box, CC, LIST_BOX, GtkListBox)
-
-void
-cc_list_box_update_header_func (GtkListBoxRow *row,
- GtkListBoxRow *before,
- gpointer user_data);
-
-void
-cc_list_box_adjust_scrolling (GtkListBox *listbox);
-
-void
-cc_list_box_setup_scrolling (GtkListBox *listbox,
- guint num_rows);
diff --git a/shell/meson.build b/shell/meson.build
index d9364521b..73b18f84e 100644
--- a/shell/meson.build
+++ b/shell/meson.build
@@ -7,53 +7,50 @@ service_conf.set('bindir', control_center_bindir)
service = 'org.gnome.ControlCenter.service'
configure_file(
- input: service + '.in',
- output: service,
- install: true,
- install_dir: join_paths(control_center_datadir, 'dbus-1', 'services'),
- configuration: service_conf
+ input : service + '.in',
+ output : service,
+ install : true,
+ install_dir : join_paths(control_center_datadir, 'dbus-1', 'services'),
+ configuration : service_conf
)
desktop = 'gnome-control-center.desktop'
desktop_in = configure_file(
- input: desktop + '.in.in',
- output: desktop + '.in',
- configuration: desktop_conf
+ 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
+ desktop,
+ type : 'desktop',
+ input : desktop_in,
+ output : desktop,
+ po_dir : po_dir,
+ install : true,
+ install_dir : control_center_desktopdir
)
cflags = ['-DGNOMELOCALEDIR="@0@"'.format(control_center_localedir)]
libshell = static_library(
- 'shell',
- sources: 'cc-shell-model.c',
- include_directories: [top_inc, common_inc],
- dependencies: common_deps,
- c_args: cflags
+ 'shell',
+ sources : 'cc-shell-model.c',
+ include_directories : [top_inc, common_inc],
+ dependencies : common_deps,
+ c_args : cflags
)
-common_sources = files(
+sources = files(
'cc-application.c',
- 'cc-editable-entry.c',
- 'cc-hostname-entry.c',
+ 'cc-log.c',
+ 'cc-object-storage.c',
'cc-panel-loader.c',
'cc-panel.c',
'cc-shell-category-view.c',
'cc-shell-item-view.c',
- 'cc-shell-log.c',
'cc-shell.c',
- 'hostname-helper.c',
- 'list-box-helper.c',
'main.c'
)
@@ -63,14 +60,14 @@ resource_data = files(
'window.ui'
)
-common_sources += gnome.compile_resources(
+sources += gnome.compile_resources(
'resources',
meson.project_name() + '.gresource.xml',
dependencies: resource_data,
export: true
)
-sources = common_sources + files(
+sources += files(
'cc-panel-list.c',
'cc-window.c'
)
@@ -78,7 +75,7 @@ sources = common_sources + files(
shell_deps = common_deps + [
libdevice_dep,
liblanguage_dep,
- polkit_gobject_dep,
+ libwidgets_dep,
x11_dep
]
@@ -90,48 +87,61 @@ if host_is_linux_not_s390
shell_deps += wacom_deps
endif
+# Debug
+debug_conf = configuration_data()
+debug_conf.set('BUGREPORT_URL', 'http://bugzilla.gnome.org/enter_bug.cgi?product=' + meson.project_name())
+debug_conf.set10('ENABLE_TRACING', enable_tracing)
+
+sources += configure_file(
+ input : 'cc-debug.h.in',
+ output : 'cc-debug.h',
+ configuration : debug_conf
+)
+
executable(
meson.project_name(),
- sources,
- include_directories: top_inc,
- dependencies: shell_deps,
- c_args: cflags,
- link_with: panels_libs + [libshell],
- install: true
+ sources,
+ include_directories : top_inc,
+ dependencies : shell_deps,
+ c_args : cflags,
+ link_with : panels_libs + [libshell],
+ install : true
)
# Because it is confusing and somewhat problematic to directly add and compile
# cc-panel-loader.o by another directory (i.e. the shell search provider), we
# have to create a library and link it there, just like libshell.la.
libpanel_loader = static_library(
- 'panel_loader',
- sources: 'cc-panel-loader.c',
- include_directories: top_inc,
- dependencies: common_deps,
- c_args: cflags + ['-DCC_PANEL_LOADER_NO_GTYPES']
+ 'panel_loader',
+ sources : 'cc-panel-loader.c',
+ include_directories : top_inc,
+ dependencies : common_deps,
+ c_args : cflags + ['-DCC_PANEL_LOADER_NO_GTYPES']
)
-test_unit = 'test-hostname'
-
+# libshell_test
sources = files(
- 'hostname-helper.c',
- test_unit + '.c'
+ 'cc-panel.c',
+ 'cc-shell.c',
+ 'cc-log.c',
+ 'cc-object-storage.c',
)
-
-cflags += [
- '-DTEST_SRCDIR="@0@"'.format(meson.current_source_dir()),
- '-DTEST_TOPSRCDIR="@0@"'.format(meson.source_root())
-]
-
-exe = executable(
- test_unit,
- sources,
- include_directories: top_inc,
- dependencies: common_deps,
- c_args: cflags
+libtestshell = static_library(
+ 'testshell',
+ sources,
+ include_directories : top_inc,
+ dependencies : common_deps + [ libwidgets_dep ],
+ c_args : cflags,
+ link_with : panels_libs
+)
+libtestshell_dep = declare_dependency(
+ include_directories : top_inc,
+ link_with : libtestshell
)
+libtestshell_deps = common_deps + [ libwidgets_dep, libtestshell_dep ]
-test(test_unit, exe)
-install_data ('org.gnome.ControlCenter.gschema.xml',
- install_dir: control_center_schemadir)
+install_data (
+ 'org.gnome.ControlCenter.gschema.xml',
+ install_dir : control_center_schemadir
+)
diff --git a/shell/org.gnome.ControlCenter.gschema.xml b/shell/org.gnome.ControlCenter.gschema.xml
index a40b9b08c..40350bca4 100644
--- a/shell/org.gnome.ControlCenter.gschema.xml
+++ b/shell/org.gnome.ControlCenter.gschema.xml
@@ -8,5 +8,12 @@
will be ignored and the first panel in the list selected.
</description>
</key>
+ <key name="show-development-warning" type="b">
+ <default>true</default>
+ <summary>Show warning when running a development build of Settings</summary>
+ <description>
+ Whether Settings should show a warning when running a development build.
+ </description>
+ </key>
</schema>
</schemalist>
diff --git a/shell/ssids-test.txt b/shell/ssids-test.txt
deleted file mode 100644
index 0545437cf..000000000
--- a/shell/ssids-test.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-GNOME GNOME
-0123456789abcdefghijklmnopqrstuvwxyz 0123456789abcdefghijklmnopqrstuv
-レナート レナート
diff --git a/shell/test-hostname.c b/shell/test-hostname.c
deleted file mode 100644
index 3df293051..000000000
--- a/shell/test-hostname.c
+++ /dev/null
@@ -1,136 +0,0 @@
-#include "config.h"
-
-#include <glib.h>
-#include <glib/gi18n.h>
-#include <locale.h>
-
-#include "hostname-helper.h"
-
-static void
-test_hostname (void)
-{
- char *contents;
- char *result;
- guint i;
- char **lines;
-
- if (g_file_get_contents (TEST_SRCDIR "/hostnames-test.txt", &contents, NULL, NULL) == FALSE) {
- g_warning ("Failed to load '%s'", TEST_SRCDIR "/hostnames-test.txt");
- g_test_fail ();
- return;
- }
-
- lines = g_strsplit (contents, "\n", -1);
- if (lines == NULL) {
- g_warning ("Test file is empty");
- g_test_fail ();
- return;
- }
-
- for (i = 0; lines[i] != NULL; i++) {
- char *utf8;
- char **items;
-
- if (*lines[i] == '#')
- continue;
- if (*lines[i] == '\0')
- break;
-
- items = g_strsplit (lines[i], "\t", -1);
- utf8 = g_locale_from_utf8 (items[0], -1, NULL, NULL, NULL);
- result = pretty_hostname_to_static (items[0], FALSE);
- if (g_strcmp0 (result, items[2]) != 0) {
- g_error ("Result for '%s' doesn't match '%s' (got: '%s')",
- utf8, items[2], result);
- g_test_fail ();
- } else {
- g_debug ("Result for '%s' matches '%s'",
- utf8, result);
- }
- g_free (result);
- g_free (utf8);
-
- result = pretty_hostname_to_static (items[0], TRUE);
- utf8 = g_locale_from_utf8 (items[0], -1, NULL, NULL, NULL);
- if (g_strcmp0 (result, items[1]) != 0) {
- g_error ("Result for '%s' doesn't match '%s' (got: '%s')",
- utf8, items[1], result);
- g_test_fail ();
- } else {
- g_debug ("Result for '%s' matches '%s'",
- utf8, result);
- }
- g_free (result);
- g_free (utf8);
-
- g_strfreev (items);
- }
-
- g_strfreev (lines);
- g_free (contents);
-}
-
-static void
-test_ssid (void)
-{
- char *contents;
- guint i;
- char **lines;
-
- if (g_file_get_contents (TEST_SRCDIR "/ssids-test.txt", &contents, NULL, NULL) == FALSE) {
- g_warning ("Failed to load '%s'", TEST_SRCDIR "/ssids-test.txt");
- g_test_fail ();
- return;
- }
-
- lines = g_strsplit (contents, "\n", -1);
- if (lines == NULL) {
- g_warning ("Test file is empty");
- g_test_fail ();
- return;
- }
-
- for (i = 0; lines[i] != NULL; i++) {
- char *ssid;
- char **items;
-
- if (*lines[i] == '#')
- continue;
- if (*lines[i] == '\0')
- break;
-
- items = g_strsplit (lines[i], "\t", -1);
- ssid = pretty_hostname_to_ssid (items[0]);
- g_assert_cmpstr (ssid, ==, items[1]);
- g_free (ssid);
- g_strfreev (items);
- }
-
- g_strfreev (lines);
- g_free (contents);
-}
-
-int main (int argc, char **argv)
-{
- char *locale;
-
- /* Running in some locales will
- * break the tests as "ü" will be transliterated to
- * "ue" in de_DE, and 'u"' in the C locale.
- *
- * Work around that by forcing en_US with UTF-8 in
- * our tests
- * https://bugzilla.gnome.org/show_bug.cgi?id=650342 */
- locale = setlocale (LC_ALL, "en_US.UTF-8");
- if (locale == NULL) {
- g_debug("Missing en_US.UTF-8 locale, ignoring test.");
- return 0;
- }
- bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
- g_test_init (&argc, &argv, NULL);
-
- g_test_add_func ("/shell/hostname", test_hostname);
- g_test_add_func ("/shell/ssid", test_ssid);
-
- return g_test_run ();
-}
diff --git a/shell/window.ui b/shell/window.ui
index 92ff197ce..c34ce60bc 100644
--- a/shell/window.ui
+++ b/shell/window.ui
@@ -224,4 +224,17 @@
<widget name="sidebar_box"/>
</widgets>
</object>
+
+ <!-- Warning dialog for development builds -->
+ <object class="GtkMessageDialog" id="development_warning_dialog">
+ <property name="message-type">warning</property>
+ <property name="transient-for">CcWindow</property>
+ <property name="resizable">false</property>
+ <property name="modal">true</property>
+ <property name="buttons">ok</property>
+ <property name="text" translatable="yes">Warning: Development Version</property>
+ <property name="secondary-text" translatable="yes">This version of Settings should only be used for development purposes. You may experience incorrect system behavior, data loss, and other unexpected issues. </property>
+ <signal name="response" handler="on_development_warning_dialog_responded_cb" object="CcWindow" swapped="no" />
+ </object>
+
</interface>