1/*
2 * Copyright (c) 2014, 2020 Red Hat, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "config.h"
19#include <glib/gi18n-lib.h>
20
21#include "tree-data.h"
22
23#include "object-tree.h"
24
25#include "gtktreeview.h"
26#include "gtkcellrenderertext.h"
27#include "gtktogglebutton.h"
28#include "gtklabel.h"
29#include "gtkstack.h"
30#include "gtkboxlayout.h"
31#include "gtkorientable.h"
32
33
34struct _GtkInspectorTreeData
35{
36 GtkWidget parent_instance;
37
38 GtkTreeModel *object;
39 GtkTreeModel *types;
40 GtkTreeView *view;
41 GtkWidget *object_title;
42 gboolean show_data;
43};
44
45typedef struct _GtkInspectorTreeDataClass GtkInspectorTreeDataClass;
46struct _GtkInspectorTreeDataClass
47{
48 GtkWidgetClass parent_class;
49};
50
51
52G_DEFINE_TYPE (GtkInspectorTreeData, gtk_inspector_tree_data, GTK_TYPE_WIDGET)
53
54static void
55gtk_inspector_tree_data_init (GtkInspectorTreeData *sl)
56{
57 gtk_widget_init_template (GTK_WIDGET (sl));
58
59 gtk_orientable_set_orientation (GTK_ORIENTABLE (gtk_widget_get_layout_manager (GTK_WIDGET (sl))),
60 orientation: GTK_ORIENTATION_VERTICAL);
61}
62
63static void
64cell_data_func (GtkTreeViewColumn *col,
65 GtkCellRenderer *cell,
66 GtkTreeModel *model,
67 GtkTreeIter *iter,
68 gpointer data)
69{
70 int num;
71 GValue gvalue = { 0, };
72 char *value;
73
74 num = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (col), "num"));
75 gtk_tree_model_get_value (tree_model: model, iter, column: num, value: &gvalue);
76 value = g_strdup_value_contents (value: &gvalue);
77 g_object_set (object: cell, first_property_name: "text", value ? value : "", NULL);
78 g_free (mem: value);
79 g_value_unset (value: &gvalue);
80}
81
82static void
83add_columns (GtkInspectorTreeData *sl)
84{
85 int n_columns;
86 GtkCellRenderer *cell;
87 GType type;
88 char *title;
89 GtkTreeViewColumn *col;
90 int i;
91
92 n_columns = gtk_tree_model_get_n_columns (tree_model: sl->object);
93 for (i = 0; i < n_columns; i++)
94 {
95 cell = gtk_cell_renderer_text_new ();
96 type = gtk_tree_model_get_column_type (tree_model: sl->object, index_: i);
97 title = g_strdup_printf (format: "%d: %s", i, g_type_name (type));
98 col = gtk_tree_view_column_new_with_attributes (title, cell, NULL);
99 g_object_set_data (G_OBJECT (col), key: "num", GINT_TO_POINTER (i));
100 gtk_tree_view_column_set_cell_data_func (tree_column: col, cell_renderer: cell, func: cell_data_func, func_data: sl, NULL);
101 gtk_tree_view_append_column (tree_view: sl->view, column: col);
102 g_free (mem: title);
103 }
104}
105
106static void
107show_types (GtkInspectorTreeData *sl)
108{
109 gtk_tree_view_set_model (tree_view: sl->view, NULL);
110 sl->show_data = FALSE;
111}
112
113static void
114show_data (GtkInspectorTreeData *sl)
115{
116 gtk_tree_view_set_model (tree_view: sl->view, model: sl->object);
117 sl->show_data = TRUE;
118}
119
120static void
121clear_view (GtkInspectorTreeData *sl)
122{
123 gtk_tree_view_set_model (tree_view: sl->view, NULL);
124 while (gtk_tree_view_get_n_columns (tree_view: sl->view) > 0)
125 gtk_tree_view_remove_column (tree_view: sl->view,
126 column: gtk_tree_view_get_column (tree_view: sl->view, n: 0));
127}
128
129void
130gtk_inspector_tree_data_set_object (GtkInspectorTreeData *sl,
131 GObject *object)
132{
133 GtkWidget *stack;
134 GtkStackPage *page;
135 char *title;
136
137 stack = gtk_widget_get_parent (GTK_WIDGET (sl));
138 page = gtk_stack_get_page (GTK_STACK (stack), GTK_WIDGET (sl));
139
140 clear_view (sl);
141 sl->object = NULL;
142 sl->show_data = FALSE;
143
144 if (!GTK_IS_TREE_MODEL (object))
145 {
146 g_object_set (object: page, first_property_name: "visible", FALSE, NULL);
147 return;
148 }
149
150 title = gtk_inspector_get_object_title (object);
151 gtk_label_set_label (GTK_LABEL (sl->object_title), str: title);
152 g_free (mem: title);
153
154 g_object_set (object: page, first_property_name: "visible", TRUE, NULL);
155
156 sl->object = GTK_TREE_MODEL (object);
157 add_columns (sl);
158 show_types (sl);
159}
160
161static void
162toggle_show (GtkToggleButton *button,
163 GtkInspectorTreeData *sl)
164{
165 if (gtk_toggle_button_get_active (toggle_button: button) == sl->show_data)
166 return;
167
168 if (gtk_toggle_button_get_active (toggle_button: button))
169 show_data (sl);
170 else
171 show_types (sl);
172}
173
174static void
175dispose (GObject *object)
176{
177 GtkInspectorTreeData *sl = GTK_INSPECTOR_TREE_DATA (object);
178 GtkWidget *child;
179
180 while ((child = gtk_widget_get_first_child (GTK_WIDGET (sl))))
181 gtk_widget_unparent (widget: child);
182
183 G_OBJECT_CLASS (gtk_inspector_tree_data_parent_class)->dispose (object);
184}
185
186static void
187gtk_inspector_tree_data_class_init (GtkInspectorTreeDataClass *klass)
188{
189 GObjectClass *object_class = G_OBJECT_CLASS (klass);
190 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
191
192 object_class->dispose = dispose;
193
194 gtk_widget_class_set_template_from_resource (widget_class, resource_name: "/org/gtk/libgtk/inspector/tree-data.ui");
195 gtk_widget_class_bind_template_child (widget_class, GtkInspectorTreeData, view);
196 gtk_widget_class_bind_template_child (widget_class, GtkInspectorTreeData, object_title);
197 gtk_widget_class_bind_template_callback (widget_class, toggle_show);
198
199 gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
200}
201
202// vim: set et sw=2 ts=2:
203

source code of gtk/gtk/inspector/tree-data.c