Dictionary search extension



Hi Epiphany team,

I just completed an extension for Epiphany (1.2.x) based on Dictionary Search extension for Mozilla/Firefox.

The goal: 
To provide a very easy way to lookup or translate a word in a webpage in a user defineable online dictionary. 

How: 
Simply select the word of which you want to know the meaning. Then right click and select "Dictionary->My dictionary". A new window will open with the meaning or translation of the word you selected.
Dictionary means an url like: http://dictionary.cambridge.org/results.asp?searchword=$&dict=E where $ is replaced by the selected word.

Design:
Dictionaries are stored in gconf registry as string list. Menus that appear in context menu too, in the same order as of dictionaries.

Because it is my first extension, may i ask the team to check my code ?

Issues:
There is no UI at time. But would be easy to develop.
DictionaySearch extension doesn't work with Frame, but I known to do that.

JFR
/*
 *  Copyright (C) 2003 Marco Pesenti Gritti
 *  Copyright (C) 2003 Christian Persch
 *  Copyright (C) 2004 Jean-François Rameau
 *
 *  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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 *  $Id$
 */

#ifndef DICTIONARY_SEARCH_EXTENSION_H
#define DICTIONARY_SEARCH_EXTENSION_H

#include <glib.h>
#include <glib-object.h>

G_BEGIN_DECLS

#define TYPE_DICTIONARY_SEARCH_EXTENSION	  (dictionary_search_extension_get_type ())
#define DICTIONARY_SEARCH_EXTENSION(o)		  (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_DICTIONARY_SEARCH_EXTENSION, DictionarySearchExtension))
#define DICTIONARY_SEARCH_EXTENSION_CLASS(k)	  (G_TYPE_CHECK_CLASS_CAST((k), TYPE_DICTIONARY_SEARCH_EXTENSION, DictionarySearchExtensionClass))
#define IS_DICTIONARY_SEARCH_EXTENSION(o)	  (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_DICTIONARY_SEARCH_EXTENSION))
#define IS_DICTIONARY_SEARCH_EXTENSION_CLASS(k)	  (G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_DICTIONARY_SEARCH_EXTENSION))
#define DICTIONARY_SEARCH_EXTENSION_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_DICTIONARY_SEARCH_EXTENSION, DictionarySearchExtensionClass))

typedef struct DictionarySearchExtension	DictionarySearchExtension;
typedef struct DictionarySearchExtensionClass	DictionarySearchExtensionClass;
typedef struct DictionarySearchExtensionPrivate	DictionarySearchExtensionPrivate;

struct DictionarySearchExtensionClass
{
	GObjectClass parent_class;
};

struct DictionarySearchExtension
{
	GObject parent_instance;

	DictionarySearchExtensionPrivate *priv;
};

GType	ephy_dictionary_search_extension_get_type	(void);

GType	ephy_dictionary_search_extension_register_type	(GTypeModule *module);

G_END_DECLS

#endif
/*
 *  Copyright (C) 2003 Marco Pesenti Gritti
 *  Copyright (C) 2003 Christian Persch
 *  Copyright (C) 2004 Jean-François Rameau
 *
 *  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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 *  $Id$
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "dictionary-search-extension.h"
#include "ephy-debug.h"
#include <epiphany/ephy-extension.h>
#include <epiphany/ephy-command-manager.h>
#include <epiphany/ephy-shell.h>
#include "eel-gconf-extensions.h"

#include <gmodule.h>
#include <gtk/gtk.h>
#include <gtk/gtkuimanager.h>
#include <gtk/gtkactiongroup.h>
#include <gtk/gtkaction.h>
#include <glib/gi18n-lib.h>
#include <gtk/gtkclipboard.h>

#define DICTIONARY_SEARCH_EXTENSION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), TYPE_DICTIONARY_SEARCH_EXTENSION, DictionarySearchExtensionPrivate))

#define CONF_DICTIONARIES "/apps/epiphany/extension/dictionarysearch/dictionaries"
#define CONF_MENUS        "/apps/epiphany/extension/dictionarysearch/menu_items"

#define LOG(x) printf(x);printf("\n");

struct DictionarySearchExtensionPrivate
{
};

static void dictionary_search_extension_class_init (DictionarySearchExtensionClass *klass);
static void dictionary_search_extension_iface_init (EphyExtensionIface *iface);
static void dictionary_search_extension_init       (DictionarySearchExtension *extension);

enum
{
	PROP_0
};

static GObjectClass *parent_class = NULL;

static GType type = 0;

GType
dictionary_search_extension_get_type (void)
{
	return type;
}

GType
dictionary_search_extension_register_type (GTypeModule *module)
{
	static const GTypeInfo our_info =
	{
		sizeof (DictionarySearchExtensionClass),
		NULL, /* base_init */
		NULL, /* base_finalize */
		(GClassInitFunc) dictionary_search_extension_class_init,
		NULL,
		NULL, /* class_data */
		sizeof (DictionarySearchExtension),
		0, /* n_preallocs */
		(GInstanceInitFunc) dictionary_search_extension_init
	};

	static const GInterfaceInfo extension_info =
	{
		(GInterfaceInitFunc) dictionary_search_extension_iface_init,
		NULL,
		NULL
	};

	type = g_type_module_register_type (module,
					    G_TYPE_OBJECT,
					    "DictionarySearchExtension",
					    &our_info, 0);

	g_type_module_add_interface (module,
				     type,
				     EPHY_TYPE_EXTENSION,
				     &extension_info);

	return type;
}

