[evince/wip/gpoo/gtk4-rebase-port: 15/89] ev-recent-view: port to gtk4 with composite template




commit f9e52e8a8f80f2527a92fab3c876ab486834c8c3
Author: Qiu Wenbo <qiuwenbo kylinos com cn>
Date:   Tue Aug 3 00:07:54 2021 +0800

    ev-recent-view: port to gtk4 with composite template
    
    Signed-off-by: Qiu Wenbo <qiuwenbo kylinos com cn>

 shell/ev-recent-view.c      | 163 +++++++++++++-------------------------------
 shell/ev-recent-view.h      |   4 +-
 shell/evince-recent-view.ui |  60 ++++++++++++++++
 3 files changed, 110 insertions(+), 117 deletions(-)
---
diff --git a/shell/ev-recent-view.c b/shell/ev-recent-view.c
index 74a97a469..95a75a163 100644
--- a/shell/ev-recent-view.c
+++ b/shell/ev-recent-view.c
@@ -66,7 +66,7 @@ enum {
 
 static guint signals[NUM_SIGNALS] = { 0, };
 
-G_DEFINE_TYPE_WITH_PRIVATE (EvRecentView, ev_recent_view, GTK_TYPE_SCROLLED_WINDOW)
+G_DEFINE_TYPE_WITH_PRIVATE (EvRecentView, ev_recent_view, GTK_TYPE_BOX)
 
 #define ICON_VIEW_SIZE 128
 #define MAX_RECENT_VIEW_ITEMS 64
@@ -138,7 +138,6 @@ ev_recent_view_clear_model (EvRecentView *ev_recent_view)
         gtk_tree_model_foreach (GTK_TREE_MODEL (priv->model),
                                 (GtkTreeModelForeachFunc)ev_recent_view_clear_async_data,
                                 ev_recent_view);
-
         gtk_list_store_clear (priv->model);
 }
 
@@ -150,8 +149,6 @@ ev_recent_view_dispose (GObject *obj)
 
         if (priv->model) {
                 ev_recent_view_clear_model (ev_recent_view);
-                g_object_unref (priv->model);
-                priv->model = NULL;
         }
 
         if (priv->recent_manager_changed_handler_id) {
@@ -165,6 +162,7 @@ ev_recent_view_dispose (GObject *obj)
         g_clear_object (&priv->thumbnail_factory);
 #endif
 
+
         G_OBJECT_CLASS (ev_recent_view_parent_class)->dispose (obj);
 }
 
