source: trunk/third/gnome-desktop/gnome-about/gnome-about.c @ 20867

Revision 20867, 28.5 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20866, which included commits to RCS files with non-trunk default branches.
Line 
1/* gnome-about.c: Super Funky Dope gnome about window.
2 *
3 * Copyright (C) 2002, Sun Microsystems, Inc.
4 * Copyright (C) 2003, Kristian Rietveld
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307, USA.
20 *
21 * Authors:
22 *      Glynn Foster <glynn.foster@sun.com>
23 *      Mark McLoughlin <mark@skynet.ie>
24 *      Kristian Rietveld <kris@gtk.org>
25 *      Jeff Waugh <jdub@perkypants.org>
26 *      Malcolm Tredinnick <malcolm@commsecure.com.au>
27 */
28
29#include <config.h>
30
31
32#include <libgnome/libgnome.h>
33#include <libgnomeui/libgnomeui.h>
34#include <libgnomecanvas/libgnomecanvas.h>
35
36/* for parsing gnome-version.xml */
37#include <libxml/tree.h>
38#include <libxml/parser.h>
39
40/* for readdir */
41#include <sys/types.h>
42#include <string.h>
43
44#include <dirent.h>
45#include <errno.h>
46#include <time.h>
47
48#include "contributors.h"
49
50/* pick some good defaults */
51static gdouble canvas_width = 550.0;
52static gdouble canvas_height = 350.0;
53
54
55static char             **introduction_messages = NULL;
56static GnomeCanvasItem   *subheader = NULL;
57static gdouble            version_info_height = 0.0;
58static gint               contrib_i = 0;
59static gint              *contrib_order;
60
61/* funky animations */
62typedef struct {
63        GnomeCanvas *canvas;
64        GnomeCanvasItem *item;
65} AnimationData;
66
67/* contributors */
68static gboolean   display_contributors (gpointer data);
69
70static gboolean
71animate_contributor (gpointer data)
72{
73        AnimationData *ani_data = (AnimationData *)data;
74        gboolean before_middle;
75        gdouble tmp, tmp2, y;
76        guint color, tmpcolor;
77        gdouble size;
78
79        g_object_get (ani_data->item,
80                      "text_width", &tmp,
81                      "text_height", &tmp2,
82                      "fill_color_rgba", &color,
83                      "size_points", &size,
84                      NULL);
85
86        y = ani_data->item->parent->y1;
87
88        /* ugh */
89        g_object_set (GNOME_CANVAS_GROUP (ani_data->item->parent)->item_list->data,
90                      "x1", -1.0 * (tmp / 2.0 + 3.0),
91                      "y1", -1.0 * (tmp2 / 2.0 + 3.0),
92                      "x2", tmp / 2.0 + 3.0,
93                      "y2", tmp2 / 2.0 + 3.0,
94                      NULL);
95
96        before_middle = 130.0 + ((canvas_height - 130.0 - version_info_height - tmp2) / 2.0) < y;
97
98        /* update the color */
99        tmpcolor = color & 0xff;
100        tmpcolor += before_middle ? -6 : 6;
101        size += before_middle ? 1.0 : -1.0;
102        size = MAX (0.0, size);
103        color = GNOME_CANVAS_COLOR_A (tmpcolor, tmpcolor, tmpcolor, tmpcolor);
104
105        g_object_set (ani_data->item,
106                      "fill_color_rgba", color,
107                      "size_points", size,
108                      NULL);
109
110        /* move damnit!! */
111        gnome_canvas_item_move (ani_data->item->parent, 0.0, -2.5);
112
113        y -= 2.5;
114
115        gnome_canvas_update_now (ani_data->canvas);
116
117        /* time for a new one ??? */
118        if (y <= 130.0) {
119                display_contributors (ani_data->canvas);
120                g_free (ani_data);
121                return FALSE;
122        }
123
124        return TRUE;
125}
126
127static gboolean
128canvas_button_press_event (GtkWidget      *widget,
129                           GdkEventButton *event,
130                           gpointer        user_data)
131{
132        gchar *text;
133
134        /* the links should still be clickable */
135        if (event->y <= 80.0)
136                return FALSE;
137
138        if (contrib_i >= (G_N_ELEMENTS (contributors) - 1))
139                text = g_strdup_printf ("<b>%s</b>", _("The End!"));
140        else {
141                text = g_strdup_printf ("<b>%s</b>",
142                                        contributors[contrib_order[contrib_i]]);
143                contrib_i++;
144        }
145
146        gnome_canvas_item_set (GNOME_CANVAS_ITEM (user_data),
147                               "markup", text,
148                               NULL);
149        g_free (text);
150
151        return TRUE;
152}
153
154static gboolean
155display_contributors (gpointer data)
156{
157        GnomeCanvas *canvas = GNOME_CANVAS (data);
158        AnimationData *ani_data;
159
160        static GnomeCanvasItem *contributor = NULL;
161        static GnomeCanvasItem *contributor_rect = NULL;
162        static GnomeCanvasItem *contributor_text = NULL;
163
164        if (contrib_i >= (G_N_ELEMENTS (contributors) - 1)) {
165                g_signal_handlers_disconnect_by_func (canvas,
166                                                      canvas_button_press_event,
167                                                      contributor_text);
168                return FALSE;
169        }
170
171        if (!contributor) {
172                gchar *text;
173
174                contributor =
175                        gnome_canvas_item_new (GNOME_CANVAS_GROUP (canvas->root),
176                                               gnome_canvas_group_get_type (),
177                                               NULL);
178
179                contributor_rect =
180                        gnome_canvas_item_new (GNOME_CANVAS_GROUP (contributor),
181                                               gnome_canvas_rect_get_type (),
182                                               "fill_color", "White",
183                                               NULL);
184
185                text = g_strdup_printf ("<b>%s</b>",
186                                        contributors[contrib_order[contrib_i]]);
187                contributor_text =
188                        gnome_canvas_item_new (GNOME_CANVAS_GROUP (contributor),
189                                               gnome_canvas_text_get_type (),
190                                               "markup", text,
191                                               "anchor", GTK_ANCHOR_CENTER,
192                                               "fill_color_rgba", 0xffffffff,
193                                               NULL);
194                g_free (text);
195
196                g_signal_connect (canvas, "button_press_event",
197                                  G_CALLBACK (canvas_button_press_event),
198                                  contributor_text);
199
200                gnome_canvas_item_move (contributor,
201                                        canvas_width / 2.0,
202                                        canvas_height - version_info_height);
203        } else {
204                gchar *text;
205
206                text = g_strdup_printf ("<b>%s</b>",
207                                        contributors[contrib_order[contrib_i]]);
208                gnome_canvas_item_set (contributor_text,
209                                       "markup", text,
210                                       "fill_color_rgba", 0xffffffff,
211                                       "size_points", 0.0,
212                                       NULL);
213                g_free (text);
214
215                gnome_canvas_item_move (contributor, 0.0,
216                                        canvas_height - version_info_height - contributor->y1);
217        }
218
219        ani_data = g_new0 (AnimationData, 1);
220
221        ani_data->canvas = canvas;
222        ani_data->item = contributor_text;
223
224        g_timeout_add (75, animate_contributor, ani_data);
225        contrib_i++;
226
227        return FALSE;
228}
229
230/* subheader */
231static gboolean
232display_subheader (gpointer data)
233{
234        GnomeCanvas *canvas = GNOME_CANVAS (data);
235        static gboolean first = TRUE;
236
237        if (first) {
238                guint color = GNOME_CANVAS_COLOR_A (0xff, 0xff, 0xff, 0xff);
239
240                gnome_canvas_item_set (subheader,
241                                       "fill_color_rgba", color,
242                                       NULL);
243                gnome_canvas_item_show (subheader);
244                gnome_canvas_update_now (canvas);
245
246                first = FALSE;
247        } else {
248                guint color;
249                guint tmp;
250
251                g_object_get (subheader, "fill_color_rgba", &color, NULL);
252                tmp = color & 0xFF;
253
254                if (tmp < 15) {
255                        /* make sure it's black */
256                        color = GNOME_CANVAS_COLOR_A (0x0, 0x0, 0x0, 0x0);
257                        g_object_set (subheader,
258                                      "fill_color_rgba", color, NULL);
259                        gnome_canvas_update_now (canvas);
260
261                        display_contributors (canvas);
262
263                        return FALSE;
264                }
265
266                tmp -= 15;
267                color = GNOME_CANVAS_COLOR_A (tmp, tmp, tmp, tmp);
268                g_object_set (subheader, "fill_color_rgba", color, NULL);
269                gnome_canvas_update_now (canvas);
270        }
271
272        return TRUE;
273}
274
275/* introduction messages */
276static gboolean    display_introduction_message (gpointer data);
277
278static gboolean
279animate_text (gpointer data)
280{
281        AnimationData *ani_data = (AnimationData *)data;
282
283        gnome_canvas_item_move (ani_data->item->parent, 0.0, -10.0);
284
285        if (ani_data->item->parent->y1 <= 120.0) {
286                g_timeout_add (5 * 1000,
287                               display_introduction_message,
288                               ani_data->canvas);
289                g_free (ani_data);
290                return FALSE;
291        }
292
293        return TRUE;
294}
295
296static gboolean
297display_introduction_message (gpointer data)
298{
299        GnomeCanvas *canvas = GNOME_CANVAS (data);
300        AnimationData *ani_data;
301
302        static GnomeCanvasItem *intro = NULL;
303        static GnomeCanvasItem *intro_rect = NULL;
304        static GnomeCanvasItem *intro_text = NULL;
305        static gint intro_i = 0;
306
307        if (!introduction_messages || !introduction_messages[intro_i]) {
308                /* just hide the intro now, the canvas will
309                 * take care of disposing it (if we do an _unref here
310                 * it crashes for some reason, too lazy to find out why)
311                 */
312                if (intro)
313                        gnome_canvas_item_hide (GNOME_CANVAS_ITEM (intro));
314                intro = NULL;
315
316                g_timeout_add (100, display_subheader, canvas);
317                return FALSE;
318        }
319
320        if (!intro_text) {
321                gdouble tmp;
322
323                intro =
324                        gnome_canvas_item_new (GNOME_CANVAS_GROUP (canvas->root),
325                                               gnome_canvas_group_get_type (),
326                                               NULL);
327
328                intro_rect =
329                        gnome_canvas_item_new (GNOME_CANVAS_GROUP (intro),
330                                               gnome_canvas_rect_get_type (),
331                                               "fill_color", "White",
332                                               "x1", -4.0,
333                                               "y1", -4.0,
334                                               "x2", 304.0,
335                                               "y2", 84.0,
336                                               NULL);
337
338                intro_text =
339                        gnome_canvas_item_new (GNOME_CANVAS_GROUP (intro),
340                                               gnome_canvas_rich_text_get_type (),
341                                               "text", introduction_messages[intro_i],
342                                                "editable", FALSE,
343                                               /* FIXME */
344                                               "width", 300.0,
345                                               "height", 80.0,
346                                               "grow_height", TRUE,
347                                               "cursor_visible", FALSE,
348                                               NULL);
349
350                g_object_get (intro_text, "height", &tmp, NULL);
351                gnome_canvas_item_move (intro,
352                                        (canvas_width - 300.0) / 2.0,
353                                         canvas_height - version_info_height - tmp);
354                gnome_canvas_update_now (canvas);
355        } else {
356                gdouble y;
357                gdouble tmp;
358
359                gnome_canvas_item_set (intro_text,
360                                       "text", introduction_messages[intro_i],
361                                       NULL);
362
363                g_object_get (intro_text, "height", &tmp, NULL);
364                y = intro->y1;
365
366                gnome_canvas_item_move (intro,
367                                        0.0,
368                                        canvas_height - version_info_height - y - tmp);
369                gnome_canvas_update_now (canvas);
370        }
371
372        ani_data = g_new0 (AnimationData, 1);
373
374        ani_data->canvas = canvas;
375        ani_data->item = intro_text;
376
377        g_timeout_add (15, animate_text, ani_data);
378        intro_i++;
379
380        return FALSE;
381}
382
383static void
384start_animations (GtkWidget *widget,
385                  gpointer   user_data)
386{
387        display_introduction_message (GNOME_CANVAS (widget));
388}
389
390/* loading funky stuff */
391static void
392show_error_dialog (const gchar *message)
393{
394        GtkWidget *dialog;
395
396        dialog = gtk_message_dialog_new (NULL,
397                                         GTK_DIALOG_DESTROY_WITH_PARENT,
398                                         GTK_MESSAGE_ERROR,
399                                         GTK_BUTTONS_CLOSE,
400                                         message);
401
402        gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
403        gtk_widget_show (dialog);
404
405        gtk_dialog_run (GTK_DIALOG (dialog));
406
407        gtk_widget_destroy (dialog);
408}
409
410static GdkPixbuf *
411load_random_header (void)
412{
413        GdkPixbuf *pixbuf;
414        GList *files = NULL, *i;
415        GError *error = NULL;
416        gchar *text;
417        gchar *directory;
418        gint selected;
419
420        DIR *dir;
421        struct dirent *d;
422
423        directory = gnome_program_locate_file (NULL,
424                                               GNOME_FILE_DOMAIN_DATADIR,
425                                               "gnome-about/headers/",
426                                               TRUE, NULL);
427        if (!directory) {
428                show_error_dialog (_("Could not locate the directory with header images."));
429
430                return NULL;
431        }
432
433        dir = opendir (directory);
434        if (!dir) {
435                char *message;
436
437                message = g_strdup_printf (_("Failed to open directory with header images: %s"),
438                                           strerror (errno));
439                show_error_dialog (message);
440                g_free (message);
441                g_free (directory);
442
443                return NULL;
444        }
445
446        while ((d = readdir (dir))) {
447                if (g_str_has_suffix (d->d_name, ".gif") ||
448                    g_str_has_suffix (d->d_name, ".png"))
449                        files = g_list_prepend (files, g_strdup (d->d_name));
450        }
451
452        closedir (dir);
453
454        selected = g_random_int_range (0, g_list_length (files));
455
456        text = g_strdup_printf ("%s/%s", directory,
457                                (char *)g_list_nth_data (files, selected));
458        g_free (directory);
459
460        pixbuf = gdk_pixbuf_new_from_file (text, &error);
461        g_free (text);
462
463        for (i = files; i; i = i->next)
464                g_free (i->data);
465        g_list_free (files);
466
467        if (error) {
468                char *message;
469
470                message = g_strdup_printf (_("Unable to load header image: %s"),
471                                           error->message);
472                show_error_dialog (message);
473
474                g_free (message);
475                g_error_free (error);
476
477                return NULL;
478        }
479
480        return pixbuf;
481}
482
483static GdkPixbuf *
484load_button (void)
485{
486        gchar *file;
487        GdkPixbuf *pixbuf;
488        GError *error = NULL;
489
490        file = gnome_program_locate_file (NULL,
491                                          GNOME_FILE_DOMAIN_DATADIR,
492                                          "gnome-about/gnome-64.gif",
493                                          TRUE, NULL);
494        if (!file) {
495                show_error_dialog (_("Could not locate the GNOME logo button."));
496
497                return NULL;
498        }
499
500        pixbuf = gdk_pixbuf_new_from_file (file, &error);
501        if (error) {
502                char *message;
503
504                message = g_strdup_printf (_("Unable to load '%s': %s"),
505                                           file,
506                                           error->message);
507                g_free (file);
508                show_error_dialog (message);
509
510                g_free (message);
511                g_error_free (error);
512
513                return NULL;
514        }
515
516        g_free (file);
517
518        return pixbuf;
519}
520
521/* href item impl */
522typedef struct {
523        GnomeCanvasItem *item;
524
525        const gchar *text;
526        const gchar *url;
527} HRefItem;
528
529static gboolean
530href_item_event_callback (GnomeCanvasItem *item,
531                          GdkEvent        *event,
532                          gpointer         user_data)
533{
534        HRefItem *href = (HRefItem *) user_data;
535
536        switch (event->type) {
537        case GDK_ENTER_NOTIFY: {
538                GdkCursor *cursor;
539
540                cursor = gdk_cursor_new (GDK_HAND2);
541
542                gdk_window_set_cursor (GTK_WIDGET (item->canvas)->window, cursor);
543                gdk_cursor_unref (cursor);
544        }
545                break;
546        case GDK_LEAVE_NOTIFY:
547                gdk_window_set_cursor (GTK_WIDGET (item->canvas)->window, NULL);
548                break;
549
550        case GDK_BUTTON_PRESS: {
551                GError *error= NULL;
552
553                gnome_url_show (href->url, &error);
554                if (error) {
555                        char *message;
556
557                        message = g_strdup_printf (_("Could not open the address \"%s\": %s"),
558                                                   href->url, error->message);
559                        show_error_dialog (message);
560
561                        g_free (message);
562                        g_error_free (error);
563                }
564
565                return TRUE;
566        }
567
568        default:
569                break;
570        }
571
572        return FALSE;
573}
574
575static HRefItem *
576href_item_new (GnomeCanvasGroup *group,
577               const gchar      *text,
578               const gchar      *url,
579               gdouble          *current_x,
580               gdouble          *current_y)
581{
582        HRefItem *item;
583        gdouble tmp;
584
585        item = g_new0 (HRefItem, 1);
586        item->text = g_strdup (text);
587        item->url = g_strdup (url);
588
589        item->item =
590                gnome_canvas_item_new (group,
591                                       gnome_canvas_text_get_type (),
592                                       "text", text,
593                                       "anchor", GTK_ANCHOR_NW,
594                                       "x", *current_x,
595                                       "y", *current_y,
596                                       "underline", PANGO_UNDERLINE_SINGLE,
597                                       "weight", PANGO_WEIGHT_BOLD,
598                                       "fill_color", "#000000",
599                                       NULL);
600        g_signal_connect (item->item, "event",
601                          G_CALLBACK (href_item_event_callback), item);
602
603        g_object_get (item->item, "text_width", &tmp, NULL);
604        *current_x += tmp + 5.0;
605
606        return item;
607}
608
609static GnomeCanvasItem *
610create_dot (GnomeCanvasGroup *group,
611            gdouble          *current_x,
612            gdouble          *current_y,
613            gdouble           dot_delta)
614{
615        GnomeCanvasItem *item;
616        gdouble tmp;
617
618        item = gnome_canvas_item_new (group,
619                                      gnome_canvas_text_get_type (),
620                                      "text", ".",
621                                      "anchor", GTK_ANCHOR_NW,
622                                      "x", *current_x,
623                                      "y", *current_y - dot_delta,
624                                      "weight", PANGO_WEIGHT_BOLD,
625                                      "fill_color", "#000000",
626                                      NULL);
627
628        g_object_get (item, "text_width", &tmp, NULL);
629        *current_x += tmp + 5.0;
630
631        return item;
632}
633
634/* the canvas */
635static char *
636strip_newlines (const char *str)
637{
638        char **strv;
639        char *tmp;
640
641        if (!str)
642                return NULL;
643
644        strv = g_strsplit (str, "\n", -1);
645        tmp = g_strjoinv (" ", strv);
646        g_strfreev (strv);
647        tmp = g_strchug (tmp);
648
649        return tmp;
650}
651
652/* FIXME: This could possibly be done more smoothly. The locale matching stuff
653 * needs to be abstracted out, since it must be useful in a number of places. */
654
655/* The language selection stuff here is not blindingly efficient, but it is
656 * only done once for a small number of paragraphs, so I (Malcolm) think we can
657 * just pay the penalty rather than going for something more complex.
658 *
659 * The problem we are solving here is, for each paragraph, find the translated
660 * version that matches the highest preference possible from amongst the user's
661 * LC_MESSAGES settings. Note that the translated paragraphs may not appear in
662 * the same order as the LC_MESSAGE preferences, so a certain amount of messing
663 * around is required (in particular, we cannot quit after finding the first
664 * match).
665 */
666
667/* FIXME: this code is atrocious */
668
669static void
670get_description_messages (xmlNodePtr node)
671{
672        xmlNodePtr paras;
673        GSList *list = NULL, *l;
674        const GList *langs = NULL;
675        gint i;
676        gboolean started = FALSE;
677        char *best_value = NULL;
678
679        langs = gnome_i18n_get_language_list ("LC_MESSAGES");
680        paras = node->children;
681
682        while (paras) {
683                while (paras) {
684                        char *value = (char *)xmlNodeGetContent (paras);
685                        char *tmp;
686                        xmlChar *cur, *best = NULL;
687                        const GList *t;
688
689                        if (paras->type == XML_ELEMENT_NODE &&
690                                        xmlStrEqual (paras->name, "p") &&
691                                        value && value[0]) {
692                                cur = xmlNodeGetLang (paras);
693
694                                tmp = strip_newlines (value);
695
696                                if (!started) {
697                                        started = TRUE;
698                                        if (!cur) {
699                                                best = xmlCharStrdup ("C");
700                                        }
701                                        else {
702                                                best = xmlStrdup (cur);
703                                        }
704                                        best_value = g_strdup (tmp);
705                                }
706                                else {
707                                        if (!cur || xmlStrEqual (cur, "C")) {
708                                                break;
709                                        }
710                                        /* See if the current lanaguage occurs
711                                         * earlier than the previous best. */
712                                        for (t = langs; t; t = t->next) {
713                                                if (xmlStrEqual (t->data,
714                                                                best)) {
715                                                        break;
716                                                }
717                                                else if (xmlStrEqual (t->data,
718                                                                        cur)) {
719                                                        xmlFree (best);
720                                                        best = xmlStrdup (cur);
721                                                        g_free (best_value);
722                                                        best_value = g_strdup (tmp);
723                                                        /* If this is the first
724                                                         * language on the
725                                                         * list of choices,
726                                                         * stop. We are not
727                                                         * going to go any
728                                                         * better. */
729                                                        if (t == langs) {
730                                                                break;
731                                                        }
732                                                }
733                                        }
734                                }
735                                g_free (tmp);
736                                xmlFree (cur);
737                                xmlFree (best);
738                        }
739
740                        paras = paras->next;
741                        xmlFree (value);
742                }
743                list = g_slist_prepend (list, best_value);
744                started = FALSE;
745        }
746
747        list = g_slist_reverse (list);
748
749        introduction_messages = g_new (char *, g_slist_length (list) + 1);
750
751        for (i = 0, l = list; l; l = l->next, i++)
752                introduction_messages[i] = l->data;
753
754        introduction_messages[i] = NULL;
755
756        g_slist_free (list);
757}
758
759static char*
760create_date_string (const char *value)
761{
762        char  *result;
763        GDate *date;
764        int    day;
765        int    month;
766        int    year;
767
768        /* YYYY-MM-DD */
769        if (sscanf (value, "%d-%d-%d", &year, &month, &day) < 3)
770                return NULL;
771
772        date = g_date_new ();
773
774        g_date_set_dmy (date, day, month, year);
775
776        result = g_new0 (char, 24);
777        g_date_strftime (result, 24, "%x", date);
778
779        g_date_free (date);
780
781        return result;
782}
783
784static void
785display_version_info (GnomeCanvasGroup *group)
786{
787        xmlDocPtr about;
788        xmlNodePtr node;
789        xmlNodePtr bits;
790
791        gchar *file;
792
793        char *platform = NULL;
794        char *minor = NULL;
795        char *micro = NULL;
796        char *version_string = NULL;
797        char *distributor_string = NULL;
798        char *build_date_string = NULL;
799        char *text = NULL;
800
801        GnomeCanvasItem *info;
802        gdouble height = 0.0;
803
804        file = gnome_program_locate_file (NULL,
805                                          GNOME_FILE_DOMAIN_DATADIR,
806                                          "gnome-about/gnome-version.xml",
807                                          TRUE, NULL);
808        if (!file) {
809                show_error_dialog (_("Could not locate the file with GNOME version information."));
810        }
811
812        about = xmlParseFile (file);
813        g_free (file);
814
815        if (!about)
816                return;
817
818        node = about->children;
819
820        if (g_ascii_strcasecmp (node->name, "gnome-version")) {
821                xmlFreeDoc (about);
822                return;
823        }
824
825        bits = node->children;
826
827        while (bits) {
828                char *name = (char *)bits->name;
829                char *value;
830
831                if (!g_ascii_strcasecmp (name, "description"))
832                        get_description_messages (bits);
833
834                value = (char *)xmlNodeGetContent (bits);
835
836                if (!g_ascii_strcasecmp (name, "platform")
837                    && value && value[0])
838                        platform = g_strdup (value);
839                if (!g_ascii_strcasecmp (name, "minor") && value && value[0])
840                        minor = g_strdup (value);
841                if (!g_ascii_strcasecmp (name, "micro") && value && value[0])
842                        micro = g_strdup (value);
843                if (!g_ascii_strcasecmp (name, "distributor") && value && value[0])
844                        distributor_string = g_strdup (value);
845                if (!g_ascii_strcasecmp (name, "date") && value && value[0])
846                        build_date_string = create_date_string (value);
847
848                bits = bits->next;
849                xmlFree (value);
850        }
851
852        xmlFreeDoc (about);
853
854        if (!minor)
855                version_string = g_strconcat (platform, NULL);
856
857        if (!version_string && !micro)
858                version_string = g_strconcat (platform, ".", minor, NULL);
859
860        if (!version_string)
861                version_string = g_strconcat (platform, ".", minor, ".",
862                                              micro, NULL);
863
864        g_free (platform);
865        g_free (minor);
866        g_free (micro);
867
868        info = gnome_canvas_item_new (group,
869                                      gnome_canvas_group_get_type (),
870                                      "x", 10.0,
871                                      NULL);
872
873        if (version_string && version_string[0]) {
874                gdouble tmp;
875                GnomeCanvasItem *item;
876
877                text = g_strdup_printf ("<b>%s: </b>%s",
878                                        _("Version"), version_string);
879                item = gnome_canvas_item_new (GNOME_CANVAS_GROUP (info),
880                                              gnome_canvas_text_get_type (),
881                                              "markup", text,
882                                              "anchor", GTK_ANCHOR_NW,
883                                              "x", 0.0,
884                                              "y", height,
885                                              NULL);
886                g_free (text);
887
888                g_object_get (item, "text_height", &tmp, NULL);
889                height += tmp + 4.0;
890        }
891
892        if (distributor_string && distributor_string[0]) {
893                gdouble tmp;
894                GnomeCanvasItem *item;
895
896                text = g_strdup_printf ("<b>%s: </b>%s",
897                                        _("Distributor"), distributor_string);
898                item = gnome_canvas_item_new (GNOME_CANVAS_GROUP (info),
899                                              gnome_canvas_text_get_type (),
900                                              "markup", text,
901                                              "anchor", GTK_ANCHOR_NW,
902                                              "x", 0.0,
903                                              "y", height,
904                                              NULL);
905                g_free (text);
906
907                g_object_get (item, "text_height", &tmp, NULL);
908                height += tmp + 4.0;
909        }
910
911        if (build_date_string && build_date_string[0]) {
912                gdouble tmp;
913                GnomeCanvasItem *item;
914
915                text = g_strdup_printf ("<b>%s: </b>%s",
916                                        _("Build Date"), build_date_string);
917                item = gnome_canvas_item_new (GNOME_CANVAS_GROUP (info),
918                                              gnome_canvas_text_get_type (),
919                                              "markup", text,
920                                              "anchor", GTK_ANCHOR_NW,
921                                              "x", 0.0,
922                                              "y", height,
923                                              NULL);
924                g_free (text);
925
926                g_object_get (item, "text_height", &tmp, NULL);
927                height += tmp + 4.0;
928        }
929
930        g_free (version_string);
931        g_free (distributor_string);
932        g_free (build_date_string);
933
934        gnome_canvas_item_set (info, "y", canvas_height - height, NULL);
935        version_info_height = height;
936}
937
938static GtkWidget *
939create_canvas (void)
940{
941        GdkColor color = {0, 0xffff, 0xffff, 0xffff};
942        GtkWidget *canvas;
943
944        HRefItem *href;
945        gchar *text;
946
947        GnomeCanvasItem *item;
948        GnomeCanvasGroup *root;
949        GnomeCanvasPoints *points;
950
951        GdkPixbuf *header;
952        GdkPixbuf *button;
953
954        gdouble current_x;
955        gdouble current_y;
956        gdouble dot_delta;
957        gdouble tmp;
958
959        /* set up a canvas */
960        canvas = gnome_canvas_new ();
961
962        gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas), 0, 0,
963                                        canvas_width, canvas_height);
964        gtk_widget_set_size_request (canvas, canvas_width, canvas_height);
965
966        gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET (canvas)),
967                                  &color, TRUE, TRUE);
968
969        /* euhm? */
970        gtk_widget_modify_bg (GTK_WIDGET (canvas), GTK_STATE_NORMAL, &color);
971
972        root = GNOME_CANVAS_GROUP (GNOME_CANVAS (canvas)->root);
973
974        /* the header */
975        header = load_random_header ();
976        if (!header)
977                /* emergency stop complete with leaks */
978                return NULL;
979
980        item = gnome_canvas_item_new (root,
981                                      gnome_canvas_pixbuf_get_type (),
982                                      "x", 0.0,
983                                      "y", 0.0,
984                                      "pixbuf", header,
985                                      NULL);
986
987        /* load button logo in advance, we need it's size */
988        button = load_button ();
989        if (!button)
990                /* emergency stop complete with leaks */
991                return NULL;
992
993        /* and a coulple o' links */
994        current_x = 10.0 + (gdouble)gdk_pixbuf_get_width (button) + 10.0;
995        current_y = (gdouble)gdk_pixbuf_get_height (header) + 5.0;
996
997        href = href_item_new (root,
998                              _("About GNOME"),
999                              "http://www.gnome.org/about/",
1000                              &current_x, &current_y);
1001
1002        /* make a nice guess for the dot delta */
1003        g_object_get (href->item, "text_height", &tmp, NULL);
1004        dot_delta = tmp / 4.5;
1005
1006        /* draw a dot */
1007        item = create_dot (root, &current_x, &current_y, dot_delta);
1008
1009        /* and more items on a likewise way.
1010         */
1011        href = href_item_new (root,
1012                              _("News"),
1013                              "http://news.gnome.org",
1014                              &current_x, &current_y);
1015        item = create_dot (root, &current_x, &current_y, dot_delta);
1016
1017        /*
1018         * FIXME: this used to be 'users' and it would be great to make it
1019         * users again once there is a user-centric page on the we site.
1020         */
1021        href = href_item_new (root,
1022                              _("Software"),
1023                              "http://www.gnome.org/softwaremap",
1024                              &current_x, &current_y);
1025        item = create_dot (root, &current_x, &current_y, dot_delta);
1026
1027        href = href_item_new (root,
1028                              _("Developers"),
1029                              "http://developer.gnome.org/",
1030                              &current_x, &current_y);
1031        item = create_dot (root, &current_x, &current_y, dot_delta);
1032
1033        href = href_item_new (root,
1034                              _("Friends of GNOME"),
1035                              "http://www.gnome.org/friends/",
1036                              &current_x, &current_y);
1037        item = create_dot (root, &current_x, &current_y, dot_delta);
1038
1039        href = href_item_new (root,
1040                              _("Contact"),
1041                              "http://www.gnome.org/contact/",
1042                              &current_x, &current_y);
1043
1044        /* resize */
1045        canvas_width = current_x;
1046        gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas), 0, 0,
1047                                        canvas_width, canvas_height);
1048        gtk_widget_set_size_request (GTK_WIDGET (canvas),
1049                                     canvas_width, canvas_height);
1050
1051        /* and a nice black stripe */
1052        points = gnome_canvas_points_new (2);
1053        points->coords[0] = 0.0;
1054        points->coords[1] = gdk_pixbuf_get_height (header);
1055        points->coords[2] = current_x;
1056        points->coords[3] = gdk_pixbuf_get_height (header);
1057
1058        item = gnome_canvas_item_new (root,
1059                                      gnome_canvas_line_get_type (),
1060                                      "points", points,
1061                                      "fill_color", "#666666",
1062                                      "width_pixels", 1,
1063                                      NULL);
1064
1065        gnome_canvas_points_free (points);
1066
1067        /* the gnome button logo */
1068        item = gnome_canvas_item_new (root,
1069                                      gnome_canvas_pixbuf_get_type (),
1070                                      "x", 10.0,
1071                                      "y", 10.0,
1072                                      "pixbuf", button,
1073                                      NULL);
1074
1075        /* and some introduction text */
1076        text = g_strdup_printf ("<big><big><b>%s</b></big></big>",
1077                                _("Welcome to the GNOME Desktop"));
1078        item = gnome_canvas_item_new (root,
1079                                      gnome_canvas_text_get_type (),
1080                                      "markup", text,
1081                                      "anchor", GTK_ANCHOR_NW,
1082                                      "y", current_y + 25.0,
1083                                      "fill_color", "#000000",
1084                                      NULL);
1085        g_free (text);
1086
1087        g_object_get (item, "text_width", &tmp, NULL);
1088        gnome_canvas_item_set (item,
1089                               "x", (canvas_width - tmp) / 2.0,
1090                               NULL);
1091
1092
1093        text = g_strdup_printf ("<big><b>%s</b></big>",
1094                                _("Brought to you by:"));
1095        item = gnome_canvas_item_new (root,
1096                                      gnome_canvas_text_get_type (),
1097                                      "markup", text,
1098                                      "anchor", GTK_ANCHOR_NW,
1099                                      "y", current_y + 55.0,
1100                                      NULL);
1101        subheader = item;
1102        gnome_canvas_item_hide (item);
1103        g_free (text);
1104
1105        g_object_get (item, "text_width", &tmp, NULL);
1106        gnome_canvas_item_set (item,
1107                               "x", (canvas_width - tmp) / 2.0,
1108                               NULL);
1109
1110        /* and the version info */
1111        display_version_info (root);
1112
1113        /* pfff done */
1114        return canvas;
1115}
1116
1117/* the dialog */
1118static gboolean
1119quit_callback (GtkWidget *widget,
1120               gpointer   user_data)
1121{
1122        gtk_main_quit ();
1123
1124        return FALSE;
1125}
1126
1127static void
1128response_callback (GtkDialog *dialog,
1129                   int        reponse_id,
1130                   gpointer   user_data)
1131{
1132        if (reponse_id == GTK_RESPONSE_CLOSE)
1133                quit_callback (GTK_WIDGET (dialog), NULL);
1134}
1135
1136static GtkWidget *
1137create_about_dialog (void)
1138{
1139        GtkWidget *dialog;
1140        GtkWidget *canvas;
1141
1142        dialog = gtk_dialog_new_with_buttons (_("About the GNOME Desktop"),
1143                                              NULL, 0,
1144                                              GTK_STOCK_CLOSE,
1145                                              GTK_RESPONSE_CLOSE,
1146                                              NULL);
1147        gtk_dialog_set_default_response (GTK_DIALOG (dialog),
1148                                         GTK_RESPONSE_CLOSE);
1149
1150        g_signal_connect (dialog, "delete_event",
1151                          G_CALLBACK (quit_callback), NULL);
1152        g_signal_connect (dialog, "response",
1153                          G_CALLBACK (response_callback), NULL);
1154
1155        gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
1156        g_object_set (dialog,
1157                      "allow_shrink", FALSE,
1158                      "allow_grow", FALSE,
1159                      NULL);
1160
1161        canvas = create_canvas ();
1162        if (!canvas) {
1163                gtk_widget_destroy (dialog);
1164                return NULL;
1165        }
1166
1167        /* start animations once the canvas has been mapped */
1168        g_signal_connect (canvas, "map",
1169                          G_CALLBACK (start_animations), NULL);
1170
1171        gtk_container_set_border_width
1172                (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), GNOME_PAD_SMALL);
1173        gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
1174                            canvas, TRUE, TRUE, 0);
1175
1176        return dialog;
1177}
1178
1179static void
1180generate_randomness ()
1181{
1182        gint i;
1183        gint random_number;
1184        gint tmp;
1185        gint num_contributors;
1186        GRand *generator;
1187
1188        generator = g_rand_new ();
1189
1190        num_contributors = G_N_ELEMENTS (contributors);
1191
1192        contrib_order = g_malloc (num_contributors * sizeof (gint));
1193
1194        for (i = 0; i < num_contributors; i++) {
1195                contrib_order[i]=i;
1196        }
1197
1198        for (i = 0; i < num_contributors; i++) {
1199                random_number = g_rand_int_range (generator, i,
1200                                                  num_contributors);
1201                tmp = contrib_order[i];
1202                contrib_order[i] = contrib_order[random_number];
1203                contrib_order[random_number] = tmp;
1204        }
1205
1206        g_rand_free (generator);
1207}
1208               
1209
1210/* main */
1211int
1212main (int argc, char **argv)
1213{
1214        GtkWidget *dialog;
1215
1216        bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
1217        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1218        textdomain (GETTEXT_PACKAGE);
1219
1220        gnome_program_init ("gnome-about", "1.0",
1221                            LIBGNOMEUI_MODULE,
1222                            argc, argv, NULL);
1223        gnome_window_icon_set_default_from_file (GNOME_ICONDIR
1224                        "/gnome-logo-icon-transparent.png");
1225
1226        dialog = create_about_dialog ();
1227        if (!dialog)
1228                return -1;
1229
1230        generate_randomness ();
1231
1232        gtk_widget_show_all (dialog);
1233
1234        gtk_main ();
1235
1236        return 0;
1237}
Note: See TracBrowser for help on using the repository browser.