[gnome-utils] dictionary: Port to GtkApplication



commit d84f19ae8cd387d1600ece9c4cc50cfeccd5020e
Author: Emmanuele Bassi <ebassi linux intel com>
Date:   Sat Jan 29 18:36:04 2011 +0000

    dictionary: Port to GtkApplication
    
    Use the newly added GApplication and GtkApplication classes, provided by
    GIO and GTK+ respectively, to handle the lifetime of the Dictionary.
    
    This makes the Dictionary a single instance application; new windows are
    created on demand by the running process.

 gnome-dictionary/src/gdict-app.c    |  451 ++++++++++-------------------------
 gnome-dictionary/src/gdict-app.h    |   18 +--
 gnome-dictionary/src/gdict-window.c |   23 ++-
 gnome-dictionary/src/gdict-window.h |    2 +
 gnome-dictionary/src/main.c         |    5 +-
 5 files changed, 150 insertions(+), 349 deletions(-)
---
diff --git a/gnome-dictionary/src/gdict-app.c b/gnome-dictionary/src/gdict-app.c
index 8d41fbc..c744920 100644
--- a/gnome-dictionary/src/gdict-app.c
+++ b/gnome-dictionary/src/gdict-app.c
@@ -40,40 +40,66 @@
 
 static GdictApp *singleton = NULL;
 
-
 struct _GdictAppClass
 {
   GObjectClass parent_class;
 };
 
+G_DEFINE_TYPE (GdictApp, gdict_app, G_TYPE_OBJECT);
 
+static gchar **gdict_lookup_words = NULL;
+static gchar **gdict_match_words = NULL;
 
-G_DEFINE_TYPE (GdictApp, gdict_app, G_TYPE_OBJECT);
+static gchar *gdict_source_name = NULL;
+static gchar *gdict_database_name = NULL;
+static gchar *gdict_strategy_name = NULL;
 
+static GOptionEntry gdict_app_goptions[] = {
+  {
+    "look-up", 0,
+    0,
+    G_OPTION_ARG_STRING_ARRAY, &gdict_lookup_words,
+    N_("Words to look up"), N_("WORD")
+  },
+  {
+    "match", 0,
+    0,
+    G_OPTION_ARG_STRING_ARRAY, &gdict_match_words,
+    N_("Words to match"), N_("WORD")
+  },
+  {
+    "source", 's',
+    0,
+    G_OPTION_ARG_STRING, &gdict_source_name,
+    N_("Dictionary source to use"), N_("NAME")
+  },
+  {
+    "database", 'D',
+    0,
+    G_OPTION_ARG_STRING, &gdict_database_name,
+    N_("Database to use"), N_("NAME")
+  },
+  {
+    "strategy", 'S',
+    0,
+    G_OPTION_ARG_STRING, &gdict_strategy_name,
+    N_("Strategy to use"), N_("NAME")
+  },
+  {
+    G_OPTION_REMAINING, 0, 0,
+    G_OPTION_ARG_STRING_ARRAY, &gdict_lookup_words,
+    N_("Words to look up"), N_("WORDS")
+  },
+  { NULL },
+};
 
 static void
 gdict_app_finalize (GObject *object)
 {
   GdictApp *app = GDICT_APP (object);
-  
+
   if (app->loader)
     g_object_unref (app->loader);
-  
-  app->current_window = NULL;
-  
-  g_slist_foreach (app->windows,
-  		   (GFunc) gtk_widget_destroy,
-  		   NULL);
-  g_slist_free (app->windows);
-
-  g_slist_foreach (app->lookup_words, (GFunc) g_free, NULL);
-  g_slist_free (app->lookup_words);
-
-  g_slist_foreach (app->match_words, (GFunc) g_free, NULL);
-  g_slist_free (app->match_words);
-
-  g_free (app->database);
-  g_free (app->source_name);
 
   G_OBJECT_CLASS (gdict_app_parent_class)->finalize (object);
 }
