~kroq-gar78/ubuntu/precise/gnome-control-center/fix-885947

« back to all changes in this revision

Viewing changes to capplets/about-me/e-image-chooser.c

  • Committer: Bazaar Package Importer
  • Author(s): Rodrigo Moya
  • Date: 2011-05-17 10:47:27 UTC
  • mfrom: (0.1.11 experimental) (1.1.45 upstream)
  • Revision ID: james.westby@ubuntu.com-20110517104727-lqel6m8vhfw5jby1
Tags: 1:3.0.1.1-1ubuntu1
* Rebase on Debian, remaining Ubuntu changes:
* debian/control:
  - Build-Depend on hardening-wrapper, dpkg-dev and dh-autoreconf
  - Add dependency on ubuntu-system-service
  - Remove dependency on gnome-icon-theme-symbolic
  - Move dependency on apg, gnome-icon-theme-symbolic and accountsservice to
    be a Recommends: until we get them in main
* debian/rules:
  - Use autoreconf
  - Add binary-post-install rule for gnome-control-center-data
  - Run dh-autoreconf
* debian/gnome-control-center.dirs:
* debian/gnome-control-center.links:
  - Add a link to the control center shell for indicators
* debian/patches/00_disable-nm.patch:
  - Temporary patch to disable building with NetworkManager until we get
    the new one in the archive
* debian/patches/01_git_remove_gettext_calls.patch:
  - Remove calls to AM_GNU_GETTEXT, IT_PROG_INTLTOOL should be enough
* debian/patches/01_git_kill_warning.patch:
  - Kill warning
* debian/patches/50_ubuntu_systemwide_prefs.patch:
  - Ubuntu specific proxy preferences
* debian/patches/51_ubuntu_system_keyboard.patch:
  - Implement the global keyboard spec at https://wiki.ubuntu.com/DefaultKeyboardSettings

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
 
/* e-image-chooser.c
3
 
 * Copyright (C) 2004  Novell, Inc.
4
 
 * Author: Chris Toshok <toshok@ximian.com>
5
 
 *
6
 
 * This library is free software; you can redistribute it and/or
7
 
 * modify it under the terms of version 2 of the GNU General Public
8
 
 * License as published by the Free Software Foundation.
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 GNU
13
 
 * General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public
16
 
 * License along with this library; if not, write to the
17
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
 
 * Boston, MA 02111-1307, USA.
19
 
 */
20
 
 
21
 
#include <config.h>
22
 
 
23
 
#include <string.h>
24
 
 
25
 
#include <glib-object.h>
26
 
#include <glib/gi18n.h>
27
 
#include <gio/gio.h>
28
 
#include <gtk/gtk.h>
29
 
 
30
 
#include "e-image-chooser.h"
31
 
 
32
 
struct _EImageChooserPrivate {
33
 
 
34
 
        GtkWidget *image;
35
 
        GtkWidget *browse_button;
36
 
 
37
 
        char *image_buf;
38
 
        int   image_buf_size;
39
 
        int   image_width;
40
 
        int   image_height;
41
 
 
42
 
        gboolean editable;
43
 
};
44
 
 
45
 
enum {
46
 
        CHANGED,
47
 
        LAST_SIGNAL
48
 
};
49
 
 
50
 
 
51
 
static gint image_chooser_signals [LAST_SIGNAL] = { 0 };
52
 
 
53
 
static void e_image_chooser_init         (EImageChooser          *chooser);
54
 
static void e_image_chooser_class_init   (EImageChooserClass     *klass);
55
 
static void e_image_chooser_dispose      (GObject *object);
56
 
 
57
 
static gboolean image_drag_motion_cb (GtkWidget *widget,
58
 
                                      GdkDragContext *context,
59
 
                                      gint x, gint y, guint time, EImageChooser *chooser);
60
 
static gboolean image_drag_drop_cb (GtkWidget *widget,
61
 
                                    GdkDragContext *context,
62
 
                                    gint x, gint y, guint time, EImageChooser *chooser);
63
 
