]> www.fi.muni.cz Git - evince.git/blob - shell/ev-page-action.c
Translation updated.
[evince.git] / shell / ev-page-action.c
1 /*
2  *  Copyright (C) 2003, 2004 Marco Pesenti Gritti
3  *  Copyright (C) 2003, 2004 Christian Persch
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  *
19  */
20
21 #include "config.h"
22
23 #include "ev-page-action.h"
24 #include "ev-page-cache.h"
25 #include "ev-window.h"
26 #include "ev-document-links.h"
27 #include "ev-page-action-widget.h"
28 #include "ev-marshal.h"
29
30 #include <glib/gi18n.h>
31 #include <gtk/gtkentry.h>
32 #include <gtk/gtktoolitem.h>
33 #include <gtk/gtklabel.h>
34 #include <gtk/gtkhbox.h>
35 #include <string.h>
36 #include <stdlib.h>
37
38 struct _EvPageActionPrivate
39 {
40         EvPageCache *page_cache;
41         GtkTreeModel *model;
42 };
43
44
45 static void ev_page_action_init       (EvPageAction *action);
46 static void ev_page_action_class_init (EvPageActionClass *class);
47
48 enum
49 {
50         ACTIVATE_LINK,
51         ACTIVATE_LABEL,
52         N_SIGNALS
53 };
54
55 static guint signals[N_SIGNALS] = {0, };
56
57 G_DEFINE_TYPE (EvPageAction, ev_page_action, GTK_TYPE_ACTION)
58
59 #define EV_PAGE_ACTION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_PAGE_ACTION, EvPageActionPrivate))
60
61 enum {
62         PROP_0,
63         PROP_PAGE_CACHE,
64         PROP_MODEL,
65 };
66
67 static void
68 update_pages_label (EvPageActionWidget *proxy,
69                     gint                page,
70                     EvPageCache        *page_cache)
71 {
72         char *label_text;
73         gint n_pages;
74
75         n_pages = page_cache ? ev_page_cache_get_n_pages (page_cache) : 0;
76         if (page_cache && ev_page_cache_has_nonnumeric_page_labels (page_cache)) {
77                 label_text = g_strdup_printf (_("(%d of %d)"), page + 1, n_pages);
78         } else {
79                 label_text = g_strdup_printf (_("of %d"), n_pages);
80         }
81         gtk_label_set_text (GTK_LABEL (proxy->label), label_text);
82         g_free (label_text);
83 }
84
85 static void
86 page_changed_cb (EvPageCache        *page_cache,
87                  gint                page,
88                  EvPageActionWidget *proxy)
89 {
90         g_assert (proxy);
91         
92         if (page_cache != NULL && page >= 0) {
93                 gchar *page_label;
94
95                 gtk_entry_set_width_chars (GTK_ENTRY (proxy->entry), 
96                                            CLAMP (ev_page_cache_get_max_label_chars (page_cache), 
97                                            6, 12));     
98                 
99                 page_label = ev_page_cache_get_page_label (page_cache, page);
100                 gtk_entry_set_text (GTK_ENTRY (proxy->entry), page_label);
101                 gtk_editable_set_position (GTK_EDITABLE (proxy->entry), -1);
102                 g_free (page_label);
103                 
104         } else {
105                 gtk_entry_set_text (GTK_ENTRY (proxy->entry), "");
106         }
107
108         update_pages_label (proxy, page, page_cache);
109 }
110
111 static void
112 activate_cb (GtkWidget *entry, GtkAction *action)
113 {
114         EvPageAction *page = EV_PAGE_ACTION (action);
115         EvPageCache *page_cache;
116         const char *text;
117         gchar *page_label;
118         gint page_number;
119         gboolean changed;
120
121         text = gtk_entry_get_text (GTK_ENTRY (entry));
122         page_cache = page->priv->page_cache;
123
124         g_signal_emit (action, signals[ACTIVATE_LABEL], 0, text, &changed);
125
126         if (changed)
127                 return;
128         
129         /* Check whether it's a valid page number */
130         page_number = atoi (text) - 1;
131         if (page_number >= 0 &&
132             page_number < ev_page_cache_get_n_pages (page_cache)) {
133                 page_label = ev_page_cache_get_page_label (page_cache, page_number);
134                 gtk_entry_set_text (GTK_ENTRY (entry), page_label);
135                 gtk_editable_set_position (GTK_EDITABLE (entry), -1);
136
137                 g_signal_emit (action, signals[ACTIVATE_LABEL], 0, page_label, &changed);
138                 g_free (page_label);
139                 
140                 return;
141         }
142         
143         /* rest the entry to the current page if we were unable to
144          * change it */
145         page_label = ev_page_cache_get_page_label (page_cache,
146                                                    ev_page_cache_get_current_page (page_cache));
147         gtk_entry_set_text (GTK_ENTRY (entry), page_label);
148         gtk_editable_set_position (GTK_EDITABLE (entry), -1);
149         g_free (page_label);
150 }
151
152 static GtkWidget *
153 create_tool_item (GtkAction *action)
154 {
155         EvPageActionWidget *proxy;
156         GtkWidget *hbox;
157
158         proxy = g_object_new (ev_page_action_widget_get_type (), NULL);
159         gtk_container_set_border_width (GTK_CONTAINER (proxy), 6); 
160         gtk_widget_show (GTK_WIDGET (proxy));
161
162         hbox = gtk_hbox_new (FALSE, 0);
163         gtk_box_set_spacing (GTK_BOX (hbox), 6);
164
165         proxy->entry = gtk_entry_new ();
166         gtk_entry_set_width_chars (GTK_ENTRY (proxy->entry), 5);
167         gtk_box_pack_start (GTK_BOX (hbox), proxy->entry, FALSE, FALSE, 0);
168         gtk_widget_show (proxy->entry);
169         g_signal_connect (proxy->entry, "activate",
170                           G_CALLBACK (activate_cb),
171                           action);
172
173         proxy->label = gtk_label_new (NULL);
174         gtk_box_pack_start (GTK_BOX (hbox), proxy->label, FALSE, FALSE, 0);
175         gtk_widget_show (proxy->label);
176
177         gtk_container_add (GTK_CONTAINER (proxy), hbox);
178         gtk_widget_show (hbox);
179
180         return GTK_WIDGET (proxy);
181 }
182
183 static void
184 update_page_cache (EvPageAction *page, GParamSpec *pspec, EvPageActionWidget *proxy)
185 {
186         EvPageCache *page_cache;
187         guint signal_id;
188
189         page_cache = page->priv->page_cache;
190
191         /* clear the old signal */
192         if (proxy->signal_id > 0 && proxy->page_cache)
193                 g_signal_handler_disconnect (proxy->page_cache, proxy->signal_id);
194         
195         if (page_cache != NULL) {
196                 signal_id = g_signal_connect_object (page_cache,
197                                                      "page-changed",
198                                                      G_CALLBACK (page_changed_cb),
199                                                      proxy, 0);
200                 /* Set the initial value */
201                 page_changed_cb (page_cache,
202                                  ev_page_cache_get_current_page (page_cache),
203                                  proxy);
204         } else {
205                 /* Or clear the entry */
206                 signal_id = 0;
207                 page_changed_cb (NULL, 0, proxy);
208         }
209         ev_page_action_widget_set_page_cache (proxy, page_cache);
210         proxy->signal_id = signal_id;
211 }
212
213 static void
214 activate_link_cb (EvPageActionWidget *proxy, EvLink *link, EvPageAction *action)
215 {
216         g_signal_emit (action, signals[ACTIVATE_LINK], 0, link);
217 }
218
219 static void
220 update_model (EvPageAction *page, GParamSpec *pspec, EvPageActionWidget *proxy)
221 {       
222         GtkTreeModel *model;
223
224         g_object_get (G_OBJECT (page),
225                       "model", &model,
226                       NULL);
227
228         ev_page_action_widget_update_model (proxy, model);
229 }
230
231 static void
232 connect_proxy (GtkAction *action, GtkWidget *proxy)
233 {
234         if (GTK_IS_TOOL_ITEM (proxy)) {
235                 g_signal_connect_object (action, "notify::page-cache",
236                                          G_CALLBACK (update_page_cache),
237                                          proxy, 0);
238                 g_signal_connect (proxy, "activate_link",
239                                   G_CALLBACK (activate_link_cb),
240                                   action);
241                 update_page_cache (EV_PAGE_ACTION (action), NULL,
242                                    EV_PAGE_ACTION_WIDGET (proxy));
243                 g_signal_connect_object (action, "notify::model",
244                                          G_CALLBACK (update_model),
245                                          proxy, 0);
246         }
247
248         GTK_ACTION_CLASS (ev_page_action_parent_class)->connect_proxy (action, proxy);
249 }
250
251 static void
252 ev_page_action_dispose (GObject *object)
253 {
254         EvPageAction *page = EV_PAGE_ACTION (object);
255
256         if (page->priv->page_cache) {
257                 g_object_unref (page->priv->page_cache);
258                 page->priv->page_cache = NULL;
259         }
260
261         G_OBJECT_CLASS (ev_page_action_parent_class)->dispose (object);
262 }
263
264 static void
265 ev_page_action_set_property (GObject      *object,
266                              guint         prop_id,
267                              const GValue *value,
268                              GParamSpec   *pspec)
269 {
270         EvPageAction *page;
271         EvPageCache *page_cache;
272         GtkTreeModel *model;
273   
274         page = EV_PAGE_ACTION (object);
275
276         switch (prop_id)
277         {
278         case PROP_PAGE_CACHE:
279                 page_cache = page->priv->page_cache;
280                 page->priv->page_cache = EV_PAGE_CACHE (g_value_dup_object (value));
281                 if (page_cache)
282                         g_object_unref (page_cache);
283                 break;
284         case PROP_MODEL:
285                 model = page->priv->model;
286                 page->priv->model = GTK_TREE_MODEL (g_value_dup_object (value));
287                 if (model)
288                         g_object_unref (model);
289                 break;
290         default:
291                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
292                 break;
293         }
294 }
295
296 static void
297 ev_page_action_get_property (GObject    *object,
298                              guint       prop_id,
299                              GValue     *value,
300                              GParamSpec *pspec)
301 {
302         EvPageAction *page;
303   
304         page = EV_PAGE_ACTION (object);
305
306         switch (prop_id)
307         {
308         case PROP_PAGE_CACHE:
309                 g_value_set_object (value, page->priv->page_cache);
310                 break;
311         case PROP_MODEL:
312                 g_value_set_object (value, page->priv->model);
313                 break;
314         default:
315                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
316                 break;
317         }
318 }
319
320 void
321 ev_page_action_set_document (EvPageAction *page, EvDocument *document)
322 {
323         EvPageCache *page_cache = NULL;
324
325         if (document)
326                 page_cache = ev_page_cache_get (document);
327         
328         g_object_set (page,
329                       "page-cache", page_cache,
330                       "model", NULL,
331                       NULL);
332 }
333
334 void
335 ev_page_action_set_model (EvPageAction *page_action,
336                           GtkTreeModel *model)
337 {
338         g_object_set (page_action,
339                       "model", model,
340                       NULL);
341 }
342
343 void
344 ev_page_action_grab_focus (EvPageAction *page_action)
345 {
346         GSList *proxies;
347
348         proxies = gtk_action_get_proxies (GTK_ACTION (page_action));
349         for (; proxies != NULL; proxies = proxies->next) {
350                 EvPageActionWidget *proxy;
351
352                 proxy = EV_PAGE_ACTION_WIDGET (proxies->data);
353                 gtk_widget_grab_focus (proxy->entry);
354         }
355 }
356
357 static void
358 ev_page_action_init (EvPageAction *page)
359 {
360         page->priv = EV_PAGE_ACTION_GET_PRIVATE (page);
361 }
362
363 static void
364 ev_page_action_class_init (EvPageActionClass *class)
365 {
366         GObjectClass *object_class = G_OBJECT_CLASS (class);
367         GtkActionClass *action_class = GTK_ACTION_CLASS (class);
368
369         object_class->dispose = ev_page_action_dispose;
370         object_class->set_property = ev_page_action_set_property;
371         object_class->get_property = ev_page_action_get_property;
372
373         action_class->toolbar_item_type = GTK_TYPE_TOOL_ITEM;
374         action_class->create_tool_item = create_tool_item;
375         action_class->connect_proxy = connect_proxy;
376
377         signals[ACTIVATE_LINK] = g_signal_new ("activate_link",
378                                                G_OBJECT_CLASS_TYPE (object_class),
379                                                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
380                                                G_STRUCT_OFFSET (EvPageActionClass, activate_link),
381                                                NULL, NULL,
382                                                g_cclosure_marshal_VOID__OBJECT,
383                                                G_TYPE_NONE, 1,
384                                                G_TYPE_OBJECT);
385         signals[ACTIVATE_LABEL] = g_signal_new ("activate_label",
386                                                 G_OBJECT_CLASS_TYPE (object_class),
387                                                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
388                                                 G_STRUCT_OFFSET (EvPageActionClass, activate_label),
389                                                 NULL, NULL,
390                                                 ev_marshal_BOOLEAN__STRING,
391                                                 G_TYPE_BOOLEAN, 1,
392                                                 G_TYPE_STRING);
393
394         g_object_class_install_property (object_class,
395                                          PROP_PAGE_CACHE,
396                                          g_param_spec_object ("page-cache",
397                                                               "Page Cache",
398                                                               "Current page cache",
399                                                               EV_TYPE_PAGE_CACHE,
400                                                               G_PARAM_READWRITE));
401
402         g_object_class_install_property (object_class,
403                                          PROP_MODEL,
404                                          g_param_spec_object ("model",
405                                                               "Model",
406                                                               "Current Model",
407                                                               GTK_TYPE_TREE_MODEL,
408                                                               G_PARAM_READWRITE));
409
410         g_type_class_add_private (object_class, sizeof (EvPageActionPrivate));
411 }