Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Gnome/demos/gtk-demo/   (Gnome Linux Desktop Version 4.23.2©)  Datei vom 30.5.2026 mit Größe 21 kB image not shown  

Quelle  listview_selections.c

  Sprache: C
 

/* Lists/Selections
 * #Keywords: suggestion, completion
 *
 * The GtkDropDown widget is a modern alternative to GtkComboBox.
 * It uses list models instead of tree models, and the content is
 * displayed using widgets instead of cell renderers.
 *
 * This example also shows a custom widget that can replace
 * GtkEntryCompletion or GtkComboBoxText. It is not currently
 * part of GTK.
 */


#include <gtk/gtk.h>
#include "suggestionentry.h"

#define STRING_TYPE_HOLDER (string_holder_get_type ())
G_DECLARE_FINAL_TYPE (StringHolder, string_holder, STRING, HOLDER, GObject)

struct _StringHolder {
  GObject parent_instance;
  char *title;
  char *icon;
  char *description;
};

G_DEFINE_TYPE (StringHolder, string_holder, G_TYPE_OBJECT);

static void
string_holder_init (StringHolder *holder)
{
}

static void
string_holder_finalize (GObject *object)
{
  StringHolder *holder = STRING_HOLDER (object);

  g_free (holder->title);
  g_free (holder->icon);
  g_free (holder->description);

  G_OBJECT_CLASS (string_holder_parent_class)->finalize (object);
}

static void
string_holder_class_init (StringHolderClass *class)
{
  GObjectClass *object_class = G_OBJECT_CLASS (class);

  object_class->finalize = string_holder_finalize;
}

static StringHolder *
string_holder_new (const char *title, const char *icon, const char *description)
{
  StringHolder *holder = g_object_new (STRING_TYPE_HOLDER, NULL);
  holder->title = g_strdup (title);
  holder->icon = g_strdup (icon);
  holder->description = g_strdup (description);
  return holder;
}

static void
strings_setup_item_single_line (GtkSignalListItemFactory *factory,
                                GtkListItem              *item)
{
  GtkWidget *box, *image, *title;
  GtkWidget *checkmark;

  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);

  image = gtk_image_new ();
  title = gtk_label_new ("");
  gtk_label_set_xalign (GTK_LABEL (title), 0.0);
  checkmark = gtk_image_new_from_icon_name ("object-select-symbolic");

  gtk_box_append (GTK_BOX (box), image);
  gtk_box_append (GTK_BOX (box), title);
  gtk_box_append (GTK_BOX (box), checkmark);

  g_object_set_data (G_OBJECT (item), "title", title);
  g_object_set_data (G_OBJECT (item), "image", image);
  g_object_set_data (G_OBJECT (item), "checkmark", checkmark);

  gtk_list_item_set_child (item, box);
}

static void
strings_setup_item_full (GtkSignalListItemFactory *factory,
                         GtkListItem              *item)
{
  GtkWidget *box, *box2, *image, *title, *description;
  GtkWidget *checkmark;

  image = gtk_image_new ();
  title = gtk_label_new ("");
  gtk_label_set_xalign (GTK_LABEL (title), 0.0);
  description = gtk_label_new ("");
  gtk_label_set_xalign (GTK_LABEL (description), 0.0);
  gtk_widget_add_css_class (description, "dim-label");
  checkmark = gtk_image_new_from_icon_name ("object-select-symbolic");

  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
  box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);

  gtk_box_append (GTK_BOX (box), image);
  gtk_box_append (GTK_BOX (box), box2);
  gtk_box_append (GTK_BOX (box2), title);
  gtk_box_append (GTK_BOX (box2), description);
  gtk_box_append (GTK_BOX (box), checkmark);

  g_object_set_data (G_OBJECT (item), "title", title);
  g_object_set_data (G_OBJECT (item), "image", image);
  g_object_set_data (G_OBJECT (item), "description", description);
  g_object_set_data (G_OBJECT (item), "checkmark", checkmark);

  gtk_list_item_set_child (item, box);
}

static void
selected_item_changed (GtkDropDown *dropdown,
                       GParamSpec  *pspec,
                       GtkListItem *item)
{
  GtkWidget *checkmark;

  checkmark = g_object_get_data (G_OBJECT (item), "checkmark");

  if (gtk_drop_down_get_selected_item (dropdown) == gtk_list_item_get_item (item))
    gtk_widget_set_opacity (checkmark, 1.0);
  else
    gtk_widget_set_opacity (checkmark, 0.0);
}