@@ -89,310 +115,126 @@ gdict_app_class_init (GdictAppClass *klass)
 static void
 gdict_app_init (GdictApp *app)
 {
-  app->windows = NULL;
-  app->current_window = NULL;
 }
 
 static void
-gdict_window_destroy_cb (GtkWidget *widget,
-		         gpointer   user_data)
+gdict_activate (GApplication *application,
+                GdictApp     *gdict_app)
 {
-  GdictWindow *window = GDICT_WINDOW (widget);
-  GdictApp *app = GDICT_APP (user_data);
-  
-  g_assert (GDICT_IS_APP (app));
+  GtkWidget *window;
 
-  app->windows = g_slist_remove (app->windows, window);
-  
-  if (window == app->current_window)
-    app->current_window = app->windows ? app->windows->data : NULL;
-  
-  if (app->windows == NULL)
-    gtk_main_quit ();  
 }
 
-static void
-gdict_window_created_cb (GdictWindow *parent,
-			 GdictWindow *new_window,
-			 gpointer     user_data)
-{
-  GdictApp *app = GDICT_APP (user_data);
-  
-  /* this might seem convoluted - but it's necessary, since I don't want
-   * GdictWindow to know about the GdictApp singleton.  every time a new
-   * window is created by a GdictWindow, it will register its "child window"
-   * here; the lifetime handlers will check every child window created and
-   * destroyed, and will add/remove it to the windows list accordingly
-   */
-  g_signal_connect (new_window, "created",
-  		    G_CALLBACK (gdict_window_created_cb), app);
-  g_signal_connect (new_window, "destroy",
-  		    G_CALLBACK (gdict_window_destroy_cb), app);
-
-  if (gtk_window_get_group (GTK_WINDOW (parent)))
-    gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (parent)),
-		    		 GTK_WINDOW (new_window));
-  
-  app->windows = g_slist_prepend (app->windows, new_window);
-  app->current_window = new_window;
-}
-
-static void
-gdict_create_window (GdictApp *app)
+static int
+gdict_command_line (GApplication *application,
+                    GApplicationCommandLine *cmd_line,
+                    GdictApp                *gdict_app)
 {
+  GOptionContext *context;
+  GError *error;
   GSList *l;
+  gsize words_len, i;
+  gint argc;
+  char **argv;
 
-  if (!singleton->lookup_words && !singleton->match_words)
-    {
-      GtkWidget *window;
+  argv = g_application_command_line_get_arguments (cmd_line, &argc);
 
-      window = gdict_window_new (GDICT_WINDOW_ACTION_CLEAR,
-      				 singleton->loader,
-				 singleton->source_name,
-				 NULL);
-      g_signal_connect (window, "created",
-		        G_CALLBACK (gdict_window_created_cb), app);
-      g_signal_connect (window, "destroy",
-		        G_CALLBACK (gdict_window_destroy_cb), app);
-  
-      app->windows = g_slist_prepend (app->windows, window);
-      app->current_window = GDICT_WINDOW (window);
+  /* create the new option context */
+  context = g_option_context_new (N_(" - Look up words in dictionaries"));
   
+  g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
+  g_option_context_add_main_entries (context, gdict_app_goptions, GETTEXT_PACKAGE);
+  g_option_context_add_group (context, gdict_get_option_group ());
+  g_option_context_add_group (context, gtk_get_option_group (FALSE));
+
+  error = NULL;
+  if (!g_option_context_parse (context, &argc, &argv, &error))
+    {
+      g_critical ("Failed to parse argument: %s", error->message);
+      g_error_free (error);
+      g_option_context_free (context);
+      return 1;
+    }
+
+  g_option_context_free (context);
+
+  if (gdict_lookup_words == NULL &&
+      gdict_match_words == NULL)
+    {
+      GtkWidget *window = gdict_window_new (GDICT_WINDOW_ACTION_CLEAR,
+                                            singleton->loader,
+                                            gdict_source_name,
+                                            gdict_database_name,
+                                            gdict_strategy_name,
+                                            NULL);
+      gtk_window_set_application (GTK_WINDOW (window), singleton->app);
       gtk_widget_show (window);
 
-      return;
+      return 0;
     }
-      
-  for (l = singleton->lookup_words; l != NULL; l = l->next)
+
+  if (gdict_lookup_words != NULL)
+    words_len = g_strv_length (gdict_lookup_words);
+  else
+    words_len = 0;
+
+  for (i = 0; i < words_len; i++)
     {
-      gchar *word = l->data;
+      const gchar *word = gdict_lookup_words[i];
       GtkWidget *window;
 
       window = gdict_window_new (GDICT_WINDOW_ACTION_LOOKUP,
-      				 singleton->loader,
-		      		 singleton->source_name,
-				 word);
+                                 singleton->loader,
+                                 gdict_source_name,
+                                 gdict_database_name,
+                                 gdict_strategy_name,
+                                 word);
       
-      g_signal_connect (window, "created",
-		        G_CALLBACK (gdict_window_created_cb), app);
-      g_signal_connect (window, "destroy",
-		        G_CALLBACK (gdict_window_destroy_cb), app);
-  
-      app->windows = g_slist_prepend (app->windows, window);
-      app->current_window = GDICT_WINDOW (window);
-  
+      gtk_window_set_application (GTK_WINDOW (window), singleton->app);
       gtk_widget_show (window);
     }
 
-  for (l = singleton->match_words; l != NULL; l = l->next)
+  if (gdict_match_words != NULL)
+    words_len = g_strv_length (gdict_match_words);
+  else
+    words_len = 0;
+
+  for (i = 0; i < words_len; i++)
     {
-      gchar *word = l->data;
+      const gchar *word = gdict_match_words[i];
       GtkWidget *window;
 
       window = gdict_window_new (GDICT_WINDOW_ACTION_MATCH,
       				 singleton->loader,
-				 singleton->source_name,
+				 gdict_source_name,
+                                 gdict_database_name,
+                                 gdict_strategy_name,
 				 word);
       
-      g_signal_connect (window, "created",
-      			G_CALLBACK (gdict_window_created_cb), app);
-      g_signal_connect (window, "destroy",
-      			G_CALLBACK (gdict_window_destroy_cb), app);
-      
-      app->windows = g_slist_prepend (app->windows, window);
-      app->current_window = GDICT_WINDOW (window);
-
+      gtk_window_set_application (GTK_WINDOW (window), singleton->app);
       gtk_widget_show (window);
     }
-}
-
-static void
-definition_found_cb (GdictContext    *context,
-		     GdictDefinition *definition,
-		     gpointer         user_data)
-{
-  /* Translators: the first is the word found, the second is the
-   * database name and the last is the definition's text; please
-   * keep the new lines. */
-  g_print (_("Definition for '%s'\n"
-	     "  From '%s':\n"
-	     "\n"
-	     "%s\n"),
-           gdict_definition_get_word (definition),
-	   gdict_definition_get_database (definition),
-	   gdict_definition_get_text (definition));
-}
-
-static void
-error_cb (GdictContext *context,
-          const GError *error,
-	  gpointer      user_data)
-{
-  g_print (_("Error: %s\n"), error->message);
-
-  gtk_main_quit ();
-}
-
-static void
-lookup_end_cb (GdictContext *context,
-	       gpointer      user_data)
-{
-  GdictApp *app = GDICT_APP (user_data);
-
-  app->remaining_words -= 1;
 
-  if (app->remaining_words == 0)
-    gtk_main_quit ();
-}
-
-static void
-gdict_look_up_word_and_quit (GdictApp *app)
-{
-  GdictSource *source;
-  GdictContext *context;
-  GSList *l;
-  
-  if ((!app->lookup_words) || (!app->match_words))
-    {
-      g_print (_("See gnome-dictionary --help for usage\n"));
-
-      gdict_cleanup ();
-      exit (1);
-    }
-
-  if (app->source_name)
-    source = gdict_source_loader_get_source (app->loader, app->source_name);
-  else
-    source = gdict_source_loader_get_source (app->loader, GDICT_DEFAULT_SOURCE_NAME);
-
-  if (!source)
-    {
-      g_warning (_("Unable to find a suitable dictionary source"));
-
-      gdict_cleanup ();
-      exit (1);
-    }
-
-  /* we'll just use this one context, so we can destroy it along with
-   * the source that contains it
-   */
-  context = gdict_source_peek_context (source);
-  g_assert (GDICT_IS_CONTEXT (context));
-
-  g_signal_connect (context, "definition-found",
-		    G_CALLBACK (definition_found_cb), app);
-  g_signal_connect (context, "error",
-		    G_CALLBACK (error_cb), app);
-  g_signal_connect (context, "lookup-end",
-		    G_CALLBACK (lookup_end_cb), app);
-
-  app->remaining_words = 0;
-  for (l = app->lookup_words; l != NULL; l = l->next)
-    {
-      gchar *word = l->data;
-      GError *err = NULL;
-
-      app->remaining_words += 1;
-
-      gdict_context_define_word (context,
-		      		 app->database,
-				 word,
-				 &err);
-
-      if (err)
-	{
-          g_warning (_("Error while looking up the definition of \"%s\":\n%s"),
-		     word,
-		     err->message);
-
-	  g_error_free (err);
-	}
-    }
-
-  gtk_main ();
-
-  g_object_unref (source);
-
-  gdict_cleanup ();
-  exit (0);
+  return 0;
 }
 
 void
