GTK4 LIST MODEL 知多少?

【GTK4】LIST MODEL总结

本人就职于国际知名终端厂商,负责modem芯片研发。
在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G算力网络技术标准研究。


博客内容主要围绕:
       5G协议讲解
       算力网络讲解(云计算,边缘计算,端计算)
       高级C语言讲解
       Rust语言讲解

一、LIST MODEL创建、管理工具

通过这些工具我们可以通过修改、结合我们现有的models,去创建新的models

1️⃣ GtkSliceListModel

       取一个现有model的切片,由偏移量和大小给出,并创建一个只包含这些项的新model。如果你想在页面视图中显示一个大列表,这是很有用的——前进和后退按钮将根据大小增加或减少偏移量。切片模型还可以用来递增地填充列表,方法是随着时间的推移增大切片。

2️⃣ GtkFlattenListModel

       取几个list model并将它们组合成一个list model(可以理解为合并后的list model中的数据是多个不同的list model elements)。当您需要组合来自多个来源的数据时,这是非常有用的,例如GTK在打印对话框中处理纸张大小。
A flattened list

Note:组合成flatten model之后,原始model继续存在,并且原始model的更新将传播到flatten model。

3️⃣ GtkMapListModel

       有时,你的 list model 中有数据,但它的形式并不完全正确。在这种情况下,可以使用GtkMapListModel将原始模型中的每个项替换为不同的项


二、LIST MODEL的具体应用

1️⃣ Pango objects

       这里的第一个例子是Pango objects,它为自己的数据对象实现了list model 接口:

  • PangoFontMap是PangoFontFamily对象的list model,PangoFontFamily是PangoFontFace对象的list model。字体选择器正在使用这些模型。
    在这里插入图片描述

2️⃣ GtkDirectoryList和GtkBookmarkList

       下一个示例是GtkDirectoryList和GtkBookmarkList对象,它们将在文件选择器中用于表示目录内容和书签。一个有趣的细节是,它们都需要做IO来填充它们的内容,而且它们是异步进行的,以避免阻塞UI很长时间。

3️⃣ GtkDropDown

       GtkStringList是一个简单的 list model 包装非常常见的字符串数组。经常使用这种列表模型的一个例子是GtkDropDown。这是如此常见,以至于GtkDropDown有一个方便的构造函数,它接受一个字符串数组,并为你创建GtkStringList:

GtkWidget * gtk_drop_down_new_from_strings (const char * const * strings)

三、LIST MODEL的增强版本

GtkSelectionModel

GtkSelectionModel对list model进行了扩展

GtkSelectionModel 对 list model 中的每个项,无论是否被选中都会维护信息。可以通过下面的函数获取item 的选择状态👇

gboolean gtk_selection_model_is_selected (GtkSelectionModel *model ,guint pos)

GtkBitset * gtk_selection_model_get_selection (GtkSelectionModel *model)

所以你可以获得单个项目的选择信息,或者以bitset的形式获得整个项目的选择信息。当然,还有一个::selection-changed信号,其工作方式与GListModel的::items-changed信号非常相似。

三种GtkSelectionModel实现

GTK有三种GtkSelectionModel实现:

  • GtkSingleSelection :同一时刻只能选择一个item
  • GtkMultiSelection : 同一时刻可以选择多个item
  • GtkNoSelection : 任何item 都不可以被选中

gtk4-demo中关于GtkMultiSelection 的例子

