Re: Recently Used Files Proposal



Hi,

On Wed, 2005-06-08 at 00:44 -0500, Federico Mena Quintero wrote:
> On Thu, 2005-06-02 at 10:19 +0200, Emmanuele Bassi wrote:
> 
> > I've attached a prototype API for GtkRecentItem and GtkRecentManager
> > (already set to live in libegg, for the time being). Let me know what
> > you think of it.
> 
> Oh, BTW... to see what other systems do already, I looked at the Win32
> API and Cocoa.

I did look at Win32 APIs.

They use the Registry to store their data, so I came up with a more
generic manager (API attached).

The new RecentManager is an abstract interface, providing simple methods
that accesses a storage system; we could implement the storage of
recently used items using XBEL, GConf, the Registry, etc.; the storage
backend is platform dependent, as we already do with the GtkFileSystem
interface.

The recently used manager is checked by GtkFileChooser: developers need
not to meddle with a RecentManager object directely.  Once a document is
opened or saved using the FileChooser, it is automagically added to the
list.

The list itself is showed using a RecentChooser UI, be it a menu or a
completely new widget.

Ideally, the first time a user instantiates a RecentChooser or a
FileChooser object, a RecentManager is created a set as a global object;
the best idea I came up with is to attach it to the GdkScreen as we
currently do with the IconTheme object - it's convenient, even though it
could yield some notification latency across multiple screens.  Then,
every other FileChooser or RecentChooser would simple have to access
that RecentManager:

  recent_manager = g_object_get_data (screen, "gtk-recent-manager");

This would decrease memory footprint, allow inter-process notification
and also cut off the locking issues we currently have.

> Emmanuele, do you already have a working parser for XBEL using libxml2
> or whatever?  This would be a good start to implement the API for GTK+.

I have a generic GObject-based parser (which currently doesn't handle
metadata, at least until I come up with an idea on how to register
custom objects representing custom metadata), and a GObject-based parser
specifically designed around my desktop-bookmark spec (linked on the
wiki), which is what we should use to store recently used items on disk.

I'll clean them up and upload them.

Kind regards,
 Emmanuele.

P.S.: I've attached the interface for the RecentManager and for the
RecentChooser objects, and an implementation of a 'Open recent' menu
object using the RecentChooser interface.

-- 
Emmanuele Bassi <ebassi gmail com>
Web site: http://log.emmanuelebassi.net
/* eggrecentmanager.h: Abstract recent manager interface
 * Copyright (C) 2005 Emmanuele Bassi
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#ifndef __EGG_RECENT_MANAGER_H__
#define __EGG_RECENT_MANAGER_H__

#ifndef EGG_RECENT_MANAGER_ENABLE_UNSUPPORTED
#error "EggRecentManager is not supported API for general use."
#endif

#include <glib-object.h>

G_BEGIN_DECLS

typedef gint64 EggRecentTime;

typedef struct _EggRecentItem		EggRecentItem;
typedef struct _EggRecentAppInfo	EggRecentAppInfo;
typedef struct _EggRecentManager	EggRecentManager;
typedef struct _EggRecentManagerIface	EggRecentManagerIface;

/*
 * GError enumeration for EggRecentManager
 */
#define EGG_RECENT_MANAGER_ERROR	(egg_recent_manager_error_quark ())

typedef enum
{
  EGG_RECENT_MANAGER_ERROR_INVALID_URI,
  EGG_RECENT_MANAGER_ERROR_NOT_FOUND,
  EGG_RECENT_MANAGER_ERROR_NOT_REGISTERED,
  EGG_RECENT_MANAGER_ERROR_PARSE,
  EGG_RECENT_MANAGER_ERROR_READ,
  EGG_RECENT_MANAGER_ERROR_WRITE,
  EGG_RECENT_MANAGER_ERROR_FAILED
} EggRecentManagerError;

GQuark	egg_recent_manager_error_quark 	(void);

/*
 * Detailed informations on the application registering a recent item
 */
#define EGG_TYPE_RECENT_APP_INFO	(egg_recent_app_info_get_type ())

GType		      egg_recent_app_info_get_type  (void) G_GNUC_CONST;

