[gtk+/wip/csoriano/pathbar-prototype] work on implementing root
- From: Carlos Soriano Sánchez <csoriano src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/csoriano/pathbar-prototype] work on implementing root
- Date: Thu, 19 Nov 2015 16:24:42 +0000 (UTC)
commit 683c13cb9c4efaaaebda8527cf20639719eb883f
Author: Carlos Soriano <csoriano gnome org>
Date: Thu Nov 19 17:24:05 2015 +0100
work on implementing root
gtk/gtkpathbar.c | 296 +++++++++++++++++++++++++++++++++++++++------------
tests/testpathbar.c | 4 +-
2 files changed, 231 insertions(+), 69 deletions(-)
---
diff --git a/gtk/gtkpathbar.c b/gtk/gtkpathbar.c
index 813b8fa..0d3ae8f 100644
--- a/gtk/gtkpathbar.c
+++ b/gtk/gtkpathbar.c
@@ -70,6 +70,10 @@ struct _GtkPathBarPrivate
GtkWidget *overflow_button_2;
GtkWidget *path_chunk_popover_container;
+ GIcon *root_icon;
+ gchar *root_label;
+ gchar *root_path;
+
gchar *path;
gchar *selected_path;
gboolean hide_direction;
@@ -247,7 +251,6 @@ create_path_chunk (GtkPathBar *self,
direction = gtk_widget_get_direction (GTK_WIDGET (self));
path_chunk = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-
button = gtk_toggle_button_new ();
button_label = gtk_label_new (label);
gtk_label_set_ellipsize (GTK_LABEL (button_label), PANGO_ELLIPSIZE_MIDDLE);
@@ -257,11 +260,11 @@ create_path_chunk (GtkPathBar *self,
MIN (g_utf8_strlen (label, -1), 10));
gtk_container_add (GTK_CONTAINER (button), button_label);
- g_signal_connect_swapped (button, "button-release-event",
- G_CALLBACK (on_path_chunk_button_release_event), path_chunk);
style = gtk_widget_get_style_context (button);
gtk_style_context_add_class (style, "flat");
+ g_signal_connect_swapped (button, "button-release-event",
+ G_CALLBACK (on_path_chunk_button_release_event), path_chunk);
if (add_separator)
{
separator = gtk_label_new ("/");
@@ -292,6 +295,76 @@ create_path_chunk (GtkPathBar *self,
return path_chunk;
}
+static GtkWidget*
+create_root_chunk (GtkPathBar *self)
+{
+ GtkPathBarPrivate *priv = gtk_path_bar_get_instance_private (self);
+ GtkWidget *button;
+ GtkWidget *separator;
+ GtkWidget *path_chunk = NULL;
+ GtkWidget *button_label;
+ GtkWidget *image;
+ GtkStyleContext *style;
+ PathChunkData *path_chunk_data;
+ GtkTextDirection direction;
+
+ if (priv->root_label || priv->root_icon)
+ {
+ direction = gtk_widget_get_direction (GTK_WIDGET (self));
+
+ path_chunk = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ button = gtk_toggle_button_new ();
+ if (priv->root_label)
+ {
+ button_label = gtk_label_new (priv->root_label);
+ gtk_label_set_ellipsize (GTK_LABEL (button_label), PANGO_ELLIPSIZE_MIDDLE);
+ gtk_button_set_label (GTK_BUTTON (path_chunk), priv->root_label);
+ // FIXME: the GtkLabel requests more than the number of chars set here.
+ // For visual testing for now substract 2 chars.
+ gtk_label_set_width_chars (GTK_LABEL (button_label),
+ MIN (g_utf8_strlen (priv->root_label, -1), 10));
+ gtk_container_add (GTK_CONTAINER (button), button_label);
+ }
+
+ if (priv->root_icon)
+ {
+ image = gtk_image_new_from_gicon (priv->root_icon, GTK_ICON_SIZE_MENU);
+ gtk_button_set_image (GTK_BUTTON (path_chunk), image);
+ }
+
+ style = gtk_widget_get_style_context (button);
+ gtk_style_context_add_class (style, "flat");
+
+ g_signal_connect_swapped (button, "button-release-event",
+ G_CALLBACK (on_path_chunk_button_release_event), path_chunk);
+
+ separator = gtk_label_new ("/");
+ gtk_widget_set_sensitive (separator, FALSE);
+ gtk_container_add (GTK_CONTAINER (path_chunk), separator);
+
+ if (direction == GTK_TEXT_DIR_LTR)
+ {
+ gtk_container_add (GTK_CONTAINER (path_chunk), button);
+ gtk_container_add (GTK_CONTAINER (path_chunk), separator);
+ } else {
+ gtk_container_add (GTK_CONTAINER (path_chunk), separator);
+ gtk_container_add (GTK_CONTAINER (path_chunk), button);
+ }
+
+ path_chunk_data = g_slice_new (PathChunkData);
+ path_chunk_data->label = g_strdup (priv->root_label);
+ path_chunk_data->path = g_string_new (priv->root_path);
+ path_chunk_data->path_bar = self;
+ path_chunk_data->button = path_chunk;
+ g_object_set_data_full (G_OBJECT (path_chunk), "data",
+ path_chunk_data, (GDestroyNotify) free_path_chunk_data);
+
+ gtk_widget_show_all (path_chunk);
+ }
+
+ return path_chunk;
+}
+
static void
on_entry_activate (GtkPathBar *self)
{
@@ -301,9 +374,97 @@ on_entry_activate (GtkPathBar *self)
gtk_path_bar_set_path (self, gtk_entry_get_text (GTK_ENTRY (priv->edit_entry)));
}
+static gboolean
+check_path_format (const gchar *path)
+{
+ gchar ** splitted_path;
+ gboolean valid = FALSE;
+
+ splitted_path = g_strsplit (path, "/", -1);
+
+ if (g_strv_length (splitted_path) == 0)
+ goto out;
+
+ if (!g_utf8_validate (path, -1, NULL))
+ goto out;
+
+ for (guint i = 0; i < g_strv_length (splitted_path); i++)
+ {
+ /* First and last part of the path is always empty when splitted */
+ if (g_strcmp0 (splitted_path[i], "") == 0 && i != 0)
+ goto out;
+ }
+ /* Path must start with "/" */
+ if (g_strcmp0 (splitted_path[0], "") != 0)
+ goto out;
+
+ valid = TRUE;
+
+out:
+ g_strfreev (splitted_path);
+
+ return valid;
+}
+
static void
-update_selected_path (GtkPathBar *self,
- const gchar *path)
+update_path_bar (GtkPathBar *self)
+{
+ GtkPathBarPrivate *priv = gtk_path_bar_get_instance_private (self);
+ gchar ** splitted_path;
+ GString *current_path = NULL;
+ GtkWidget *path_chunk;
+ GtkWidget *path_box;
+ GtkWidget *overflow_button;
+ GtkWidget *path_bar;
+ GtkWidget *root_chunk;
+ gchar *unprefixed_path = NULL;
+
+ get_path_bar_widgets (GTK_PATH_BAR (self), &path_bar, &overflow_button, &path_box, FALSE);
+
+ /* Make sure we dismiss all popovers */
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->overflow_button_1), FALSE);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->overflow_button_2), FALSE);
+
+ gtk_container_foreach (GTK_CONTAINER (path_box), (GtkCallback) gtk_widget_destroy, NULL);
+
+ root_chunk = create_root_chunk (self);
+ if (root_chunk)
+ gtk_container_add (GTK_CONTAINER (path_box), root_chunk);
+
+ /* Remove root path */
+ if (priv->root_path)
+ unprefixed_path = g_utf8_substring (priv->path, strlen (priv->root_path) - 1,
+ strlen (priv->path) -1);
+ else
+ unprefixed_path = g_strdup (priv->path);
+
+ splitted_path = g_strsplit (unprefixed_path, "/", -1);
+ current_path = g_string_new ("");
+
+ for (guint i = 0; i < g_strv_length (splitted_path); i++)
+ {
+ if (g_strcmp0 (splitted_path[0], "") == 0 && i == 0)
+ continue;
+
+ g_string_append (current_path, "/");
+ g_string_append (current_path, splitted_path[i]);
+
+ path_chunk = create_path_chunk (self, current_path, splitted_path[i],
+ i != g_strv_length (splitted_path) - 1);
+ gtk_container_add (GTK_CONTAINER (path_box), path_chunk);
+ }
+
+ gtk_entry_set_text (GTK_ENTRY (priv->edit_entry), priv->path);
+
+ gtk_stack_set_visible_child (GTK_STACK (priv->path_bar_containers_stack), path_bar);
+
+ g_strfreev (splitted_path);
+ g_free (unprefixed_path);
+ g_string_free (current_path, TRUE);
+}
+
+static void
+update_selected_path (GtkPathBar *self)
{
GtkPathBarPrivate *priv = gtk_path_bar_get_instance_private (self);
PathChunkData *data;
@@ -326,14 +487,14 @@ update_selected_path (GtkPathBar *self,
{
data = g_object_get_data (G_OBJECT (l->data), "data");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->button),
- g_strcmp0 (data->path->str, path) == 0);
+ g_strcmp0 (data->path->str, priv->selected_path) == 0);
}
for (l = overflow_children; l != NULL; l = l->next)
{
data = g_object_get_data (G_OBJECT (l->data), "data");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->button),
- g_strcmp0 (data->path->str, path) == 0);
+ g_strcmp0 (data->path->str, priv->selected_path) == 0);
}
g_list_free (children);
@@ -345,7 +506,6 @@ update_selected_path (GtkPathBar *self,
static void
populate_overflow_popover (GtkPathBar *self)
{
- GtkPathBarPrivate *priv = gtk_path_bar_get_instance_private (self);
GList *overflow_children;
GList *l;
PathChunkData *data;
@@ -371,7 +531,7 @@ populate_overflow_popover (GtkPathBar *self)
gtk_container_add (GTK_CONTAINER (overflow_container), path_chunk);
}
- update_selected_path (self, (const gchar *) priv->selected_path);
+ update_selected_path (self);
g_list_free (overflow_children);
}
@@ -591,74 +751,22 @@ gtk_path_bar_set_path (GtkPathBar *self,
const gchar *path)
{
GtkPathBarPrivate *priv;
- gchar ** splitted_path;
- GString *current_path = NULL;
- GtkWidget *path_chunk;
- PathChunkData *data;
- GList *children;
- GtkWidget *path_box;
- GtkWidget *overflow_button;
- GtkWidget *path_bar;
g_return_if_fail (GTK_IS_PATH_BAR (self));
+ g_return_if_fail (check_path_format (path));
priv = gtk_path_bar_get_instance_private (GTK_PATH_BAR (self));
if (g_strcmp0 (priv->path, path) == 0)
return;
- get_path_bar_widgets (GTK_PATH_BAR (self), &path_bar, &overflow_button, &path_box, FALSE);
-
- /* Make sure we dismiss all popovers */
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->overflow_button_1), FALSE);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->overflow_button_2), FALSE);
-
- gtk_container_foreach (GTK_CONTAINER (path_box), (GtkCallback) gtk_widget_destroy, NULL);
-
if (priv->path)
- {
- g_free (priv->path);
- priv->path = NULL;
- }
-
- if (priv->selected_path)
- {
- g_free (priv->selected_path);
- priv->selected_path = NULL;
- }
-
- splitted_path = g_strsplit (path, "/", -1);
- current_path = g_string_new ("");
-
- for (guint i = 0; i < g_strv_length (splitted_path); i++)
- {
- if (g_strcmp0 (splitted_path[i], "") == 0)
- continue;
-
- g_string_append (current_path, "/");
- g_string_append (current_path, splitted_path[i]);
- path_chunk = create_path_chunk (self, current_path, splitted_path[i], TRUE);
- gtk_container_add (GTK_CONTAINER (path_box), path_chunk);
- }
-
- children = gtk_container_get_children (GTK_CONTAINER (path_box));
- if (children != NULL)
- {
- path_chunk = GTK_WIDGET (g_list_last (children)->data);
- data = g_object_get_data (G_OBJECT (path_chunk), "data");
- priv->path = g_strdup (data->path->str);
- }
-
- gtk_entry_set_text (GTK_ENTRY (priv->edit_entry), priv->path);
+ g_free (priv->path);
+ priv->path = g_strdup (path);
- gtk_stack_set_visible_child (GTK_STACK (priv->path_bar_containers_stack), path_bar);
+ update_path_bar (self);
g_object_notify_by_pspec (G_OBJECT (self), path_bar_properties[PROP_PATH]);
-
gtk_path_bar_set_selected_path (self, priv->path);
-
- g_strfreev (splitted_path);
- g_string_free (current_path, TRUE);
- g_list_free (children);
}
/**
@@ -704,7 +812,9 @@ gtk_path_bar_set_selected_path (GtkPathBar *self,
priv = gtk_path_bar_get_instance_private (GTK_PATH_BAR (self));
- g_return_if_fail (g_str_has_prefix (priv->path, path));
+ g_print ("set selected %s %s\n", priv->path, path);
+ g_return_if_fail (g_str_has_prefix (priv->path, path) ||
+ g_strcmp0 (priv->path, path) == 0);
if (g_strcmp0 (priv->selected_path, path) != 0)
{
@@ -712,9 +822,14 @@ gtk_path_bar_set_selected_path (GtkPathBar *self,
g_free (priv->selected_path);
priv->selected_path = g_strdup (path);
- update_selected_path (self, path);
+ update_selected_path (self);
g_object_notify_by_pspec (G_OBJECT (self), path_bar_properties[PROP_SELECTED_PATH]);
}
+ else
+ {
+ /* Update the style in any case */
+ update_selected_path (self);
+ }
}
/**
@@ -818,6 +933,53 @@ gtk_path_bar_set_edit_mode_enabled (GtkPathBar *self,
}
}
+void
+gtk_path_bar_set_root (GtkPathBar *self,
+ GIcon *icon,
+ const gchar *label,
+ const gchar *path)
+{
+ GtkPathBarPrivate *priv ;
+
+ g_return_if_fail (GTK_IS_PATH_BAR (self));
+ priv = gtk_path_bar_get_instance_private (GTK_PATH_BAR (self));
+
+ if (path)
+ {
+ g_return_if_fail (g_str_has_prefix (priv->path, path) ||
+ g_strcmp0 (priv->path, path) == 0);
+ g_return_if_fail (label || icon);
+
+ }
+
+ if (priv->root_icon)
+ {
+ g_object_unref (priv->root_icon);
+ priv->root_icon = NULL;
+ }
+ if (icon)
+ priv->root_icon = g_object_ref (icon);
+
+ if (priv->root_label)
+ {
+ g_free (priv->root_label);
+ priv->root_label = NULL;
+ }
+ if (label)
+ priv->root_label = g_strdup (label);
+
+ if (priv->root_path)
+ {
+ g_free (priv->root_path);
+ priv->root_path = NULL;
+ }
+ if (path)
+ priv->root_path = g_strdup (path);
+
+ update_path_bar (self);
+ update_selected_path (self);
+}
+
GtkWidget *
gtk_path_bar_new (void)
{
diff --git a/tests/testpathbar.c b/tests/testpathbar.c
index 39a3a3f..0cbaaa7 100644
--- a/tests/testpathbar.c
+++ b/tests/testpathbar.c
@@ -5,8 +5,8 @@
static GActionGroup *action_group;
static GList *path_bars = NULL;
static GList *files_path_bars = NULL;
-static const gchar* original_path = "/test/test 2/test 3/asda lkasdl//pppppppppppppppp/ alskd/";
-static const gchar* file_original_path = "/test/test 2/test 3/asda lkasdl/pppppppppppppppp/alskd/";
+static const gchar* original_path = "/test/test 2/test 3/asda lkasdl/pppppppppppppppp/ alskd";
+static const gchar* file_original_path = "/test/test 2/test 3/asda lkasdl/pppppppppppppppp/alskd";
static void
action_menu_1 (GSimpleAction *action,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]