[aisleriot/wip/redesign: 7/17] all: Move card theme to prefs dialogue



commit 60bf2fc8a3e35795c0d340c3f59bf7adf86be78d
Author: Christian Persch <chpe gnome org>
Date:   Wed Jul 3 11:48:36 2013 +0200

    all: Move card theme to prefs dialogue

 src/ar-application.c |   23 +++++-
 src/ar-application.h |    5 +
 src/ar-prefs.c       |  110 +++++++++++++++++++++++++
 src/window.c         |  218 ++++++--------------------------------------------
 src/window.h         |    1 -
 5 files changed, 158 insertions(+), 199 deletions(-)
---
diff --git a/src/ar-application.c b/src/ar-application.c
index 15e8707..e930951 100644
--- a/src/ar-application.c
+++ b/src/ar-application.c
@@ -24,6 +24,7 @@
 #include "ar-application.h"
 #include "ar-defines.h"
 #include "ar-runtime.h"
+#include "ar-card-themes.h"
 
 #include <errno.h>
 #include <stdlib.h>
@@ -67,14 +68,11 @@ struct _ArApplicationPrivate
   gint seed; /* unused */
   gboolean freecell; /* unused */
 
+  ArCardThemes *card_themes;
   GSettingsBackend *state_keyfile_backend;
   GSettingsBackend *scores_keyfile_backend;
 };
 
-#if !GTK_CHECK_VERSION (3, 6, 0)
-#define gtk_application_get_active_window(w) NULL
-#endif
-
 G_DEFINE_TYPE (ArApplication, ar_application, GTK_TYPE_APPLICATION)
 
 static void
@@ -304,6 +302,7 @@ ar_application_dispose (GObject *object)
   g_free (self->priv->variation);
   self->priv->variation = NULL;
 
+  g_clear_object (&priv->card_themes);
   g_clear_object (&priv->state_keyfile_backend);
   g_clear_object (&priv->scores_keyfile_backend);
 
@@ -396,3 +395,19 @@ ar_application_options_settings_new (ArApplication *application,
 
   return settings;
 }
+
+ArCardThemes *
+ar_application_get_card_themes (ArApplication *application)
+{
+  ArApplicationPrivate *priv;
+
+  g_return_val_if_fail (AR_IS_APPLICATION (application), NULL);
+
+  priv = application->priv;
+
+  if (priv->card_themes == NULL)
+    priv->card_themes = ar_card_themes_new ();
+
+  return priv->card_themes;
+}
+
diff --git a/src/ar-application.h b/src/ar-application.h
index df5f381..f060126 100644
--- a/src/ar-application.h
+++ b/src/ar-application.h
@@ -19,6 +19,7 @@
 #define AR_APPLICATION_H
 
 #include <gtk/gtk.h>
+#include "ar-card-themes.h"
 
 G_BEGIN_DECLS
 
