[Goodies-commits] r2984 - in xfce4-places-plugin/trunk: . panel-plugin

Diego Ongaro ongardie at xfce.org
Sat Aug 11 08:09:59 CEST 2007


Author: ongardie
Date: 2007-08-11 06:09:59 +0000 (Sat, 11 Aug 2007)
New Revision: 2984

Modified:
   xfce4-places-plugin/trunk/ChangeLog
   xfce4-places-plugin/trunk/panel-plugin/model.c
   xfce4-places-plugin/trunk/panel-plugin/model.h
   xfce4-places-plugin/trunk/panel-plugin/model_system.c
   xfce4-places-plugin/trunk/panel-plugin/model_system.h
   xfce4-places-plugin/trunk/panel-plugin/model_user.c
   xfce4-places-plugin/trunk/panel-plugin/model_user.h
   xfce4-places-plugin/trunk/panel-plugin/model_volumes.c
   xfce4-places-plugin/trunk/panel-plugin/model_volumes.h
   xfce4-places-plugin/trunk/panel-plugin/places.c
   xfce4-places-plugin/trunk/panel-plugin/places.h
   xfce4-places-plugin/trunk/panel-plugin/view.c
Log:
2007-08-11	Diego Ongaro <ongardie at gmail.com>

* Large model refactoring for flexibility, maintainability.


Modified: xfce4-places-plugin/trunk/ChangeLog
===================================================================
--- xfce4-places-plugin/trunk/ChangeLog	2007-08-10 17:19:20 UTC (rev 2983)
+++ xfce4-places-plugin/trunk/ChangeLog	2007-08-11 06:09:59 UTC (rev 2984)
@@ -1,3 +1,7 @@
+2007-08-11	Diego Ongaro <ongardie at gmail.com>
+
+	* Large model refactoring for flexibility, maintainability.
+
 2007-08-10	Diego Ongaro <ongardie at gmail.com>
 
 	* Clicking on Recent Changes -> Clear no longer hides the menu

Modified: xfce4-places-plugin/trunk/panel-plugin/model.c
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/model.c	2007-08-10 17:19:20 UTC (rev 2983)
+++ xfce4-places-plugin/trunk/panel-plugin/model.c	2007-08-11 06:09:59 UTC (rev 2984)
@@ -22,155 +22,76 @@
 #endif
 
 #include "model.h"
-#include "model_system.h"
-#include "model_volumes.h"
-#include "model_user.h"
 
 #include <libxfce4util/libxfce4util.h>
 
-struct _Bookmarks
+inline void
+places_bookmark_action_call(PlacesBookmarkAction *act)
 {
-    BookmarksSystem  *system;
-    BookmarksVolumes *volumes;
-    BookmarksUser    *user;
-};
+    g_assert(act != NULL);
 
-Bookmarks*
-places_bookmarks_init()
-{
-    DBG("initializing model");
-
-    Bookmarks *b = g_new0(Bookmarks, 1);
-    
-    b->system = places_bookmarks_system_init();
-    return b;
+    if(act->action != NULL)
+        act->action(act);
 }
 
-void
-places_bookmarks_enable(Bookmarks *b, gint enable_mask)
+inline void
+places_bookmark_action_free(PlacesBookmarkAction *act)
 {
-    g_assert(b != NULL);
+    g_assert(act != NULL);
 
-    gboolean enable_volumes, enable_user;
-    
-    // Enable/disable volumes
-    enable_volumes = (enable_mask & PLACES_BOOKMARKS_ENABLE_VOLUMES);
-
-    if(b->volumes == NULL && enable_volumes){
-        b->volumes = places_bookmarks_volumes_init();
-    }else if(b->volumes != NULL && !enable_volumes) {
-        places_bookmarks_volumes_finalize(b->volumes);
-        b->volumes = NULL;
-    }
-
-    // Enable/disable GTK bookmarks
-    enable_user = (enable_mask & PLACES_BOOKMARKS_ENABLE_USER);
-
-    if(b->user == NULL && enable_user){
-        b->user = places_bookmarks_user_init(b->system); // user depends on system for 
-                                                         // places_bookmarks_system_bi_system_mod().
-                                                         // It's a sucky aspect of this design...
-    }else if(b->user != NULL && !enable_user){
-        places_bookmarks_user_finalize(b->user);
-        b->user = NULL;
-    }
-
+    if(act->free != NULL)
+        act->free(act);
+    else
+        g_free(act);
 }
 
-void
-places_bookmarks_visit(Bookmarks *b,
-                       BookmarksVisitor *visitor)
+static inline void
+places_bookmark_actions_free(GList *actions)
 {
-    g_assert(b != NULL);
-    g_assert(visitor != NULL);
-
-    places_bookmarks_system_visit  (b->system,  visitor);
-
-    if(b->volumes != NULL)
-        places_bookmarks_volumes_visit (b->volumes, visitor);
-
-    if(b->user != NULL){
-        visitor->separator             (visitor->pass_thru);
-        places_bookmarks_user_visit    (b->user,    visitor);
+    while(actions != NULL){
+        if(actions->data != NULL)
+            places_bookmark_action_free((PlacesBookmarkAction*) actions->data);
+        actions = actions->next;
     }
+    g_list_free(actions);
 }
 
-gboolean
-places_bookmarks_changed(Bookmarks *b)
+inline void
+places_bookmark_free(PlacesBookmark *bookmark)
 {
-    g_assert(b != NULL);
+    g_assert(bookmark != NULL);
 
-    // try to avoid short-circuit of || since changed() has side-effects
-    gboolean changed = FALSE;
+    if(bookmark->actions != NULL){
+        places_bookmark_actions_free(bookmark->actions);
+        bookmark->actions = NULL;
+    }
 
-    changed = places_bookmarks_system_changed(b->system)        || changed;
-
-    if(b->volumes != NULL)
-        changed = places_bookmarks_volumes_changed(b->volumes)  || changed;
-
-    if(b->user != NULL)
-        changed = places_bookmarks_user_changed(b->user)        || changed;
-
-    return changed;
+    if(bookmark->free != NULL)
+        bookmark->free(bookmark);
+    else
+        g_free(bookmark);
 }
 
-void
-places_bookmarks_finalize(Bookmarks *b)
+inline GList*
+places_bookmark_group_get_bookmarks(PlacesBookmarkGroup *pbg)
 {
-    g_assert(b != NULL);
-
-    places_bookmarks_system_finalize(b->system);
-    b->system = NULL;
-    
-    places_bookmarks_enable(b, PLACES_BOOKMARKS_ENABLE_NONE);
-
-    g_free(b);
+    return pbg->get_bookmarks(pbg);
 }
 
-void
-places_bookmark_info_free(BookmarkInfo *bi)
+inline gboolean
+places_bookmark_group_changed(PlacesBookmarkGroup *pbg)
 {
-    g_assert(bi != NULL);
-
-    if(bi->label != NULL){
-        g_free(bi->label);
-        bi->label = NULL;
-    }
-    if(bi->uri != NULL){
-        g_free(bi->uri);
-        bi->uri = NULL;
-    }
-    if(bi->icon != NULL){
-        g_free(bi->icon);
-        bi->icon = NULL;
-    }
-    if(bi->data != NULL){
-        DBG("WARNING: data != NULL. Caller is in charge of freeing data");
-        bi->data = NULL;
-    }
-
-    g_free(bi);
+    return pbg->changed(pbg);
 }
 
-
-void places_bookmark_action_call(BookmarkAction *act)
+inline void
+places_bookmark_group_finalize(PlacesBookmarkGroup *pbg)
 {
-    g_assert(act != NULL);
-
-    if(act->action != NULL)
-        act->action(act);
+    pbg->finalize(pbg);
 }
 
-void places_bookmark_action_free(BookmarkAction *act)
-{
-    g_assert(act != NULL);
 
-    if(act->free != NULL)
-        act->free(act);
-    else
-        g_free(act);
-}
-
+/*
 void
 places_bookmark_actions_list_destroy(GSList *actions)
 {
@@ -179,5 +100,6 @@
     g_slist_foreach(actions, (GFunc) places_bookmark_action_free, NULL);
     g_slist_free(actions);
 }
+*/
 
 // vim: ai et tabstop=4

Modified: xfce4-places-plugin/trunk/panel-plugin/model.h
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/model.h	2007-08-10 17:19:20 UTC (rev 2983)
+++ xfce4-places-plugin/trunk/panel-plugin/model.h	2007-08-11 06:09:59 UTC (rev 2984)
@@ -22,62 +22,66 @@
 
 #include <glib.h>
 
-// Bookmark Info
-
-typedef struct
+/* Places Bookmark Action */
+typedef struct _PlacesBookmarkAction PlacesBookmarkAction;
+struct _PlacesBookmarkAction
 {
-    gchar           *label;
-    gchar           *uri;
-    gchar           *icon;
-    gboolean         show;
-    gpointer         data;
-} BookmarkInfo;
-
-void
-places_bookmark_info_free(BookmarkInfo*);
-
-typedef struct _BookmarkAction BookmarkAction;
-struct _BookmarkAction
-{
-    gchar       *label;
+    gchar       *label;     /* must not be NULL */
     gpointer    priv;
-    void        (*action)   (BookmarkAction *self);
-    void        (*free)     (BookmarkAction *self);
+    void        (*action)   (PlacesBookmarkAction *self);
+    void        (*free)     (PlacesBookmarkAction *self);
 
 };
 
-void places_bookmark_action_call(BookmarkAction *act);
-void places_bookmark_action_free(BookmarkAction *act);
-void places_bookmark_actions_list_destroy(GSList *actions);
+inline void
+places_bookmark_action_call(PlacesBookmarkAction*);
 
-typedef struct
+inline void
+places_bookmark_action_free(PlacesBookmarkAction*);
+
+/* Places Bookmark */
+
+typedef enum
 {
-    gpointer   pass_thru;
-    void       (*item)        (gpointer, const gchar*, const gchar*, const gchar*, GSList *actions);
-    void       (*separator)   (gpointer);
-} BookmarksVisitor;
+    PLACES_URI_SCHEME_NONE=0,
+    PLACES_URI_SCHEME_FILE, 
+    PLACES_URI_SCHEME_TRASH
+} places_uri_scheme;
 
