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 | |
---|
28 | static GPdfRecentFacade *recent_facade; |
---|
29 | static GPdfURIInput *uri_in; |
---|
30 | /* The list of all open windows */ |
---|
31 | static GList *window_list = NULL; |
---|
32 | |
---|
33 | static void gpdf_window_update_window_title (GPdfWindow *); |
---|
34 | |
---|
35 | static gboolean |
---|
36 | create_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 | |
---|
48 | static gboolean |
---|
49 | handle_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 | |
---|
71 | static gint |
---|
72 | no_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 | |
---|
81 | static GPdfWindow * |
---|
82 | find_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 | |
---|
100 | static void |
---|
101 | open_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 |
---|
115 | static void |
---|
116 | open_request_logger (GPdfURIInput *in, const char *uri, gpointer user_data) |
---|
117 | { |
---|
118 | g_message ("Requested URI: '%s'", uri); |
---|
119 | } |
---|
120 | #endif |
---|
121 | |
---|
122 | int |
---|
123 | main (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 | |
---|
181 | GNOME_CLASS_BOILERPLATE (GPdfWindow, gpdf_window, BonoboWindow, PARENT_TYPE); |
---|
182 | |
---|
183 | struct _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 */ |
---|
195 | enum { |
---|
196 | TARGET_URI_LIST |
---|
197 | }; |
---|
198 | |
---|
199 | #define GPDF_IS_NON_NULL_WINDOW(obj) \ |
---|
200 | (((obj) != NULL) && (GPDF_IS_WINDOW ((obj)))) |
---|
201 | |
---|
202 | |
---|
203 | gboolean |
---|
204 | gpdf_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 | |
---|
210 | static gboolean |
---|
211 | gw_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 | |
---|
240 | static void |
---|
241 | gpdf_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 | |
---|
278 | static gboolean |
---|
279 | gw_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 | |
---|
311 | error_persist_file: |
---|
312 | bonobo_object_release_unref (persist, &ev); |
---|
313 | error_persist: |
---|
314 | CORBA_exception_free (&ev); |
---|
315 | |
---|
316 | return success; |
---|
317 | } |
---|
318 | |
---|
319 | gboolean |
---|
320 | gpdf_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 | |
---|
355 | static void |
---|
356 | gw_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 | |
---|
366 | void |
---|
367 | gpdf_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 | |
---|
387 | static void |
---|
388 | gpdf_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 | |
---|
396 | static void |
---|
397 | exit_fullscreen_button_clicked_cb (GtkWidget *button, GPdfWindow *window) |
---|
398 | { |
---|
399 | gpdf_window_set_fullscreen (window, FALSE); |
---|
400 | } |
---|
401 | |
---|
402 | static void |
---|
403 | update_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 | |
---|
424 | static void |
---|
425 | screen_size_changed_cb (GdkScreen *screen, GPdfWindow *gpdf_window) |
---|
426 | { |
---|
427 | update_exit_fullscreen_popup_position (gpdf_window); |
---|
428 | } |
---|
429 | |
---|
430 | static void |
---|
431 | gpdf_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 | |
---|
477 | static gboolean |
---|
478 | gpdf_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 | |
---|
489 | static gboolean |
---|
490 | gpdf_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 | |
---|
501 | static gboolean |
---|
502 | gpdf_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 | |
---|
548 | static gboolean |
---|
549 | gw_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 | |
---|
606 | static void |
---|
607 | gw_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 | |
---|
627 | static gboolean |
---|
628 | gw_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 | |
---|
642 | static void |
---|
643 | verb_FileOpen_cb (BonoboUIComponent *uic, gpointer user_data, |
---|
644 | const char *cname) |
---|
645 | { |
---|
646 | gw_open_dialog (GPDF_WINDOW (user_data)); |
---|
647 | } |
---|
648 | |
---|
649 | static void |
---|
650 | verb_FileClose_cb (BonoboUIComponent *uic, gpointer user_data, |
---|
651 | const char *cname) |
---|
652 | { |
---|
653 | gpdf_window_close (GPDF_WINDOW (user_data)); |
---|
654 | } |
---|
655 | |
---|
656 | static void |
---|
657 | listener_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 */ |
---|
674 | static void |
---|
675 | raise_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 | |
---|
682 | static void |
---|
683 | verb_HelpContents_cb (BonoboUIComponent *uic, gpointer user_data, |
---|
684 | const char *cname) |
---|
685 | { |
---|
686 | gnome_help_display ("gpdf.xml", |
---|
687 | NULL, |
---|
688 | NULL); |
---|
689 | } |
---|
690 | |
---|
691 | static void |
---|
692 | verb_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é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 | |
---|
757 | static gint |
---|
758 | gw_delete_event (GtkWidget *widget, GdkEventAny *event) |
---|
759 | { |
---|
760 | gpdf_window_close (GPDF_WINDOW (widget)); |
---|
761 | return TRUE; |
---|
762 | } |
---|
763 | |
---|
764 | static void |
---|
765 | gw_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 | |
---|
788 | static void |
---|
789 | gw_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 | |
---|
798 | static void |
---|
799 | gpdf_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 | |
---|
812 | static void |
---|
813 | gpdf_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 | |
---|
824 | static void |
---|
825 | gw_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 | |
---|
840 | static void |
---|
841 | gw_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 | */ |
---|
855 | static 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 | |
---|
865 | static void |
---|
866 | gw_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 | |
---|
891 | static void |
---|
892 | gw_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 | |
---|
910 | static void |
---|
911 | gw_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 | |
---|
934 | GPdfWindow *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 | |
---|
950 | GtkWidget *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 | } |
---|