1 /*
2  * Copyright (c) 2010 Mike Massonnet, <mmassonnet@xfce.org>
3  *
4  * Based on ThunarPreferences:
5  * Copyright (c) Benedikt Meurer <benny@xfce.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or (at
10  * your option) any later version.
11  */
12 
13 #ifdef HAVE_CONFIG_H
14 #include <config.h>
15 #endif
16 
17 #ifdef HAVE_STRING_H
18 #include <string.h>
19 #endif
20 
21 #ifdef HAVE_STDLIB_H
22 #include <stdlib.h>
23 #endif
24 
25 #include <glib-object.h>
26 #include <glib.h>
27 #include <glib/gi18n.h>
28 
29 #include "settings.h"
30 
31 
32 
33 enum
34 {
35 	PROP_SHOW_ALL_PROCESSES = 1,
36 	PROP_SHOW_LEGEND,
37 	PROP_MORE_PRECISION,
38 	PROP_FULL_COMMAND_LINE,
39 	PROP_SHOW_STATUS_ICON,
40 	PROP_MONITOR_PAINT_BOX,
41 	PROP_SHOW_APPLICATION_ICONS,
42 	PROP_TOOLBAR_STYLE,
43 	PROP_PROMPT_TERMINATE_TASK,
44 	PROP_REFRESH_RATE,
45 	PROP_COLUMNS_POSITIONS,
46 	PROP_COLUMN_UID,
47 	PROP_COLUMN_PID,
48 	PROP_COLUMN_PPID,
49 	PROP_COLUMN_STATE,
50 	PROP_COLUMN_VSZ,
51 	PROP_COLUMN_RSS,
52 	PROP_COLUMN_CPU,
53 	PROP_COLUMN_PRIORITY,
54 	PROP_SORT_COLUMN_ID,
55 	PROP_SORT_TYPE,
56 	PROP_WINDOW_WIDTH,
57 	PROP_WINDOW_HEIGHT,
58 	PROP_HANDLE_POSITION,
59 	PROP_PROCESS_TREE,
60 	N_PROPS,
61 };
62 typedef struct _XtmSettingsClass XtmSettingsClass;
63 struct _XtmSettingsClass
64 {
65 	GObjectClass		parent_class;
66 };
67 struct _XtmSettings
68 {
69 	GObject			parent;
70 	/*<private>*/
71 	GValue			values[N_PROPS];
72 	gint			loading; /* Setting loading now, do not save. */
73 };
74 G_DEFINE_TYPE (XtmSettings, xtm_settings, G_TYPE_OBJECT)
75 
76 static void	xtm_settings_get_property			(GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
77 static void	xtm_settings_set_property			(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
78 
79 static void	xtm_settings_load_settings			(XtmSettings *settings);
80 
81 
82 static void
xtm_settings_class_init(XtmSettingsClass * klass)83 xtm_settings_class_init (XtmSettingsClass *klass)
84 {
85 	GObjectClass *class = G_OBJECT_CLASS (klass);
86 	xtm_settings_parent_class = g_type_class_peek_parent (klass);
87 	class->get_property = xtm_settings_get_property;
88 	class->set_property = xtm_settings_set_property;
89 	g_object_class_install_property (class, PROP_SHOW_ALL_PROCESSES,
90 		g_param_spec_boolean ("show-all-processes", "ShowAllProcesses", "Show all processes", FALSE, G_PARAM_READWRITE));
91 	g_object_class_install_property (class, PROP_SHOW_LEGEND,
92 		g_param_spec_boolean ("show-legend", "ShowLegend", "Show legend", TRUE, G_PARAM_READWRITE));
93 	g_object_class_install_property (class, PROP_MORE_PRECISION,
94 		g_param_spec_boolean ("more-precision", "MorePrecision", "More precision", FALSE, G_PARAM_READWRITE));
95 	g_object_class_install_property (class, PROP_FULL_COMMAND_LINE,
96 		g_param_spec_boolean ("full-command-line", "FullCommandLine", "Full command line", FALSE, G_PARAM_READWRITE));
97 	g_object_class_install_property (class, PROP_SHOW_STATUS_ICON,
98 		g_param_spec_boolean ("show-status-icon", "ShowStatusIcon", "Show/hide the status icon", FALSE, G_PARAM_READWRITE));
99 	g_object_class_install_property (class, PROP_MONITOR_PAINT_BOX,
100 		g_param_spec_boolean ("monitor-paint-box", "MonitorPaintBox", "Paint box around monitor", TRUE, G_PARAM_READWRITE));
101 	g_object_class_install_property (class, PROP_SHOW_APPLICATION_ICONS,
102 		g_param_spec_boolean ("show-application-icons", "ShowApplicationIcons", "Show application icons", TRUE, G_PARAM_READWRITE));
103 	g_object_class_install_property (class, PROP_TOOLBAR_STYLE,
104 		g_param_spec_enum ("toolbar-style", "ToolbarStyle", "Toolbar style", XTM_TYPE_TOOLBAR_STYLE, XTM_TOOLBAR_STYLE_DEFAULT, G_PARAM_READWRITE));
105 	g_object_class_install_property (class, PROP_PROMPT_TERMINATE_TASK,
106 		g_param_spec_boolean ("prompt-terminate-task", "PromptTerminateTask", "Prompt dialog for terminating a task", TRUE, G_PARAM_READWRITE));
107 	g_object_class_install_property (class, PROP_REFRESH_RATE,
108 		g_param_spec_uint ("refresh-rate", "RefreshRate", "Refresh rate in milliseconds", 0, G_MAXUINT, 750, G_PARAM_READWRITE));
109 	g_object_class_install_property (class, PROP_COLUMNS_POSITIONS,
110 		g_param_spec_string ("columns-positions", "ColumnsPositions", "Positions of the tree view columns", NULL, G_PARAM_READWRITE));
111 	g_object_class_install_property (class, PROP_COLUMN_UID,
112 		g_param_spec_boolean ("column-uid", "ColumnUID", "Show column UID", FALSE, G_PARAM_READWRITE));
113 	g_object_class_install_property (class, PROP_COLUMN_PID,
114 		g_param_spec_boolean ("column-pid", "ColumnPID", "Show column PID", TRUE, G_PARAM_READWRITE));
115 	g_object_class_install_property (class, PROP_COLUMN_PPID,
116 		g_param_spec_boolean ("column-ppid", "ColumnPPID", "Show column PPID", FALSE, G_PARAM_READWRITE));
117 	g_object_class_install_property (class, PROP_COLUMN_STATE,
118 		g_param_spec_boolean ("column-state", "ColumnState", "Show column state", FALSE, G_PARAM_READWRITE));
119 	g_object_class_install_property (class, PROP_COLUMN_VSZ,
120 		g_param_spec_boolean ("column-vsz", "ColumnVSZ", "Show column VSZ", FALSE, G_PARAM_READWRITE));
121 	g_object_class_install_property (class, PROP_COLUMN_RSS,
122 		g_param_spec_boolean ("column-rss", "ColumnRSS", "Show column RSS", TRUE, G_PARAM_READWRITE));
123 	g_object_class_install_property (class, PROP_COLUMN_CPU,
124 		g_param_spec_boolean ("column-cpu", "ColumnCPU", "Show column CPU", TRUE, G_PARAM_READWRITE));
125 	g_object_class_install_property (class, PROP_COLUMN_PRIORITY,
126 		g_param_spec_boolean ("column-priority", "ColumnPriority", "Show column priority", FALSE, G_PARAM_READWRITE));
127 	g_object_class_install_property (class, PROP_SORT_COLUMN_ID,
128 		g_param_spec_uint ("sort-column-id", "SortColumn", "Sort by column id", 0, G_MAXUINT, 0, G_PARAM_READWRITE));
129 	g_object_class_install_property (class, PROP_SORT_TYPE,
130 		g_param_spec_uint ("sort-type", "SortType", "Sort type (asc/dsc)", 0, 1, 0, G_PARAM_READWRITE));
131 	g_object_class_install_property (class, PROP_WINDOW_WIDTH,
132 		g_param_spec_int ("window-width", "WindowWidth", "Window width", -1, G_MAXINT, -1, G_PARAM_READWRITE));
133 	g_object_class_install_property (class, PROP_WINDOW_HEIGHT,
134 		g_param_spec_int ("window-height", "WindowHeight", "Window height", -1, G_MAXINT, -1, G_PARAM_READWRITE));
135 	g_object_class_install_property (class, PROP_HANDLE_POSITION,
136 		g_param_spec_int ("handle-position", "HandlePosition", "Handle position", -1, G_MAXINT, -1, G_PARAM_READWRITE));
137 	g_object_class_install_property (class, PROP_PROCESS_TREE,
138 		g_param_spec_boolean ("process-tree", "ProcessTreeView", "Process tree", FALSE, G_PARAM_READWRITE));
139 }
140 
141 static void
xtm_settings_init(XtmSettings * settings)142 xtm_settings_init (XtmSettings *settings)
143 {
144 	xtm_settings_load_settings (settings);
145 }
146 
147 static void
xtm_settings_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)148 xtm_settings_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
149 {
150 	GValue *src = XTM_SETTINGS (object)->values + property_id;
151 	if (G_IS_VALUE (src))
152 		g_value_copy (src, value);
153 	else
154 		g_param_value_set_default (pspec, value);
155 }
156 
157 static void
xtm_settings_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)158 xtm_settings_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
159 {
160 	GValue *dest = XTM_SETTINGS (object)->values + property_id;
161 	if (!G_IS_VALUE(dest))
162 	{
163 		g_value_init (dest, pspec->value_type);
164 		g_param_value_set_default (pspec, dest);
165 	}
166 	if (g_param_values_cmp (pspec, value, dest) != 0)
167 	{
168 		g_value_copy (value, dest);
169 		/* Do not save some noisy changed props on fly. */
170 		switch (property_id) {
171 		case PROP_WINDOW_WIDTH:
172 		case PROP_WINDOW_HEIGHT:
173 			break;
174 		default:
175 			xtm_settings_save_settings (XTM_SETTINGS (object));
176 			break;
177 		}
178 	}
179 }
180 
181 
182 
183 static void
transform_string_to_boolean(const GValue * src,GValue * dst)184 transform_string_to_boolean (const GValue *src, GValue *dst)
185 {
186 	g_value_set_boolean (dst, (gboolean)strcmp (g_value_get_string (src), "FALSE") != 0);
187 }
188 
189 static void
transform_string_to_int(const GValue * src,GValue * dst)190 transform_string_to_int (const GValue *src, GValue *dst)
191 {
192 	g_value_set_int (dst, (gint)strtol (g_value_get_string (src), NULL, 10));
193 }
194 
195 static void
transform_string_to_uint(const GValue * src,GValue * dst)196 transform_string_to_uint (const GValue *src, GValue *dst)
197 {
198 	g_value_set_uint (dst, (guint)strtoul (g_value_get_string (src), NULL, 10));
199 }
200 
201 static void
transform_string_to_enum(const GValue * src,GValue * dst)202 transform_string_to_enum (const GValue *src, GValue *dst)
203 {
204 	GEnumClass *klass;
205 	gint value = 0;
206 	guint n;
207 
208 	klass = g_type_class_ref (G_VALUE_TYPE (dst));
209 	for (n = 0; n < klass->n_values; ++n)
210 	{
211 		value = klass->values[n].value;
212 		if (!g_ascii_strcasecmp (klass->values[n].value_name, g_value_get_string (src)))
213 			break;
214 	}
215 	g_type_class_unref (klass);
216 
217 	g_value_set_enum (dst, value);
218 }
219 
220 static void
register_transformable(void)221 register_transformable (void)
222 {
223 	if (!g_value_type_transformable (G_TYPE_STRING, G_TYPE_BOOLEAN))
224 		g_value_register_transform_func (G_TYPE_STRING, G_TYPE_BOOLEAN, transform_string_to_boolean);
225 
226 	if (!g_value_type_transformable (G_TYPE_STRING, G_TYPE_INT))
227 		g_value_register_transform_func (G_TYPE_STRING, G_TYPE_INT, transform_string_to_int);
228 
229 	if (!g_value_type_transformable (G_TYPE_STRING, G_TYPE_UINT))
230 		g_value_register_transform_func (G_TYPE_STRING, G_TYPE_UINT, transform_string_to_uint);
231 
232 	g_value_register_transform_func (G_TYPE_STRING, G_TYPE_ENUM, transform_string_to_enum);
233 }
234 
235 static void
xtm_settings_load_settings(XtmSettings * settings)236 xtm_settings_load_settings (XtmSettings *settings)
237 {
238 	GKeyFile *rc;
239 	gchar *filename;
240 
241 	register_transformable ();
242 
243 	settings->loading = 1;
244 	g_object_freeze_notify (G_OBJECT (settings));
245 
246 	rc = g_key_file_new ();
247 	filename = g_strdup_printf ("%s/xfce4/xfce4-taskmanager.rc", g_get_user_config_dir ());
248 
249 	if (g_key_file_load_from_file (rc, filename, G_KEY_FILE_NONE, NULL))
250 	{
251 		gchar *string;
252 		GValue dst = {0};
253 		GValue src = {0};
254 		GParamSpec **specs;
255 		GParamSpec *spec;
256 		guint nspecs;
257 		guint n;
258 
259 		specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (settings), &nspecs);
260 		for (n = 0; n < nspecs; ++n)
261 		{
262 			spec = specs[n];
263 			string = g_key_file_get_string (rc, "Settings", g_param_spec_get_nick (spec), NULL);
264 			if (string == NULL)
265 				continue;
266 
267 			g_value_init (&src, G_TYPE_STRING);
268 			g_value_set_string (&src, string);
269 			g_free (string);
270 
271 			if (spec->value_type == G_TYPE_STRING)
272 			{
273 				g_object_set_property (G_OBJECT (settings), spec->name, &src);
274 			}
275 			else if (g_value_type_transformable (G_TYPE_STRING, spec->value_type))
276 			{
277 				g_value_init (&dst, spec->value_type);
278 				if (g_value_transform (&src, &dst))
279 					g_object_set_property (G_OBJECT (settings), spec->name, &dst);
280 				g_value_unset (&dst);
281 			}
282 			else
283 			{
284 				g_warning ("Failed to load property \"%s\"", spec->name);
285 			}
286 
287 			g_value_unset (&src);
288 		}
289 		g_free (specs);
290 	}
291 
292 	g_free (filename);
293 	g_key_file_free (rc);
294 
295 	g_object_thaw_notify (G_OBJECT (settings));
296 	settings->loading = 0;
297 }
298 
299 void
xtm_settings_save_settings(XtmSettings * settings)300 xtm_settings_save_settings (XtmSettings *settings)
301 {
302 	GKeyFile *rc;
303 	gchar *filename;
304 
305 	if (0 != settings->loading)
306 		return;
307 	rc = g_key_file_new ();
308 	filename = g_strdup_printf ("%s/xfce4/xfce4-taskmanager.rc", g_get_user_config_dir ());
309 
310 	{
311 		const gchar *string;
312 		GValue dst = {0};
313 		GValue src = {0};
314 		GParamSpec **specs;
315 		GParamSpec *spec;
316 		guint nspecs;
317 		guint n;
318 
319 		specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (settings), &nspecs);
320 		for (n = 0; n < nspecs; ++n)
321 		{
322 			spec = specs[n];
323 			g_value_init (&dst, G_TYPE_STRING);
324 			if (spec->value_type == G_TYPE_STRING)
325 			{
326 				g_object_get_property (G_OBJECT (settings), spec->name, &dst);
327 			}
328 			else
329 			{
330 				g_value_init (&src, spec->value_type);
331 				g_object_get_property (G_OBJECT (settings), spec->name, &src);
332 				g_value_transform (&src, &dst);
333 				g_value_unset (&src);
334 			}
335 			string = g_value_get_string (&dst);
336 
337 			if (string != NULL)
338 				g_key_file_set_string (rc, "Settings", g_param_spec_get_nick (spec), string);
339 
340 			g_value_unset (&dst);
341 		}
342 		g_free (specs);
343 	}
344 
345 	{
346 		GError *error = NULL;
347 		gchar *data;
348 		gsize length;
349 
350 		if (!g_file_test (filename, G_FILE_TEST_EXISTS))
351 		{
352 			gchar *path = g_strdup_printf ("%s/xfce4", g_get_user_config_dir ());
353 			g_mkdir_with_parents (path, 0700);
354 			g_free (path);
355 		}
356 
357 		data = g_key_file_to_data (rc, &length, NULL);
358 		if (!g_file_set_contents (filename, data, (gssize)length, &error))
359 		{
360 			g_warning ("Unable to save settings: %s", error->message);
361 			g_error_free (error);
362 		}
363 
364 		g_free (data);
365 	}
366 
367 	g_free (filename);
368 	g_key_file_free (rc);
369 }
370 
371 
372 
373 XtmSettings *
xtm_settings_get_default(void)374 xtm_settings_get_default (void)
375 {
376 	static XtmSettings *settings = NULL;
377 	if (settings == NULL)
378 	{
379 		settings = g_object_new (XTM_TYPE_SETTINGS, NULL);
380 		g_object_add_weak_pointer (G_OBJECT (settings), (gpointer)&settings);
381 	}
382 	else
383 	{
384 		g_object_ref (settings);
385 	}
386 	return settings;
387 }
388 
389 
390 
391 GType
xtm_toolbar_style_get_type(void)392 xtm_toolbar_style_get_type (void)
393 {
394 	static GType type = G_TYPE_INVALID;
395 
396 	static const GEnumValue values[] = {
397 		{ XTM_TOOLBAR_STYLE_DEFAULT, "DEFAULT", N_("Default") },
398 		{ XTM_TOOLBAR_STYLE_SMALL, "SMALL", N_("Small") },
399 		{ XTM_TOOLBAR_STYLE_LARGE, "LARGE", N_("Large") },
400 		{ XTM_TOOLBAR_STYLE_TEXT, "TEXT", N_("Text") },
401 		{ 0, NULL, NULL }
402 	};
403 
404 	if (type != G_TYPE_INVALID)
405 		return type;
406 
407 	type = g_enum_register_static ("XtmToolbarStyle", values);
408 	return type;
409 }
410