-typedef struct _Bookmarks Bookmarks;
+typedef struct _PlacesBookmark PlacesBookmark;
+struct _PlacesBookmark
+{
+    gchar               *label;         /* must not be NULL */
+    gchar               *uri;           /* may be NULL */
+    places_uri_scheme    uri_scheme;    
+    gchar               *icon;          /* may be NULL */
+    GList               *actions;       /* may be NULL (empty) */
 
-Bookmarks*
-places_bookmarks_init();
+    gpointer             priv;          /* private data */
+    void               (*free) (PlacesBookmark *self);
+};
 
-#define PLACES_BOOKMARKS_ENABLE_NONE    (0)
-#define PLACES_BOOKMARKS_ENABLE_VOLUMES (1)
-#define PLACES_BOOKMARKS_ENABLE_USER    (1 << 1)
-#define PLACES_BOOKMARKS_ENABLE_ALL     (PLACES_BOOKMARKS_ENABLE_VOLUMES & PLACES_BOOKMARKS_ENABLE_USER)
-void
-places_bookmarks_enable(Bookmarks *b, gint enable);
+inline void
+places_bookmark_free(PlacesBookmark *bookmark);
 
-void
-places_bookmarks_visit(Bookmarks *b, BookmarksVisitor *visitor);
+/* Places Bookmark Group */
+typedef struct _PlacesBookmarkGroup PlacesBookmarkGroup;
+struct _PlacesBookmarkGroup
+{
+    GList*      (*get_bookmarks) (PlacesBookmarkGroup *self);
+    gboolean    (*changed)       (PlacesBookmarkGroup *self);
+    void        (*finalize)      (PlacesBookmarkGroup *self);
+    gpointer    priv;
+};
 
-gboolean
-places_bookmarks_changed(Bookmarks *b);
+inline GList*
+places_bookmark_group_get_bookmarks(PlacesBookmarkGroup*);
 
-void
-places_bookmarks_finalize(Bookmarks *b);
+inline gboolean
+places_bookmark_group_changed(PlacesBookmarkGroup*);
 
+inline void
+places_bookmark_group_finalize(PlacesBookmarkGroup*);
 
 #endif
 // vim: ai et tabstop=4

Modified: xfce4-places-plugin/trunk/panel-plugin/model_system.c
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/model_system.c	2007-08-10 17:19:20 UTC (rev 2983)
+++ xfce4-places-plugin/trunk/panel-plugin/model_system.c	2007-08-11 06:09:59 UTC (rev 2984)
@@ -23,179 +23,172 @@
 
 #include "model_system.h"
 #include "model.h"
+
+#include <string.h>
+
+#include <glib.h>
+
 #include <libxfce4util/libxfce4util.h>
+
 #define EXO_API_SUBJECT_TO_CHANGE
-#include <exo/exo.h>
 #include <thunar-vfs/thunar-vfs.h>
 
-#define bookmarks_system_check_existence data
 
-struct _BookmarksSystem
+#define pbg_priv(pbg) ((PBSysData*) pbg->priv)
+
+typedef struct
 {
-    GPtrArray *bookmarks;
     ThunarVfsPath *trash_path;
-};
 
+    /* These are the things that might "change" */
+    gboolean       check_changed;   /* starts off false to indicate the following are meaningless */
+    gboolean       desktop_exists;
+    gboolean       trash_is_empty;
 
-BookmarksSystem*
-places_bookmarks_system_init()
+} PBSysData;
+ 
+static void
+pbsys_free_desktop_bookmark(PlacesBookmark *bookmark)
 {
-    thunar_vfs_init();
+    g_assert(bookmark != NULL);
 
-    BookmarksSystem *b = g_new0(BookmarksSystem, 1);
+    if(bookmark->uri != NULL)
+        g_free(bookmark->uri);
 
-    BookmarkInfo *bookmark;
-    b->bookmarks = g_ptr_array_sized_new(4);
-    
+    g_free(bookmark);
+}
+
+static void
+pbsys_free_trash_bookmark(PlacesBookmark *bookmark)
+{
+    g_assert(bookmark != NULL);
+
+    if(bookmark->icon != NULL)
+        g_free(bookmark->icon);
+
+    g_free(bookmark);
+}
+
+static GList*
+pbsys_get_bookmarks(PlacesBookmarkGroup *bookmark_group)
+{
+    GList *bookmarks = NULL;           /* we'll return this */
+    PlacesBookmark *bookmark;
+    ThunarVfsInfo *trash_info;
     const gchar *home_dir = xfce_get_homedir();
 
+    pbg_priv(bookmark_group)->check_changed = TRUE;
+
     // These icon names are consistent with Thunar.
 
     // Home
-    bookmark = g_new0(BookmarkInfo, 1);
-    bookmark->label = g_strdup(g_get_user_name());
-    bookmark->uri = g_strdup(home_dir);
-    bookmark->icon = g_strdup("gnome-fs-home");
-    bookmark->show = TRUE;
-    bookmark->bookmarks_system_check_existence = NULL;
-    g_ptr_array_add(b->bookmarks, bookmark);
+    bookmark                = g_new0(PlacesBookmark, 1);
+    bookmark->label         = (gchar*) g_get_user_name();
+    bookmark->uri           = (gchar*) home_dir;
+    bookmark->icon          = "gnome-fs-home";
+    bookmarks = g_list_append(bookmarks, bookmark);
 
     // Trash
-    bookmark = g_new0(BookmarkInfo, 1);
+    bookmark                = g_new0(PlacesBookmark, 1);
+    bookmark->label         = _("Trash");
+    bookmark->uri           = "trash:///";
+    bookmark->uri_scheme    = PLACES_URI_SCHEME_TRASH;
+    bookmark->free          = pbsys_free_trash_bookmark;;
 
-    bookmark->label = g_strdup(_("Trash"));
-    bookmark->uri = g_strdup("trash:///");
-
-    b->trash_path = thunar_vfs_path_get_for_trash();
-
-    ThunarVfsInfo *trash_info = thunar_vfs_info_new_for_path(b->trash_path, NULL);
-    bookmark->icon = g_strdup(trash_info->custom_icon);
-    if(bookmark->icon == NULL)
+    /* Try for an icon from ThunarVFS to indicate whether trash is empty or not */
+    
+    trash_info = thunar_vfs_info_new_for_path(pbg_priv(bookmark_group)->trash_path, NULL);
+    if(trash_info->custom_icon != NULL){
+        bookmark->icon = g_strdup(trash_info->custom_icon);
+        pbg_priv(bookmark_group)->trash_is_empty = (strcmp("gnome-fs-trash-full", bookmark->icon) != 0);
+    }else{
         bookmark->icon = g_strdup("gnome-fs-trash-full");
+        pbg_priv(bookmark_group)->trash_is_empty = FALSE;
+    }
     thunar_vfs_info_unref(trash_info);
 
-    bookmark->show = TRUE;
-    bookmark->bookmarks_system_check_existence = NULL;
-    g_ptr_array_add(b->bookmarks, bookmark);
+    bookmarks = g_list_append(bookmarks, bookmark);
 
     // Desktop
-    bookmark = g_new0(BookmarkInfo, 1);
-    bookmark->uri = g_build_filename(home_dir, "Desktop", NULL);
-    bookmark->label = g_strdup(_("Desktop"));
-    bookmark->icon = g_strdup("gnome-fs-desktop");
-    bookmark->show = g_file_test(bookmark->uri, G_FILE_TEST_IS_DIR);
-    bookmark->bookmarks_system_check_existence = (gpointer) 1;
-    g_ptr_array_add(b->bookmarks, bookmark);
+    bookmark                = g_new0(PlacesBookmark, 1);
+    bookmark->label         = _("Desktop");
+    bookmark->uri           = g_build_filename(home_dir, "Desktop", NULL);
+    bookmark->icon          = "gnome-fs-desktop";
+    bookmark->free          = pbsys_free_desktop_bookmark;
+
+    if(g_file_test(bookmark->uri, G_FILE_TEST_IS_DIR)){
+        pbg_priv(bookmark_group)->desktop_exists = TRUE;
+        bookmarks = g_list_append(bookmarks, bookmark);
+    }else{
+        pbg_priv(bookmark_group)->desktop_exists = FALSE;
+        places_bookmark_free(bookmark);
+    }
     
     // File System (/)
-    bookmark = g_new0(BookmarkInfo, 1);
-    bookmark->label = g_strdup(_("File System"));
-    bookmark->uri = g_strdup("/");
-    bookmark->icon = g_strdup("gnome-dev-harddisk");
-    bookmark->show = TRUE;
-    bookmark->bookmarks_system_check_existence = NULL;
-    g_ptr_array_add(b->bookmarks, bookmark);
+    bookmark                = g_new0(PlacesBookmark, 1);
+    bookmark->label         = _("File System");
+    bookmark->uri           = "/";
+    bookmark->icon          = "gnome-dev-harddisk";
+    bookmarks = g_list_append(bookmarks, bookmark);
 
-    return b;
-}
+    return bookmarks;
+};
 
 gboolean
