1/* Copyright 2015 Red Hat, Inc.
2 *
3 * GTK+ is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU Lesser General Public License as
5 * published by the Free Software Foundation; either version 2 of the
6 * License, or (at your option) any later version.
7 *
8 * GLib is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with GTK+; see the file COPYING. If not,
15 * see <http://www.gnu.org/licenses/>.
16 *
17 * Author: Matthias Clasen
18 */
19
20#include <stdlib.h>
21#include <string.h>
22#include <errno.h>
23
24#include <glib/gi18n.h>
25#include <glib/gprintf.h>
26#include <glib/gstdio.h>
27#include <gtk/gtk.h>
28#include "gtkbuilderprivate.h"
29#include "gtk-builder-tool.h"
30
31
32static void
33set_window_title (GtkWindow *window,
34 const char *filename,
35 const char *id)
36{
37 char *name;
38 char *title;
39
40 name = g_path_get_basename (file_name: filename);
41
42 if (id)
43 title = g_strdup_printf (format: "%s in %s", id, name);
44 else
45 title = g_strdup (str: name);
46
47 gtk_window_set_title (window, title);
48
49 g_free (mem: title);
50 g_free (mem: name);
51}
52
53static void
54quit_cb (GtkWidget *widget,
55 gpointer user_data)
56{
57 gboolean *is_done = user_data;
58
59 *is_done = TRUE;
60
61 g_main_context_wakeup (NULL);
62}
63
64static void
65preview_file (const char *filename,
66 const char *id,
67 const char *cssfile)
68{
69 GtkBuilder *builder;
70 GError *error = NULL;
71 GObject *object;
72 GtkWidget *window;
73 gboolean done = FALSE;
74
75 if (cssfile)
76 {
77 GtkCssProvider *provider;
78
79 provider = gtk_css_provider_new ();
80 gtk_css_provider_load_from_path (css_provider: provider, path: cssfile);
81
82 gtk_style_context_add_provider_for_display (display: gdk_display_get_default (),
83 GTK_STYLE_PROVIDER (provider),
84 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
85 }
86
87 builder = gtk_builder_new ();
88 if (!gtk_builder_add_from_file (builder, filename, error: &error))
89 {
90 g_printerr (format: "%s\n", error->message);
91 exit (status: 1);
92 }
93
94 object = NULL;
95
96 if (id)
97 {
98 object = gtk_builder_get_object (builder, name: id);
99 }
100 else
101 {
102 GSList *objects, *l;
103
104 objects = gtk_builder_get_objects (builder);
105 for (l = objects; l; l = l->next)
106 {
107 GObject *obj = l->data;
108
109 if (GTK_IS_WINDOW (obj))
110 {
111 object = obj;
112 break;
113 }
114 else if (GTK_IS_WIDGET (obj))
115 {
116 if (object == NULL)
117 object = obj;
118 }
119 }
120 g_slist_free (list: objects);
121 }
122
123 if (object == NULL)
124 {
125 if (id)
126 g_printerr (format: "No object with ID '%s' found\n", id);
127 else
128 g_printerr (format: "No previewable object found\n");
129 exit (status: 1);
130 }
131
132 if (!GTK_IS_WIDGET (object))
133 {
134 g_printerr (format: "Objects of type %s can't be previewed\n", G_OBJECT_TYPE_NAME (object));
135 exit (status: 1);
136 }
137
138 if (GTK_IS_WINDOW (object))
139 window = GTK_WIDGET (object);
140 else
141 {
142 GtkWidget *widget = GTK_WIDGET (object);
143
144 window = gtk_window_new ();
145
146 if (GTK_IS_BUILDABLE (object))
147 id = gtk_buildable_get_buildable_id (GTK_BUILDABLE (object));
148
149 set_window_title (GTK_WINDOW (window), filename, id);
150
151 g_object_ref (widget);
152 if (gtk_widget_get_parent (widget) != NULL)
153 gtk_box_remove (GTK_BOX (gtk_widget_get_parent (widget)), child: widget);
154 gtk_window_set_child (GTK_WINDOW (window), child: widget);
155 g_object_unref (object: widget);
156 }
157
158 gtk_window_present (GTK_WINDOW (window));
159 g_signal_connect (window, "destroy", G_CALLBACK (quit_cb), &done);
160
161 while (!done)
162 g_main_context_iteration (NULL, TRUE);
163
164 g_object_unref (object: builder);
165}
166
167void
168do_preview (int *argc,
169 const char ***argv)
170{
171 GOptionContext *context;
172 char *id = NULL;
173 char *css = NULL;
174 char **filenames = NULL;
175 const GOptionEntry entries[] = {
176 { "id", 0, 0, G_OPTION_ARG_STRING, &id, NULL, NULL },
177 { "css", 0, 0, G_OPTION_ARG_FILENAME, &css, NULL, NULL },
178 { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL, NULL },
179 { NULL, }
180 };
181 GError *error = NULL;
182
183 context = g_option_context_new (NULL);
184 g_option_context_set_help_enabled (context, FALSE);
185 g_option_context_add_main_entries (context, entries, NULL);
186
187 if (!g_option_context_parse (context, argc, argv: (char ***)argv, error: &error))
188 {
189 g_printerr (format: "%s\n", error->message);
190 g_error_free (error);
191 exit (status: 1);
192 }
193
194 g_option_context_free (context);
195
196 if (filenames == NULL)
197 {
198 g_printerr (format: "No .ui file specified\n");
199 exit (status: 1);
200 }
201
202 if (g_strv_length (str_array: filenames) > 1)
203 {
204 g_printerr (format: "Can only preview a single .ui file\n");
205 exit (status: 1);
206 }
207
208 preview_file (filename: filenames[0], id, cssfile: css);
209
210 g_strfreev (str_array: filenames);
211 g_free (mem: id);
212 g_free (mem: css);
213}
214

source code of gtk/tools/gtk-builder-tool-preview.c