/* Copyright (C) 2005 Emmanuele Bassi
*
* This file is part of MATE Utils.
*
* MATE Utils 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.
*
* MATE Utils 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 MATE Utils. If not, see .
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include "gdict-common.h"
#include "gdict-pref-dialog.h"
#include "gdict-app.h"
static GdictApp *singleton = NULL;
struct _GdictAppClass
{
GObjectClass parent_class;
};
G_DEFINE_TYPE (GdictApp, gdict_app, G_TYPE_OBJECT);
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_free_full (app->windows, (GDestroyNotify) gtk_widget_destroy);
g_slist_free_full (app->lookup_words, g_free);
g_slist_free_full (app->match_words, g_free);
g_free (app->database);
g_free (app->source_name);
G_OBJECT_CLASS (gdict_app_parent_class)->finalize (object);
}
static void
gdict_app_class_init (GdictAppClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = gdict_app_finalize;
}
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)
{
GdictWindow *window = GDICT_WINDOW (widget);
GdictApp *app = GDICT_APP (user_data);
g_assert (GDICT_IS_APP (app));
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)
{
GSList *l;
if (!singleton->lookup_words && !singleton->match_words)
{
GtkWidget *window;
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);
gtk_widget_show (window);
return;
}
for (l = singleton->lookup_words; l != NULL; l = l->next)
{
gchar *word = l->data;
GtkWidget *window;
window = gdict_window_new (GDICT_WINDOW_ACTION_LOOKUP,
singleton->loader,
singleton->source_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_widget_show (window);
}
for (l = singleton->match_words; l != NULL; l = l->next)
{
gchar *word = l->data;
GtkWidget *window;
window = gdict_window_new (GDICT_WINDOW_ACTION_MATCH,
singleton->loader,
singleton->source_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_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)
{
g_print (_("See mate-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);
}
void
gdict_init (int *argc, char ***argv)
{
GError *err = NULL;
GOptionContext *context;
gchar *loader_path;
gchar **lookup_words = NULL;
gchar **match_words = NULL;
gchar *database = NULL;
gchar *source_name = NULL;
gboolean no_window = 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") },
{ "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") },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &lookup_words,
N_("Words to look up"), N_("word") },
{ NULL },
};
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));
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 ();
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.mate.dictionary");
/* add user's path for fetching dictionary sources */
singleton->loader = gdict_source_loader_new ();
loader_path = gdict_get_data_dir ();
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;
}
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 ();
}
void
gdict_cleanup (void)
{
if (!singleton)
{
g_warning ("You must initialize GdictApp using gdict_init()\n");
return;
}
g_object_unref (singleton);
}