1 /*
2  *  Copyright (c) 2013 Andrzej Radecki <andrzejr@xfce.org>
3  *  Copyright (c) 2017 Viktor Odintsev <ninetls@xfce.org>
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Library General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19 
20 
21 
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #ifdef HAVE_STRING_H
26 #include <string.h>
27 #endif
28 
29 #include <libxfce4ui/libxfce4ui.h>
30 #include <libxfce4util/libxfce4util.h>
31 #include <libxfce4panel/xfce-panel-plugin.h>
32 #include <xfconf/xfconf.h>
33 #ifdef XFCONF_LEGACY
34 #include <dbus/dbus-glib.h>
35 #endif
36 
37 #include "sn-plugin.h"
38 #include "sn-config.h"
39 
40 
41 
42 #define DEFAULT_ICON_SIZE          22
43 #define DEFAULT_SINGLE_ROW         FALSE
44 #define DEFAULT_SQUARE_ICONS       FALSE
45 #define DEFAULT_SYMBOLIC_ICONS     FALSE
46 #define DEFAULT_MENU_IS_PRIMARY    FALSE
47 #define DEFAULT_ORIENTATION        GTK_ORIENTATION_HORIZONTAL
48 #define DEFAULT_PANEL_ORIENTATION  GTK_ORIENTATION_HORIZONTAL
49 #define DEFAULT_PANEL_SIZE         28
50 #define DEFAULT_HIDE_NEW_ITEMS     FALSE
51 
52 
53 
54 static void                  sn_config_finalize                      (GObject                 *object);
55 
56 static void                  sn_config_get_property                  (GObject                 *object,
57                                                                       guint                    prop_id,
58                                                                       GValue                  *value,
59                                                                       GParamSpec              *pspec);
60 
61 static void                  sn_config_set_property                  (GObject                 *object,
62                                                                       guint                    prop_id,
63                                                                       const GValue            *value,
64                                                                       GParamSpec              *pspec);
65 
66 
67 
68 struct _SnConfigClass
69 {
70   GObjectClass         __parent__;
71 };
72 
73 struct _SnConfig
74 {
75   GObject             __parent__;
76 
77   gint                icon_size;
78   gboolean            single_row;
79   gboolean            square_icons;
80   gboolean            symbolic_icons;
81   gboolean            menu_is_primary;
82   gboolean            hide_new_items;
83   GList              *known_items;
84   GHashTable         *hidden_items;
85   GList              *known_legacy_items;
86   GHashTable         *hidden_legacy_items;
87 
88   /* not xfconf properties but it is still convenient to have them here */
89   GtkOrientation      orientation;
90   GtkOrientation      panel_orientation;
91   gint                nrows;
92   gint                panel_size;
93   gint                panel_icon_size;
94 };
95 
96 G_DEFINE_TYPE (SnConfig, sn_config, G_TYPE_OBJECT)
97 
98 
99 
100 enum
101 {
102   PROP_0,
103   PROP_ICON_SIZE,
104   PROP_SINGLE_ROW,
105   PROP_SQUARE_ICONS,
106   PROP_SYMBOLIC_ICONS,
107   PROP_MENU_IS_PRIMARY,
108   PROP_HIDE_NEW_ITEMS,
109   PROP_KNOWN_ITEMS,
110   PROP_HIDDEN_ITEMS,
111   PROP_KNOWN_LEGACY_ITEMS,
112   PROP_HIDDEN_LEGACY_ITEMS
113 };
114 
115 enum
116 {
117   CONFIGURATION_CHANGED,
118   ITEM_LIST_CHANGED,
119   COLLECT_KNOWN_ITEMS,
120   LEGACY_ITEM_LIST_CHANGED,
121   ICONS_CHANGED,
122   LAST_SIGNAL
123 };
124 
125 static guint sn_config_signals[LAST_SIGNAL] = { 0, };
126 
127 
128 #ifdef XFCONF_LEGACY
129 
130 #define XFCE_TYPE_SN_CONFIG_VALUE_ARRAY (sn_config_value_array_get_type ())
131 
132 static GType
sn_config_value_array_get_type(void)133 sn_config_value_array_get_type (void)
134 {
135   static volatile gsize type__volatile = 0;
136   GType                 type;
137 
138   if (g_once_init_enter (&type__volatile))
139     {
140       type = dbus_g_type_get_collection ("GPtrArray", G_TYPE_VALUE);
141       g_once_init_leave (&type__volatile, type);
142     }
143 
144   return type__volatile;
145 }
146 
147 #else
148 
149 #define XFCE_TYPE_SN_CONFIG_VALUE_ARRAY G_TYPE_PTR_ARRAY
150 
151 #endif
152 
153 
154 
155 static void
sn_config_class_init(SnConfigClass * klass)156 sn_config_class_init (SnConfigClass *klass)
157 {
158   GObjectClass *object_class;
159 
160   object_class = G_OBJECT_CLASS (klass);
161   object_class->finalize = sn_config_finalize;
162   object_class->get_property = sn_config_get_property;
163   object_class->set_property = sn_config_set_property;
164 
165   g_object_class_install_property (object_class,
166                                    PROP_ICON_SIZE,
167                                    g_param_spec_int ("icon-size", NULL, NULL,
168                                                      0, 64, DEFAULT_ICON_SIZE,
169                                                      G_PARAM_READWRITE |
170                                                      G_PARAM_STATIC_STRINGS));
171 
172   g_object_class_install_property (object_class,
173                                    PROP_SINGLE_ROW,
174                                    g_param_spec_boolean ("single-row", NULL, NULL,
175                                                          DEFAULT_SINGLE_ROW,
176                                                          G_PARAM_READWRITE |
177                                                          G_PARAM_STATIC_STRINGS));
178 
179   g_object_class_install_property (object_class,
180                                    PROP_SQUARE_ICONS,
181                                    g_param_spec_boolean ("square-icons", NULL, NULL,
182                                                          DEFAULT_SQUARE_ICONS,
183                                                          G_PARAM_READWRITE |
184                                                          G_PARAM_STATIC_STRINGS));
185 
186   g_object_class_install_property (object_class,
187                                    PROP_SYMBOLIC_ICONS,
188                                    g_param_spec_boolean ("symbolic-icons", NULL, NULL,
189                                                          DEFAULT_SYMBOLIC_ICONS,
190                                                          G_PARAM_READWRITE |
191                                                          G_PARAM_STATIC_STRINGS));
192 
193   g_object_class_install_property (object_class,
194                                    PROP_MENU_IS_PRIMARY,
195                                    g_param_spec_boolean ("menu-is-primary", NULL, NULL,
196                                                          DEFAULT_MENU_IS_PRIMARY,
197                                                          G_PARAM_READWRITE |
198                                                          G_PARAM_STATIC_STRINGS));
199 
200   g_object_class_install_property (object_class,
201                                    PROP_HIDE_NEW_ITEMS,
202                                    g_param_spec_boolean ("hide-new-items", NULL, NULL,
203                                                          DEFAULT_HIDE_NEW_ITEMS,
204                                                          G_PARAM_READWRITE |
205                                                          G_PARAM_STATIC_STRINGS));
206 
207   g_object_class_install_property (object_class,
208                                    PROP_KNOWN_ITEMS,
209                                    g_param_spec_boxed ("known-items",
210                                                        NULL, NULL,
211                                                        XFCE_TYPE_SN_CONFIG_VALUE_ARRAY,
212                                                        G_PARAM_READWRITE |
213                                                        G_PARAM_STATIC_STRINGS));
214 
215   g_object_class_install_property (object_class,
216                                    PROP_HIDDEN_ITEMS,
217                                    g_param_spec_boxed ("hidden-items",
218                                                        NULL, NULL,
219                                                        XFCE_TYPE_SN_CONFIG_VALUE_ARRAY,
220                                                        G_PARAM_READWRITE |
221                                                        G_PARAM_STATIC_STRINGS));
222 
223   g_object_class_install_property (object_class,
224                                    PROP_KNOWN_LEGACY_ITEMS,
225                                    g_param_spec_boxed ("known-legacy-items",
226                                                        NULL, NULL,
227                                                        XFCE_TYPE_SN_CONFIG_VALUE_ARRAY,
228                                                        G_PARAM_READWRITE |
229                                                        G_PARAM_STATIC_STRINGS));
230 
231   g_object_class_install_property (object_class,
232                                    PROP_HIDDEN_LEGACY_ITEMS,
233                                    g_param_spec_boxed ("hidden-legacy-items",
234                                                        NULL, NULL,
235                                                        XFCE_TYPE_SN_CONFIG_VALUE_ARRAY,
236                                                        G_PARAM_READWRITE |
237                                                        G_PARAM_STATIC_STRINGS));
238 
239   sn_config_signals[CONFIGURATION_CHANGED] =
240     g_signal_new (g_intern_static_string ("configuration-changed"),
241                   G_TYPE_FROM_CLASS (object_class),
242                   G_SIGNAL_RUN_LAST,
243                   0, NULL, NULL,
244                   g_cclosure_marshal_VOID__VOID,
245                   G_TYPE_NONE, 0);
246 
247   sn_config_signals[ICONS_CHANGED] =
248     g_signal_new (g_intern_static_string ("icons-changed"),
249                   G_TYPE_FROM_CLASS (object_class),
250                   G_SIGNAL_RUN_LAST,
251                   0, NULL, NULL,
252                   g_cclosure_marshal_VOID__VOID,
253                   G_TYPE_NONE, 0);
254 
255   sn_config_signals[ITEM_LIST_CHANGED] =
256     g_signal_new (g_intern_static_string ("items-list-changed"),
257                   G_TYPE_FROM_CLASS (object_class),
258                   G_SIGNAL_RUN_LAST,
259                   0, NULL, NULL,
260                   g_cclosure_marshal_VOID__VOID,
261                   G_TYPE_NONE, 0);
262 
263   sn_config_signals[COLLECT_KNOWN_ITEMS] =
264     g_signal_new (g_intern_static_string ("collect-known-items"),
265                   G_TYPE_FROM_CLASS (object_class),
266                   G_SIGNAL_RUN_LAST,
267                   0, NULL, NULL,
268                   g_cclosure_marshal_generic,
269                   G_TYPE_NONE, 1, G_TYPE_POINTER);
270 
271   sn_config_signals[LEGACY_ITEM_LIST_CHANGED] =
272     g_signal_new (g_intern_static_string ("legacy-items-list-changed"),
273                   G_TYPE_FROM_CLASS (object_class),
274                   G_SIGNAL_RUN_LAST,
275                   0, NULL, NULL,
276                   g_cclosure_marshal_VOID__VOID,
277                   G_TYPE_NONE, 0);
278 }
279 
280 
281 
282 static void
sn_config_init(SnConfig * config)283 sn_config_init (SnConfig *config)
284 {
285   config->icon_size            = DEFAULT_ICON_SIZE;
286   config->single_row           = DEFAULT_SINGLE_ROW;
287   config->square_icons         = DEFAULT_SQUARE_ICONS;
288   config->symbolic_icons       = DEFAULT_SYMBOLIC_ICONS;
289   config->hide_new_items       = DEFAULT_HIDE_NEW_ITEMS;
290   config->known_items          = NULL;
291   config->hidden_items         = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
292   config->known_legacy_items   = NULL;
293   config->hidden_legacy_items  = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
294 
295   config->orientation          = DEFAULT_ORIENTATION;
296   config->panel_orientation    = DEFAULT_PANEL_ORIENTATION;
297   config->nrows                = 1;
298   config->panel_size           = DEFAULT_PANEL_SIZE;
299 }
300 
301 
302 
303 static void
sn_config_finalize(GObject * object)304 sn_config_finalize (GObject *object)
305 {
306   SnConfig *config = XFCE_SN_CONFIG (object);
307 
308   xfconf_shutdown ();
309 
310   g_list_free_full (config->known_items, g_free);
311   g_hash_table_destroy (config->hidden_items);
312 
313   g_list_free_full (config->known_legacy_items, g_free);
314   g_hash_table_destroy (config->hidden_legacy_items);
315 
316   G_OBJECT_CLASS (sn_config_parent_class)->finalize (object);
317 }
318 
319 
320 
321 static void
sn_config_free_array_element(gpointer data)322 sn_config_free_array_element (gpointer data)
323 {
324   GValue *value = (GValue *)data;
325 
326   g_value_unset (value);
327   g_free (value);
328 }
329 
330 
331 
332 static void
sn_config_collect_keys(gpointer key,gpointer value,gpointer array)333 sn_config_collect_keys (gpointer key,
334                         gpointer value,
335                         gpointer array)
336 {
337   GValue *tmp;
338 
339   tmp = g_new0 (GValue, 1);
340   g_value_init (tmp, G_TYPE_STRING);
341   g_value_set_string (tmp, key);
342   g_ptr_array_add (array, tmp);
343 }
344 
345 
346 
347 static void
sn_config_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)348 sn_config_get_property (GObject    *object,
349                         guint       prop_id,
350                         GValue     *value,
351                         GParamSpec *pspec)
352 {
353   SnConfig  *config = XFCE_SN_CONFIG (object);
354   GPtrArray *array;
355   GList     *li;
356   GValue    *tmp;
357 
358   switch (prop_id)
359     {
360     case PROP_ICON_SIZE:
361       g_value_set_int (value, config->icon_size);
362       break;
363 
364     case PROP_SINGLE_ROW:
365       g_value_set_boolean (value, config->single_row);
366       break;
367 
368     case PROP_SQUARE_ICONS:
369       g_value_set_boolean (value, config->square_icons);
370       break;
371 
372     case PROP_SYMBOLIC_ICONS:
373       g_value_set_boolean (value, config->symbolic_icons);
374       break;
375 
376     case PROP_MENU_IS_PRIMARY:
377       g_value_set_boolean (value, config->menu_is_primary);
378       break;
379 
380     case PROP_HIDE_NEW_ITEMS:
381       g_value_set_boolean (value, config->hide_new_items);
382       break;
383 
384     case PROP_KNOWN_ITEMS:
385       array = g_ptr_array_new_full (1, sn_config_free_array_element);
386       for (li = config->known_items; li != NULL; li = li->next)
387         {
388           tmp = g_new0 (GValue, 1);
389           g_value_init (tmp, G_TYPE_STRING);
390           g_value_set_string (tmp, li->data);
391           g_ptr_array_add (array, tmp);
392         }
393       g_value_set_boxed (value, array);
394       g_ptr_array_unref (array);
395       break;
396 
397     case PROP_HIDDEN_ITEMS:
398       array = g_ptr_array_new_full (1, sn_config_free_array_element);
399       g_hash_table_foreach (config->hidden_items, sn_config_collect_keys, array);
400       g_value_set_boxed (value, array);
401       g_ptr_array_unref (array);
402       break;
403 
404     case PROP_KNOWN_LEGACY_ITEMS:
405       array = g_ptr_array_new_full (1, sn_config_free_array_element);
406       for (li = config->known_legacy_items; li != NULL; li = li->next)
407         {
408           tmp = g_new0 (GValue, 1);
409           g_value_init (tmp, G_TYPE_STRING);
410           g_value_set_string (tmp, li->data);
411           g_ptr_array_add (array, tmp);
412         }
413       g_value_set_boxed (value, array);
414       g_ptr_array_unref (array);
415       break;
416 
417     case PROP_HIDDEN_LEGACY_ITEMS:
418       array = g_ptr_array_new_full (1, sn_config_free_array_element);
419       g_hash_table_foreach (config->hidden_legacy_items, sn_config_collect_keys, array);
420       g_value_set_boxed (value, array);
421       g_ptr_array_unref (array);
422       break;
423 
424     default:
425       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
426       break;
427     }
428 }
429 
430 
431 
432 static void
sn_config_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)433 sn_config_set_property (GObject      *object,
434                         guint         prop_id,
435                         const GValue *value,
436                         GParamSpec   *pspec)
437 {
438   SnConfig     *config = XFCE_SN_CONFIG (object);
439   gint          val;
440   GPtrArray    *array;
441   const GValue *tmp;
442   gchar        *name;
443   guint         i;
444 
445   switch (prop_id)
446     {
447     case PROP_ICON_SIZE:
448       val = g_value_get_int (value);
449       if (config->icon_size != val)
450         {
451           config->icon_size = val;
452           g_signal_emit (G_OBJECT (config), sn_config_signals[ICONS_CHANGED], 0);
453           g_signal_emit (G_OBJECT (config), sn_config_signals[CONFIGURATION_CHANGED], 0);
454         }
455       break;
456 
457     case PROP_SINGLE_ROW:
458       val = g_value_get_boolean (value);
459       if (config->single_row != val)
460         {
461           config->single_row = val;
462           g_signal_emit (G_OBJECT (config), sn_config_signals[CONFIGURATION_CHANGED], 0);
463         }
464       break;
465 
466     case PROP_SQUARE_ICONS:
467       val = g_value_get_boolean (value);
468       if (config->square_icons != val)
469         {
470           config->square_icons = val;
471           g_signal_emit (G_OBJECT (config), sn_config_signals[CONFIGURATION_CHANGED], 0);
472         }
473       break;
474 
475     case PROP_SYMBOLIC_ICONS:
476       val = g_value_get_boolean (value);
477       if (config->symbolic_icons != val)
478         {
479           config->symbolic_icons = val;
480           g_signal_emit (G_OBJECT (config), sn_config_signals[CONFIGURATION_CHANGED], 0);
481         }
482       break;
483 
484     case PROP_MENU_IS_PRIMARY:
485       val = g_value_get_boolean (value);
486       if (config->menu_is_primary != val)
487         {
488           config->menu_is_primary = val;
489           g_signal_emit (G_OBJECT (config), sn_config_signals[CONFIGURATION_CHANGED], 0);
490         }
491       break;
492 
493     case PROP_HIDE_NEW_ITEMS:
494       val = g_value_get_boolean (value);
495       if (config->hide_new_items != val)
496         {
497           config->hide_new_items = val;
498           g_signal_emit (G_OBJECT (config), sn_config_signals[ITEM_LIST_CHANGED], 0);
499           g_signal_emit (G_OBJECT (config), sn_config_signals[LEGACY_ITEM_LIST_CHANGED], 0);
500         }
501       break;
502 
503     case PROP_KNOWN_ITEMS:
504       g_list_free_full (config->known_items, g_free);
505       config->known_items = NULL;
506       array = g_value_get_boxed (value);
507       if (G_LIKELY (array != NULL))
508         {
509           for (i = 0; i < array->len; i++)
510             {
511               tmp = g_ptr_array_index (array, i);
512               g_assert (G_VALUE_HOLDS_STRING (tmp));
513               name = g_value_dup_string (tmp);
514               config->known_items = g_list_append (config->known_items, name);
515             }
516         }
517       g_signal_emit (G_OBJECT (config), sn_config_signals[ITEM_LIST_CHANGED], 0);
518       break;
519 
520     case PROP_HIDDEN_ITEMS:
521       g_hash_table_remove_all (config->hidden_items);
522       array = g_value_get_boxed (value);
523       if (G_LIKELY (array != NULL))
524         {
525           for (i = 0; i < array->len; i++)
526             {
527               tmp = g_ptr_array_index (array, i);
528               g_assert (G_VALUE_HOLDS_STRING (tmp));
529               name = g_value_dup_string (tmp);
530               g_hash_table_replace (config->hidden_items, name, name);
531             }
532         }
533       g_signal_emit (G_OBJECT (config), sn_config_signals[ITEM_LIST_CHANGED], 0);
534       break;
535 
536     case PROP_KNOWN_LEGACY_ITEMS:
537       g_list_free_full (config->known_legacy_items, g_free);
538       config->known_legacy_items = NULL;
539       array = g_value_get_boxed (value);
540       if (G_LIKELY (array != NULL))
541         {
542           for (i = 0; i < array->len; i++)
543             {
544               tmp = g_ptr_array_index (array, i);
545               g_assert (G_VALUE_HOLDS_STRING (tmp));
546               name = g_value_dup_string (tmp);
547               config->known_legacy_items = g_list_append (config->known_legacy_items, name);
548             }
549         }
550       g_signal_emit (G_OBJECT (config), sn_config_signals[LEGACY_ITEM_LIST_CHANGED], 0);
551       break;
552 
553     case PROP_HIDDEN_LEGACY_ITEMS:
554       g_hash_table_remove_all (config->hidden_legacy_items);
555       array = g_value_get_boxed (value);
556       if (G_LIKELY (array != NULL))
557         {
558           for (i = 0; i < array->len; i++)
559             {
560               tmp = g_ptr_array_index (array, i);
561               g_assert (G_VALUE_HOLDS_STRING (tmp));
562               name = g_value_dup_string (tmp);
563               g_hash_table_replace (config->hidden_legacy_items, name, name);
564             }
565         }
566       g_signal_emit (G_OBJECT (config), sn_config_signals[LEGACY_ITEM_LIST_CHANGED], 0);
567       break;
568 
569     default:
570       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
571       break;
572     }
573 }
574 
575 
576 
577 gint
sn_config_get_icon_size(SnConfig * config)578 sn_config_get_icon_size (SnConfig *config)
579 {
580   g_return_val_if_fail (XFCE_IS_SN_CONFIG (config), DEFAULT_ICON_SIZE);
581 
582   if (config->icon_size > 0)
583     return config->icon_size;
584 
585   return config->panel_icon_size;
586 }
587 
588 
589 
590 gboolean
sn_config_get_icon_size_is_automatic(SnConfig * config)591 sn_config_get_icon_size_is_automatic (SnConfig *config)
592 {
593   g_return_val_if_fail (XFCE_IS_SN_CONFIG (config), FALSE);
594 
595   return config->icon_size == 0;
596 }
597 
598 
599 
600 void
sn_config_get_dimensions(SnConfig * config,gint * ret_icon_size,gint * ret_n_rows,gint * ret_row_size,gint * ret_padding)601 sn_config_get_dimensions (SnConfig *config,
602                           gint     *ret_icon_size,
603                           gint     *ret_n_rows,
604                           gint     *ret_row_size,
605                           gint     *ret_padding)
606 {
607   gint panel_size, config_nrows, icon_size, hx_size, hy_size, nrows, row_size, padding;
608   gboolean single_row, square_icons;
609 
610   panel_size = sn_config_get_panel_size(config);
611   config_nrows = sn_config_get_nrows(config);
612   icon_size = sn_config_get_icon_size(config);
613   single_row = sn_config_get_single_row(config);
614   square_icons = sn_config_get_square_icons(config);
615   if (square_icons)
616   {
617     single_row = TRUE;
618     nrows = single_row ? 1 : MAX(1, config_nrows);
619     hx_size = hy_size = panel_size / nrows;
620   }
621   else
622   {
623     hx_size = MIN(icon_size + 2, panel_size);
624     nrows = single_row ? 1 : MAX(1, panel_size / hx_size);
625     hy_size = panel_size / nrows;
626   }
627   icon_size = MIN(icon_size, MIN(hx_size, hy_size));
628 
629   if (icon_size % 2 != 0)
630     {
631       icon_size--;
632     }
633 
634   row_size = hy_size;
635   padding = (hy_size - icon_size) / 2;
636 
637   if (square_icons)
638     padding = 0;
639 
640   if (ret_icon_size != NULL)
641     *ret_icon_size = icon_size;
642 
643   if (ret_n_rows != NULL)
644     *ret_n_rows = nrows;
645 
646   if (ret_row_size != NULL)
647     *ret_row_size = row_size;
648 
649   if (ret_padding != NULL)
650     *ret_padding = padding;
651 }
652 
653 
654 
655 gboolean
sn_config_get_single_row(SnConfig * config)656 sn_config_get_single_row (SnConfig *config)
657 {
658   g_return_val_if_fail (XFCE_IS_SN_CONFIG (config), DEFAULT_SINGLE_ROW);
659 
660   return config->single_row;
661 }
662 
663 
664 
665 gboolean
sn_config_get_square_icons(SnConfig * config)666 sn_config_get_square_icons (SnConfig *config)
667 {
668   g_return_val_if_fail (XFCE_IS_SN_CONFIG (config), DEFAULT_SQUARE_ICONS);
669 
670   return config->square_icons;
671 }
672 
673 
674 
675 gboolean
sn_config_get_symbolic_icons(SnConfig * config)676 sn_config_get_symbolic_icons (SnConfig *config)
677 {
678   g_return_val_if_fail (XFCE_IS_SN_CONFIG (config), DEFAULT_SYMBOLIC_ICONS);
679 
680   return config->symbolic_icons;
681 }
682 
683 
684 
685 gboolean
sn_config_get_menu_is_primary(SnConfig * config)686 sn_config_get_menu_is_primary (SnConfig *config)
687 {
688   g_return_val_if_fail (XFCE_IS_SN_CONFIG (config), DEFAULT_MENU_IS_PRIMARY);
689 
690   return config->menu_is_primary;
691 }
692 
693 
694 
695 void
sn_config_set_orientation(SnConfig * config,GtkOrientation panel_orientation,GtkOrientation orientation)696 sn_config_set_orientation (SnConfig       *config,
697                            GtkOrientation  panel_orientation,
698                            GtkOrientation  orientation)
699 {
700   gboolean needs_update = FALSE;
701 
702   g_return_if_fail (XFCE_IS_SN_CONFIG (config));
703 
704   if (config->orientation != orientation)
705     {
706       config->orientation = orientation;
707       needs_update = TRUE;
708     }
709 
710   if (config->panel_orientation != panel_orientation)
711     {
712       config->panel_orientation = panel_orientation;
713       needs_update = TRUE;
714     }
715 
716   if (needs_update)
717     g_signal_emit (G_OBJECT (config), sn_config_signals[CONFIGURATION_CHANGED], 0);
718 }
719 
720 
721 
722 GtkOrientation
sn_config_get_orientation(SnConfig * config)723 sn_config_get_orientation (SnConfig *config)
724 {
725   g_return_val_if_fail (XFCE_IS_SN_CONFIG (config), DEFAULT_ORIENTATION);
726 
727   return config->orientation;
728 }
729 
730 
731 
732 GtkOrientation
sn_config_get_panel_orientation(SnConfig * config)733 sn_config_get_panel_orientation (SnConfig *config)
734 {
735   g_return_val_if_fail (XFCE_IS_SN_CONFIG (config), DEFAULT_PANEL_ORIENTATION);
736 
737   return config->panel_orientation;
738 }
739 
740 
741 
742 void
sn_config_set_size(SnConfig * config,gint panel_size,gint nrows,gint icon_size)743 sn_config_set_size (SnConfig  *config,
744                     gint       panel_size,
745                     gint       nrows,
746                     gint       icon_size)
747 {
748   gboolean needs_update = FALSE;
749 
750   g_return_if_fail (XFCE_IS_SN_CONFIG (config));
751 
752   if (config->nrows != nrows)
753     {
754       config->nrows = nrows;
755       needs_update = TRUE;
756     }
757 
758   if (config->panel_size != panel_size)
759     {
760       config->panel_size = panel_size;
761       needs_update = TRUE;
762     }
763 
764   if (config->panel_icon_size != icon_size)
765     {
766       config->panel_icon_size = icon_size;
767       needs_update = TRUE;
768       g_signal_emit (G_OBJECT (config), sn_config_signals[ICONS_CHANGED], 0);
769     }
770 
771   if (needs_update)
772     g_signal_emit (G_OBJECT (config), sn_config_signals[CONFIGURATION_CHANGED], 0);
773 }
774 
775 
776 
777 gint
sn_config_get_nrows(SnConfig * config)778 sn_config_get_nrows (SnConfig *config)
779 {
780   g_return_val_if_fail (XFCE_IS_SN_CONFIG (config), 1);
781 
782   return config->nrows;
783 }
784 
785 
786 
787 gint
sn_config_get_panel_size(SnConfig * config)788 sn_config_get_panel_size (SnConfig *config)
789 {
790   g_return_val_if_fail (XFCE_IS_SN_CONFIG (config), DEFAULT_PANEL_SIZE);
791 
792   return config->panel_size;
793 }
794 
795 
796 
797 gboolean
sn_config_is_hidden(SnConfig * config,const gchar * name)798 sn_config_is_hidden (SnConfig    *config,
799                      const gchar *name)
800 {
801   g_return_val_if_fail (XFCE_IS_SN_CONFIG (config), FALSE);
802 
803   return g_hash_table_lookup_extended (config->hidden_items, name, NULL, NULL);
804 }
805 
806 
807 
808 void
sn_config_set_hidden(SnConfig * config,const gchar * name,gboolean hidden)809 sn_config_set_hidden (SnConfig    *config,
810                       const gchar *name,
811                       gboolean     hidden)
812 {
813   gchar *name_copy;
814 
815   g_return_if_fail (XFCE_IS_SN_CONFIG (config));
816 
817   if (hidden)
818     {
819       name_copy = g_strdup (name);
820       g_hash_table_replace (config->hidden_items, name_copy, name_copy);
821     }
822   else
823     {
824       g_hash_table_remove (config->hidden_items, name);
825     }
826   g_object_notify (G_OBJECT (config), "hidden-items");
827   g_signal_emit (G_OBJECT (config), sn_config_signals[ITEM_LIST_CHANGED], 0);
828 }
829 
830 
831 
832 gboolean
sn_config_is_legacy_hidden(SnConfig * config,const gchar * name)833 sn_config_is_legacy_hidden (SnConfig    *config,
834                             const gchar *name)
835 {
836   g_return_val_if_fail (XFCE_IS_SN_CONFIG (config), FALSE);
837 
838   return g_hash_table_lookup_extended (config->hidden_legacy_items, name, NULL, NULL);
839 }
840 
841 
842 
843 void
sn_config_set_legacy_hidden(SnConfig * config,const gchar * name,gboolean hidden)844 sn_config_set_legacy_hidden (SnConfig    *config,
845                               const gchar *name,
846                               gboolean     hidden)
847 {
848   gchar *name_copy;
849 
850   g_return_if_fail (XFCE_IS_SN_CONFIG (config));
851 
852   if (hidden)
853     {
854       name_copy = g_strdup (name);
855       g_hash_table_replace (config->hidden_legacy_items, name_copy, name_copy);
856     }
857   else
858     {
859       g_hash_table_remove (config->hidden_legacy_items, name);
860     }
861   g_object_notify (G_OBJECT (config), "hidden-legacy-items");
862   g_signal_emit (G_OBJECT (config), sn_config_signals[LEGACY_ITEM_LIST_CHANGED], 0);
863 }
864 
865 
866 
867 GList*
sn_config_get_known_items(SnConfig * config)868 sn_config_get_known_items (SnConfig *config)
869 {
870   g_return_val_if_fail (XFCE_IS_SN_CONFIG (config), NULL);
871 
872   return config->known_items;
873 }
874 
875 
876 
877 GList*
sn_config_get_known_legacy_items(SnConfig * config)878 sn_config_get_known_legacy_items (SnConfig *config)
879 {
880   g_return_val_if_fail (XFCE_IS_SN_CONFIG (config), NULL);
881 
882   return config->known_legacy_items;
883 }
884 
885 
886 
887 GList*
sn_config_get_hidden_legacy_items(SnConfig * config)888 sn_config_get_hidden_legacy_items (SnConfig *config)
889 {
890   GList *list = NULL;
891 
892   g_return_val_if_fail (XFCE_IS_SN_CONFIG (config), NULL);
893 
894   list = g_hash_table_get_values (config->hidden_legacy_items);
895 
896   return list;
897 }
898 
899 
900 
901 void
sn_config_add_known_item(SnConfig * config,const gchar * name)902 sn_config_add_known_item (SnConfig    *config,
903                           const gchar *name)
904 {
905   GList *li;
906   gchar *name_copy;
907 
908   g_return_if_fail (XFCE_IS_SN_CONFIG (config));
909 
910   /* check if item is already known */
911   for(li = config->known_items; li != NULL; li = li->next)
912     if (g_strcmp0 (li->data, name) == 0)
913       return;
914 
915   config->known_items = g_list_prepend (config->known_items, g_strdup (name));
916 
917   if (config->hide_new_items)
918     {
919       name_copy = g_strdup (name);
920       g_hash_table_replace (config->hidden_items, name_copy, name_copy);
921       g_object_notify (G_OBJECT (config), "hidden-items");
922     }
923 
924   g_object_notify (G_OBJECT (config), "known-items");
925   g_signal_emit (G_OBJECT (config), sn_config_signals[ITEM_LIST_CHANGED], 0);
926 }
927 
928 
929 
930 gboolean
sn_config_add_known_legacy_item(SnConfig * config,const gchar * name)931 sn_config_add_known_legacy_item (SnConfig    *config,
932                                  const gchar *name)
933 {
934   GList *li;
935   gchar *name_copy;
936 
937   g_return_val_if_fail (XFCE_IS_SN_CONFIG (config), TRUE);
938 
939   /* check if item is already known */
940   for(li = config->known_legacy_items; li != NULL; li = li->next)
941     if (g_strcmp0 (li->data, name) == 0)
942       return g_hash_table_contains (config->hidden_legacy_items, name);
943 
944   config->known_legacy_items = g_list_prepend (config->known_legacy_items, g_strdup (name));
945 
946   if (config->hide_new_items)
947     {
948       name_copy = g_strdup (name);
949       g_hash_table_replace (config->hidden_legacy_items, name_copy, name_copy);
950       g_object_notify (G_OBJECT (config), "hidden-legacy-items");
951     }
952 
953   g_object_notify (G_OBJECT (config), "known-legacy-items");
954   g_signal_emit (G_OBJECT (config), sn_config_signals[LEGACY_ITEM_LIST_CHANGED], 0);
955 
956   return config->hide_new_items;
957 }
958 
959 
960 
961 void
sn_config_swap_known_items(SnConfig * config,const gchar * name1,const gchar * name2)962 sn_config_swap_known_items (SnConfig    *config,
963                             const gchar *name1,
964                             const gchar *name2)
965 {
966   GList *li, *li_tmp;
967 
968   g_return_if_fail (XFCE_IS_SN_CONFIG (config));
969 
970   for(li = config->known_items; li != NULL; li = li->next)
971     if (g_strcmp0 (li->data, name1) == 0)
972       break;
973 
974   /* make sure that the list contains name1 followed by name2 */
975   if (li == NULL || li->next == NULL || g_strcmp0 (li->next->data, name2) != 0)
976     {
977       g_debug("Couldn't swap items: %s and %s", name1, name2);
978       return;
979     }
980 
981   /* li_tmp will contain only the removed element (name2) */
982   li_tmp = li->next;
983   config->known_items = g_list_remove_link (config->known_items, li_tmp);
984 
985   /* not strictly necessary (in testing the list contents was preserved)
986    * but searching for the index again should be safer */
987   for(li = config->known_items; li != NULL; li = li->next)
988     if (g_strcmp0 (li->data, name1) == 0)
989       break;
990 
991   config->known_items = g_list_insert_before (config->known_items, li, li_tmp->data);
992   g_list_free (li_tmp);
993 
994   g_object_notify (G_OBJECT (config), "known-items");
995   g_signal_emit (G_OBJECT (config), sn_config_signals[ITEM_LIST_CHANGED], 0);
996 }
997 
998 
999 
sn_config_swap_known_legacy_items(SnConfig * config,const gchar * name1,const gchar * name2)1000 void sn_config_swap_known_legacy_items(SnConfig *config,
1001                                        const gchar *name1,
1002                                        const gchar *name2)
1003 {
1004   GList *li, *li_tmp;
1005 
1006   g_return_if_fail(XFCE_IS_SN_CONFIG(config));
1007 
1008   for (li = config->known_legacy_items; li != NULL; li = li->next)
1009     if (g_strcmp0(li->data, name1) == 0)
1010       break;
1011 
1012   /* make sure that the list contains name1 followed by name2 */
1013   if (li == NULL || li->next == NULL || g_strcmp0(li->next->data, name2) != 0)
1014   {
1015     g_debug("Couldn't swap items: %s and %s", name1, name2);
1016     return;
1017   }
1018 
1019   /* li_tmp will contain only the removed element (name2) */
1020   li_tmp = li->next;
1021   config->known_legacy_items = g_list_remove_link(config->known_legacy_items, li_tmp);
1022 
1023   /* not strictly necessary (in testing the list contents was preserved)
1024    * but searching for the index again should be safer */
1025   for (li = config->known_legacy_items; li != NULL; li = li->next)
1026     if (g_strcmp0(li->data, name1) == 0)
1027       break;
1028 
1029   config->known_legacy_items = g_list_insert_before(config->known_legacy_items, li, li_tmp->data);
1030   g_list_free(li_tmp);
1031 
1032   g_object_notify(G_OBJECT(config), "known-legacy-items");
1033   g_signal_emit(G_OBJECT(config), sn_config_signals[LEGACY_ITEM_LIST_CHANGED], 0);
1034 }
1035 
1036 
1037 
1038 static gboolean
sn_config_items_clear_callback(gpointer key,gpointer value,gpointer user_data)1039 sn_config_items_clear_callback (gpointer key,
1040                                 gpointer value,
1041                                 gpointer user_data)
1042 {
1043   GHashTable *collected_known_items = user_data;
1044   return !g_hash_table_contains (collected_known_items, key);
1045 }
1046 
1047 
1048 
1049 gboolean
sn_config_items_clear(SnConfig * config)1050 sn_config_items_clear (SnConfig *config)
1051 {
1052   GHashTable *collected_known_items;
1053   guint       initial_size;
1054   GList      *new_list, *li;
1055 
1056   collected_known_items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1057 
1058   g_signal_emit (G_OBJECT (config), sn_config_signals[COLLECT_KNOWN_ITEMS],
1059                  0, collected_known_items);
1060 
1061   initial_size = g_list_length (config->known_items);
1062   new_list = NULL;
1063   for (li = config->known_items; li != NULL; li = li->next)
1064     {
1065       if (g_hash_table_contains (collected_known_items, li->data))
1066         {
1067           new_list = g_list_append (new_list, g_strdup (li->data));
1068         }
1069     }
1070   g_list_free_full (config->known_items, g_free);
1071   config->known_items = new_list;
1072 
1073   g_hash_table_foreach_remove (config->hidden_items,
1074                                sn_config_items_clear_callback,
1075                                collected_known_items);
1076   g_hash_table_destroy (collected_known_items);
1077 
1078   if (initial_size != g_list_length (config->known_items))
1079     {
1080       g_object_notify (G_OBJECT (config), "known-items");
1081       g_object_notify (G_OBJECT (config), "hidden-items");
1082       g_signal_emit (G_OBJECT (config), sn_config_signals[ITEM_LIST_CHANGED], 0);
1083 
1084       return TRUE;
1085     }
1086   else
1087     {
1088       return FALSE;
1089     }
1090 }
1091 
1092 
1093 
1094 gboolean
sn_config_legacy_items_clear(SnConfig * config)1095 sn_config_legacy_items_clear(SnConfig *config)
1096 {
1097   g_list_free_full(config->known_legacy_items, g_free);
1098   config->known_legacy_items = NULL;
1099   g_hash_table_remove_all (config->hidden_legacy_items);
1100 
1101   g_object_notify(G_OBJECT(config), "known-legacy-items");
1102   g_object_notify(G_OBJECT(config), "hidden-legacy-items");
1103 
1104   g_signal_emit(G_OBJECT(config), sn_config_signals[LEGACY_ITEM_LIST_CHANGED], 0);
1105 
1106   return TRUE;
1107 }
1108 
1109 
1110 
1111 SnConfig *
sn_config_new(const gchar * property_base)1112 sn_config_new (const gchar *property_base)
1113 {
1114   SnConfig      *config;
1115   XfconfChannel *channel;
1116   gchar         *property;
1117 
1118   config = g_object_new (XFCE_TYPE_SN_CONFIG, NULL);
1119 
1120   if (xfconf_init (NULL))
1121     {
1122       channel = xfconf_channel_get ("xfce4-panel");
1123 
1124       property = g_strconcat (property_base, "/icon-size", NULL);
1125       xfconf_g_property_bind (channel, property, G_TYPE_INT, config, "icon-size");
1126       g_free (property);
1127 
1128       property = g_strconcat (property_base, "/single-row", NULL);
1129       xfconf_g_property_bind (channel, property, G_TYPE_BOOLEAN, config, "single-row");
1130       g_free (property);
1131 
1132       property = g_strconcat (property_base, "/square-icons", NULL);
1133       xfconf_g_property_bind (channel, property, G_TYPE_BOOLEAN, config, "square-icons");
1134       g_free (property);
1135 
1136       property = g_strconcat (property_base, "/symbolic-icons", NULL);
1137       xfconf_g_property_bind (channel, property, G_TYPE_BOOLEAN, config, "symbolic-icons");
1138       g_free (property);
1139 
1140       property = g_strconcat (property_base, "/menu-is-primary", NULL);
1141       xfconf_g_property_bind (channel, property, G_TYPE_BOOLEAN, config, "menu-is-primary");
1142       g_free (property);
1143 
1144       property = g_strconcat (property_base, "/hide-new-items", NULL);
1145       xfconf_g_property_bind (channel, property, G_TYPE_BOOLEAN, config, "hide-new-items");
1146       g_free (property);
1147 
1148       property = g_strconcat (property_base, "/known-items", NULL);
1149       xfconf_g_property_bind (channel, property, XFCE_TYPE_SN_CONFIG_VALUE_ARRAY, config, "known-items");
1150       g_free (property);
1151 
1152       property = g_strconcat (property_base, "/hidden-items", NULL);
1153       xfconf_g_property_bind (channel, property, XFCE_TYPE_SN_CONFIG_VALUE_ARRAY, config, "hidden-items");
1154       g_free (property);
1155 
1156       property = g_strconcat (property_base, "/known-legacy-items", NULL);
1157       xfconf_g_property_bind (channel, property, XFCE_TYPE_SN_CONFIG_VALUE_ARRAY, config, "known-legacy-items");
1158       g_free (property);
1159 
1160       property = g_strconcat (property_base, "/hidden-legacy-items", NULL);
1161       xfconf_g_property_bind (channel, property, XFCE_TYPE_SN_CONFIG_VALUE_ARRAY, config, "hidden-legacy-items");
1162       g_free (property);
1163 
1164       g_signal_emit (G_OBJECT (config), sn_config_signals[CONFIGURATION_CHANGED], 0);
1165     }
1166 
1167   return config;
1168 }
1169