static void
strings_bind_item (GtkSignalListItemFactory *factory,
                   GtkListItem              *item,
                   gpointer                  data)
{
  GtkDropDown *dropdown = data;
  GtkWidget *image, *title, *description;
  GtkWidget *checkmark;
  StringHolder *holder;
  GtkWidget *popup;

  holder = gtk_list_item_get_item (item);

  title = g_object_get_data (G_OBJECT (item), "title");
  image = g_object_get_data (G_OBJECT (item), "image");
  description = g_object_get_data (G_OBJECT (item), "description");
  checkmark = g_object_get_data (G_OBJECT (item), "checkmark");

  gtk_label_set_label (GTK_LABEL (title), holder->title);
  if (image)
    {
      gtk_image_set_from_icon_name (GTK_IMAGE (image), holder->icon);
      gtk_widget_set_visible (image, holder->icon != NULL);
    }
  if (description)
    {
      gtk_label_set_label (GTK_LABEL (description), holder->description);
      gtk_widget_set_visible (description , holder->description != NULL);
    }

  popup = gtk_widget_get_ancestor (title, GTK_TYPE_POPOVER);
  if (popup && gtk_widget_is_ancestor (popup, GTK_WIDGET (dropdown)))
    {
      gtk_widget_set_visible (checkmark, TRUE);
      g_signal_connect (dropdown, "notify::selected-item",
                        G_CALLBACK (selected_item_changed), item);
      selected_item_changed (dropdown, NULL, item);
    }
  else
    {
      gtk_widget_set_visible (checkmark, FALSE);
    }
}

static void
strings_unbind_item (GtkSignalListItemFactory *factory,
                     GtkListItem              *list_item,
                     gpointer                  data)
{
  GtkDropDown *dropdown = data;

  g_signal_handlers_disconnect_by_func (dropdown, selected_item_changed, list_item);
}

static GtkListItemFactory *
strings_factory_new (gpointer data, gboolean full)
{
  GtkListItemFactory *factory;

  factory = gtk_signal_list_item_factory_new ();
  if (full)
    g_signal_connect (factory, "setup", G_CALLBACK (strings_setup_item_full), data);
  else
    g_signal_connect (factory, "setup", G_CALLBACK (strings_setup_item_single_line), data);
  g_signal_connect (factory, "bind", G_CALLBACK (strings_bind_item), data);
  g_signal_connect (factory, "unbind", G_CALLBACK (strings_unbind_item), data);

  return factory;
}

static GListModel *
strings_model_new (const char *const *titles,
                   const char *const *icons,
                   const char *const *descriptions)
{
  GListStore *store;
  int i;

  store = g_list_store_new (STRING_TYPE_HOLDER);
  for (i = 0; titles[i]; i++)
    {
      StringHolder *holder = string_holder_new (titles[i],
                                                icons ? icons[i] : NULL,
                                                descriptions ? descriptions[i] : NULL);
      g_list_store_append (store, holder);
      g_object_unref (holder);
    }

  return G_LIST_MODEL (store);
}

static GtkWidget *
drop_down_new_from_strings (const char *const *titles,
                            const char *const *icons,
                            const char *const *descriptions)
{
  GtkWidget *widget;
  GListModel *model;
  GtkListItemFactory *factory;
  GtkListItemFactory *list_factory;

  g_return_val_if_fail (titles != NULL, NULL);
  g_return_val_if_fail (icons == NULL || g_strv_length ((char **)icons) == g_strv_length ((char **)titles), NULL);
  g_return_val_if_fail (descriptions == NULL || g_strv_length ((char **)icons) == g_strv_length ((char **)descriptions), NULL);

  model = strings_model_new (titles, icons, descriptions);
  widget = g_object_new (GTK_TYPE_DROP_DOWN,
                         "model", model,
                         NULL);
  g_object_unref (model);

  factory = strings_factory_new (widget, FALSE);
  if (icons != NULL || descriptions != NULL)
    list_factory = strings_factory_new (widget, TRUE);
  else
    list_factory = NULL;

  g_object_set (widget,
                "factory", factory,
                "list-factory", list_factory,
                NULL);

  g_object_unref (factory);
  if (list_factory)
    g_object_unref (list_factory);

  return widget;
}

static char *
get_family_name (gpointer item)
{
  return g_strdup (pango_font_family_get_name (PANGO_FONT_FAMILY (item)));
}