static void
dictionary_search_extension_init (DictionarySearchExtension *extension)
{
	extension->priv = DICTIONARY_SEARCH_EXTENSION_GET_PRIVATE (extension);

	LOG ("DictionarySearchExtension initialising")
}

static void
dictionary_search_extension_finalize (GObject *object)
{
	LOG ("DictionarySearchExtension finalising")

	G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
clipboard_text_received_cb (GtkClipboard *clipboard,
			    const char *text,
			    gpointer *ptr)
{
  GSList *dicos_url, *dicos_lbl, *du, *dl;
  gchar **cutter, *a_dico, *url;
  const gchar *action_lbl;
  GtkAction *action;    

  action = (GtkAction *)ptr;

  dicos_url = eel_gconf_get_string_list (CONF_DICTIONARIES); 
  dicos_lbl = eel_gconf_get_string_list (CONF_MENUS); 
  
  /* We have to search for this action */
  action_lbl = gtk_action_get_name(action);

  for (dl=dicos_lbl,du=dicos_url; dl != NULL && du != NULL; dl=dl->next, du=du->next)
  {
    if (strcmp((const char *)dl->data, action_lbl) == 0)
    {
      /* User selected this one */
      a_dico = (char *)(du->data);

      break;
    }
  }

  /* Replace $ by the selected word */
  cutter = g_strsplit (a_dico, "$", 0);
  url = g_strconcat (cutter[0], text, cutter[1], NULL);
   
  ephy_shell_new_tab (ephy_shell, NULL, NULL, url,
                      EPHY_NEW_TAB_OPEN_PAGE | EPHY_NEW_TAB_IN_NEW_WINDOW);

  g_strfreev (cutter);
  g_slist_foreach (dicos_url, (GFunc) g_free, NULL);
  g_slist_free (dicos_url);
  g_slist_foreach (dicos_lbl, (GFunc) g_free, NULL);
  g_slist_free (dicos_lbl);
}

static void dico_cb (GtkAction *action,
		     EphyWindow *window)
{
  EphyEmbed *embed;

  embed = ephy_window_get_active_embed (window);
  g_return_if_fail (EPHY_IS_EMBED (embed));

  ephy_command_manager_do_command (EPHY_COMMAND_MANAGER (embed), "cmd_copy");

  gtk_clipboard_request_text (gtk_widget_get_clipboard (GTK_WIDGET (embed),
			      GDK_SELECTION_CLIPBOARD),
			      (GtkClipboardTextReceivedFunc) clipboard_text_received_cb,
			      action);
}

static void
context_menu_cb (EphyEmbed *embed,
		 EphyEmbedEvent *event,
		 DictionarySearchExtension *extension)
{
  EphyWindow *window;
  EphyTab    *tab;
  gboolean    can_copy;
  GtkAction  *action;
  GtkUIManager *manager;
  GList      *list, *elt;
  GtkActionGroup *action_group;

  can_copy = ephy_command_manager_can_do_command(EPHY_COMMAND_MANAGER(embed), "cmd_copy");

  tab = ephy_tab_for_embed (embed);
  g_return_if_fail (EPHY_IS_TAB (tab));

  window = ephy_tab_get_window (tab);
  g_return_if_fail (EPHY_IS_WINDOW (window));

  manager = GTK_UI_MANAGER (window->ui_merge);

  list = gtk_ui_manager_get_action_groups (manager);

  action_group = NULL;

  for (elt = list; elt != NULL; elt = elt->next)
  {
    action_group = GTK_ACTION_GROUP (elt->data);

    if (strcmp("DicoExtension", gtk_action_group_get_name (action_group)) == 0)
    {
      break;
    }
  }

  action = gtk_action_group_get_action (action_group, "DicoEntry");

  if (action)
    g_object_set(action, "sensitive", can_copy, "visible", can_copy, NULL);
}

static void
tab_added_cb (GtkWidget *notebook,
	      EphyTab *tab,
	      DictionarySearchExtension *extension)
{
	EphyEmbed *embed;

	g_return_if_fail (EPHY_IS_TAB (tab));

	embed = ephy_tab_get_embed (tab);
	g_return_if_fail (EPHY_IS_EMBED (embed));

	g_signal_connect (embed, "ge_context_menu",
			  G_CALLBACK (context_menu_cb), extension);
}

static void
tab_removed_cb (EphyEmbed *notebook,
		EphyTab *tab,
		DictionarySearchExtension *extension)
{
	EphyEmbed *embed;

	g_return_if_fail (EPHY_IS_TAB (tab));

	embed = ephy_tab_get_embed (tab);
	g_return_if_fail (EPHY_IS_EMBED (embed));

	g_signal_handlers_disconnect_by_func
		(embed, G_CALLBACK (context_menu_cb), extension);
}

static void
impl_attach_window (EphyExtension *ext,
		    EphyWindow *window)
{
  GtkWidget *notebook;
  GtkUIManager *manager;
  GtkActionGroup *action_group;
  guint ui_id, n_entries,i;
  GtkActionEntry *entries;
  GSList *dicos, *l;
  gchar  *a_dico;

  LOG ("DictionarySearchExtension attach_window")

  notebook = ephy_window_get_notebook (window);

  g_signal_connect_after (notebook, "tab_added",
      G_CALLBACK (tab_added_cb), ext);
  g_signal_connect_after (notebook, "tab_removed",
      G_CALLBACK (tab_removed_cb), ext);

  /* Add ui */
  manager = GTK_UI_MANAGER (window->ui_merge);

  action_group = gtk_action_group_new ("DicoExtension");
  gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);

  /* Add dictionary entries */
  dicos = eel_gconf_get_string_list (CONF_MENUS);

  /* + 1 means sub menu entries + menu entry itself */
  n_entries = g_slist_length (dicos) + 1;
  entries = g_new0(GtkActionEntry, n_entries);
    
  entries[0].name = "DicoEntry"; entries[0].label = N_("Dictionary");

  for (l=dicos,i=1; l != NULL; l = l->next,i++)
  {
    a_dico = (gchar *)(l->data);

    entries[i].name = a_dico;
    entries[i].label = a_dico;
    entries[i].callback = G_CALLBACK(dico_cb);
  }

  gtk_action_group_add_actions (action_group, entries, n_entries, window);

  gtk_ui_manager_insert_action_group (manager, action_group, 0),
  g_object_unref (action_group);

  ui_id = gtk_ui_manager_new_merge_id( manager);

  gtk_ui_manager_add_ui (manager, ui_id, "/EphyDocumentPopup",
                         "ViewSCSep1", NULL, GTK_UI_MANAGER_SEPARATOR, FALSE);
  gtk_ui_manager_add_ui (manager, ui_id, "/EphyDocumentPopup",
                         "DicoEntry", "DicoEntry", GTK_UI_MANAGER_MENU, FALSE);

  for (l=dicos,i=0; l != NULL; l = l->next,i++)
  {
    a_dico = (gchar *)(l->data);

    gtk_ui_manager_add_ui (manager, ui_id, "/EphyDocumentPopup/DicoEntry",
                         a_dico, a_dico, GTK_UI_MANAGER_MENUITEM, FALSE);
  }

  g_slist_foreach (dicos, (GFunc) g_free, NULL);
  g_slist_free (dicos);
  g_free(entries);
}