-places_bookmarks_system_changed(BookmarksSystem *b)
+pbsys_changed(PlacesBookmarkGroup *bookmark_group)
 {
-    guint k;
-    BookmarkInfo *bi;
-    gboolean ret = FALSE;
+    gchar *uri;
+    gboolean trash_is_empty = FALSE;
+    ThunarVfsInfo *trash_info;
     
-    for(k=0; k < b->bookmarks->len; k++){
-        bi = g_ptr_array_index(b->bookmarks, k);
-        if(bi->bookmarks_system_check_existence && bi->show != g_file_test(bi->uri, G_FILE_TEST_IS_DIR)){
-            bi->show = !bi->show;
-            ret = TRUE;
-        }
-    }
+    if(!pbg_priv(bookmark_group)->check_changed)
+        return FALSE;
+    
+    /* Check if desktop now exists and didn't before */
+    uri = g_build_filename(xfce_get_homedir(), "Desktop", NULL);
+    if(g_file_test(uri, G_FILE_TEST_IS_DIR) != pbg_priv(bookmark_group)->desktop_exists){
+        g_free(uri);
+        return TRUE;
+    }else
+        g_free(uri);
 
     // see if trash gets a different icon (e.g., was empty, now full)
-    bi = g_ptr_array_index(b->bookmarks, 1);
-    ThunarVfsInfo *trash_info = thunar_vfs_info_new_for_path(b->trash_path, NULL);
-    if(trash_info->custom_icon != NULL && !exo_str_is_equal(trash_info->custom_icon, bi->icon)){
-        g_free(bi->icon);
-        bi->icon = g_strdup(trash_info->custom_icon);
-        ret = TRUE;
-    }
+    trash_info = thunar_vfs_info_new_for_path(pbg_priv(bookmark_group)->trash_path, NULL);
+    if(trash_info->custom_icon != NULL)
+        trash_is_empty = (strcmp("gnome-fs-trash-full", trash_info->custom_icon) != 0);
     thunar_vfs_info_unref(trash_info);
+    
+    if(trash_is_empty != pbg_priv(bookmark_group)->trash_is_empty)
+        return TRUE;
 
-    return ret;
+    return FALSE;
 }
 
-void
-places_bookmarks_system_visit(BookmarksSystem *b,
-                              BookmarksVisitor *visitor)
+static void
+pbsys_finalize(PlacesBookmarkGroup *bookmark_group)
 {
-    guint k;
-    BookmarkInfo *bi;
+    thunar_vfs_path_unref(pbg_priv(bookmark_group)->trash_path);
+    thunar_vfs_shutdown();
     
-    for(k=0; k < b->bookmarks->len; k++){
-        bi = g_ptr_array_index(b->bookmarks, k);
-        if(bi->show)
-            visitor->item(visitor->pass_thru, bi->label, bi->uri, bi->icon, NULL);
-    }
-}
+    g_free(pbg_priv(bookmark_group));
 
-static void
-places_bookmarks_system_clear_bi_data(BookmarkInfo *bi)
-{
-    bi->data = NULL;
+    g_free(bookmark_group);
 }
 
-void
-places_bookmarks_system_finalize(BookmarksSystem *b)
+PlacesBookmarkGroup*
+places_bookmarks_system_create()
 {
-    g_ptr_array_foreach(b->bookmarks, (GFunc) places_bookmarks_system_clear_bi_data, NULL);
-    g_ptr_array_foreach(b->bookmarks, (GFunc) places_bookmark_info_free, NULL);
-    g_ptr_array_free(b->bookmarks, TRUE);
-    b->bookmarks = NULL;
-
-    thunar_vfs_path_unref(b->trash_path);
-    thunar_vfs_shutdown();
+    PlacesBookmarkGroup *bookmark_group = g_new0(PlacesBookmarkGroup, 1);
+    bookmark_group->get_bookmarks = pbsys_get_bookmarks;
+    bookmark_group->changed       = pbsys_changed;
+    bookmark_group->finalize      = pbsys_finalize;
+    bookmark_group->priv          = g_new0(PBSysData, 1);
     
-    g_free(b);
-}
+    thunar_vfs_init();
+    pbg_priv(bookmark_group)->trash_path = thunar_vfs_path_get_for_trash();
 
-/*
- * A bookmark with the same path as a system path should have the system icon.
- * Such a bookmark with its default label should also use the system label.
- */
-void
-places_bookmarks_system_bi_system_mod(BookmarksSystem *b, BookmarkInfo *other){
-    g_assert(b != NULL);
-    g_assert(other != NULL);
-    g_assert(other->icon != NULL);
-    g_assert(other->label != NULL);
-
-    gboolean label_is_default;
-    gchar   *default_label;
-    
-    default_label    = g_filename_display_basename(other->uri);
-    label_is_default = exo_str_is_equal(default_label, other->label);
-    g_free(default_label);
-
-    BookmarkInfo *bi;
-    guint k;
-    for(k=0; k < b->bookmarks->len; k++){
-        bi = g_ptr_array_index(b->bookmarks, k);
-
-        if(G_UNLIKELY(exo_str_is_equal(other->uri, bi->uri))){
-            g_free(other->icon);
-            other->icon = g_strdup(bi->icon);
-
-            if(label_is_default && !exo_str_is_equal(other->label, bi->label)){
-                g_free(other->label);
-                other->label = g_strdup(bi->label);
-            }
-            
-            return;
-        }
-    }
+    return bookmark_group;
 }
+   
 
 // vim: ai et tabstop=4

Modified: xfce4-places-plugin/trunk/panel-plugin/model_system.h
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/model_system.h	2007-08-10 17:19:20 UTC (rev 2983)
+++ xfce4-places-plugin/trunk/panel-plugin/model_system.h	2007-08-11 06:09:59 UTC (rev 2984)
@@ -21,25 +21,9 @@
 #define _XFCE_PANEL_PLACES_MODEL_SYSTEM_H
 
 #include "model.h"
-#include <glib.h>
 
-typedef struct _BookmarksSystem BookmarksSystem;
+PlacesBookmarkGroup*
+places_bookmarks_system_create();
 
-BookmarksSystem*
-places_bookmarks_system_init();
-
-void
-places_bookmarks_system_visit(BookmarksSystem *b, BookmarksVisitor *visitor);
-
-gboolean
-places_bookmarks_system_changed(BookmarksSystem *b);
-
-void
-places_bookmarks_system_finalize(BookmarksSystem *b);
-
-void
-places_bookmarks_system_bi_system_mod(BookmarksSystem *b, 
-                                      BookmarkInfo *other);
-
 #endif
 // vim: ai et tabstop=4

Modified: xfce4-places-plugin/trunk/panel-plugin/model_user.c
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/model_user.c	2007-08-10 17:19:20 UTC (rev 2983)
+++ xfce4-places-plugin/trunk/panel-plugin/model_user.c	2007-08-11 06:09:59 UTC (rev 2984)
@@ -21,42 +21,81 @@
 #  include <config.h>
 #endif
 
-#include "model_system.h"
 #include "model_user.h"
 #include "model.h"
 
 #include <libxfce4util/libxfce4util.h>
+#include <glib.h>
 #include <glib/gstdio.h>
 
+#define pbg_priv(pbg) ((PBUserData*) pbg->priv)
+#define show_bookmark(b) ((gboolean) b->priv)
 
-#define bookmarks_user_dir_exists(path)    g_file_test(path, G_FILE_TEST_IS_DIR)
 
-struct _BookmarksUser
+typedef struct
 {
-  GPtrArray             *bookmarks;
-  gchar                 *filename;
-  time_t                 loaded;
+  GList     *bookmarks;
+  gchar     *filename;
+  time_t     loaded;
 
-  const BookmarksSystem *system;
+} PBUserData;
 