static void image_drag_data_received_cb (GtkWidget *widget,
64
 
                                         GdkDragContext *context,
65
 
                                         gint x, gint y,
66
 
                                         GtkSelectionData *selection_data,
67
 
                                         guint info, guint time, EImageChooser *chooser);
68
 
 
69
 
static GtkObjectClass *parent_class = NULL;
70
 
#define PARENT_TYPE GTK_TYPE_VBOX
71
 
 
72
 
enum DndTargetType {
73
 
        DND_TARGET_TYPE_URI_LIST
74
 
};
75
 
#define URI_LIST_TYPE "text/uri-list"
76
 
 
77
 
static GtkTargetEntry image_drag_types[] = {
78
 
        { URI_LIST_TYPE, 0, DND_TARGET_TYPE_URI_LIST },
79
 
};
80
 
static const int num_image_drag_types = sizeof (image_drag_types) / sizeof (image_drag_types[0]);
81
 
 
82
 
GtkWidget *
83
 
e_image_chooser_new (void)
84
 
{
85
 
        return g_object_new (E_TYPE_IMAGE_CHOOSER, NULL);
86
 
}
87
 
 
88
 
GType
89
 
e_image_chooser_get_type (void)
90
 
{
91
 
        static GType eic_type = 0;
92
 
 
93
 
        if (!eic_type) {
94
 
                static const GTypeInfo eic_info =  {
95
 
                        sizeof (EImageChooserClass),
96
 
                        NULL,           /* base_init */
97
 
                        NULL,           /* base_finalize */
98
 
                        (GClassInitFunc) e_image_chooser_class_init,
99
 
                        NULL,           /* class_finalize */
100
 
                        NULL,           /* class_data */
101
 
                        sizeof (EImageChooser),
102
 
                        0,             /* n_preallocs */
103
 
                        (GInstanceInitFunc) e_image_chooser_init,
104
 
                };
105
 
 
106
 
                eic_type = g_type_register_static (PARENT_TYPE, "EImageChooser", &eic_info, 0);
107
 
        }
108
 
 
109
 
        return eic_type;
110
 
}
111
 
 
112
 
 
113
 
static void
114
 
e_image_chooser_class_init (EImageChooserClass *klass)
115
 
{
116
 
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
117
 
 
118
 
        parent_class = g_type_class_ref (PARENT_TYPE);
119
 
 
120
 
        image_chooser_signals [CHANGED] =
121
 
                g_signal_new ("changed",
122
 
                              G_OBJECT_CLASS_TYPE (object_class),
123
 
                              G_SIGNAL_RUN_FIRST,
124
 
                              G_STRUCT_OFFSET (EImageChooserClass, changed),
125
 
                              NULL, NULL,
126
 
                              g_cclosure_marshal_VOID__VOID,
127
 
                              GTK_TYPE_NONE, 0);
128
 
 
129
 
        object_class->dispose = e_image_chooser_dispose;
130
 
}
131
 
 
132
 
static void
133
 
e_image_chooser_init (EImageChooser *chooser)
134
 
{
135
 
        EImageChooserPrivate *priv;
136
 
 
137
 
        priv = chooser->priv = g_new0 (EImageChooserPrivate, 1);
138
 
 
139
 
        priv->image = gtk_image_new ();
140
 
 
141
 
        gtk_box_set_homogeneous (GTK_BOX (chooser), FALSE);
142
 
        gtk_box_pack_start (GTK_BOX (chooser), priv->image, TRUE, TRUE, 0);
143
 
 
144
 
        gtk_drag_dest_set (priv->image, 0, image_drag_types, num_image_drag_types, GDK_ACTION_COPY);
145
 
        g_signal_connect (priv->image,
146
 
                          "drag_motion", G_CALLBACK (image_drag_motion_cb), chooser);
147
 
        g_signal_connect (priv->image,
148
 
                          "drag_drop", G_CALLBACK (image_drag_drop_cb), chooser);
149
 
        g_signal_connect (priv->image,
150
 
                          "drag_data_received", G_CALLBACK (image_drag_data_received_cb), chooser);
151
 
 
152
 
        gtk_widget_show_all (priv->image);
153
 
 
154
 
        /* we default to being editable */
155
 
        priv->editable = TRUE;
156
 
}
157
 
 
158
 