@@ -47,6 +48,10 @@ GSettings *ar_application_scores_settings_new (ArApplication *application,
 GSettings *ar_application_options_settings_new (ArApplication *application,
                                                 const char *game);
 
+ArCardThemes *ar_application_get_card_themes (ArApplication *application);
+
+#define AR_APP (AR_APPLICATION (g_application_get_default ()))
+
 G_END_DECLS
 
 #endif /* !AR_APPLICATION_H */
diff --git a/src/ar-prefs.c b/src/ar-prefs.c
index f2fdf5a..564c523 100644
--- a/src/ar-prefs.c
+++ b/src/ar-prefs.c
@@ -23,6 +23,7 @@
 #include <glib/gi18n.h>
 
 #include "ar-application.h"
+#include "ar-card-themes.h"
 #include "ar-debug.h"
 #include "ar-defines.h"
 #include "util.h"
@@ -33,6 +34,8 @@ typedef struct {
   GtkWidget *click_checkbutton;
   GtkWidget *sound_checkbutton;
   GtkWidget *animations_checkbutton;
+  GtkWidget *theme_combobox;
+  GtkListStore *theme_store;
 } ArPrefsPrivate;
 
 struct _ArPrefs
@@ -53,6 +56,11 @@ enum {
   PROP_WINDOW
 };
 
+enum {
+  COL_DISPLAY_NAME,
+  COL_THEME_INFO
+};
+
 /* private functions */
 
 static void
@@ -68,6 +76,72 @@ response_cb (GtkWidget *dialog,
   gtk_widget_destroy (dialog);
 }
 
+static void
+theme_combobox_changed_cb (GtkComboBox *combo,
+                           ArPrefs *prefs);
+
+static void
+theme_changed_cb (GSettings *settings,
+                  const char *key,
+                  ArPrefs *prefs)
+{
+  ArPrefsPrivate *priv = prefs->priv;
+  GtkTreeModel *model = GTK_TREE_MODEL (priv->theme_store);
+  GtkTreeIter iter;
+  gboolean found = FALSE;
+  ArCardThemeInfo *info;
+  const char *theme;
+
+  g_settings_get (settings, key, "&s", &theme);
+
+  if (!gtk_tree_model_get_iter_first (model, &iter))
+    goto done;
+
+  do {
+    gtk_tree_model_get (model, &iter, COL_THEME_INFO, &info, -1);
+
+    found = g_str_equal (ar_card_theme_info_get_persistent_name (info), theme);
+
+    ar_card_theme_info_unref (info);
+    if (found)
+      break;
+  } while (gtk_tree_model_iter_next (model, &iter));
+
+ done:
+
+  g_signal_handlers_block_by_func (priv->theme_combobox, G_CALLBACK (theme_combobox_changed_cb), prefs);
+
+  if (found)
+    gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->theme_combobox), &iter);
+  else
+    gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->theme_combobox), NULL);
+
+  g_signal_handlers_unblock_by_func (priv->theme_combobox, G_CALLBACK (theme_combobox_changed_cb), prefs);
+}
+
+static void
+theme_combobox_changed_cb (GtkComboBox *combo,
+                           ArPrefs *prefs)
+{
+  ArPrefsPrivate *priv = prefs->priv;
+  GtkTreeIter iter;
+  ArCardThemeInfo *info;
+  
+  if (!gtk_combo_box_get_active_iter (combo, &iter))
+    return;
+
+  gtk_tree_model_get (GTK_TREE_MODEL (priv->theme_store), &iter,
+                      COL_THEME_INFO, &info,
+                      -1);
+
+  g_signal_handlers_block_by_func (priv->settings, G_CALLBACK (theme_changed_cb), prefs);
+  g_settings_set_string (priv->settings, AR_SETTINGS_CARD_THEME_KEY,
+                         ar_card_theme_info_get_persistent_name (info));
+  g_signal_handlers_unblock_by_func (priv->settings, G_CALLBACK (theme_changed_cb), prefs);
+
+  ar_card_theme_info_unref (info);
+}
+
 /* GType impl */
 
 G_DEFINE_TYPE (ArPrefs, ar_prefs, GTK_TYPE_DIALOG)