EggRecentAppInfo *    egg_recent_app_info_new	    (void);
EggRecentAppInfo *    egg_recent_app_info_copy	    (EggRecentAppInfo *info);
void		      egg_recent_app_info_free	    (EggRecentAppInfo *info);

G_CONST_RETURN gchar *egg_recent_app_info_get_name  (EggRecentAppInfo *info);
void		      egg_recent_app_info_set_name  (EggRecentAppInfo *info,
						     const gchar      *name);
G_CONST_RETURN gchar *egg_recent_app_info_get_exec  (EggRecentAppInfo *info);
void		      egg_recent_app_info_set_exec  (EggRecentAppInfo *info,
						     const gchar      *exec);
EggRecentTime	      egg_recent_app_info_get_time  (EggRecentAppInfo *info);
void		      egg_recent_app_info_set_time  (EggRecentAppInfo *info,
						     EggRecentTime     time);
guint		      egg_recent_app_info_get_count (EggRecentAppInfo *info);
void		      egg_recent_app_info_set_count (EggRecentAppInfo *info,
						     guint             count);

/*
 * EggRecentItem: object used for representing a recently used resource.
 */
#define EGG_TYPE_RECENT_ITEM		(egg_recent_item_get_type ())
#define EGG_RECENT_ITEM(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_RECENT_ITEM, EggRecentItem))
#define EGG_IS_RECENT_ITEM(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_RECENT_ITEM))

GType			egg_recent_item_get_type		(void) G_GNUC_CONST;

EggRecentItem *		egg_recent_item_new			(void);
EggRecentItem *		egg_recent_item_new_for_uri		(const gchar *uri);

void			egg_recent_item_set_uri			(EggRecentItem    *recent_item,
								 const gchar      *uri);
G_CONST_RETURN gchar *	egg_recent_item_get_uri			(EggRecentItem    *recent_item);
void			egg_recent_item_set_mime_type		(EggRecentItem    *recent_item,
								 const gchar      *mime_type);
G_CONST_RETURN gchar *	egg_recent_item_get_mime_type		(EggRecentItem    *recent_item);
void			egg_recent_item_set_display_name	(EggRecentItem    *recent_item,
								 const gchar      *display_name);
G_CONST_RETURN gchar *	egg_recent_item_get_display_name	(EggRecentItem    *recent_item);
void			egg_recent_item_set_description		(EggRecentItem    *recent_item,
								 const gchar      *description);
G_CONST_RETURN gchar *	egg_recent_item_get_description		(EggRecentItem    *recent_item);
void			egg_recent_item_set_private_hint        (EggRecentItem    *recent_item,
								 gboolean          is_private);
gboolean		egg_recent_item_get_private_hint	(EggRecentItem    *recent_item);
EggRecentTime		egg_recent_item_added			(EggRecentItem    *recent_item);
EggRecentTime		egg_recent_item_modified		(EggRecentItem    *recent_item);
EggRecentTime		egg_recent_item_visited			(EggRecentItem    *recent_item);
gboolean		egg_recent_item_register_application	(EggRecentItem    *recent_item,
								 const gchar      *app_name,
								 const gchar      *app_exec);
EggRecentAppInfo *	egg_recent_item_get_application_info	(EggRecentItem    *recent_item,
								 const gchar      *app_name);
guint			egg_recent_item_get_registration_count	(EggRecentItem    *recent_item,
								 const gchar      *app_name);
EggRecentTime		egg_recent_item_get_registration_time	(EggRecentItem    *recent_item,
								 const gchar      *app_name);
gboolean		egg_recent_item_has_application		(EggRecentItem    *recent_item,
								 const gchar      *app_name);
gchar**			egg_recent_item_get_applications	(EggRecentItem    *recent_item,
								 gsize            *length);
void			egg_recent_item_add_group		(EggRecentItem    *recent_item,
								 const gchar      *group_name);
void			egg_recent_item_remove_group		(EggRecentItem    *recent_item,
								 const gchar      *group_name);
gboolean		egg_recent_item_in_group		(EggRecentItem    *recent_item,
								 const gchar      *group_name);
