[gtk+/wip/csoriano/bookmarks: 41/41] gtkplacesidebar: use GtkListBox



commit 3f66a71a318b761d9a99c3dde8f22c42cc1b63c4
Author: Carlos Soriano <csoriano gnome org>
Date:   Wed May 6 23:07:17 2015 +0200

    gtkplacesidebar: use GtkListBox
    
    We were using GTkTreeView in a simple list. Also, as we know,
    GtkCellRenderers are not the best way to theme and manipulate
    widgets.
    
    So instead use a GtkListBox to modernize the GtkPlacesSidebar,
    and in the way clean up some parts of the code (like headings)
    which were not used anymore.
    Also we don't use a model anymore, since the data is simple
    enough to manage it in a subclass of the row itself.

 gtk/gtkplacessidebar.c |  367 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 360 insertions(+), 7 deletions(-)
---
diff --git a/gtk/gtkplacessidebar.c b/gtk/gtkplacessidebar.c
index 78720cf..e35f267 100644
--- a/gtk/gtkplacessidebar.c
+++ b/gtk/gtkplacessidebar.c
@@ -44,6 +44,7 @@
 #include "config.h"
 
 #include <gio/gio.h>
+#include <gtk/gtk.h>
 
 #include "gdk/gdkkeysyms.h"
 #include "gtkbookmarksmanager.h"
@@ -70,6 +71,7 @@
 #include "gtkgrid.h"
 #include "gtklabel.h"
 #include "gtkbutton.h"
