]> www.fi.muni.cz Git - evince.git/blob - shell/ev-application.c
Save last uri in file chooser dialog. Fix for the bug #327950.
[evince.git] / shell / ev-application.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2004 Martin Kretzschmar
4  *
5  *  Author:
6  *    Martin Kretzschmar <martink@gnome.org>
7  *
8  * Evince is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * Evince is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "ev-application.h"
28 #include "ev-utils.h"
29 #include "ev-document-types.h"
30 #include "ev-file-helpers.h"
31
32 #include <glib.h>
33 #include <glib/gi18n.h>
34 #include <glib-object.h>
35 #include <gtk/gtkfilechooserdialog.h>
36 #include <gtk/gtkstock.h>
37 #include <gtk/gtkwidget.h>
38 #include <gtk/gtkmain.h>
39 #include <libgnomeui/gnome-client.h>
40 #include <string.h>
41
42 #ifdef ENABLE_DBUS
43 #include "ev-application-service.h"
44 #include <dbus/dbus-glib-bindings.h>
45 #endif
46
47 G_DEFINE_TYPE (EvApplication, ev_application, G_TYPE_OBJECT);
48
49 #define EV_APPLICATION_GET_PRIVATE(object) \
50         (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_APPLICATION, EvApplicationPrivate))
51
52 #define APPLICATION_SERVICE_NAME "org.gnome.evince.ApplicationService"
53
54 #ifdef ENABLE_DBUS
55 gboolean
56 ev_application_register_service (EvApplication *application)
57 {
58         DBusGConnection *connection;
59         DBusGProxy *driver_proxy;
60         GError *err = NULL;
61         guint request_name_result;
62
63         connection = dbus_g_bus_get (DBUS_BUS_STARTER, &err);
64         if (connection == NULL) {
65                 g_warning ("Service registration failed.");
66                 g_error_free (err);
67
68                 return FALSE;
69         }
70
71         driver_proxy = dbus_g_proxy_new_for_name (connection,
72                                                   DBUS_SERVICE_DBUS,
73                                                   DBUS_PATH_DBUS,
74                                                   DBUS_INTERFACE_DBUS);
75
76         if (!org_freedesktop_DBus_request_name (driver_proxy,
77                                                 APPLICATION_SERVICE_NAME,
78                                                 0, &request_name_result, &err)) {
79                 g_warning ("Service registration failed.");
80                 g_clear_error (&err);
81         }
82
83         if (request_name_result == DBUS_REQUEST_NAME_REPLY_EXISTS) {
84                 return FALSE;
85         }
86
87 #if DBUS_VERSION == 33
88         dbus_g_object_class_install_info (G_OBJECT_GET_CLASS (application),
89                                           &dbus_glib_ev_application_object_info);
90 #else
91         dbus_g_object_type_install_info (EV_TYPE_APPLICATION,
92                                          &dbus_glib_ev_application_object_info);
93 #endif
94
95         dbus_g_connection_register_g_object (connection,
96                                              "/org/gnome/evince/Evince",
97                                              G_OBJECT (application));
98
99         return TRUE;
100 }
101 #endif /* ENABLE_DBUS */
102
103 EvApplication *
104 ev_application_get_instance (void)
105 {
106         static EvApplication *instance;
107
108         if (!instance) {
109                 instance = EV_APPLICATION (g_object_new (EV_TYPE_APPLICATION, NULL));
110         }
111
112         return instance;
113 }
114
115 static void
116 removed_from_session (GnomeClient *client, EvApplication *application)
117 {
118         ev_application_shutdown (application);
119 }
120
121 static gint
122 save_session (GnomeClient *client, gint phase, GnomeSaveStyle save_style, gint shutdown,
123               GnomeInteractStyle interact_style, gint fast, EvApplication *application)
124 {
125         GList *windows, *l;
126         char **restart_argv;
127         int argc = 0, k;
128
129         windows = ev_application_get_windows (application);
130         restart_argv = g_new (char *, g_list_length (windows) + 1);
131         restart_argv[argc++] = g_strdup ("evince");
132
133         for (l = windows; l != NULL; l = l->next) {
134                 EvWindow *window = EV_WINDOW (l->data);
135                 restart_argv[argc++] = g_strdup (ev_window_get_uri (window));
136         }
137
138         gnome_client_set_restart_command (client, argc, restart_argv);
139
140         for (k = 0; k < argc; k++) {
141                 g_free (restart_argv[k]);
142         }
143
144         g_list_free (windows);
145         g_free (restart_argv);
146         
147         return TRUE;
148 }
149
150 static void
151 init_session (EvApplication *application)
152 {
153         GnomeClient *client;
154
155         client = gnome_master_client ();
156
157         g_signal_connect (client, "save_yourself",
158                           G_CALLBACK (save_session), application);      
159         g_signal_connect (client, "die",
160                           G_CALLBACK (removed_from_session), application);
161 }
162
163 gboolean
164 ev_application_open_window (EvApplication  *application,
165                             guint32         timestamp,
166                             GError        **error)
167 {
168         GtkWidget *new_window = ev_window_new ();
169
170         gtk_widget_show (new_window);
171         
172 #ifdef HAVE_GTK_WINDOW_PRESENT_WITH_TIME
173         gtk_window_present_with_time (GTK_WINDOW (new_window),
174                                       timestamp);
175 #else
176         gtk_window_present (GTK_WINDOW (new_window));
177 #endif
178
179         return TRUE;
180 }
181
182 static EvWindow *
183 ev_application_get_empty_window (EvApplication *application)
184 {
185         EvWindow *empty_window = NULL;
186         GList *windows = ev_application_get_windows (application);
187         GList *l;
188
189         for (l = windows; l != NULL; l = l->next) {
190                 EvWindow *window = EV_WINDOW (l->data);
191
192                 if (ev_window_is_empty (window)) {
193                         empty_window = window;
194                         break;
195                 }
196         }
197
198         g_list_free (windows);
199         
200         return empty_window;
201 }
202
203 static EvWindow *
204 ev_application_get_uri_window (EvApplication *application, const char *uri)
205 {
206         EvWindow *uri_window = NULL;
207         GList *windows = gtk_window_list_toplevels ();
208         GList *l;
209
210         g_return_val_if_fail (uri != NULL, NULL);
211
212         for (l = windows; l != NULL; l = l->next) {
213                 if (EV_IS_WINDOW (l->data)) {
214                         EvWindow *window = EV_WINDOW (l->data);
215                         const char *window_uri = ev_window_get_uri (window);
216
217                         if (window_uri && strcmp (window_uri, uri) == 0 && !ev_window_is_empty (window)) {
218                                 uri_window = window;
219                                 break;
220                         }
221                 }
222         }
223
224         g_list_free (windows);
225         
226         return uri_window;
227 }
228
229 gboolean
230 ev_application_open_uri (EvApplication  *application,
231                          const char     *uri,
232                          const char     *page_label,
233                          guint           timestamp,
234                          GError        **error)
235 {
236         EvWindow *new_window;
237
238         g_return_val_if_fail (uri != NULL, FALSE);
239
240         new_window = ev_application_get_uri_window (application, uri);
241         if (new_window != NULL) {
242 #ifdef HAVE_GTK_WINDOW_PRESENT_WITH_TIME
243                 gtk_window_present_with_time (GTK_WINDOW (new_window),
244                                               timestamp);
245 #else
246                 gtk_window_present (GTK_WINDOW (new_window));
247 #endif  
248                 return TRUE;
249         }
250
251         new_window = ev_application_get_empty_window (application);
252
253         if (new_window == NULL) {
254                 new_window = EV_WINDOW (ev_window_new ());
255         }
256
257         /* We need to load uri before showing the window, so
258            we can restore window size without flickering */     
259         ev_window_open_uri (new_window, uri);
260
261         gtk_widget_show (GTK_WIDGET (new_window));
262
263 #ifdef HAVE_GTK_WINDOW_PRESENT_WITH_TIME
264         gtk_window_present_with_time (GTK_WINDOW (new_window),
265                                       timestamp);
266 #else
267         gtk_window_present (GTK_WINDOW (new_window));
268 #endif
269
270         if (page_label != NULL) {
271                 ev_window_open_page_label (new_window, page_label);
272         }
273
274         return TRUE;
275 }
276
277 void
278 ev_application_open_uri_list (EvApplication *application,
279                               GSList        *uri_list,
280                               guint          timestamp)
281 {
282         GSList *l;
283
284         for (l = uri_list; l != NULL; l = l->next) {
285                 ev_application_open_uri (application, (char *)l->data,
286                                          NULL,
287                                          timestamp,
288                                          NULL);
289         }
290 }
291
292 void
293 ev_application_shutdown (EvApplication *application)
294 {
295         if (application->toolbars_model) {
296                 g_object_unref (application->toolbars_model);
297                 g_free (application->toolbars_file);
298                 application->toolbars_model = NULL;
299                 application->toolbars_file = NULL;
300         }
301
302         if (application->recent_model) {
303                 g_object_unref (application->recent_model);
304                 application->recent_model = NULL;
305         }
306
307         g_free (application->last_chooser_uri);
308         g_object_unref (application);
309         
310         gtk_main_quit ();
311 }
312
313 static void
314 ev_application_class_init (EvApplicationClass *ev_application_class)
315 {
316 }
317
318 static void
319 ev_application_init (EvApplication *ev_application)
320 {
321         init_session (ev_application);
322
323         ev_application->toolbars_model = egg_toolbars_model_new ();
324
325         ev_application->toolbars_file = g_build_filename
326                         (ev_dot_dir (), "evince_toolbar.xml", NULL);
327
328         if (!egg_toolbars_model_load (ev_application->toolbars_model,
329                                       ev_application->toolbars_file)) {
330                 egg_toolbars_model_load (ev_application->toolbars_model,
331                                          DATADIR"/evince-toolbar.xml");
332         }
333
334         egg_toolbars_model_set_flags (ev_application->toolbars_model, 0,
335                                       EGG_TB_MODEL_NOT_REMOVABLE); 
336                                       
337         ev_application->recent_model = egg_recent_model_new (EGG_RECENT_MODEL_SORT_MRU);
338         /* FIXME we should add a mime type filter but current eggrecent
339            has only a varargs style api which does not work well when
340            the list of mime types is dynamic */
341         egg_recent_model_set_limit (ev_application->recent_model, 5);   
342         egg_recent_model_set_filter_groups (ev_application->recent_model,
343                                             "Evince", NULL);
344 }
345
346 GList *
347 ev_application_get_windows (EvApplication *application)
348 {
349         GList *l, *toplevels;
350         GList *windows = NULL;
351
352         toplevels = gtk_window_list_toplevels ();
353
354         for (l = toplevels; l != NULL; l = l->next) {
355                 if (EV_IS_WINDOW (l->data)) {
356                         windows = g_list_append (windows, l->data);
357                 }
358         }
359
360         g_list_free (toplevels);
361
362         return windows;
363 }
364
365 EggToolbarsModel *ev_application_get_toolbars_model (EvApplication *application)
366 {
367         return application->toolbars_model;
368 }
369
370 EggRecentModel *ev_application_get_recent_model (EvApplication *application)
371 {
372         return application->recent_model;
373 }
374
375 void ev_application_save_toolbars_model (EvApplication *application)
376 {
377         egg_toolbars_model_save (application->toolbars_model,
378                                  application->toolbars_file, "1.0");
379 }
380
381 void ev_application_set_chooser_uri (EvApplication *application, gchar *uri)
382 {
383         g_free (application->last_chooser_uri);
384         application->last_chooser_uri = g_strdup (uri);
385 }
386
387 const gchar* ev_application_get_chooser_uri (EvApplication *application)
388 {
389         return application->last_chooser_uri;
390 }
391