@@ -179,12 +177,12 @@ compare_recent_items (GtkRecentInfo *a,
         has_ev_b = gtk_recent_info_has_application (b, evince);
 
         if (has_ev_a && has_ev_b) {
-                time_t time_a, time_b;
+                GDateTime *time_a, *time_b;
 
                 time_a = gtk_recent_info_get_modified (a);
                 time_b = gtk_recent_info_get_modified (b);
 
-                return (time_b - time_a);
+                return g_date_time_compare (time_b, time_a);
         } else if (has_ev_a) {
                 return -1;
         } else if (has_ev_b) {
@@ -211,7 +209,7 @@ on_query_tooltip_event (GtkWidget     *widget,
 
         model = gtk_icon_view_get_model (GTK_ICON_VIEW (priv->view));
         if (!gtk_icon_view_get_tooltip_context (GTK_ICON_VIEW (priv->view),
-                                                &x, &y, keyboard_tip,
+                                                x, y, keyboard_tip,
                                                 &model, &path, &iter))
                 return FALSE;
 
@@ -232,53 +230,6 @@ on_query_tooltip_event (GtkWidget     *widget,
         return TRUE;
 }
 
-static gboolean
-on_button_release_event (GtkWidget      *view,
-                         GdkEventButton *event,
-                         EvRecentView   *ev_recent_view)
-{
-        EvRecentViewPrivate *priv = GET_PRIVATE (ev_recent_view);
-        GtkTreePath         *path;
-
-        /* eat double/triple click events */
-        if (event->type != GDK_BUTTON_RELEASE)
-                return TRUE;
-
-        if (priv->pressed_item_tree_path == NULL)
-                return FALSE;
-
-        path = gtk_icon_view_get_path_at_pos (GTK_ICON_VIEW (priv->view), event->x, event->y);
-        if (path == NULL)
-                return FALSE;
-
-        if (gtk_tree_path_compare (path, priv->pressed_item_tree_path) == 0) {
-                g_clear_pointer (&priv->pressed_item_tree_path, gtk_tree_path_free);
-                gtk_icon_view_item_activated (GTK_ICON_VIEW (priv->view), path);
-                gtk_tree_path_free (path);
-
-                return TRUE;
-        }
-
-        g_clear_pointer (&priv->pressed_item_tree_path, gtk_tree_path_free);
-        gtk_tree_path_free (path);
-
-        return FALSE;
-}
-
-static gboolean
-on_button_press_event (GtkWidget      *view,
-                       GdkEventButton *event,
-                       EvRecentView   *ev_recent_view)
-{
-        EvRecentViewPrivate *priv = GET_PRIVATE (ev_recent_view);
-
-        g_clear_pointer (&priv->pressed_item_tree_path, gtk_tree_path_free);
-        priv->pressed_item_tree_path =
-                gtk_icon_view_get_path_at_pos (GTK_ICON_VIEW (priv->view), event->x, event->y);
-
-       return TRUE;
-}
-
 static void
 on_icon_view_item_activated (GtkIconView  *iconview,
                              GtkTreePath  *path,
@@ -298,6 +249,33 @@ on_icon_view_item_activated (GtkIconView  *iconview,
         g_free (uri);
 }
 
+static GdkTexture *
+gdk_texture_new_for_surface (cairo_surface_t *surface)
+{
+  GdkTexture *texture;
+  GBytes *bytes;
+
+  g_return_val_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE, NULL);
+  g_return_val_if_fail (cairo_image_surface_get_width (surface) > 0, NULL);
+  g_return_val_if_fail (cairo_image_surface_get_height (surface) > 0, NULL);
+
+  bytes = g_bytes_new_with_free_func (cairo_image_surface_get_data (surface),
+                                      cairo_image_surface_get_height (surface)
+                                      * cairo_image_surface_get_stride (surface),
+                                      (GDestroyNotify) cairo_surface_destroy,
+                                      cairo_surface_reference (surface));
+
+  texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface),
+                                    cairo_image_surface_get_height (surface),
+                                    GDK_MEMORY_DEFAULT,
+                                    bytes,
+                                    cairo_image_surface_get_stride (surface));
+
+  g_bytes_unref (bytes);
+
+  return texture;
+}
+
 static void
 add_thumbnail_to_model (GetDocumentInfoAsyncData *data,
                         cairo_surface_t          *thumbnail)
@@ -315,20 +293,20 @@ add_thumbnail_to_model (GetDocumentInfoAsyncData *data,
         border.top = 3;
         border.bottom = 6;
 
+#if 0
         surface = gd_embed_surface_in_frame (thumbnail,
                                              "resource:///org/gnome/evince/ui/thumbnail-frame.png",
                                              &border, &border);
+#endif
 
         path = gtk_tree_row_reference_get_path (data->row);
         if (path != NULL) {
                 gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->model), &iter, path);
                 gtk_list_store_set (priv->model, &iter,
-                                    EV_RECENT_VIEW_COLUMN_ICON, surface,
+                                    EV_RECENT_VIEW_COLUMN_ICON, gdk_texture_new_for_surface (thumbnail),
                                     -1);
                 gtk_tree_path_free (path);
         }
-
-        cairo_surface_destroy (surface);
 }
 
 #ifdef HAVE_LIBGNOME_DESKTOP
@@ -755,7 +733,7 @@ ev_recent_view_refresh (EvRecentView *ev_recent_view)
                 GtkTreePath              *path;
                 GtkRecentInfo            *info;
                 const gchar              *uri;
-                GdkPixbuf                *pixbuf;
+                GIcon                    *icon;
                 cairo_surface_t          *thumbnail = NULL;
                 GtkTreeIter               iter;
 