gchar**			egg_recent_item_get_groups		(EggRecentItem    *recent_item,
								 gsize            *length);
gboolean		egg_recent_item_match			(EggRecentItem    *recent_item_1,
								 EggRecentItem    *recent_item_2);
gboolean		egg_recent_item_get_status		(EggRecentItem    *recent_item);

void	 _egg_recent_item_merge_groups	     (EggRecentItem *source,
					      EggRecentItem *target);
void	 _egg_recent_item_merge_applications (EggRecentItem *source,
					      EggRecentItem *target);
gboolean _egg_recent_item_is_registered	     (EggRecentItem *recent_item);

/*
 * The base EggRecentManager interface
 */
#define EGG_TYPE_RECENT_MANAGER			(egg_recent_manager_get_type ())
#define EGG_RECENT_MANAGER(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_RECENT_MANAGER, EggRecentManager))
#define EGG_IS_RECENT_MANAGER(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_RECENT_MANAGER))
#define EGG_IS_RECENT_MANAGER_GET_IFACE(inst)	(G_TYPE_INSTANCE_GET_INTERFACE ((inst), EGG_TYPE_RECENT_MANAGER, EggRecentManagerIface))

struct _EggRecentManager
{
  GTypeInterface base_iface;

  /*
   * Methods
   */
  gboolean        (*add_item)    (EggRecentManager  *recent_manager,
		  	          EggRecentItem     *recent_item,
				  GError           **error);
  gboolean        (*remove_item) (EggRecentManager  *recent_manager,
		  	          EggRecentItem     *recent_item,
				  GError           **error);
  gboolean        (*has_item)    (EggRecentManager  *recent_manager,
		  		  const gchar       *uri);
  EggRecentItem * (*get_item)    (EggRecentManager  *recent_manager,
		  		  const gchar       *uri,
				  GError           **error);
  gboolean        (*create_item) (EggRecentManager  *recent_manager,
		  		  const gchar       *uri,
				  const gchar       *mime_type,
				  gboolean           is_private,
				  EggRecentAppInfo  *app_info,
				  GError           **error);
  GList *         (*list_items)  (EggRecentManager *recent_manager);
  void            (*purge_items) (EggRecentManager *recent_manager);

  /*
   * Signals
   */
  void (* items_changed) (EggRecentManager *recent_manager);
};

GType 	       egg_recent_manager_get_type    (void) G_GNUC_CONST;

gboolean       egg_recent_manager_add_item    (EggRecentManager  *recent_manager,
					       EggRecentItem     *recent_item,
					       GError           **error);
gboolean       egg_recent_manager_remove_item (EggRecentManager  *recent_manager,
					       EggRecentItem     *recent_item,
					       GError           **error);
gboolean       egg_recent_manager_has_item    (EggRecentManager  *recent_manager,
					       const gchar       *uri);
EggRecentItem *egg_recent_manager_get_item    (EggRecentManager  *recent_manager,
					       const gchar       *uri,
					       GError           **error);
gboolean       egg_recent_manager_create_item (EggRecentManager  *recent_manager,
					       const gchar       *uri,
					       const gchar       *mime_type,
					       gboolean           is_private,
					       EggRecentAppInfo  *app_info,
					       GError           **error);
GList *	       egg_recent_manager_list_items  (EggRecentManager *recent_manager);
void	       egg_recent_manager_purge_items (EggRecentManager *recent_manager);

/* EggRecentManager modules support */
EggRecentManager *_egg_recent_manager_create (const char *recent_manager_name);

G_END_DECLS

#endif /* ! __EGG_RECENT_MANAGER_H__ */
/* eggrecentchooser.h - Abstract interface for recent file selectors GUIs
 * Copyright (C) 2005, Emmanuele Bassi
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#ifndef __EGG_RECENT_CHOOSER_H__
#define __EGG_RECENT_CHOOSER_H__

#include <gtk/gtkwidget.h>

#include "eggrecentmanager.h"
#include "eggrecentfilter.h"

G_BEGIN_DECLS

#define EGG_TYPE_RECENT_CHOOSER		(egg_recent_chooser_get_type ())
#define EGG_RECENT_CHOOSER(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_RECENT_CHOOSER, EggRecentChooser))
#define EGG_IS_RECENT_CHOOSER(obj)	(G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_RECENT_CHOOSER))

typedef struct _EggRecentChooser	EggRecentChooser;

GType		   egg_recent_chooser_get_type		  (void) G_GNUC_CONST;

/*
 * Configuration
 */