static void
impl_detach_window (EphyExtension *ext,
		    EphyWindow *window)
{
	GtkWidget *notebook;

	LOG ("DictionarySearchExtension detach_window")

	notebook = ephy_window_get_notebook (window);

	g_signal_handlers_disconnect_by_func
		(notebook, G_CALLBACK (tab_added_cb), ext);
	g_signal_handlers_disconnect_by_func
		(notebook, G_CALLBACK (tab_removed_cb), ext);
}

static void
dictionary_search_extension_iface_init (EphyExtensionIface *iface)
{
	iface->attach_window = impl_attach_window;
	iface->detach_window = impl_detach_window;
}

static void
dictionary_search_extension_class_init (DictionarySearchExtensionClass *klass)
{
	GObjectClass *object_class = G_OBJECT_CLASS (klass);

	parent_class = g_type_class_peek_parent (klass);

	object_class->finalize = dictionary_search_extension_finalize;

	g_type_class_add_private (object_class, sizeof (DictionarySearchExtensionPrivate));
}
/*
 *  Copyright (C) 2003 Marco Pesenti Gritti
 *  Copyright (C) 2003 Christian Persch
 *  Copyright (C) 2004 Jean-François Rameau
 *
 *  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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 *  $Id$
 */

#include "dictionary-search-extension.h"
#include "ephy-debug.h"

#include <gmodule.h>

G_MODULE_EXPORT GType
register_module (GTypeModule *module)
{
	LOG ("Registering Dictionary Search Extension")

	return dictionary_search_extension_register_type (module);
}


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