@@ -768,10 +746,10 @@ ev_recent_view_refresh (EvRecentView *ev_recent_view)
                         continue;
 
                 uri = gtk_recent_info_get_uri (info);
-                pixbuf = gtk_recent_info_get_icon (info, ICON_VIEW_SIZE);
-                if (pixbuf) {
-                        thumbnail = ev_document_misc_surface_from_pixbuf (pixbuf);
-                        g_object_unref (pixbuf);
+                icon = gtk_recent_info_get_gicon (info);
+                if (GDK_IS_PIXBUF (icon)) {
+                        thumbnail = ev_document_misc_surface_from_pixbuf (GDK_PIXBUF (icon));
+                        g_object_unref (icon);
                 }
 
                 gtk_list_store_append (priv->model, &iter);
@@ -802,46 +780,9 @@ ev_recent_view_constructed (GObject *object)
 {
         EvRecentView        *ev_recent_view = EV_RECENT_VIEW (object);
         EvRecentViewPrivate *priv = GET_PRIVATE (ev_recent_view);
-        GtkCellRenderer     *renderer;
 
         G_OBJECT_CLASS (ev_recent_view_parent_class)->constructed (object);
 
-        priv->view = gtk_icon_view_new_with_model (GTK_TREE_MODEL (priv->model));
-
-        gtk_icon_view_set_column_spacing (GTK_ICON_VIEW (priv->view), 20);
-        gtk_icon_view_set_margin (GTK_ICON_VIEW (priv->view), 16);
-        gtk_icon_view_set_selection_mode (GTK_ICON_VIEW (priv->view), GTK_SELECTION_NONE);
-        gtk_widget_set_hexpand (priv->view, TRUE);
-        gtk_widget_set_vexpand (priv->view, TRUE);
-        gtk_widget_set_has_tooltip (priv->view, TRUE);
-
-        renderer = gtk_cell_renderer_pixbuf_new ();
-        g_object_set (renderer, "xalign", 0.5, "yalign", 0.5, NULL);
-
-        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->view), renderer, FALSE);
-        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (priv->view), renderer,
-                                       "surface", EV_RECENT_VIEW_COLUMN_ICON);
-
-        renderer = gd_two_lines_renderer_new ();
-        g_object_set (renderer,
-                      "xalign", 0.5,
-                      "alignment", PANGO_ALIGN_CENTER,
-                      "wrap-mode", PANGO_WRAP_WORD_CHAR,
-                      "wrap-width", 128,
-                      "text-lines", 3,
-                      NULL);
-        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->view), renderer, FALSE);
-        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (priv->view), renderer,
-                                       "text", EV_RECENT_VIEW_COLUMN_PRIMARY_TEXT);
-        gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (priv->view), renderer,
-                                       "line-two", EV_RECENT_VIEW_COLUMN_SECONDARY_TEXT);
-
-        g_signal_connect (priv->view, "button-press-event",
-                          G_CALLBACK (on_button_press_event),
-                          ev_recent_view);
-        g_signal_connect (priv->view, "button-release-event",
-                          G_CALLBACK (on_button_release_event),
-                          ev_recent_view);
         g_signal_connect (priv->view, "item-activated",
                           G_CALLBACK (on_icon_view_item_activated),
                           ev_recent_view);
@@ -849,10 +790,6 @@ ev_recent_view_constructed (GObject *object)
                           G_CALLBACK (on_query_tooltip_event),
                           ev_recent_view);
 
-        gtk_style_context_add_class (gtk_widget_get_style_context (priv->view), "content-view");
-        gtk_container_add (GTK_CONTAINER (ev_recent_view), priv->view);
-        gtk_widget_show (priv->view);
-
         ev_recent_view_refresh (ev_recent_view);
 }
 