void		   egg_recent_chooser_set_manager	  (EggRecentChooser *recent_chooser,
							   EggRecentManager *recent_manager);
EggRecentManager * egg_recent_chooser_get_manager	  (EggRecentChooser *recent_chooser);
void		   egg_recent_chooser_set_show_private	  (EggRecentChooser *recent_chooser,
							   gboolean          show_private);
gboolean	   egg_recent_chooser_get_show_private	  (EggRecentChooser *recent_chooser);
void		   egg_recent_chooser_set_select_multiple (EggRecentChooser *recent_chooser,
							   gboolean          select_multiple);
gboolean	   egg_recent_chooser_get_select_multiple (EggRecentChooser *recent_chooser);

/*
 * Items handling
 */
gboolean	egg_recent_chooser_set_current_item	(EggRecentChooser *recent_chooser,
							 EggRecentItem    *recent_item);
gboolean	egg_recent_chooser_set_current_uri	(EggRecentChooser *recent_chooser,
							 const gchar      *item_uri);
EggRecentItem *	egg_recent_chooser_get_current_item	(EggRecentChooser *recent_chooser);
gchar *		egg_recent_chooser_get_current_uri	(EggRecentChooser *recent_chooser);
gboolean	egg_recent_chooser_select_item		(EggRecentChooser *recent_chooser,
							 EggRecentItem    *recent_item);
gboolean	egg_recent_chooser_select_uri		(EggRecentChooser *recent_chooser,
							 const gchar      *uri);
void		egg_recent_chooser_unselect_item	(EggRecentChooser *recent_chooser,
							 EggRecentItem    *recent_item);
void		egg_recent_chooser_unselect_uri		(EggRecentChooser *recent_chooser,
							 const gchar      *uri);
GSList *	egg_recent_chooser_get_items		(EggRecentChooser *recent_chooser);
GSList *	egg_recent_chooser_get_uris		(EggRecentChooser *recent_chooser);

/*
 * Sorting
 */

/* Enumeration for sorting type; we provide MRU and LRU sorting; every other
 * sorting should be provided by the user.  Sorting is done inside the UI; the
 * RecentManager knows nothing about sorting, and will always return an
 * unsorted list. */
typedef enum
{
  EGG_RECENT_SORT_NONE = 0,
  EGG_RECENT_SORT_MRU,
  EGG_RECENT_SORT_LRU,
  EGG_RECENT_SORT_CUSTOM
} EggRecentSortType;

/* Sorting function.
 * 
 * Should return a negative integer if item a is before item b, zero if they
 * are equal, and a positive integer if item a is after item b.
 */
typedef gint (*EggRecentSortFunc) (EggRecentItem *a,
				   EggRecentItem *b,
				   gpointer       user_data);

void		  egg_recent_chooser_set_sort_type	(EggRecentChooser  *recent_chooser,
							 EggRecentSortType  sort_type);
EggRecentSortType egg_recent_chooser_get_sort_type	(EggRecentChooser  *recent_chooser);
void		  egg_recent_chooser_set_sort_func	(EggRecentChooser  *recent_chooser,
							 EggRecentSortFunc  sort_func,
							 gpointer           sort_data,
							 GDestroyNotify     data_destroy);

/*
 * Filters
 */
void		  egg_recent_chooser_add_filter		(EggRecentChooser *recent_chooser,
							 EggRecentFilter  *recent_filter);
void		  egg_recent_chooser_remove_filter	(EggRecentChooser *recent_chooser,
							 EggRecentFilter  *recent_filter);
GSList *	  egg_recent_chooser_list_filters	(EggRecentChooser *recent_chooser);

void		  egg_recent_chooser_set_filter		(EggRecentChooser *recent_chooser,
							 EggRecentFilter  *recent_filter);
