source: trunk/third/gpdf/shell/gpdf.c @ 21437

Revision 21437, 23.7 KB checked in by ghudson, 19 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21436, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*
3 * PDF viewer Bonobo container.
4 *
5 * Author:
6 *   Michael Meeks <michael@ximian.com>
7 */
8#include <aconf.h>
9#include "gpdf-window.h"
10#include "gpdf-uri-input.h"
11#include <stdio.h>
12#include <stdlib.h>
13#include <stddef.h>
14#include <string.h>
15#include <gnome.h>
16#include <bonobo-activation/bonobo-activation.h>
17#include <libbonoboui.h>
18#include <libgnomevfs/gnome-vfs-uri.h>
19#include <libgnomevfs/gnome-vfs-utils.h>
20
21#define noPDF_DEBUG
22#ifdef PDF_DEBUG
23#  define DBG(x) x
24#else
25#  define DBG(x)
26#endif
27
28static GPdfRecentFacade *recent_facade;
29static GPdfURIInput *uri_in;
30/* The list of all open windows */
31static GList *window_list = NULL;
32
33static void gpdf_window_update_window_title (GPdfWindow *);
34
35static gboolean
36create_window (gpointer data)
37{
38        const gchar *fname;
39
40        fname = (const gchar *)data;
41
42        if (fname)
43                gpdf_uri_input_open_shell_arg (uri_in, fname);
44
45        return FALSE;
46}
47
48static gboolean
49handle_cmdline_args (gpointer data)
50{
51        poptContext ctx;
52        const gchar **startup_files;
53
54        ctx = data;
55        startup_files = poptGetArgs (ctx);
56
57        if (startup_files) {
58                gint i;
59                for (i = 0; startup_files [i]; ++i)
60                        g_idle_add (create_window,
61                                    (gchar *) startup_files [i]);
62        } else {
63                g_idle_add (create_window, NULL);
64        }
65       
66        poptFreeContext (ctx);
67
68        return FALSE;
69}
70
71static gint
72no_contents (const GPdfWindow *window, gconstpointer dummy)
73{
74        g_assert (GPDF_IS_WINDOW (window));
75
76        return gpdf_window_has_contents (window)
77                ? -1
78                : 0;
79}
80
81static GPdfWindow *
82find_empty_or_create_new_window (GList *windows)
83{
84        GPdfWindow *window;
85        GList *node;
86
87        node = g_list_find_custom (windows, NULL,
88                                   (GCompareFunc)no_contents);
89        if (node == NULL)
90                window = GPDF_WINDOW (gpdf_window_new ());
91        else
92                window = node->data;
93
94        g_assert (GPDF_IS_WINDOW (window));
95
96        return window;
97}
98
99
100static void
101open_request_handler (GPdfURIInput *in, const char *uri, gpointer user_data)
102{
103        GPdfWindow *window;
104
105        window = find_empty_or_create_new_window (window_list);
106        if (gpdf_window_open (window, uri)) {
107                gpdf_window_update_window_title (window);
108                gtk_widget_show_now (GTK_WIDGET (window));
109        } else
110          if (g_list_length (window_list) > 1)
111                gtk_widget_destroy (GTK_WIDGET (window));
112}
113
114#ifdef PDF_DEBUG
115static void
116open_request_logger (GPdfURIInput *in, const char *uri, gpointer user_data)
117{
118        g_message ("Requested URI: '%s'", uri);
119}
120#endif
121
122int
123main (int argc, char **argv)
124{
125        GnomeProgram *program;
126        GnomeClient *client;
127        GValue value = { 0 };
128        poptContext ctx;
129
130#ifdef ENABLE_NLS
131        bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
132        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
133        textdomain (GETTEXT_PACKAGE);
134#endif
135
136        program = gnome_program_init ("gpdf", VERSION,
137                                      LIBGNOMEUI_MODULE, argc, argv,
138                                      GNOME_PARAM_APP_DATADIR, DATADIR,
139                                      NULL);
140
141        if (bonobo_ui_init ("GNOME PDF Viewer", VERSION, &argc, argv) == FALSE)
142                g_error (_("Could not initialize Bonobo!\n"));
143
144        gtk_window_set_default_icon_from_file (GNOMEICONDIR "/gnome-pdf.png", NULL);
145
146        client = gnome_master_client ();
147       
148        g_value_init (&value, G_TYPE_POINTER);
149        g_object_get_property (G_OBJECT (program), GNOME_PARAM_POPT_CONTEXT,
150                               &value);
151        ctx = g_value_get_pointer (&value);
152        g_value_unset (&value);
153
154        g_idle_add (handle_cmdline_args, ctx);
155
156        uri_in = g_object_new (GPDF_TYPE_URI_INPUT, NULL);
157        recent_facade = g_object_new (GPDF_TYPE_RECENT_FACADE, NULL);
158        gpdf_uri_input_set_recent_facade (uri_in, recent_facade);
159        DBG (g_signal_connect (G_OBJECT (uri_in), "open_request",
160                               G_CALLBACK (open_request_logger), NULL));
161        g_signal_connect (G_OBJECT (uri_in), "open_request",
162                          G_CALLBACK (open_request_handler), NULL);
163        gtk_widget_show (gpdf_window_new ());
164
165        bonobo_main ();
166
167        return 0;
168}
169
170
171/* GPdfWindow class */
172#include <recent-files/egg-recent-view.h>
173#include <recent-files/egg-recent-view-bonobo.h>
174#include <recent-files/egg-recent-view-gtk.h>
175#include "gpdf-recent-view-toolitem.h"
176
177#define GPDF_CONTROL_IID    "OAFIID:GNOME_PDF_Control"
178
179#define PARENT_TYPE BONOBO_TYPE_WINDOW
180
181GNOME_CLASS_BOILERPLATE (GPdfWindow, gpdf_window, BonoboWindow, PARENT_TYPE);
182
183struct _GPdfWindowPrivate {
184        BonoboWidget *bonobo_widget;
185        BonoboUIComponent *ui_component;
186 
187        GtkWidget *slot;
188
189        EggRecentView *recent_view;
190
191        GtkWidget *exit_fullscreen_popup;
192};
193
194/* Drag target types */
195enum {
196        TARGET_URI_LIST
197};
198
199#define GPDF_IS_NON_NULL_WINDOW(obj) \
200(((obj) != NULL) && (GPDF_IS_WINDOW ((obj))))
201
202
203gboolean
204gpdf_window_has_contents (const GPdfWindow *gpdf_window)
205{
206        return (gpdf_window->priv->bonobo_widget != NULL
207                && BONOBO_IS_WIDGET (gpdf_window->priv->bonobo_widget));
208}
209
210static gboolean
211gw_add_control_to_ui (GPdfWindow *gpdf_window)
212{
213        GPdfWindowPrivate *priv;
214        CORBA_Environment ev;
215        Bonobo_UIContainer ui_container;
216        GtkWidget *bonobo_widget;
217
218        g_return_val_if_fail (GPDF_IS_NON_NULL_WINDOW (gpdf_window), FALSE);
219
220        priv = gpdf_window->priv;
221
222        CORBA_exception_init (&ev);
223
224        ui_container = BONOBO_OBJREF (
225                bonobo_window_get_ui_container (BONOBO_WINDOW (gpdf_window)));
226        bonobo_widget =
227                bonobo_widget_new_control (GPDF_CONTROL_IID, ui_container);
228
229        if (bonobo_widget == NULL)
230                return FALSE;
231
232        g_object_ref (G_OBJECT (bonobo_widget));
233        priv->bonobo_widget = BONOBO_WIDGET (bonobo_widget);
234        gtk_container_add (GTK_CONTAINER (priv->slot), bonobo_widget);
235        CORBA_exception_free (&ev);
236
237        return TRUE;
238}
239
240static void
241gpdf_window_update_window_title (GPdfWindow *gpdf_window)
242{
243        Bonobo_PropertyBag pb;
244        CORBA_Environment ev;
245        char *exception_str;
246        gboolean is_default;
247        char *title;
248       
249        g_return_if_fail (GPDF_IS_NON_NULL_WINDOW (gpdf_window));
250       
251        CORBA_exception_init (&ev);
252       
253        pb = bonobo_control_frame_get_control_property_bag (
254                bonobo_widget_get_control_frame (
255                        gpdf_window->priv->bonobo_widget), &ev);
256       
257        /* Here we handle a exception when getting PB */
258        if (BONOBO_EX (&ev)) {
259                /* Report exception & use default title */
260                exception_str = bonobo_exception_get_text (&ev);
261                g_warning ("Property bag access exception '%s'", exception_str);
262                g_free (exception_str);
263                title = g_strdup (_("PDF Document"));
264        } else {
265                title = bonobo_pbclient_get_string_with_default (pb, "title",
266                                                                 _("PDF Document"),
267                                                                 &is_default);
268                bonobo_object_release_unref (pb, &ev);
269        }
270       
271        CORBA_exception_free (&ev);
272       
273        g_object_set (G_OBJECT (gpdf_window), "title", title, NULL);
274       
275        g_free (title);
276}
277
278static gboolean
279gw_control_load_pdf (GPdfWindow *gpdf_window, const char *uri)
280{
281        GPdfWindowPrivate *priv;
282        CORBA_Environment ev;
283        Bonobo_Unknown control;
284        Bonobo_PersistFile persist;
285        gboolean success = FALSE;
286
287        g_return_val_if_fail (GPDF_IS_NON_NULL_WINDOW (gpdf_window), FALSE);
288
289        priv = gpdf_window->priv;
290        control = bonobo_widget_get_objref (priv->bonobo_widget);
291
292        g_return_val_if_fail (control != CORBA_OBJECT_NIL, FALSE);
293       
294        CORBA_exception_init (&ev);
295
296        persist = Bonobo_Unknown_queryInterface (
297                control, "IDL:Bonobo/PersistFile:1.0", &ev);
298
299        if (BONOBO_EX (&ev) || persist == CORBA_OBJECT_NIL) {
300                g_warning ("Panic: component doesn't implement PersistFile.");
301                goto error_persist;
302        }
303
304        Bonobo_PersistFile_load (persist, uri, &ev);
305
306        if (BONOBO_EX (&ev))
307                goto error_persist_file;
308
309        success = TRUE;         
310
311error_persist_file:
312        bonobo_object_release_unref (persist, &ev);
313error_persist:
314        CORBA_exception_free (&ev);
315
316        return success;
317}
318
319gboolean
320gpdf_window_open (GPdfWindow *gpdf_window, const char *name)
321{
322        GPdfWindowPrivate *priv;
323
324        g_return_val_if_fail (GPDF_IS_NON_NULL_WINDOW (gpdf_window), FALSE);
325        g_return_val_if_fail (!gpdf_window_has_contents (gpdf_window), FALSE);
326
327        priv = gpdf_window->priv;
328
329        if (gw_add_control_to_ui (gpdf_window) == FALSE)
330                return FALSE;
331
332        if (gw_control_load_pdf (gpdf_window, name) == FALSE) {
333                gtk_container_remove (GTK_CONTAINER (priv->slot),
334                                      GTK_WIDGET (priv->bonobo_widget));
335                gtk_widget_destroy (GTK_WIDGET (priv->bonobo_widget));
336                priv->bonobo_widget = NULL;
337                bonobo_ui_component_set_prop (gpdf_window->priv->ui_component,
338                                              "/commands/ViewFullScreen",
339                                              "sensitive", "0", NULL);
340                return FALSE;
341        }
342
343        /* Activate component */
344        bonobo_control_frame_control_activate (
345               bonobo_widget_get_control_frame (priv->bonobo_widget));
346        gtk_widget_show (GTK_WIDGET (priv->bonobo_widget));
347
348        bonobo_ui_component_set_prop (gpdf_window->priv->ui_component,
349                                      "/commands/ViewFullScreen",
350                                      "sensitive", "1", NULL);
351       
352        return TRUE;
353}
354
355static void
356gw_drag_data_received (GtkWidget *widget, GdkDragContext *context,
357                       gint x, gint y, GtkSelectionData *selection_data,
358                       guint info, guint time)
359{
360        g_return_if_fail (info == TARGET_URI_LIST);
361
362        gpdf_uri_input_open_uri_list (uri_in,
363                                      (const gchar *)selection_data->data);
364}
365
366void
367gpdf_window_close (GPdfWindow *gpdf_window)
368{
369        g_return_if_fail (GPDF_IS_NON_NULL_WINDOW (gpdf_window));
370
371        if (gpdf_window_has_contents (gpdf_window)) {
372                bonobo_control_frame_set_autoactivate (
373                        bonobo_widget_get_control_frame (
374                                gpdf_window->priv->bonobo_widget),
375                        FALSE);
376                bonobo_control_frame_control_deactivate (
377                        bonobo_widget_get_control_frame (
378                                gpdf_window->priv->bonobo_widget));
379        }
380
381        gtk_widget_destroy (GTK_WIDGET (gpdf_window));
382
383        if (window_list == NULL)
384                bonobo_main_quit ();
385}
386
387static void
388gpdf_window_set_fullscreen (GPdfWindow *gpdf_window, gboolean fullscreen)
389{
390        if (fullscreen)
391                gtk_window_fullscreen (GTK_WINDOW (gpdf_window));
392        else
393                gtk_window_unfullscreen (GTK_WINDOW (gpdf_window));
394}
395
396static void
397exit_fullscreen_button_clicked_cb (GtkWidget *button, GPdfWindow *window)
398{
399        gpdf_window_set_fullscreen (window, FALSE);
400}
401
402static void
403update_exit_fullscreen_popup_position (GPdfWindow *gpdf_window)
404{
405        GdkRectangle screen_rect;
406        int popup_height;
407
408        if (gpdf_window->priv->exit_fullscreen_popup == NULL)
409                return;
410
411        gtk_window_get_size (GTK_WINDOW (gpdf_window->priv->exit_fullscreen_popup),
412                             NULL, &popup_height);
413
414        gdk_screen_get_monitor_geometry (
415                gdk_screen_get_default (),
416                gdk_screen_get_monitor_at_window (gdk_screen_get_default (),
417                                                  GTK_WIDGET (gpdf_window)->window),
418                &screen_rect);
419
420        gtk_window_move (GTK_WINDOW (gpdf_window->priv->exit_fullscreen_popup),
421                         screen_rect.x, screen_rect.height - popup_height);
422}
423
424static void
425screen_size_changed_cb (GdkScreen *screen, GPdfWindow *gpdf_window)
426{
427        update_exit_fullscreen_popup_position (gpdf_window);
428}
429
430static void
431gpdf_window_init_fullscreen_popup (GPdfWindow *gpdf_window)
432{
433        GtkWidget *popup, *button, *hbox, *icon, *label;
434        GtkAccelGroup *accel_group;
435
436        accel_group = gtk_accel_group_new ();
437       
438        popup = gtk_window_new (GTK_WINDOW_POPUP);
439        gpdf_window->priv->exit_fullscreen_popup = popup;
440
441        button = gtk_button_new ();
442        g_signal_connect (button, "clicked",
443                          G_CALLBACK (exit_fullscreen_button_clicked_cb),
444                          gpdf_window);
445        gtk_widget_add_accelerator (button, "clicked", accel_group,
446                                    GDK_Escape, 0,
447                                    GTK_ACCEL_VISIBLE);
448        gtk_widget_add_accelerator (button, "clicked", accel_group,
449                                    GDK_F11, 0,
450                                    GTK_ACCEL_VISIBLE);
451        gtk_widget_show (button);
452        gtk_container_add (GTK_CONTAINER (popup), button);
453
454        hbox = gtk_hbox_new (FALSE, 2);
455        gtk_widget_show (hbox);
456        gtk_container_add (GTK_CONTAINER (button), hbox);
457
458        icon = gtk_image_new_from_stock (GTK_STOCK_QUIT, GTK_ICON_SIZE_BUTTON);
459        gtk_widget_show (icon);
460        gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
461
462        label = gtk_label_new (_("Exit Full Screen"));
463        gtk_widget_show (label);
464        gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
465
466        update_exit_fullscreen_popup_position (gpdf_window);
467
468        gtk_widget_show (popup);
469
470        g_signal_connect (G_OBJECT (gdk_screen_get_default ()),
471                          "size-changed", G_CALLBACK (screen_size_changed_cb),
472                          gpdf_window);
473
474        gtk_window_add_accel_group (GTK_WINDOW (gpdf_window), accel_group);
475}
476
477static gboolean
478gpdf_window_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
479{
480        GPdfWindow *gpdf_window = GPDF_WINDOW (widget);
481
482        if (gpdf_window->priv->exit_fullscreen_popup) {
483                gtk_widget_show (gpdf_window->priv->exit_fullscreen_popup);
484        }
485
486        return GTK_WIDGET_CLASS (parent_class)->focus_in_event (widget, event);
487}
488
489static gboolean
490gpdf_window_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
491{
492        GPdfWindow *gpdf_window = GPDF_WINDOW (widget);
493
494        if (gpdf_window->priv->exit_fullscreen_popup) {
495                gtk_widget_hide (gpdf_window->priv->exit_fullscreen_popup);
496        }
497
498        return GTK_WIDGET_CLASS (parent_class)->focus_out_event (widget, event);
499}
500
501static gboolean
502gpdf_window_window_state_changed (GtkWidget *widget, GdkEventWindowState *event,
503                                  gpointer user_data)
504{
505        gboolean fullscreen;
506        GPdfWindow *gpdf_window;
507        BonoboUIComponent *uic;
508
509        if (!(event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN))
510                return FALSE;
511
512        g_return_val_if_fail (GPDF_IS_NON_NULL_WINDOW (widget), FALSE);
513
514        gpdf_window = GPDF_WINDOW (widget);
515        fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN;
516
517        uic = gpdf_window->priv->ui_component;
518        if (uic == NULL)
519                return FALSE;
520
521        bonobo_ui_component_set_prop (uic, "/commands/ViewFullScreen", "state",
522                                      fullscreen ? "1" : "0", NULL);
523
524        if (fullscreen) {
525                bonobo_ui_component_freeze (uic, NULL);
526                bonobo_ui_component_set_prop (uic,
527                                              "/menu", "hidden", "1", NULL);
528                bonobo_ui_component_set_prop (uic,
529                                              "/Toolbar", "hidden", "1", NULL);
530                bonobo_ui_component_thaw (uic, NULL);
531
532                gpdf_window_init_fullscreen_popup (gpdf_window);
533        } else {
534                bonobo_ui_component_freeze (uic, NULL);
535                bonobo_ui_component_set_prop (uic,
536                                              "/menu", "hidden", "0", NULL);
537                bonobo_ui_component_set_prop (uic,
538                                              "/Toolbar", "hidden", "0", NULL);
539                bonobo_ui_component_thaw (uic, NULL);
540
541                gtk_widget_destroy (gpdf_window->priv->exit_fullscreen_popup);
542                gpdf_window->priv->exit_fullscreen_popup = NULL;
543        }
544
545        return FALSE;
546}
547
548static gboolean
549gw_ask_for_uri (GPdfWindow *gpdf_window, gchar ***uri)
550{
551        GtkFileChooser *chooser;
552        GtkFileFilter *pdf_filter, *all_filter;
553        gboolean accepted = FALSE;
554
555        g_return_val_if_fail (GPDF_IS_NON_NULL_WINDOW (gpdf_window), FALSE);
556        g_return_val_if_fail (uri, FALSE);
557        g_return_val_if_fail (*uri == NULL, FALSE);
558
559        chooser = GTK_FILE_CHOOSER (gtk_file_chooser_dialog_new (_("Load file"),
560                                                                 GTK_WINDOW (gpdf_window),
561                                                                 GTK_FILE_CHOOSER_ACTION_OPEN,
562                                                                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
563                                                                 GTK_STOCK_OPEN, GTK_RESPONSE_OK,
564                                                                 NULL));
565        gtk_file_chooser_set_select_multiple (chooser, TRUE);
566        gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
567        pdf_filter = gtk_file_filter_new ();
568        gtk_file_filter_set_name (pdf_filter, _("PDF Documents"));
569        gtk_file_filter_add_mime_type (pdf_filter, "application/pdf");
570        gtk_file_chooser_add_filter (chooser, pdf_filter);
571        all_filter = gtk_file_filter_new ();
572        gtk_file_filter_set_name (all_filter, _("All Files"));
573        gtk_file_filter_add_pattern (all_filter, "*");
574        gtk_file_chooser_add_filter (chooser, all_filter);
575        gtk_file_chooser_set_filter (chooser, pdf_filter);
576       
577        gtk_window_set_position (GTK_WINDOW (chooser), GTK_WIN_POS_MOUSE);
578
579        accepted = (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_OK);
580
581        if (accepted) {
582                GSList *files, *iter;
583                guint n;
584
585                files = gtk_file_chooser_get_filenames (chooser);
586
587                *uri = g_new (gchar*, g_slist_length (files) + 1);
588
589                n = 0;
590                for (iter = files; iter != NULL; iter = iter->next) {
591                        (*uri)[n] =
592                                gnome_vfs_get_uri_from_local_path (iter->data);
593                        g_free (iter->data);
594                        n++;
595                }
596                (*uri)[n] = NULL;
597
598                g_slist_free (files);
599        }
600
601        gtk_widget_destroy (GTK_WIDGET (chooser));
602
603        return accepted;
604}
605
606static void
607gw_open_dialog (GPdfWindow *gpdf_window)
608{
609        gchar **uri = NULL;
610
611        g_return_if_fail (GPDF_IS_NON_NULL_WINDOW (gpdf_window));
612
613        if (gw_ask_for_uri (gpdf_window, &uri)) {
614                guint n;
615               
616                g_assert (uri != NULL);
617
618                n = 0;
619                while (uri[n]) {
620                        gpdf_uri_input_open_uri (uri_in, uri[n]);
621                        n++;
622                }
623                g_strfreev (uri);
624        }
625}
626
627static gboolean
628gw_open_recent_file (EggRecentView *view, EggRecentItem *item, gpointer data)
629{
630        GPdfURIInput *uri_in;
631        gchar *uri;   
632
633        uri_in = GPDF_URI_INPUT (data);
634
635        uri = egg_recent_item_get_uri_utf8 (item);
636        gpdf_uri_input_open_uri (uri_in, uri);
637
638        return TRUE;
639}
640
641
642static void
643verb_FileOpen_cb (BonoboUIComponent *uic, gpointer user_data,
644                  const char *cname)
645{
646        gw_open_dialog (GPDF_WINDOW (user_data));
647}
648
649static void
650verb_FileClose_cb (BonoboUIComponent *uic, gpointer user_data,
651                   const char *cname)
652{
653        gpdf_window_close (GPDF_WINDOW (user_data));
654}
655
656static void
657listener_ViewFullScreen (BonoboUIComponent *uic, const char *path,
658                         Bonobo_UIComponent_EventType type, const char *state,
659                         gpointer user_data)
660{
661        g_return_if_fail (GPDF_IS_NON_NULL_WINDOW (user_data));
662
663        if(type != Bonobo_UIComponent_STATE_CHANGED)
664                return;
665
666        if(!state)
667                return;
668
669        gpdf_window_set_fullscreen(GPDF_WINDOW (user_data), atoi (state));
670}
671
672
673/* Brings attention to a window by raising it and giving it focus */
674static void
675raise_and_focus (GtkWidget *widget)
676{
677        g_assert (GTK_WIDGET_REALIZED (widget));
678        gdk_window_show (widget->window);
679        gtk_widget_grab_focus (widget);
680}
681
682static void
683verb_HelpContents_cb (BonoboUIComponent *uic, gpointer user_data,
684                     const char *cname)
685{
686        gnome_help_display ("gpdf.xml",
687                            NULL,
688                            NULL);
689}
690
691static void
692verb_HelpAbout_cb (BonoboUIComponent *uic, gpointer user_data,
693                   const char *cname)
694{
695        static GtkWidget *about;
696
697        gchar *tmp_str;
698
699        static const gchar *authors[] = {
700                N_("Derek B. Noonburg, Xpdf author."),
701                N_("Martin Kretzschmar, GNOME port maintainer."),
702                N_("Michael Meeks, GNOME port creator."),
703                /* please localize as R&eacute;mi (R\303\251mi) */
704                N_("Remi Cohen-Scali."),
705                N_("Miguel de Icaza."),
706                N_("Nat Friedman."),
707                N_("Ravi Pratap."),
708                NULL
709        };
710
711        static const gchar *documenters[] = {
712                N_("Chee Bin HOH <cbhoh@mimos.my>"),
713                N_("Breda McColgan <BredaMcColgan@sun.com>"),
714                NULL
715        };
716
717        static const gchar *translators;
718
719        if (!about) {
720#ifdef ENABLE_NLS
721                int i;
722               
723                for (i = 0; authors[i] != NULL; i++)
724                        authors [i] = _(authors [i]);
725#endif
726
727                translators = _("translator-credits");
728
729                tmp_str = g_strconcat ("Copyright \xc2\xa9 1996-2004 ",
730                                     _("Glyph & Cog, LLC and authors"),
731                                     NULL);
732
733                about = gnome_about_new (
734                        _("GNOME PDF Viewer"),
735                        VERSION,
736                        tmp_str,
737                        _("A PDF viewer based on Xpdf"),
738                        authors,
739                        documenters,
740                        (strcmp (translators,
741                                 "translator-credits")
742                         ? translators : NULL),
743                        NULL);
744       
745                g_signal_connect (about, "destroy",
746                                  G_CALLBACK (gtk_widget_destroyed),
747                                  &about);
748
749                g_free (tmp_str);
750        }
751
752        gtk_widget_show_now (about);
753        raise_and_focus (about);
754}
755
756
757static gint
758gw_delete_event (GtkWidget *widget, GdkEventAny *event)
759{
760        gpdf_window_close (GPDF_WINDOW (widget));
761        return TRUE;
762}
763
764static void
765gw_destroy (GtkObject *object)
766{
767        GPdfWindow *gpdf_window = GPDF_WINDOW (object);
768        GPdfWindowPrivate *priv;
769
770        g_return_if_fail (GPDF_IS_NON_NULL_WINDOW (gpdf_window));
771
772        priv = gpdf_window->priv;
773        window_list = g_list_remove (window_list, gpdf_window);
774
775        if (priv->bonobo_widget != NULL) {
776                g_object_unref  (G_OBJECT (priv->bonobo_widget));
777                priv->bonobo_widget = NULL;
778        }
779
780        if (priv->recent_view != NULL) {
781                g_object_unref (G_OBJECT (priv->recent_view));
782                priv->recent_view = NULL;
783        }
784               
785        GNOME_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object));
786}
787
788static void
789gw_finalize (GObject *object)
790{
791        g_return_if_fail (GPDF_IS_NON_NULL_WINDOW (object));
792
793        g_free (GPDF_WINDOW (object)->priv);
794
795        GNOME_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
796}
797
798static void
799gpdf_window_class_init (GPdfWindowClass *klass)
800{
801        GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
802
803        G_OBJECT_CLASS (klass)->finalize = gw_finalize;
804        GTK_OBJECT_CLASS (klass)->destroy = gw_destroy;
805
806        widget_class->delete_event = gw_delete_event;
807        widget_class->drag_data_received = gw_drag_data_received;
808        widget_class->focus_in_event = gpdf_window_focus_in_event;
809        widget_class->focus_out_event = gpdf_window_focus_out_event;
810}
811
812static void
813gpdf_window_instance_init (GPdfWindow *gpdf_window)
814{
815        g_return_if_fail (GPDF_IS_NON_NULL_WINDOW (gpdf_window));
816       
817        gpdf_window->priv = g_new0 (GPdfWindowPrivate, 1);
818        window_list = g_list_prepend (window_list, gpdf_window);
819}
820
821
822/* Construction */
823
824static void
825gw_setup_dnd (GPdfWindow *gpdf_window)
826{
827        static GtkTargetEntry drag_types[] = {
828                { "text/uri-list", 0, TARGET_URI_LIST },
829        };
830        static gint n_drag_types =
831                sizeof (drag_types) / sizeof (drag_types [0]);
832
833        g_return_if_fail (GPDF_IS_NON_NULL_WINDOW (gpdf_window));
834
835        gtk_drag_dest_set (GTK_WIDGET (gpdf_window),
836                           GTK_DEST_DEFAULT_ALL,
837                           drag_types, n_drag_types, GDK_ACTION_COPY);
838}
839
840static void
841gw_setup_local_contents (GPdfWindow *gpdf_window)
842{
843        g_return_if_fail (GPDF_IS_NON_NULL_WINDOW (gpdf_window));
844
845        gpdf_window->priv->slot = gtk_event_box_new ();
846        gtk_widget_show (gpdf_window->priv->slot);
847        bonobo_window_set_contents (BONOBO_WINDOW (gpdf_window),
848                                    gpdf_window->priv->slot);
849        gtk_widget_show_all (gpdf_window->priv->slot);
850}
851
852/*
853 * The menus.
854 */
855static BonoboUIVerb gw_verbs [] = {
856        BONOBO_UI_VERB ("FileOpen",  verb_FileOpen_cb),
857        BONOBO_UI_VERB ("FileClose", verb_FileClose_cb),
858
859        BONOBO_UI_VERB ("HelpContents", verb_HelpContents_cb),
860        BONOBO_UI_VERB ("HelpAbout", verb_HelpAbout_cb),
861
862        BONOBO_UI_VERB_END
863};
864
865static void
866gw_setup_toplevel_ui (GPdfWindow *gpdf_window)
867{
868        GPdfWindowPrivate *priv;
869        BonoboUIContainer *ui_container;
870
871        g_return_if_fail (GPDF_IS_NON_NULL_WINDOW (gpdf_window));
872
873        priv = gpdf_window->priv;
874        ui_container = bonobo_window_get_ui_container (
875                BONOBO_WINDOW (gpdf_window));
876
877        priv->ui_component = bonobo_ui_component_new ("gpdf");
878        bonobo_ui_component_set_container (priv->ui_component,
879                                           BONOBO_OBJREF (ui_container),
880                                           NULL);
881        bonobo_ui_component_add_verb_list_with_data (priv->ui_component,
882                                                     gw_verbs, gpdf_window);
883        bonobo_ui_util_set_ui (priv->ui_component,
884                               DATADIR, "gpdf-window-ui.xml", "GPDF",
885                               NULL);
886
887        bonobo_ui_component_add_listener(priv->ui_component, "ViewFullScreen",
888                                         listener_ViewFullScreen, gpdf_window);
889}
890
891static void
892gw_setup_recent_menu (GPdfWindow *gpdf_window, GPdfRecentFacade *facade,
893                      GPdfURIInput *uri_in)
894{
895        const EggRecentModel *model;
896        EggRecentView *view;
897
898        model = gpdf_recent_facade_get_model (facade);
899        view = EGG_RECENT_VIEW (egg_recent_view_bonobo_new (
900                                        gpdf_window->priv->ui_component,
901                                        "/menu/File/Recents"));
902        egg_recent_view_bonobo_show_icons (EGG_RECENT_VIEW_BONOBO (view),
903                                           FALSE);
904        egg_recent_view_set_model (view, (EggRecentModel *)model);
905        g_signal_connect (G_OBJECT (view), "activate",
906                          G_CALLBACK (gw_open_recent_file), uri_in);
907        gpdf_window->priv->recent_view = view;
908}
909
910static void
911gw_setup_recent_toolitem (GPdfWindow *gpdf_window, GPdfRecentFacade *facade,
912                          GPdfURIInput *uri_in)
913{
914        GtkWidget *toolitem;
915        const EggRecentModel *model;
916
917        toolitem = GTK_WIDGET (g_object_new (GPDF_TYPE_RECENT_VIEW_TOOLITEM,
918                                           NULL));
919        gtk_widget_show_all (GTK_WIDGET (toolitem));       
920
921        model = gpdf_recent_facade_get_model (facade);
922
923        gpdf_recent_view_toolitem_set_model (
924                GPDF_RECENT_VIEW_TOOLITEM (toolitem), (EggRecentModel *)model);
925        g_signal_connect_object (G_OBJECT (toolitem), "item_activate",
926                                 G_CALLBACK (gw_open_recent_file),
927                                 uri_in, 0);
928
929        bonobo_ui_component_widget_set (gpdf_window->priv->ui_component,
930                                        "/Toolbar/FileOpenMenu",
931                                        GTK_WIDGET (toolitem), NULL);
932}
933
934GPdfWindow *gpdf_window_construct (GPdfWindow *gpdf_window)
935{
936        g_return_val_if_fail (GPDF_IS_NON_NULL_WINDOW (gpdf_window), NULL);
937
938        gw_setup_dnd (gpdf_window);
939        gw_setup_local_contents (gpdf_window);
940        gw_setup_toplevel_ui (gpdf_window);
941        gw_setup_recent_menu (gpdf_window, recent_facade, uri_in);
942        gw_setup_recent_toolitem (gpdf_window, recent_facade, uri_in);
943
944        g_signal_connect (G_OBJECT (gpdf_window), "window_state_event",
945                          G_CALLBACK (gpdf_window_window_state_changed), NULL);
946
947        return gpdf_window;
948}
949
950GtkWidget *gpdf_window_new (void)
951{
952        GPdfWindow *gpdf_window;
953
954        gpdf_window = GPDF_WINDOW (g_object_new (GPDF_TYPE_WINDOW,
955                                                 "win_name", "gpdf",
956                                                 "title", _("PDF Viewer"),
957                                                 "default-width", 600,
958                                                 "default-height", 600,
959                                                 NULL));
960
961        return GTK_WIDGET (gpdf_window_construct (gpdf_window));
962}
Note: See TracBrowser for help on using the repository browser.