@@ -861,19 +798,9 @@ ev_recent_view_init (EvRecentView *ev_recent_view)
 {
         EvRecentViewPrivate *priv = GET_PRIVATE (ev_recent_view);
 
+        gtk_widget_init_template (GTK_WIDGET (ev_recent_view));
+
         priv->recent_manager = gtk_recent_manager_get_default ();
-        priv->model = gtk_list_store_new (NUM_COLUMNS,
-                                          G_TYPE_STRING,
-                                          G_TYPE_STRING,
-                                          G_TYPE_STRING,
-                                          CAIRO_GOBJECT_TYPE_SURFACE,
-                                          G_TYPE_POINTER);
-
-        gtk_widget_set_hexpand (GTK_WIDGET (ev_recent_view), TRUE);
-        gtk_widget_set_vexpand (GTK_WIDGET (ev_recent_view), TRUE);
-        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (ev_recent_view),
-                                        GTK_POLICY_NEVER,
-                                        GTK_POLICY_AUTOMATIC);
         priv->recent_manager_changed_handler_id =
                 g_signal_connect_swapped (priv->recent_manager,
                                           "changed",
@@ -885,10 +812,16 @@ static void
 ev_recent_view_class_init (EvRecentViewClass *klass)
 {
         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
+        GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
         g_object_class->constructed = ev_recent_view_constructed;
         g_object_class->dispose = ev_recent_view_dispose;
 
+        g_type_ensure (GD_TYPE_TWO_LINES_RENDERER);
+        gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/evince/ui/recent-view.ui");
+        gtk_widget_class_bind_template_child_private (widget_class, EvRecentView, model);
+        gtk_widget_class_bind_template_child_private (widget_class, EvRecentView, view);
+
         signals[ITEM_ACTIVATED] =
                   g_signal_new ("item-activated",
                                 EV_TYPE_RECENT_VIEW,
diff --git a/shell/ev-recent-view.h b/shell/ev-recent-view.h
index ea1186cc7..0110574b5 100644
--- a/shell/ev-recent-view.h
+++ b/shell/ev-recent-view.h
@@ -36,12 +36,12 @@ typedef struct _EvRecentViewClass   EvRecentViewClass;
 
 struct _EvRecentView
 {
-        GtkScrolledWindow parent;
+        GtkBox parent;
 };
 
 struct _EvRecentViewClass
 {
-        GtkScrolledWindowClass parent_class;
+        GtkBoxClass parent_class;
 };
 
 GType      ev_recent_view_get_type (void) G_GNUC_CONST;
diff --git a/shell/evince-recent-view.ui b/shell/evince-recent-view.ui
new file mode 100644
index 000000000..311ff0dd0
--- /dev/null
+++ b/shell/evince-recent-view.ui
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk" version="4.0"/>
+  <template class="EvRecentView" parent="GtkBox">
+    <property name="orientation">vertical</property>
+    <child type="end">
+      <object class="GtkScrolledWindow" id="swindow">
+        <property name="vexpand">True</property>
+        <property name="hexpand">True</property>
+        <property name="hscrollbar-policy">never</property>
+        <property name="vscrollbar-policy">automatic</property>
+        <child>
+          <object class="GtkIconView" id="view">
+            <property name="model">model</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <property name="has-tooltip">True</property>
+            <property name="column-spacing">20</property>
+            <property name="margin">16</property>
+            <property name="activate-on-single-click">True</property>
+            <style>
+              <class name="content-view" />
+            </style>
+            <child>
+              <object class="GtkCellRendererPixbuf">
+                <property name="xalign">0.5</property>
+                <property name="yalign">0.5</property>
+              </object>
+              <attributes>
+                <attribute name="texture">3</attribute>
+              </attributes>
+            </child>
+            <child>
+              <object class="GdTwoLinesRenderer">
+                <property name="xalign">0.5</property>
+                <property name="alignment">center</property>
+                <property name="wrap-mode">2</property>
+                <property name="wrap-width">128</property>
+                <property name="text-lines">3</property>
+              </object>
+              <attributes>
+                <attribute name="text">1</attribute>
+                <attribute name="line-two">2</attribute>
+              </attributes>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+    <object class="GtkListStore" id="model">
+      <columns>
+        <column type="gchararray" />
+        <column type="gchararray" />
+        <column type="gchararray" />
+        <column type="GdkTexture" />
+        <column type="gpointer" />
+      </columns>
+    </object>
+  </template>
+</interface>


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