@@ -77,7 +151,11 @@ G_DEFINE_TYPE (ArPrefs, ar_prefs, GTK_TYPE_DIALOG)
 static void
 ar_prefs_init (ArPrefs *prefs)
 {
+  ArApplication *application = AR_APP;
   ArPrefsPrivate *priv;
+  GList *list, *l;
+  GtkListStore *store;
+  ArCardThemes *card_themes;
 
   priv = prefs->priv = G_TYPE_INSTANCE_GET_PRIVATE (prefs, AR_TYPE_PREFS, ArPrefsPrivate);
 
@@ -85,6 +163,29 @@ ar_prefs_init (ArPrefs *prefs)
 
   gtk_widget_init_template (GTK_WIDGET (prefs));
 
+  /* Populate the card theme combo */
+  store = priv->theme_store = gtk_list_store_new (2, G_TYPE_STRING, AR_TYPE_CARD_THEME_INFO);
+
+  card_themes = ar_application_get_card_themes (application);
+  ar_card_themes_request_themes (card_themes);
+  list = ar_card_themes_get_themes (card_themes);
+  for (l = list; l != NULL; l = l->next) {
+    ArCardThemeInfo *info = (ArCardThemeInfo *) l->data;
+    GtkTreeIter iter;
+
+    gtk_list_store_insert_with_values (store, &iter, -1,
+                                       COL_DISPLAY_NAME,
+                                       ar_card_theme_info_get_display_name (info),
+                                       COL_THEME_INFO,
+                                       info,
+                                       -1);
+  }
+  g_list_free_full (list, (GDestroyNotify) ar_card_theme_info_unref);
+
+  gtk_combo_box_set_model (GTK_COMBO_BOX (priv->theme_combobox), GTK_TREE_MODEL (store));
+  g_object_unref (store);
+
+  /* Bind settings */
   g_settings_bind (priv->settings, AR_SETTINGS_CLICK_TO_MOVE_KEY,
                    priv->click_checkbutton, "active",
                    G_SETTINGS_BIND_DEFAULT);
@@ -99,6 +200,12 @@ ar_prefs_init (ArPrefs *prefs)
   gtk_widget_hide (priv->animations_checkbutton);
 #endif
 
+  theme_changed_cb (priv->settings, AR_SETTINGS_CARD_THEME_KEY, prefs);
+  g_signal_connect (priv->settings, "changed::" AR_SETTINGS_CARD_THEME_KEY,
+                    G_CALLBACK (theme_changed_cb), prefs);
+  g_signal_connect (priv->theme_combobox, "changed",
+                    G_CALLBACK (theme_combobox_changed_cb), prefs);
+
   g_signal_connect (prefs, "response", G_CALLBACK (response_cb), NULL);
 }
 
@@ -108,6 +215,8 @@ ar_prefs_finalize (GObject *object)
   ArPrefs *prefs = AR_PREFS (object);
   ArPrefsPrivate *priv = prefs->priv;
 
+  g_signal_handlers_disconnect_by_func (priv->settings, G_CALLBACK (theme_changed_cb), prefs);
+
   g_clear_object (&priv->settings);
 
   G_OBJECT_CLASS (ar_prefs_parent_class)->finalize (object);
@@ -161,6 +270,7 @@ ar_prefs_class_init (ArPrefsClass *klass)
   gtk_widget_class_bind_child (widget_class, ArPrefsPrivate, click_checkbutton);
   gtk_widget_class_bind_child (widget_class, ArPrefsPrivate, sound_checkbutton);
   gtk_widget_class_bind_child (widget_class, ArPrefsPrivate, animations_checkbutton);
+  gtk_widget_class_bind_child (widget_class, ArPrefsPrivate, theme_combobox);
 }
 
 /* public API */
diff --git a/src/window.c b/src/window.c
index fdbdb3d..e7fd4a2 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1378,170 +1378,30 @@ aisleriot_window_take_card_theme (AisleriotWindow *window,
   ar_style_set_card_theme (priv->board_style, theme);
 }
 
-#if 0
 static void
