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
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>
23 #include "package_revision.h"
24 #include "pidginabout.h"
25 #include "pidginresources.h"
31 #ifdef HAVE_MESON_CONFIG
32 #include "meson-config.h"
35 struct _PidginAboutDialog
{
38 GtkWidget
*close_button
;
39 GtkWidget
*application_name
;
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 /******************************************************************************
60 *****************************************************************************/
62 _pidgin_about_dialog_load_application_name(PidginAboutDialog
*about
) {
63 gchar
*label
= g_strdup_printf(
69 gtk_label_set_text(GTK_LABEL(about
->application_name
), label
);
75 _pidgin_about_dialog_load_main_page(PidginAboutDialog
*about
) {
77 GInputStream
*istream
= NULL
;
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
,
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
);
97 gtk_text_buffer_get_start_iter(about
->main_buffer
, &start
);
99 talkatu_markdown_buffer_insert_markdown(
100 TALKATU_MARKDOWN_BUFFER(about
->main_buffer
),
106 g_string_free(str
, TRUE
);
108 g_input_stream_close(istream
, NULL
, NULL
);
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
,
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
, §ion_iter
, NULL
);
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
, §ion_iter
);
175 0, json_array_get_string_element(people
, idx
),
182 g_list_free(sections
);
185 g_object_unref(G_OBJECT(parser
));
187 g_input_stream_close(istream
, NULL
, NULL
);
191 _pidgin_about_dialog_load_developers(PidginAboutDialog
*about
) {
192 _pidgin_about_dialog_load_json(about
->developers_store
, "developers");
196 _pidgin_about_dialog_load_translators(PidginAboutDialog
*about
) {
197 _pidgin_about_dialog_load_json(about
->translators_store
, "languages");
201 _pidgin_about_dialog_add_build_args(
202 PidginAboutDialog
*about
,
204 const gchar
*build_args
206 GtkTreeIter section
, value
;
207 gchar
**splits
= NULL
;
208 gchar
*markup
= NULL
;
211 markup
= g_strdup_printf("<span font-weight=\"bold\">%s</span>", title
);
212 gtk_tree_store_append(about
->build_info_store
, §ion
, NULL
);
214 about
->build_info_store
,
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') {
230 gtk_tree_store_append(about
->build_info_store
, &value
, §ion
);
232 about
->build_info_store
,
234 0, value_split
[0] ? value_split
[0] : "",
235 1, value_split
[1] ? value_split
[1] : "",
239 g_strfreev(value_split
);
246 _pidgin_about_dialog_build_info_add_version(
248 GtkTreeIter
*section
,
255 gchar
*version
= g_strdup_printf("%u.%u.%u", major
, minor
, micro
);
257 gtk_tree_store_append(store
, &item
, section
);
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
, §ion
, NULL
);
279 about
->build_info_store
,
286 /* add the commit hash */
287 gtk_tree_store_append(about
->build_info_store
, &item
, §ion
);
289 about
->build_info_store
,
296 /* add the purple version */
297 _pidgin_about_dialog_build_info_add_version(
298 about
->build_info_store
,
301 PURPLE_MAJOR_VERSION
,
302 PURPLE_MINOR_VERSION
,
306 /* add the glib version */
307 _pidgin_about_dialog_build_info_add_version(
308 about
->build_info_store
,
316 /* add the gtk version */
317 _pidgin_about_dialog_build_info_add_version(
318 about
->build_info_store
,
328 _pidgin_about_dialog_load_runtime_info(PidginAboutDialog
*about
) {
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
, §ion
, NULL
);
339 about
->build_info_store
,
346 /* add the purple version */
347 _pidgin_about_dialog_build_info_add_version(
348 about
->build_info_store
,
351 purple_major_version
,
352 purple_minor_version
,
356 /* add the glib version */
357 _pidgin_about_dialog_build_info_add_version(
358 about
->build_info_store
,
366 /* add the gtk version */
367 _pidgin_about_dialog_build_info_add_version(
368 about
->build_info_store
,
378 _pidgin_about_dialog_load_build_configuration(PidginAboutDialog
*about
) {
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 /******************************************************************************
389 *****************************************************************************/
391 _pidgin_about_dialog_close(GtkWidget
*b
, gpointer data
) {
392 gtk_widget_destroy(GTK_WIDGET(data
));
395 /******************************************************************************
397 *****************************************************************************/
398 G_DEFINE_TYPE(PidginAboutDialog
, pidgin_about_dialog
, GTK_TYPE_DIALOG
);
401 pidgin_about_dialog_class_init(PidginAboutDialogClass
*klass
) {
402 GtkWidgetClass
*widget_class
= GTK_WIDGET_CLASS(klass
);
404 gtk_widget_class_set_template_from_resource(
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
);
430 pidgin_about_dialog_init(PidginAboutDialog
*about
) {
431 gtk_widget_init_template(GTK_WIDGET(about
));
433 /* wire up the close button */
437 G_CALLBACK(_pidgin_about_dialog_close
),
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
));
461 pidgin_about_dialog_new(void) {
462 GtkWidget
*about
= NULL
;
464 about
= g_object_new(
465 PIDGIN_TYPE_ABOUT_DIALOG
,
466 "title", "About Pidgin",