-gdict_init (int *argc, char ***argv)
+gdict_main (int    *argc,
+            char ***argv)
 {
-  GError *err = NULL;
-  GOptionContext *context;
   gchar *loader_path;
-  gchar **lookup_words = NULL;
-  gchar **match_words = NULL;
-  gchar *database = NULL;
-  gchar *strategy = NULL;
-  gchar *source_name = NULL;
-  gboolean no_window = FALSE;
-  gboolean list_sources = FALSE;
-
-  const GOptionEntry gdict_app_goptions[] =
-  {
-    { "look-up", 0, 0, G_OPTION_ARG_STRING_ARRAY, &lookup_words,
-       N_("Words to look up"), N_("word") },
-    { "match", 0, 0, G_OPTION_ARG_STRING_ARRAY, &match_words,
-       N_("Words to match"), N_("word") },
-    { "source", 's', 0, G_OPTION_ARG_STRING, &source_name,
-       N_("Dictionary source to use"), N_("source") },
-    { "list-sources", 'l', 0, G_OPTION_ARG_NONE, &list_sources,
-       N_("Show available dictionary sources"), NULL },
-    { "no-window", 'n', 0, G_OPTION_ARG_NONE, &no_window,
-       N_("Print result to the console"), NULL },
-    { "database", 'D', 0, G_OPTION_ARG_STRING, &database,
-       N_("Database to use"), N_("db") },
-    { "strategy", 'S', 0, G_OPTION_ARG_STRING, &strategy,
-       N_("Strategy to use"), N_("strat") },
-    { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &lookup_words,
-       N_("Words to look up"), N_("word") },
-    { NULL },
-  };
-  
-  /* we must have GLib's type system up and running in order to create the
-   * singleton object for gnome-dictionary; thus, we can't rely on
-   * gnome_program_init() calling g_type_init() for us.
-   */
-  g_type_init ();
 
-  g_assert (singleton == NULL);  
-  
-  singleton = GDICT_APP (g_object_new (GDICT_TYPE_APP, NULL));
-  g_assert (GDICT_IS_APP (singleton));
-  
-  /* create the new option context */
-  context = g_option_context_new (_(" - Look up words in dictionaries"));
-  
-  g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
-  g_option_context_add_main_entries (context, gdict_app_goptions, GETTEXT_PACKAGE);
-  g_option_context_add_group (context, gdict_get_option_group ());
-  g_option_context_add_group (context, gtk_get_option_group (TRUE));
+  if (!gdict_create_data_dir ())
+    exit (1);
 
-  g_option_context_parse (context, argc, argv, &err);
-  if (err)
-    {
-      g_critical ("Failed to parse argument: %s", err->message);
-      g_error_free (err);
-      g_option_context_free (context);
-      gdict_cleanup ();
+  g_type_init ();
+  gtk_init (argc, argv);
 
-      exit (1);
-    }
-  
   g_set_application_name (_("Dictionary"));
   gtk_window_set_default_icon_name ("accessories-dictionary");
-  
-  if (!gdict_create_data_dir ())
-    {
-      gdict_cleanup ();
-
-      exit (1);
-    }
 
-  singleton->settings = g_settings_new ("org.gnome.dictionary");
+  /* the main application instance */
+  singleton = g_object_new (gdict_app_get_type (), NULL);
 
   /* add user's path for fetching dictionary sources */  
   singleton->loader = gdict_source_loader_new ();
@@ -400,54 +242,10 @@ gdict_init (int *argc, char ***argv)
   gdict_source_loader_add_search_path (singleton->loader, loader_path);
   g_free (loader_path);
 
-  if (lookup_words)
-    {
-      gsize i;
-      gsize length = g_strv_length (lookup_words);
-
-      for (i = 0; i < length; i++)
-	singleton->lookup_words = g_slist_prepend (singleton->lookup_words,
-			                           g_strdup (lookup_words[i]));
-    }
-
-  if (match_words)
-    {
-      gsize i;
-      gsize length = g_strv_length (match_words);
-
-      for (i = 0; i < length; i++)
-        singleton->match_words = g_slist_prepend (singleton->match_words,
-			                          g_strdup (match_words[i]));
-    }
-
-  if (database)
-    singleton->database = g_strdup (database);
-  
-  if (source_name)
-    singleton->source_name = g_strdup (source_name);
-
-  if (no_window)
-    singleton->no_window = TRUE;
+  singleton->app = gtk_application_new ("org.gnome.Dictionary", G_APPLICATION_HANDLES_COMMAND_LINE);
+  g_signal_connect (singleton->app, "command-line", G_CALLBACK (gdict_command_line), singleton);
 
-  if (list_sources)
-    singleton->list_sources = TRUE;
-}
-
-void
-gdict_main (void)
-{
-  if (!singleton)
-    {
-      g_warning ("You must initialize GdictApp using gdict_init()\n");
-      return;
-    }
-  
-  if (!singleton->no_window)
-    gdict_create_window (singleton);
-  else
-    gdict_look_up_word_and_quit (singleton);
-  
-  gtk_main ();
+  g_application_run (G_APPLICATION (singleton->app), *argc, *argv);
 }
 
 void
