summaryrefslogtreecommitdiff
path: root/src/trg-prefs.c
diff options
context:
space:
mode:
authorGravatar Alan Fitton <ajf@eth0.org.uk>2011-08-27 17:15:31 +0000
committerGravatar Alan Fitton <ajf@eth0.org.uk>2011-08-27 17:15:31 +0000
commitbd758ee4fc423b9ca152a01f897609daa656c938 (patch)
tree0378306b5b007f38f0c4f6c0d868215f70fd70d6 /src/trg-prefs.c
parentb8a1599a2ab9eafd496ba23179dda97d6e83e917 (diff)
Profile support! Please test and report bugs, as the config system is totally rewritten and may not be perfect. No more GConf (trying to implement profiles with this was UGLY), settings now (for most) live in JSON at $HOME/.config/transmission-remote-gtk/config.json. Hopefully windows support will be easier without GConf.
Diffstat (limited to 'src/trg-prefs.c')
-rw-r--r--src/trg-prefs.c355
1 files changed, 355 insertions, 0 deletions
diff --git a/src/trg-prefs.c b/src/trg-prefs.c
new file mode 100644
index 0000000..5ef7ff9
--- /dev/null
+++ b/src/trg-prefs.c
@@ -0,0 +1,355 @@
+/*
+ * transmission-remote-gtk - Transmission RPC client for GTK
+ * Copyright (C) 2011 Alan Fitton
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <glib.h>
+#include <stdio.h>
+#include <json-glib/json-glib.h>
+#include <glib/gi18n.h>
+#include <glib/gprintf.h>
+
+#include "util.h"
+#include "trg-client.h"
+#include "trg-prefs.h"
+
+G_DEFINE_TYPE (TrgPrefs, trg_prefs, G_TYPE_OBJECT)
+
+#define GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_PREFS, TrgPrefsPrivate))
+
+typedef struct _TrgPrefsPrivate TrgPrefsPrivate;
+
+struct _TrgPrefsPrivate {
+ JsonObject *defaultsObj;
+ JsonNode *user;
+ JsonObject *userObj;
+ gchar *file;
+};
+
+static void trg_prefs_get_property(GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec) {
+ switch (property_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void trg_prefs_set_property(GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec) {
+ switch (property_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void trg_prefs_dispose(GObject *object) {
+ G_OBJECT_CLASS (trg_prefs_parent_class)->dispose(object);
+}
+
+static void trg_prefs_create_defaults(TrgPrefs *p) {
+ TrgPrefsPrivate *priv = GET_PRIVATE(p);
+ priv->defaultsObj = json_object_new();
+
+ trg_prefs_add_default_string(p, TRG_PREFS_KEY_PROFILE_NAME,
+ _(TRG_PROFILE_NAME_DEFAULT));
+ trg_prefs_add_default_int(p, TRG_PREFS_KEY_PORT, 9091);
+ trg_prefs_add_default_int(p, TRG_PREFS_KEY_UPDATE_INTERVAL, 3);
+
+ trg_prefs_add_default_bool(p, TRG_PREFS_KEY_FILTER_DIRS, TRUE);
+ trg_prefs_add_default_bool(p, TRG_PREFS_KEY_FILTER_TRACKERS, TRUE);
+ trg_prefs_add_default_bool(p, TRG_PREFS_KEY_AUTO_CONNECT, FALSE);
+ trg_prefs_add_default_bool(p, TRG_PREFS_KEY_SHOW_GRAPH, TRUE);
+ trg_prefs_add_default_bool(p, TRG_PREFS_KEY_SHOW_GRAPH, TRUE);
+ trg_prefs_add_default_bool(p, TRG_PREFS_KEY_ADD_OPTIONS_DIALOG, TRUE);
+}
+
+static GObject *trg_prefs_constructor(GType type, guint n_construct_properties,
+ GObjectConstructParam * construct_params) {
+ GObject *object;
+ TrgPrefsPrivate *priv;
+
+ object = G_OBJECT_CLASS
+ (trg_prefs_parent_class)->constructor(type, n_construct_properties,
+ construct_params);
+ priv = GET_PRIVATE(object);
+
+ trg_prefs_create_defaults(TRG_PREFS(object));
+
+ priv->file = g_build_filename (g_get_user_config_dir (),
+ g_get_application_name (),
+ TRG_PREFS_FILENAME, NULL);
+
+ return object;
+}
+
+static void trg_prefs_class_init(TrgPrefsClass *klass) {
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private(klass, sizeof(TrgPrefsPrivate));
+
+ object_class->get_property = trg_prefs_get_property;
+ object_class->set_property = trg_prefs_set_property;
+ object_class->dispose = trg_prefs_dispose;
+ object_class->constructor = trg_prefs_constructor;
+}
+
+static void trg_prefs_init(TrgPrefs *self) {
+}
+
+TrgPrefs*
+trg_prefs_new(void) {
+ return g_object_new(TRG_TYPE_PREFS, NULL);
+}
+
+static JsonObject *trg_prefs_new_profile_object() {
+ JsonObject *obj = json_object_new();
+ return obj;
+}
+
+void trg_prefs_add_default_int(TrgPrefs *p, gchar *key, int value) {
+ TrgPrefsPrivate *priv = GET_PRIVATE(p);
+ json_object_set_int_member(priv->defaultsObj, key, value);
+}
+
+void trg_prefs_add_default_string(TrgPrefs *p, gchar *key, gchar *value) {
+ TrgPrefsPrivate *priv = GET_PRIVATE(p);
+ json_object_set_string_member(priv->defaultsObj, key, value);
+}
+
+void trg_prefs_add_default_double(TrgPrefs *p, gchar *key, double value) {
+ TrgPrefsPrivate *priv = GET_PRIVATE(p);
+ json_object_set_double_member(priv->defaultsObj, key, value);
+}
+
+void trg_prefs_add_default_bool(TrgPrefs *p, gchar *key, gboolean value) {
+ TrgPrefsPrivate *priv = GET_PRIVATE(p);
+ json_object_set_boolean_member(priv->defaultsObj, key, value);
+}
+
+gint trg_prefs_get_profile_id(TrgPrefs *p) {
+ TrgPrefsPrivate *priv = GET_PRIVATE(p);
+ return (gint)json_object_get_int_member(priv->userObj, TRG_PREFS_KEY_PROFILE_ID);
+}
+
+JsonObject *trg_prefs_get_current_profile(TrgPrefs *p) {
+ JsonArray *profiles = trg_prefs_get_profiles(p);
+ return json_array_get_object_element(profiles, trg_prefs_get_profile_id(p));
+}
+
+JsonNode *trg_prefs_get_value(TrgPrefs *p, gchar *key, int flags) {
+ TrgPrefsPrivate *priv = GET_PRIVATE(p);
+
+ if ((flags & TRG_PREFS_PROFILE)) {
+ JsonObject *profile = trg_prefs_get_current_profile(p);
+ if (json_object_has_member(profile, key)) {
+ return json_object_get_member(profile, key);
+ } else if ((flags & TRG_PREFS_NEWNODE)) {
+ JsonNode *newNode = json_node_new(JSON_NODE_VALUE);
+ json_object_set_member(profile, key, newNode);
+ return newNode;
+ }
+ } else {
+ if (json_object_has_member(priv->userObj, key)) {
+ return json_object_get_member(priv->userObj, key);
+ } else if ((flags & TRG_PREFS_NEWNODE)) {
+ JsonNode *newNode = json_node_new(JSON_NODE_VALUE);
+ json_object_set_member(priv->userObj, key, newNode);
+ return newNode;
+ }
+ }
+
+ if (priv->defaultsObj && json_object_has_member(priv->defaultsObj,
+ key)) {
+ return json_object_get_member(priv->defaultsObj, key);
+ }
+
+ return NULL;
+}
+
+gchar *trg_prefs_get_string(TrgPrefs *p, gchar *key, int flags) {
+ JsonNode *node = trg_prefs_get_value(p, key, flags);
+ if (node)
+ return g_strdup(json_node_get_string(node));
+ else
+ return NULL;
+}
+
+int trg_prefs_get_int(TrgPrefs *p, gchar *key, int flags) {
+ JsonNode *node = trg_prefs_get_value(p, key, flags);
+ if (node)
+ return json_node_get_int(node);
+ else
+ return 0;
+}
+
+gdouble trg_prefs_get_double(TrgPrefs *p, gchar *key, int flags) {
+ JsonNode *node = trg_prefs_get_value(p, key, flags);
+ if (node)
+ return json_node_get_double(node);
+ else
+ return 0.0;
+}
+
+gboolean trg_prefs_get_bool(TrgPrefs *p, gchar *key, int flags) {
+ JsonNode *node = trg_prefs_get_value(p, key, flags);
+ if (node)
+ return json_node_get_boolean(node);
+ else
+ return FALSE;
+}
+
+void trg_prefs_set_int(TrgPrefs *p, gchar *key, int value, int flags) {
+ JsonNode *node = trg_prefs_get_value(p, key, flags | TRG_PREFS_NEWNODE);
+ json_node_set_int(node, (gint64)value);
+}
+
+void trg_prefs_set_string(TrgPrefs *p, gchar *key, const gchar *value,
+ int flags) {
+ JsonNode *node = trg_prefs_get_value(p, key, flags | TRG_PREFS_NEWNODE);
+ json_node_set_string(node, value);
+}
+
+void trg_prefs_set_profile(TrgPrefs *p, int index) {
+ trg_prefs_set_int(p, TRG_PREFS_KEY_PROFILE_ID, index, TRG_PREFS_GLOBAL);
+}
+
+gint trg_prefs_new_profile(TrgPrefs *p) {
+ JsonArray *profiles = trg_prefs_get_profiles(p);
+ JsonObject *newp = trg_prefs_new_profile_object();
+ json_array_add_object_element(profiles, newp);
+ return json_array_get_length(profiles) - 1;
+}
+
+void trg_prefs_del_profile(TrgPrefs *p, guint index) {
+ JsonArray *profiles = trg_prefs_get_profiles(p);
+ json_array_remove_element(profiles, index);
+}
+
+JsonArray* trg_prefs_get_profiles(TrgPrefs *p) {
+ TrgPrefsPrivate *priv = GET_PRIVATE(p);
+ return json_object_get_array_member(priv->userObj, TRG_PREFS_KEY_PROFILES);
+}
+
+void trg_prefs_set_double(TrgPrefs *p, gchar *key, gdouble value, int flags) {
+ JsonNode *node = trg_prefs_get_value(p, key, flags | TRG_PREFS_NEWNODE);
+ json_node_set_double(node, value);
+}
+
+void trg_prefs_set_bool(TrgPrefs *p, gchar *key, gboolean value, int flags) {
+ JsonNode *node = trg_prefs_get_value(p, key, flags | TRG_PREFS_NEWNODE);
+ json_node_set_boolean(node, value);
+}
+
+gboolean trg_prefs_save(TrgPrefs *p) {
+ TrgPrefsPrivate *priv = GET_PRIVATE(p);
+ JsonGenerator *gen = json_generator_new();
+ gchar *dirName;
+ gboolean success = TRUE;
+
+ dirName = g_path_get_dirname (priv->file);
+ if (!g_file_test(dirName, G_FILE_TEST_IS_DIR))
+ success = g_mkdir_with_parents (dirName, TRG_PREFS_DEFAULT_DIR_MODE) == 0;
+ g_free(dirName);
+
+ if (!success) {
+ g_error("Problem creating parent directory (permissions?) for: %s\n", priv->file);
+ return success;
+ }
+
+ g_object_set(G_OBJECT(gen), "pretty", TRUE, NULL);
+ json_generator_set_root(gen, priv->user);
+
+ success = json_generator_to_file(gen, priv->file, NULL);
+ if (!success)
+ g_error("Problem writing configuration file (permissions?) to: %s", priv->file);
+
+ g_object_unref(gen);
+
+ return success;
+}
+
+JsonObject *trg_prefs_get_root(TrgPrefs *p) {
+ TrgPrefsPrivate *priv = GET_PRIVATE(p);
+ return priv->userObj;
+}
+
+void trg_prefs_empty_init(TrgPrefs *p) {
+ TrgPrefsPrivate *priv = GET_PRIVATE(p);
+ priv->user = json_node_new(JSON_NODE_OBJECT);
+ priv->userObj = json_object_new();
+ json_node_take_object(priv->user, priv->userObj);
+
+ JsonObject *profile = trg_prefs_new_profile_object();
+
+ JsonArray *profiles = json_array_new();
+ json_array_add_object_element(profiles, profile);
+ json_object_set_array_member(priv->userObj, TRG_PREFS_KEY_PROFILES,
+ profiles);
+
+ json_object_set_int_member(priv->userObj, TRG_PREFS_KEY_PROFILE_ID, 0);
+}
+
+void trg_prefs_load(TrgPrefs *p) {
+ TrgPrefsPrivate *priv = GET_PRIVATE(p);
+ JsonParser *parser = json_parser_new();
+ JsonNode *root;
+ guint n_profiles;
+ JsonArray *profiles;
+
+ gboolean parsed = json_parser_load_from_file(parser, priv->file, NULL);
+
+ if (!parsed) {
+ trg_prefs_empty_init(p);
+ g_object_unref(parser);
+ return;
+ }
+
+ root = json_parser_get_root(parser);
+ if (root) {
+ priv->user = json_node_copy(root);
+ priv->userObj = json_node_get_object(priv->user);
+ }
+
+ g_object_unref(parser);
+
+ if (!root) {
+ trg_prefs_empty_init(p);
+ return;
+ }
+
+ if (!json_object_has_member(priv->userObj, TRG_PREFS_KEY_PROFILES)) {
+ profiles = json_array_new();
+ json_object_set_array_member(priv->userObj, TRG_PREFS_KEY_PROFILES,
+ profiles);
+ } else {
+ profiles = json_object_get_array_member(priv->userObj,
+ TRG_PREFS_KEY_PROFILES);
+ }
+
+ n_profiles = json_array_get_length(profiles);
+
+ if (n_profiles < 1) {
+ json_array_add_object_element(profiles, trg_prefs_new_profile_object());
+ trg_prefs_set_int(p, TRG_PREFS_KEY_PROFILE_ID, 0, TRG_PREFS_GLOBAL);
+ } else {
+ gint profile_id = trg_prefs_get_int(p, TRG_PREFS_KEY_PROFILE_ID,
+ TRG_PREFS_GLOBAL);
+ if (profile_id >= n_profiles)
+ trg_prefs_set_int(p, TRG_PREFS_KEY_PROFILE_ID, 0, TRG_PREFS_GLOBAL);
+ }
+}