First weekly status report on GNOME Dictionary



[Cc:-ing desktop-devel, and with my Flame-Resistant,
I-Can't-Believe-It's-Not-Asbestos jacket on]

Hi all.

In order to let others know how's the status of GNOME Dictionary
Breaking is progressing (and in order to force myself hacking on it
regularly ;-)), I'm sending the

	Not So Weekly Status Report on GNOME Dictionary

Containing the status of the review-slash-breaking-slash-rewrite process
of the GNOME Dictionary application and applet.  Okay, it won't be
weekly, and I could simply use my blog (see signature and link on
Vincent's own blog) instead of email; nevertheless, having someone to
report to makes room for public discussion, and since I'm breaking
(mostly) working stuff better be sure that some discussion actually
happens at all.

So, what have you been doing so far?
====================================

First of all, I tried to salvage the ugly mess that was implementing the
dictionary protocol (gnome-utils/gdictsrc/dict.[ch]).  For the lack of
better (or non 12-years-old-sister safe) words, I won't use the ones I
came up while auditing the said code.  Suffice is to say that the code
couldn't be salvaged without a massive rewrite process anyway, so I
scrapped out the implementation, and created a new, GObject-based one.
You can see a preliminary version of the API usage on my weblog[1]; I've
also attached to this mail the GdictContext API, for reference.  How's
the rewrite going?  I've pretty much implemented all the needed client
commands for a RFC2229-compliant client, testing it both on dict.org and
on my local dictionary server.  The MATCH command is still missing, but
I evaluate that will be a matter of 15 minutes worth of coding, in the
new infrastructure.  About the new infrastructure: I'm pretty proud of
my implementation; for example, now the client will advertise itself
(using a predefined string or a custom one), and all the commands get
queued; thus, you can set up a batch of commands (connect-lookup
databases-lookup strategies-disconnect) without having to actually
*wait* inside the callback for a command to complete its run.  This will
allow lazy data loading, and close one of my pet peeves about the
current GNOME Dictionary, that is the absence of a CLI output; I'd like
to write into a terminal:

	$ gnome-dictionary --lookup "GNOME" --no-window

and have my definition of "GNOME" with no fuss (yes, I know that there
already is "dict", but what's the point of having a dictionary client in
GNOME if I also have to install dict?).

Another point of the new infrastructure is that lives all inside a
shared library; which means that we can now have the much needed
separation between the back-end code and the UI and the
application/applet.  Also, this means we can provide language bindings
for it, allowing other applications to interface to dictionary servers
(and I specifically thinking about the Deskbar Applet, here, even though
I think there already is a dictionary protocol implementation in Python,
using one based only on platform stuff would shorten the dependency
chain).

What are you planning to do next?
=================================

First of all, finishing the client implementation (also, authentication
could be added, if I can come up with a UI for it); adding a way to get
some data like server's capabilities; caching of the databases and
strategies lists, etc.  Also, I'll do some code polishing and
consolidation.  This shouldn't take long - probably no more than a week.

The UI is what comes next.  The GdictEntry will be the first to be
checked; I'd like to use the SexyIconEntry by Christian Hammond[2] as a
base for this widget, in order to have something more appealing (for the
applet, mostly)- but first I've got to check out how it behaves with
GtkEntryCompletion.

The next widget to be targeted will be GdictSpeller; I'm still dubious
about the form of this widget, or if it's useful at all.

Finally, GdictDefbox.  The main widget is pretty much right as it is, so
I'll just update it in order to use the new GdictContext; I'll move the
"find" dialog into a bottom pane a-la-Firefox, and I think that will be
the most relevant change, UI-wise.

This would complete the road-map for the GNOME Dictionary Library
(libgdict): the application and the applet would simply fall into place,
once this has been sorted out.

When do we see the code?
========================

This is the worst part of all.  Since I'm basically rewriting
everything, up until I can actually provide a working version of GNOME
Dictionary I'd like not to taint the CVS repository; but I also
understand the need for looking at the code, and comment on it - so, as
soon as I'm able to create a full *text* client using libgdict, I'll
upload a tarball of it on my web space.  If it passes a review from the
gnome-utils maintainer, I'll begin by creating a branch of gnome-utils
HEAD with the new code, and keep working on it.

As usual, comments, questions and flames here on the list or in private
mail.

Ciao,
 Emmanuele.

+++

[1] http://log.emmanuelebassi.net/2005/11/07/dictionary-applet3/
[2] http://wiki.chipx86.com/wiki/Libsexy#SexyIconEntry

-- 
Emmanuele Bassi - <ebassi gmail com>
Log: http://log.emmanuelebassi.net
/* gdict-context.h - Implementation of a dictionary protocol client class
 *
 * Copyright (C) 2005  Emmanuele Bassi <ebassi gmail com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 */

#ifndef __GDICT_CONTEXT_H__
#define __GDICT_CONTEXT_H__

#include <glib-object.h>

G_BEGIN_DECLS

#define GDICT_TYPE_MATCH		(gdict_match_get_type ())
#define GDICT_TYPE_DEFINITION		(gdict_definition_get_type ())
#define GDICT_TYPE_DATABASE		(gdict_database_get_type ())
#define GDICT_TYPE_STRATEGY		(gdict_strategy_get_type ())

#define GDICT_TYPE_CONTEXT		(gdict_context_get_type ())
#define GDICT_CONTEXT(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GDICT_TYPE_CONTEXT, GdictContext))
#define GDICT_IS_CONTEXT(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDICT_TYPE_CONTEXT))
#define GDICT_CONTEXT_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass), GDICT_TYPE_CONTEXT, GdictContextClass))
#define GDICT_IS_CONTEXT_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), GDICT_TYPE_CONTEXT))
#define GDICT_CONTEXT_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), GDICT_TYPE_CONTEXT, GdictContextClass))


#define GDICT_CONTEXT_ERROR	(gdict_context_error_get_quark ())
typedef enum {
  GDICT_CONTEXT_ERROR_SOCKET,
  GDICT_CONTEXT_ERROR_LOOKUP,
  GDICT_CONTEXT_ERROR_NO_CONNECTION,
  GDICT_CONTEXT_ERROR_PARSE,
  GDICT_CONTEXT_ERROR_SERVER_DOWN,
  GDICT_CONTEXT_ERROR_NO_ACCESS,
  GDICT_CONTEXT_ERROR_NOT_IMPLEMENTED,
  GDICT_CONTEXT_ERROR_BAD_DATABASE,
  GDICT_CONTEXT_ERROR_BAD_STRATEGY,
  GDICT_CONTEXT_ERROR_NO_MATCH,
  GDICT_CONTEXT_ERROR_NO_DATABASES,
  GDICT_CONTEXT_ERROR_NO_STRATEGIES
} GdictContextError;

GQuark gdict_context_error_get_quark (void);

/* Server replies are incapsulated inside these boxed types; their lifetime
 * is handled by the GdictContext object, so we don't need constructors or
 * destructors for them, just accessors.
 */
typedef struct _GdictMatch          GdictMatch;
typedef struct _GdictDefinition     GdictDefinition;
typedef struct _GdictDatabase       GdictDatabase;
typedef struct _GdictStrategy       GdictStrategy;


GType                 gdict_match_get_type            (void) G_GNUC_CONST;
G_CONST_RETURN gchar *gdict_match_get_word            (GdictMatch      *match);
G_CONST_RETURN gchar *gdict_match_get_strategy        (GdictMatch      *match);
G_CONST_RETURN gchar *gdict_match_get_database        (GdictMatch      *match);

GType                 gdict_definition_get_type       (void) G_GNUC_CONST;
G_CONST_RETURN gchar *gdict_definition_get_word       (GdictDefinition *definition);
G_CONST_RETURN gchar *gdict_definition_get_database   (GdictDefinition *definition);
G_CONST_RETURN gchar *gdict_definition_get_definition (GdictDefinition *definition);

GType                 gdict_database_get_type         (void) G_GNUC_CONST;
G_CONST_RETURN gchar *gdict_database_get_name         (GdictDatabase   *database);
G_CONST_RETURN gchar *gdict_database_get_full_name    (GdictDatabase   *database);

GType                 gdict_strategy_get_type         (void) G_GNUC_CONST;
G_CONST_RETURN gchar *gdict_strategy_get_name         (GdictStrategy   *strategy);
G_CONST_RETURN gchar *gdict_strategy_get_full_name    (GdictStrategy   *strategy);


typedef struct _GdictContext        GdictContext;
typedef struct _GdictContextClass   GdictContextClass;
typedef struct _GdictContextPrivate GdictContextPrivate;

/* The GdictContext object - the object that does all the magic */
struct _GdictContext
{
  /*< private >*/
  GObject parent_instance;
  
  GdictContextPrivate *priv;
};

struct _GdictContextClass
{
  GObjectClass parent_class;
  
  /* These signals are used to monitor the lifetime of the
   * connection to the dictionary server used by the context
   */
  void (*connected)        (GdictContext    *context);
  void (*disconnected)     (GdictContext    *context);
  
  /* These signals are fired when a server reply comes 
   * along the wire
   */
  void (*database_found)   (GdictContext    *context,
  			    GdictDatabase   *database);
  void (*strategy_found)   (GdictContext    *context,
  			    GdictStrategy   *strategy);
  void (*match_found)      (GdictContext    *context,
  		            GdictMatch      *match);
  void (*definition_found) (GdictContext    *context,
  			    GdictDefinition *definition);
  
  /* This signal is fired when an error occurs on the wire,
   * after our command to the dictionary server has been sent.
   * Errors happening before that point are handled by the
   * GdictContext functions
   */
  void (*error)            (GdictContext    *context,
  			    GError          *error);
};


GType                 gdict_context_get_type       (void) G_GNUC_CONST;

GdictContext *        gdict_context_new            (const gchar *hostname,
				                    gint         port);
				                  
void                  gdict_context_set_client     (GdictContext *context,
						    const gchar  *client);
G_CONST_RETURN gchar *gdict_context_get_client     (GdictContext *context);
void                  gdict_context_set_hostname   (GdictContext *context,
						    const gchar  *hostname);
G_CONST_RETURN gchar *gdict_context_get_hostname   (GdictContext *context);
void                  gdict_context_set_port       (GdictContext *context,
						    gint          port);
guint                 gdict_context_get_port       (GdictContext *context);

gboolean              gdict_context_connect        (GdictContext  *context,
						    GError       **error);
void                  gdict_context_disconnect     (GdictContext  *context);
gboolean              gdict_context_is_connected   (GdictContext  *context);

gboolean              gdict_context_get_databases  (GdictContext  *context,
						    GError       **error);
gboolean              gdict_context_get_strategies (GdictContext  *context,
						    GError       **error);
gboolean              gdict_context_define         (GdictContext  *context,
						    const gchar   *database,
						    const gchar   *word,
						    GError       **error);
gboolean              gdict_context_match          (GdictContext  *context,
						    const gchar   *database,
						    const gchar   *strategy,
						    const gchar   *word,
						    GError       **error);

G_END_DECLS

#endif /* __GDICT_CONTEXT_H__ */


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