@@ -459,5 +257,6 @@ gdict_cleanup (void)
       return;
     }
 
+  g_object_unref (singleton->app);
   g_object_unref (singleton);
 }
diff --git a/gnome-dictionary/src/gdict-app.h b/gnome-dictionary/src/gdict-app.h
index e70d585..5223b0f 100644
--- a/gnome-dictionary/src/gdict-app.h
+++ b/gnome-dictionary/src/gdict-app.h
@@ -23,7 +23,6 @@
 #ifndef __GDICT_APP_H__
 #define __GDICT_APP_H__
 
-#include <gio/gio.h>
 #include <gtk/gtk.h>
 #include <libgdict/gdict.h>
 
@@ -43,28 +42,15 @@ struct _GdictApp
 {
   GObject parent_instance;
 
-  GSettings *settings;
+  GtkApplication *app;
 
-  GSList *lookup_words;
-  GSList *match_words;
-  gint remaining_words;
-  
-  gchar *database;
-  gchar *source_name;
-  gboolean no_window;
-  gboolean list_sources;
-  
   GdictSourceLoader *loader;
-
-  GdictWindow *current_window;
-  GSList *windows;  
 };
 
 
 GType      gdict_app_get_type    (void) G_GNUC_CONST;
 
-void       gdict_init            (int *argc, char ***argv);
-void       gdict_main            (void);
+void       gdict_main            (int *argc, char ***argv);
 void       gdict_cleanup         (void);
 
 G_END_DECLS