static char *
get_file_name (gpointer item)
{
  return g_strdup (g_file_info_get_display_name (G_FILE_INFO (item)));
}

static void
setup_item (GtkSignalListItemFactory *factory,
            GtkListItem              *item)
{
  GtkWidget *box;
  GtkWidget *icon;
  GtkWidget *label;

  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
  icon = gtk_image_new ();
  label = gtk_label_new ("");
  gtk_label_set_xalign (GTK_LABEL (label), 0);
  gtk_box_append (GTK_BOX (box), icon);
  gtk_box_append (GTK_BOX (box), label);
  gtk_list_item_set_child (item, box);
}

static void
bind_item (GtkSignalListItemFactory *factory,
           GtkListItem              *item)
{
  MatchObject *match = MATCH_OBJECT (gtk_list_item_get_item (item));
  GFileInfo *info = G_FILE_INFO (match_object_get_item (match));
  GtkWidget *box = gtk_list_item_get_child (item);
  GtkWidget *icon = gtk_widget_get_first_child (box);
  GtkWidget *label = gtk_widget_get_last_child (box);

  gtk_image_set_from_gicon (GTK_IMAGE (icon), g_file_info_get_icon (info));
  gtk_label_set_label (GTK_LABEL (label), g_file_info_get_display_name (info));
}

static void
setup_highlight_item (GtkSignalListItemFactory *factory,
                      GtkListItem              *item)
{
  GtkWidget *label;

  label = gtk_label_new ("");
  gtk_label_set_xalign (GTK_LABEL (label), 0);
  gtk_list_item_set_child (item, label);
}

static void
bind_highlight_item (GtkSignalListItemFactory *factory,
                     GtkListItem              *item)
{
  MatchObject *obj;
  GtkWidget *label;
  PangoAttrList *attrs;
  PangoAttribute *attr;
  const char *str;

  obj = MATCH_OBJECT (gtk_list_item_get_item (item));
  label = gtk_list_item_get_child (item);

  str = match_object_get_string (obj);

  gtk_label_set_label (GTK_LABEL (label), str);
  attrs = pango_attr_list_new ();
  attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
  attr->start_index = match_object_get_match_start (obj);
  attr->end_index = match_object_get_match_end (obj);
  pango_attr_list_insert (attrs, attr);
  gtk_label_set_attributes (GTK_LABEL (label), attrs);
  pango_attr_list_unref (attrs);
}

static void
match_func (MatchObject *obj,
            const char  *search,
            gpointer     user_data)
{
  char *tmp1, *tmp2;
  char *p;

  tmp1 = g_utf8_normalize (match_object_get_string (obj), -1, G_NORMALIZE_ALL);
  tmp2 = g_utf8_normalize (search, -1, G_NORMALIZE_ALL);

  if ((p = strstr (tmp1, tmp2)) != NULL)
    match_object_set_match (obj,
                            p - tmp1,
                            (p - tmp1) + g_utf8_strlen (search, -1),
                            1);
  else
    match_object_set_match (obj, 000);

  g_free (tmp1);
  g_free (tmp2);
}

static void
setup_header (GtkSignalListItemFactory *factory,
              GObject                  *list_item,
              gpointer                  data)
{
  GtkListHeader *self = GTK_LIST_HEADER (list_item);
  GtkWidget *child;

  child = gtk_label_new ("");
  gtk_label_set_xalign (GTK_LABEL (child), 0);
  gtk_label_set_use_markup (GTK_LABEL (child), TRUE);
  gtk_widget_set_margin_top (child, 10);
  gtk_widget_set_margin_bottom (child, 10);

  gtk_list_header_set_child (self, child);
}

static void
bind_header (GtkSignalListItemFactory *factory,
             GObject                  *list_item,
             gpointer                  data)
{
  GtkListHeader *self = GTK_LIST_HEADER (list_item);
  GtkWidget *child = gtk_list_header_get_child (self);
  GObject *item = gtk_list_header_get_item (self);

  if (strstr (gtk_string_object_get_string (GTK_STRING_OBJECT (item)), "hour"))
    gtk_label_set_label (GTK_LABEL (child), "<big><b>Hours</b></big>");
  else
    gtk_label_set_label (GTK_LABEL (child), "<big><b>Minutes</b></big>");
}