static void
159
 
e_image_chooser_dispose (GObject *object)
160
 
{
161
 
        EImageChooser *eic = E_IMAGE_CHOOSER (object);
162
 
 
163
 
        if (eic->priv) {
164
 
                EImageChooserPrivate *priv = eic->priv;
165
 
 
166
 
                if (priv->image_buf) {
167
 
                        g_free (priv->image_buf);
168
 
                        priv->image_buf = NULL;
169
 
                }
170
 
 
171
 
                g_free (eic->priv);
172
 
                eic->priv = NULL;
173
 
        }
174
 
 
175
 
        if (G_OBJECT_CLASS (parent_class)->dispose)
176
 
                (* G_OBJECT_CLASS (parent_class)->dispose) (object);
177
 
}
178
 
 
179
 
 
180
 
static gboolean
181
 
set_image_from_data (EImageChooser *chooser,
182
 
                     char *data, int length)
183
 
{
184
 
        gboolean rv = FALSE;
185
 
        GdkPixbufLoader *loader = gdk_pixbuf_loader_new ();
186
 
        GdkPixbuf *pixbuf;
187
 
 
188
 
        gdk_pixbuf_loader_write (loader, data, length, NULL);
189
 
        gdk_pixbuf_loader_close (loader, NULL);
190
 
 
191
 
        pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
192
 
        if (pixbuf)
193
 
                g_object_ref (pixbuf);
194
 
        g_object_unref (loader);
195
 
 
196
 
        if (pixbuf) {
197
 
                GdkPixbuf *scaled;
198
 
                GtkRequisition chooser_size;
199
 
 
200
 
                float scale;
201
 
                int new_height, new_width;
202
 
 
203
 
                gtk_widget_size_request (gtk_widget_get_parent (GTK_WIDGET (chooser)),
204
 
                                         &chooser_size);
205
 
                chooser_size.width -= 5;
206
 
                chooser_size.height -= 5;
207
 
 
208
 
                new_height = gdk_pixbuf_get_height (pixbuf);
209
 
                new_width = gdk_pixbuf_get_width (pixbuf);
210
 
 
211
 
                if (chooser->priv->image_height == 0
212
 
                    && chooser->priv->image_width == 0) {
213
 
                        scale = 1.0;
214
 
                }
215
 
                else if (chooser->priv->image_height < new_height
216
 
                         || chooser->priv->image_width < new_width) {
217
 
                        /* we need to scale down */
218
 
                        if (new_height > new_width)
219
 
                                scale = (float)chooser_size.height / new_height;
220
 
                        else
221
 
                                scale = (float)chooser_size.width / new_width;
222
 
                }
223
 
                else {
224
 
                        /* we need to scale up */
225
 
                        if (new_height > new_width)
226
 
                                scale = (float)new_height / chooser_size.height;
227
 
                        else
228
 
                                scale = (float)new_width / chooser_size.width;
229
 
                }
230
 
 
231
 
                if (scale == 1.0) {
232
 
                        gtk_image_set_from_pixbuf (GTK_IMAGE (chooser->priv->image), pixbuf);
233
 
 
234
 
                        chooser->priv->image_width = new_width;
235
 
                        chooser->priv->image_height = new_height;
236
 
                }
237
 
                else {
238
 
                        new_width *= scale;
239
 
                        new_height *= scale;
240
 
                        new_width = MIN (new_width, chooser_size.width);
241
 
                        new_height = MIN (new_height, chooser_size.height);
242
 
 
243
 
                        scaled = gdk_pixbuf_scale_simple (pixbuf,
244
 
                                                          new_width, new_height,
245
 
                                                          GDK_INTERP_BILINEAR);
246
 
 
247
 
                        gtk_image_set_from_pixbuf (GTK_IMAGE (chooser->priv->image), scaled);
248
 
                        g_object_unref (scaled);
249
 
                }
250
 
 
251
 
                g_object_unref (pixbuf);
252
 
 
253
 
                g_free (chooser->priv->image_buf);
254
 
                chooser->priv->image_buf = data;
255
 
                chooser->priv->image_buf_size = length;
256
 
 
257
 
                g_signal_emit (chooser,
258
 
                               image_chooser_signals [CHANGED], 0);
259
 
 
260
 
                rv = TRUE;
261
 
        }
262
 
 
263
 
        return rv;
264
 
}
265
 
 
266
 