diff --git a/gnome-dictionary/src/gdict-window.c b/gnome-dictionary/src/gdict-window.c
index d84d4a6..a114e7a 100644
--- a/gnome-dictionary/src/gdict-window.c
+++ b/gnome-dictionary/src/gdict-window.c
@@ -925,13 +925,19 @@ gdict_window_cmd_file_new (GtkAction   *action,
     {
       new_window = gdict_window_new (GDICT_WINDOW_ACTION_LOOKUP,
                                      window->loader,
-                                     NULL, word);
+                                     NULL,
+                                     NULL,
+                                     NULL,
+                                     word);
       g_free (word);
     }
   else
     new_window = gdict_window_new (GDICT_WINDOW_ACTION_CLEAR,
                                    window->loader,
-                                   NULL, NULL);
+                                   NULL,
+                                   NULL,
+                                   NULL,
+                                   NULL);
 
   gtk_widget_show (new_window);
   
@@ -1530,7 +1536,10 @@ gdict_window_link_clicked (GdictDefbox *defbox,
 
   new_window = gdict_window_new (GDICT_WINDOW_ACTION_LOOKUP,
                                  window->loader,
-                                 NULL, link_text);
+                                 NULL,
+                                 NULL,
+                                 NULL,
+                                 link_text);
   gtk_widget_show (new_window);
   
   g_signal_emit (window, gdict_window_signals[CREATED], 0, new_window);