+#include "gtklistbox.h"
 
 /**
  * SECTION:gtkplacessidebar
@@ -129,6 +131,8 @@ typedef enum {
 struct _GtkPlacesSidebar {
   GtkScrolledWindow parent;
 
+  GtkWidget *list_box;
+
   GtkTreeView       *tree_view;
   GtkCellRenderer   *eject_icon_cell_renderer;
   GtkCellRenderer   *text_cell_renderer;
@@ -230,6 +234,7 @@ enum {
 };
 
 typedef enum {
+  PLACES_0,
   PLACES_BUILT_IN,
   PLACES_XDG_DIR,
   PLACES_MOUNTED_VOLUME,
@@ -237,14 +242,17 @@ typedef enum {
   PLACES_HEADING,
   PLACES_CONNECT_TO_SERVER,
   PLACES_ENTER_LOCATION,
-  PLACES_DROP_FEEDBACK
+  PLACES_DROP_FEEDBACK,
+  N_PLACES
 } PlaceType;
 
 typedef enum {
+  SECTION_0,
   SECTION_DEVICES,
   SECTION_BOOKMARKS,
   SECTION_COMPUTER,
-  SECTION_NETWORK
+  SECTION_NETWORK,
+  N_SECTIONS
 } SectionType;
 
 enum {
@@ -347,6 +355,176 @@ static GtkListStore *shortcuts_model_new (GtkPlacesSidebar *sidebar);
 
 G_DEFINE_TYPE (GtkPlacesSidebar, gtk_places_sidebar, GTK_TYPE_SCROLLED_WINDOW);
 
+#define SIDEBAR_TYPE_ROW (sidebar_row_get_type ())
+G_DECLARE_DERIVABLE_TYPE (SidebarRow, sidebar_row, SIDEBAR, ROW, GtkListBoxRow)
+
+struct _SidebarRowClass
+{
+  GtkListBoxRowClass parent_class;
+};
+
+typedef struct
+{
+  gint section_type;
+  gint place_type;
+  gchar *label;
+  GIcon *icon;
+  GtkWidget *icon_widget;
+  GtkWidget *label_widget;
+} SidebarRowPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (SidebarRow, sidebar_row, GTK_TYPE_LIST_BOX_ROW)
+
+enum
+{
+  PROP_0,
+  PROP_LABEL,
+  PROP_SECTION_TYPE,
+  PROP_PLACE_TYPE,
+  PROP_ICON,
+  LAST_PROP
+};
+
+static GParamSpec *gParamSpecs [LAST_PROP];
+
+static void
+sidebar_row_get_property (GObject    *object,
+                          guint       prop_id,
+                          GValue     *value,
+                          GParamSpec *pspec)
+{
+  SidebarRow *self = SIDEBAR_ROW (object);
+  SidebarRowPrivate *priv = sidebar_row_get_instance_private (self);
+
+  switch (prop_id)
+    {
+    case PROP_LABEL:
+      g_value_set_string (value, priv->label);
+      break;
+
+    case PROP_SECTION_TYPE:
+      g_value_set_int (value, priv->section_type);
+      break;
+
+    case PROP_PLACE_TYPE:
+      g_value_set_int (value, priv->place_type);
+      break;
+
+    case PROP_ICON:
+      g_value_set_object (value, priv->icon);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sidebar_row_set_property (GObject      *object,
+                          guint         prop_id,
+                          const GValue *value,
+                          GParamSpec   *pspec)
+{
+  SidebarRow *self = SIDEBAR_ROW (object);
+  SidebarRowPrivate *priv = sidebar_row_get_instance_private (self);
+
+  switch (prop_id)
+    {
+    case PROP_LABEL:
+      {
+        g_free (priv->label);
+        priv->label = g_strdup (g_value_get_string (value));
+        gtk_label_set_text (GTK_LABEL (priv->label_widget), priv->label);
+        break;
+      }
+
+    case PROP_SECTION_TYPE:
+      {
+        priv->section_type = g_value_get_int (value);
+        break;
+      }
+
+    case PROP_PLACE_TYPE:
+      {
+        priv->place_type = g_value_get_int (value);
+        break;
+      }
+
+    case PROP_ICON:
+      {
+        g_clear_object (&priv->icon);
+        priv->icon = g_object_ref (g_value_get_object (value));
+        gtk_image_set_from_gicon (GTK_IMAGE (priv->icon_widget), priv->icon, GTK_ICON_SIZE_MENU);
+        break;
+      }
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+sidebar_row_init (SidebarRow *self)
+{
+  GtkWidget *hbox;
+  GtkWidget *eject_icon;
+  SidebarRowPrivate *priv = sidebar_row_get_instance_private (self);
+
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
+  priv->icon_widget = gtk_image_new ();
+  gtk_container_add (GTK_CONTAINER (hbox), priv->icon_widget);
+  priv->label_widget = gtk_label_new (NULL);
+  gtk_container_add (GTK_CONTAINER (hbox), priv->label_widget);
+  eject_icon = gtk_button_new_from_icon_name ("media-eject-symbolic", GTK_ICON_SIZE_MENU);
+  gtk_widget_set_hexpand (eject_icon, TRUE);
+  gtk_widget_set_halign (eject_icon, GTK_ALIGN_END);
+  gtk_widget_set_valign (eject_icon, GTK_ALIGN_CENTER);
+  gtk_container_add (GTK_CONTAINER (hbox), eject_icon);
+
+  gtk_container_add (GTK_CONTAINER (self), hbox);
+}
+
+static void
+sidebar_row_class_init (SidebarRowClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  object_class->get_property = sidebar_row_get_property;
+  object_class->set_property = sidebar_row_set_property;
+
+
+  gParamSpecs [PROP_LABEL] =
+    g_param_spec_string ("label",
+                         "label",
+                         "The label text.",
+                         NULL,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (object_class, PROP_LABEL, gParamSpecs [PROP_LABEL]);
+
+  gParamSpecs [PROP_SECTION_TYPE] =
+    g_param_spec_int ("section-type",
+                      "section type",
+                      "The section type.",
+                      SECTION_0, N_SECTIONS, SECTION_0,
+                      (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class, PROP_SECTION_TYPE, gParamSpecs [PROP_SECTION_TYPE]);
+
+  gParamSpecs [PROP_PLACE_TYPE] =
+    g_param_spec_int ("place-type",
+                      "place type",
+                      "The place type.",
+                      PLACES_0, N_PLACES, PLACES_0,
+                      (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class, PROP_PLACE_TYPE, gParamSpecs [PROP_PLACE_TYPE]);
+
+  gParamSpecs [PROP_ICON] =
+    g_param_spec_object ("icon",
+                      "icon",
+                      "The place icon.",
+                      G_TYPE_ICON,
+                      (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (object_class, PROP_ICON, gParamSpecs [PROP_ICON]);
+}
+
 static void
 emit_open_location (GtkPlacesSidebar   *sidebar,
                     GFile              *location,
@@ -457,6 +635,35 @@ add_heading (GtkPlacesSidebar *sidebar,
 }
 
 static void
+check_separator_for_section (GtkPlacesSidebar *sidebar,
+                             GtkListBoxRow    *row,
+                             SectionType       section_type)
+{
+
+  switch (section_type)
+    {
+    case SECTION_DEVICES:
+      if (!sidebar->devices_header_added)
+        {
+          gtk_list_box_row_set_header (row, gtk_separator_new (GTK_ORIENTATION_HORIZONTAL));
+          sidebar->devices_header_added = TRUE;
+        }
+      break;
+
+    case SECTION_BOOKMARKS:
+      if (!sidebar->bookmarks_header_added)
+        {
+          gtk_list_box_row_set_header (row, gtk_separator_new (GTK_ORIENTATION_HORIZONTAL));
+          sidebar->bookmarks_header_added = TRUE;
+        }
+      break;
+
+    default:
+      break;
+  }
+}
+
+static void
 check_heading_for_section (GtkPlacesSidebar *sidebar,
                            SectionType       section_type)
 {
@@ -500,8 +707,6 @@ add_place (GtkPlacesSidebar *sidebar,
   gboolean show_eject, show_unmount;
   gboolean show_eject_button;
 
-  check_heading_for_section (sidebar, section_type);
-
   check_unmount_and_eject (mount, volume, drive,
                            &show_unmount, &show_eject);
 
@@ -920,6 +1125,147 @@ out:
 }
 
 static void
+add_place2 (GtkPlacesSidebar *self,
+            PlaceType         place_type,
+            SectionType       section_type,
+            const gchar      *name,
+            GIcon            *icon,
+            const gchar      *uri,
+            GDrive           *drive,
+            GVolume          *volume,
+            GMount           *mount,
+            const gint        index,
+            const gchar      *tooltip)
+{
+  gboolean show_eject, show_unmount;
+  gboolean show_eject_button;
+  SidebarRow *row;
+
+
+  check_unmount_and_eject (mount, volume, drive,
+                           &show_unmount, &show_eject);
+
+  if (show_unmount || show_eject)
+    g_assert (place_type != PLACES_BOOKMARK);
+
+  if (mount == NULL)
+    show_eject_button = FALSE;
+  else
+    show_eject_button = (show_unmount || show_eject);
+
+  row = g_object_new (SIDEBAR_TYPE_ROW,
+                      "label", name,
+                      "icon", icon,
+                      "section-type", section_type,
+                      "place-type", place_type,
+                      NULL);
+
+  check_separator_for_section (self, GTK_LIST_BOX_ROW (row), section_type);
+
+  gtk_container_add (GTK_CONTAINER (self->list_box), GTK_WIDGET (row));
+}
+
+static void
+update_places2 (GtkPlacesSidebar *self)
+{
+  GVolumeMonitor *volume_monitor;
+  GList *mounts, *l, *ll;
+  GMount *mount;
+  GList *drives;
+  GDrive *drive;
+  GList *volumes;
+  GVolume *volume;
+  GSList *bookmarks, *sl;
+  gint index;
+  gchar *original_uri, *mount_uri, *name, *identifier;
+  gchar *home_uri;
+  GIcon *icon;
+  GFile *root;
+  gchar *tooltip;
+  GList *network_mounts, *network_volumes;
+
+  g_cancellable_cancel (self->cancellable);
+
+  g_object_unref (self->cancellable);
+  self->cancellable = g_cancellable_new ();
+
+  gtk_container_foreach (GTK_CONTAINER (self->list_box),
+                         (GtkCallback) gtk_widget_destroy,
+                         NULL);
+
+  /* add built-in places */
+
+  if (should_show_recent (self))
+    {
+      mount_uri = "recent:///";
+      icon = g_themed_icon_new_with_default_fallbacks ("document-open-recent-symbolic");
+      add_place2 (self, PLACES_BUILT_IN,
+                 SECTION_COMPUTER,
+                 _("Recent"), icon, mount_uri,
+                 NULL, NULL, NULL, 0,
+                 _("Recent files"));
+      g_object_unref (icon);
+    }
+
+  /* home folder */
+  home_uri = get_home_directory_uri ();
+  icon = g_themed_icon_new_with_default_fallbacks (ICON_NAME_HOME);
+  add_place2 (self, PLACES_BUILT_IN,
+             SECTION_COMPUTER,
+             _("Home"), icon, home_uri,
+             NULL, NULL, NULL, 0,
+             _("Open your personal folder"));
+  g_object_unref (icon);
+  g_free (home_uri);
+
+  /* desktop */
+  if (self->show_desktop)
+    {
+      mount_uri = get_desktop_directory_uri ();
+      if (mount_uri)
+        {
+          icon = g_themed_icon_new_with_default_fallbacks (ICON_NAME_DESKTOP);
+          add_place2 (self, PLACES_BUILT_IN,
+                     SECTION_COMPUTER,
+                     _("Desktop"), icon, mount_uri,
+                     NULL, NULL, NULL, 0,
+                     _("Open the contents of your desktop in a folder"));
+          g_object_unref (icon);
+          g_free (mount_uri);
+        }
+    }
+
+  /* XDG directories */
+  // add_special_dirs (self);
+
+  if (self->show_enter_location)
+    {
+      icon = g_themed_icon_new_with_default_fallbacks (ICON_NAME_NETWORK_SERVER);
+      add_place2 (self, PLACES_ENTER_LOCATION,
+                 SECTION_COMPUTER,
+                 _("Enter Location"), icon, NULL,
+                 NULL, NULL, NULL, 0,
+                 _("Manually enter a location"));
+      g_object_unref (icon);
+    }
+
+  /* Trash */
+  if (!self->local_only)
+    {
+      mount_uri = "trash:///"; /* No need to strdup */
+      icon = _gtk_trash_monitor_get_icon (self->trash_monitor);
+      add_place2 (self, PLACES_BUILT_IN,
+                 SECTION_COMPUTER,
+                 _("Trash"), icon, mount_uri,
+                 NULL, NULL, NULL, 0,
+                 _("Open the trash"));
+      g_object_unref (icon);
+    }
+
+  gtk_widget_show_all (GTK_WIDGET (self));
+}
+
+static void
 update_places (GtkPlacesSidebar *sidebar)
 {
   GtkTreeIter iter;
@@ -4229,6 +4575,11 @@ gtk_places_sidebar_init (GtkPlacesSidebar *sidebar)
   gtk_style_context_set_junction_sides (gtk_widget_get_style_context (GTK_WIDGET (sidebar)),
                                         GTK_JUNCTION_RIGHT | GTK_JUNCTION_LEFT);
 
+  /* list box */
+  sidebar->list_box = gtk_list_box_new ();
+  gtk_container_add (GTK_CONTAINER (sidebar), sidebar->list_box);
+  gtk_widget_show (GTK_WIDGET (sidebar));
+
   /* tree view */
   tree_view = GTK_TREE_VIEW (gtk_tree_view_new ());
   gtk_tree_view_set_headers_visible (tree_view, FALSE);
@@ -4318,7 +4669,7 @@ gtk_places_sidebar_init (GtkPlacesSidebar *sidebar)
                                    sidebar, NULL);
 
   gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (sidebar->store));
-  gtk_container_add (GTK_CONTAINER (sidebar), GTK_WIDGET (tree_view));
+//  gtk_container_add (GTK_CONTAINER (sidebar), GTK_WIDGET (tree_view));
   gtk_widget_show (GTK_WIDGET (tree_view));
   gtk_tree_view_set_enable_search (tree_view, FALSE);
 
@@ -4391,6 +4742,8 @@ gtk_places_sidebar_init (GtkPlacesSidebar *sidebar)
 
   /* populate the sidebar */
   update_places (sidebar);
+
+  update_places2 (sidebar);
 }
 
 static void
@@ -4833,7 +5186,7 @@ gtk_places_sidebar_new (void)
   return GTK_WIDGET (g_object_new (gtk_places_sidebar_get_type (), NULL));
 }
 
-
+
 
 /* Drag and drop interfaces */
 
@@ -4911,7 +5264,7 @@ shortcuts_model_new (GtkPlacesSidebar *sidebar)
   return GTK_LIST_STORE (model);
 }
 
-
+
 
 /* Public methods for GtkPlacesSidebar */
 


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