1/*
2 * Copyright (c) 2015 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 "strv-editor.h"
22#include "gtkbutton.h"
23#include "gtkentry.h"
24#include "gtkbox.h"
25#include "gtkorientable.h"
26#include "gtkmarshalers.h"
27
28enum
29{
30 CHANGED,
31 N_SIGNALS
32};
33
34static guint signals[N_SIGNALS] = { 0 };
35
36G_DEFINE_TYPE (GtkInspectorStrvEditor, gtk_inspector_strv_editor, GTK_TYPE_BOX);
37
38static void
39emit_changed (GtkInspectorStrvEditor *editor)
40{
41 if (editor->blocked)
42 return;
43
44 g_signal_emit (instance: editor, signal_id: signals[CHANGED], detail: 0);
45}
46
47static void
48remove_string (GtkButton *button,
49 GtkInspectorStrvEditor *editor)
50{
51 GtkWidget *row;
52
53 row = gtk_widget_get_parent (GTK_WIDGET (button));
54 gtk_box_remove (GTK_BOX (gtk_widget_get_parent (row)), child: row);
55 emit_changed (editor);
56}
57
58static void
59add_string (GtkInspectorStrvEditor *editor,
60 const char *str)
61{
62 GtkWidget *box;
63 GtkWidget *entry;
64 GtkWidget *button;
65
66 box = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 0);
67 gtk_widget_add_css_class (widget: box, css_class: "linked");
68 gtk_widget_show (widget: box);
69
70 entry = gtk_entry_new ();
71 gtk_editable_set_text (GTK_EDITABLE (entry), text: str);
72 gtk_widget_show (widget: entry);
73 gtk_box_append (GTK_BOX (box), child: entry);
74 g_object_set_data (G_OBJECT (box), key: "entry", data: entry);
75 g_signal_connect_swapped (entry, "notify::text", G_CALLBACK (emit_changed), editor);
76
77 button = gtk_button_new_from_icon_name (icon_name: "user-trash-symbolic");
78 gtk_widget_add_css_class (widget: button, css_class: "image-button");
79 gtk_widget_show (widget: button);
80 gtk_box_append (GTK_BOX (box), child: button);
81 g_signal_connect (button, "clicked", G_CALLBACK (remove_string), editor);
82
83 gtk_box_append (GTK_BOX (editor->box), child: box);
84
85 gtk_widget_grab_focus (widget: entry);
86
87 emit_changed (editor);
88}
89
90static void
91add_cb (GtkButton *button,
92 GtkInspectorStrvEditor *editor)
93{
94 add_string (editor, str: "");
95}
96
97static void
98gtk_inspector_strv_editor_init (GtkInspectorStrvEditor *editor)
99{
100 gtk_box_set_spacing (GTK_BOX (editor), spacing: 6);
101 gtk_orientable_set_orientation (GTK_ORIENTABLE (editor), orientation: GTK_ORIENTATION_VERTICAL);
102 editor->box = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 6);
103 gtk_widget_show (widget: editor->box);
104
105 editor->button = gtk_button_new_from_icon_name (icon_name: "list-add-symbolic");
106 gtk_widget_add_css_class (widget: editor->button, css_class: "image-button");
107 gtk_widget_set_focus_on_click (widget: editor->button, FALSE);
108 gtk_widget_set_halign (widget: editor->button, align: GTK_ALIGN_END);
109 gtk_widget_show (widget: editor->button);
110 g_signal_connect (editor->button, "clicked", G_CALLBACK (add_cb), editor);
111
112 gtk_box_append (GTK_BOX (editor), child: editor->box);
113 gtk_box_append (GTK_BOX (editor), child: editor->button);
114}
115
116static void
117gtk_inspector_strv_editor_class_init (GtkInspectorStrvEditorClass *class)
118{
119 signals[CHANGED] =
120 g_signal_new (signal_name: "changed",
121 G_TYPE_FROM_CLASS (class),
122 signal_flags: G_SIGNAL_RUN_FIRST,
123 G_STRUCT_OFFSET (GtkInspectorStrvEditorClass, changed),
124 NULL, NULL,
125 NULL,
126 G_TYPE_NONE, n_params: 0);
127}
128
129void
130gtk_inspector_strv_editor_set_strv (GtkInspectorStrvEditor *editor,
131 char **strv)
132{
133 GtkWidget *child;
134 int i;
135
136 editor->blocked = TRUE;
137
138 while ((child = gtk_widget_get_first_child (GTK_WIDGET (editor->box))))
139 gtk_box_remove (GTK_BOX (editor->box), child);
140
141 if (strv)
142 {
143 for (i = 0; strv[i]; i++)
144 add_string (editor, str: strv[i]);
145 }
146
147 editor->blocked = FALSE;
148
149 emit_changed (editor);
150}
151
152char **
153gtk_inspector_strv_editor_get_strv (GtkInspectorStrvEditor *editor)
154{
155 GtkWidget *child;
156 GPtrArray *p;
157
158 p = g_ptr_array_new ();
159
160 for (child = gtk_widget_get_first_child (widget: editor->box);
161 child != NULL;
162 child = gtk_widget_get_next_sibling (widget: child))
163 {
164 GtkEntry *entry;
165
166 entry = GTK_ENTRY (g_object_get_data (G_OBJECT (child), "entry"));
167 g_ptr_array_add (array: p, data: g_strdup (str: gtk_editable_get_text (GTK_EDITABLE (entry))));
168 }
169
170 g_ptr_array_add (array: p, NULL);
171
172 return (char **)g_ptr_array_free (array: p, FALSE);
173}
174

source code of gtk/gtk/inspector/strv-editor.c