@@ -2100,6 +2109,8 @@ GtkWidget *
 gdict_window_new (GdictWindowAction  action,
 		  GdictSourceLoader *loader,
 		  const gchar       *source_name,
+                  const gchar       *database_name,
+                  const gchar       *strategy_name,
 		  const gchar       *word)
 {
   GtkWidget *retval;
@@ -2111,6 +2122,8 @@ gdict_window_new (GdictWindowAction  action,
   			 "action", action,
                          "source-loader", loader,
 			 "source-name", source_name,
+                         "database", database_name,
+                         "strategy", strategy_name,
 			 NULL);
 
   window = GDICT_WINDOW (retval);
@@ -2123,6 +2136,7 @@ gdict_window_new (GdictWindowAction  action,
 	  gtk_entry_set_text (GTK_ENTRY (window->entry), word);
 	  gdict_window_set_word (window, word, NULL);
 	  break;
+
 	case GDICT_WINDOW_ACTION_MATCH:
           {
           GdictSource *source;
@@ -2152,9 +2166,12 @@ gdict_window_new (GdictWindowAction  action,
       
           gdict_speller_match (GDICT_SPELLER (window->speller), word);
           }
+          break;
+
 	case GDICT_WINDOW_ACTION_CLEAR:
           gdict_defbox_clear (GDICT_DEFBOX (window->defbox));
 	  break;
+
 	default:
 	  g_assert_not_reached ();
 	  break;
diff --git a/gnome-dictionary/src/gdict-window.h b/gnome-dictionary/src/gdict-window.h
index 8c35670..74b65e6 100644
--- a/gnome-dictionary/src/gdict-window.h
+++ b/gnome-dictionary/src/gdict-window.h
@@ -128,6 +128,8 @@ GType      gdict_window_get_type (void) G_GNUC_CONST;
 GtkWidget *gdict_window_new      (GdictWindowAction  action,
 				  GdictSourceLoader *loader,
 				  const gchar       *source_name,
+                                  const gchar       *database_name,
+                                  const gchar       *strategy_name,
 				  const gchar       *word);
 
 #endif /* __GDICT_WINDOW_H__ */
diff --git a/gnome-dictionary/src/main.c b/gnome-dictionary/src/main.c
index 669f050..5db8abc 100644
--- a/gnome-dictionary/src/main.c
+++ b/gnome-dictionary/src/main.c
@@ -14,10 +14,7 @@ int main (int argc, char *argv[])
         bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
         textdomain (GETTEXT_PACKAGE);
 
-	gdict_init (&argc, &argv);
-	
-	gdict_main ();
-
+	gdict_main (&argc, &argv);
 	gdict_cleanup ();
 	
 	return EXIT_SUCCESS;



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