[gnome-builder/wip/gtk4-port: 609/736] libide/gtk: add sorted helper for list store insertion
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/gtk4-port: 609/736] libide/gtk: add sorted helper for list store insertion
- Date: Tue, 26 Apr 2022 01:46:32 +0000 (UTC)
commit dbf2ba1f61b574394d42c409d56883fb40c66d57
Author: Christian Hergert <chergert redhat com>
Date: Mon Apr 18 07:10:58 2022 -0700
libide/gtk: add sorted helper for list store insertion
src/libide/gtk/ide-gtk.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++
src/libide/gtk/ide-gtk.h | 25 +++++---
2 files changed, 162 insertions(+), 9 deletions(-)
---
diff --git a/src/libide/gtk/ide-gtk.c b/src/libide/gtk/ide-gtk.c
index 34d68c73d..a83367693 100644
--- a/src/libide/gtk/ide-gtk.c
+++ b/src/libide/gtk/ide-gtk.c
@@ -227,3 +227,149 @@ ide_gtk_widget_hide_with_fade (GtkWidget *widget)
g_object_unref);
}
}
+
+static gboolean
+list_store_iter_middle (GtkListStore *store,
+ const GtkTreeIter *begin,
+ const GtkTreeIter *end,
+ GtkTreeIter *middle)
+{
+ g_assert (store != NULL);
+ g_assert (begin != NULL);
+ g_assert (end != NULL);
+ g_assert (middle != NULL);
+ g_assert (middle->stamp == begin->stamp);
+ g_assert (middle->stamp == end->stamp);
+
+ /*
+ * middle MUST ALREADY BE VALID as it saves us some copying
+ * as well as just makes things easier when binary searching.
+ */
+
+ middle->user_data = g_sequence_range_get_midpoint (begin->user_data, end->user_data);
+
+ if (g_sequence_iter_is_end (middle->user_data))
+ {
+ middle->stamp = 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static inline gboolean
+list_store_iter_equal (const GtkTreeIter *a,
+ const GtkTreeIter *b)
+{
+ return a->user_data == b->user_data;
+}
+
+/**
+ * ide_gtk_list_store_insert_sorted: (skip)
+ * @store: A #GtkListStore
+ * @iter: (out): A location for a #GtkTextIter
+ * @key: A key to compare to when binary searching
+ * @compare_column: the column containing the data to compare
+ * @compare_func: (scope call) (closure compare_data): A callback to compare
+ * @compare_data: data for @compare_func
+ *
+ * This function will binary search the contents of @store looking for the
+ * location to insert a new row.
+ *
+ * @compare_column must be the index of a column that is a %G_TYPE_POINTER,
+ * %G_TYPE_BOXED or %G_TYPE_OBJECT based column.
+ *
+ * @compare_func will be called with @key as the first parameter and the
+ * value from the #GtkListStore row as the second parameter. The third and
+ * final parameter is @compare_data.
+ */
+void
+ide_gtk_list_store_insert_sorted (GtkListStore *store,
+ GtkTreeIter *iter,
+ gconstpointer key,
+ guint compare_column,
+ GCompareDataFunc compare_func,
+ gpointer compare_data)
+{
+ GValue value = G_VALUE_INIT;
+ gpointer (*get_func) (const GValue *) = NULL;
+ GtkTreeModel *model = (GtkTreeModel *)store;
+ GtkTreeIter begin;
+ GtkTreeIter end;
+ GtkTreeIter middle;
+ guint n_children;
+ gint cmpval = 0;
+ GType type;
+
+ g_return_if_fail (GTK_IS_LIST_STORE (store));
+ g_return_if_fail (GTK_IS_LIST_STORE (model));
+ g_return_if_fail (iter != NULL);
+ g_return_if_fail (compare_column < gtk_tree_model_get_n_columns (GTK_TREE_MODEL (store)));
+ g_return_if_fail (compare_func != NULL);
+
+ type = gtk_tree_model_get_column_type (GTK_TREE_MODEL (store), compare_column);
+
+ if (g_type_is_a (type, G_TYPE_POINTER))
+ get_func = g_value_get_pointer;
+ else if (g_type_is_a (type, G_TYPE_BOXED))
+ get_func = g_value_get_boxed;
+ else if (g_type_is_a (type, G_TYPE_OBJECT))
+ get_func = g_value_get_object;
+ else
+ {
+ g_warning ("%s() only supports pointer, boxed, or object columns",
+ G_STRFUNC);
+ gtk_list_store_append (store, iter);
+ return;
+ }
+
+ /* Try to get the first iter instead of calling n_children to
+ * avoid walking the GSequence all the way to the right. If this
+ * matches, we know there are some children.
+ */
+ if (!gtk_tree_model_get_iter_first (model, &begin))
+ {
+ gtk_list_store_append (store, iter);
+ return;
+ }
+
+ n_children = gtk_tree_model_iter_n_children (model, NULL);
+ if (!gtk_tree_model_iter_nth_child (model, &end, NULL, n_children - 1))
+ g_assert_not_reached ();
+
+ middle = begin;
+
+ while (list_store_iter_middle (store, &begin, &end, &middle))
+ {
+ gtk_tree_model_get_value (model, &middle, compare_column, &value);
+ cmpval = compare_func (key, get_func (&value), compare_data);
+ g_value_unset (&value);
+
+ if (cmpval == 0 || list_store_iter_equal (&begin, &end))
+ break;
+
+ if (cmpval < 0)
+ {
+ end = middle;
+
+ if (!list_store_iter_equal (&begin, &end) &&
+ !gtk_tree_model_iter_previous (model, &end))
+ break;
+ }
+ else if (cmpval > 0)
+ {
+ begin = middle;
+
+ if (!list_store_iter_equal (&begin, &end) &&
+ !gtk_tree_model_iter_next (model, &begin))
+ break;
+ }
+ else
+ g_assert_not_reached ();
+ }
+
+ if (cmpval < 0)
+ gtk_list_store_insert_before (store, iter, &middle);
+ else
+ gtk_list_store_insert_after (store, iter, &middle);
+}
diff --git a/src/libide/gtk/ide-gtk.h b/src/libide/gtk/ide-gtk.h
index 2632d9845..843cda571 100644
--- a/src/libide/gtk/ide-gtk.h
+++ b/src/libide/gtk/ide-gtk.h
@@ -31,19 +31,26 @@
G_BEGIN_DECLS
IDE_AVAILABLE_IN_ALL
-gboolean ide_gtk_show_uri_on_window (GtkWindow *window,
- const char *uri,
- gint64 timestamp,
- GError **error);
+gboolean ide_gtk_show_uri_on_window (GtkWindow *window,
+ const char *uri,
+ gint64 timestamp,
+ GError **error);
IDE_AVAILABLE_IN_ALL
-void ide_gtk_window_present (GtkWindow *window);
+void ide_gtk_window_present (GtkWindow *window);
IDE_AVAILABLE_IN_ALL
-void ide_gtk_progress_bar_start_pulsing (GtkProgressBar *progress);
+void ide_gtk_progress_bar_start_pulsing (GtkProgressBar *progress);
IDE_AVAILABLE_IN_ALL
-void ide_gtk_progress_bar_stop_pulsing (GtkProgressBar *progress);
+void ide_gtk_progress_bar_stop_pulsing (GtkProgressBar *progress);
IDE_AVAILABLE_IN_ALL
-void ide_gtk_widget_show_with_fade (GtkWidget *widget);
+void ide_gtk_widget_show_with_fade (GtkWidget *widget);
IDE_AVAILABLE_IN_ALL
-void ide_gtk_widget_hide_with_fade (GtkWidget *widget);
+void ide_gtk_widget_hide_with_fade (GtkWidget *widget);
+IDE_AVAILABLE_IN_ALL
+void ide_gtk_list_store_insert_sorted (GtkListStore *store,
+ GtkTreeIter *iter,
+ gconstpointer key,
+ guint compare_column,
+ GCompareDataFunc compare_func,
+ gpointer compare_data);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]