1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) John Stebbins 2008-2011 <stebbins@stebbins>
6 * settings.c is free software.
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
17 #include <glib/gstdio.h>
21 #include "hb-backend.h"
24 void dump_settings(GValue *settings);
25 void ghb_pref_audio_init(signal_user_data_t *ud);
28 debug_get_object(GtkBuilder* b, const gchar *n)
30 g_message("name %s\n", n);
31 return gtk_builder_get_object(b, n);
37 return ghb_dict_value_new();
41 ghb_settings_set_value(
46 if (key == NULL || value == NULL)
48 ghb_dict_insert(settings, g_strdup(key), ghb_value_dup(value));
52 ghb_settings_take_value(GValue *settings, const gchar *key, GValue *value)
54 ghb_dict_insert(settings, g_strdup(key), value);
58 ghb_settings_set_string(
64 value = ghb_string_value_new(sval);
65 ghb_dict_insert(settings, g_strdup(key), value);
69 ghb_settings_set_double(GValue *settings, const gchar *key, gdouble dval)
72 value = ghb_double_value_new(dval);
73 ghb_dict_insert(settings, g_strdup(key), value);
77 ghb_settings_set_int64(GValue *settings, const gchar *key, gint64 ival)
80 value = ghb_int64_value_new(ival);
81 ghb_dict_insert(settings, g_strdup(key), value);
85 ghb_settings_set_int(GValue *settings, const gchar *key, gint ival)
88 value = ghb_int64_value_new((gint64)ival);
89 ghb_dict_insert(settings, g_strdup(key), value);
93 ghb_settings_set_boolean(GValue *settings, const gchar *key, gboolean bval)
96 value = ghb_boolean_value_new(bval);
97 ghb_dict_insert(settings, g_strdup(key), value);
101 ghb_settings_get_value(const GValue *settings, const gchar *key)
104 value = ghb_dict_lookup(settings, key);
106 g_warning("returning null (%s)", key);
111 ghb_settings_get_boolean(const GValue *settings, const gchar *key)
114 value = ghb_settings_get_value(settings, key);
115 if (value == NULL) return FALSE;
116 return ghb_value_boolean(value);
120 ghb_settings_get_int64(const GValue *settings, const gchar *key)
123 value = ghb_settings_get_value(settings, key);
124 if (value == NULL) return 0;
125 return ghb_value_int64(value);
129 ghb_settings_get_int(const GValue *settings, const gchar *key)
132 value = ghb_settings_get_value(settings, key);
133 if (value == NULL) return 0;
134 return ghb_value_int(value);
138 ghb_settings_get_double(const GValue *settings, const gchar *key)
141 value = ghb_settings_get_value(settings, key);
142 if (value == NULL) return 0;
143 return ghb_value_double(value);
147 ghb_settings_get_string(const GValue *settings, const gchar *key)
150 value = ghb_settings_get_value(settings, key);
151 if (value == NULL) return g_strdup("");
152 return ghb_value_string(value);
156 ghb_settings_combo_int(const GValue *settings, const gchar *key)
158 return ghb_lookup_combo_int(key, ghb_settings_get_value(settings, key));
162 ghb_settings_combo_double(const GValue *settings, const gchar *key)
164 return ghb_lookup_combo_double(key, ghb_settings_get_value(settings, key));
168 ghb_settings_combo_option(const GValue *settings, const gchar *key)
170 return ghb_lookup_combo_option(key, ghb_settings_get_value(settings, key));
174 ghb_settings_combo_string(const GValue *settings, const gchar *key)
176 return ghb_lookup_combo_string(key, ghb_settings_get_value(settings, key));
179 // Map widget names to setting keys
180 // Widgets that map to settings have names
181 // of this format: s_<setting key>
183 ghb_get_setting_key(GtkWidget *widget)
187 g_debug("get_setting_key ()\n");
188 if (widget == NULL) return NULL;
189 name = gtk_buildable_get_name(GTK_BUILDABLE(widget));
193 // Bad widget pointer? Should never happen.
194 g_debug("Bad widget\n");
201 ghb_widget_value(GtkWidget *widget)
203 GValue *value = NULL;
209 g_debug("NULL widget\n");
213 type = GTK_WIDGET_TYPE(widget);
214 name = ghb_get_setting_key(widget);
215 g_debug("ghb_widget_value widget (%s)\n", name);
216 if (type == GTK_TYPE_ENTRY)
218 const gchar *str = gtk_entry_get_text(GTK_ENTRY(widget));
219 value = ghb_string_value_new(str);
221 else if (type == GTK_TYPE_RADIO_BUTTON)
223 g_debug("\tradio_button");
225 bval = gtk_toggle_button_get_inconsistent(GTK_TOGGLE_BUTTON(widget));
228 value = ghb_boolean_value_new(FALSE);
232 bval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
233 value = ghb_boolean_value_new(bval);
236 else if (type == GTK_TYPE_CHECK_BUTTON)
238 g_debug("\tcheck_button");
240 bval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
241 value = ghb_boolean_value_new(bval);
243 else if (type == GTK_TYPE_TOGGLE_TOOL_BUTTON)
245 g_debug("\ttoggle_tool_button");
247 bval = gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(widget));
248 value = ghb_boolean_value_new(bval);
250 else if (type == GTK_TYPE_TOGGLE_BUTTON)
252 g_debug("\ttoggle_button");
254 bval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
255 value = ghb_boolean_value_new(bval);
257 else if (type == GTK_TYPE_TOGGLE_ACTION)
259 g_debug("\ttoggle action");
261 bval = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(widget));
262 value = ghb_boolean_value_new(bval);
264 else if (type == GTK_TYPE_CHECK_MENU_ITEM)
266 g_debug("\tcheck_menu_item");
268 bval = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
269 value = ghb_boolean_value_new(bval);
271 else if (type == GTK_TYPE_COMBO_BOX)
273 g_debug("\tcombo_box");
278 store = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
279 if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget), &iter))
281 gtk_tree_model_get(store, &iter, 2, &shortOpt, -1);
282 value = ghb_string_value_new(shortOpt);
287 value = ghb_string_value_new("");
290 else if (type == GTK_TYPE_COMBO_BOX_ENTRY)
296 g_debug("\tcombo_box_entry");
297 store = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
298 if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget), &iter))
300 gtk_tree_model_get(store, &iter, 2, &shortOpt, -1);
301 value = ghb_string_value_new(shortOpt);
307 str = gtk_combo_box_get_active_text(GTK_COMBO_BOX(widget));
308 if (str == NULL) str = "";
309 value = ghb_string_value_new(str);
312 else if (type == GTK_TYPE_SPIN_BUTTON)
315 ival = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
316 value = ghb_int64_value_new(ival);
318 else if (type == GTK_TYPE_HSCALE)
323 digits = gtk_scale_get_digits(GTK_SCALE(widget));
324 dval = gtk_range_get_value(GTK_RANGE(widget));
327 value = ghb_double_value_new(dval);
331 value = ghb_int_value_new(dval);
334 else if (type == GTK_TYPE_SCALE_BUTTON)
338 dval = gtk_scale_button_get_value(GTK_SCALE_BUTTON(widget));
339 value = ghb_double_value_new(dval);
341 else if (type == GTK_TYPE_TEXT_VIEW)
343 GtkTextBuffer *buffer;
344 GtkTextIter start, end;
347 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
348 gtk_text_buffer_get_bounds(buffer, &start, &end);
349 str = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
350 value = ghb_string_value_new(str);
353 else if (type == GTK_TYPE_LABEL)
356 str = gtk_label_get_text (GTK_LABEL(widget));
357 value = ghb_string_value_new(str);
359 else if (type == GTK_TYPE_FILE_CHOOSER_BUTTON)
362 str = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(widget));
364 str = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget));
365 value = ghb_string_value_new(str);
371 g_debug("Attempt to set unknown widget type: %s\n", name);
379 ghb_widget_string(GtkWidget *widget)
384 value = ghb_widget_value(widget);
385 sval = ghb_value_string(value);
386 ghb_value_free(value);
391 ghb_widget_double(GtkWidget *widget)
396 value = ghb_widget_value(widget);
397 dval = ghb_value_double(value);
398 ghb_value_free(value);
403 ghb_widget_int64(GtkWidget *widget)
408 value = ghb_widget_value(widget);
409 ival = ghb_value_int64(value);
410 ghb_value_free(value);
415 ghb_widget_int(GtkWidget *widget)
420 value = ghb_widget_value(widget);
421 ival = (gint)ghb_value_int64(value);
422 ghb_value_free(value);
427 ghb_widget_boolean(GtkWidget *widget)
432 value = ghb_widget_value(widget);
433 bval = ghb_value_boolean(value);
434 ghb_value_free(value);
438 static void check_radio_consistency(GValue *settings, GtkWidget *widget)
440 const gchar *key = NULL;
443 if (widget == NULL) return;
444 if (G_OBJECT_TYPE(widget) == GTK_TYPE_RADIO_BUTTON)
446 // Find corresponding setting
447 key = ghb_get_setting_key(widget);
448 if (key == NULL) return;
449 value = ghb_widget_value(widget);
450 if (value == NULL) return;
451 if (ghb_value_boolean(value) == ghb_settings_get_boolean(settings, key))
453 gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(widget), FALSE);
459 ghb_widget_to_setting(GValue *settings, GtkWidget *widget)
461 const gchar *key = NULL;
464 if (widget == NULL) return;
465 g_debug("ghb_widget_to_setting");
466 // Find corresponding setting
467 key = ghb_get_setting_key(widget);
468 if (key == NULL) return;
469 value = ghb_widget_value(widget);
472 check_radio_consistency(settings, widget);
473 ghb_settings_take_value(settings, key, value);
477 g_debug("No value found for %s\n", key);
482 update_widget(GtkWidget *widget, const GValue *value)
489 g_debug("update_widget");
490 type = G_VALUE_TYPE(value);
491 if (type == ghb_array_get_type() || type == ghb_dict_get_type())
493 if (value == NULL) return;
494 str = ghb_value_string(value);
495 ival = ghb_value_int(value);
496 dval = ghb_value_double(value);
497 type = GTK_OBJECT_TYPE(widget);
498 if (type == GTK_TYPE_ENTRY)
501 gtk_entry_set_text((GtkEntry*)widget, str);
503 else if (type == GTK_TYPE_RADIO_BUTTON)
505 g_debug("radio button");
506 int cur_val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
507 if (cur_val && !ival)
509 gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(widget), TRUE);
513 gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(widget), FALSE);
514 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), ival);
517 else if (type == GTK_TYPE_CHECK_BUTTON)
519 g_debug("check button");
520 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), ival);
522 else if (type == GTK_TYPE_TOGGLE_TOOL_BUTTON)
524 g_debug("toggle button");
525 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(widget), ival);
527 else if (type == GTK_TYPE_TOGGLE_BUTTON)
529 g_debug("toggle button");
530 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), ival);
532 else if (type == GTK_TYPE_TOGGLE_ACTION)
534 g_debug("toggle action");
535 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(widget), ival);
537 else if (type == GTK_TYPE_CHECK_MENU_ITEM)
539 g_debug("check menu item");
540 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), ival);
542 else if (type == GTK_TYPE_COMBO_BOX)
548 gboolean foundit = FALSE;
550 g_debug("combo (%s)", str);
551 store = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
552 if (gtk_tree_model_get_iter_first (store, &iter))
556 gtk_tree_model_get(store, &iter, 2, &shortOpt, -1);
557 if (strcmp(shortOpt, str) == 0)
559 gtk_combo_box_set_active_iter (
560 GTK_COMBO_BOX(widget), &iter);
566 } while (gtk_tree_model_iter_next (store, &iter));
568 if (!foundit && gtk_tree_model_get_iter_first (store, &iter))
572 gtk_tree_model_get(store, &iter, 3, &ivalue, -1);
573 if ((gint)ivalue == ival || ivalue == dval)
575 gtk_combo_box_set_active_iter (
576 GTK_COMBO_BOX(widget), &iter);
580 } while (gtk_tree_model_iter_next (store, &iter));
584 gtk_combo_box_set_active (GTK_COMBO_BOX(widget), 0);
587 else if (type == GTK_TYPE_COMBO_BOX_ENTRY)
593 gboolean foundit = FALSE;
595 g_debug("GTK_COMBO_BOX_ENTRY");
596 store = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
597 if (gtk_tree_model_get_iter_first (store, &iter))
601 gtk_tree_model_get(store, &iter, 2, &shortOpt, -1);
602 if (strcmp(shortOpt, str) == 0)
604 gtk_combo_box_set_active_iter (
605 GTK_COMBO_BOX(widget), &iter);
611 } while (gtk_tree_model_iter_next (store, &iter));
613 if (!foundit && gtk_tree_model_get_iter_first (store, &iter))
617 gtk_tree_model_get(store, &iter, 3, &ivalue, -1);
618 if ((gint)ivalue == ival || ivalue == dval)
620 gtk_combo_box_set_active_iter (
621 GTK_COMBO_BOX(widget), &iter);
625 } while (gtk_tree_model_iter_next (store, &iter));
629 GtkEntry *entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(widget)));
632 gtk_entry_set_text (entry, str);
636 else if (type == GTK_TYPE_SPIN_BUTTON)
638 g_debug("spin (%s)", str);
639 gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), dval);
641 else if (type == GTK_TYPE_HSCALE)
644 gtk_range_set_value(GTK_RANGE(widget), dval);
646 else if (type == GTK_TYPE_SCALE_BUTTON)
648 g_debug("scale_button");
649 gtk_scale_button_set_value(GTK_SCALE_BUTTON(widget), dval);
651 else if (type == GTK_TYPE_TEXT_VIEW)
653 g_debug("textview (%s)", str);
654 GtkTextBuffer *buffer = gtk_text_view_get_buffer(
655 GTK_TEXT_VIEW(widget));
656 gtk_text_buffer_set_text (buffer, str, -1);
658 else if (type == GTK_TYPE_LABEL)
660 gtk_label_set_markup (GTK_LABEL(widget), str);
662 else if (type == GTK_TYPE_FILE_CHOOSER_BUTTON)
664 GtkFileChooserAction act;
665 act = gtk_file_chooser_get_action(GTK_FILE_CHOOSER(widget));
671 else if (act == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
672 act == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
674 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(widget), str);
676 else if (act == GTK_FILE_CHOOSER_ACTION_SAVE)
678 gtk_file_chooser_set_filename (GTK_FILE_CHOOSER(widget), str);
682 if (g_file_test(str, G_FILE_TEST_IS_DIR))
684 gtk_file_chooser_set_current_folder(
685 GTK_FILE_CHOOSER(widget), str);
687 else if (g_file_test(str, G_FILE_TEST_EXISTS))
689 gtk_file_chooser_set_filename (GTK_FILE_CHOOSER(widget), str);
695 dirname = g_path_get_dirname(str);
696 gtk_file_chooser_set_current_folder(
697 GTK_FILE_CHOOSER(widget), dirname);
704 g_debug("Attempt to set unknown widget type");
710 ghb_ui_update(signal_user_data_t *ud, const gchar *name, const GValue *value)
714 g_debug("ghb_ui_update() %s", name);
715 if (name == NULL || value == NULL)
717 object = GHB_OBJECT(ud->builder, name);
720 g_debug("Failed to find widget for key: %s\n", name);
723 update_widget((GtkWidget*)object, value);
724 // Its possible the value hasn't changed. Since settings are only
725 // updated when the value changes, I'm initializing settings here as well.
726 ghb_widget_to_setting(ud->settings, (GtkWidget*)object);