| 28 #define PURPLE_IMAGE_GET_PRIVATE(obj) \ |
28 #define PURPLE_IMAGE_GET_PRIVATE(obj) \ |
| 29 (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_IMAGE, PurpleImagePrivate)) |
29 (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_IMAGE, PurpleImagePrivate)) |
| 30 |
30 |
| 31 typedef struct { |
31 typedef struct { |
| 32 gchar *path; |
32 gchar *path; |
| 33 GString *contents; |
33 |
| |
34 GBytes *contents; |
| 34 |
35 |
| 35 const gchar *extension; |
36 const gchar *extension; |
| 36 const gchar *mime; |
37 const gchar *mime; |
| 37 gchar *gen_filename; |
38 gchar *gen_filename; |
| 38 gchar *friendly_filename; |
39 gchar *friendly_filename; |
| 39 |
|
| 40 gboolean is_ready; |
|
| 41 gboolean has_failed; |
|
| 42 } PurpleImagePrivate; |
40 } PurpleImagePrivate; |
| 43 |
41 |
| 44 enum |
42 enum { |
| 45 { |
|
| 46 PROP_0, |
43 PROP_0, |
| 47 PROP_IS_READY, |
|
| 48 PROP_HAS_FAILED, |
|
| 49 PROP_LAST |
44 PROP_LAST |
| 50 }; |
45 }; |
| 51 |
46 |
| 52 enum |
47 static GObjectClass *parent_class; |
| |
48 static GParamSpec *properties[PROP_LAST]; |
| |
49 |
| |
50 /****************************************************************************** |
| |
51 * Object stuff |
| |
52 ******************************************************************************/ |
| |
53 static void |
| |
54 purple_image_init(PurpleImage *image) { |
| |
55 } |
| |
56 |
| |
57 static void |
| |
58 purple_image_finalize(GObject *obj) { |
| |
59 PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(obj); |
| |
60 |
| |
61 g_bytes_unref(priv->contents); |
| |
62 |
| |
63 g_free(priv->path); |
| |
64 g_free(priv->gen_filename); |
| |
65 g_free(priv->friendly_filename); |
| |
66 |
| |
67 G_OBJECT_CLASS(parent_class)->finalize(obj); |
| |
68 } |
| |
69 |
| |
70 static void |
| |
71 purple_image_set_property(GObject *object, guint par_id, |
| |
72 const GValue *value, GParamSpec *pspec) |
| 53 { |
73 { |
| 54 SIG_READY, |
74 switch (par_id) { |
| 55 SIG_FAILED, |
75 default: |
| 56 SIG_LAST |
76 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec); |
| 57 }; |
77 break; |
| 58 |
78 } |
| 59 static GObjectClass *parent_class; |
79 } |
| 60 static guint signals[SIG_LAST]; |
80 |
| 61 static GParamSpec *properties[PROP_LAST]; |
81 static void |
| |
82 purple_image_get_property(GObject *object, guint par_id, GValue *value, |
| |
83 GParamSpec *pspec) |
| |
84 { |
| |
85 switch (par_id) { |
| |
86 default: |
| |
87 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec); |
| |
88 break; |
| |
89 } |
| |
90 } |
| |
91 |
| |
92 static void |
| |
93 purple_image_class_init(PurpleImageClass *klass) { |
| |
94 GObjectClass *gobj_class = G_OBJECT_CLASS(klass); |
| |
95 |
| |
96 parent_class = g_type_class_peek_parent(klass); |
| |
97 |
| |
98 gobj_class->finalize = purple_image_finalize; |
| |
99 gobj_class->get_property = purple_image_get_property; |
| |
100 gobj_class->set_property = purple_image_set_property; |
| |
101 |
| |
102 g_object_class_install_properties(gobj_class, PROP_LAST, properties); |
| |
103 } |
| |
104 |
| |
105 G_DEFINE_TYPE_WITH_PRIVATE(PurpleImage, purple_image, G_TYPE_OBJECT); |
| 62 |
106 |
| 63 /****************************************************************************** |
107 /****************************************************************************** |
| 64 * Internal logic |
108 * API |
| 65 ******************************************************************************/ |
109 ******************************************************************************/ |
| 66 |
110 PurpleImage * |
| 67 static void |
111 purple_image_new_from_bytes(GBytes *bytes, GError **error) { |
| 68 has_failed(PurpleImage *image) |
112 return g_object_new( |
| 69 { |
113 PURPLE_TYPE_IMAGE, |
| 70 gboolean ready_changed; |
114 NULL |
| 71 PurpleImagePrivate *priv; |
115 ); |
| 72 priv = PURPLE_IMAGE_GET_PRIVATE(image); |
116 } |
| 73 |
117 |
| 74 g_return_if_fail(!priv->has_failed); |
118 PurpleImage * |
| 75 |
119 purple_image_new_from_file(const gchar *path) { |
| 76 priv->has_failed = TRUE; |
120 PurpleImage *image = NULL; |
| 77 ready_changed = (priv->is_ready != FALSE); |
121 GBytes *bytes = NULL; |
| 78 priv->is_ready = FALSE; |
122 gchar *contents = NULL; |
| 79 |
123 gsize length = 0; |
| 80 if (priv->contents) { |
124 |
| 81 g_string_free(priv->contents, TRUE); |
125 if(!g_file_test(path, G_FILE_TEST_EXISTS)) { |
| 82 priv->contents = NULL; |
126 return NULL; |
| 83 } |
127 } |
| 84 |
128 |
| 85 if (ready_changed) { |
129 if(!g_file_get_contents(path, &contents, &length, NULL)) { |
| 86 g_object_notify_by_pspec(G_OBJECT(image), |
130 return NULL; |
| 87 properties[PROP_IS_READY]); |
131 } |
| 88 } |
132 |
| 89 g_object_notify_by_pspec(G_OBJECT(image), properties[PROP_HAS_FAILED]); |
133 bytes = g_bytes_new_take(contents, length); |
| 90 g_signal_emit(image, signals[SIG_FAILED], 0); |
134 |
| 91 } |
135 image = purple_image_new_from_bytes(bytes, NULL); |
| 92 |
136 |
| 93 static void |
137 g_bytes_unref(bytes); |
| 94 became_ready(PurpleImage *image) |
138 |
| 95 { |
139 return image; |
| 96 PurpleImagePrivate *priv; |
140 } |
| 97 priv = PURPLE_IMAGE_GET_PRIVATE(image); |
141 |
| 98 |
142 PurpleImage * |
| 99 g_return_if_fail(!priv->has_failed); |
143 purple_image_new_from_data(const guint8 *data, gsize length) { |
| 100 g_return_if_fail(!priv->is_ready); |
144 PurpleImage *image; |
| 101 |
145 GBytes *bytes = NULL; |
| 102 priv->is_ready = TRUE; |
146 |
| 103 |
147 bytes = g_bytes_new(data, length); |
| 104 g_object_notify_by_pspec(G_OBJECT(image), properties[PROP_IS_READY]); |
148 |
| 105 g_signal_emit(image, signals[SIG_READY], 0); |
149 image = purple_image_new_from_bytes(bytes, NULL); |
| 106 } |
150 |
| 107 |
151 g_bytes_unref(bytes); |
| 108 static void |
152 |
| 109 steal_contents(PurpleImagePrivate *priv, gpointer data, gsize length) |
153 return image; |
| 110 { |
154 } |
| 111 g_return_if_fail(priv != NULL); |
155 |
| 112 g_return_if_fail(priv->contents == NULL); |
156 PurpleImage * |
| 113 g_return_if_fail(data != NULL); |
157 purple_image_new_from_data_take(guint8 *data, gsize length) { |
| 114 g_return_if_fail(length > 0); |
158 PurpleImage *image; |
| 115 |
159 GBytes *bytes = NULL; |
| 116 priv->contents = g_string_new(NULL); |
160 |
| 117 g_free(priv->contents->str); |
161 bytes = g_bytes_new(data, length); |
| 118 priv->contents->str = data; |
162 |
| 119 priv->contents->len = priv->contents->allocated_len = length; |
163 image = purple_image_new_from_bytes(bytes, NULL); |
| 120 } |
164 |
| 121 |
165 g_bytes_unref(bytes); |
| 122 static void |
166 |
| 123 fill_data(PurpleImage *image) |
167 return image; |
| 124 { |
|
| 125 PurpleImagePrivate *priv; |
|
| 126 GError *error = NULL; |
|
| 127 gchar *contents; |
|
| 128 gsize length; |
|
| 129 |
|
| 130 priv = PURPLE_IMAGE_GET_PRIVATE(image); |
|
| 131 if (priv->contents) |
|
| 132 return; |
|
| 133 |
|
| 134 if (!priv->is_ready) |
|
| 135 return; |
|
| 136 |
|
| 137 g_return_if_fail(priv->path); |
|
| 138 (void)g_file_get_contents(priv->path, &contents, &length, &error); |
|
| 139 if (error) { |
|
| 140 purple_debug_error("image", "failed to read '%s' image: %s", |
|
| 141 priv->path, error->message); |
|
| 142 g_error_free(error); |
|
| 143 |
|
| 144 has_failed(image); |
|
| 145 return; |
|
| 146 } |
|
| 147 |
|
| 148 steal_contents(priv, contents, length); |
|
| 149 } |
|
| 150 |
|
| 151 |
|
| 152 /****************************************************************************** |
|
| 153 * API implementation |
|
| 154 ******************************************************************************/ |
|
| 155 |
|
| 156 PurpleImage * |
|
| 157 purple_image_new_from_file(const gchar *path, gboolean be_eager) |
|
| 158 { |
|
| 159 PurpleImagePrivate *priv; |
|
| 160 PurpleImage *img; |
|
| 161 |
|
| 162 g_return_val_if_fail(path != NULL, NULL); |
|
| 163 g_return_val_if_fail(g_file_test(path, G_FILE_TEST_EXISTS), NULL); |
|
| 164 |
|
| 165 img = g_object_new(PURPLE_TYPE_IMAGE, NULL); |
|
| 166 purple_image_set_friendly_filename(img, path); |
|
| 167 priv = PURPLE_IMAGE_GET_PRIVATE(img); |
|
| 168 priv->path = g_strdup(path); |
|
| 169 |
|
| 170 if (be_eager) { |
|
| 171 fill_data(img); |
|
| 172 if (!priv->contents) { |
|
| 173 g_object_unref(img); |
|
| 174 return NULL; |
|
| 175 } |
|
| 176 |
|
| 177 g_assert(priv->is_ready && !priv->has_failed); |
|
| 178 } |
|
| 179 |
|
| 180 return img; |
|
| 181 } |
|
| 182 |
|
| 183 PurpleImage * |
|
| 184 purple_image_new_from_data(gpointer data, gsize length) |
|
| 185 { |
|
| 186 PurpleImage *img; |
|
| 187 PurpleImagePrivate *priv; |
|
| 188 |
|
| 189 g_return_val_if_fail(data != NULL, NULL); |
|
| 190 g_return_val_if_fail(length > 0, NULL); |
|
| 191 |
|
| 192 img = g_object_new(PURPLE_TYPE_IMAGE, NULL); |
|
| 193 priv = PURPLE_IMAGE_GET_PRIVATE(img); |
|
| 194 |
|
| 195 steal_contents(priv, data, length); |
|
| 196 |
|
| 197 return img; |
|
| 198 } |
168 } |
| 199 |
169 |
| 200 gboolean |
170 gboolean |
| 201 purple_image_save(PurpleImage *image, const gchar *path) |
171 purple_image_save(PurpleImage *image, const gchar *path) { |
| 202 { |
|
| 203 PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image); |
172 PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image); |
| 204 gconstpointer data; |
173 gconstpointer data; |
| 205 gsize len; |
174 gsize len; |
| 206 gboolean succ; |
175 gboolean succ; |
| 207 |
176 |
| 221 |
190 |
| 222 return succ; |
191 return succ; |
| 223 } |
192 } |
| 224 |
193 |
| 225 const gchar * |
194 const gchar * |
| 226 purple_image_get_path(PurpleImage *image) |
195 purple_image_get_path(PurpleImage *image) { |
| 227 { |
|
| 228 PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image); |
196 PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image); |
| 229 |
197 |
| 230 g_return_val_if_fail(priv != NULL, NULL); |
198 g_return_val_if_fail(priv != NULL, NULL); |
| 231 |
199 |
| 232 return priv->path; |
200 return priv->path; |
| 233 } |
201 } |
| 234 |
202 |
| 235 gboolean |
|
| 236 purple_image_is_ready(PurpleImage *image) |
|
| 237 { |
|
| 238 PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image); |
|
| 239 |
|
| 240 g_return_val_if_fail(priv != NULL, FALSE); |
|
| 241 |
|
| 242 return priv->is_ready; |
|
| 243 } |
|
| 244 |
|
| 245 gboolean |
|
| 246 purple_image_has_failed(PurpleImage *image) |
|
| 247 { |
|
| 248 PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image); |
|
| 249 |
|
| 250 g_return_val_if_fail(priv != NULL, TRUE); |
|
| 251 |
|
| 252 return priv->has_failed; |
|
| 253 } |
|
| 254 |
|
| 255 gsize |
203 gsize |
| 256 purple_image_get_size(PurpleImage *image) |
204 purple_image_get_size(PurpleImage *image) { |
| 257 { |
|
| 258 PurpleImagePrivate *priv; |
205 PurpleImagePrivate *priv; |
| |
206 |
| |
207 g_return_val_if_fail(PURPLE_IS_IMAGE(image), 0); |
| |
208 |
| 259 priv = PURPLE_IMAGE_GET_PRIVATE(image); |
209 priv = PURPLE_IMAGE_GET_PRIVATE(image); |
| 260 |
210 |
| 261 g_return_val_if_fail(priv != NULL, 0); |
211 return g_bytes_get_size(priv->contents); |
| 262 g_return_val_if_fail(priv->is_ready, 0); |
|
| 263 |
|
| 264 fill_data(image); |
|
| 265 g_return_val_if_fail(priv->contents, 0); |
|
| 266 |
|
| 267 return priv->contents->len; |
|
| 268 } |
212 } |
| 269 |
213 |
| 270 gconstpointer |
214 gconstpointer |
| 271 purple_image_get_data(PurpleImage *image) |
215 purple_image_get_data(PurpleImage *image) { |
| 272 { |
216 PurpleImagePrivate *priv = NULL; |
| 273 PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image); |
217 |
| 274 |
218 g_return_val_if_fail(PURPLE_IS_IMAGE(image), NULL); |
| 275 g_return_val_if_fail(priv != NULL, NULL); |
219 |
| 276 g_return_val_if_fail(priv->is_ready, NULL); |
220 priv = PURPLE_IMAGE_GET_PRIVATE(image); |
| 277 |
221 |
| 278 fill_data(image); |
222 return g_bytes_get_data(priv->contents, NULL); |
| 279 g_return_val_if_fail(priv->contents, NULL); |
223 } |
| 280 |
224 |
| 281 return priv->contents->str; |
225 const gchar * |
| 282 } |
226 purple_image_get_extension(PurpleImage *image) { |
| 283 |
|
| 284 const gchar * |
|
| 285 purple_image_get_extension(PurpleImage *image) |
|
| 286 { |
|
| 287 PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image); |
227 PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image); |
| 288 gconstpointer data; |
228 gconstpointer data; |
| 289 |
229 |
| 290 g_return_val_if_fail(priv != NULL, NULL); |
230 g_return_val_if_fail(priv != NULL, NULL); |
| 291 |
231 |
| 398 g_free(priv->friendly_filename); |
335 g_free(priv->friendly_filename); |
| 399 priv->friendly_filename = g_strdup(escaped); |
336 priv->friendly_filename = g_strdup(escaped); |
| 400 } |
337 } |
| 401 |
338 |
| 402 const gchar * |
339 const gchar * |
| 403 purple_image_get_friendly_filename(PurpleImage *image) |
340 purple_image_get_friendly_filename(PurpleImage *image) { |
| 404 { |
341 PurpleImagePrivate *priv = NULL; |
| 405 PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image); |
342 |
| 406 |
343 g_return_val_if_fail(PURPLE_IS_IMAGE(image), NULL); |
| 407 g_return_val_if_fail(priv != NULL, NULL); |
344 |
| 408 |
345 priv = PURPLE_IMAGE_GET_PRIVATE(image); |
| 409 if (G_UNLIKELY(!priv->friendly_filename)) { |
346 |
| 410 const gchar *newname = purple_image_generate_filename(image); |
347 if(priv->friendly_filename) { |
| 411 gsize newname_len = strlen(newname); |
348 return priv->friendly_filename; |
| 412 |
349 } |
| 413 if (newname_len < 10) |
350 |
| 414 return NULL; |
351 return purple_image_get_friendly_filename(image); |
| 415 |
352 } |
| 416 /* let's use last 6 characters from checksum + 4 characters |
353 |
| 417 * from file ext */ |
354 PurpleImage * |
| 418 newname += newname_len - 10; |
355 purple_image_transfer_new(void) { |
| 419 priv->friendly_filename = g_strdup(newname); |
356 return NULL; |
| 420 } |
|
| 421 |
|
| 422 if (G_UNLIKELY(priv->is_ready && |
|
| 423 strchr(priv->friendly_filename, '.') == NULL)) |
|
| 424 { |
|
| 425 const gchar *ext = purple_image_get_extension(image); |
|
| 426 gchar *tmp; |
|
| 427 if (!ext) |
|
| 428 return priv->friendly_filename; |
|
| 429 |
|
| 430 tmp = g_strdup_printf("%s.%s", priv->friendly_filename, ext); |
|
| 431 g_free(priv->friendly_filename); |
|
| 432 priv->friendly_filename = tmp; |
|
| 433 } |
|
| 434 |
|
| 435 return priv->friendly_filename; |
|
| 436 } |
|
| 437 |
|
| 438 PurpleImage * |
|
| 439 purple_image_transfer_new(void) |
|
| 440 { |
|
| 441 PurpleImage *img; |
|
| 442 PurpleImagePrivate *priv; |
|
| 443 |
|
| 444 img = g_object_new(PURPLE_TYPE_IMAGE, NULL); |
|
| 445 priv = PURPLE_IMAGE_GET_PRIVATE(img); |
|
| 446 |
|
| 447 priv->is_ready = FALSE; |
|
| 448 priv->contents = g_string_new(NULL); |
|
| 449 |
|
| 450 return img; |
|
| 451 } |
357 } |
| 452 |
358 |
| 453 void |
359 void |
| 454 purple_image_transfer_write(PurpleImage *image, gconstpointer data, |
360 purple_image_transfer_write(PurpleImage *image, gconstpointer data, gsize length) { |
| 455 gsize length) |
|
| 456 { |
|
| 457 PurpleImagePrivate *priv = |
|
| 458 PURPLE_IMAGE_GET_PRIVATE(image); |
|
| 459 |
|
| 460 g_return_if_fail(priv != NULL); |
|
| 461 g_return_if_fail(!priv->has_failed); |
|
| 462 g_return_if_fail(!priv->is_ready); |
|
| 463 g_return_if_fail(priv->contents != NULL); |
|
| 464 g_return_if_fail(data != NULL || length == 0); |
|
| 465 |
|
| 466 if (length == 0) |
|
| 467 return; |
|
| 468 |
|
| 469 g_string_append_len(priv->contents, (const gchar*)data, length); |
|
| 470 } |
361 } |
| 471 |
362 |
| 472 void |
363 void |
| 473 purple_image_transfer_close(PurpleImage *image) |
364 purple_image_transfer_close(PurpleImage *image) { |
| 474 { |
|
| 475 PurpleImagePrivate *priv = |
|
| 476 PURPLE_IMAGE_GET_PRIVATE(image); |
|
| 477 |
|
| 478 g_return_if_fail(priv != NULL); |
|
| 479 g_return_if_fail(!priv->has_failed); |
|
| 480 g_return_if_fail(!priv->is_ready); |
|
| 481 g_return_if_fail(priv->contents != NULL); |
|
| 482 |
|
| 483 if (priv->contents->len == 0) { |
|
| 484 purple_debug_error("image", "image is empty"); |
|
| 485 has_failed(image); |
|
| 486 return; |
|
| 487 } |
|
| 488 |
|
| 489 became_ready(image); |
|
| 490 } |
365 } |
| 491 |
366 |
| 492 void |
367 void |
| 493 purple_image_transfer_failed(PurpleImage *image) |
368 purple_image_transfer_failed(PurpleImage *image) { |
| 494 { |
369 } |
| 495 PurpleImagePrivate *priv = |
|
| 496 PURPLE_IMAGE_GET_PRIVATE(image); |
|
| 497 |
|
| 498 g_return_if_fail(priv != NULL); |
|
| 499 g_return_if_fail(!priv->has_failed); |
|
| 500 g_return_if_fail(!priv->is_ready); |
|
| 501 |
|
| 502 has_failed(image); |
|
| 503 } |
|
| 504 |
|
| 505 /****************************************************************************** |
|
| 506 * Object stuff |
|
| 507 ******************************************************************************/ |
|
| 508 |
|
| 509 static void |
|
| 510 purple_image_init(GTypeInstance *instance, gpointer klass) |
|
| 511 { |
|
| 512 PurpleImage *image = PURPLE_IMAGE(instance); |
|
| 513 PurpleImagePrivate *priv = |
|
| 514 PURPLE_IMAGE_GET_PRIVATE(image); |
|
| 515 |
|
| 516 priv->contents = NULL; |
|
| 517 priv->is_ready = TRUE; |
|
| 518 priv->has_failed = FALSE; |
|
| 519 } |
|
| 520 |
|
| 521 static void |
|
| 522 purple_image_finalize(GObject *obj) |
|
| 523 { |
|
| 524 PurpleImage *image = PURPLE_IMAGE(obj); |
|
| 525 PurpleImagePrivate *priv = |
|
| 526 PURPLE_IMAGE_GET_PRIVATE(image); |
|
| 527 |
|
| 528 if (priv->contents) |
|
| 529 g_string_free(priv->contents, TRUE); |
|
| 530 g_free(priv->path); |
|
| 531 g_free(priv->gen_filename); |
|
| 532 g_free(priv->friendly_filename); |
|
| 533 |
|
| 534 G_OBJECT_CLASS(parent_class)->finalize(obj); |
|
| 535 } |
|
| 536 |
|
| 537 static void |
|
| 538 purple_image_get_property(GObject *object, guint par_id, GValue *value, |
|
| 539 GParamSpec *pspec) |
|
| 540 { |
|
| 541 PurpleImage *image = PURPLE_IMAGE(object); |
|
| 542 PurpleImagePrivate *priv = PURPLE_IMAGE_GET_PRIVATE(image); |
|
| 543 |
|
| 544 switch (par_id) { |
|
| 545 case PROP_IS_READY: |
|
| 546 g_value_set_boolean(value, priv->is_ready); |
|
| 547 break; |
|
| 548 case PROP_HAS_FAILED: |
|
| 549 g_value_set_boolean(value, priv->has_failed); |
|
| 550 break; |
|
| 551 default: |
|
| 552 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec); |
|
| 553 break; |
|
| 554 } |
|
| 555 } |
|
| 556 |
|
| 557 static void |
|
| 558 purple_image_class_init(PurpleImageClass *klass) |
|
| 559 { |
|
| 560 GObjectClass *gobj_class = G_OBJECT_CLASS(klass); |
|
| 561 |
|
| 562 parent_class = g_type_class_peek_parent(klass); |
|
| 563 |
|
| 564 g_type_class_add_private(klass, sizeof(PurpleImagePrivate)); |
|
| 565 |
|
| 566 gobj_class->finalize = purple_image_finalize; |
|
| 567 gobj_class->get_property = purple_image_get_property; |
|
| 568 |
|
| 569 properties[PROP_IS_READY] = g_param_spec_boolean("is-ready", |
|
| 570 "Is ready", "The image is ready to be displayed. Image may " |
|
| 571 "change the state to failed in a single case: if it's backed " |
|
| 572 "by a file and that file fails to load", |
|
| 573 TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); |
|
| 574 |
|
| 575 properties[PROP_HAS_FAILED] = g_param_spec_boolean("has-failed", |
|
| 576 "Has hailed", "The remote host has failed to send the image", |
|
| 577 FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); |
|
| 578 |
|
| 579 g_object_class_install_properties(gobj_class, PROP_LAST, properties); |
|
| 580 |
|
| 581 /** |
|
| 582 * PurpleImage::failed: |
|
| 583 * @image: a image that failed to transfer. |
|
| 584 * |
|
| 585 * Called when a @image fails to be transferred. It's guaranteed to be |
|
| 586 * fired at most once for a particular @image. |
|
| 587 */ |
|
| 588 signals[SIG_FAILED] = g_signal_new("failed", G_OBJECT_CLASS_TYPE(klass), |
|
| 589 0, 0, NULL, NULL, |
|
| 590 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); |
|
| 591 |
|
| 592 /** |
|
| 593 * PurpleImage::ready: |
|
| 594 * @image: a image that became ready. |
|
| 595 * |
|
| 596 * Called when a @image becames ready to be displayed. It's guaranteed to be |
|
| 597 * fired at most once for a particular @image. |
|
| 598 */ |
|
| 599 signals[SIG_READY] = g_signal_new("ready", G_OBJECT_CLASS_TYPE(klass), |
|
| 600 0, 0, NULL, NULL, |
|
| 601 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); |
|
| 602 } |
|
| 603 |
|
| 604 GType |
|
| 605 purple_image_get_type(void) |
|
| 606 { |
|
| 607 static GType type = 0; |
|
| 608 |
|
| 609 if (G_UNLIKELY(type == 0)) { |
|
| 610 static const GTypeInfo info = { |
|
| 611 .class_size = sizeof(PurpleImageClass), |
|
| 612 .class_init = (GClassInitFunc)purple_image_class_init, |
|
| 613 .instance_size = sizeof(PurpleImage), |
|
| 614 .instance_init = purple_image_init, |
|
| 615 }; |
|
| 616 |
|
| 617 type = g_type_register_static(G_TYPE_OBJECT, |
|
| 618 "PurpleImage", &info, 0); |
|
| 619 } |
|
| 620 |
|
| 621 return type; |
|
| 622 } |
|