]> www.fi.muni.cz Git - evince.git/blob - libdocument/ev-backends-manager.c
[dualscreen] fix crash on ctrl+w and fix control window closing
[evince.git] / libdocument / ev-backends-manager.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
4  *
5  * Evince is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Evince is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 #include <config.h>
21
22 #include <glib/gstdio.h>
23
24 #include "ev-module.h"
25 #include "ev-backends-manager.h"
26
27 static GList *ev_backends_list = NULL;
28
29 typedef struct _EvBackendInfo EvBackendInfo;
30 struct _EvBackendInfo {
31         gchar       *module_name;
32         GTypeModule *module;
33         gboolean     resident;
34
35         GType        type_id;
36
37         gchar       *type_desc;
38         gchar      **mime_types;
39 };
40
41 #define EV_BACKENDS_GROUP     "Evince Backend"
42 #define EV_BACKENDS_EXTENSION ".evince-backend"
43
44 static gchar *backendsdir = NULL;
45
46 static const gchar *
47 backends_dir (void)
48 {
49         if (!backendsdir) {
50 #ifdef G_OS_WIN32
51                 gchar *dir;
52
53                 dir = g_win32_get_package_installation_directory_of_module (NULL);
54                 backendsdir = g_build_filename (dir, "lib", "evince",
55                                                 EV_BACKENDSBINARYVERSION,
56                                                 "backends", NULL);
57                 g_free (dir);
58 #else
59                 backendsdir = g_strdup (EV_BACKENDSDIR);
60 #endif
61         }
62
63         return backendsdir;
64 }
65
66 static void
67 ev_backend_info_free (EvBackendInfo *info)
68 {
69         g_free (info->module_name);
70         g_free (info->type_desc);
71         g_strfreev (info->mime_types);
72         g_free (info);
73 }
74
75 static EvBackendInfo *
76 ev_backends_manager_load_backend (const gchar *file)
77 {
78         EvBackendInfo *info;
79         GKeyFile      *backend_file = NULL;
80         GError        *error = NULL;
81
82         backend_file = g_key_file_new ();
83         if (!g_key_file_load_from_file (backend_file, file, G_KEY_FILE_NONE, &error)) {
84                 g_warning ("Error opening backend file %s: %s",
85                            file, error->message);
86                 g_error_free (error);
87                 g_key_file_free (backend_file);
88
89                 return NULL;
90         }
91
92         info = g_new0 (EvBackendInfo, 1);
93         info->module_name = g_key_file_get_string (backend_file, EV_BACKENDS_GROUP,
94                                                    "Module", NULL);
95         if (!info->module_name) {
96                 g_warning ("Bad evince backend file %s: Could not find 'Module'",
97                            file);
98                 ev_backend_info_free (info);
99                 g_key_file_free (backend_file);
100
101                 return NULL;
102         }
103
104         info->resident = g_key_file_get_boolean (backend_file, EV_BACKENDS_GROUP,
105                                                  "Resident", NULL);
106         
107         info->type_desc = g_key_file_get_locale_string (backend_file, EV_BACKENDS_GROUP,
108                                                         "TypeDescription", NULL, NULL);
109         if (!info->type_desc) {
110                 g_warning ("Bad evince backend file %s: Could not find 'TypeDescription'",
111                            file);
112                 ev_backend_info_free (info);
113                 g_key_file_free (backend_file);
114
115                 return NULL;
116         }
117
118         info->mime_types = g_key_file_get_string_list (backend_file, EV_BACKENDS_GROUP,
119                                                        "MimeType", NULL, NULL);
120         if (!info->mime_types) {
121                 g_warning ("Bad evince backend file %s: Could not find 'MimeType'",
122                            file);
123                 ev_backend_info_free (info);
124                 g_key_file_free (backend_file);
125
126                 return NULL;
127         }
128
129         g_key_file_free (backend_file);
130
131         return info;
132 }
133
134 static gboolean
135 ev_backends_manager_load (void)
136 {
137         GDir        *dir;
138         const gchar *dirent;
139         GError      *error = NULL;
140
141         dir = g_dir_open (backends_dir(), 0, &error);
142         if (!dir) {
143                 g_warning ("%s", error->message);
144                 g_error_free (error);
145
146                 return FALSE;
147         }
148
149         while ((dirent = g_dir_read_name (dir))) {
150                 EvBackendInfo *info;
151                 gchar         *file;
152                 
153                 if (!g_str_has_suffix (dirent, EV_BACKENDS_EXTENSION))
154                         continue;
155
156                 file = g_build_filename (backends_dir(), dirent, NULL);
157                 info = ev_backends_manager_load_backend (file);
158                 g_free (file);
159
160                 if (!info)
161                         continue;
162                 
163                 ev_backends_list = g_list_prepend (ev_backends_list, info);
164         }
165
166         g_dir_close (dir);
167
168         return ev_backends_list != NULL;
169 }
170
171 /*
172  * _ev_backends_manager_init:
173  *
174  * Initializes the evince backends manager.
175  *
176  * Returns: %TRUE if there were any backends found; %FALSE otherwise
177  */
178 gboolean
179 _ev_backends_manager_init (void)
180 {
181         if (ev_backends_list)
182                 return TRUE;
183
184         return ev_backends_manager_load ();
185 }
186
187 /*
188  * _ev_backends_manager_shutdown:
189  *
190  * Shuts the evince backends manager down.
191  */
192 void
193 _ev_backends_manager_shutdown (void)
194 {
195         g_list_foreach (ev_backends_list, (GFunc)ev_backend_info_free, NULL);
196         g_list_free (ev_backends_list);
197         ev_backends_list = NULL;
198
199         g_free (backendsdir);
200 }
201
202 static EvBackendInfo *
203 ev_backends_manager_get_backend_info (const gchar *mime_type)
204 {
205         GList *l;
206
207         for (l = ev_backends_list; l; l = g_list_next (l)) {
208                 EvBackendInfo *info;
209                 gint           i = 0;
210                 const char    *mime;
211                 
212                 info = (EvBackendInfo *)l->data;
213                 
214                 while ((mime = info->mime_types[i++])) {
215                         if (g_ascii_strcasecmp (mime, mime_type) == 0)
216                                 return info;
217                 }
218         }
219
220         return NULL;
221 }
222
223 EvDocument *
224 ev_backends_manager_get_document (const gchar *mime_type)
225 {
226         EvDocument    *document;
227         EvBackendInfo *info;
228
229         info = ev_backends_manager_get_backend_info (mime_type);
230         if (!info)
231                 return NULL;
232
233         if (!info->module) {
234                 gchar *path;
235                 
236                 path = g_module_build_path (backends_dir(), info->module_name);
237                 info->module = G_TYPE_MODULE (ev_module_new (path, info->resident));
238                 g_free (path);
239         }
240         
241         if (!g_type_module_use (info->module)) {
242                 g_warning ("Cannot load backend '%s' since file '%s' cannot be read.",
243                            info->module_name,
244                            ev_module_get_path (EV_MODULE (info->module)));
245                 g_object_unref (G_OBJECT (info->module));
246                 info->module = NULL;
247
248                 return NULL;
249         }
250
251         document = EV_DOCUMENT (ev_module_new_object (EV_MODULE (info->module)));
252         g_type_module_unuse (info->module);
253
254         return document;
255 }
256
257 static EvBackendInfo *
258 get_document_backend_info (EvDocument *document)
259 {
260         GList *l;
261
262         for (l = ev_backends_list; l; l = g_list_next (l)) {
263                 EvBackendInfo *info;
264                 GType          type_id;
265
266                 info = (EvBackendInfo *)l->data;
267
268                 if (!info->module)
269                         continue;
270
271                 type_id = ev_module_get_object_type (EV_MODULE (info->module));
272
273                 if (G_TYPE_CHECK_INSTANCE_TYPE (document, type_id)) {
274                         return info;
275                 }
276         }
277
278         return NULL;
279 }
280
281 const gchar *
282 ev_backends_manager_get_document_module_name (EvDocument *document)
283 {
284         EvBackendInfo *info;
285
286         info = get_document_backend_info (document);
287         return info ? info->module_name : NULL;
288 }
289
290 static EvTypeInfo *
291 ev_type_info_new (const gchar *desc, const gchar **mime_types)
292 {
293         EvTypeInfo *info;
294
295         info = g_new (EvTypeInfo, 1);
296
297         info->desc = desc;
298         info->mime_types = mime_types;
299
300         return info;
301 }
302
303 EvTypeInfo *
304 ev_backends_manager_get_document_type_info (EvDocument *document)
305 {
306         EvBackendInfo *info;
307
308         info = get_document_backend_info (document);
309         return info ?
310                 ev_type_info_new (info->type_desc,
311                                   (const gchar **)info->mime_types)
312                 : NULL;
313 }
314
315 GList *
316 ev_backends_manager_get_all_types_info (void)
317 {
318         GList *l;
319         GList *retval = NULL;
320
321         for (l = ev_backends_list; l; l = g_list_next (l)) {
322                 EvBackendInfo *info;
323                 EvTypeInfo    *type_info;
324
325                 info = (EvBackendInfo *)l->data;
326
327                 type_info = ev_type_info_new (info->type_desc,
328                                               (const gchar **)info->mime_types);
329                 retval = g_list_prepend (retval, type_info);
330         }
331
332         return retval;
333 }