-};
+static inline time_t
+pbuser_get_mtime(const gchar *filename)
+{
+    struct stat buf;
+    if(g_stat(filename, &buf) == 0)
+        return buf.st_mtime;
+    return 0;
+}
 
-// internal use
+static inline gboolean
+pbuser_dir_exists(const gchar *path)
+{
+    return g_file_test(path, G_FILE_TEST_IS_DIR);
+}
 
 static void
-places_bookmarks_user_reinit(BookmarksUser *b)
+pbuser_free_bookmark(PlacesBookmark *bookmark)
 {
-    DBG("initializing");
+    g_assert(bookmark != NULL);
+    g_free(bookmark->uri);
+    g_free(bookmark->label);
+    g_free(bookmark);
+}
+
+static void
+pbuser_destroy_bookmarks(PlacesBookmarkGroup *bookmark_group)
+{
+    GList *bookmarks = pbg_priv(bookmark_group)->bookmarks;
+
+    if(bookmarks == NULL)
+        return;
+    
+    while(bookmarks != NULL){
+        pbuser_free_bookmark((PlacesBookmark*) bookmarks->data);
+        bookmarks = bookmarks->next;
+    }
+    g_list_free(bookmarks);
+    pbg_priv(bookmark_group)->bookmarks = NULL;
+}
+
+static void
+pbuser_build_bookmarks(PlacesBookmarkGroup *bookmark_group)
+{
     // As of 2007-04-06, this is pretty much taken from/analogous to Thunar
 
-    BookmarkInfo *bi;
+    GList  *bookmarks = NULL;
+    PlacesBookmark *bookmark;
     gchar  *name;
     gchar  *path;
     gchar   line[2048];
     FILE   *fp;
  
-    fp = fopen(b->filename, "r");
+    pbuser_destroy_bookmarks(bookmark_group);
 
+    fp = fopen(pbg_priv(bookmark_group)->filename, "r");
+
     if(G_UNLIKELY(fp == NULL)){
         DBG("Error opening gtk bookmarks file");
         return;
@@ -95,104 +134,108 @@
         }
 
         /* create the BookmarkInfo container */
-        bi = g_new0(BookmarkInfo, 1);
-        bi->uri = path;
-        bi->label = name;
-        bi->show = bookmarks_user_dir_exists(bi->uri);
-        bi->icon = g_strdup("gnome-fs-directory");
+        bookmark        = g_new0(PlacesBookmark, 1);
+        bookmark->uri   = path;                                   /* needs to be freed */
+        bookmark->label = name;                                   /* needs to be freed */
+        bookmark->icon  = "gnome-fs-directory";
+        bookmark->priv  = (gpointer) pbuser_dir_exists(path);
+        bookmark->free  = pbuser_free_bookmark;
 
-        places_bookmarks_system_bi_system_mod((BookmarksSystem*) b->system, bi);
-
-        g_ptr_array_add(b->bookmarks, bi);
+        bookmarks = g_list_prepend(bookmarks, bookmark);
     }
 
     fclose(fp);
+
+    pbg_priv(bookmark_group)->bookmarks = g_list_reverse(bookmarks);
+    pbg_priv(bookmark_group)->loaded    = pbuser_get_mtime(pbg_priv(bookmark_group)->filename);
 }
 
-static time_t
-places_bookmarks_user_get_mtime(BookmarksUser *b)
+
+static GList*
+pbuser_get_bookmarks(PlacesBookmarkGroup *bookmark_group)
 {
-    struct stat buf;
-    if(g_stat(b->filename, &buf) == 0)
-        return buf.st_mtime;
-    return 0;
-}
+    GList *bookmarks    = pbg_priv(bookmark_group)->bookmarks;
+    GList *clone        = NULL;
+    PlacesBookmark *bookmark;
 
-// external interface
+    if(bookmarks == NULL){
+        pbuser_build_bookmarks(bookmark_group);
+        bookmarks = pbg_priv(bookmark_group)->bookmarks;
+    }
 
-BookmarksUser*
-places_bookmarks_user_init(const BookmarksSystem *system)
-{ 
-    BookmarksUser *b = g_new0(BookmarksUser, 1);
-    
-    g_assert(system != NULL);
-    b->system = system;
+    bookmarks = g_list_last(bookmarks);
 
-    b->filename = xfce_get_homefile(".gtk-bookmarks", NULL);
-    b->bookmarks = g_ptr_array_new();
-    b->loaded = places_bookmarks_user_get_mtime(b);
-    
-    places_bookmarks_user_reinit(b);
-    return b;
+    while(bookmarks != NULL){
+        bookmark        = g_memdup(bookmarks->data, sizeof(PlacesBookmark));
+        bookmark->uri   = g_strdup(bookmark->uri);
+        bookmark->label = g_strdup(bookmark->label);
+
+        clone = g_list_prepend(clone, bookmark);
+        bookmarks = bookmarks->prev;
+    }
+
+    return clone;
+
 }
 
