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
);
231 gtk_tree_store_set(about
->build_info_store
, &value
, 0, value_split
[0],
232 1, value_split
[1] ? value_split
[1] : "", -1);
234 g_strfreev(value_split
);
241 _pidgin_about_dialog_build_info_add_version(
243 GtkTreeIter
*section
,
250 gchar
*version
= g_strdup_printf("%u.%u.%u", major
, minor
, micro
);
252 gtk_tree_store_append(store
, &item
, section
);
263 _pidgin_about_dialog_load_build_info(PidginAboutDialog
*about
) {
264 GtkTreeIter section
, item
;
265 gchar
*markup
= NULL
;
267 /* create the section */
268 markup
= g_strdup_printf(
269 "<span font-weight=\"bold\">%s</span>",
270 _("Build Information")
272 gtk_tree_store_append(about
->build_info_store
, §ion
, NULL
);
274 about
->build_info_store
,
281 /* add the commit hash */
282 gtk_tree_store_append(about
->build_info_store
, &item
, §ion
);
284 about
->build_info_store
,
291 /* add the purple version */
292 _pidgin_about_dialog_build_info_add_version(
293 about
->build_info_store
,
296 PURPLE_MAJOR_VERSION
,
297 PURPLE_MINOR_VERSION
,
301 /* add the glib version */
302 _pidgin_about_dialog_build_info_add_version(
303 about
->build_info_store
,
311 /* add the gtk version */
312 _pidgin_about_dialog_build_info_add_version(
313 about
->build_info_store
,
323 _pidgin_about_dialog_load_runtime_info(PidginAboutDialog
*about
) {
325 gchar
*markup
= NULL
;
327 /* create the section */
328 markup
= g_strdup_printf(
329 "<span font-weight=\"bold\">%s</span>",
330 _("Runtime Information")
332 gtk_tree_store_append(about
->build_info_store
, §ion
, NULL
);
334 about
->build_info_store
,
341 /* add the purple version */
342 _pidgin_about_dialog_build_info_add_version(
343 about
->build_info_store
,
346 purple_major_version
,
347 purple_minor_version
,
351 /* add the glib version */
352 _pidgin_about_dialog_build_info_add_version(
353 about
->build_info_store
,
361 /* add the gtk version */
362 _pidgin_about_dialog_build_info_add_version(
363 about
->build_info_store
,
373 _pidgin_about_dialog_load_build_configuration(PidginAboutDialog
*about
) {
375 _pidgin_about_dialog_add_build_args(about
, "Meson Arguments", MESON_ARGS
);
376 #endif /* MESON_ARGS */
378 _pidgin_about_dialog_load_build_info(about
);
379 _pidgin_about_dialog_load_runtime_info(about
);
382 /******************************************************************************
384 *****************************************************************************/
386 _pidgin_about_dialog_close(GtkWidget
*b
, gpointer data
) {
387 gtk_widget_destroy(GTK_WIDGET(data
));
390 /******************************************************************************
392 *****************************************************************************/
393 G_DEFINE_TYPE(PidginAboutDialog
, pidgin_about_dialog
, GTK_TYPE_DIALOG
);
396 pidgin_about_dialog_class_init(PidginAboutDialogClass
*klass
) {
397 GtkWidgetClass
*widget_class
= GTK_WIDGET_CLASS(klass
);
399 gtk_widget_class_set_template_from_resource(
401 "/im/pidgin/Pidgin/About/about.ui"
404 gtk_widget_class_bind_template_child(widget_class
, PidginAboutDialog
, close_button
);
405 gtk_widget_class_bind_template_child(widget_class
, PidginAboutDialog
, application_name
);
406 gtk_widget_class_bind_template_child(widget_class
, PidginAboutDialog
, stack
);
408 gtk_widget_class_bind_template_child(widget_class
, PidginAboutDialog
, main_scrolled_window
);
409 gtk_widget_class_bind_template_child(widget_class
, PidginAboutDialog
, main_buffer
);
411 gtk_widget_class_bind_template_child(widget_class
, PidginAboutDialog
, developers_page
);
412 gtk_widget_class_bind_template_child(widget_class
, PidginAboutDialog
, developers_store
);
413 gtk_widget_class_bind_template_child(widget_class
, PidginAboutDialog
, developers_treeview
);
415 gtk_widget_class_bind_template_child(widget_class
, PidginAboutDialog
, translators_page
);
416 gtk_widget_class_bind_template_child(widget_class
, PidginAboutDialog
, translators_store
);
417 gtk_widget_class_bind_template_child(widget_class
, PidginAboutDialog
, translators_treeview
);
419 gtk_widget_class_bind_template_child(widget_class
, PidginAboutDialog
, build_info_page
);
420 gtk_widget_class_bind_template_child(widget_class
, PidginAboutDialog
, build_info_store
);
421 gtk_widget_class_bind_template_child(widget_class
, PidginAboutDialog
, build_info_treeview
);
425 pidgin_about_dialog_init(PidginAboutDialog
*about
) {
426 gtk_widget_init_template(GTK_WIDGET(about
));
428 /* wire up the close button */
432 G_CALLBACK(_pidgin_about_dialog_close
),
436 /* setup the application name label */
437 _pidgin_about_dialog_load_application_name(about
);
439 /* setup the main page */
440 _pidgin_about_dialog_load_main_page(about
);
442 /* setup the developers stuff */
443 _pidgin_about_dialog_load_developers(about
);
444 gtk_tree_view_expand_all(GTK_TREE_VIEW(about
->developers_treeview
));
446 /* setup the translators stuff */
447 _pidgin_about_dialog_load_translators(about
);
448 gtk_tree_view_expand_all(GTK_TREE_VIEW(about
->translators_treeview
));
450 /* setup the build info page */
451 _pidgin_about_dialog_load_build_configuration(about
);
452 gtk_tree_view_expand_all(GTK_TREE_VIEW(about
->build_info_treeview
));
456 pidgin_about_dialog_new(void) {
457 GtkWidget
*about
= NULL
;
459 about
= g_object_new(
460 PIDGIN_TYPE_ABOUT_DIALOG
,
461 "title", "About Pidgin",