EggRecentFilter * egg_recent_chooser_get_filter		(EggRecentChooser *recent_chooser);

G_END_DECLS

#endif /* ! __EGG_RECENT_CHOOSER_H__ */
/* eggrecentchoosermenu.h - Recentlyb used items menu widget
 * Copyright (C) 2005, Emmanuele Bassi
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#ifndef __EGG_RECENT_CHOOSER_MENU_H__
#define __EGG_RECENT_CHOOSER_MENU_H__

#include <gtk/gtkmenu.h>
#include <gtk/gtktooltips.h>

#include "eggrecentchooser.h"

G_BEGIN_DECLS

#define EGG_TYPE_RECENT_CHOOSER_MENU		(egg_recent_chooser_menu_get_type ())
#define EGG_RECENT_CHOOSER_MENU(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_RECENT_CHOOSER_MENU, EggRecentChooserMenu))
#define EGG_IS_RECENT_CHOOSER_MENU(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_RECENT_CHOOSER_MENU))
#define EGG_RECENT_CHOOSER_MENU_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_RECENT_CHOOSER_MENU, EggRecentChooserMenuClass))
#define EGG_IS_RECENT_CHOOSER_MENU_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_RECENT_CHOOSER_MENU))
#define EGG_RECENT_CHOOSER_MENU_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_RECENT_CHOOSER_MENU, EggRecentChooserMenuClass))

typedef struct _EggRecentChooserMenu		EggRecentChooserMenu;
typedef struct _EggRecentChooserMenuClass	EggRecentChooserMenuClass;

struct _EggRecentChooserMenu
{
  GtkMenu parent_instance;

  /*< private >*/
  guint show_tooltips : 1;
  guint show_icons : 1;
  guint show_trailing_sep : 1;
  guint show_clear_item : 1;
  guint show_more_item : 1;

  /* the list of our menu items */
  GSList *our_items;

  /* menu items we use */
  GtkWidget *separator_item;
  GtkWidget *clear_item;
  GtkWidget *more_item;

  /* tooltips for our bookmark items*/
  GtkTooltips *tooltips;
};

struct _EggRecentChooserMenuClass
{
  GtkMenuClass parent_class;
  
  void (* bookmark_activate) (EggRecentChooserMenu *recent_menu,
		  	      EggRecentItem        *recent_item);
  
  /* padding for future expansion */
  void (* egg_recent1) (void);
  void (* egg_recent2) (void);
  void (* egg_recent3) (void);
  void (* egg_recent4) (void);
};

GType		egg_recent_chooser_menu_get_type	     (void) G_GNUC_CONST;

GtkWidget *	egg_recent_chooser_menu_new		     (void);
GtkWidget *	egg_recent_chooser_menu_new_with_backend     (const gchar *backend);

void		egg_recent_chooser_menu_set_has_trailing_sep (EggRecentChooserMenu *recent_menu,
							      gboolean	            has_trailing_sep);
gboolean	egg_recent_chooser_menu_get_has_trailing_sep (EggRecentChooserMenu *recent_menu);
void		egg_recent_chooser_menu_set_show_icons       (EggRecentChooserMenu *recent_menu,
							      gboolean              show_icons);
gboolean	egg_recent_chooser_menu_get_show_icons       (EggRecentChooserMenu *recent_menu);
void		egg_recent_chooser_menu_set_show_tips	     (EggRecentChooserMenu *recent_menu,
							      gboolean              show_menu);
gboolean	egg_recent_chooser_menu_get_show_tips	     (EggRecentChooserMenu *recent_menu);
void		egg_recent_chooser_menu_set_show_clear	     (EggRecentChooserMenu *recent_menu,
							      gboolean              show_clear);
gboolean	egg_recent_chooser_menu_get_show_clear	     (EggRecentChooserMenu *recent_menu);
void		egg_recent_chooser_menu_set_show_more	     (EggRecentChooserMenu *recent_menu,
							      gboolean              show_more);
gboolean	egg_recent_chooser_menu_get_show_more	     (EggRecentChooserMenu *recent_menu);

G_END_DECLS

#endif /* ! __EGG_RECENT_CHOOSER_MENU_H__ */


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