static gboolean
267
 
image_drag_motion_cb (GtkWidget *widget,
268
 
                      GdkDragContext *context,
269
 
                      gint x, gint y, guint time, EImageChooser *chooser)
270
 
{
271
 
        GList *p;
272
 
 
273
 
        if (!chooser->priv->editable)
274
 
                return FALSE;
275
 
 
276
 
        for (p = context->targets; p != NULL; p = p->next) {
277
 
                char *possible_type;
278
 
 
279
 
                possible_type = gdk_atom_name (GDK_POINTER_TO_ATOM (p->data));
280
 
                if (!strcmp (possible_type, URI_LIST_TYPE)) {
281
 
                        g_free (possible_type);
282
 
                        gdk_drag_status (context, GDK_ACTION_COPY, time);
283
 
                        return TRUE;
284
 
                }
285
 
 
286
 
                g_free (possible_type);
287
 
        }
288
 
 
289
 
        return FALSE;
290
 
}
291
 
 
292
 
static gboolean
293
 
image_drag_drop_cb (GtkWidget *widget,
294
 
                    GdkDragContext *context,
295
 
                    gint x, gint y, guint time, EImageChooser *chooser)
296
 
{
297
 
        GList *p;
298
 
 
299
 
        if (!chooser->priv->editable)
300
 
                return FALSE;
301
 
 
302
 
        if (context->targets == NULL) {
303
 
                return FALSE;
304
 
        }
305
 
 
306
 
        for (p = context->targets; p != NULL; p = p->next) {
307
 
                char *possible_type;
308
 
 
309
 
                possible_type = gdk_atom_name (GDK_POINTER_TO_ATOM (p->data));
310
 
                if (!strcmp (possible_type, URI_LIST_TYPE)) {
311
 
                        g_free (possible_type);
312
 
                        gtk_drag_get_data (widget, context,
313
 
                                           GDK_POINTER_TO_ATOM (p->data),
314
 
                                           time);
315
 
                        return TRUE;
316
 
                }
317
 
 
318
 
                g_free (possible_type);
319
 
        }
320
 
 
321
 
        return FALSE;
322
 
}
323
 
 
324
 
static void
325
 
image_drag_data_received_cb (GtkWidget *widget,
326
 
                             GdkDragContext *context,
327
 
                             gint x, gint y,
328
 
                             GtkSelectionData *selection_data,
329
 
                             guint info, guint time, EImageChooser *chooser)
330
 
