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 | |
32 | static void |
33 | set_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 | |
53 | static void |
54 | quit_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 | |
64 | static void |
65 | preview_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 | |
167 | void |
168 | do_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 | |