[epiphany/wip/bookmarks: 12/76] bookmarks: Add properties dialog
- From: Iulian Radu <iulianradu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany/wip/bookmarks: 12/76] bookmarks: Add properties dialog
- Date: Wed, 28 Sep 2016 13:17:48 +0000 (UTC)
commit bc464c6b5ce7569109e463855d3fa20a6758c430
Author: Iulian Radu <iulian radu67 gmail com>
Date: Tue Jul 26 21:22:58 2016 +0300
bookmarks: Add properties dialog
src/Makefile.am | 9 +-
src/ephy-bookmark-properties-grid.c | 336 +++++++++++++++++++++++++
src/ephy-bookmark-properties-grid.h | 45 ++++
src/ephy-bookmark-row.c | 38 +++
src/ephy-bookmark.c | 71 +++++-
src/ephy-bookmark.h | 10 +-
src/ephy-bookmarks-manager.c | 107 ++++++---
src/ephy-bookmarks-manager.h | 10 +-
src/ephy-bookmarks-popover.c | 63 ++---
src/epiphany.gresource.xml | 1 +
src/resources/epiphany.css | 36 +++-
src/resources/epiphany.scss | 42 +++
src/resources/gtk/bookmark-properties-grid.ui | 171 +++++++++++++
src/resources/gtk/bookmark-row.ui | 22 ++
14 files changed, 881 insertions(+), 80 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 065ec95..649bc40 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,6 +10,7 @@ dist_noinst_DATA = \
TYPES_H_FILES = \
ephy-link.h \
+ ephy-bookmark-properties-grid.h \
ephy-session.h \
ephy-shell.h \
ephy-window.h
@@ -23,8 +24,12 @@ libephymain_la_SOURCES = \
ephy-action-helper.h \
ephy-bookmark.c \
ephy-bookmark.h \
+ ephy-bookmark-properties-grid.c \
+ ephy-bookmark-properties-grid.h \
ephy-bookmark-row.c \
ephy-bookmark-row.h \
+ ephy-bookmarks-manager.c \
+ ephy-bookmarks-manager.h \
ephy-bookmarks-popover.c \
ephy-bookmarks-popover.h \
ephy-completion-model.c \
@@ -136,7 +141,9 @@ RESOURCE_FILES = \
resources/prefs-lang-dialog.ui \
resources/prism.css \
resources/prism.js \
- resources/shortcuts-dialog.ui
+ resources/shortcuts-dialog.ui \
+ resources/gtk/bookmark-properties-grid.ui \
+ resources/gtk/bookmark-row.ui \
resources/gtk/bookmarks-popover.ui \
resources/gtk/menus.ui \
$(NULL)
diff --git a/src/ephy-bookmark-properties-grid.c b/src/ephy-bookmark-properties-grid.c
new file mode 100644
index 0000000..f1c9fb2
--- /dev/null
+++ b/src/ephy-bookmark-properties-grid.c
@@ -0,0 +1,336 @@
+/* vim: set sw=2 ts=2 sts=2 et: */
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright (C) 2016 Iulian-Gabriel Radu <iulian radu67 gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#include "ephy-bookmark-properties-grid.h"
+
+#include "ephy-bookmarks-manager.h"
+#include "ephy-debug.h"
+#include "ephy-shell.h"
+#include "ephy-type-builtins.h"
+
+#include <libsoup/soup.h>
+#include <string.h>
+
+struct _EphyBookmarkPropertiesGrid {
+ GtkGrid parent_instance;
+
+ EphyBookmark *bookmark;
+ EphyBookmarkPropertiesGridType type;
+
+ GtkWidget *popover_bookmark_label;
+ GtkWidget *name_entry;
+ GtkWidget *address_entry;
+ GtkWidget *popover_tags_label;
+ GtkWidget *tags_box;
+ GtkWidget *add_tag_entry;
+ GtkWidget *add_tag_button;
+ GtkWidget *remove_bookmark_button;
+};
+
+G_DEFINE_TYPE (EphyBookmarkPropertiesGrid, ephy_bookmark_properties_grid, GTK_TYPE_GRID)
+
+enum {
+ PROP_0,
+ PROP_BOOKMARK,
+ PROP_TYPE,
+ LAST_PROP
+};
+
+static GParamSpec *obj_properties[LAST_PROP];
+
+static void
+ephy_bookmark_properties_grid_tags_box_child_activated_cb (EphyBookmarkPropertiesGrid *self,
+ GtkFlowBoxChild *child,
+ GtkFlowBox *flow_box)
+{
+ GtkStyleContext *context;
+ GtkWidget *box;
+ GtkWidget *label;
+
+ g_assert (EPHY_IS_BOOKMARK_PROPERTIES_GRID (self));
+ g_assert (GTK_IS_FLOW_BOX_CHILD (child));
+ g_assert (GTK_IS_FLOW_BOX (flow_box));
+
+ box = gtk_bin_get_child (GTK_BIN (child));
+ label = g_object_get_data (G_OBJECT (box), "label");
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (child));
+ if (gtk_style_context_has_class (context, "bookmark-tag-widget-selected")) {
+ ephy_bookmark_remove_tag (self->bookmark,
+ gtk_label_get_text (GTK_LABEL (label)));
+ gtk_style_context_remove_class (context, "bookmark-tag-widget-selected");
+ } else {
+ ephy_bookmark_add_tag (self->bookmark,
+ gtk_label_get_text (GTK_LABEL (label)));
+ gtk_style_context_add_class (context, "bookmark-tag-widget-selected");
+ }
+}
+
+static GtkWidget *
+ephy_bookmark_properties_grid_create_tag_widget (EphyBookmarkPropertiesGrid *self,
+ const char *tag,
+ gboolean selected)
+{
+ GtkWidget *widget;
+ GtkWidget *box;
+ GtkWidget *label;
+ GtkWidget *button;
+ GtkStyleContext *context;
+
+ widget = gtk_flow_box_child_new ();
+
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+ label = gtk_label_new (tag);
+ gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
+
+ button = gtk_button_new ();
+ gtk_button_set_image (GTK_BUTTON (button),
+ gtk_image_new_from_icon_name ("window-close-symbolic",
+ GTK_ICON_SIZE_MENU));
+ gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+ gtk_box_pack_end (GTK_BOX (box), button, FALSE, FALSE, 0);
+
+ g_object_set_data (G_OBJECT (box), "label", label);
+
+ gtk_container_add (GTK_CONTAINER (widget), box);
+
+ context = gtk_widget_get_style_context (widget);
+ gtk_style_context_add_class (context, "bookmark-tag-widget");
+ if (selected) {
+ /* Toggle initial state on child */
+ ephy_bookmark_properties_grid_tags_box_child_activated_cb (EPHY_BOOKMARK_PROPERTIES_GRID (self),
+ GTK_FLOW_BOX_CHILD (GTK_FLOW_BOX_CHILD
(widget)),
+ GTK_FLOW_BOX (self->tags_box));
+ }
+
+ gtk_widget_show_all (widget);
+
+ return widget;
+}
+
+static void
+ephy_bookmark_properties_grid_add_tag_button_clicked_cb (EphyBookmarkPropertiesGrid *self,
+ GtkButton *button)
+{
+ GtkEntryBuffer *buffer;
+ GtkWidget *widget;
+ const char *text;
+
+ g_assert (EPHY_IS_BOOKMARK_PROPERTIES_GRID (self));
+ g_assert (GTK_IS_BUTTON (button));
+
+ buffer = gtk_entry_get_buffer (GTK_ENTRY (self->add_tag_entry));
+ text = gtk_entry_buffer_get_text (buffer);
+ ephy_bookmark_add_tag (self->bookmark, text);
+
+ widget = ephy_bookmark_properties_grid_create_tag_widget (self, text, TRUE);
+ gtk_flow_box_insert (GTK_FLOW_BOX (self->tags_box), widget, -1);
+}
+
+static void
+ephy_bookmark_properties_grid_remove_bookmark_button_clicked_cb (EphyBookmarkPropertiesGrid *self,
+ GtkButton *button)
+{
+ g_assert (EPHY_IS_BOOKMARK_PROPERTIES_GRID (self));
+ g_assert (GTK_IS_BUTTON (button));
+
+ g_signal_emit_by_name (self->bookmark, "removed");
+
+ gtk_widget_hide (gtk_widget_get_parent (gtk_widget_get_parent (GTK_WIDGET (self))));
+ gtk_widget_destroy (gtk_widget_get_parent (gtk_widget_get_parent (GTK_WIDGET (self))));
+}
+
+static void
+ephy_bookmark_properties_grid_buffer_text_changed_cb (EphyBookmarkPropertiesGrid *self,
+ GParamSpec *pspec,
+ GtkEntryBuffer *buffer)
+{
+ const char *text;
+
+ g_assert (EPHY_IS_BOOKMARK_PROPERTIES_GRID (self));
+ g_assert (GTK_IS_ENTRY_BUFFER (buffer));
+
+ text = gtk_entry_buffer_get_text (buffer);
+ /* TODO: Check if the tag already exists. Before doing this check, come up
+ * with a better way of storing a list of all existing tags. The current way
+ * of iterating over all bookmarks and doing a reunion of their tags is
+ * really slow */
+ if (strlen (text) >= 3)
+ gtk_widget_set_sensitive (self->add_tag_button, TRUE);
+}
+
+static void
+ephy_bookmark_properties_grid_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphyBookmarkPropertiesGrid *self = EPHY_BOOKMARK_PROPERTIES_GRID (object);
+
+ switch (prop_id) {
+ case PROP_BOOKMARK:
+ self->bookmark = g_value_dup_object (value);
+ break;
+ case PROP_TYPE:
+ self->type = g_value_get_enum (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_bookmark_properties_grid_constructed (GObject *object)
+{
+ EphyBookmarkPropertiesGrid *self = EPHY_BOOKMARK_PROPERTIES_GRID (object);
+ EphyBookmarksManager *manager = ephy_shell_get_bookmarks_manager (ephy_shell_get_default ());
+ GSequence *tags;
+ GSequence *bookmark_tags;
+ GSequenceIter *iter;
+ SoupURI *uri;
+
+ /* Set text for name entry */
+ gtk_entry_set_text (GTK_ENTRY (self->name_entry),
+ ephy_bookmark_get_title (self->bookmark));
+
+ /* Set text for address entry */
+ uri = soup_uri_new (ephy_bookmark_get_url (self->bookmark));
+ gtk_entry_set_text (GTK_ENTRY (self->address_entry),
+ g_strconcat (soup_uri_get_host (uri),
+ soup_uri_get_path (uri),
+ soup_uri_get_query (uri),
+ soup_uri_get_fragment (uri),
+ NULL));
+ soup_uri_free (uri);
+
+ /* Create tag widgets */
+ tags = ephy_bookmarks_manager_get_tags (manager);
+ bookmark_tags = ephy_bookmark_get_tags (self->bookmark);
+ g_sequence_sort (bookmark_tags, (GCompareDataFunc)g_strcmp0, NULL);
+ for (iter = g_sequence_get_begin_iter (tags);
+ !g_sequence_iter_is_end (iter);
+ iter = g_sequence_iter_next (iter)) {
+ GtkWidget *widget;
+ gboolean selected = FALSE;
+ const char *tag = g_sequence_get (iter);
+
+ if (g_sequence_lookup (bookmark_tags, (gpointer)tag, (GCompareDataFunc)g_strcmp0, NULL))
+ selected = TRUE;
+
+ widget = ephy_bookmark_properties_grid_create_tag_widget (self, tag, selected);
+ gtk_flow_box_insert (GTK_FLOW_BOX (self->tags_box), widget, -1);
+ }
+
+ g_signal_connect_object (self->tags_box, "child-activated",
+ G_CALLBACK (ephy_bookmark_properties_grid_tags_box_child_activated_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ gtk_widget_show_all (self->tags_box);
+
+ /* Connect */
+}
+
+static void
+ephy_bookmark_properties_grid_class_init (EphyBookmarkPropertiesGridClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->set_property = ephy_bookmark_properties_grid_set_property;
+ object_class->constructed = ephy_bookmark_properties_grid_constructed;
+
+ obj_properties[PROP_BOOKMARK] =
+ g_param_spec_object ("bookmark",
+ "An EphyBookmark object",
+ "The EphyBookmark whose properties are being displayed",
+ EPHY_TYPE_BOOKMARK,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ obj_properties[PROP_TYPE] =
+ g_param_spec_enum ("type",
+ "An EphyBookmarkPropertiesGrid object",
+ "The type of widget the grid will be used for",
+ EPHY_TYPE_BOOKMARK_PROPERTIES_GRID_TYPE,
+ EPHY_BOOKMARK_PROPERTIES_GRID_TYPE_DIALOG,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/epiphany/gtk/bookmark-properties-grid.ui");
+ gtk_widget_class_bind_template_child (widget_class, EphyBookmarkPropertiesGrid, popover_bookmark_label);
+ gtk_widget_class_bind_template_child (widget_class, EphyBookmarkPropertiesGrid, name_entry);
+ gtk_widget_class_bind_template_child (widget_class, EphyBookmarkPropertiesGrid, address_entry);
+ gtk_widget_class_bind_template_child (widget_class, EphyBookmarkPropertiesGrid, popover_tags_label);
+ gtk_widget_class_bind_template_child (widget_class, EphyBookmarkPropertiesGrid, tags_box);
+ gtk_widget_class_bind_template_child (widget_class, EphyBookmarkPropertiesGrid, add_tag_entry);
+ gtk_widget_class_bind_template_child (widget_class, EphyBookmarkPropertiesGrid, add_tag_button);
+ gtk_widget_class_bind_template_child (widget_class, EphyBookmarkPropertiesGrid, remove_bookmark_button);
+}
+
+static void
+ephy_bookmark_properties_grid_init (EphyBookmarkPropertiesGrid *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ if (self->type == EPHY_BOOKMARK_PROPERTIES_GRID_TYPE_DIALOG) {
+ gtk_container_remove (GTK_CONTAINER (self), self->popover_bookmark_label);
+ gtk_container_remove (GTK_CONTAINER (self), self->popover_tags_label);
+ } else if (self->type == EPHY_BOOKMARK_PROPERTIES_GRID_TYPE_DIALOG) {
+ gtk_grid_remove_column (GTK_GRID (self), 0);
+ }
+
+ g_signal_connect_object (gtk_entry_get_buffer (GTK_ENTRY (self->add_tag_entry)),
+ "notify::text",
+ G_CALLBACK (ephy_bookmark_properties_grid_buffer_text_changed_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->add_tag_button,
+ "clicked",
+ G_CALLBACK (ephy_bookmark_properties_grid_add_tag_button_clicked_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (self->remove_bookmark_button,
+ "clicked",
+ G_CALLBACK (ephy_bookmark_properties_grid_remove_bookmark_button_clicked_cb),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+GtkWidget *
+ephy_bookmark_properties_grid_new (EphyBookmark *bookmark,
+ EphyBookmarkPropertiesGridType type)
+{
+ g_return_val_if_fail (EPHY_IS_BOOKMARK (bookmark), NULL);
+
+ return g_object_new (EPHY_TYPE_BOOKMARK_PROPERTIES_GRID,
+ "bookmark", bookmark,
+ "type", type,
+ NULL);
+}
+
+GtkWidget *
+ephy_bookmark_properties_grid_get_add_tag_button (EphyBookmarkPropertiesGrid *self)
+{
+ g_return_val_if_fail (EPHY_IS_BOOKMARK_PROPERTIES_GRID (self), NULL);
+
+ return self->add_tag_button;
+}
diff --git a/src/ephy-bookmark-properties-grid.h b/src/ephy-bookmark-properties-grid.h
new file mode 100644
index 0000000..389aeae
--- /dev/null
+++ b/src/ephy-bookmark-properties-grid.h
@@ -0,0 +1,45 @@
+/* vim: set sw=2 ts=2 sts=2 et: */
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright (C) 2016 Iulian-Gabriel Radu <iulian radu67 gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _EPHY_BOOKMARK_PROPERTIES_GRID_H
+#define _EPHY_BOOKMARK_PROPERTIES_GRID_H
+
+#include "ephy-bookmark.h"
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_BOOKMARK_PROPERTIES_GRID (ephy_bookmark_properties_grid_get_type ())
+
+G_DECLARE_FINAL_TYPE (EphyBookmarkPropertiesGrid, ephy_bookmark_properties_grid, EPHY,
BOOKMARK_PROPERTIES_GRID, GtkGrid)
+
+typedef enum {
+ EPHY_BOOKMARK_PROPERTIES_GRID_TYPE_DIALOG,
+ EPHY_BOOKMARK_PROPERTIES_GRID_TYPE_POPOVER
+} EphyBookmarkPropertiesGridType;
+
+GtkWidget *ephy_bookmark_properties_grid_new (EphyBookmark *bookmark,
+ EphyBookmarkPropertiesGridType type);
+
+GtkWidget *ephy_bookmark_properties_grid_get_add_tag_button (EphyBookmarkPropertiesGrid *self);
+
+G_END_DECLS
+
+#endif /* _EPHY_BOOKMARK_PROPERTIES_GRID_H */
diff --git a/src/ephy-bookmark-row.c b/src/ephy-bookmark-row.c
index a5b0fde..4fe2c92 100644
--- a/src/ephy-bookmark-row.c
+++ b/src/ephy-bookmark-row.c
@@ -17,6 +17,7 @@
#include "config.h"
+#include "ephy-bookmark-properties-grid.h"
#include "ephy-bookmark-row.h"
struct _EphyBookmarkRow {
@@ -25,6 +26,7 @@ struct _EphyBookmarkRow {
EphyBookmark *bookmark;
GtkWidget *title_label;
+ GtkWidget *properties_button;
};
G_DEFINE_TYPE (EphyBookmarkRow, ephy_bookmark_row, GTK_TYPE_LIST_BOX_ROW)
@@ -38,6 +40,35 @@ enum {
static GParamSpec *obj_properties[LAST_PROP];
static void
+ephy_bookmark_row_button_clicked_cb (EphyBookmarkRow *row,
+ GtkButton *button)
+{
+ GtkWidget *dialog;
+ GtkWidget *content_area;
+ GtkWidget *grid;
+
+ g_assert (EPHY_IS_BOOKMARK_ROW (row));
+ g_assert (GTK_IS_BUTTON (button));
+
+ dialog = gtk_dialog_new_with_buttons ("Bookmark Properties",
+ GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (row))),
+ GTK_DIALOG_USE_HEADER_BAR,
+ NULL, NULL);
+ gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+ grid = ephy_bookmark_properties_grid_new (ephy_bookmark_row_get_bookmark (row),
+ EPHY_BOOKMARK_PROPERTIES_GRID_TYPE_DIALOG);
+ gtk_window_set_default (GTK_WINDOW (dialog),
+ ephy_bookmark_properties_grid_get_add_tag_button (EPHY_BOOKMARK_PROPERTIES_GRID
(grid)));
+
+ gtk_container_add (GTK_CONTAINER (content_area), grid);
+
+ gtk_widget_show (dialog);
+}
+
+static void
ephy_bookmark_row_set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -117,12 +148,19 @@ ephy_bookmark_row_class_init (EphyBookmarkRowClass *klass)
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/epiphany/gtk/bookmark-row.ui");
gtk_widget_class_bind_template_child (widget_class, EphyBookmarkRow, title_label);
+ gtk_widget_class_bind_template_child (widget_class, EphyBookmarkRow, properties_button);
}
static void
ephy_bookmark_row_init (EphyBookmarkRow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
+
+ g_signal_connect_object (self->properties_button,
+ "clicked",
+ G_CALLBACK (ephy_bookmark_row_button_clicked_cb),
+ self,
+ G_CONNECT_SWAPPED);
}
GtkWidget *
diff --git a/src/ephy-bookmark.c b/src/ephy-bookmark.c
index 38ccaa4..3cf08b4 100644
--- a/src/ephy-bookmark.c
+++ b/src/ephy-bookmark.c
@@ -24,7 +24,7 @@ struct _EphyBookmark {
char *url;
char *title;
- GList *tags;
+ GSequence *tags;
};
G_DEFINE_TYPE (EphyBookmark, ephy_bookmark, G_TYPE_OBJECT)
@@ -36,7 +36,13 @@ enum {
LAST_PROP
};
+enum {
+ REMOVED,
+ LAST_SIGNAL
+};
+
static GParamSpec *obj_properties[LAST_PROP];
+static guint signals[LAST_SIGNAL];
static void
ephy_bookmark_set_property (GObject *object,
@@ -68,7 +74,7 @@ ephy_bookmark_get_property (GObject *object,
switch (prop_id) {
case PROP_TITLE:
- g_value_set_string (value, self->title);
+ g_value_set_string (value, ephy_bookmark_get_title (self));
break;
case PROP_URL:
g_value_set_string (value, ephy_bookmark_get_url (self));
@@ -86,8 +92,7 @@ ephy_bookmark_finalize (GObject *object)
g_clear_pointer (&self->url, g_free);
g_clear_pointer (&self->title, g_free);
- g_list_free_full (self->tags, g_object_unref);
- self->tags = NULL;
+ g_sequence_free (self->tags);
G_OBJECT_CLASS (ephy_bookmark_parent_class)->finalize (object);
}
@@ -116,6 +121,14 @@ ephy_bookmark_class_init (EphyBookmarkClass *klass)
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
+
+ signals[REMOVED] =
+ g_signal_new ("removed",
+ EPHY_TYPE_BOOKMARK,
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
}
static void
@@ -139,15 +152,61 @@ ephy_bookmark_get_url (EphyBookmark *self) {
return self->url;
}
+const char *
+ephy_bookmark_get_title (EphyBookmark *bookmark)
+{
+ g_return_val_if_fail (EPHY_IS_BOOKMARK (bookmark), NULL);
+
+ return bookmark->title;
+}
+
+void
+ephy_bookmark_add_tag (EphyBookmark *self,
+ const char *tag)
+{
+ GSequenceIter *tag_iter;
+ GSequenceIter *prev_tag_iter;
+
+ g_return_if_fail (EPHY_IS_BOOKMARK (self));
+
+ tag_iter = g_sequence_search (self->tags,
+ (gpointer)tag,
+ (GCompareDataFunc)g_strcmp0,
+ NULL);
+
+ prev_tag_iter = g_sequence_iter_prev (tag_iter);
+ if (g_strcmp0 (g_sequence_get (prev_tag_iter), tag) != 0)
+ g_sequence_insert_before (tag_iter, g_strdup (tag));
+}
+
+void
+ephy_bookmark_remove_tag (EphyBookmark *self,
+ const char *tag)
+{
+ GSequenceIter *tag_iter;
+
+ g_return_if_fail (EPHY_IS_BOOKMARK (self));
+
+ tag_iter = g_sequence_lookup (self->tags,
+ (gpointer)tag,
+ (GCompareDataFunc)g_strcmp0,
+ NULL);
+
+ g_assert (tag_iter != NULL);
+
+ g_sequence_remove (tag_iter);
+}
+
void
-ephy_bookmark_set_tags (EphyBookmark *self, GList *tags)
+ephy_bookmark_set_tags (EphyBookmark *self, GSequence *tags)
{
g_return_if_fail (EPHY_IS_BOOKMARK (self));
+ g_return_if_fail (tags != NULL);
self->tags = tags;
}
-GList *
+GSequence *
ephy_bookmark_get_tags (EphyBookmark *self)
{
g_return_val_if_fail (EPHY_IS_BOOKMARK (self), NULL);
diff --git a/src/ephy-bookmark.h b/src/ephy-bookmark.h
index 9d5d279..e752f58 100644
--- a/src/ephy-bookmark.h
+++ b/src/ephy-bookmark.h
@@ -29,11 +29,15 @@ G_DECLARE_FINAL_TYPE (EphyBookmark, ephy_bookmark, EPHY, BOOKMARK, GObject)
EphyBookmark *ephy_bookmark_new (char *url,
char *title);
-
const char *ephy_bookmark_get_url (EphyBookmark *self);
+const char *ephy_bookmark_get_title (EphyBookmark *self);
+void ephy_bookmark_add_tag (EphyBookmark *self,
+ const char *tag);
+void ephy_bookmark_remove_tag (EphyBookmark *self,
+ const char *tag);
void ephy_bookmark_set_tags (EphyBookmark *self,
- GList *tags);
-GList *ephy_bookmark_get_tags (EphyBookmark *self);
+ GSequence *tags);
+GSequence *ephy_bookmark_get_tags (EphyBookmark *self);
G_END_DECLS
diff --git a/src/ephy-bookmarks-manager.c b/src/ephy-bookmarks-manager.c
index 9c3735c..4257aaf 100644
--- a/src/ephy-bookmarks-manager.c
+++ b/src/ephy-bookmarks-manager.c
@@ -31,25 +31,14 @@ struct _EphyBookmarksManager {
gchar *gvdb_file;
};
-G_DEFINE_TYPE (EphyBookmarksManager, ephy_bookmarks_manager, G_TYPE_OBJECT)
+static void list_model_iface_init (GListModelInterface *iface);
-enum {
- BOOKMARK_ADDED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL];
+G_DEFINE_TYPE_EXTENDED (EphyBookmarksManager, ephy_bookmarks_manager, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
static void
ephy_bookmarks_manager_class_init (EphyBookmarksManagerClass *klass)
{
- signals[BOOKMARK_ADDED] =
- g_signal_new ("bookmark-added",
- EPHY_TYPE_BOOKMARKS_MANAGER,
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL, NULL,
- G_TYPE_NONE, 1,
- EPHY_TYPE_BOOKMARK);
}
static void
@@ -60,6 +49,42 @@ ephy_bookmarks_manager_init (EphyBookmarksManager *self)
NULL);
}
+static GType
+ephy_bookmarks_manager_get_item_type (GListModel *model)
+{
+ return EPHY_TYPE_BOOKMARK;
+}
+
+static guint
+ephy_bookmarks_manager_get_n_items (GListModel *model)
+{
+ EphyBookmarksManager *self = (EphyBookmarksManager *)model;
+
+ g_assert (EPHY_IS_BOOKMARKS_MANAGER (self));
+
+ return g_list_length (self->bookmarks);
+}
+
+static gpointer
+ephy_bookmarks_manager_get_item (GListModel *model,
+ guint position)
+{
+ EphyBookmarksManager *self = (EphyBookmarksManager *)model;
+
+ g_return_val_if_fail (EPHY_IS_BOOKMARKS_MANAGER (self), NULL);
+ g_return_val_if_fail (position < g_list_length (self->bookmarks), NULL);
+
+ return g_object_ref (g_list_nth_data (self->bookmarks, position));
+}
+
+static void
+list_model_iface_init (GListModelInterface *iface)
+{
+ iface->get_item_type = ephy_bookmarks_manager_get_item_type;
+ iface->get_n_items = ephy_bookmarks_manager_get_n_items;
+ iface->get_item = ephy_bookmarks_manager_get_item;
+}
+
void
ephy_bookmarks_manager_add_bookmark (EphyBookmarksManager *self,
EphyBookmark *bookmark)
@@ -70,9 +95,29 @@ ephy_bookmarks_manager_add_bookmark (EphyBookmarksManager *self,
if (g_list_find (self->bookmarks, bookmark))
return;
+ g_signal_connect_object (bookmark,
+ "removed",
+ G_CALLBACK (ephy_bookmarks_manager_remove_bookmark),
+ self,
+ G_CONNECT_SWAPPED);
+
self->bookmarks = g_list_prepend (self->bookmarks, bookmark);
+}
+
+void
+ephy_bookmarks_manager_remove_bookmark (EphyBookmarksManager *self,
+ EphyBookmark *bookmark)
+{
+ gint position;
- g_signal_emit (self, signals[BOOKMARK_ADDED], 0, bookmark);
+ g_return_if_fail (EPHY_IS_BOOKMARKS_MANAGER (self));
+ g_return_if_fail (EPHY_IS_BOOKMARK (bookmark));
+
+ position = g_list_position (self->bookmarks,
+ g_list_find (self->bookmarks, bookmark));
+
+ self->bookmarks = g_list_remove (self->bookmarks, bookmark);
+ g_list_model_items_changed (G_LIST_MODEL (self), position, 1, 0);
}
GList *
@@ -83,29 +128,33 @@ ephy_bookmarks_manager_get_bookmarks (EphyBookmarksManager *self)
return self->bookmarks;
}
-GList *
+GSequence *
ephy_bookmarks_manager_get_tags (EphyBookmarksManager *self)
{
- GHashTable *tags_set;
GList *l;
- GList *tags;
+ GSequence *tags;
g_return_val_if_fail (EPHY_IS_BOOKMARKS_MANAGER (self), NULL);
- tags_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
+ tags = g_sequence_new (g_free);
for (l = self->bookmarks; l != NULL; l = l->next) {
EphyBookmark *bookmark = EPHY_BOOKMARK (l->data);
- GList *ll;
-
- for (ll = ephy_bookmark_get_tags (bookmark); ll != NULL; ll = ll->next)
- g_hash_table_add (tags_set, g_strdup (ll->data));
+ GSequence *bookmark_tags;
+ GSequenceIter *iter;
+
+ bookmark_tags = ephy_bookmark_get_tags (bookmark);
+ for (iter = g_sequence_get_begin_iter (bookmark_tags);
+ !g_sequence_iter_is_end (iter);
+ iter = g_sequence_iter_next (iter)) {
+ char *tag = g_sequence_get (iter);
+
+ if (g_sequence_lookup (tags, tag, (GCompareDataFunc)g_strcmp0, NULL) == NULL)
+ g_sequence_insert_sorted (tags,
+ g_strdup (tag),
+ (GCompareDataFunc)g_strcmp0,
+ NULL);
+ }
}
- tags = g_list_copy_deep (g_hash_table_get_values (tags_set),
- (GCopyFunc)g_strdup,
- NULL);
- g_hash_table_destroy (tags_set);
-
return tags;
}
diff --git a/src/ephy-bookmarks-manager.h b/src/ephy-bookmarks-manager.h
index 55c90ff..a284a00 100644
--- a/src/ephy-bookmarks-manager.h
+++ b/src/ephy-bookmarks-manager.h
@@ -26,11 +26,13 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (EphyBookmarksManager, ephy_bookmarks_manager, EPHY, BOOKMARKS_MANAGER, GObject)
-void ephy_bookmarks_manager_add_bookmark (EphyBookmarksManager *self,
- EphyBookmark *bookmark);
+void ephy_bookmarks_manager_add_bookmark (EphyBookmarksManager *self,
+ EphyBookmark *bookmark);
+void ephy_bookmarks_manager_remove_bookmark (EphyBookmarksManager *self,
+ EphyBookmark *bookmark);
-GList *ephy_bookmarks_manager_get_bookmarks (EphyBookmarksManager *self);
-GList *ephy_bookmarks_manager_get_tags (EphyBookmarksManager *manager);
+GList *ephy_bookmarks_manager_get_bookmarks (EphyBookmarksManager *self);
+GSequence *ephy_bookmarks_manager_get_tags (EphyBookmarksManager *self);
G_END_DECLS
diff --git a/src/ephy-bookmarks-popover.c b/src/ephy-bookmarks-popover.c
index e8862ac..3aa2be0 100644
--- a/src/ephy-bookmarks-popover.c
+++ b/src/ephy-bookmarks-popover.c
@@ -45,18 +45,13 @@ enum {
static GParamSpec *obj_properties[LAST_PROP];
-static void
-bookmark_added_cb (EphyBookmarksPopover *self,
- EphyBookmark *bookmark)
+static GtkWidget *
+create_bookmark_row (gpointer item,
+ gpointer user_data)
{
- GtkWidget *bookmark_row;
-
- g_assert (EPHY_IS_BOOKMARKS_POPOVER (self));
- g_assert (EPHY_IS_BOOKMARK (bookmark));
-
- bookmark_row = ephy_bookmark_row_new (bookmark);
+ EphyBookmark *bookmark = EPHY_BOOKMARK (item);
- gtk_list_box_prepend (GTK_LIST_BOX (self->bookmarks_list_box), bookmark_row);
+ return ephy_bookmark_row_new (bookmark);
}
static void
@@ -67,13 +62,12 @@ bookmarks_list_box_row_activated_cb (EphyBookmarksPopover *self,
EphyBookmark *bookmark;
GActionGroup *action_group;
GAction *action;
- const gchar *url;
+ const char *url;
g_assert (EPHY_IS_BOOKMARKS_POPOVER (self));
g_assert (EPHY_IS_BOOKMARK_ROW (row));
g_assert (GTK_IS_LIST_BOX (box));
-
action_group = gtk_widget_get_action_group (GTK_WIDGET (self->window), "win");
action = g_action_map_lookup_action (G_ACTION_MAP (action_group), "open-bookmark");
@@ -84,7 +78,7 @@ bookmarks_list_box_row_activated_cb (EphyBookmarksPopover *self,
}
static GtkWidget *
-build_tag_box (const gchar *tag)
+create_tag_box (const char *tag)
{
GtkWidget *box;
GtkWidget *image;
@@ -162,44 +156,43 @@ static void
ephy_bookmarks_popover_init (EphyBookmarksPopover *self)
{
EphyBookmarksManager *manager = ephy_shell_get_bookmarks_manager (ephy_shell_get_default ());
- GList *bookmarks;
- GList *tags = NULL;
- GList *l;
+ GSequence *tags, *tags1, *tags2;
+ GSequenceIter *iter;
EphyBookmark *dummy_bookmark;
+ gint i;
gtk_widget_init_template (GTK_WIDGET (self));
- dummy_bookmark = ephy_bookmark_new (g_strdup ("https://duckduckgo.com"), g_strdup ("Test title"));
- tags = g_list_append (tags, g_strdup ("Fun"));
- tags = g_list_append (tags, g_strdup ("Work"));
- ephy_bookmark_set_tags (dummy_bookmark, tags);
+ dummy_bookmark = ephy_bookmark_new (g_strdup ("https://duckduckgo.com/asdasdas/asdas"), g_strdup ("Test
title"));
+ tags1 = g_sequence_new (g_free);
+ for (i = 0; i < 20; i++)
+ g_sequence_insert_sorted (tags1, g_strdup_printf ("Fun %d", i), (GCompareDataFunc)g_strcmp0, NULL);
+
+ ephy_bookmark_set_tags (dummy_bookmark, tags1);
ephy_bookmarks_manager_add_bookmark (manager, dummy_bookmark);
dummy_bookmark = ephy_bookmark_new (g_strdup ("https://wikipedia.com"), g_strdup ("wikipedia"));
ephy_bookmarks_manager_add_bookmark (manager, dummy_bookmark);
+ tags2 = g_sequence_new (g_free);
+ g_sequence_insert_sorted (tags2, g_strdup_printf ("Not Fun %d", 1), (GCompareDataFunc)g_strcmp0, NULL);
+ ephy_bookmark_set_tags (dummy_bookmark, tags2);
- bookmarks = ephy_bookmarks_manager_get_bookmarks (manager);
- for (l = bookmarks; l != NULL; l = g_list_next (l)) {
- EphyBookmark *bookmark = (EphyBookmark *)l->data;
- GtkWidget *bookmark_row;
-
- bookmark_row = ephy_bookmark_row_new (bookmark);
- gtk_list_box_prepend (GTK_LIST_BOX (self->bookmarks_list_box), bookmark_row);
- }
+ gtk_list_box_bind_model (GTK_LIST_BOX (self->bookmarks_list_box),
+ G_LIST_MODEL (manager),
+ create_bookmark_row,
+ NULL, NULL);
tags = ephy_bookmarks_manager_get_tags (manager);
- for (l = tags; l != NULL; l = g_list_next (l)) {
+ for (iter = g_sequence_get_begin_iter (tags);
+ !g_sequence_iter_is_end (iter);
+ iter = g_sequence_iter_next (iter)) {
GtkWidget *tag_box;
- gchar *tag = (gchar *)l->data;
+ const char *tag = g_sequence_get (iter);
- tag_box = build_tag_box (tag);
+ tag_box = create_tag_box (tag);
gtk_list_box_prepend (GTK_LIST_BOX (self->tags_list_box), tag_box);
}
- g_signal_connect_object (manager, "bookmark-added",
- G_CALLBACK (bookmark_added_cb),
- self, G_CONNECT_SWAPPED);
-
g_signal_connect_object (self->bookmarks_list_box, "row-activated",
G_CALLBACK (bookmarks_list_box_row_activated_cb),
self, G_CONNECT_SWAPPED);
diff --git a/src/epiphany.gresource.xml b/src/epiphany.gresource.xml
index 5d528fe..317697e 100644
--- a/src/epiphany.gresource.xml
+++ b/src/epiphany.gresource.xml
@@ -12,6 +12,7 @@
<file preprocess="xml-stripblanks" compressed="true">history-dialog.ui</file>
<file preprocess="xml-stripblanks" compressed="true">passwords-dialog.ui</file>
<file preprocess="xml-stripblanks" compressed="true">shortcuts-dialog.ui</file>
+ <file preprocess="xml-stripblanks" compressed="true">gtk/bookmark-properties-grid.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/bookmark-row.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/bookmarks-popover.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/menus.ui</file>
diff --git a/src/resources/epiphany.css b/src/resources/epiphany.css
index 4ae71ed..301aed0 100644
--- a/src/resources/epiphany.css
+++ b/src/resources/epiphany.css
@@ -3,7 +3,7 @@ button.active-menu {
outline-color: rgba(46, 52, 54, 0.3);
border-color: #b6b6b3;
background-image: none;
- background-color: #d4d4d2;
+ background-color: #d9d9d7;
box-shadow: inset 0 1px rgba(255, 255, 255, 0);
text-shadow: none;
-gtk-icon-shadow: none; }
@@ -70,7 +70,7 @@ button.active-menu {
outline-color: rgba(46, 52, 54, 0.3);
border-color: #909fae;
background-image: none;
- background-color: #b3bec8;
+ background-color: #b9c3cc;
box-shadow: inset 0 1px rgba(255, 255, 255, 0);
text-shadow: none;
-gtk-icon-shadow: none; }
@@ -125,3 +125,35 @@ button.active-menu {
box-shadow: inset 0 0 0 1px #4a90d9; }
.incognito-mode.titlebar entry:backdrop {
box-shadow: none; }
+
+/* Bookmarks */
+.bookmarks-row button {
+ opacity: 0; }
+.bookmarks-row:hover button {
+ opacity: 1; }
+
+.bookmark-tag-widget {
+ padding-left: 8px;
+ padding-right: 8px;
+ background-color: #d7d7d5; }
+ .bookmark-tag-widget label {
+ padding-left: 8px;
+ padding-right: 8px; }
+ .bookmark-tag-widget button {
+ color: white; }
+
+.bookmark-tag-widget-selected {
+ background-color: #4a90d9;
+ color: white; }
+ .bookmark-tag-widget-selected button {
+ color: white; }
+ .bookmark-tag-widget-selected button:hover {
+ color: #2e3436;
+ outline-color: rgba(46, 52, 54, 0.3);
+ border-color: #215d9c;
+ border-bottom-color: #184472;
+ background-image: linear-gradient(to bottom, #63a0de, #4a90d9 60%, #3986d5);
+ text-shadow: 0 1px rgba(255, 255, 255, 0.76923);
+ -gtk-icon-shadow: 0 1px rgba(255, 255, 255, 0.76923);
+ box-shadow: inset 0 1px rgba(255, 255, 255, 0.4);
+ color: white; }
diff --git a/src/resources/epiphany.scss b/src/resources/epiphany.scss
index 18b87fb..35f481d 100644
--- a/src/resources/epiphany.scss
+++ b/src/resources/epiphany.scss
@@ -110,3 +110,45 @@ $edge_color: lighten($incognito_color, 13%);
}
}
}
+
+/* Bookmarks */
+.bookmarks-row {
+ button {
+ opacity: 0;
+ }
+
+ &:hover {
+ button {
+ opacity: 1;
+ }
+ }
+}
+
+.bookmark-tag-widget {
+ padding-left: 8px;
+ padding-right: 8px;
+ background-color: darken($bg_color, 7%);
+
+ label {
+ padding-left: 8px;
+ padding-right: 8px;
+ }
+
+ button {
+ color: white;
+ }
+}
+
+.bookmark-tag-widget-selected {
+ background-color: $selected_bg_color;
+ color: white;
+
+ button {
+ color: white;
+
+ &:hover {
+ @include button(hover, $selected_bg_color);
+ color: white;
+ }
+ }
+}
diff --git a/src/resources/gtk/bookmark-properties-grid.ui b/src/resources/gtk/bookmark-properties-grid.ui
new file mode 100644
index 0000000..5ec3e98
--- /dev/null
+++ b/src/resources/gtk/bookmark-properties-grid.ui
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.18 -->
+ <template class="EphyBookmarkPropertiesGrid" parent="GtkGrid">
+ <property name="margin">12</property>
+ <!-- <property name="border-width">12</property> -->
+ <property name="column-spacing">12</property>
+ <property name="row-spacing">12</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkLabel" id="popover_bookmark_label">
+ <property name="label" translatable="yes">Bookmark</property>
+ <property name="visible">false</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="width">2</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">Name</property>
+ <property name="visible">true</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="name_entry">
+ <property name="visible">true</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">Address</property>
+ <property name="visible">true</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="address_entry">
+ <property name="visible">true</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="popover_tags_label">
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">Tags</property>
+ <property name="visible">false</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+ <property name="label" translatable="yes">Tags</property>
+ <property name="visible">true</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="valign">start</property>
+ <property name="height-request">100</property>
+ <property name="min-content-height">100</property>
+ <property name="hscrollbar-policy">never</property>
+ <property name="vscrollbar-policy">automatic</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkFlowBox" id="tags_box">
+ <property name="column-spacing">6</property>
+ <property name="row-spacing">6</property>
+ <property name="selection-mode">none</property>
+ <property name="homogeneous">true</property>
+ <property name="valign">start</property>
+ <property name="min-children-per-line">2</property>
+ <property name="max-children-per-line">3</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="visible">true</property>
+ <style>
+ <class name="linked"/>
+ </style>
+ <child>
+ <object class="GtkEntry" id="add_tag_entry">
+ <property name="placeholder-text">Add Tag…</property>
+ <property name="activates-default">true</property>
+ <property name="hexpand">true</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="add_tag_button">
+ <property name="label" translatable="yes">_Add</property>
+ <property name="can-default">true</property>
+ <property name="sensitive">false</property>
+ <property name="use-underline">true</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="remove_bookmark_button">
+ <property name="label" translatable="yes">_Remove Bookmark</property>
+ <property name="use-underline">true</property>
+ <property name="halign">end</property>
+ <property name="visible">true</property>
+ <style>
+ <class name="destructive-action"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">6</property>
+ </packing>
+ </child>
+ </template>
+</interface>
diff --git a/src/resources/gtk/bookmark-row.ui b/src/resources/gtk/bookmark-row.ui
index 689924c..d068167 100644
--- a/src/resources/gtk/bookmark-row.ui
+++ b/src/resources/gtk/bookmark-row.ui
@@ -3,14 +3,36 @@
<!-- interface-requires gtk+ 3.18 -->
<template class="EphyBookmarkRow" parent="GtkListBoxRow">
<property name="visible">true</property>
+ <style>
+ <class name="bookmarks-row"/>
+ </style>
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="visible">true</property>
<child>
<object class="GtkLabel" id="title_label">
+ <property name="expand">true</property>
+ <property name="halign">start</property>
<property name="visible">true</property>
</object>
+ <packing>
+ <property name="pack-type">start</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="properties_button">
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">emblem-system-symbolic</property>
+ <property name="visible">true</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="pack-type">end</property>
+ </packing>
</child>
</object>
</child>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]