[evince/wip/gpoo/gtk4-rebase-port: 16/89] shell: Port EvSidebar to gtk4
- From: Germán Poo-Caamaño <gpoo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evince/wip/gpoo/gtk4-rebase-port: 16/89] shell: Port EvSidebar to gtk4
- Date: Mon, 21 Mar 2022 01:11:28 +0000 (UTC)
commit 7e95e640be07a0b2e9c4106bbffc1551c3aebd39
Author: Qiu Wenbo <qiuwenbo kylinos com cn>
Date: Tue Aug 3 00:17:58 2021 +0800
shell: Port EvSidebar to gtk4
* Switch to composite template
* Support internal-child property
Signed-off-by: Qiu Wenbo <qiuwenbo kylinos com cn>
shell/ev-sidebar.c | 236 +++++++++++++++++++++---------------------------
shell/ev-sidebar.h | 2 +-
shell/evince-sidebar.ui | 24 +++++
3 files changed, 129 insertions(+), 133 deletions(-)
---
diff --git a/shell/ev-sidebar.c b/shell/ev-sidebar.c
index ff8ca1d16..23ef6fbb3 100644
--- a/shell/ev-sidebar.c
+++ b/shell/ev-sidebar.c
@@ -35,11 +35,13 @@
#include "ev-sidebar.h"
#include "ev-sidebar-page.h"
+#include "ev-sidebar-links.h"
enum
{
PROP_0,
PROP_CURRENT_PAGE,
+ PROP_DOCUMENT_MODEL,
PROP_ACTIVE_ICON_NAME
};
@@ -57,26 +59,16 @@ typedef struct {
GtkWidget *switcher;
EvDocumentModel *model;
- GtkTreeModel *page_model;
} EvSidebarPrivate;
-G_DEFINE_TYPE_WITH_PRIVATE (EvSidebar, ev_sidebar, GTK_TYPE_BOX)
+static void ev_sidebar_buildable_iface_init (GtkBuildableIface *iface);
-#define GET_PRIVATE(o) ev_sidebar_get_instance_private (o)
-
-static void
-ev_sidebar_dispose (GObject *object)
-{
- EvSidebar *ev_sidebar = EV_SIDEBAR (object);
- EvSidebarPrivate *priv = GET_PRIVATE (ev_sidebar);
+G_DEFINE_TYPE_WITH_CODE (EvSidebar, ev_sidebar, GTK_TYPE_BOX,
+ G_ADD_PRIVATE (EvSidebar)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+ ev_sidebar_buildable_iface_init))
- if (priv->page_model) {
- g_object_unref (priv->page_model);
- priv->page_model = NULL;
- }
-
- G_OBJECT_CLASS (ev_sidebar_parent_class)->dispose (object);
-}
+#define GET_PRIVATE(o) ev_sidebar_get_instance_private (o)
static void
ev_sidebar_set_property (GObject *object,
@@ -91,6 +83,10 @@ ev_sidebar_set_property (GObject *object,
case PROP_CURRENT_PAGE:
ev_sidebar_set_page (sidebar, g_value_get_object (value));
break;
+ case PROP_DOCUMENT_MODEL:
+ ev_sidebar_set_model (sidebar,
+ EV_DOCUMENT_MODEL (g_value_get_object (value)));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -114,13 +110,27 @@ ev_sidebar_get_visible_icon_name (EvSidebar *ev_sidebar)
stack = GTK_STACK (priv->stack);
widget = gtk_stack_get_visible_child (stack);
- gtk_container_child_get (GTK_CONTAINER (stack), widget,
+
+ g_object_get (gtk_stack_get_page (stack, widget),
"icon-name", &icon_name,
NULL);
-
return icon_name;
}
+static void
+on_child_change (GObject *gobject,
+ GParamSpec *pspec,
+ EvSidebar *ev_sidebar)
+{
+ EvSidebarPrivate *priv = GET_PRIVATE (ev_sidebar);
+ GtkStack *stack = GTK_STACK (priv->stack);
+ const gchar *name;
+
+ name = gtk_stack_get_visible_child_name (stack);
+ if (name)
+ g_object_notify (G_OBJECT (ev_sidebar), "current-page");
+}
+
static void
ev_sidebar_get_property (GObject *object,
guint prop_id,
@@ -149,11 +159,19 @@ static void
ev_sidebar_class_init (EvSidebarClass *ev_sidebar_class)
{
GObjectClass *g_object_class = G_OBJECT_CLASS (ev_sidebar_class);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (ev_sidebar_class);
- g_object_class->dispose = ev_sidebar_dispose;
g_object_class->get_property = ev_sidebar_get_property;
g_object_class->set_property = ev_sidebar_set_property;
+ g_type_ensure (EV_TYPE_SIDEBAR_LINKS);
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/evince/ui/sidebar.ui");
+ gtk_widget_class_bind_template_child_private (widget_class, EvSidebar, switcher);
+ gtk_widget_class_bind_template_child_private (widget_class, EvSidebar, stack);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_child_change);
+
g_object_class_install_property (g_object_class,
PROP_CURRENT_PAGE,
g_param_spec_object ("current-page",
@@ -170,62 +188,27 @@ ev_sidebar_class_init (EvSidebarClass *ev_sidebar_class)
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
-}
-static void
-ev_sidebar_child_change_cb (GObject *gobject,
- GParamSpec *pspec,
- EvSidebar *ev_sidebar)
-{
- EvSidebarPrivate *priv = GET_PRIVATE (ev_sidebar);
- GtkStack *stack = GTK_STACK (priv->stack);
- const gchar *name;
-
- name = gtk_stack_get_visible_child_name (stack);
- if (name)
- g_object_notify (G_OBJECT (ev_sidebar), "current-page");
+ g_object_class_install_property (g_object_class,
+ PROP_DOCUMENT_MODEL,
+ g_param_spec_object ("document-model",
+ "DocumentModel",
+ "The document model",
+ EV_TYPE_DOCUMENT_MODEL,
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
}
static void
ev_sidebar_init (EvSidebar *ev_sidebar)
{
- EvSidebarPrivate *priv;
- GtkWidget *switcher;
- GtkWidget *stack;
+ GtkWidget *widget = GTK_WIDGET (ev_sidebar);
- priv = GET_PRIVATE (ev_sidebar);
-
- /* data model */
- priv->page_model = (GtkTreeModel *)
- gtk_list_store_new (PAGE_COLUMN_NUM_COLS,
- G_TYPE_STRING,
- GTK_TYPE_WIDGET,
- G_TYPE_STRING,
- G_TYPE_STRING);
-
- switcher = gtk_stack_switcher_new ();
- priv->switcher = switcher;
- gtk_box_pack_end (GTK_BOX (ev_sidebar), switcher, FALSE, TRUE, 0);
- g_object_set (switcher, "icon-size", 1, NULL);
- gtk_container_set_border_width (GTK_CONTAINER (switcher), 6);
- gtk_widget_set_halign (switcher, GTK_ALIGN_FILL);
- gtk_widget_set_hexpand (switcher, TRUE);
- gtk_box_set_homogeneous (GTK_BOX (switcher), TRUE);
- gtk_widget_show (priv->switcher);
-
- stack = gtk_stack_new ();
- priv->stack = stack;
- gtk_stack_set_homogeneous (GTK_STACK (stack), TRUE);
- gtk_stack_switcher_set_stack (GTK_STACK_SWITCHER (switcher),
- GTK_STACK (stack));
- gtk_box_pack_end (GTK_BOX (ev_sidebar), stack, TRUE, TRUE, 0);
- gtk_widget_show (priv->stack);
-
- g_signal_connect (stack, "notify::visible-child",
- G_CALLBACK (ev_sidebar_child_change_cb),
- ev_sidebar);
+ gtk_widget_init_template (widget);
}
+
static gboolean
ev_sidebar_current_page_support_document (EvSidebar *ev_sidebar,
EvDocument *document)
@@ -236,6 +219,7 @@ ev_sidebar_current_page_support_document (EvSidebar *ev_sidebar,
document);
}
+
static void
ev_sidebar_document_changed_cb (EvDocumentModel *model,
GParamSpec *pspec,
@@ -243,66 +227,63 @@ ev_sidebar_document_changed_cb (EvDocumentModel *model,
{
EvSidebarPrivate *priv = GET_PRIVATE (ev_sidebar);
EvDocument *document = ev_document_model_get_document (model);
- GtkTreeIter iter;
- gboolean valid;
- GtkWidget *first_supported_page = NULL;
-
- for (valid = gtk_tree_model_get_iter_first (priv->page_model, &iter);
- valid;
- valid = gtk_tree_model_iter_next (priv->page_model, &iter)) {
- GtkWidget *widget;
- gchar *title;
- gchar *icon_name;
-
- gtk_tree_model_get (priv->page_model, &iter,
- PAGE_COLUMN_MAIN_WIDGET, &widget,
- PAGE_COLUMN_TITLE, &title,
- PAGE_COLUMN_ICON_NAME, &icon_name,
- -1);
-
- if (ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (widget), document)) {
- gtk_container_child_set (GTK_CONTAINER (priv->stack),
- widget,
- "icon-name", icon_name,
- "title", title,
- NULL);
- if (!first_supported_page)
- first_supported_page = widget;
- } else {
- /* Without icon and title, the page is not shown in
- * the GtkStackSwitchter */
- gtk_container_child_set (GTK_CONTAINER (priv->stack),
- widget,
- "icon-name", NULL,
- "title", NULL,
- NULL);
- }
- g_object_unref (widget);
- g_free (title);
- g_free (icon_name);
+ GListModel *list = G_LIST_MODEL (gtk_stack_get_pages (GTK_STACK (priv->stack)));
+ EvSidebarPage *first_supported_page = NULL, *sidebar_page;
+ guint i = 0;
+ GtkStackPage *page;
+ gboolean supported;
+
+ while ((page = g_list_model_get_item (list, i)) != NULL) {
+ sidebar_page = EV_SIDEBAR_PAGE (gtk_stack_page_get_child (page));
+
+ supported = ev_sidebar_page_support_document (sidebar_page, document);
+ gtk_stack_page_set_visible (page, supported);
+
+ if (supported && !first_supported_page)
+ first_supported_page = sidebar_page;
+
+ i++;
}
if (first_supported_page != NULL) {
if (!ev_sidebar_current_page_support_document (ev_sidebar, document)) {
- ev_sidebar_set_page (ev_sidebar, first_supported_page);
+ ev_sidebar_set_page (ev_sidebar, GTK_WIDGET (first_supported_page));
}
} else {
gtk_widget_hide (GTK_WIDGET (ev_sidebar));
}
}
+static GtkBuildableIface *parent_buildable_iface;
+
+static GObject *
+ev_sidebar_buildable_get_internal_child (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ const char *childname)
+{
+ EvSidebar *sidebar = EV_SIDEBAR (buildable);
+ EvSidebarPrivate *priv = GET_PRIVATE (sidebar);
+
+ if (strcmp (childname, "stack") == 0)
+ return G_OBJECT (priv->stack);
+
+ return parent_buildable_iface->get_internal_child (buildable, builder, childname);
+}
+
+static void
+ev_sidebar_buildable_iface_init (GtkBuildableIface *iface)
+{
+ parent_buildable_iface = g_type_interface_peek_parent (iface);
+
+ iface->get_internal_child = ev_sidebar_buildable_get_internal_child;
+}
+
/* Public functions */
GtkWidget *
ev_sidebar_new (void)
{
- GtkWidget *ev_sidebar;
-
- ev_sidebar = g_object_new (EV_TYPE_SIDEBAR,
- "orientation", GTK_ORIENTATION_VERTICAL,
- NULL);
-
- return ev_sidebar;
+ return GTK_WIDGET (g_object_new (EV_TYPE_SIDEBAR, NULL));
}
void
@@ -312,32 +293,18 @@ ev_sidebar_add_page (EvSidebar *ev_sidebar,
const gchar *title,
const gchar *icon_name)
{
- EvSidebarPrivate *priv;
- GtkTreeIter iter;
+ EvSidebarPrivate *priv = GET_PRIVATE (ev_sidebar);
+ GtkStackPage *page;
+ GtkStack *stack = GTK_STACK (priv->stack);
g_return_if_fail (EV_IS_SIDEBAR (ev_sidebar));
g_return_if_fail (GTK_IS_WIDGET (widget));
- priv = GET_PRIVATE (ev_sidebar);
-
ev_sidebar_page_set_model (EV_SIDEBAR_PAGE (widget), priv->model);
- gtk_stack_add_named (GTK_STACK (priv->stack), widget, name);
- gtk_container_child_set (GTK_CONTAINER (priv->stack), widget,
- "icon-name", icon_name,
- "title", title,
- NULL);
-
- /* Insert and move to end */
- gtk_list_store_insert_with_values (GTK_LIST_STORE (priv->page_model),
- &iter, 0,
- PAGE_COLUMN_NAME, name,
- PAGE_COLUMN_MAIN_WIDGET, widget,
- PAGE_COLUMN_TITLE, title,
- PAGE_COLUMN_ICON_NAME, icon_name,
- -1);
- gtk_list_store_move_before (GTK_LIST_STORE (priv->page_model),
- &iter, NULL);
+ gtk_stack_add_named (stack, widget, name);
+ page = gtk_stack_get_page (stack, widget);
+ g_object_set (page, "icon-name", icon_name, "title", title, NULL);
}
void
@@ -354,8 +321,13 @@ ev_sidebar_set_model (EvSidebar *ev_sidebar,
if (model == priv->model)
return;
- priv->model = model;
+ if (priv->model) {
+ g_signal_handlers_disconnect_by_func (priv->model,
+ G_CALLBACK (ev_sidebar_document_changed_cb), ev_sidebar);
+ g_object_unref (priv->model);
+ }
+ priv->model = g_object_ref (model);
g_signal_connect (model, "notify::document",
G_CALLBACK (ev_sidebar_document_changed_cb),
ev_sidebar);
diff --git a/shell/ev-sidebar.h b/shell/ev-sidebar.h
index b0e1e5574..61f19e187 100644
--- a/shell/ev-sidebar.h
+++ b/shell/ev-sidebar.h
@@ -1,6 +1,6 @@
/* ev-sidebar.h
* this file is part of evince, a gnome document viewer
- *
+ *
* Copyright (C) 2004 Red Hat, Inc.
* Copyright (C) 2018 Germán Poo-Caamaño <gpoo gnome org>
*
diff --git a/shell/evince-sidebar.ui b/shell/evince-sidebar.ui
new file mode 100644
index 000000000..41ae83166
--- /dev/null
+++ b/shell/evince-sidebar.ui
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk" version="4.0"/>
+ <requires lib="libadwaita" version="1.0"/>
+ <template class="EvSidebar" parent="GtkBox">
+ <property name="orientation">vertical</property>
+ <child type="start">
+ <object class="GtkStack" id="stack">
+ <signal name="notify::visible-child" handler="on_child_change" />
+ </object>
+ </child>
+ <child type="start">
+ <object class="GtkStackSwitcher" id="switcher">
+ <property name="stack">stack</property>
+ <property name="halign">center</property>
+ <property name="hexpand">True</property>
+ <property name="margin-top">6</property>
+ <property name="margin-bottom">6</property>
+ <property name="margin-start">6</property>
+ <property name="margin-end">6</property>
+ </object>
+ </child>
+ </template>
+</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]