GtkWidget *
do_listview_selections (GtkWidget *do_widget)
{
  static GtkWidget *window = NULL;
  GtkWidget *button, *box, *spin, *check, *hbox, *label, *entry;
  GListModel *model;
  GtkExpression *expression;
  GtkListItemFactory *factory;
  const char * const times[] = { "1 minute""2 minutes""5 minutes""20 minutes", NULL };
  const char * const minutes[] = {
    "1 minute""2 minutes""5 minutes""10 minutes""15 minutes""20 minutes",
    "25 minutes""30 minutes""35 minutes""40 minutes""45 minutes""50 minutes",
    "55 minutes", NULL
  };
  const char * const hours[] = { "1 hour""2 hours""3 hours""5 hours""6 hours""7 hours",
    "8 hours""9 hours""10 hours""11 hours""12 hours", NULL
  };
  const char * const device_titles[] = { "Digital Output""Headphones""Digital Output""Analog Output", NULL };
  const char * const device_icons[] = {  "audio-card-symbolic""audio-headphones-symbolic""audio-card-symbolic""audio-card-symbolic", NULL };
  const char * const device_descriptions[] = {
    "Built-in Audio""Built-in audio""Thinkpad Tunderbolt 3 Dock USB Audio""Thinkpad Tunderbolt 3 Dock USB Audio", NULL
  };
  char *cwd;
  GFile *file;
  GListModel *dir;
  GtkStringList *strings;

  if (!window)
    {
      GtkStringList *minutes_model, *hours_model;
      GListStore *store;
      GtkFlattenListModel *flat;

      window = gtk_window_new ();
      gtk_window_set_display (GTK_WINDOW (window),
                              gtk_widget_get_display (do_widget));
      gtk_window_set_title (GTK_WINDOW (window), "Selections");
      gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
      g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);

      hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 20);

      gtk_widget_set_margin_start (hbox, 20);
      gtk_widget_set_margin_end (hbox, 20);
      gtk_widget_set_margin_top (hbox, 20);
      gtk_widget_set_margin_bottom (hbox, 20);
      gtk_window_set_child (GTK_WINDOW (window), hbox);

      box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
      gtk_box_append (GTK_BOX (hbox), box);

      label = gtk_label_new ("Dropdowns");
      gtk_widget_add_css_class (label, "title-4");
      gtk_box_append (GTK_BOX (box), label);

      /* A basic dropdown */
      button = drop_down_new_from_strings (times, NULL, NULL);
      gtk_box_append (GTK_BOX (box), button);

      /* A dropdown using an expression to obtain strings */
      minutes_model = gtk_string_list_new (minutes);
      hours_model = gtk_string_list_new (hours);
      store = g_list_store_new (G_TYPE_LIST_MODEL);
      g_list_store_append (store, minutes_model);
      g_list_store_append (store, hours_model);
      g_object_unref (minutes_model);
      g_object_unref (hours_model);
      flat = gtk_flatten_list_model_new (G_LIST_MODEL (store));
      expression = gtk_property_expression_new (GTK_TYPE_STRING_OBJECT,
                                                NULL,
                                                "string");
      button = gtk_drop_down_new (G_LIST_MODEL (flat), expression);
      gtk_drop_down_set_enable_search (GTK_DROP_DOWN (button), TRUE);
      factory = gtk_signal_list_item_factory_new ();
      g_signal_connect (factory, "setup", G_CALLBACK (setup_header), NULL);
      g_signal_connect (factory, "bind", G_CALLBACK (bind_header), NULL);
      gtk_drop_down_set_header_factory (GTK_DROP_DOWN (button), factory);
      g_object_unref (factory);
      gtk_box_append (GTK_BOX (box), button);

      button = gtk_drop_down_new (NULL, NULL);

      model = G_LIST_MODEL (pango_cairo_font_map_get_default ());
      gtk_drop_down_set_model (GTK_DROP_DOWN (button), model);
      gtk_drop_down_set_selected (GTK_DROP_DOWN (button), 0);

      expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
                                                0, NULL,
                                                (GCallback)get_family_name,
                                                NULL, NULL);
      gtk_drop_down_set_expression (GTK_DROP_DOWN (button), expression);
      gtk_expression_unref (expression);
      gtk_box_append (GTK_BOX (box), button);

      spin = gtk_spin_button_new_with_range (-1, g_list_model_get_n_items (G_LIST_MODEL (model)), 1);
      gtk_widget_set_halign (spin, GTK_ALIGN_START);
      gtk_widget_set_margin_start (spin, 20);
      g_object_bind_property  (button, "selected", spin, "value", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
      gtk_box_append (GTK_BOX (box), spin);

      check = gtk_check_button_new_with_label ("Enable search");
      gtk_widget_set_margin_start (check, 20);
      g_object_bind_property  (button, "enable-search", check, "active", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
      gtk_box_append (GTK_BOX (box), check);

      g_object_unref (model);

      /* A dropdown with a separate list factory */
      button = drop_down_new_from_strings (device_titles, device_icons, device_descriptions);
      gtk_box_append (GTK_BOX (box), button);

      gtk_box_append (GTK_BOX (hbox), gtk_separator_new (GTK_ORIENTATION_VERTICAL));

      box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
      gtk_box_append (GTK_BOX (hbox), box);

      label = gtk_label_new ("Suggestions");
      gtk_widget_add_css_class (label, "title-4");
      gtk_box_append (GTK_BOX (box), label);

      /* A basic suggestion entry */
      entry = suggestion_entry_new ();
      g_object_set (entry, "placeholder-text""Words with T or G…", NULL);
      strings = gtk_string_list_new ((const char *[]){
                                     "GNOME",
                                     "gnominious",
                                     "Gnomonic projection",
                                     "total",
                                     "totally",
                                     "toto",
                                     "tottery",
                                     "totterer",
                                     "Totten trust",
                                     "totipotent",
                                     "totipotency",
                                     "totemism",
                                     "totem pole",
                                     "Totara",
                                     "totalizer",
                                     "totalizator",
                                     "totalitarianism",
                                     "total parenteral nutrition",
                                     "total hysterectomy",
                                     "total eclipse",
                                     "Totipresence",
                                     "Totipalmi",
                                     "Tomboy",
                                     "zombie",
                                     NULL});
      suggestion_entry_set_model (SUGGESTION_ENTRY (entry), G_LIST_MODEL (strings));
      g_object_unref (strings);

      gtk_box_append (GTK_BOX (box), entry);

      /* A suggestion entry using a custom model, and no filtering */
      entry = suggestion_entry_new ();

      cwd = g_get_current_dir ();
      file = g_file_new_for_path (cwd);
      dir = G_LIST_MODEL (gtk_directory_list_new ("standard::display-name,standard::content-type,standard::icon,standard::size", file));
      suggestion_entry_set_model (SUGGESTION_ENTRY (entry), dir);
      g_object_unref (dir);
      g_object_unref (file);
      g_free (cwd);

      expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
                                                0, NULL,
                                                (GCallback)get_file_name,
                                                NULL, NULL);
      suggestion_entry_set_expression (SUGGESTION_ENTRY (entry), expression);
      gtk_expression_unref (expression);

      factory = gtk_signal_list_item_factory_new ();
      g_signal_connect (factory, "setup", G_CALLBACK (setup_item), NULL);
      g_signal_connect (factory, "bind", G_CALLBACK (bind_item), NULL);

      suggestion_entry_set_factory (SUGGESTION_ENTRY (entry), factory);
      g_object_unref (factory);

      suggestion_entry_set_use_filter (SUGGESTION_ENTRY (entry), FALSE);
      suggestion_entry_set_show_arrow (SUGGESTION_ENTRY (entry), TRUE);

      gtk_box_append (GTK_BOX (box), entry);

      /* A suggestion entry with match highlighting */
      entry = suggestion_entry_new ();
      g_object_set (entry, "placeholder-text""Destination", NULL);

      strings = gtk_string_list_new ((const char *[]){
                                     "app-mockups",
                                     "settings-mockups",
                                     "os-mockups",
                                     "software-mockups",
                                     "mocktails",
                                     NULL});
      suggestion_entry_set_model (SUGGESTION_ENTRY (entry), G_LIST_MODEL (strings));
      g_object_unref (strings);

      gtk_box_append (GTK_BOX (box), entry);

      suggestion_entry_set_match_func (SUGGESTION_ENTRY (entry), match_func, NULL, NULL);

      factory = gtk_signal_list_item_factory_new ();
      g_signal_connect (factory, "setup", G_CALLBACK (setup_highlight_item), NULL);
      g_signal_connect (factory, "bind", G_CALLBACK (bind_highlight_item), NULL);
      suggestion_entry_set_factory (SUGGESTION_ENTRY (entry), factory);
      g_object_unref (factory);

    }

  if (!gtk_widget_get_visible (window))
    gtk_widget_set_visible (window, TRUE);
  else
    gtk_window_destroy (GTK_WINDOW (window));

  return window;
}

Messung V0.5 in Prozent
C=99 H=94 G=96

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-07-02) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.