mark PurpleImageClass as private
[pidgin-git.git] / pidgin / pidginabout.c
blob3f7d55a18e814508257c7ac0e35475269e660359
1 /* Purple is the legal property of its developers, whose names are too numerous
2 * to list here. Please refer to the COPYRIGHT file distributed with this
3 * source distribution.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
19 #include <gdk-pixbuf/gdk-pixbuf.h>
20 #include <json-glib/json-glib.h>
21 #include <talkatu.h>
23 #include "package_revision.h"
24 #include "pidginabout.h"
25 #include "pidginresources.h"
26 #include "internal.h"
27 #include "gtkutils.h"
29 #include <stdio.h>
31 #ifdef HAVE_MESON_CONFIG
32 #include "meson-config.h"
33 #endif
35 struct _PidginAboutDialog {
36 GtkDialog parent;
38 GtkWidget *close_button;
39 GtkWidget *application_name;
40 GtkWidget *stack;
42 GtkWidget *main_scrolled_window;
43 GtkTextBuffer *main_buffer;
45 GtkWidget *developers_page;
46 GtkWidget *developers_treeview;
47 GtkTreeStore *developers_store;
49 GtkWidget *translators_page;
50 GtkWidget *translators_treeview;
51 GtkTreeStore *translators_store;
53 GtkWidget *build_info_page;
54 GtkWidget *build_info_treeview;
55 GtkTreeStore *build_info_store;
58 /******************************************************************************
59 * Helpers
60 *****************************************************************************/
61 static void
62 _pidgin_about_dialog_load_application_name(PidginAboutDialog *about) {
63 gchar *label = g_strdup_printf(
64 "%s %s",
65 PIDGIN_NAME,
66 VERSION
69 gtk_label_set_text(GTK_LABEL(about->application_name), label);
71 g_free(label);
74 static void
75 _pidgin_about_dialog_load_main_page(PidginAboutDialog *about) {
76 GtkTextIter start;
77 GInputStream *istream = NULL;
78 GString *str = NULL;
79 gchar buffer[8192];
80 gssize read = 0, size = 0;
82 /* now load the html */
83 istream = g_resource_open_stream(
84 pidgin_get_resource(),
85 "/im/pidgin/Pidgin/About/about.md",
86 G_RESOURCE_LOOKUP_FLAGS_NONE,
87 NULL
90 str = g_string_new("");
92 while((read = g_input_stream_read(istream, buffer, sizeof(buffer), NULL, NULL)) > 0) {
93 g_string_append_len(str, (gchar *)buffer, read);
94 size += read;
97 gtk_text_buffer_get_start_iter(about->main_buffer, &start);
99 talkatu_markdown_buffer_insert_markdown(
100 TALKATU_MARKDOWN_BUFFER(about->main_buffer),
101 &start,
102 str->str,
103 size
106 g_string_free(str, TRUE);
108 g_input_stream_close(istream, NULL, NULL);
111 static void
112 _pidgin_about_dialog_load_json(GtkTreeStore *store, const gchar *json_section) {
113 GInputStream *istream = NULL;
114 GList *l = NULL, *sections = NULL;
115 GError *error = NULL;
116 JsonParser *parser = NULL;
117 JsonNode *root_node = NULL;
118 JsonObject *root_object = NULL;
119 JsonArray *sections_array = NULL;
121 /* get a stream to the credits resource */
122 istream = g_resource_open_stream(
123 pidgin_get_resource(),
124 "/im/pidgin/Pidgin/About/credits.json",
125 G_RESOURCE_LOOKUP_FLAGS_NONE,
126 NULL
129 /* create our parser */
130 parser = json_parser_new();
132 if(!json_parser_load_from_stream(parser, istream, NULL, &error)) {
133 g_critical("%s", error->message);
136 root_node = json_parser_get_root(parser);
137 root_object = json_node_get_object(root_node);
139 sections_array = json_object_get_array_member(root_object, json_section);
140 sections = json_array_get_elements(sections_array);
142 for(l = sections; l; l = l->next) {
143 GtkTreeIter section_iter;
144 JsonObject *section = json_node_get_object(l->data);
145 JsonArray *people = NULL;
146 gchar *markup = NULL;
147 guint idx = 0, n_people = 0;
149 markup = g_strdup_printf(
150 "<span font_weight=\"bold\" font_size=\"large\">%s</span>",
151 json_object_get_string_member(section, "title")
154 gtk_tree_store_append(store, &section_iter, NULL);
155 gtk_tree_store_set(
156 store,
157 &section_iter,
158 0, markup,
159 1, 0.5f,
163 g_free(markup);
165 people = json_object_get_array_member(section, "people");
166 n_people = json_array_get_length(people);
168 for(idx = 0; idx < n_people; idx++) {
169 GtkTreeIter person_iter;
171 gtk_tree_store_append(store, &person_iter, &section_iter);
172 gtk_tree_store_set(
173 store,
174 &person_iter,
175 0, json_array_get_string_element(people, idx),
176 1, 0.5f,
182 g_list_free(sections);
184 /* clean up */
185 g_object_unref(G_OBJECT(parser));
187 g_input_stream_close(istream, NULL, NULL);
190 static void
191 _pidgin_about_dialog_load_developers(PidginAboutDialog *about) {
192 _pidgin_about_dialog_load_json(about->developers_store, "developers");
195 static void
196 _pidgin_about_dialog_load_translators(PidginAboutDialog *about) {
197 _pidgin_about_dialog_load_json(about->translators_store, "languages");
200 static void
201 _pidgin_about_dialog_add_build_args(
202 PidginAboutDialog *about,
203 const gchar *title,
204 const gchar *build_args
206 GtkTreeIter section, value;
207 gchar **splits = NULL;
208 gchar *markup = NULL;
209 gint idx = 0;
211 markup = g_strdup_printf("<span font-weight=\"bold\">%s</span>", title);
212 gtk_tree_store_append(about->build_info_store, &section, NULL);
213 gtk_tree_store_set(
214 about->build_info_store,
215 &section,
216 0, markup,
219 g_free(markup);
221 /* now walk through the arguments and add them */
222 splits = g_strsplit(build_args, " ", -1);
223 for(idx = 0; splits[idx]; idx++) {
224 gchar **value_split = g_strsplit(splits[idx], "=", 2);
226 if(value_split[0] == NULL || value_split[0][0] == '\0') {
227 continue;
230 gtk_tree_store_append(about->build_info_store, &value, &section);
231 gtk_tree_store_set(
232 about->build_info_store,
233 &value,
234 0, value_split[0] ? value_split[0] : "",
235 1, value_split[1] ? value_split[1] : "",
239 g_strfreev(value_split);
242 g_strfreev(splits);
245 static void
246 _pidgin_about_dialog_build_info_add_version(
247 GtkTreeStore *store,
248 GtkTreeIter *section,
249 const gchar *title,
250 guint major,
251 guint minor,
252 guint micro
254 GtkTreeIter item;
255 gchar *version = g_strdup_printf("%u.%u.%u", major, minor, micro);
257 gtk_tree_store_append(store, &item, section);
258 gtk_tree_store_set(
259 store, &item,
260 0, title,
261 1, version,
264 g_free(version);
267 static void
268 _pidgin_about_dialog_load_build_info(PidginAboutDialog *about) {
269 GtkTreeIter section, item;
270 gchar *markup = NULL;
272 /* create the section */
273 markup = g_strdup_printf(
274 "<span font-weight=\"bold\">%s</span>",
275 _("Build Information")
277 gtk_tree_store_append(about->build_info_store, &section, NULL);
278 gtk_tree_store_set(
279 about->build_info_store,
280 &section,
281 0, markup,
284 g_free(markup);
286 /* add the commit hash */
287 gtk_tree_store_append(about->build_info_store, &item, &section);
288 gtk_tree_store_set(
289 about->build_info_store,
290 &item,
291 0, "Commit Hash",
292 1, REVISION,
296 /* add the purple version */
297 _pidgin_about_dialog_build_info_add_version(
298 about->build_info_store,
299 &section,
300 _("Purple Version"),
301 PURPLE_MAJOR_VERSION,
302 PURPLE_MINOR_VERSION,
303 PURPLE_MICRO_VERSION
306 /* add the glib version */
307 _pidgin_about_dialog_build_info_add_version(
308 about->build_info_store,
309 &section,
310 _("GLib Version"),
311 GLIB_MAJOR_VERSION,
312 GLIB_MINOR_VERSION,
313 GLIB_MICRO_VERSION
316 /* add the gtk version */
317 _pidgin_about_dialog_build_info_add_version(
318 about->build_info_store,
319 &section,
320 _("GTK+ Version"),
321 GTK_MAJOR_VERSION,
322 GTK_MINOR_VERSION,
323 GTK_MICRO_VERSION
327 static void
328 _pidgin_about_dialog_load_runtime_info(PidginAboutDialog *about) {
329 GtkTreeIter section;
330 gchar *markup = NULL;
332 /* create the section */
333 markup = g_strdup_printf(
334 "<span font-weight=\"bold\">%s</span>",
335 _("Runtime Information")
337 gtk_tree_store_append(about->build_info_store, &section, NULL);
338 gtk_tree_store_set(
339 about->build_info_store,
340 &section,
341 0, markup,
344 g_free(markup);
346 /* add the purple version */
347 _pidgin_about_dialog_build_info_add_version(
348 about->build_info_store,
349 &section,
350 _("Purple Version"),
351 purple_major_version,
352 purple_minor_version,
353 purple_micro_version
356 /* add the glib version */
357 _pidgin_about_dialog_build_info_add_version(
358 about->build_info_store,
359 &section,
360 _("GLib Version"),
361 glib_major_version,
362 glib_minor_version,
363 glib_micro_version
366 /* add the gtk version */
367 _pidgin_about_dialog_build_info_add_version(
368 about->build_info_store,
369 &section,
370 _("GTK+ Version"),
371 gtk_major_version,
372 gtk_minor_version,
373 gtk_micro_version
377 static void
378 _pidgin_about_dialog_load_build_configuration(PidginAboutDialog *about) {
379 #ifdef MESON_ARGS
380 _pidgin_about_dialog_add_build_args(about, "Meson Arguments", MESON_ARGS);
381 #endif /* MESON_ARGS */
383 _pidgin_about_dialog_load_build_info(about);
384 _pidgin_about_dialog_load_runtime_info(about);
387 /******************************************************************************
388 * Callbacks
389 *****************************************************************************/
390 static void
391 _pidgin_about_dialog_close(GtkWidget *b, gpointer data) {
392 gtk_widget_destroy(GTK_WIDGET(data));
395 /******************************************************************************
396 * GObject Stuff
397 *****************************************************************************/
398 G_DEFINE_TYPE(PidginAboutDialog, pidgin_about_dialog, GTK_TYPE_DIALOG);
400 static void
401 pidgin_about_dialog_class_init(PidginAboutDialogClass *klass) {
402 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
404 gtk_widget_class_set_template_from_resource(
405 widget_class,
406 "/im/pidgin/Pidgin/About/about.ui"
409 gtk_widget_class_bind_template_child(widget_class, PidginAboutDialog, close_button);
410 gtk_widget_class_bind_template_child(widget_class, PidginAboutDialog, application_name);
411 gtk_widget_class_bind_template_child(widget_class, PidginAboutDialog, stack);
413 gtk_widget_class_bind_template_child(widget_class, PidginAboutDialog, main_scrolled_window);
414 gtk_widget_class_bind_template_child(widget_class, PidginAboutDialog, main_buffer);
416 gtk_widget_class_bind_template_child(widget_class, PidginAboutDialog, developers_page);
417 gtk_widget_class_bind_template_child(widget_class, PidginAboutDialog, developers_store);
418 gtk_widget_class_bind_template_child(widget_class, PidginAboutDialog, developers_treeview);
420 gtk_widget_class_bind_template_child(widget_class, PidginAboutDialog, translators_page);
421 gtk_widget_class_bind_template_child(widget_class, PidginAboutDialog, translators_store);
422 gtk_widget_class_bind_template_child(widget_class, PidginAboutDialog, translators_treeview);
424 gtk_widget_class_bind_template_child(widget_class, PidginAboutDialog, build_info_page);
425 gtk_widget_class_bind_template_child(widget_class, PidginAboutDialog, build_info_store);
426 gtk_widget_class_bind_template_child(widget_class, PidginAboutDialog, build_info_treeview);
429 static void
430 pidgin_about_dialog_init(PidginAboutDialog *about) {
431 gtk_widget_init_template(GTK_WIDGET(about));
433 /* wire up the close button */
434 g_signal_connect(
435 about->close_button,
436 "clicked",
437 G_CALLBACK(_pidgin_about_dialog_close),
438 about
441 /* setup the application name label */
442 _pidgin_about_dialog_load_application_name(about);
444 /* setup the main page */
445 _pidgin_about_dialog_load_main_page(about);
447 /* setup the developers stuff */
448 _pidgin_about_dialog_load_developers(about);
449 gtk_tree_view_expand_all(GTK_TREE_VIEW(about->developers_treeview));
451 /* setup the translators stuff */
452 _pidgin_about_dialog_load_translators(about);
453 gtk_tree_view_expand_all(GTK_TREE_VIEW(about->translators_treeview));
455 /* setup the build info page */
456 _pidgin_about_dialog_load_build_configuration(about);
457 gtk_tree_view_expand_all(GTK_TREE_VIEW(about->build_info_treeview));
460 GtkWidget *
461 pidgin_about_dialog_new(void) {
462 GtkWidget *about = NULL;
464 about = g_object_new(
465 PIDGIN_TYPE_ABOUT_DIALOG,
466 "title", "About Pidgin",
467 NULL
470 return about;