-card_theme_changed_cb (GtkToggleAction *action,
+card_theme_changed_cb (GSettings *settings,
+                       const char *key,
                        AisleriotWindow *window)
 {
   AisleriotWindowPrivate *priv = window->priv;
-  ArCardThemeInfo *current_theme_info = NULL, *new_theme_info;
-  ArCardTheme *theme;
   const char *theme_name;
+  ArCardTheme *theme;
 
-  if (!gtk_toggle_action_get_active (action))
-    return;
-
-  new_theme_info = g_object_get_data (G_OBJECT (action), "theme-info");
-  g_assert (new_theme_info != NULL);
-
-  if (priv->theme) {
-    current_theme_info = ar_card_theme_get_theme_info (priv->theme);
-  }
-
-  if (ar_card_theme_info_equal (new_theme_info, current_theme_info))
-    return;
+  g_settings_get (settings, key, "&s", &theme_name);
 
-  theme = ar_card_themes_get_theme (priv->theme_manager, new_theme_info);
+  theme = ar_card_themes_get_theme_by_name (priv->theme_manager, theme_name);
   if (!theme) {
-    GSList *group, *l;
-
-    gtk_widget_error_bell (GTK_WIDGET (window));
-
-    /* Set this action insensitive so we don't try again */
-    gtk_action_set_sensitive (GTK_ACTION (action), FALSE);
-
-    /* Re-set the radio action of the current theme to active */
-    group = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
-    for (l = group; l != NULL; l = l->next) {
-      GtkToggleAction *theme_action = GTK_TOGGLE_ACTION (l->data);
-      ArCardThemeInfo *info;
-
-      if (theme_action == action)
-        continue;
-
-      info = g_object_get_data (G_OBJECT (theme_action), "theme-info");
-      if (!ar_card_theme_info_equal (info, current_theme_info))
-        continue;
-
-      /* The check at the top will prevent an infinite loop */
-      gtk_toggle_action_set_active (theme_action, TRUE);
-      break;
-    }
-
-    return;
-  }
-
-  aisleriot_window_take_card_theme (window, theme);
-
-  theme_name = ar_card_theme_info_get_persistent_name (new_theme_info);
-  g_settings_set_string (priv->settings, AR_SETTINGS_CARD_THEME_KEY, theme_name);
-}
-#endif // 0
-
-static void
-install_card_theme_menu (ArCardThemes *theme_manager,
-                         AisleriotWindow *window)
-{
-#if 0
-  AisleriotWindowPrivate *priv = window->priv;
-  GList *list, *l;
-  GSList *radio_group = NULL;
-  ArCardThemeInfo *current_theme_info;
-  guint i = 0;
-
-  /* Clean out the old menu */
-  if (priv->card_themes_merge_id != 0) {
-    gtk_ui_manager_remove_ui (priv->ui_manager, priv->card_themes_merge_id);
-    priv->card_themes_merge_id = 0;
-  }
-  if (priv->card_themes_group != NULL) {
-    gtk_ui_manager_remove_action_group (priv->ui_manager, priv->card_themes_group);
-    priv->card_themes_group = NULL;
-  }
-
-  /* See gtk bug #424448 */
-  gtk_ui_manager_ensure_update (priv->ui_manager);
-
-  list = ar_card_themes_get_themes (priv->theme_manager);
-
-  /* No need to install the menu when there's only one theme available anyway */
-  if (list == NULL || list->next == NULL) {
-    g_list_foreach (list, (GFunc) ar_card_theme_info_unref, NULL);
-    g_list_free (list);
-    return;
+    /* Last-ditch fallback: try getting *any* theme */
+    theme = ar_card_themes_get_theme_any (priv->theme_manager);
   }
-
-  priv->card_themes_group = gtk_action_group_new ("Theme");
-  gtk_ui_manager_insert_action_group (priv->ui_manager, priv->card_themes_group, -1);
-  g_object_unref (priv->card_themes_group);
-
-  priv->card_themes_merge_id = gtk_ui_manager_new_merge_id (priv->ui_manager);
-
-  if (priv->theme) {
-    current_theme_info = ar_card_theme_get_theme_info (priv->theme);
+  if (theme) {
+    aisleriot_window_take_card_theme (window, theme /* adopts */);
   } else {
-    current_theme_info = NULL;
-  }
-
-  for (l = list; l != NULL; l = l->next) {
-    ArCardThemeInfo *info = (ArCardThemeInfo *) l->data;
-    GtkRadioAction *action;
-    char actionname[32];
-    char *display_name, *tooltip;
-
-    display_name = g_strdup (ar_card_theme_info_get_display_name (info));
-
-    g_snprintf (actionname, sizeof (actionname), "Theme%d", i);
-    tooltip = g_strdup_printf (_("Display cards with ā€œ%sā€ card theme"), display_name);
-    action = gtk_radio_action_new (actionname, display_name, tooltip, NULL, i);
-    g_free (display_name);
-    g_free (tooltip);
-
-    gtk_radio_action_set_group (action, radio_group);
-    radio_group = gtk_radio_action_get_group (action);
-
-    /* Check if this is the current theme's action. Do this before connecting the callback */
-    if (ar_card_theme_info_equal (info, current_theme_info)) {
-      gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
-    }
-
-    /* We steal the data from the list */
-    g_object_set_data_full (G_OBJECT (action), "theme-info",
-                            l->data, (GDestroyNotify) ar_card_theme_info_unref);
-    l->data = NULL;
-
-    g_signal_connect (action, "toggled",
-                      G_CALLBACK (card_theme_changed_cb), window);
-    gtk_action_group_add_action (priv->card_themes_group, GTK_ACTION (action));
-    g_object_unref (action);
-
-    gtk_ui_manager_add_ui (priv->ui_manager,
-                           priv->card_themes_merge_id,
-                           CARD_THEMES_MENU_PATH,
-                           actionname, actionname,
-                           GTK_UI_MANAGER_MENUITEM, FALSE);
-
-    ++i;
+    /* FIXMEchpe: FUCK, what now? Panic! */
+    /* Put up some UI, and exit! */
+    g_assert_not_reached ();
   }
-
-  /* The list elements' data's refcount has been adopted above */
-  g_list_free (list);
-#endif // 0
-}
-
-#if 0 //fixme
-static void
-view_menu_activate_cb (GtkAction *action,
-                       AisleriotWindow *window)
-{
-  AisleriotWindowPrivate *priv = window->priv;
-
-  /* Request the list of themes. If it wasn't updated yet, the "changed"
-   * callback will build the card themes submenu.
-   */
-  ar_card_themes_request_themes (priv->theme_manager);
 }
-#endif
 
 /* Callbacks */
 
@@ -1967,26 +1827,24 @@ aisleriot_window_init (AisleriotWindow *window)
   AisleriotWindowPrivate *priv;
   GtkWidget *main_vbox;
   GAction *action;
-  const char *theme_name;
-  ArCardTheme *theme;
   GtkStatusbar *statusbar;
   GtkWidget *statusbar_hbox, *label, *time_box;
 #ifdef HAVE_CLUTTER
   ClutterContainer *stage;
 #endif
+  ArApplication *app = AR_APP;
 
   priv = window->priv = AISLERIOT_WINDOW_GET_PRIVATE (window);
 
   priv->settings = g_settings_new (AR_SETTINGS_SCHEMA);
 
-  priv->state_settings = ar_application_state_settings_new (AR_APPLICATION (g_application_get_default ()),
-                                                            AR_STATE_SCHEMA);
+  priv->state_settings = ar_application_state_settings_new (app, AR_STATE_SCHEMA);
 
   priv->fullscreen = FALSE;
 
   priv->game = aisleriot_game_new ();
 
-  priv->theme_manager = ar_card_themes_new ();
+  priv->theme_manager = ar_application_get_card_themes (app);
 
   priv->board_style = ar_style_new ();
 
@@ -2019,20 +1877,6 @@ aisleriot_window_init (AisleriotWindow *window)
   priv->board = AISLERIOT_BOARD (aisleriot_board_new (priv->board_style, priv->game));
 #endif /* HAVE_CLUTTER */
 
-  g_settings_get (priv->settings, AR_SETTINGS_CARD_THEME_KEY, "&s", &theme_name);
-  theme = ar_card_themes_get_theme_by_name (priv->theme_manager, theme_name);
-  if (!theme) {
-    /* Last-ditch fallback: try getting *any* theme */
-    theme = ar_card_themes_get_theme_any (priv->theme_manager);
-  }
-  if (theme) {
-    aisleriot_window_take_card_theme (window, theme /* adopts */);
-  } else {
-    /* FIXMEchpe: FUCK, what now? Panic! */
-    /* Put up some UI, and exit! */
-    g_assert_not_reached ();
-  }
-
   /* GAction setup */
   g_action_map_add_action_entries (G_ACTION_MAP (window),
                                    gaction_entries, G_N_ELEMENTS (gaction_entries),
@@ -2102,24 +1946,6 @@ aisleriot_window_init (AisleriotWindow *window)
                                GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
 #endif
 
-#if 0 // fixme
-  /* Defer building the card themes menu until its parent's menu is opened */
-  action = gtk_action_group_get_action (priv->action_group, "ViewMenu");
-  g_signal_connect (action, "activate",
-                    G_CALLBACK (view_menu_activate_cb), window);
-#endif
-
-  /* It's possible that the themes list has already been loaded (e.g.
-   * if the theme loading above involved the fallback); in that case
-   * we need to update the menu right now.
-   */
-  if (ar_card_themes_get_themes_loaded (priv->theme_manager))
-    install_card_theme_menu (priv->theme_manager, window);
-
-  /* Rebuild the themes menu when the themes list changes */
-  g_signal_connect (priv->theme_manager, "changed",
-                    G_CALLBACK (install_card_theme_menu), window);
-
   /* The actions and menus are done. The
    * recent games menu will be updated when the initial game loads.
    */
@@ -2195,6 +2021,10 @@ aisleriot_window_init (AisleriotWindow *window)
                     G_CALLBACK (enable_animations_changed_cb), window);
 #endif
 
+  card_theme_changed_cb (priv->settings, AR_SETTINGS_CARD_THEME_KEY, window);
+  g_signal_connect (priv->settings, "changed::" AR_SETTINGS_CARD_THEME_KEY,
+                    G_CALLBACK (card_theme_changed_cb), window);
+
   /* Restore window state */
   ar_gsettings_bind_window_state (AR_SETTINGS_WINDOW_STATE_PATH, GTK_WINDOW (window));
 
@@ -2247,7 +2077,6 @@ aisleriot_window_dispose (GObject *object)
     priv->load_idle_id = 0;
   }
 
-  g_clear_object (&priv->settings);
   g_clear_object (&priv->state_settings);
   g_clear_object (&priv->game_options_settings);
 
@@ -2264,11 +2093,12 @@ aisleriot_window_finalize (GObject *object)
   g_object_unref (priv->board_style);
 #endif /* HAVE_CLUTTER */
 
-  if (priv->theme) {
-    g_object_unref (priv->theme);
-  }
+  g_clear_object (&priv->theme);
 
-  g_object_unref (priv->theme_manager);
+  g_signal_handlers_disconnect_matched (priv->settings,
+                                        G_SIGNAL_MATCH_DATA,
+                                        0, 0, NULL, NULL, window);
+  g_clear_object (&priv->settings);
 
   g_signal_handlers_disconnect_matched (priv->game,
                                         G_SIGNAL_MATCH_DATA,
diff --git a/src/window.h b/src/window.h
index 0327f87..4b8c791 100644
--- a/src/window.h
+++ b/src/window.h
@@ -61,7 +61,6 @@ void aisleriot_window_change_game (AisleriotWindow * window);
 void aisleriot_window_show_statistics_dialog (AisleriotWindow * window);
 void aisleriot_window_show_about_dialog (AisleriotWindow * window);
 
-
 G_END_DECLS
 
 #endif /* !AISLERIOT_WINDOW_H */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]