GTK4 LIST MODEL 知多少?

Posted 从善若水

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GTK4 LIST MODEL 知多少?相关的知识,希望对你有一定的参考价值。

【GTK4】LIST MODEL总结

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


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

一、LIST MODEL创建、管理工具

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

1️⃣ GtkSliceListModel

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

2️⃣ GtkFlattenListModel

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

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 的例子

GtkGridView colors demo


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

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

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

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。今天我就不讲这些了。


以上是关于GTK4 LIST MODEL 知多少?的主要内容,如果未能解决你的问题,请参考以下文章

春眠不觉晓,Redis数据类型知多少?String,List,Set,SortedSet,Hash,Bitmap,HyperLogLogs

Carson带你学Java:泛型知识知多少

如何将 List<Model> 从 Activity 传递到 Fragment

Windows下安装并使用 GTK4

Windows下安装并使用 GTK4

xubuntu 21.10 g++ gtk4“错误:‘gtk_container_add’未在此范围内声明”