{
331
 
        char *target_type;
332
 
        gboolean handled = FALSE;
333
 
 
334
 
        target_type = gdk_atom_name (gtk_selection_data_get_target (selection_data));
335
 
 
336
 
        if (!strcmp (target_type, URI_LIST_TYPE)) {
337
 
                const char *data = gtk_selection_data_get_data (selection_data);
338
 
                char *uri;
339
 
                GFile *file;
340
 
                GInputStream *istream;
341
 
                char *nl = strstr (data, "\r\n");
342
 
 
343
 
                if (nl)
344
 
                        uri = g_strndup (data, nl - (char *) data);
345
 
                else
346
 
                        uri = g_strdup (data);
347
 
 
348
 
                file = g_file_new_for_uri (uri);
349
 
                istream = G_INPUT_STREAM (g_file_read (file, NULL, NULL));
350
 
 
351
 
                if (istream != NULL) {
352
 
                        GFileInfo *info;
353
 
 
354
 
                        info = g_file_query_info (file,
355
 
                                                  G_FILE_ATTRIBUTE_STANDARD_SIZE,
356
 
                                                  G_FILE_QUERY_INFO_NONE,
357
 
                                                  NULL, NULL);
358
 
 
359
 
                        if (info != NULL) {
360
 
                                gsize size;
361
 
                                gboolean success;
362
 
                                gchar *buf;
363
 
 
364
 
                                size = g_file_info_get_size (info);
365
 
                                g_object_unref (info);
366
 
 
367
 
                                buf = g_malloc (size);
368
 
 
369
 
                                success = g_input_stream_read_all (istream,
370
 
                                                                   buf,
371
 
                                                                   size,
372
 
                                                                   &size,
373
 
                                                                   NULL,
374
 
                                                                   NULL);
375
 
                                g_input_stream_close (istream, NULL, NULL);
376
 
 
377
 
                                if (success &&
378
 
                                                set_image_from_data (chooser, buf, size))
379
 
                                        handled = TRUE;
380
 
                                else
381
 
                                        g_free (buf);
382
 
                        }
383
 
 
384
 
                        g_object_unref (istream);
385
 
                }
386
 
 
387
 
                g_object_unref (file);
388
 
                g_free (uri);
389
 
        }
390
 
 
391
 
        gtk_drag_finish (context, handled, FALSE, time);
392
 
}
393
 
 
394
 
gboolean
395
 
e_image_chooser_set_from_file (EImageChooser *chooser, const char *filename)
396
 
{
397
 
        gchar *data;
398
 
        gsize data_length;
399
 
 
400
 
        g_return_val_if_fail (E_IS_IMAGE_CHOOSER (chooser), FALSE);
401
 
        g_return_val_if_fail (filename, FALSE);
402
 
 
403
 
        if (!g_file_get_contents (filename, &data, &data_length, NULL)) {
404
 
                return FALSE;
405
 
        }
406
 
 
407
 
        if (!set_image_from_data (chooser, data, data_length))
408
 
                g_free (data);
409
 
 
410
 
        return TRUE;
411
 
}
412
 
 
413
 
void
414
 
e_image_chooser_set_editable (EImageChooser *chooser, gboolean editable)
415
 
{
416
 
        g_return_if_fail (E_IS_IMAGE_CHOOSER (chooser));
417
 
 
418
 
        chooser->priv->editable = editable;
419
 
 
420
 
        gtk_widget_set_sensitive (chooser->priv->browse_button, editable);
421
 
}
422
 
 
423
 
gboolean
424
 
e_image_chooser_get_image_data (EImageChooser *chooser, char **data, gsize *data_length)
425
 
{
426
 
        g_return_val_if_fail (E_IS_IMAGE_CHOOSER (chooser), FALSE);
427
 
        g_return_val_if_fail (data != NULL, FALSE);
428
 
        g_return_val_if_fail (data_length != NULL, FALSE);
429
 
 
430
 
        *data_length = chooser->priv->image_buf_size;
431
 
        *data = g_malloc (*data_length);
432
 
        memcpy (*data, chooser->priv->image_buf, *data_length);
433
 
 
434
 
        return TRUE;
435
 
}
436
 
 
437
 
gboolean
438
 
e_image_chooser_set_image_data (EImageChooser *chooser, char *data, gsize data_length)
439
 
{
440
 
        char *buf;
441
 
 
442
 
        g_return_val_if_fail (E_IS_IMAGE_CHOOSER (chooser), FALSE);
443
 
        g_return_val_if_fail (data != NULL, FALSE);
444
 
 
445
 
        /* yuck, a copy... */
446
 
        buf = g_malloc (data_length);
447
 
        memcpy (buf, data, data_length);
448
 
 
449
 
        if (!set_image_from_data (chooser, buf, data_length)) {
450
 
                g_free (buf);
451
 
                return FALSE;
452
 
        }
453
 
 
454
 
        return TRUE;
455
 
}