[video(video-fmXrzeOb-1627999924924)(type-csdn)(url-https://live.csdn.net/v/embed/174416)(image-https://vedu.csdnimg.cn/0af22d8fa3484e639e4b2cf8cd663a87/snapshots/71735d89e8e14b10ad3d13b5734623da-00001.jpg)(title-GtkGridView colors demo)]


四、可实现动态过滤、排序的 LIST MODEL

       这两个model分别为 GtkFilterListModelGtkSortListModel。它们俩都使用辅助对象GtkFilter 和 GtkSorter来帮助实现item 的过滤与排序。

这里有一个gtk4-demo中的例子,它就是使用GtkFilterListModel 实现的关键字过滤👇

[video(video-zNO1Ugz3-1628000856763)(type-csdn)(url-https://live.csdn.net/v/embed/174417)(image-https://vedu.csdnimg.cn/cdeb7bcae77a4ad2bb83e24f0b057094/snapshots/87ae09c4a8c74efb97dbf129aebff0ad-00002.jpg)(title-GtkFilterListModel )]

下面👇附上具体的code,以供参考:

#include <gtk/gtk.h>

static GtkWidget *window = NULL;
static GtkWidget *progress;

const char *factory_text =
"<?xml version='1.0' encoding='UTF-8'?>\n"
"<interface>\n"
"  <template class='GtkListItem'>\n"
"    <property name='child'>\n"
"      <object class='GtkLabel'>\n"
"        <property name='ellipsize'>end</property>\n"
"        <property name='xalign'>0</property>\n"
"        <binding name='label'>\n"
"          <lookup name='string' type='GtkStringObject'>\n"
"            <lookup name='item'>GtkListItem</lookup>\n"
"          </lookup>\n"
"        </binding>\n"
"      </object>\n"
"    </property>\n"
"  </template>\n"
"</interface>\n";

static void
update_title_cb (GtkFilterListModel *model)
{
  guint total;
  char *title;
  guint pending;

  total = g_list_model_get_n_items (gtk_filter_list_model_get_model (model));
  pending = gtk_filter_list_model_get_pending (model);

  title = g_strdup_printf ("%u lines", g_list_model_get_n_items (G_LIST_MODEL (model)));

  gtk_widget_set_visible (progress, pending != 0);
  gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progress), (total - pending) / (double) total);
  gtk_window_set_title (GTK_WINDOW (window), title);
  g_free (title);
}

GtkWidget *
do_listview_words (GtkWidget *do_widget)
{
  if (window == NULL)
    {
      GtkWidget *listview, *sw, *vbox, *search_entry, *overlay;
      GtkFilterListModel *filter_model;
      GtkStringList *stringlist;
      GtkFilter *filter;

      char **words;
      words = g_strsplit ("lorem ipsum dolor sit amet consectetur adipisci elit sed eiusmod tempor incidunt labore et dolore magna aliqua ut enim ad minim veniam quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat", " ", -1);
      stringlist = gtk_string_list_new ((const char **) words);
      g_strfreev (words);
      g_object_unref (file);

      filter = GTK_FILTER (gtk_string_filter_new (gtk_property_expression_new (GTK_TYPE_STRING_OBJECT, NULL, "string")));
      filter_model = gtk_filter_list_model_new (G_LIST_MODEL (stringlist), filter);
      gtk_filter_list_model_set_incremental (filter_model, TRUE);

      window = gtk_window_new ();
      gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);

      gtk_window_set_display (GTK_WINDOW (window),
                              gtk_widget_get_display (do_widget));
      g_object_add_weak_pointer (G_OBJECT (window), (gpointer*)&window);

      vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
      gtk_window_set_child (GTK_WINDOW (window), vbox);

      search_entry = gtk_search_entry_new ();
      g_object_bind_property (search_entry, "text", filter, "search", 0);
      gtk_box_append (GTK_BOX (vbox), search_entry);

      overlay = gtk_overlay_new ();
      gtk_box_append (GTK_BOX (vbox), overlay);

      progress = gtk_progress_bar_new ();
      gtk_widget_set_halign (progress, GTK_ALIGN_FILL);
      gtk_widget_set_valign (progress, GTK_ALIGN_START);
      gtk_widget_set_hexpand (progress, TRUE);
      gtk_overlay_add_overlay (GTK_OVERLAY (overlay), progress);

      sw = gtk_scrolled_window_new ();
      gtk_widget_set_vexpand (sw, TRUE);
      gtk_overlay_set_child (GTK_OVERLAY (overlay), sw);

      listview = gtk_list_view_new (
          GTK_SELECTION_MODEL (gtk_no_selection_new (G_LIST_MODEL (filter_model))),
          gtk_builder_list_item_factory_new_from_bytes (NULL,
              g_bytes_new_static (factory_text, strlen (factory_text))));
              
      gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), listview);

      g_signal_connect (filter_model, "items-changed", G_CALLBACK (update_title_cb), progress);
      g_signal_connect (filter_model, "notify::pending", G_CALLBACK (update_title_cb), progress);
      update_title_cb (filter_model);

    }

  if (!gtk_widget_get_visible (window))
    gtk_widget_show (window);
  else
    gtk_window_destroy (GTK_WINDOW (window));

  return window;
}


五、其它的 LIST MODEL

       在GTK4中还有一些列表模型实现不能很好地适合上述任何组,如GtkTreeListModel、GtkSelectionFilterModel或GtkShortcutController。今天我就不讲这些了。


在这里插入图片描述

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

从善若水

原创不易,感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值