diff options
author | Matej Urbančič <mateju@svn.gnome.org> | 2018-05-15 21:03:11 +0200 |
---|---|---|
committer | Matej Urbančič <mateju@svn.gnome.org> | 2018-05-15 21:03:11 +0200 |
commit | 2acb520fc9b19118107916b4c89a041d1651df4d (patch) | |
tree | de915d27698f0f0ee89862dfce8c103c157df952 /shell | |
parent | 2da5fd3b3dfb4a0f2885349dad2a8e2cc063119c (diff) | |
parent | f4433b3766bab48b85ae0e42e3e704bb7f380663 (diff) | |
download | gnome-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.c | 19 | ||||
-rw-r--r-- | shell/cc-debug.h.in | 229 | ||||
-rw-r--r-- | shell/cc-editable-entry.c | 644 | ||||
-rw-r--r-- | shell/cc-editable-entry.h | 83 | ||||
-rw-r--r-- | shell/cc-hostname-entry.c | 288 | ||||
-rw-r--r-- | shell/cc-hostname-entry.h | 33 | ||||
-rw-r--r-- | shell/cc-log.c | 107 | ||||
-rw-r--r-- | shell/cc-log.h (renamed from shell/hostname-helper.h) | 22 | ||||
-rw-r--r-- | shell/cc-object-storage.c | 438 | ||||
-rw-r--r-- | shell/cc-object-storage.h | 65 | ||||
-rw-r--r-- | shell/cc-panel-list.c | 1 | ||||
-rw-r--r-- | shell/cc-panel-loader.c | 6 | ||||
-rw-r--r-- | shell/cc-shell-log.c | 62 | ||||
-rw-r--r-- | shell/cc-shell-log.h | 32 | ||||
-rw-r--r-- | shell/cc-shell-model.c | 61 | ||||
-rw-r--r-- | shell/cc-shell-model.h | 67 | ||||
-rw-r--r-- | shell/cc-window.c | 170 | ||||
-rw-r--r-- | shell/hostname-helper.c | 221 | ||||
-rw-r--r-- | shell/hostnames-test.txt | 11 | ||||
-rw-r--r-- | shell/list-box-helper.c | 153 | ||||
-rw-r--r-- | shell/list-box-helper.h | 37 | ||||
-rw-r--r-- | shell/meson.build | 128 | ||||
-rw-r--r-- | shell/org.gnome.ControlCenter.gschema.xml | 7 | ||||
-rw-r--r-- | shell/ssids-test.txt | 3 | ||||
-rw-r--r-- | shell/test-hostname.c | 136 | ||||
-rw-r--r-- | shell/window.ui | 13 |
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> |