-gboolean
-places_bookmarks_user_changed(BookmarksUser *b)
+static gboolean
+pbuser_changed(PlacesBookmarkGroup *bookmark_group)
 {
+    if(pbg_priv(bookmark_group)->loaded == 0)
+        goto pbuser_did_change;
+
     // see if the file has changed
-    time_t mtime = places_bookmarks_user_get_mtime(b);
+    time_t mtime = pbuser_get_mtime(pbg_priv(bookmark_group)->filename);
+    if(mtime > pbg_priv(bookmark_group)->loaded)
+        goto pbuser_did_change;
     
-    if(mtime > b->loaded){
-        g_ptr_array_foreach(b->bookmarks, (GFunc) places_bookmark_info_free, NULL);
-        g_ptr_array_free(b->bookmarks, TRUE);
-        b->bookmarks = g_ptr_array_new();
-        b->loaded = mtime;
-        places_bookmarks_user_reinit(b);
-        return TRUE;
-    }
-
     // see if any directories have been created or removed
-    guint k;
-    BookmarkInfo *bi;
+    GList *bookmarks = pbg_priv(bookmark_group)->bookmarks;
+    PlacesBookmark *bookmark;
     gboolean ret = FALSE;
 
-    for(k=0; k < b->bookmarks->len; k++){
-        bi = g_ptr_array_index(b->bookmarks, k);
-        if(bi->show != bookmarks_user_dir_exists(bi->uri)){
-            bi->show = !bi->show;
+    while(bookmarks != NULL){
+        bookmark = bookmarks->data;
+        if(show_bookmark(bookmark) != pbuser_dir_exists(bookmark->uri)){
+            bookmark->priv = (gpointer) !show_bookmark(bookmark);
             ret = TRUE;
         }
+        bookmarks = bookmarks->next;
     }
+    return ret;
 
-    return ret;
+  pbuser_did_change:
+    pbuser_destroy_bookmarks(bookmark_group);
+    return TRUE;
 }
 
-void
-places_bookmarks_user_visit(BookmarksUser *b,  BookmarksVisitor *visitor)
+static void
+pbuser_finalize(PlacesBookmarkGroup *bookmark_group)
 {
-    guint k;
-    BookmarkInfo *bi;
-    
-    for(k=0; k < b->bookmarks->len; k++){
-        bi = g_ptr_array_index(b->bookmarks, k);
-        if(bi->show)
-            visitor->item(visitor->pass_thru, bi->label, bi->uri, bi->icon, NULL);
-    }
+    pbuser_destroy_bookmarks(bookmark_group);
+
+    g_free(pbg_priv(bookmark_group)->filename);
+    pbg_priv(bookmark_group)->filename = NULL;
+
+    g_free(pbg_priv(bookmark_group));
+    g_free(bookmark_group);
 }
 
-void
-places_bookmarks_user_finalize(BookmarksUser *b)
-{
-    g_ptr_array_foreach(b->bookmarks, (GFunc) places_bookmark_info_free, NULL);
-    g_ptr_array_free(b->bookmarks, TRUE);
-    b->bookmarks = NULL;
 
-    g_free(b->filename);
-    b->filename = NULL;
+// external interface
 
-    b->system = NULL;
+PlacesBookmarkGroup*
+places_bookmarks_user_create()
+{ 
+    PlacesBookmarkGroup *bookmark_group = g_new0(PlacesBookmarkGroup, 1);
+    bookmark_group->get_bookmarks       = pbuser_get_bookmarks;
+    bookmark_group->changed             = pbuser_changed;
+    bookmark_group->finalize            = pbuser_finalize;
+    bookmark_group->priv                = g_new0(PBUserData, 1);
 
-    g_free(b);
+    pbg_priv(bookmark_group)->filename = xfce_get_homefile(".gtk-bookmarks", NULL);
+    
+    return bookmark_group;
 }
 
 // vim: ai et tabstop=4

Modified: xfce4-places-plugin/trunk/panel-plugin/model_user.h
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/model_user.h	2007-08-10 17:19:20 UTC (rev 2983)
+++ xfce4-places-plugin/trunk/panel-plugin/model_user.h	2007-08-11 06:09:59 UTC (rev 2984)
@@ -21,22 +21,9 @@
 #define _XFCE_PANEL_PLACES_MODEL_USER_H
 
 #include "model.h"
-#include "model_system.h"
-#include <glib.h>
 
-typedef struct _BookmarksUser BookmarksUser;
+PlacesBookmarkGroup*
+places_bookmarks_user_create();
 
-BookmarksUser*
-places_bookmarks_user_init(const BookmarksSystem *system);
-
-void
-places_bookmarks_user_visit(BookmarksUser *b, BookmarksVisitor *visitor);
-
-gboolean
-places_bookmarks_user_changed(BookmarksUser *b);
-
-void
-places_bookmarks_user_finalize(BookmarksUser *b);
-
 #endif
 // vim: ai et tabstop=4

Modified: xfce4-places-plugin/trunk/panel-plugin/model_volumes.c
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/model_volumes.c	2007-08-10 17:19:20 UTC (rev 2983)
+++ xfce4-places-plugin/trunk/panel-plugin/model_volumes.c	2007-08-11 06:09:59 UTC (rev 2984)
@@ -31,176 +31,53 @@
 
 #include <string.h>
 
-struct _BookmarksVolumes
-{
-    GPtrArray *bookmarks;
-    gboolean   changed;
-    ThunarVfsVolumeManager *volume_manager;
-};
+#define pbg_priv(pbg) ((PBVolData*) pbg->priv)
 
-typedef struct {
-    BookmarksVolumes    *b;
-    ThunarVfsVolume     *volume;
-} BookmarksVolumes_Volume;
-
-static gboolean 
-places_bookmarks_volumes_show_volume(ThunarVfsVolume *volume);
-
-static void
-places_bookmarks_volumes_add(BookmarksVolumes *b, const GList *volumes);
-
-
-/********** ThunarVFS Callbacks **********/
-
-static void
-places_bookmarks_volumes_cb_changed(ThunarVfsVolume *volume, 
-                                    BookmarksVolumes *b)
+typedef struct
 {
-    DBG("volume changed"); 
-    // unfortunately there tends to be like 3 of these in a row
 
-    BookmarkInfo *bi;
-    GList *volumes;
-    guint k;
-    
-    b->changed = TRUE;
+    ThunarVfsVolumeManager *volume_manager;
+    gboolean   changed;
 
-    if(places_bookmarks_volumes_show_volume(volume)){
+} PBVolData;
 
-        // make sure it's in the array
-        for(k = 0; k < b->bookmarks->len; k++){
-            bi = g_ptr_array_index(b->bookmarks, k);
-            if(THUNAR_VFS_VOLUME(bi->data) == volume)
-                break;
-        }
 
-        if(k == b->bookmarks->len){ // it's not there
-            DBG("adding volume to array");
+/********** Actions Callbacks **********/
 
-            volumes = g_list_prepend(NULL, volume);
-            places_bookmarks_volumes_add(b, volumes);
-            g_list_free(volumes);
-        }else{
-            DBG("volume already in array");
-        }
-
-    }else{
-        // make sure it's not in the array
-        for(k = 0; k < b->bookmarks->len; k++){
-            bi = g_ptr_array_index(b->bookmarks, k);
-            if(THUNAR_VFS_VOLUME(bi->data) == volume){ // it is there
-                DBG("dropping volume from array");
-                
-                bi = g_ptr_array_remove_index(b->bookmarks, k);
-                g_object_unref(bi->data); // unref the volume
-                bi->data = NULL;
-                places_bookmark_info_free(bi);
-            }
-        }
-    }
-}
-
 static void
-places_bookmarks_volumes_cb_added(ThunarVfsVolumeManager *volume_manager,
-                                  const GList *volumes, 
-                                  BookmarksVolumes *b)
+pbvol_eject(PlacesBookmarkAction *action)
 {
-    DBG("volumes added");
-    places_bookmarks_volumes_add(b, volumes);
-    b->changed = TRUE;
-}
+    DBG("Eject");
 
-static void
-places_bookmarks_volumes_cb_removed(ThunarVfsVolumeManager *volume_manager, 
-                                    const GList *volumes, 
-                                    BookmarksVolumes *b)
-{
-    DBG("volumes removed");
+    ThunarVfsVolume *volume = THUNAR_VFS_VOLUME(action->priv);
 
-    BookmarkInfo *bi;
-    GList *vol_iter;
-    guint k;
-
-    // step through existing bookmarks
-    for(k = 0; k < b->bookmarks->len; k++){
-        bi = g_ptr_array_index(b->bookmarks, k);
-
-        // step through removals
-        vol_iter = (GList*) volumes;
-        while(vol_iter){
-            if(bi->data == vol_iter->data){ // it is there
-                
-                // delete the bookmark
-                bi = g_ptr_array_remove_index(b->bookmarks, k);
-                DBG("Removing bookmark %s", bi->label);
-                
-                if(bi->data != NULL){ // unref the volume
-                    g_object_unref(bi->data);
-                    bi->data = NULL;
-                }
-                places_bookmark_info_free(bi);
-                
-                b->changed = TRUE;
-                break;
-            }
-
-            vol_iter = vol_iter->next;
-        }
-    }
+    thunar_vfs_volume_eject(volume, NULL, NULL);
 }
 
-/********** Actions Callbacks **********/
-
 static void
-places_bookmarks_volumes_unmount(BookmarkAction *act)
+pbvol_unmount(PlacesBookmarkAction *action)
 {
     DBG("Unmount");
-    BookmarksVolumes_Volume *priv = (BookmarksVolumes_Volume*) act->priv;
-    ThunarVfsVolume *volume = priv->volume;
 
-    if(thunar_vfs_volume_is_mounted(volume)){
-        if(thunar_vfs_volume_is_ejectable(volume))
-            thunar_vfs_volume_eject(volume, NULL, NULL);
-        else
-            thunar_vfs_volume_unmount(volume, NULL, NULL);
-    }
+    ThunarVfsVolume *volume = THUNAR_VFS_VOLUME(action->priv);
+
+    if(thunar_vfs_volume_is_mounted(volume))
+        thunar_vfs_volume_unmount(volume, NULL, NULL);
 }
 
 static void
-places_bookmarks_volumes_mount(BookmarkAction *act)
+pbvol_mount(PlacesBookmarkAction *action)
 {
     DBG("Mount");
-    BookmarksVolumes_Volume *priv = (BookmarksVolumes_Volume*) act->priv;
-    ThunarVfsVolume *volume = priv->volume;
-    BookmarksVolumes *b = priv->b;
-    BookmarkInfo *bi;
-    guint k;
 
-    if(!thunar_vfs_volume_is_mounted(volume)){
+    ThunarVfsVolume *volume = THUNAR_VFS_VOLUME(action->priv);
 
+    if(!thunar_vfs_volume_is_mounted(volume))
         thunar_vfs_volume_mount(volume, NULL, NULL);
-    
-        /* it sometimes wouldn't get the mount point right otherwise */
-        for(k = 0; k < b->bookmarks->len; k++){
-            bi = g_ptr_array_index(b->bookmarks, k);
-            if(volume == bi->data){
-
-                if(bi->uri != NULL)
-                    g_free(bi->uri);
-
-                bi->uri = thunar_vfs_path_dup_uri(thunar_vfs_volume_get_mount_point(volume));
-
-                b->changed = TRUE;
-
-                break;
-            }
-        }
-    }
 }
 
-/********** Internal **********/
-static gboolean
-places_bookmarks_volumes_show_volume(ThunarVfsVolume *volume){
+static inline gboolean
+pbvol_show_volume(ThunarVfsVolume *volume){
     
     DBG("Volume: %s [mounted=%x removable=%x present=%x]", thunar_vfs_volume_get_name(volume), 
                                                            thunar_vfs_volume_is_mounted(volume),
@@ -211,156 +88,182 @@
            thunar_vfs_volume_is_present(volume);
 }
 
-
 static void
-places_bookmarks_volumes_add(BookmarksVolumes *b, const GList *volumes)
+pbvol_set_changed(PlacesBookmarkGroup *bookmark_group)
 {
-    ThunarVfsVolume *volume;
-    BookmarkInfo *bi;
-    GtkIconTheme *icon_theme = gtk_icon_theme_get_default();
+    pbg_priv(bookmark_group)->changed = TRUE;
+}
 
-    while(volumes){
-        volume = THUNAR_VFS_VOLUME(volumes->data);
-        
-        g_signal_connect (volume, "changed",
-                      G_CALLBACK(places_bookmarks_volumes_cb_changed), b);
 
-        if(places_bookmarks_volumes_show_volume(volume)){
+static void
+pbvol_volumes_added(ThunarVfsVolumeManager *volman, GList *volumes, PlacesBookmarkGroup *bookmark_group)
+{
+    while(volumes != NULL){
+        g_signal_connect_swapped(THUNAR_VFS_VOLUME(volumes->data), "changed",
+                                 G_CALLBACK(pbvol_set_changed), bookmark_group);
+        volumes = volumes->next;
+    }
+}
 
-            g_object_ref(volume);
-
-            bi          = g_new0(BookmarkInfo, 1);
-            bi->label   = g_strdup( thunar_vfs_volume_get_name(volume) );
-            bi->uri     = thunar_vfs_path_dup_uri( thunar_vfs_volume_get_mount_point(volume) );
-            bi->icon    = g_strdup( thunar_vfs_volume_lookup_icon_name(volume, icon_theme) );
-            bi->data    = (gpointer) volume;
-
-            g_ptr_array_add(b->bookmarks, bi);
-        }
-
+static void
+pbvol_volumes_removed(ThunarVfsVolumeManager *volman, GList *volumes, PlacesBookmarkGroup *bookmark_group)
+{
+    while(volumes != NULL){
+        g_signal_handlers_disconnect_by_func(THUNAR_VFS_VOLUME(volumes->data),
+                                             G_CALLBACK(pbvol_set_changed), bookmark_group);
         volumes = volumes->next;
     }
 }
 
-/********** External **********/
-
-BookmarksVolumes*
-places_bookmarks_volumes_init()
+static void
+pbvol_bookmark_free(PlacesBookmark *bookmark)
 {
-    DBG("init");
-    BookmarksVolumes *b = g_new0(BookmarksVolumes, 1);
+    if(bookmark->uri != NULL)
+        g_free(bookmark->uri);
+    g_free(bookmark);
+}
 
-    thunar_vfs_init();
+static void
+pbvol_bookmark_action_free(PlacesBookmarkAction *action){
+    g_assert(action != NULL && action->priv != NULL);
+
+    ThunarVfsVolume *volume = THUNAR_VFS_VOLUME(action->priv);
+    g_object_unref(volume);
+    action->priv = NULL;
+
+    g_free(action);
+}
+
+static GList*
+pbvol_get_bookmarks(PlacesBookmarkGroup *bookmark_group)
+{
+    GList *bookmarks = NULL;
+    PlacesBookmark *bookmark;
+    PlacesBookmarkAction *action;
     
-    b->bookmarks = g_ptr_array_new();
-    b->changed = FALSE;
-    b->volume_manager = thunar_vfs_volume_manager_get_default();
-    
-    places_bookmarks_volumes_add(b, thunar_vfs_volume_manager_get_volumes(b->volume_manager));
+    GList *volumes = thunar_vfs_volume_manager_get_volumes(pbg_priv(bookmark_group)->volume_manager);
+    ThunarVfsVolume *volume;
 
-    g_signal_connect (b->volume_manager, "volumes-added",
-                      G_CALLBACK (places_bookmarks_volumes_cb_added), b);
+    GtkIconTheme *icon_theme = gtk_icon_theme_get_default();
 
-    g_signal_connect (b->volume_manager, "volumes-removed",
-                      G_CALLBACK (places_bookmarks_volumes_cb_removed), b);
+    while(volumes != NULL){
+        volume = THUNAR_VFS_VOLUME(volumes->data);
 
-    DBG("done");
+        if(pbvol_show_volume(volume)){
 
-    return b;
-}
+            bookmark        = g_new0(PlacesBookmark, 1);
+            bookmark->label = (gchar*) thunar_vfs_volume_get_name(volume);
+            if(thunar_vfs_volume_is_mounted(volume))
+                bookmark->uri   = thunar_vfs_path_dup_uri(thunar_vfs_volume_get_mount_point(volume));
+            else
+                bookmark->uri   = NULL;
+            bookmark->icon  = (gchar*) thunar_vfs_volume_lookup_icon_name(volume, icon_theme);
+            bookmark->free  = pbvol_bookmark_free;
 
-void
-places_bookmarks_volumes_finalize(BookmarksVolumes *b)
-{
-    BookmarkInfo *bi;
-    guint k;
+            if(!thunar_vfs_volume_is_mounted(volume)){
+                g_object_ref(volume);
+                action          = g_new0(PlacesBookmarkAction, 1);
+                action->label   = _("Mount");
+                action->priv    = volume;
+                action->action  = pbvol_mount;
+                action->free    = pbvol_bookmark_action_free;
+                bookmark->actions = g_list_append(bookmark->actions, action);
+            }
 
-    for(k = 0; k < b->bookmarks->len; k++){
-        bi = g_ptr_array_remove_index(b->bookmarks, k);
-        if(bi->data != NULL){ // unref the volume
-            g_object_unref(bi->data);
-            bi->data = NULL;
+            if(thunar_vfs_volume_is_disc(volume)){
+                if(thunar_vfs_volume_is_ejectable(volume)){
+                    g_object_ref(volume);
+                    action          = g_new0(PlacesBookmarkAction, 1);
+                    action->label   = _("Eject");
+                    action->priv    = volume;
+                    action->action  = pbvol_eject;
+                    action->free    = pbvol_bookmark_action_free;
+                    bookmark->actions = g_list_append(bookmark->actions, action);
+                }
+            }else{
+                if(thunar_vfs_volume_is_mounted(volume)){
+                    g_object_ref(volume);
+                    action          = g_new0(PlacesBookmarkAction, 1);
+                    action->label   = _("Unmount");
+                    action->priv    = volume;
+                    action->action  = pbvol_unmount;
+                    action->free    = pbvol_bookmark_action_free;
+                    bookmark->actions = g_list_append(bookmark->actions, action);
+                }
+            }
+
+            bookmarks = g_list_prepend(bookmarks, bookmark);
         }
-        places_bookmark_info_free(bi);
-    }
 
-    g_object_unref(b->volume_manager);
-    b->volume_manager = NULL;
-    thunar_vfs_shutdown();
+        volumes = volumes->next;
+    }
     
-    g_ptr_array_foreach(b->bookmarks, (GFunc) places_bookmark_info_free, NULL);
-    g_ptr_array_free(b->bookmarks, TRUE);
-    b->bookmarks = NULL;
+    pbg_priv(bookmark_group)->changed = FALSE;
 
-    g_free(b);
+    return g_list_reverse(bookmarks);
+
 }
 
-gboolean
-places_bookmarks_volumes_changed(BookmarksVolumes *b)
+
+static gboolean
+pbvol_changed(PlacesBookmarkGroup *bookmark_group)
 {
-    if(b->changed){
-        b->changed = FALSE;
-        return TRUE;
-    }else{
-        return FALSE;
-    }
+    return pbg_priv(bookmark_group)->changed;
 }
 
+
 static void
-free_toggle_mount_action(BookmarkAction *act)
+pbvol_finalize(PlacesBookmarkGroup *bookmark_group)
 {
-    g_assert(act != NULL);
-    g_assert(act->priv != NULL);
+    GList *volumes = thunar_vfs_volume_manager_get_volumes(pbg_priv(bookmark_group)->volume_manager);
+    while(volumes != NULL){
+        g_signal_handlers_disconnect_by_func(THUNAR_VFS_VOLUME(volumes->data),
+                                             G_CALLBACK(pbvol_set_changed), bookmark_group);
+        volumes = volumes->next;
+    }
 
-    g_free(act->priv);
-    g_free(act);
+    g_signal_handlers_disconnect_by_func(pbg_priv(bookmark_group)->volume_manager,
+                                         G_CALLBACK(pbvol_volumes_added), bookmark_group);
+    g_signal_handlers_disconnect_by_func(pbg_priv(bookmark_group)->volume_manager,
+                                         G_CALLBACK(pbvol_volumes_removed), bookmark_group);
+    g_object_unref(pbg_priv(bookmark_group)->volume_manager);
+    pbg_priv(bookmark_group)->volume_manager = NULL;
+    thunar_vfs_shutdown();
+    
+    g_free(bookmark_group->priv);
+    g_free(bookmark_group);
 }
 
-void
-places_bookmarks_volumes_visit(BookmarksVolumes *b, BookmarksVisitor *visitor)
-{
-    guint k;
-    BookmarkInfo *bi;
-    GSList *actions;
-    ThunarVfsVolume *volume;
-    gchar *uri;
-    BookmarkAction *toggle_mount;
-    BookmarksVolumes_Volume *toggle_mount_priv;
 
-    for(k=0; k < b->bookmarks->len; k++){
-        bi = g_ptr_array_index(b->bookmarks, k);
-        volume = THUNAR_VFS_VOLUME(bi->data);
 
-        toggle_mount_priv = g_new0(BookmarksVolumes_Volume, 1);
-        toggle_mount_priv->b = b;
-        toggle_mount_priv->volume = volume;
+PlacesBookmarkGroup*
+places_bookmarks_volumes_create()
+{
+    PlacesBookmarkGroup *bookmark_group = g_new0(PlacesBookmarkGroup, 1);
+    bookmark_group->get_bookmarks       = pbvol_get_bookmarks;
+    bookmark_group->changed             = pbvol_changed;
+    bookmark_group->finalize            = pbvol_finalize;
+    bookmark_group->priv                = g_new0(PBVolData, 1);
+    
 
-        toggle_mount = g_new0(BookmarkAction, 1); /* visitor will free */
-        toggle_mount->priv = toggle_mount_priv;
-        toggle_mount->free = free_toggle_mount_action;
-        
-        actions = g_slist_prepend(NULL, toggle_mount);
+    thunar_vfs_init();
+    pbg_priv(bookmark_group)->volume_manager = thunar_vfs_volume_manager_get_default();
+    pbg_priv(bookmark_group)->changed        = TRUE;
     
-        if(thunar_vfs_volume_is_mounted(volume)){
+    GList *volumes = thunar_vfs_volume_manager_get_volumes(pbg_priv(bookmark_group)->volume_manager);
+    while(volumes != NULL){
+        g_signal_connect_swapped(THUNAR_VFS_VOLUME(volumes->data), "changed",
+                                 G_CALLBACK(pbvol_set_changed), bookmark_group);
+        volumes = volumes->next;
+    }
 
-            if(thunar_vfs_volume_is_ejectable(volume))
-                toggle_mount->label = _("Eject Volume");
-            else
-                toggle_mount->label = _("Unmount Volume");
-            toggle_mount->action = places_bookmarks_volumes_unmount;
+    g_signal_connect(pbg_priv(bookmark_group)->volume_manager, "volumes-added",
+                     G_CALLBACK(pbvol_volumes_added), bookmark_group);
 
-            uri = bi->uri;
+    g_signal_connect(pbg_priv(bookmark_group)->volume_manager, "volumes-removed",
+                     G_CALLBACK(pbvol_volumes_removed), bookmark_group);
 
-        }else{
-
-            toggle_mount->label = _("Mount Volume");
-            toggle_mount->action = places_bookmarks_volumes_mount;
-
-            uri = NULL;
-        }
-
-        visitor->item(visitor->pass_thru, bi->label, uri, bi->icon, actions);
-    }
+    return bookmark_group;
 }
 
 

Modified: xfce4-places-plugin/trunk/panel-plugin/model_volumes.h
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/model_volumes.h	2007-08-10 17:19:20 UTC (rev 2983)
+++ xfce4-places-plugin/trunk/panel-plugin/model_volumes.h	2007-08-11 06:09:59 UTC (rev 2984)
@@ -21,21 +21,9 @@
 #define _XFCE_PANEL_PLACES_MODEL_VOLUMES_H
 
 #include "model.h"
-#include <glib.h>
 
-typedef struct _BookmarksVolumes BookmarksVolumes;
+PlacesBookmarkGroup*
+places_bookmarks_volumes_create();
 
-BookmarksVolumes*
-places_bookmarks_volumes_init();
-
-void
-places_bookmarks_volumes_visit(BookmarksVolumes *b, BookmarksVisitor *visitor);
-
-gboolean
-places_bookmarks_volumes_changed(BookmarksVolumes *b);
-
-void
-places_bookmarks_volumes_finalize(BookmarksVolumes *b);
-
 #endif
 // vim: ai et tabstop=4

Modified: xfce4-places-plugin/trunk/panel-plugin/places.c
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/places.c	2007-08-10 17:19:20 UTC (rev 2983)
+++ xfce4-places-plugin/trunk/panel-plugin/places.c	2007-08-11 06:09:59 UTC (rev 2984)
@@ -27,7 +27,6 @@
 #include <exo/exo.h>
 
 #include "places.h"
-#include "model.h"
 #include "view.h"
 
 #include "string.h" // for strncmp
@@ -42,9 +41,8 @@
  *
  * 1. Sets up i18n
  * 2. Creates the PlacesData struct
- * 3. Asks the model to initialize
- * 4. Asks the view to initialize
- * 5. Connects the finalize callback.
+ * 3. Asks the view to initialize
+ * 4. Connects the finalize callback.
  */
 static void 
 places_construct(XfcePanelPlugin *plugin)
@@ -58,9 +56,6 @@
     PlacesData *pd = panel_slice_new0(PlacesData);
     pd->plugin = plugin;
 
-    // Initialize model
-    pd->bookmarks = places_bookmarks_init();
-
     // Initialize view
     places_view_init(pd);
 
@@ -74,8 +69,7 @@
  * Cleans up resources.
  *
  * 1. Asks the view to finalize
- * 2. Asks the model to finalize
- * 3. Frees the PlacesData struct
+ * 2. Frees the PlacesData struct
  */
 static void 
 places_finalize(XfcePanelPlugin *plugin, PlacesData *pd)
@@ -86,9 +80,6 @@
     // finalize the view
     places_view_finalize(pd);
     
-    // finalize the model
-    places_bookmarks_finalize(pd->bookmarks);
-
     // free the PlacesData struct
     panel_slice_free(PlacesData, pd);
 }

Modified: xfce4-places-plugin/trunk/panel-plugin/places.h
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/places.h	2007-08-10 17:19:20 UTC (rev 2983)
+++ xfce4-places-plugin/trunk/panel-plugin/places.h	2007-08-11 06:09:59 UTC (rev 2984)
@@ -47,8 +47,7 @@
   gboolean           view_needs_separator;
 
   // model
-  gpointer           bookmarks;
-
+  GList *bookmark_groups;
 };
 
 void places_load_thunar(const gchar *path);

Modified: xfce4-places-plugin/trunk/panel-plugin/view.c
===================================================================
--- xfce4-places-plugin/trunk/panel-plugin/view.c	2007-08-10 17:19:20 UTC (rev 2983)
+++ xfce4-places-plugin/trunk/panel-plugin/view.c	2007-08-11 06:09:59 UTC (rev 2984)
@@ -43,6 +43,9 @@
 #include "view.h"
 #include "places.h"
 #include "model.h"
+#include "model_system.h"
+#include "model_volumes.h"
+#include "model_user.h"
 #include "cfg.h"
 
 // UI Helpers
@@ -76,9 +79,7 @@
 #endif
 
 // Model Visitor Callbacks
-static void     places_view_add_menu_item(gpointer _places_data, 
-                                   const gchar *label, const gchar *uri, const gchar *icon, GSList *actions);
-static void     places_view_lazy_add_menu_sep(gpointer _places_data);
+static void     places_view_add_menu_item(PlacesData*, PlacesBookmark*);
 
 /********** Initialization & Finalization **********/
 void
@@ -166,20 +167,46 @@
     if(pd->view_button_label != NULL)
         g_object_unref(pd->view_button_label);
     g_object_unref(pd->view_tooltips);
- 
+
+    if(pd->bookmark_groups != NULL){
+        GList *bookmark_group = pd->bookmark_groups;
+        while(bookmark_group != NULL){
+            if(bookmark_group->data != NULL)
+               places_bookmark_group_finalize((PlacesBookmarkGroup*) bookmark_group->data);
+            bookmark_group = bookmark_group->next;
+        }
+        g_list_free(pd->bookmark_groups);
+        pd->bookmark_groups = NULL;
+    }
+
     places_cfg_finalize(pd);
 }
 
 void
 places_view_reconfigure_model(PlacesData *pd)
 {
-    gint model_enable;
-    model_enable = PLACES_BOOKMARKS_ENABLE_NONE;
+    /* destroy first */
+    if(pd->bookmark_groups != NULL){
+        GList *bookmark_group = pd->bookmark_groups;
+        while(bookmark_group != NULL){
+            if(bookmark_group->data != NULL)
+                places_bookmark_group_finalize((PlacesBookmarkGroup*) bookmark_group->data);
+            bookmark_group = bookmark_group->next;
+        }
+        g_list_free(pd->bookmark_groups);
+        pd->bookmark_groups = NULL;
+    }
+
+    /* now create */
+    pd->bookmark_groups = g_list_append(pd->bookmark_groups, places_bookmarks_system_create());
+
     if(pd->cfg->show_volumes)
-        model_enable |= PLACES_BOOKMARKS_ENABLE_VOLUMES;
-    if(pd->cfg->show_bookmarks)
-        model_enable |= PLACES_BOOKMARKS_ENABLE_USER;
-    places_bookmarks_enable(pd->bookmarks, model_enable);
+        pd->bookmark_groups = g_list_append(pd->bookmark_groups, places_bookmarks_volumes_create());
+
+    if(pd->cfg->show_bookmarks){
+        pd->bookmark_groups = g_list_append(pd->bookmark_groups, NULL); /* separator */
+        pd->bookmark_groups = g_list_append(pd->bookmark_groups, places_bookmarks_user_create());
+    }
 }
 
 /********** UI Helpers **********/
@@ -187,7 +214,6 @@
 static void
 places_view_update_menu(PlacesData *pd)
 {
-    BookmarksVisitor visitor;
 #if USE_RECENT_DOCUMENTS
     GtkWidget *recent_menu;
     GtkWidget *clear_item;
@@ -204,13 +230,30 @@
     gtk_menu_set_screen (GTK_MENU (pd->view_menu),
                          gtk_widget_get_screen (GTK_WIDGET (pd->plugin)));
 
+    GList *bookmark_group = pd->bookmark_groups;
+    GList *bookmarks;
+    PlacesBookmark *bookmark;
+    while(bookmark_group != NULL){
+        
+        if(bookmark_group->data == NULL){ /* separator */
 
-    // Add system, volumes, user bookmarks
-    visitor.pass_thru  = pd;
-    visitor.item       = places_view_add_menu_item;
-    visitor.separator  = places_view_lazy_add_menu_sep;
-    places_bookmarks_visit(pd->bookmarks, &visitor);
+            pd->view_needs_separator = TRUE;
 
+        }else{
+
+            bookmarks = places_bookmark_group_get_bookmarks((PlacesBookmarkGroup*) bookmark_group->data);
+    
+            while(bookmarks != NULL){
+                bookmark = (PlacesBookmark*) bookmarks->data;
+                places_view_add_menu_item(pd, bookmark);
+                bookmarks = bookmarks->next;
+            }
+
+        }
+
+        bookmark_group = bookmark_group->next;
+    }
+
     // Recent Documents
 #if USE_RECENT_DOCUMENTS
     if(pd->cfg->show_recent || (pd->cfg->search_cmd != NULL && strlen(pd->cfg->search_cmd))){
@@ -285,12 +328,28 @@
     gtk_widget_realize(pd->view_menu);
 }
 
+static gboolean
+places_view_bookmarks_changed(GList *bookmark_groups)
+{
+    gboolean ret = FALSE;
+    GList *bookmark_group = bookmark_groups;
 
+    while(bookmark_group != NULL){
+
+        if(bookmark_group->data != NULL)
+            ret = places_bookmark_group_changed((PlacesBookmarkGroup*) bookmark_group->data) || ret;
+
+        bookmark_group = bookmark_group->next;
+    }
+
+    return ret;
+}
+
 void
 places_view_open_menu(PlacesData *pd)
 {
     /* check if menu is needed, or it needs an update */
-    if(pd->view_menu == NULL || places_bookmarks_changed(pd->bookmarks))
+    if(pd->view_menu == NULL || places_view_bookmarks_changed(pd->bookmark_groups))
         places_view_update_menu(pd);
 
     /* toggle the button */
@@ -522,7 +581,6 @@
 void
 places_view_cb_menu_item_context_act(GtkWidget *item, PlacesData *pd)
 {
-    BookmarkAction *action;
     g_assert(pd != NULL);
     g_assert(pd->view_menu != NULL && GTK_IS_WIDGET(pd->view_menu));
 
@@ -531,38 +589,49 @@
     while(g_main_context_iteration(NULL, FALSE))
         /* no op */;
 
-    action = (BookmarkAction*) g_object_get_data(G_OBJECT(item), "action");
+    PlacesBookmarkAction *action = (PlacesBookmarkAction*) g_object_get_data(G_OBJECT(item), "action");
     DBG("Calling action %s", action->label);
     places_bookmark_action_call(action);
-
+    
 }
 
 gboolean
 places_view_cb_menu_item_do_alt(PlacesData *pd, GtkWidget *menu_item)
 {
-        const GSList *actions = (const GSList*) g_object_get_data(G_OBJECT(menu_item), "actions");
-        if(actions != NULL){
     
-            GtkWidget *context = gtk_menu_new();
-            gtk_widget_show(context);
-            while(actions != NULL){
-                BookmarkAction *action = (BookmarkAction*) actions->data;
-                GtkWidget *context_item = gtk_menu_item_new_with_label(action->label);
-                g_object_set_data(G_OBJECT(context_item), "action", action);
-                gtk_widget_show(context_item);
-                g_signal_connect(context_item, "activate",
-                                 G_CALLBACK(places_view_cb_menu_item_context_act), pd);
-                gtk_menu_shell_append(GTK_MENU_SHELL(context), context_item);
-                actions = actions->next;
-            }
-            gtk_menu_popup(GTK_MENU(context),
-                           NULL, NULL,
-                           NULL, NULL,
-                           0, gtk_get_current_event_time());
-            g_signal_connect_swapped(context, "deactivate", G_CALLBACK(places_view_open_menu), pd);
+    GList *actions = (GList*) g_object_get_data(G_OBJECT(menu_item), "actions");
+    GtkWidget *context, *context_item;
+    PlacesBookmarkAction *action;
+
+
+    if(actions != NULL){
+
+        context = gtk_menu_new();
+        gtk_widget_show(context);
+
+        while(actions != NULL){
+            action = (PlacesBookmarkAction*) actions->data;
+
+            context_item = gtk_menu_item_new_with_label(action->label);
+            g_object_set_data(G_OBJECT(context_item), "action", action);
+            gtk_widget_show(context_item);
+            g_signal_connect(context_item, "activate",
+                             G_CALLBACK(places_view_cb_menu_item_context_act), pd);
+            gtk_menu_shell_append(GTK_MENU_SHELL(context), context_item);
+
+            actions = actions->next;
         }
 
-        return TRUE;
+        gtk_menu_popup(GTK_MENU(context),
+                       NULL, NULL,
+                       NULL, NULL,
+                       0, gtk_get_current_event_time());
+
+        g_signal_connect_swapped(context, "deactivate", G_CALLBACK(places_view_open_menu), pd);
+
+    }
+
+    return TRUE;
 }
 
 gboolean
@@ -616,20 +685,21 @@
 
 /********** Model Visitor Callbacks **********/
 
+
 static void
-places_view_load_terminal_wrapper(BookmarkAction *act)
+places_view_load_terminal_wrapper(PlacesBookmarkAction *act)
 {
     g_assert(act != NULL);
     places_load_terminal((gchar*) act->priv);
 }
 
+
 static void
-places_view_add_menu_item(gpointer _pd, const gchar *label, const gchar *uri, const gchar *icon, GSList *actions)
+places_view_add_menu_item(PlacesData *pd, PlacesBookmark *bookmark)
 {
-    g_assert(_pd != NULL);
-    g_return_if_fail(label != NULL && strlen(label));
+    g_assert(pd != NULL);
+    g_assert(bookmark != NULL);
 
-    PlacesData *pd = (PlacesData*) _pd;
     GtkWidget *item;
 
     if(pd->view_needs_separator){
@@ -638,10 +708,10 @@
         pd->view_needs_separator = FALSE;
     }
 
-    item = gtk_image_menu_item_new_with_label(label);
+    item = gtk_image_menu_item_new_with_label(bookmark->label);
 
-    if(pd->cfg->show_icons && icon != NULL){
-        GdkPixbuf *pb = xfce_themed_icon_load(icon, 16);
+    if(pd->cfg->show_icons && bookmark->icon != NULL){
+        GdkPixbuf *pb = xfce_themed_icon_load(bookmark->icon, 16);
         
         if(G_LIKELY(pb != NULL)){
             GtkWidget *image = gtk_image_new_from_pixbuf(pb);
@@ -650,43 +720,36 @@
         }
     }
 
-    if(uri != NULL){
+    if(bookmark->uri != NULL){
         
-        g_object_set_data(G_OBJECT(item), "uri", (gchar*) uri);
+        g_object_set_data(G_OBJECT(item), "uri", (gchar*) bookmark->uri);
 
-        if(strncmp(uri, "trash://", 8) != 0){
-            BookmarkAction *terminal = g_new0(BookmarkAction, 1);
-            terminal->label = "Open Terminal Here";
-            terminal->priv = (gchar*) uri;
-            terminal->action = places_view_load_terminal_wrapper;
-            terminal->free = NULL;
-            actions = g_slist_append(actions, terminal);
+        if(bookmark->uri_scheme != PLACES_URI_SCHEME_TRASH){
+            PlacesBookmarkAction *terminal  = g_new0(PlacesBookmarkAction, 1);
+            terminal->label                 = "Open Terminal Here";
+            terminal->priv                  = (gchar*) bookmark->uri;
+            terminal->action                = places_view_load_terminal_wrapper;
+            bookmark->actions = g_list_append(bookmark->actions, terminal);
         }
 
     }else{
         /* Probably an unmounted volume. Gray it out. */
         gtk_widget_set_sensitive(gtk_bin_get_child(GTK_BIN(item)), FALSE);
     }
- 
 
-    if(actions != NULL)
-        g_object_set_data_full(G_OBJECT(item), "actions", actions, (GDestroyNotify) places_bookmark_actions_list_destroy);
-        
+    if(bookmark->actions != NULL)
+        g_object_set_data(G_OBJECT(item), "actions", bookmark->actions);
+
+
     g_signal_connect(item, "button-release-event",
                      G_CALLBACK(places_view_cb_menu_item_press), pd);
     g_signal_connect_swapped(item, "activate",
                      G_CALLBACK(places_view_cb_menu_item_do_main), pd);
+    g_signal_connect_swapped(item, "destroy",
+                     G_CALLBACK(places_bookmark_free), bookmark);
 
     gtk_menu_shell_append(GTK_MENU_SHELL(pd->view_menu), item);
 
 }
 
-static void
-places_view_lazy_add_menu_sep(gpointer _pd)
-{
-    g_assert(_pd != NULL);
-    PlacesData *pd = (PlacesData*) _pd;
-    pd->view_needs_separator = TRUE;
-}
-
 // vim: ai et tabstop=4




More information about the Goodies-commits mailing list