Mercurial > pidgin
annotate src/gtkcellview.c @ 13659:a92263b13380
[gaim-migrate @ 16061]
silcgaim_check_silc_dir() checks to make sure the user's private
key has permission 0600. If it doesn't, it chmod's the file.
Nathanael Hoyle pointed out the totally absurd scenario where, if
Gaim is suid root, someone could replace the private key with
something else between the fstat and the chmod so that the file
permissions are changed on a file that the user wouldn't otherwise
have access to. He also suggested a fix along the lines of this
one.
Ethan said this still isn't totally safe, but it should be a little
better, and I don't really care anyway because you'd have to be a
moron to run Gaim with the suid bit set in the first place.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Wed, 19 Apr 2006 02:12:45 +0000 |
parents | 7ab959eb857e |
children |
rev | line source |
---|---|
10708 | 1 /* gtkellview.c |
2 * Copyright (C) 2002, 2003 Kristian Rietveld <kris@gtk.org> | |
3 * | |
4 * This library is free software; you can redistribute it and/or | |
5 * modify it under the terms of the GNU Library General Public | |
6 * License as published by the Free Software Foundation; either | |
7 * version 2 of the License, or (at your option) any later version. | |
8 * | |
9 * This library is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 * Library General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU Library General Public | |
15 * License along with this library; if not, write to the | |
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
17 * Boston, MA 02111-1307, USA. | |
18 */ | |
19 | |
20 /* | |
21 #include <config.h> | |
22 */ | |
23 #include "gtkcellview.h" | |
24 #include <gtk/gtkversion.h> | |
25 #if !GTK_CHECK_VERSION(2,6,0) | |
26 #if GTK_CHECK_VERSION(2,4,0) | |
27 #include <gtk/gtkcelllayout.h> | |
28 #else | |
29 #include "gtkcelllayout.h" | |
30 #endif | |
31 #include <gtk/gtksignal.h> | |
32 #include <gtk/gtkcellrenderertext.h> | |
33 #include <gtk/gtkcellrendererpixbuf.h> | |
34 #include <gobject/gmarshal.h> | |
35 | |
13382
7ab959eb857e
[gaim-migrate @ 15755]
Richard Laager <rlaager@wiktel.com>
parents:
10708
diff
changeset
|
36 #define P_(x) (x) |
10708 | 37 |
38 typedef struct _GtkCellViewCellInfo GtkCellViewCellInfo; | |
39 struct _GtkCellViewCellInfo | |
40 { | |
41 GtkCellRenderer *cell; | |
42 | |
43 gint requested_width; | |
44 gint real_width; | |
45 guint expand : 1; | |
46 guint pack : 1; | |
47 | |
48 GSList *attributes; | |
49 | |
50 GtkCellLayoutDataFunc func; | |
51 gpointer func_data; | |
52 GDestroyNotify destroy; | |
53 }; | |
54 | |
55 struct _GtkCellViewPrivate | |
56 { | |
57 GtkTreeModel *model; | |
58 GtkTreeRowReference *displayed_row; | |
59 GList *cell_list; | |
60 gint spacing; | |
61 | |
62 GdkColor background; | |
63 gboolean background_set; | |
64 }; | |
65 | |
66 | |
67 static void gtk_cell_view_class_init (GtkCellViewClass *klass); | |
68 static void gtk_cell_view_cell_layout_init (GtkCellLayoutIface *iface); | |
69 static void gtk_cell_view_get_property (GObject *object, | |
70 guint param_id, | |
71 GValue *value, | |
72 GParamSpec *pspec); | |
73 static void gtk_cell_view_set_property (GObject *object, | |
74 guint param_id, | |
75 const GValue *value, | |
76 GParamSpec *pspec); | |
77 static void gtk_cell_view_init (GtkCellView *cellview); | |
78 static void gtk_cell_view_finalize (GObject *object); | |
79 static void gtk_cell_view_style_set (GtkWidget *widget, | |
80 GtkStyle *previous_style); | |
81 static void gtk_cell_view_size_request (GtkWidget *widget, | |
82 GtkRequisition *requisition); | |
83 static void gtk_cell_view_size_allocate (GtkWidget *widget, | |
84 GtkAllocation *allocation); | |
85 static gboolean gtk_cell_view_expose (GtkWidget *widget, | |
86 GdkEventExpose *event); | |
87 static void gtk_cell_view_set_valuesv (GtkCellView *cellview, | |
88 GtkCellRenderer *renderer, | |
89 va_list args); | |
90 static GtkCellViewCellInfo *gtk_cell_view_get_cell_info (GtkCellView *cellview, | |
91 GtkCellRenderer *renderer); | |
92 static void gtk_cell_view_set_cell_data (GtkCellView *cellview); | |
93 | |
94 | |
95 static void gtk_cell_view_cell_layout_pack_start (GtkCellLayout *layout, | |
96 GtkCellRenderer *renderer, | |
97 gboolean expand); | |
98 static void gtk_cell_view_cell_layout_pack_end (GtkCellLayout *layout, | |
99 GtkCellRenderer *renderer, | |
100 gboolean expand); | |
101 static void gtk_cell_view_cell_layout_add_attribute (GtkCellLayout *layout, | |
102 GtkCellRenderer *renderer, | |
103 const gchar *attribute, | |
104 gint column); | |
105 static void gtk_cell_view_cell_layout_clear (GtkCellLayout *layout); | |
106 static void gtk_cell_view_cell_layout_clear_attributes (GtkCellLayout *layout, | |
107 GtkCellRenderer *renderer); | |
108 static void gtk_cell_view_cell_layout_set_cell_data_func (GtkCellLayout *layout, | |
109 GtkCellRenderer *cell, | |
110 GtkCellLayoutDataFunc func, | |
111 gpointer func_data, | |
112 GDestroyNotify destroy); | |
113 static void gtk_cell_view_cell_layout_reorder (GtkCellLayout *layout, | |
114 GtkCellRenderer *cell, | |
115 gint position); | |
116 | |
117 | |
118 enum | |
119 { | |
120 PROP_0, | |
121 PROP_BACKGROUND, | |
122 PROP_BACKGROUND_GDK, | |
123 PROP_BACKGROUND_SET | |
124 }; | |
125 | |
126 static GtkObjectClass *parent_class = NULL; | |
127 | |
128 | |
129 GType | |
130 gtk_cell_view_get_type (void) | |
131 { | |
132 static GType cell_view_type = 0; | |
133 | |
134 if (!cell_view_type) | |
135 { | |
136 static const GTypeInfo cell_view_info = | |
137 { | |
138 sizeof (GtkCellViewClass), | |
139 NULL, /* base_init */ | |
140 NULL, /* base_finalize */ | |
141 (GClassInitFunc) gtk_cell_view_class_init, | |
142 NULL, /* class_finalize */ | |
143 NULL, /* class_data */ | |
144 sizeof (GtkCellView), | |
145 0, | |
146 (GInstanceInitFunc) gtk_cell_view_init | |
147 }; | |
148 | |
149 static const GInterfaceInfo cell_layout_info = | |
150 { | |
151 (GInterfaceInitFunc) gtk_cell_view_cell_layout_init, | |
152 NULL, | |
153 NULL | |
154 }; | |
155 | |
156 cell_view_type = g_type_register_static (GTK_TYPE_WIDGET, "GaimGtkCellView", | |
157 &cell_view_info, 0); | |
158 | |
159 g_type_add_interface_static (cell_view_type, GTK_TYPE_CELL_LAYOUT, | |
160 &cell_layout_info); | |
161 } | |
162 | |
163 return cell_view_type; | |
164 } | |
165 | |
166 static void | |
167 gtk_cell_view_class_init (GtkCellViewClass *klass) | |
168 { | |
169 GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | |
170 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); | |
171 | |
172 parent_class = g_type_class_peek_parent (klass); | |
173 | |
174 gobject_class->get_property = gtk_cell_view_get_property; | |
175 gobject_class->set_property = gtk_cell_view_set_property; | |
176 gobject_class->finalize = gtk_cell_view_finalize; | |
177 | |
178 widget_class->expose_event = gtk_cell_view_expose; | |
179 widget_class->size_allocate = gtk_cell_view_size_allocate; | |
180 widget_class->size_request = gtk_cell_view_size_request; | |
181 widget_class->style_set = gtk_cell_view_style_set; | |
182 | |
183 /* properties */ | |
184 g_object_class_install_property (gobject_class, | |
185 PROP_BACKGROUND, | |
186 g_param_spec_string ("background", | |
13382
7ab959eb857e
[gaim-migrate @ 15755]
Richard Laager <rlaager@wiktel.com>
parents:
10708
diff
changeset
|
187 P_("Background color name"), |
7ab959eb857e
[gaim-migrate @ 15755]
Richard Laager <rlaager@wiktel.com>
parents:
10708
diff
changeset
|
188 P_("Background color as a string"), |
10708 | 189 NULL, |
190 G_PARAM_WRITABLE)); | |
191 g_object_class_install_property (gobject_class, | |
192 PROP_BACKGROUND_GDK, | |
193 g_param_spec_boxed ("background_gdk", | |
13382
7ab959eb857e
[gaim-migrate @ 15755]
Richard Laager <rlaager@wiktel.com>
parents:
10708
diff
changeset
|
194 P_("Background color"), |
7ab959eb857e
[gaim-migrate @ 15755]
Richard Laager <rlaager@wiktel.com>
parents:
10708
diff
changeset
|
195 P_("Background color as a GdkColor"), |
10708 | 196 GDK_TYPE_COLOR, |
197 G_PARAM_READABLE | G_PARAM_WRITABLE)); | |
198 | |
199 #define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (gobject_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE)) | |
200 | |
201 ADD_SET_PROP ("background_set", PROP_BACKGROUND_SET, | |
13382
7ab959eb857e
[gaim-migrate @ 15755]
Richard Laager <rlaager@wiktel.com>
parents:
10708
diff
changeset
|
202 P_("Background set"), |
7ab959eb857e
[gaim-migrate @ 15755]
Richard Laager <rlaager@wiktel.com>
parents:
10708
diff
changeset
|
203 P_("Whether this tag affects the background color")); |
10708 | 204 } |
205 | |
206 static void | |
207 gtk_cell_view_cell_layout_init (GtkCellLayoutIface *iface) | |
208 { | |
209 iface->pack_start = gtk_cell_view_cell_layout_pack_start; | |
210 iface->pack_end = gtk_cell_view_cell_layout_pack_end; | |
211 iface->clear = gtk_cell_view_cell_layout_clear; | |
212 iface->add_attribute = gtk_cell_view_cell_layout_add_attribute; | |
213 iface->set_cell_data_func = gtk_cell_view_cell_layout_set_cell_data_func; | |
214 iface->clear_attributes = gtk_cell_view_cell_layout_clear_attributes; | |
215 iface->reorder = gtk_cell_view_cell_layout_reorder; | |
216 } | |
217 | |
218 static void | |
219 gtk_cell_view_get_property (GObject *object, | |
220 guint param_id, | |
221 GValue *value, | |
222 GParamSpec *pspec) | |
223 { | |
224 GtkCellView *view = GTK_CELL_VIEW (object); | |
225 | |
226 switch (param_id) | |
227 { | |
228 case PROP_BACKGROUND_GDK: | |
229 { | |
230 GdkColor color; | |
231 | |
232 color = view->priv->background; | |
233 | |
234 g_value_set_boxed (value, &color); | |
235 } | |
236 break; | |
237 case PROP_BACKGROUND_SET: | |
238 g_value_set_boolean (value, view->priv->background_set); | |
239 break; | |
240 default: | |
241 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); | |
242 break; | |
243 } | |
244 } | |
245 | |
246 static void | |
247 gtk_cell_view_set_property (GObject *object, | |
248 guint param_id, | |
249 const GValue *value, | |
250 GParamSpec *pspec) | |
251 { | |
252 GtkCellView *view = GTK_CELL_VIEW (object); | |
253 | |
254 switch (param_id) | |
255 { | |
256 case PROP_BACKGROUND: | |
257 { | |
258 GdkColor color; | |
259 | |
260 if (!g_value_get_string (value)) | |
261 gtk_cell_view_set_background_color (view, NULL); | |
262 else if (gdk_color_parse (g_value_get_string (value), &color)) | |
263 gtk_cell_view_set_background_color (view, &color); | |
264 else | |
265 g_warning ("Don't know color `%s'", g_value_get_string (value)); | |
266 | |
267 g_object_notify (object, "background_gdk"); | |
268 } | |
269 break; | |
270 case PROP_BACKGROUND_GDK: | |
271 gtk_cell_view_set_background_color (view, g_value_get_boxed (value)); | |
272 break; | |
273 case PROP_BACKGROUND_SET: | |
274 view->priv->background_set = g_value_get_boolean (value); | |
275 break; | |
276 default: | |
277 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); | |
278 break; | |
279 } | |
280 } | |
281 | |
282 static void | |
283 gtk_cell_view_init (GtkCellView *cellview) | |
284 { | |
285 GTK_WIDGET_SET_FLAGS (cellview, GTK_NO_WINDOW); | |
286 | |
287 cellview->priv = g_new0(GtkCellViewPrivate,1); | |
288 } | |
289 | |
290 static void | |
291 gtk_cell_view_style_set (GtkWidget *widget, | |
292 GtkStyle *previous_style) | |
293 { | |
294 if (previous_style && GTK_WIDGET_REALIZED (widget)) | |
295 gdk_window_set_background (widget->window, | |
296 &widget->style->base[GTK_WIDGET_STATE (widget)]); | |
297 } | |
298 | |
299 static void | |
300 gtk_cell_view_finalize (GObject *object) | |
301 { | |
302 GtkCellView *cellview = GTK_CELL_VIEW (object); | |
303 | |
304 gtk_cell_view_cell_layout_clear (GTK_CELL_LAYOUT (cellview)); | |
305 | |
306 if (cellview->priv->model) | |
307 g_object_unref (cellview->priv->model); | |
308 | |
309 if (cellview->priv->displayed_row) | |
310 gtk_tree_row_reference_free (cellview->priv->displayed_row); | |
311 | |
312 if (G_OBJECT_CLASS (parent_class)->finalize) | |
313 (* G_OBJECT_CLASS (parent_class)->finalize) (object); | |
314 | |
315 g_free (cellview->priv); | |
316 } | |
317 | |
318 static void | |
319 gtk_cell_view_size_request (GtkWidget *widget, | |
320 GtkRequisition *requisition) | |
321 { | |
322 GList *i; | |
323 gboolean first_cell = TRUE; | |
324 GtkCellView *cellview; | |
325 | |
326 cellview = GTK_CELL_VIEW (widget); | |
327 | |
328 requisition->width = 0; | |
329 requisition->height = 0; | |
330 | |
331 if (cellview->priv->displayed_row) | |
332 gtk_cell_view_set_cell_data (cellview); | |
333 | |
334 for (i = cellview->priv->cell_list; i; i = i->next) | |
335 { | |
336 gint width, height; | |
337 GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data; | |
338 | |
339 if (!info->cell->visible) | |
340 continue; | |
341 | |
342 if (!first_cell) | |
343 requisition->width += cellview->priv->spacing; | |
344 | |
345 gtk_cell_renderer_get_size (info->cell, widget, NULL, NULL, NULL, | |
346 &width, &height); | |
347 | |
348 info->requested_width = width; | |
349 requisition->width += width; | |
350 requisition->height = MAX (requisition->height, height); | |
351 | |
352 first_cell = FALSE; | |
353 } | |
354 } | |
355 | |
356 static void | |
357 gtk_cell_view_size_allocate (GtkWidget *widget, | |
358 GtkAllocation *allocation) | |
359 { | |
360 GList *i; | |
361 gint expand_cell_count = 0; | |
362 gint full_requested_width = 0; | |
363 gint extra_space; | |
364 GtkCellView *cellview; | |
365 | |
366 widget->allocation = *allocation; | |
367 | |
368 cellview = GTK_CELL_VIEW (widget); | |
369 | |
370 /* checking how much extra space we have */ | |
371 for (i = cellview->priv->cell_list; i; i = i->next) | |
372 { | |
373 GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data; | |
374 | |
375 if (!info->cell->visible) | |
376 continue; | |
377 | |
378 if (info->expand) | |
379 expand_cell_count++; | |
380 | |
381 full_requested_width += info->requested_width; | |
382 } | |
383 | |
384 extra_space = widget->allocation.width - full_requested_width; | |
385 if (extra_space < 0) | |
386 extra_space = 0; | |
387 else if (extra_space > 0 && expand_cell_count > 0) | |
388 extra_space /= expand_cell_count; | |
389 | |
390 /* iterate list for PACK_START cells */ | |
391 for (i = cellview->priv->cell_list; i; i = i->next) | |
392 { | |
393 GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data; | |
394 | |
395 if (info->pack == GTK_PACK_END) | |
396 continue; | |
397 | |
398 if (!info->cell->visible) | |
399 continue; | |
400 | |
401 info->real_width = info->requested_width + (info->expand ? extra_space : 0); | |
402 } | |
403 | |
404 /* iterate list for PACK_END cells */ | |
405 for (i = cellview->priv->cell_list; i; i = i->next) | |
406 { | |
407 GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data; | |
408 | |
409 if (info->pack == GTK_PACK_START) | |
410 continue; | |
411 | |
412 if (!info->cell->visible) | |
413 continue; | |
414 | |
415 info->real_width = info->requested_width + (info->expand ? extra_space : 0); | |
416 } | |
417 } | |
418 | |
419 static gboolean | |
420 gtk_cell_view_expose (GtkWidget *widget, | |
421 GdkEventExpose *event) | |
422 { | |
423 GList *i; | |
424 GtkCellView *cellview; | |
425 GdkRectangle area; | |
426 GtkCellRendererState state; | |
427 gboolean rtl = (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL); | |
428 | |
429 cellview = GTK_CELL_VIEW (widget); | |
430 | |
431 if (! GTK_WIDGET_DRAWABLE (widget)) | |
432 return FALSE; | |
433 | |
434 /* "blank" background */ | |
435 if (cellview->priv->background_set) | |
436 { | |
437 GdkGC *gc; | |
438 | |
439 gc = gdk_gc_new (GTK_WIDGET (cellview)->window); | |
440 gdk_gc_set_rgb_fg_color (gc, &cellview->priv->background); | |
441 | |
442 gdk_draw_rectangle (GTK_WIDGET (cellview)->window, | |
443 gc, | |
444 TRUE, | |
445 | |
446 /*0, 0,*/ | |
447 widget->allocation.x, | |
448 widget->allocation.y, | |
449 | |
450 widget->allocation.width, | |
451 widget->allocation.height); | |
452 | |
453 g_object_unref (G_OBJECT (gc)); | |
454 } | |
455 | |
456 /* set cell data (if available) */ | |
457 if (cellview->priv->displayed_row) | |
458 gtk_cell_view_set_cell_data (cellview); | |
459 else if (cellview->priv->model) | |
460 return FALSE; | |
461 | |
462 /* render cells */ | |
463 area = widget->allocation; | |
464 | |
465 /* we draw on our very own window, initialize x and y to zero */ | |
466 area.x = widget->allocation.x + (rtl ? widget->allocation.width : 0); | |
467 area.y = widget->allocation.y; | |
468 | |
469 if (GTK_WIDGET_STATE (widget) == GTK_STATE_PRELIGHT) | |
470 state = GTK_CELL_RENDERER_PRELIT; | |
471 else | |
472 state = 0; | |
473 | |
474 /* PACK_START */ | |
475 for (i = cellview->priv->cell_list; i; i = i->next) | |
476 { | |
477 GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data; | |
478 | |
479 if (info->pack == GTK_PACK_END) | |
480 continue; | |
481 | |
482 if (!info->cell->visible) | |
483 continue; | |
484 | |
485 area.width = info->real_width; | |
486 if (rtl) | |
487 area.x -= area.width; | |
488 | |
489 gtk_cell_renderer_render (info->cell, | |
490 event->window, | |
491 widget, | |
492 /* FIXME! */ | |
493 &area, &area, &event->area, state); | |
494 | |
495 if (!rtl) | |
496 area.x += info->real_width; | |
497 } | |
498 | |
499 area.x = rtl ? widget->allocation.x : (widget->allocation.x + widget->allocation.width); | |
500 | |
501 /* PACK_END */ | |
502 for (i = cellview->priv->cell_list; i; i = i->next) | |
503 { | |
504 GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data; | |
505 | |
506 if (info->pack == GTK_PACK_START) | |
507 continue; | |
508 | |
509 if (!info->cell->visible) | |
510 continue; | |
511 | |
512 area.width = info->real_width; | |
513 if (!rtl) | |
514 area.x -= area.width; | |
515 | |
516 gtk_cell_renderer_render (info->cell, | |
517 widget->window, | |
518 widget, | |
519 /* FIXME ! */ | |
520 &area, &area, &event->area, state); | |
521 if (rtl) | |
522 area.x += info->real_width; | |
523 } | |
524 | |
525 return FALSE; | |
526 } | |
527 | |
528 static GtkCellViewCellInfo * | |
529 gtk_cell_view_get_cell_info (GtkCellView *cellview, | |
530 GtkCellRenderer *renderer) | |
531 { | |
532 GList *i; | |
533 | |
534 for (i = cellview->priv->cell_list; i; i = i->next) | |
535 { | |
536 GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data; | |
537 | |
538 if (info->cell == renderer) | |
539 return info; | |
540 } | |
541 | |
542 return NULL; | |
543 } | |
544 | |
545 static void | |
546 gtk_cell_view_set_cell_data (GtkCellView *cellview) | |
547 { | |
548 GList *i; | |
549 GtkTreeIter iter; | |
550 GtkTreePath *path; | |
551 | |
552 g_return_if_fail (cellview->priv->displayed_row != NULL); | |
553 | |
554 path = gtk_tree_row_reference_get_path (cellview->priv->displayed_row); | |
555 gtk_tree_model_get_iter (cellview->priv->model, &iter, path); | |
556 gtk_tree_path_free (path); | |
557 | |
558 for (i = cellview->priv->cell_list; i; i = i->next) | |
559 { | |
560 GSList *j; | |
561 GtkCellViewCellInfo *info = i->data; | |
562 | |
563 g_object_freeze_notify (G_OBJECT (info->cell)); | |
564 | |
565 for (j = info->attributes; j && j->next; j = j->next->next) | |
566 { | |
567 gchar *property = j->data; | |
568 gint column = GPOINTER_TO_INT (j->next->data); | |
569 GValue value = {0, }; | |
570 | |
571 gtk_tree_model_get_value (cellview->priv->model, &iter, | |
572 column, &value); | |
573 g_object_set_property (G_OBJECT (info->cell), | |
574 property, &value); | |
575 g_value_unset (&value); | |
576 } | |
577 | |
578 if (info->func) | |
579 (* info->func) (GTK_CELL_LAYOUT (cellview), | |
580 info->cell, | |
581 cellview->priv->model, | |
582 &iter, | |
583 info->func_data); | |
584 | |
585 g_object_thaw_notify (G_OBJECT (info->cell)); | |
586 } | |
587 } | |
588 | |
589 /* GtkCellLayout implementation */ | |
590 static void | |
591 gtk_cell_view_cell_layout_pack_start (GtkCellLayout *layout, | |
592 GtkCellRenderer *renderer, | |
593 gboolean expand) | |
594 { | |
595 GtkCellViewCellInfo *info; | |
596 GtkCellView *cellview = GTK_CELL_VIEW (layout); | |
597 | |
598 g_return_if_fail (GTK_IS_CELL_VIEW (cellview)); | |
599 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer)); | |
600 g_return_if_fail (!gtk_cell_view_get_cell_info (cellview, renderer)); | |
601 | |
602 g_object_ref (G_OBJECT (renderer)); | |
603 gtk_object_sink (GTK_OBJECT (renderer)); | |
604 | |
605 info = g_new0 (GtkCellViewCellInfo, 1); | |
606 info->cell = renderer; | |
607 info->expand = expand ? TRUE : FALSE; | |
608 info->pack = GTK_PACK_START; | |
609 | |
610 cellview->priv->cell_list = g_list_append (cellview->priv->cell_list, info); | |
611 } | |
612 | |
613 static void | |
614 gtk_cell_view_cell_layout_pack_end (GtkCellLayout *layout, | |
615 GtkCellRenderer *renderer, | |
616 gboolean expand) | |
617 { | |
618 GtkCellViewCellInfo *info; | |
619 GtkCellView *cellview = GTK_CELL_VIEW (layout); | |
620 | |
621 g_return_if_fail (GTK_IS_CELL_VIEW (cellview)); | |
622 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer)); | |
623 g_return_if_fail (!gtk_cell_view_get_cell_info (cellview, renderer)); | |
624 | |
625 g_object_ref (G_OBJECT (renderer)); | |
626 gtk_object_sink (GTK_OBJECT (renderer)); | |
627 | |
628 info = g_new0 (GtkCellViewCellInfo, 1); | |
629 info->cell = renderer; | |
630 info->expand = expand ? TRUE : FALSE; | |
631 info->pack = GTK_PACK_END; | |
632 | |
633 cellview->priv->cell_list = g_list_append (cellview->priv->cell_list, info); | |
634 } | |
635 | |
636 static void | |
637 gtk_cell_view_cell_layout_add_attribute (GtkCellLayout *layout, | |
638 GtkCellRenderer *renderer, | |
639 const gchar *attribute, | |
640 gint column) | |
641 { | |
642 GtkCellViewCellInfo *info; | |
643 GtkCellView *cellview = GTK_CELL_VIEW (layout); | |
644 | |
645 g_return_if_fail (GTK_IS_CELL_VIEW (cellview)); | |
646 info = gtk_cell_view_get_cell_info (cellview, renderer); | |
647 g_return_if_fail (info != NULL); | |
648 | |
649 info->attributes = g_slist_prepend (info->attributes, | |
650 GINT_TO_POINTER (column)); | |
651 info->attributes = g_slist_prepend (info->attributes, | |
652 g_strdup (attribute)); | |
653 } | |
654 | |
655 static void | |
656 gtk_cell_view_cell_layout_clear (GtkCellLayout *layout) | |
657 { | |
658 GtkCellView *cellview = GTK_CELL_VIEW (layout); | |
659 | |
660 g_return_if_fail (GTK_IS_CELL_VIEW (cellview)); | |
661 | |
662 while (cellview->priv->cell_list) | |
663 { | |
664 GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)cellview->priv->cell_list->data; | |
665 | |
666 gtk_cell_view_cell_layout_clear_attributes (layout, info->cell); | |
667 g_object_unref (G_OBJECT (info->cell)); | |
668 g_free (info); | |
669 cellview->priv->cell_list = g_list_delete_link (cellview->priv->cell_list, | |
670 cellview->priv->cell_list); | |
671 } | |
672 } | |
673 | |
674 static void | |
675 gtk_cell_view_cell_layout_set_cell_data_func (GtkCellLayout *layout, | |
676 GtkCellRenderer *cell, | |
677 GtkCellLayoutDataFunc func, | |
678 gpointer func_data, | |
679 GDestroyNotify destroy) | |
680 { | |
681 GtkCellView *cellview = GTK_CELL_VIEW (layout); | |
682 GtkCellViewCellInfo *info; | |
683 | |
684 g_return_if_fail (GTK_IS_CELL_VIEW (cellview)); | |
685 | |
686 info = gtk_cell_view_get_cell_info (cellview, cell); | |
687 g_return_if_fail (info != NULL); | |
688 | |
689 if (info->destroy) | |
690 { | |
691 GDestroyNotify d = info->destroy; | |
692 | |
693 info->destroy = NULL; | |
694 d (info->func_data); | |
695 } | |
696 | |
697 info->func = func; | |
698 info->func_data = func_data; | |
699 info->destroy = destroy; | |
700 } | |
701 | |
702 static void | |
703 gtk_cell_view_cell_layout_clear_attributes (GtkCellLayout *layout, | |
704 GtkCellRenderer *renderer) | |
705 { | |
706 GtkCellViewCellInfo *info; | |
707 GtkCellView *cellview = GTK_CELL_VIEW (layout); | |
708 GSList *list; | |
709 | |
710 g_return_if_fail (GTK_IS_CELL_VIEW (cellview)); | |
711 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer)); | |
712 | |
713 info = gtk_cell_view_get_cell_info (cellview, renderer); | |
714 if (info != NULL) | |
715 { | |
716 list = info->attributes; | |
717 while (list && list->next) | |
718 { | |
719 g_free (list->data); | |
720 list = list->next->next; | |
721 } | |
722 | |
723 g_slist_free (info->attributes); | |
724 info->attributes = NULL; | |
725 } | |
726 } | |
727 | |
728 static void | |
729 gtk_cell_view_cell_layout_reorder (GtkCellLayout *layout, | |
730 GtkCellRenderer *cell, | |
731 gint position) | |
732 { | |
733 GList *link; | |
734 GtkCellViewCellInfo *info; | |
735 GtkCellView *cellview = GTK_CELL_VIEW (layout); | |
736 | |
737 g_return_if_fail (GTK_IS_CELL_VIEW (cellview)); | |
738 g_return_if_fail (GTK_IS_CELL_RENDERER (cell)); | |
739 | |
740 info = gtk_cell_view_get_cell_info (cellview, cell); | |
741 | |
742 g_return_if_fail (info != NULL); | |
743 g_return_if_fail (position >= 0); | |
744 | |
745 link = g_list_find (cellview->priv->cell_list, info); | |
746 | |
747 g_return_if_fail (link != NULL); | |
748 | |
749 cellview->priv->cell_list = g_list_remove_link (cellview->priv->cell_list, | |
750 link); | |
751 cellview->priv->cell_list = g_list_insert (cellview->priv->cell_list, | |
752 info, position); | |
753 | |
754 gtk_widget_queue_draw (GTK_WIDGET (cellview)); | |
755 } | |
756 | |
757 /* public API */ | |
758 GtkWidget * | |
759 gtk_cell_view_new (void) | |
760 { | |
761 GtkCellView *cellview; | |
762 | |
763 cellview = GTK_CELL_VIEW (g_object_new (gtk_cell_view_get_type (), NULL)); | |
764 | |
765 return GTK_WIDGET (cellview); | |
766 } | |
767 | |
768 GtkWidget * | |
769 gtk_cell_view_new_with_text (const gchar *text) | |
770 { | |
771 GtkCellView *cellview; | |
772 GtkCellRenderer *renderer; | |
773 GValue value = {0, }; | |
774 | |
775 cellview = GTK_CELL_VIEW (gtk_cell_view_new ()); | |
776 | |
777 renderer = gtk_cell_renderer_text_new (); | |
778 gtk_cell_view_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview), | |
779 renderer, TRUE); | |
780 | |
781 g_value_init (&value, G_TYPE_STRING); | |
782 g_value_set_string (&value, text); | |
783 gtk_cell_view_set_values (cellview, renderer, "text", &value, NULL); | |
784 g_value_unset (&value); | |
785 | |
786 return GTK_WIDGET (cellview); | |
787 } | |
788 | |
789 GtkWidget * | |
790 gtk_cell_view_new_with_markup (const gchar *markup) | |
791 { | |
792 GtkCellView *cellview; | |
793 GtkCellRenderer *renderer; | |
794 GValue value = {0, }; | |
795 | |
796 cellview = GTK_CELL_VIEW (gtk_cell_view_new ()); | |
797 | |
798 renderer = gtk_cell_renderer_text_new (); | |
799 gtk_cell_view_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview), | |
800 renderer, TRUE); | |
801 | |
802 g_value_init (&value, G_TYPE_STRING); | |
803 g_value_set_string (&value, markup); | |
804 gtk_cell_view_set_values (cellview, renderer, "markup", &value, NULL); | |
805 g_value_unset (&value); | |
806 | |
807 return GTK_WIDGET (cellview); | |
808 } | |
809 | |
810 GtkWidget * | |
811 gtk_cell_view_new_with_pixbuf (GdkPixbuf *pixbuf) | |
812 { | |
813 GtkCellView *cellview; | |
814 GtkCellRenderer *renderer; | |
815 GValue value = {0, }; | |
816 | |
817 cellview = GTK_CELL_VIEW (gtk_cell_view_new ()); | |
818 | |
819 renderer = gtk_cell_renderer_pixbuf_new (); | |
820 gtk_cell_view_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview), | |
821 renderer, TRUE); | |
822 | |
823 g_value_init (&value, GDK_TYPE_PIXBUF); | |
824 g_value_set_object (&value, pixbuf); | |
825 gtk_cell_view_set_values (cellview, renderer, "pixbuf", &value, NULL); | |
826 g_value_unset (&value); | |
827 | |
828 return GTK_WIDGET (cellview); | |
829 } | |
830 | |
831 void | |
832 gtk_cell_view_set_value (GtkCellView *cell_view, | |
833 GtkCellRenderer *renderer, | |
834 gchar *property, | |
835 GValue *value) | |
836 { | |
837 g_return_if_fail (GTK_IS_CELL_VIEW (cell_view)); | |
838 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer)); | |
839 | |
840 g_object_set_property (G_OBJECT (renderer), property, value); | |
841 | |
842 /* force resize and redraw */ | |
843 gtk_widget_queue_resize (GTK_WIDGET (cell_view)); | |
844 gtk_widget_queue_draw (GTK_WIDGET (cell_view)); | |
845 } | |
846 | |
847 static void | |
848 gtk_cell_view_set_valuesv (GtkCellView *cell_view, | |
849 GtkCellRenderer *renderer, | |
850 va_list args) | |
851 { | |
852 gchar *attribute; | |
853 GValue *value; | |
854 | |
855 attribute = va_arg (args, gchar *); | |
856 | |
857 while (attribute) | |
858 { | |
859 value = va_arg (args, GValue *); | |
860 gtk_cell_view_set_value (cell_view, renderer, attribute, value); | |
861 attribute = va_arg (args, gchar *); | |
862 } | |
863 } | |
864 | |
865 void | |
866 gtk_cell_view_set_values (GtkCellView *cell_view, | |
867 GtkCellRenderer *renderer, | |
868 ...) | |
869 { | |
870 va_list args; | |
871 | |
872 g_return_if_fail (GTK_IS_CELL_VIEW (cell_view)); | |
873 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer)); | |
874 g_return_if_fail (gtk_cell_view_get_cell_info (cell_view, renderer)); | |
875 | |
876 va_start (args, renderer); | |
877 gtk_cell_view_set_valuesv (cell_view, renderer, args); | |
878 va_end (args); | |
879 } | |
880 | |
881 void | |
882 gtk_cell_view_set_model (GtkCellView *cell_view, | |
883 GtkTreeModel *model) | |
884 { | |
885 g_return_if_fail (GTK_IS_CELL_VIEW (cell_view)); | |
886 g_return_if_fail (GTK_IS_TREE_MODEL (model)); | |
887 | |
888 if (cell_view->priv->model) | |
889 { | |
890 if (cell_view->priv->displayed_row) | |
891 gtk_tree_row_reference_free (cell_view->priv->displayed_row); | |
892 cell_view->priv->displayed_row = NULL; | |
893 | |
894 g_object_unref (G_OBJECT (cell_view->priv->model)); | |
895 cell_view->priv->model = NULL; | |
896 } | |
897 | |
898 cell_view->priv->model = model; | |
899 | |
900 if (cell_view->priv->model) | |
901 g_object_ref (G_OBJECT (cell_view->priv->model)); | |
902 } | |
903 | |
904 /** | |
905 * gtk_cell_view_set_displayed_row: | |
906 * @cell_view: a #GtkCellView | |
907 * @path: a #GtkTreePath or %NULL to unset. | |
908 * | |
909 * Sets the row of the model that is currently displayed | |
910 * by the #GtkCellView. If the path is unset, then the | |
911 * contents of the cellview "stick" at their last value; | |
912 * this is not normally a desired result, but may be | |
913 * a needed intermediate state if say, the model for | |
914 * the #GtkCellView becomes temporarily empty. | |
915 **/ | |
916 void | |
917 gtk_cell_view_set_displayed_row (GtkCellView *cell_view, | |
918 GtkTreePath *path) | |
919 { | |
920 g_return_if_fail (GTK_IS_CELL_VIEW (cell_view)); | |
921 g_return_if_fail (GTK_IS_TREE_MODEL (cell_view->priv->model)); | |
922 | |
923 if (cell_view->priv->displayed_row) | |
924 gtk_tree_row_reference_free (cell_view->priv->displayed_row); | |
925 | |
926 if (path) | |
927 { | |
928 cell_view->priv->displayed_row = | |
929 gtk_tree_row_reference_new (cell_view->priv->model, path); | |
930 } | |
931 else | |
932 cell_view->priv->displayed_row = NULL; | |
933 | |
934 /* force resize and redraw */ | |
935 gtk_widget_queue_resize (GTK_WIDGET (cell_view)); | |
936 gtk_widget_queue_draw (GTK_WIDGET (cell_view)); | |
937 } | |
938 | |
939 GtkTreePath * | |
940 gtk_cell_view_get_displayed_row (GtkCellView *cell_view) | |
941 { | |
942 g_return_val_if_fail (GTK_IS_CELL_VIEW (cell_view), NULL); | |
943 | |
944 if (!cell_view->priv->displayed_row) | |
945 return NULL; | |
946 | |
947 return gtk_tree_row_reference_get_path (cell_view->priv->displayed_row); | |
948 } | |
949 | |
950 gboolean | |
951 gtk_cell_view_get_size_of_row (GtkCellView *cell_view, | |
952 GtkTreePath *path, | |
953 GtkRequisition *requisition) | |
954 { | |
955 GtkTreeRowReference *tmp; | |
956 GtkRequisition req; | |
957 | |
958 g_return_val_if_fail (GTK_IS_CELL_VIEW (cell_view), FALSE); | |
959 g_return_val_if_fail (path != NULL, FALSE); | |
960 g_return_val_if_fail (requisition != NULL, FALSE); | |
961 | |
962 tmp = cell_view->priv->displayed_row; | |
963 cell_view->priv->displayed_row = | |
964 gtk_tree_row_reference_new (cell_view->priv->model, path); | |
965 | |
966 gtk_cell_view_size_request (GTK_WIDGET (cell_view), requisition); | |
967 | |
968 gtk_tree_row_reference_free (cell_view->priv->displayed_row); | |
969 cell_view->priv->displayed_row = tmp; | |
970 | |
971 /* restore actual size info */ | |
972 gtk_cell_view_size_request (GTK_WIDGET (cell_view), &req); | |
973 | |
974 return TRUE; | |
975 } | |
976 | |
977 void | |
978 gtk_cell_view_set_background_color (GtkCellView *view, | |
979 const GdkColor *color) | |
980 { | |
981 g_return_if_fail (GTK_IS_CELL_VIEW (view)); | |
982 | |
983 if (color) | |
984 { | |
985 if (!view->priv->background_set) | |
986 { | |
987 view->priv->background_set = TRUE; | |
988 g_object_notify (G_OBJECT (view), "background_set"); | |
989 } | |
990 | |
991 view->priv->background = *color; | |
992 } | |
993 else | |
994 { | |
995 if (view->priv->background_set) | |
996 { | |
997 view->priv->background_set = FALSE; | |
998 g_object_notify (G_OBJECT (view), "background_set"); | |
999 } | |
1000 } | |
1001 } | |
1002 #endif /* Gtk 2.6 */ |