diff options
-rw-r--r-- | src/meson.build | 7 | ||||
-rw-r--r-- | src/option.c | 15 | ||||
-rw-r--r-- | src/tree.c | 716 | ||||
-rw-r--r-- | src/util.c | 4 | ||||
-rw-r--r-- | src/util.h | 2 | ||||
-rw-r--r-- | src/zenity-tree-column-view.c | 478 | ||||
-rw-r--r-- | src/zenity-tree-column-view.h | 54 | ||||
-rw-r--r-- | src/zenity-tree-column-view.ui | 21 | ||||
-rw-r--r-- | src/zenity.gresource.xml.in | 1 | ||||
-rw-r--r-- | src/zenity.h | 4 | ||||
-rw-r--r-- | src/zenity.ui | 16 |
11 files changed, 767 insertions, 551 deletions
diff --git a/src/meson.build b/src/meson.build index 2ee1889..e2395ca 100644 --- a/src/meson.build +++ b/src/meson.build @@ -16,10 +16,11 @@ zenity_sources = [ 'text.c', 'tree.c', 'util.c', + 'zenity-tree-column-view.c', ] -zenity_enums = gnome.mkenums_simple('zenity-enums', - sources: 'zenity.h', +zenity_cv_enums = gnome.mkenums_simple('zenity-tree-column-view-enums', + sources: 'zenity-tree-column-view.h', ) zenity_res_conf = configuration_data() @@ -43,7 +44,7 @@ zenity_c_args = [ zenity = executable( meson.project_name(), - zenity_sources + zenity_enums + zenity_res, + zenity_sources + zenity_cv_enums + zenity_res, include_directories: zenity_root_dir, c_args: zenity_c_args, dependencies: [adw_dep, webkitgtk_dep], diff --git a/src/option.c b/src/option.c index ee58af1..d638839 100644 --- a/src/option.c +++ b/src/option.c @@ -85,7 +85,6 @@ static char *zenity_list_print_column; static char *zenity_list_hide_column; static gboolean zenity_list_hide_header; static gboolean zenity_list_imagelist; -static gboolean zenity_list_mid_search; /* Notification Dialog Options */ static gboolean zenity_notification_active; @@ -153,6 +152,7 @@ static gboolean zenity_misc_version; /* DEPRECATED Options */ static char *zenity_general_icon_DEPRECATED; +static gboolean zenity_list_mid_search_DEPRECATED; static gboolean zenity_forms_callback (const char *option_name, const char *value, gpointer data, GError **error); @@ -547,9 +547,8 @@ static GOptionEntry list_options[] = '\0', G_OPTION_FLAG_NOALIAS, G_OPTION_ARG_NONE, - &zenity_list_mid_search, - N_ ("Change list default search function searching for text in the " - "middle, not on the beginning"), + &zenity_list_mid_search_DEPRECATED, + N_ ("DEPRECATED; does nothing"), NULL}, {NULL}}; @@ -1239,7 +1238,7 @@ zenity_list_pre_callback (GOptionContext *context, GOptionGroup *group, zenity_list_hide_header = FALSE; zenity_list_print_column = NULL; zenity_list_hide_column = NULL; - zenity_list_mid_search = FALSE; + zenity_list_mid_search_DEPRECATED = FALSE; return TRUE; } @@ -1602,7 +1601,7 @@ zenity_list_post_callback (GOptionContext *context, GOptionGroup *group, results->tree_data->hide_column = zenity_list_hide_column; results->tree_data->hide_header = zenity_list_hide_header; results->tree_data->separator = zenity_general_separator; - results->tree_data->mid_search = zenity_list_mid_search; + results->tree_data->mid_search_DEPRECATED = zenity_list_mid_search_DEPRECATED; } else { @@ -1640,9 +1639,9 @@ zenity_list_post_callback (GOptionContext *context, GOptionGroup *group, zenity_option_error ( zenity_option_get_name (list_options, &zenity_list_hide_header), ERROR_SUPPORT); - if (zenity_list_mid_search) + if (zenity_list_mid_search_DEPRECATED) zenity_option_error ( - zenity_option_get_name (list_options, &zenity_list_mid_search), + zenity_option_get_name (list_options, &zenity_list_mid_search_DEPRECATED), ERROR_SUPPORT); } return TRUE; @@ -29,6 +29,7 @@ #include "util.h" #include "zenity.h" +#include "zenity-tree-column-view.h" #include <stdlib.h> #include <string.h> @@ -37,7 +38,8 @@ #define PRINT_HIDE_COLUMN_SEPARATOR "," -static GtkTreeView *tree_view; +static ZenityTreeColumnView *col_view; +static gboolean editable; static GSList *selected; static char *separator; static gboolean print_all_columns = FALSE; @@ -46,134 +48,53 @@ static int *hide_columns = NULL; static GIOChannel *channel; static int *zenity_tree_extract_column_indexes (char *indexes, int n_columns); -static gboolean zenity_tree_column_is_hidden (int column_index); static void zenity_tree_dialog_response (GtkWidget *widget, char *rstr, gpointer data); -static void zenity_tree_row_activated (GtkTreeView *tree_view, - GtkTreePath *tree_path, GtkTreeViewColumn *tree_col, gpointer data); - -static gboolean -zenity_tree_dialog_untoggle (GtkTreeModel *model, GtkTreePath *path, - GtkTreeIter *iter, gpointer data) -{ - GValue toggle_value = G_VALUE_INIT; - - gtk_tree_model_get_value (model, iter, 0, &toggle_value); - - if (g_value_get_boolean (&toggle_value)) - gtk_list_store_set (GTK_LIST_STORE (model), iter, 0, FALSE, -1); - - return FALSE; -} - -static void -check_or_radio_label_activated_cb (GtkTreeView *tree_view, - GtkTreePath *path, - GtkTreeViewColumn *column, - gpointer user_data) -{ - GtkTreeModel *model = gtk_tree_view_get_model (tree_view); - GtkTreeIter iter; - gboolean value; - - /* Because this is a radio list, we should untoggle the previous toggle so - * that we only have one selection at any given time - */ - if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (model), "radio")) == 1) - { - gtk_tree_model_foreach (model, zenity_tree_dialog_untoggle, NULL); - } - - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, 0, &value, -1); - - value = !value; - gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, value, -1); -} +static void zenity_tree_dialog_output (void); static void -zenity_load_pixbuf (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, - GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) +show_mid_search_deprecation_warning (void) { - static GHashTable *pixbuf_cache = NULL; - GError *error = NULL; - GdkPixbuf *pixbuf; - g_autofree char *str = NULL; - - gtk_tree_model_get (tree_model, iter, 0, &str, -1); - - if (! str) - return; - - if (! pixbuf_cache) - { - pixbuf_cache = g_hash_table_new (g_str_hash, g_str_equal); - g_assert (pixbuf_cache); - } - - pixbuf = g_hash_table_lookup (pixbuf_cache, str); - - if (! pixbuf) - { - pixbuf = gdk_pixbuf_new_from_file (str, &error); - - if (! pixbuf) - g_warning ("Failed to load '%s'", str); - - g_hash_table_insert (pixbuf_cache, g_strdup (str), pixbuf); - } - - if (pixbuf) - g_object_set (cell, "pixbuf", pixbuf, NULL); + g_printerr ("Warning: --mid-search is deprecated and will be removed in a " + "future version of zenity. Ignoring.\n"); } - static gboolean -zenity_tree_handle_stdin (GIOChannel *channel, GIOCondition condition, - gpointer data) +zenity_tree_handle_stdin (GIOChannel *channel, GIOCondition condition, gpointer data) { - GtkTreeModel *model; - static GtkTreeIter iter; static int column_count = 0; static int row_count = 0; - static int n_columns; - static gboolean editable; - static gboolean toggles; static gboolean first_time = TRUE; GIOStatus status = G_IO_STATUS_NORMAL; - - /* Make sure global is properly defined */ - g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE); - - n_columns = - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_view), "n_columns")); - editable = - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_view), "editable")); - toggles = - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_view), "toggles")); - - model = gtk_tree_view_get_model (tree_view); + int n_columns = zenity_tree_column_view_get_n_columns (col_view); + gboolean toggles = FALSE; + ZenityTreeListType list_type = zenity_tree_column_view_get_list_type (col_view); + GListStore *store = G_LIST_STORE(zenity_tree_column_view_get_model (col_view)); if (first_time) - { first_time = FALSE; - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - } + + if (list_type == ZENITY_TREE_LIST_RADIO || list_type == ZENITY_TREE_LIST_CHECK) + toggles = TRUE; if ((condition & G_IO_IN) == G_IO_IN) { - g_autoptr(GString) string = NULL; + ZenityTreeRow *row = NULL; + g_autoptr(GString) gstring = g_string_new (NULL); g_autoptr(GError) error = NULL; - string = g_string_new (NULL); - while ((g_io_channel_get_flags (channel) & G_IO_FLAG_IS_READABLE) != G_IO_FLAG_IS_READABLE) ; + + row = zenity_tree_row_new (); do { + ZenityTreeItem *item; + do { if (g_io_channel_get_flags (channel) & G_IO_FLAG_IS_READABLE) { - status = g_io_channel_read_line_string (channel, - string, NULL, &error); - } else { + status = g_io_channel_read_line_string (channel, gstring, NULL, &error); + g_strchomp (gstring->str); + } + else { return FALSE; } @@ -188,9 +109,8 @@ zenity_tree_handle_stdin (GIOChannel *channel, GIOCondition condition, if (status != G_IO_STATUS_NORMAL) { if (error) { - g_warning ("%s: %s", - __func__, error->message); - error = NULL; + g_warning ("%s: %s", __func__, error->message); + g_clear_error (&error); } continue; } @@ -200,42 +120,32 @@ zenity_tree_handle_stdin (GIOChannel *channel, GIOCondition condition, /* We're starting a new row */ column_count = 0; row_count++; - gtk_list_store_append (GTK_LIST_STORE (model), &iter); } if (toggles && column_count == 0) { - if (strcmp (g_ascii_strdown ( - zenity_util_strip_newline (string->str), -1), - "true") == 0) - { - gtk_list_store_set (GTK_LIST_STORE(model), - &iter, column_count, TRUE, -1); - } - else { - gtk_list_store_set ( - GTK_LIST_STORE (model), &iter, column_count, FALSE, -1); - } + item = zenity_tree_item_new (gstring->str, gtk_check_button_new ()); } - else + else if (list_type == ZENITY_TREE_LIST_IMAGE && column_count == 0) { - gtk_list_store_set (GTK_LIST_STORE (model), - &iter, - column_count, - zenity_util_strip_newline (string->str), - -1); + item = zenity_tree_item_new (gstring->str, gtk_image_new ()); } - - if (editable) { - gtk_list_store_set (GTK_LIST_STORE(model), - &iter, n_columns, TRUE, -1); + else + { + if (editable) + item = zenity_tree_item_new (gstring->str, gtk_editable_label_new (NULL)); + else + item = zenity_tree_item_new (gstring->str, gtk_label_new (NULL)); } + zenity_tree_row_add (row, item); column_count++; - } while ((g_io_channel_get_buffer_condition (channel) & G_IO_IN) == - G_IO_IN && + } while ((g_io_channel_get_buffer_condition (channel) & G_IO_IN) == G_IO_IN && status != G_IO_STATUS_EOF); /* !do while */ + + if (row) + g_list_store_append (store, row); } if ((condition & G_IO_IN) != G_IO_IN || status == G_IO_STATUS_EOF) @@ -247,100 +157,67 @@ zenity_tree_handle_stdin (GIOChannel *channel, GIOCondition condition, } static void -zenity_tree_fill_entries_from_stdin (GtkTreeView *loc_tv, int n_columns, - gboolean toggles, gboolean editable) +zenity_tree_fill_entries_from_stdin (void) { - /* No reason this should fail. Sanity check. */ - g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); - g_assert (loc_tv == tree_view); - - g_object_set_data ( - G_OBJECT (tree_view), "n_columns", GINT_TO_POINTER (n_columns)); - g_object_set_data ( - G_OBJECT (tree_view), "toggles", GINT_TO_POINTER (toggles)); - g_object_set_data ( - G_OBJECT (tree_view), "editable", GINT_TO_POINTER (editable)); - channel = g_io_channel_unix_new (0); g_io_channel_set_encoding (channel, NULL, NULL); g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL); - g_io_add_watch (channel, - G_IO_IN | G_IO_HUP, zenity_tree_handle_stdin, NULL); + g_io_add_watch (channel, G_IO_IN | G_IO_HUP, zenity_tree_handle_stdin, NULL); } static void -zenity_tree_fill_entries (GtkTreeView *loc_tv, const char **args, - int n_columns, gboolean toggles, gboolean editable) +zenity_tree_fill_entries (const char **args) { - GtkTreeModel *model; - GtkTreeIter iter; - int i = 0; - - /* No reason this should fail. Sanity check. */ - g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); - g_assert (loc_tv == tree_view); - - model = gtk_tree_view_get_model (tree_view); - - g_object_set_data ( - G_OBJECT (tree_view), "n_columns", GINT_TO_POINTER (n_columns)); + int n_columns = zenity_tree_column_view_get_n_columns (col_view); + ZenityTreeListType list_type = zenity_tree_column_view_get_list_type (col_view); + GListStore *store = G_LIST_STORE(zenity_tree_column_view_get_model (col_view)); + gboolean toggles = FALSE; - while (args[i] != NULL) { - int j; + if (list_type == ZENITY_TREE_LIST_RADIO || list_type == ZENITY_TREE_LIST_CHECK) + toggles = TRUE; - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - - for (j = 0; j < n_columns; j++) { + for (int i = 0; args[i]; i+= n_columns) + { + ZenityTreeRow *row = zenity_tree_row_new (); - if (toggles && j == 0) { - if (strcmp (g_ascii_strdown ((gchar *) args[i + j], -1), - "true") == 0) - gtk_list_store_set ( - GTK_LIST_STORE (model), &iter, j, TRUE, -1); + for (int j = 0; j < n_columns; j++) + { + ZenityTreeItem *item; + const char *str = args[i + j]; + + if (toggles && j == 0) + { + item = zenity_tree_item_new (str, gtk_check_button_new ()); + } + else if (list_type == ZENITY_TREE_LIST_IMAGE && j == 0) + { + item = zenity_tree_item_new (str, gtk_image_new ()); + } + else + { + if (editable) + item = zenity_tree_item_new (str, gtk_editable_label_new ("")); else - gtk_list_store_set ( - GTK_LIST_STORE (model), &iter, j, FALSE, -1); - } else - gtk_list_store_set ( - GTK_LIST_STORE (model), &iter, j, args[i + j], -1); - } - - if (editable) { - gtk_list_store_set (GTK_LIST_STORE(model), - &iter, n_columns, TRUE, -1); + item = zenity_tree_item_new (str, gtk_label_new (NULL)); + } + zenity_tree_row_add (row, item); } - i += n_columns; + g_list_store_append (store, row); } } -static gboolean -zenity_mid_search_func (GtkTreeModel *model, int column, const char *key, - GtkTreeIter *iter, gpointer search_data) -{ - char *iter_string = NULL; - - gtk_tree_model_get (model, iter, column, &iter_string, -1); - - return !(g_strrstr (g_utf8_strdown (iter_string, -1), - g_utf8_strdown (key, -1)) != NULL); -} - static void -zenity_cell_edited_callback (GtkCellRendererText *cell, - const char *path_string, const char *new_text, gpointer data) +cv_activated_cb (ZenityTreeColumnView *cv, gpointer data) { - GtkTreeModel *model; - g_autoptr(GtkTreePath) path = NULL; - GtkTreeIter iter; - int column; + GtkWindow *parent; + ZenityData *zen_data = data; - model = GTK_TREE_MODEL (data); - path = gtk_tree_path_new_from_string (path_string); + zenity_tree_dialog_output (); + zen_data->exit_code = zenity_util_return_exit_code (ZENITY_OK); - column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column")); - gtk_tree_model_get_iter (model, &iter, path); + parent = GTK_WINDOW(gtk_widget_get_native (GTK_WIDGET(col_view))); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, column, new_text, -1); + zenity_util_gapp_quit (parent, zen_data); } void @@ -349,12 +226,13 @@ zenity_tree (ZenityData *data, ZenityTreeData *tree_data) g_autoptr(GtkBuilder) builder = NULL; GtkWidget *dialog; GObject *text; - GtkTreeViewColumn *column; - GtkListStore *model; - GType *column_types; + GListStore *store; + ZenityTreeListType list_type; GSList *tmp; - gboolean first_column = FALSE; - int i, column_index, n_columns; + int n_columns; + + if (tree_data->mid_search_DEPRECATED) + show_mid_search_deprecation_warning (); builder = zenity_util_load_ui_file ("zenity_tree_dialog", "zenity_tree_box", NULL); @@ -401,8 +279,7 @@ zenity_tree (ZenityData *data, ZenityTreeData *tree_data) return; } - dialog = GTK_WIDGET(gtk_builder_get_object (builder, - "zenity_tree_dialog")); + dialog = GTK_WIDGET(gtk_builder_get_object (builder, "zenity_tree_dialog")); g_signal_connect (dialog, "response", G_CALLBACK(zenity_tree_dialog_response), data); @@ -439,243 +316,55 @@ zenity_tree (ZenityData *data, ZenityTreeData *tree_data) data->width, data->height); } - /* Define global tree_view. */ - tree_view = GTK_TREE_VIEW(gtk_builder_get_object (builder, - "zenity_tree_view")); + /* Create a list store */ + store = g_list_store_new (ZENITY_TREE_TYPE_ROW); - if (tree_data->radiobox || tree_data->checkbox) - { - gtk_tree_view_set_activate_on_single_click (GTK_TREE_VIEW(tree_view), - TRUE); + /* Define global col_view */ + col_view = ZENITY_TREE_COLUMN_VIEW(gtk_builder_get_object (builder, "zenity_tree_cv")); - g_signal_connect (tree_view, - "row-activated", - G_CALLBACK (check_or_radio_label_activated_cb), - data); - } - else - { - g_signal_connect (tree_view, - "row-activated", - G_CALLBACK (zenity_tree_row_activated), - data); - } - - /* Create an empty list store */ - model = g_object_new (GTK_TYPE_LIST_STORE, NULL); - - if (tree_data->editable) - column_types = g_new (GType, n_columns + 1); - else - column_types = g_new (GType, n_columns); + /* This signal will only get emitted for certain kinds of lists, but if + * applicable, it should finish the job. + */ + g_signal_connect (col_view, "activated", G_CALLBACK(cv_activated_cb), data); - for (i = 0; i < n_columns; i++) - { - /* Have the limitation that the radioboxes and checkboxes are in the - * first column */ - if (i == 0 && (tree_data->checkbox || tree_data->radiobox)) - column_types[i] = G_TYPE_BOOLEAN; - else - column_types[i] = G_TYPE_STRING; + if (tree_data->radiobox) { + list_type = ZENITY_TREE_LIST_RADIO; } - - if (tree_data->editable) - column_types[n_columns] = G_TYPE_BOOLEAN; - - if (tree_data->editable) - gtk_list_store_set_column_types (model, n_columns + 1, column_types); - else - gtk_list_store_set_column_types (model, n_columns, column_types); - - gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL(model)); - - if (tree_data->radiobox || tree_data->checkbox) - { - gtk_tree_selection_set_mode ( - gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)), - GTK_SELECTION_SINGLE); + else if (tree_data->checkbox) { + list_type = ZENITY_TREE_LIST_CHECK; } - else - { - if (tree_data->multi) - gtk_tree_selection_set_mode ( - gtk_tree_view_get_selection (tree_view), - GTK_SELECTION_MULTIPLE); - else - gtk_tree_selection_set_mode ( - gtk_tree_view_get_selection (tree_view), - GTK_SELECTION_SINGLE); + else if (tree_data->imagebox) { + list_type = ZENITY_TREE_LIST_IMAGE; + } + else { + list_type = ZENITY_TREE_LIST_NONE; } - column_index = 0; + editable = tree_data->editable; + g_object_set (col_view, + "list-type", list_type, + "multi", tree_data->multi, + "model", G_LIST_MODEL(store), + NULL); for (tmp = tree_data->columns; tmp; tmp = tmp->next) { - if (! first_column) - { - if (tree_data->checkbox || tree_data->radiobox) - { - GtkCellRenderer *cell_renderer; - - cell_renderer = gtk_cell_renderer_toggle_new (); - - if (tree_data->radiobox) { - g_object_set ( - G_OBJECT (cell_renderer), "radio", TRUE, NULL); - g_object_set_data ( - G_OBJECT (model), "radio", GINT_TO_POINTER (1)); - } - - column = gtk_tree_view_column_new_with_attributes ( - tmp->data, cell_renderer, "active", column_index, NULL); - } - else if (tree_data->imagebox) - { - GtkCellRenderer *cell_renderer = - gtk_cell_renderer_pixbuf_new (); - - column = gtk_tree_view_column_new_with_attributes ( - tmp->data, cell_renderer, NULL); - gtk_tree_view_column_set_cell_data_func ( - column, cell_renderer, zenity_load_pixbuf, NULL, NULL); - } - else - { - if (tree_data->editable) - { - GtkCellRenderer *cell_renderer; - - cell_renderer = gtk_cell_renderer_text_new (); - g_signal_connect (cell_renderer, "edited", - G_CALLBACK (zenity_cell_edited_callback), - gtk_tree_view_get_model (tree_view)); - - g_object_set_data (G_OBJECT (cell_renderer), - "column", - GINT_TO_POINTER (column_index)); - - column = - gtk_tree_view_column_new_with_attributes (tmp->data, - cell_renderer, - "text", - column_index, - "editable", - n_columns, - NULL); - } - else - { - column = - gtk_tree_view_column_new_with_attributes (tmp->data, - gtk_cell_renderer_text_new (), - "text", - column_index, - NULL); - } - - gtk_tree_view_column_set_sort_column_id (column, column_index); - gtk_tree_view_column_set_resizable (column, TRUE); - } - if (zenity_tree_column_is_hidden (1)) - gtk_tree_view_column_set_visible (column, FALSE); - - first_column = TRUE; - } - else - { - if (tree_data->editable) - { - GtkCellRenderer *cell_renderer; - - cell_renderer = gtk_cell_renderer_text_new (); - g_signal_connect (cell_renderer, "edited", - G_CALLBACK (zenity_cell_edited_callback), - gtk_tree_view_get_model (tree_view)); - - g_object_set_data (G_OBJECT (cell_renderer), - "column", - GINT_TO_POINTER (column_index)); - - column = gtk_tree_view_column_new_with_attributes (tmp->data, - cell_renderer, - "text", - column_index, - "editable", - n_columns, - NULL); - } - else - { - column = gtk_tree_view_column_new_with_attributes (tmp->data, - gtk_cell_renderer_text_new (), - "text", - column_index, - NULL); - } - - gtk_tree_view_column_set_sort_column_id (column, column_index); - gtk_tree_view_column_set_resizable (column, TRUE); - - if (zenity_tree_column_is_hidden (column_index + 1)) - gtk_tree_view_column_set_visible (column, FALSE); - } - - gtk_tree_view_append_column (tree_view, column); - column_index++; + zenity_tree_column_view_add_column (col_view, tmp->data); } - if (tree_data->hide_header) - gtk_tree_view_set_headers_visible (tree_view, FALSE); - - if (tree_data->radiobox || tree_data->checkbox) + if (tree_data->data && *tree_data->data) /* we have argv after opts */ { - if (tree_data->data && *tree_data->data) { - zenity_tree_fill_entries (tree_view, - tree_data->data, - n_columns, - TRUE, - tree_data->editable); - } - else { - zenity_tree_fill_entries_from_stdin (tree_view, - n_columns, - TRUE, - tree_data->editable); - } + zenity_tree_fill_entries (tree_data->data); } else { - if (tree_data->data && *tree_data->data) { - zenity_tree_fill_entries (tree_view, - tree_data->data, - n_columns, - FALSE, - tree_data->editable); - } else { - zenity_tree_fill_entries_from_stdin (tree_view, - n_columns, - FALSE, - tree_data->editable); - } + zenity_tree_fill_entries_from_stdin (); } - /* GTK will automatically pick the image column as the search column - * despite it not containing any user readable text. - * Set it to second column instead if it exists. */ - if (tree_data->imagebox && n_columns > 1) { - gtk_tree_view_set_search_column (GTK_TREE_VIEW (tree_view), - 1); - } + // FIXME - make stuff searchable zenity_util_show_dialog (dialog); - if (tree_data->mid_search) { - gtk_tree_view_set_search_equal_func (tree_view, - (GtkTreeViewSearchEqualFunc) zenity_mid_search_func, - model, - NULL); - } - if (data->timeout_delay > 0) { g_timeout_add_seconds (data->timeout_delay, (GSourceFunc) zenity_util_timeout_handle, @@ -685,103 +374,115 @@ zenity_tree (ZenityData *data, ZenityTreeData *tree_data) zenity_util_gapp_main (GTK_WINDOW(dialog)); } -static void -zenity_tree_dialog_get_selected (GtkTreeModel *model, GtkTreePath *path_buf, - GtkTreeIter *iter, gpointer user_data) +static gboolean +get_row_checkbtn_toggled (ZenityTreeRow *row) { - GValue value = G_VALUE_INIT; - int n_columns, i; + ZenityTreeItem *item = zenity_tree_row_get_item (row, 0); + GtkWidget *child = zenity_tree_item_get_child (item); - n_columns = - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_view), "n_columns")); - - if (print_all_columns) + if (GTK_IS_CHECK_BUTTON (child)) { - for (i = 0; i < n_columns; i++) - { - gtk_tree_model_get_value (model, iter, i, &value); - - selected = g_slist_append (selected, g_value_dup_string (&value)); - g_value_unset (&value); - } - return; + return gtk_check_button_get_active (GTK_CHECK_BUTTON(child)); } - for (i = 0; print_columns[i] != 0; i++) - { - gtk_tree_model_get_value (model, iter, print_columns[i] - 1, &value); - selected = g_slist_append (selected, g_value_dup_string (&value)); - - g_value_unset (&value); - } + return FALSE; } -static gboolean -zenity_tree_dialog_toggle_get_selected (GtkTreeModel *model, GtkTreePath *path, - GtkTreeIter *iter, gpointer user_data) +static void +zenity_tree_dialog_get_selected (void) { - GValue toggle_value = G_VALUE_INIT; - int n_columns, i; + int n_columns = zenity_tree_column_view_get_n_columns (col_view); + GListModel *model = zenity_tree_column_view_get_model (col_view); + ZenityTreeItem *item; - n_columns = - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tree_view), "n_columns")); + for (guint i = 0; i < g_list_model_get_n_items (model); ++i) + { + ZenityTreeRow *row; - gtk_tree_model_get_value (model, iter, 0, &toggle_value); + if (! zenity_tree_column_view_is_selected (col_view, i)) + continue; - if (g_value_get_boolean (&toggle_value)) - { - GValue value = G_VALUE_INIT; + row = g_list_model_get_item (model, i); if (print_all_columns) { - for (i = 1; i < n_columns; i++) + for (int j = 0; j < n_columns; j++) { - gtk_tree_model_get_value (model, iter, i, &value); + item = zenity_tree_row_get_item (row, j); - selected = - g_slist_append (selected, g_value_dup_string (&value)); - g_value_unset (&value); + selected = g_slist_append (selected, + g_strdup (zenity_tree_item_get_text (item))); } - g_value_unset (&toggle_value); - return FALSE; } - - for (i = 0; print_columns[i] != 0; i++) + else { - gtk_tree_model_get_value ( - model, iter, print_columns[i] - 1, &value); + for (int j = 0; print_columns[j] != 0; j++) + { + /* columns in CLI count from 1 and are allocated as 0-terminated + * arrays, so account for that here with -1. */ + item = zenity_tree_row_get_item (row, print_columns[j] - 1); - selected = g_slist_append (selected, g_value_dup_string (&value)); - g_value_unset (&value); + selected = g_slist_append (selected, + g_strdup (zenity_tree_item_get_text (item))); + } } } - g_value_unset (&toggle_value); - - return FALSE; } static void -zenity_tree_dialog_output (void) +zenity_tree_dialog_toggle_get_selected (ZenityTreeRow *row, gpointer unused) { - GtkTreeSelection *selection; - GtkTreeModel *model; + int n_columns; + ZenityTreeItem *item; - g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); + if (! get_row_checkbtn_toggled (row)) + return; - model = gtk_tree_view_get_model (tree_view); + n_columns = zenity_tree_column_view_get_n_columns (col_view); - if (gtk_tree_model_get_column_type (model, 0) == G_TYPE_BOOLEAN) + if (print_all_columns) { - gtk_tree_model_foreach (model, - (GtkTreeModelForeachFunc) zenity_tree_dialog_toggle_get_selected, - NULL); + /* start at 1 because we're not printing the checklist column string + */ + for (int i = 1; i < n_columns; i++) + { + item = zenity_tree_row_get_item (row, i); + + selected = g_slist_append (selected, + g_strdup (zenity_tree_item_get_text (item))); + } } else { - selection = gtk_tree_view_get_selection (tree_view); - gtk_tree_selection_selected_foreach (selection, - (GtkTreeSelectionForeachFunc) zenity_tree_dialog_get_selected, - NULL); + for (int i = 0; print_columns[i] != 0; i++) + { + /* columns in CLI count from 1 and are allocated as 0-terminated + * arrays, so account for that here with -1. */ + item = zenity_tree_row_get_item (row, print_columns[i] - 1); + + selected = g_slist_append (selected, + g_strdup (zenity_tree_item_get_text (item))); + } + } +} + +static void +zenity_tree_dialog_output (void) +{ + gboolean multi = zenity_tree_column_view_get_multi (col_view); + ZenityTreeListType list_type = zenity_tree_column_view_get_list_type (col_view); + + if (list_type == ZENITY_TREE_LIST_RADIO || list_type == ZENITY_TREE_LIST_CHECK) + { + zenity_tree_column_view_foreach_row (col_view, + (GFunc)zenity_tree_dialog_toggle_get_selected, NULL); + } + else if (multi) + { + } + else + { + zenity_tree_dialog_get_selected (); } @@ -840,39 +541,6 @@ zenity_tree_dialog_response (GtkWidget *widget, char *rstr, gpointer data) zenity_util_gapp_quit (GTK_WINDOW(widget), zen_data); } -static void -zenity_tree_row_activated (GtkTreeView *loc_tv, GtkTreePath *tree_path, - GtkTreeViewColumn *tree_col, gpointer data) -{ - GtkWindow *parent; - ZenityData *zen_data = data; - - /* No reason this should fail. Sanity check. */ - g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); - g_assert (loc_tv == tree_view); - - zenity_tree_dialog_output (); - zen_data->exit_code = zenity_util_return_exit_code (ZENITY_OK); - - parent = GTK_WINDOW(gtk_widget_get_native (GTK_WIDGET(tree_view))); - - zenity_util_gapp_quit (parent, zen_data); -} - -static gboolean -zenity_tree_column_is_hidden (int column_index) -{ - if (hide_columns != NULL) - { - for (int i = 0; hide_columns[i] != 0; i++) - { - if (hide_columns[i] == column_index) - return TRUE; - } - } - return FALSE; -} - static int * zenity_tree_extract_column_indexes (char *indexes, int n_columns) { @@ -105,6 +105,10 @@ zenity_util_load_ui_file (const char *root_widget, ...) g_ptr_array_add (ptrarray, NULL); objects = (char **)g_ptr_array_free (ptrarray, FALSE); + /* Make sure this custom widget type is registered before this initial + * GtkBuilder method call. */ + g_type_ensure (ZENITY_TREE_TYPE_COLUMN_VIEW); + result = gtk_builder_add_objects_from_resource (builder, ZENITY_UI_RESOURCE_PATH, (const char **)objects, @@ -36,6 +36,8 @@ #pragma once #include "zenity.h" +#include "zenity-tree-column-view.h" + #include <gtk/gtk.h> G_BEGIN_DECLS diff --git a/src/zenity-tree-column-view.c b/src/zenity-tree-column-view.c new file mode 100644 index 0000000..2e12122 --- /dev/null +++ b/src/zenity-tree-column-view.c @@ -0,0 +1,478 @@ +#include "zenity-tree-column-view.h" +#include <config.h> + +#define UI_FILE RESOURCE_BASE_PATH "/zenity-tree-column-view.ui" + +struct _ZenityTreeItem +{ + GObject parent_instance; + GtkWidget *child; + char *text; +}; + +G_DEFINE_TYPE (ZenityTreeItem, zenity_tree_item, G_TYPE_OBJECT) + +static void +zenity_tree_item_init (ZenityTreeItem *item) +{ +} + +static void +zenity_tree_item_class_init (ZenityTreeItemClass *klass) +{ +} + +GtkWidget * +zenity_tree_item_get_child (ZenityTreeItem *item) +{ + return item->child; +} + +const char * +zenity_tree_item_get_text (ZenityTreeItem *item) +{ + return item->text; +} + +void +zenity_tree_item_set_text (ZenityTreeItem *item, const char *text) +{ + g_clear_pointer (&item->text, g_free); + item->text = g_strdup (text); +} + +ZenityTreeItem * +zenity_tree_item_new (const char *text, GtkWidget *child) +{ + ZenityTreeItem *item; + + g_return_val_if_fail (GTK_IS_WIDGET (child), NULL); + + item = g_object_new (ZENITY_TREE_TYPE_ITEM, NULL); + + item->child = child; + zenity_tree_item_set_text (item, text); + + return item; +} + +/* --- */ + +struct _ZenityTreeRow +{ + GObject parent_instance; + GPtrArray *items; +}; + +G_DEFINE_TYPE (ZenityTreeRow, zenity_tree_row, G_TYPE_OBJECT) + +static void +zenity_tree_row_init (ZenityTreeRow *self) +{ + self->items = g_ptr_array_new (); +} + +static void +zenity_tree_row_class_init (ZenityTreeRowClass *klass) +{ +} + +ZenityTreeRow * +zenity_tree_row_new (void) +{ + return g_object_new (ZENITY_TREE_TYPE_ROW, NULL); +} + +void +zenity_tree_row_add (ZenityTreeRow *row, ZenityTreeItem *item) +{ + g_ptr_array_add (row->items, item); +} + +guint +zenity_tree_row_get_n_items (ZenityTreeRow *row) +{ + return row->items->len; +} + +ZenityTreeItem * +zenity_tree_row_get_item (ZenityTreeRow *row, guint index) +{ + g_return_val_if_fail (index < row->items->len, NULL); + + return row->items->pdata[index]; +} + +/* --- */ + +enum zenity_tree_column_view_signal_enum { + ACTIVATED, + LAST_SIGNAL +}; + +static guint zenity_tree_column_view_signals[LAST_SIGNAL]; + +/* --- */ + +enum zenity_tree_column_view_props +{ + MULTI = 1, + LIST_TYPE, + MODEL, + N_PROPERTIES_ZENITY_TREE_COLUMN_VIEW +}; + +static GParamSpec *zenity_tree_column_view_properties[N_PROPERTIES_ZENITY_TREE_COLUMN_VIEW]; + +struct _ZenityTreeColumnView +{ + GtkWidget parent_instance; + GtkWidget *scrolled_window; + GtkColumnView *child_cv; + gboolean multi; + ZenityTreeListType list_type; + GListModel *model; + GtkCheckButton *checkbutton_group; +}; + +G_DEFINE_TYPE (ZenityTreeColumnView, zenity_tree_column_view, GTK_TYPE_WIDGET) + +void +zenity_tree_column_view_set_model (ZenityTreeColumnView *self, GListModel *model) +{ + self->model = model; + + if (self->multi) + { + gtk_column_view_set_model (self->child_cv, + GTK_SELECTION_MODEL(gtk_multi_selection_new (self->model))); + } + else + { + gtk_column_view_set_model (self->child_cv, + GTK_SELECTION_MODEL(gtk_single_selection_new (self->model))); + } + + g_object_notify_by_pspec (G_OBJECT(self), zenity_tree_column_view_properties[MODEL]); +} + +GListModel * +zenity_tree_column_view_get_model (ZenityTreeColumnView *self) +{ + return self->model; +} + +static void +zenity_tree_column_view_emit_activated (ZenityTreeColumnView *self) +{ + g_signal_emit (self, zenity_tree_column_view_signals[ACTIVATED], 0); +} + +void +zenity_tree_column_view_set_list_type (ZenityTreeColumnView *self, ZenityTreeListType type) +{ + self->list_type = type; + + g_signal_handlers_disconnect_by_func (self->child_cv, zenity_tree_column_view_emit_activated, self); + + switch (self->list_type) + { + case ZENITY_TREE_LIST_NONE: + case ZENITY_TREE_LIST_IMAGE: + g_signal_connect_swapped (self->child_cv, "activate", G_CALLBACK(zenity_tree_column_view_emit_activated), self); + break; + + default: + break; + } + + g_object_notify_by_pspec (G_OBJECT(self), zenity_tree_column_view_properties[LIST_TYPE]); +} + +ZenityTreeListType +zenity_tree_column_view_get_list_type (ZenityTreeColumnView *self) +{ + return self->list_type; +} + +gboolean +zenity_tree_column_view_get_multi (ZenityTreeColumnView *self) +{ + return self->multi; +} + +static void +zenity_tree_column_view_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + ZenityTreeColumnView *self = ZENITY_TREE_COLUMN_VIEW(object); + + switch (property_id) + { + case MULTI: + self->multi = g_value_get_boolean (value); + break; + + case LIST_TYPE: + zenity_tree_column_view_set_list_type (self, g_value_get_enum (value)); + break; + + case MODEL: + zenity_tree_column_view_set_model (self, G_LIST_MODEL(g_value_get_object (value))); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +zenity_tree_column_view_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + ZenityTreeColumnView *self = ZENITY_TREE_COLUMN_VIEW(object); + + switch (property_id) + { + case MULTI: + g_value_set_boolean (value, self->multi); + break; + + case LIST_TYPE: + g_value_set_enum (value, zenity_tree_column_view_get_list_type (self)); + break; + + case MODEL: + g_value_set_object (value, G_OBJECT(zenity_tree_column_view_get_model (self))); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +zenity_tree_column_view_dispose (GObject *object) +{ + ZenityTreeColumnView *self = ZENITY_TREE_COLUMN_VIEW(object); + + g_clear_pointer (&self->scrolled_window, gtk_widget_unparent); + + G_OBJECT_CLASS(zenity_tree_column_view_parent_class)->dispose(object); +} + +static void +zenity_tree_column_view_init (ZenityTreeColumnView *self) +{ + GtkWidget *widget = GTK_WIDGET(self); + + gtk_widget_init_template (widget); + + gtk_widget_set_hexpand (widget, TRUE); + gtk_widget_set_vexpand (widget, TRUE); +} + +static void +zenity_tree_column_view_class_init (ZenityTreeColumnViewClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); + GParamFlags flags = G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT; + + object_class->dispose = zenity_tree_column_view_dispose; + object_class->set_property = zenity_tree_column_view_set_property; + object_class->get_property = zenity_tree_column_view_get_property; + + zenity_tree_column_view_properties[MULTI] = g_param_spec_boolean ("multi", NULL, NULL, + FALSE, flags); + zenity_tree_column_view_properties[LIST_TYPE] = g_param_spec_enum ("list-type", NULL, NULL, + ZENITY_TYPE_TREE_LIST_TYPE, ZENITY_TREE_LIST_NONE, flags); + zenity_tree_column_view_properties[MODEL] = g_param_spec_object ("model", NULL, NULL, + G_TYPE_LIST_MODEL, flags); + + g_object_class_install_properties (object_class, N_PROPERTIES_ZENITY_TREE_COLUMN_VIEW, zenity_tree_column_view_properties); + + zenity_tree_column_view_signals[ACTIVATED] = g_signal_new_class_handler ("activated", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + /* no default C function */ + NULL, + /* defaults for accumulator, marshaller &c. */ + NULL, NULL, NULL, + /* No return type or params. */ + G_TYPE_NONE, 0); + + gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT); + + gtk_widget_class_set_template_from_resource (widget_class, UI_FILE); + + gtk_widget_class_bind_template_child (widget_class, ZenityTreeColumnView, scrolled_window); + gtk_widget_class_bind_template_child (widget_class, ZenityTreeColumnView, child_cv); +} + +#if 0 +static GtkWidget * +zenity_tree_column_view_new (GListModel *model) +{ + g_return_val_if_fail (G_IS_LIST_MODEL (model), NULL); + + return g_object_new (ZENITY_TREE_TYPE_COLUMN_VIEW, + "model", model, + NULL); +} +#endif + +static void +editable_notify_text_cb (GtkEditable *editable, GParamSpec *pspec, ZenityTreeItem *item) +{ + const char *str = gtk_editable_get_text (editable); + zenity_tree_item_set_text (item, str); +} + +static void +factory_bind_cb (ZenityTreeColumnView *self, + GtkListItem *list_item, + GtkSignalListItemFactory *factory) +{ + ZenityTreeRow *row = gtk_list_item_get_item (list_item); + int col_index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT(factory), "col_index")); + ZenityTreeItem *item; + GtkWidget *item_child; + const char *item_text; + + item = zenity_tree_row_get_item (row, col_index); + item_child = zenity_tree_item_get_child (item); + item_text = zenity_tree_item_get_text (item); + gtk_list_item_set_child (list_item, item_child); + + gtk_widget_set_halign (item_child, GTK_ALIGN_START); + + if (GTK_IS_EDITABLE (item_child)) /* handle first to capture anything editable */ + { + gtk_editable_set_text (GTK_EDITABLE(item_child), item_text); + g_signal_connect (item_child, "notify::text", G_CALLBACK(editable_notify_text_cb), item); + } + else if (GTK_IS_LABEL (item_child)) + { + gtk_label_set_text (GTK_LABEL(item_child), item_text); + } + else if (GTK_IS_CHECK_BUTTON (item_child) && item_text) + { + gboolean initialized = FALSE; + gboolean checked = FALSE; + + if (g_object_get_data (G_OBJECT(item_child), "initialized")) + initialized = TRUE; + + /* Radio-button-ize our check buttons if radio list requested + */ + if (self->list_type == ZENITY_TREE_LIST_RADIO) + { + if (!self->checkbutton_group) + self->checkbutton_group = GTK_CHECK_BUTTON(item_child); + + /* Annoying - if you try to add checkbtn to its own group, gtk + * spews errors instead of just returning silently. + */ + if (GTK_CHECK_BUTTON(item_child) != self->checkbutton_group) + gtk_check_button_set_group (GTK_CHECK_BUTTON(item_child), self->checkbutton_group); + } + + if (! initialized) + { + if (g_ascii_strcasecmp (item_text, "true") == 0) + checked = TRUE; + + gtk_check_button_set_active (GTK_CHECK_BUTTON(item_child), checked); + + g_object_set_data (G_OBJECT(item_child), "initialized", GINT_TO_POINTER(TRUE)); + } + } + else if (GTK_IS_IMAGE (item_child) && item_text) + { + gtk_image_set_from_file (GTK_IMAGE(item_child), item_text); + } + else + { + g_warning ("%s: Widget type of child not implemented.", __func__); + } +} + +void +zenity_tree_column_view_add_column (ZenityTreeColumnView *self, const char *col_name) +{ + int new_col_index; + GtkListItemFactory *factory; + GtkColumnViewColumn *column; + + new_col_index = zenity_tree_column_view_get_n_columns (self); + + factory = gtk_signal_list_item_factory_new (); + g_object_set_data (G_OBJECT(factory), "col_index", GINT_TO_POINTER(new_col_index)); + g_signal_connect_swapped (factory, "bind", G_CALLBACK (factory_bind_cb), self); + + /* nb: seems the signals for the factory need to be setup first *before* creating the column. */ + + column = gtk_column_view_column_new (col_name, factory); + + if (new_col_index == 0 && + (self->list_type == ZENITY_TREE_LIST_CHECK || self->list_type == ZENITY_TREE_LIST_RADIO)) + { + gtk_column_view_column_set_resizable (column, FALSE); + } + else + { + gtk_column_view_column_set_resizable (column, TRUE); + gtk_column_view_column_set_expand (column, TRUE); + } + + gtk_column_view_append_column (self->child_cv, column); +} + +void +zenity_tree_column_view_foreach_item (ZenityTreeColumnView *self, GFunc func, gpointer user_data) +{ + GListModel *model = zenity_tree_column_view_get_model (self); + + for (guint i = 0; i < g_list_model_get_n_items (model); ++i) + { + ZenityTreeRow *row = g_list_model_get_item (model, i); + + for (guint j = 0; j < zenity_tree_row_get_n_items (row); ++j) + { + ZenityTreeItem *item = zenity_tree_row_get_item (row, j); + + func (item, user_data); + } + } +} + +void +zenity_tree_column_view_foreach_row (ZenityTreeColumnView *self, GFunc func, gpointer user_data) +{ + GListModel *model = zenity_tree_column_view_get_model (self); + + for (guint i = 0; i < g_list_model_get_n_items (model); ++i) + { + ZenityTreeRow *row = g_list_model_get_item (model, i); + func (row, user_data); + } +} + +int +zenity_tree_column_view_get_n_columns (ZenityTreeColumnView *self) +{ + return g_list_model_get_n_items (gtk_column_view_get_columns (self->child_cv)); +} + +gboolean +zenity_tree_column_view_is_selected (ZenityTreeColumnView *self, guint pos) +{ + return gtk_selection_model_is_selected (gtk_column_view_get_model (self->child_cv), pos); +} diff --git a/src/zenity-tree-column-view.h b/src/zenity-tree-column-view.h new file mode 100644 index 0000000..c66e323 --- /dev/null +++ b/src/zenity-tree-column-view.h @@ -0,0 +1,54 @@ +#pragma once + +#include <gtk/gtk.h> + +#include "zenity-tree-column-view-enums.h" /* auto-generated by build system */ + +G_BEGIN_DECLS + +typedef enum +{ + ZENITY_TREE_LIST_NONE, + ZENITY_TREE_LIST_CHECK, + ZENITY_TREE_LIST_RADIO, + ZENITY_TREE_LIST_IMAGE +} ZenityTreeListType; + +/* ZenityTreeItem */ + +#define ZENITY_TREE_TYPE_ITEM (zenity_tree_item_get_type ()) +G_DECLARE_FINAL_TYPE (ZenityTreeItem, zenity_tree_item, ZENITY_TREE, ITEM, GObject) + +ZenityTreeItem * zenity_tree_item_new (const char *text, GtkWidget *child); +GtkWidget * zenity_tree_item_get_child (ZenityTreeItem *item); +const char * zenity_tree_item_get_text (ZenityTreeItem *item); +void zenity_tree_item_set_text (ZenityTreeItem *item, const char *text); + +/* ZenityTreeRow */ + +#define ZENITY_TREE_TYPE_ROW (zenity_tree_row_get_type ()) +G_DECLARE_FINAL_TYPE (ZenityTreeRow, zenity_tree_row, ZENITY_TREE, ROW, GObject) + +ZenityTreeRow * zenity_tree_row_new (void); +void zenity_tree_row_add (ZenityTreeRow *row, ZenityTreeItem *item); +guint zenity_tree_row_get_n_items (ZenityTreeRow *row); +ZenityTreeItem * zenity_tree_row_get_item (ZenityTreeRow *row, guint index); + +/* ZenityTreeColumnView */ + +#define ZENITY_TREE_TYPE_COLUMN_VIEW (zenity_tree_column_view_get_type ()) +G_DECLARE_FINAL_TYPE (ZenityTreeColumnView, zenity_tree_column_view, ZENITY_TREE, COLUMN_VIEW, GtkWidget) + +void zenity_tree_column_view_set_model (ZenityTreeColumnView *self, GListModel *model); +GListModel * zenity_tree_column_view_get_model (ZenityTreeColumnView *self); +void zenity_tree_column_view_set_list_type (ZenityTreeColumnView *self, ZenityTreeListType type); +ZenityTreeListType zenity_tree_column_view_get_list_type (ZenityTreeColumnView *self); +void zenity_tree_column_view_add_column (ZenityTreeColumnView *self, const char *col_name); +void zenity_tree_column_view_foreach_item (ZenityTreeColumnView *self, GFunc func, gpointer user_data); +void zenity_tree_column_view_foreach_row (ZenityTreeColumnView *self, GFunc func, gpointer user_data); +int zenity_tree_column_view_get_n_columns (ZenityTreeColumnView *self); +gboolean zenity_tree_column_view_get_editable (ZenityTreeColumnView *self); +gboolean zenity_tree_column_view_get_multi (ZenityTreeColumnView *self); +gboolean zenity_tree_column_view_is_selected (ZenityTreeColumnView *self, guint pos); + +G_END_DECLS diff --git a/src/zenity-tree-column-view.ui b/src/zenity-tree-column-view.ui new file mode 100644 index 0000000..fcfdd28 --- /dev/null +++ b/src/zenity-tree-column-view.ui @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- vim: ts=2 sw=2 +--> + +<interface> + <template class="ZenityTreeColumnView" parent="GtkWidget"> + <child> + <object class="GtkScrolledWindow" id="scrolled_window"> + <child> + <object class="GtkViewport"> + <property name="scroll-to-focus">true</property> <!-- good to explicitly set to true for backwards compatibility, acc. to TFM. --> + <child> + <object class="GtkColumnView" id="child_cv" /> + </child> + </object> + </child> + </object> + </child> + </template> +</interface> diff --git a/src/zenity.gresource.xml.in b/src/zenity.gresource.xml.in index 4671d46..12e4b45 100644 --- a/src/zenity.gresource.xml.in +++ b/src/zenity.gresource.xml.in @@ -24,5 +24,6 @@ <gresources> <gresource prefix="@resource_base_path@"> <file preprocess="xml-stripblanks" compressed="true">zenity.ui</file> + <file preprocess="xml-stripblanks" compressed="true">zenity-tree-column-view.ui</file> </gresource> </gresources> diff --git a/src/zenity.h b/src/zenity.h index 20cac9f..ac8b902 100644 --- a/src/zenity.h +++ b/src/zenity.h @@ -5,8 +5,6 @@ #include <adwaita.h> #include <glib/gi18n.h> -#include "zenity-enums.h" /* auto-generated by build system */ - #include <config.h> G_BEGIN_DECLS @@ -121,7 +119,7 @@ typedef struct { char *separator; gboolean multi; gboolean editable; - gboolean mid_search; + gboolean mid_search_DEPRECATED; char *print_column; char *hide_column; const char **data; diff --git a/src/zenity.ui b/src/zenity.ui index f2bb9b4..1f26eba 100644 --- a/src/zenity.ui +++ b/src/zenity.ui @@ -373,8 +373,8 @@ </object> <object class="AdwMessageDialog" id="zenity_tree_dialog"> <property name="title" translatable="yes">Select items from the list</property> - <property name="default_width">300</property> - <property name="default_height">196</property> + <property name="default_width">480</property> + <property name="default_height">320</property> <property name="extra-child">zenity_tree_box</property> <property name="resizable">true</property> <responses> @@ -395,17 +395,7 @@ </object> </child> <child> - <object class="GtkScrolledWindow" id="zenity_tree_window"> - <property name="hexpand">1</property> - <property name="vexpand">1</property> - <property name="child"> - <object class="GtkTreeView" id="zenity_tree_view"> - <child internal-child="selection"> - <object class="GtkTreeSelection" id="treeview-selection1"/> - </child> - </object> - </property> - </object> + <object class="ZenityTreeColumnView" id="zenity_tree_cv" /> </child> </object> </child> |