1 /*
2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU Lesser General Public License as published by
4 * the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful, but
7 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9 * for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public License
12 * along with this program; if not, see <http://www.gnu.org/licenses/>.
13 *
14 *
15 * Authors:
16 * Chris Lahey <clahey@ximian.com>
17 *
18 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
19 *
20 */
21
22 #include "evolution-config.h"
23
24 #include <gtk/gtk.h>
25 #include <libgnomecanvas/libgnomecanvas.h>
26
27 #include "e-table-group.h"
28 #include "e-table-group-container.h"
29 #include "e-table-group-leaf.h"
30 #include "e-table-item.h"
31
32 G_DEFINE_TYPE (
33 ETableGroup,
34 e_table_group,
35 GNOME_TYPE_CANVAS_GROUP)
36
37 #define ETG_CLASS(e) (E_TABLE_GROUP_CLASS(G_OBJECT_GET_CLASS(e)))
38
39 enum {
40 CURSOR_CHANGE,
41 CURSOR_ACTIVATED,
42 DOUBLE_CLICK,
43 RIGHT_CLICK,
44 CLICK,
45 KEY_PRESS,
46 START_DRAG,
47 LAST_SIGNAL
48 };
49
50 enum {
51 PROP_0,
52 PROP_IS_EDITING
53 };
54
55 static guint etg_signals[LAST_SIGNAL] = { 0, };
56
57 static gboolean etg_get_focus (ETableGroup *table_group);
58
59 static void
etg_dispose(GObject * object)60 etg_dispose (GObject *object)
61 {
62 ETableGroup *table_group = E_TABLE_GROUP (object);
63
64 g_clear_object (&table_group->header);
65 g_clear_object (&table_group->full_header);
66 g_clear_object (&table_group->model);
67
68 /* Chain up to parent's dispose() method. */
69 G_OBJECT_CLASS (e_table_group_parent_class)->dispose (object);
70 }
71
72 static void
etg_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)73 etg_get_property (GObject *object,
74 guint property_id,
75 GValue *value,
76 GParamSpec *pspec)
77 {
78 ETableGroup *etg = E_TABLE_GROUP (object);
79
80 switch (property_id) {
81 case PROP_IS_EDITING:
82 g_value_set_boolean (value, e_table_group_is_editing (etg));
83 break;
84 default:
85 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
86 break;
87 }
88 }
89
90 /**
91 * e_table_group_new
92 * @parent: The %GnomeCanvasGroup to create a child of.
93 * @full_header: The full header of the #ETable.
94 * @header: The current header of the #ETable.
95 * @model: The #ETableModel of the #ETable.
96 * @sort_info: The #ETableSortInfo of the #ETable.
97 * @n: The grouping information object to group by.
98 *
99 * #ETableGroup is a collection of rows of an #ETable. It's a
100 * %GnomeCanvasItem. There are two different forms. If n < the
101 * number of groupings in the given #ETableSortInfo, then the
102 * #ETableGroup will need to contain other #ETableGroups, thus it
103 * creates an #ETableGroupContainer. Otherwise, it will just contain
104 * an #ETableItem, and thus it creates an #ETableGroupLeaf.
105 *
106 * Returns: The new #ETableGroup.
107 */
108 ETableGroup *
e_table_group_new(GnomeCanvasGroup * parent,ETableHeader * full_header,ETableHeader * header,ETableModel * model,ETableSortInfo * sort_info,gint n)109 e_table_group_new (GnomeCanvasGroup *parent,
110 ETableHeader *full_header,
111 ETableHeader *header,
112 ETableModel *model,
113 ETableSortInfo *sort_info,
114 gint n)
115 {
116 g_return_val_if_fail (model != NULL, NULL);
117
118 if (n < e_table_sort_info_grouping_get_count (sort_info)) {
119 return e_table_group_container_new (
120 parent, full_header, header, model, sort_info, n);
121 } else {
122 return e_table_group_leaf_new (
123 parent, full_header, header, model, sort_info);
124 }
125 }
126
127 /**
128 * e_table_group_construct
129 * @parent: The %GnomeCanvasGroup to create a child of.
130 * @table_group: The #ETableGroup to construct.
131 * @full_header: The full header of the #ETable.
132 * @header: The current header of the #ETable.
133 * @model: The #ETableModel of the #ETable.
134 *
135 * This routine does the base construction of the #ETableGroup.
136 */
137 void
e_table_group_construct(GnomeCanvasGroup * parent,ETableGroup * table_group,ETableHeader * full_header,ETableHeader * header,ETableModel * model)138 e_table_group_construct (GnomeCanvasGroup *parent,
139 ETableGroup *table_group,
140 ETableHeader *full_header,
141 ETableHeader *header,
142 ETableModel *model)
143 {
144 table_group->full_header = g_object_ref (full_header);
145 table_group->header = g_object_ref (header);
146 table_group->model = g_object_ref (model);
147 g_object_set (table_group, "parent", parent, NULL);
148 }
149
150 /**
151 * e_table_group_add
152 * @table_group: The #ETableGroup to add a row to
153 * @row: The row to add.
154 *
155 * This routine adds the given row from the #ETableModel to this set
156 * of rows.
157 */
158 void
e_table_group_add(ETableGroup * table_group,gint row)159 e_table_group_add (ETableGroup *table_group,
160 gint row)
161 {
162 g_return_if_fail (E_IS_TABLE_GROUP (table_group));
163
164 g_return_if_fail (ETG_CLASS (table_group)->add != NULL);
165 ETG_CLASS (table_group)->add (table_group, row);
166 }
167
168 /**
169 * e_table_group_add_array
170 * @table_group: The #ETableGroup to add to
171 * @array: The array to add.
172 * @count: The number of times to add
173 *
174 * This routine adds all the rows in the array to this set of rows.
175 * It assumes that the array is already sorted properly.
176 */
177 void
e_table_group_add_array(ETableGroup * table_group,const gint * array,gint count)178 e_table_group_add_array (ETableGroup *table_group,
179 const gint *array,
180 gint count)
181 {
182 g_return_if_fail (E_IS_TABLE_GROUP (table_group));
183
184 g_return_if_fail (ETG_CLASS (table_group)->add_array != NULL);
185 ETG_CLASS (table_group)->add_array (table_group, array, count);
186 }
187
188 /**
189 * e_table_group_add_all
190 * @table_group: The #ETableGroup to add to
191 *
192 * This routine adds all the rows from the #ETableModel to this set
193 * of rows.
194 */
195 void
e_table_group_add_all(ETableGroup * table_group)196 e_table_group_add_all (ETableGroup *table_group)
197 {
198 g_return_if_fail (E_IS_TABLE_GROUP (table_group));
199
200 g_return_if_fail (ETG_CLASS (table_group)->add_all != NULL);
201 ETG_CLASS (table_group)->add_all (table_group);
202 }
203
204 /**
205 * e_table_group_remove
206 * @table_group: The #ETableGroup to remove a row from
207 * @row: The row to remove.
208 *
209 * This routine removes the given row from the #ETableModel from this
210 * set of rows.
211 *
212 * Returns: TRUE if the row was deleted and FALSE if the row was not
213 * found.
214 */
215 gboolean
e_table_group_remove(ETableGroup * table_group,gint row)216 e_table_group_remove (ETableGroup *table_group,
217 gint row)
218 {
219 g_return_val_if_fail (E_IS_TABLE_GROUP (table_group), FALSE);
220
221 g_return_val_if_fail (ETG_CLASS (table_group)->remove != NULL, FALSE);
222 return ETG_CLASS (table_group)->remove (table_group, row);
223 }
224
225 /**
226 * e_table_group_increment
227 * @table_group: The #ETableGroup to increment
228 * @position: The position to increment from
229 * @amount: The amount to increment.
230 *
231 * This routine adds amount to all rows greater than or equal to
232 * position. This is to handle when a row gets inserted into the
233 * model.
234 */
235 void
e_table_group_increment(ETableGroup * table_group,gint position,gint amount)236 e_table_group_increment (ETableGroup *table_group,
237 gint position,
238 gint amount)
239 {
240 g_return_if_fail (E_IS_TABLE_GROUP (table_group));
241
242 g_return_if_fail (ETG_CLASS (table_group)->increment != NULL);
243 ETG_CLASS (table_group)->increment (table_group, position, amount);
244 }
245
246 /**
247 * e_table_group_increment
248 * @table_group: The #ETableGroup to decrement
249 * @position: The position to decrement from
250 * @amount: The amount to decrement
251 *
252 * This routine removes amount from all rows greater than or equal to
253 * position. This is to handle when a row gets deleted from the
254 * model.
255 */
256 void
e_table_group_decrement(ETableGroup * table_group,gint position,gint amount)257 e_table_group_decrement (ETableGroup *table_group,
258 gint position,
259 gint amount)
260 {
261 g_return_if_fail (E_IS_TABLE_GROUP (table_group));
262
263 g_return_if_fail (ETG_CLASS (table_group)->decrement != NULL);
264 ETG_CLASS (table_group)->decrement (table_group, position, amount);
265 }
266
267 /**
268 * e_table_group_increment
269 * @table_group: The #ETableGroup to count
270 *
271 * This routine calculates the number of rows shown in this group.
272 *
273 * Returns: The number of rows.
274 */
275 gint
e_table_group_row_count(ETableGroup * table_group)276 e_table_group_row_count (ETableGroup *table_group)
277 {
278 g_return_val_if_fail (E_IS_TABLE_GROUP (table_group), -1);
279
280 g_return_val_if_fail (ETG_CLASS (table_group)->row_count != NULL, -1);
281 return ETG_CLASS (table_group)->row_count (table_group);
282 }
283
284 /**
285 * e_table_group_set_focus
286 * @table_group: The #ETableGroup to set
287 * @direction: The direction the focus is coming from.
288 * @view_col: The column to set the focus in.
289 *
290 * Sets the focus to this widget. Places the focus in the view column
291 * coming from direction direction.
292 */
293 void
e_table_group_set_focus(ETableGroup * table_group,EFocus direction,gint view_col)294 e_table_group_set_focus (ETableGroup *table_group,
295 EFocus direction,
296 gint view_col)
297 {
298 g_return_if_fail (E_IS_TABLE_GROUP (table_group));
299
300 g_return_if_fail (ETG_CLASS (table_group)->set_focus != NULL);
301 ETG_CLASS (table_group)->set_focus (table_group, direction, view_col);
302 }
303
304 /**
305 * e_table_group_get_focus
306 * @table_group: The #ETableGroup to check
307 *
308 * Calculates if this group has the focus.
309 *
310 * Returns: TRUE if this group has the focus.
311 */
312 gboolean
e_table_group_get_focus(ETableGroup * table_group)313 e_table_group_get_focus (ETableGroup *table_group)
314 {
315 g_return_val_if_fail (E_IS_TABLE_GROUP (table_group), FALSE);
316
317 g_return_val_if_fail (ETG_CLASS (table_group)->get_focus != NULL, FALSE);
318 return ETG_CLASS (table_group)->get_focus (table_group);
319 }
320
321 /**
322 * e_table_group_get_focus_column
323 * @table_group: The #ETableGroup to check
324 *
325 * Calculates which column in this group has the focus.
326 *
327 * Returns: The column index (view column).
328 */
329 gint
e_table_group_get_focus_column(ETableGroup * table_group)330 e_table_group_get_focus_column (ETableGroup *table_group)
331 {
332 g_return_val_if_fail (E_IS_TABLE_GROUP (table_group), -1);
333
334 g_return_val_if_fail (ETG_CLASS (table_group)->get_focus_column != NULL, -1);
335 return ETG_CLASS (table_group)->get_focus_column (table_group);
336 }
337
338 /**
339 * e_table_group_get_printable
340 * @table_group: #ETableGroup which will be printed
341 *
342 * This routine creates and returns an %EPrintable that can be used to
343 * print the given #ETableGroup.
344 *
345 * Returns: The %EPrintable.
346 */
347 EPrintable *
e_table_group_get_printable(ETableGroup * table_group)348 e_table_group_get_printable (ETableGroup *table_group)
349 {
350 g_return_val_if_fail (E_IS_TABLE_GROUP (table_group), NULL);
351
352 g_return_val_if_fail (ETG_CLASS (table_group)->get_printable != NULL, NULL);
353 return ETG_CLASS (table_group)->get_printable (table_group);
354 }
355
356 /**
357 * e_table_group_compute_location
358 * @table_group: #ETableGroup to look in.
359 * @x: A pointer to the x location to find in the #ETableGroup.
360 * @y: A pointer to the y location to find in the #ETableGroup.
361 * @row: A pointer to the location to store the found row in.
362 * @col: A pointer to the location to store the found col in.
363 *
364 * This routine locates the pixel location (*x, *y) in the
365 * #ETableGroup. If that location is in the #ETableGroup, *row and
366 * *col are set to the view row and column where it was found. If
367 * that location is not in the #ETableGroup, the height of the
368 * #ETableGroup is removed from the value y points to.
369 */
370 void
e_table_group_compute_location(ETableGroup * table_group,gint * x,gint * y,gint * row,gint * col)371 e_table_group_compute_location (ETableGroup *table_group,
372 gint *x,
373 gint *y,
374 gint *row,
375 gint *col)
376 {
377 g_return_if_fail (E_IS_TABLE_GROUP (table_group));
378
379 g_return_if_fail (ETG_CLASS (table_group)->compute_location != NULL);
380 ETG_CLASS (table_group)->compute_location (table_group, x, y, row, col);
381 }
382
383 void
e_table_group_get_mouse_over(ETableGroup * table_group,gint * row,gint * col)384 e_table_group_get_mouse_over (ETableGroup *table_group,
385 gint *row,
386 gint *col)
387 {
388 g_return_if_fail (E_IS_TABLE_GROUP (table_group));
389
390 g_return_if_fail (ETG_CLASS (table_group)->get_mouse_over != NULL);
391 ETG_CLASS (table_group)->get_mouse_over (table_group, row, col);
392 }
393
394 /**
395 * e_table_group_get_position
396 * @table_group: #ETableGroup to look in.
397 * @x: A pointer to the location to store the found x location in.
398 * @y: A pointer to the location to store the found y location in.
399 * @row: A pointer to the row number to find.
400 * @col: A pointer to the col number to find.
401 *
402 * This routine finds the view cell (row, col) in the #ETableGroup.
403 * If that location is in the #ETableGroup *@x and *@y are set to the
404 * upper left hand corner of the cell found. If that location is not
405 * in the #ETableGroup, the number of rows in the #ETableGroup is
406 * removed from the value row points to.
407 */
408 void
e_table_group_get_cell_geometry(ETableGroup * table_group,gint * row,gint * col,gint * x,gint * y,gint * width,gint * height)409 e_table_group_get_cell_geometry (ETableGroup *table_group,
410 gint *row,
411 gint *col,
412 gint *x,
413 gint *y,
414 gint *width,
415 gint *height)
416 {
417 g_return_if_fail (E_IS_TABLE_GROUP (table_group));
418
419 g_return_if_fail (ETG_CLASS (table_group)->get_cell_geometry != NULL);
420 ETG_CLASS (table_group)->get_cell_geometry (table_group, row, col, x, y, width, height);
421 }
422
423 /**
424 * e_table_group_cursor_change
425 * @table_group: #ETableGroup to emit the signal on
426 * @row: The new cursor row (model row)
427 *
428 * This routine emits the "cursor_change" signal.
429 */
430 void
e_table_group_cursor_change(ETableGroup * e_table_group,gint row)431 e_table_group_cursor_change (ETableGroup *e_table_group,
432 gint row)
433 {
434 g_return_if_fail (e_table_group != NULL);
435 g_return_if_fail (E_IS_TABLE_GROUP (e_table_group));
436
437 g_signal_emit (
438 e_table_group,
439 etg_signals[CURSOR_CHANGE], 0,
440 row);
441 }
442
443 /**
444 * e_table_group_cursor_activated
445 * @table_group: #ETableGroup to emit the signal on
446 * @row: The cursor row (model row)
447 *
448 * This routine emits the "cursor_activated" signal.
449 */
450 void
e_table_group_cursor_activated(ETableGroup * e_table_group,gint row)451 e_table_group_cursor_activated (ETableGroup *e_table_group,
452 gint row)
453 {
454 g_return_if_fail (e_table_group != NULL);
455 g_return_if_fail (E_IS_TABLE_GROUP (e_table_group));
456
457 g_signal_emit (
458 e_table_group,
459 etg_signals[CURSOR_ACTIVATED], 0,
460 row);
461 }
462
463 /**
464 * e_table_group_double_click
465 * @table_group: #ETableGroup to emit the signal on
466 * @row: The row clicked on (model row)
467 * @col: The col clicked on (model col)
468 * @event: The event that caused this signal
469 *
470 * This routine emits the "double_click" signal.
471 */
472 void
e_table_group_double_click(ETableGroup * e_table_group,gint row,gint col,GdkEvent * event)473 e_table_group_double_click (ETableGroup *e_table_group,
474 gint row,
475 gint col,
476 GdkEvent *event)
477 {
478 g_return_if_fail (e_table_group != NULL);
479 g_return_if_fail (E_IS_TABLE_GROUP (e_table_group));
480
481 g_signal_emit (
482 e_table_group,
483 etg_signals[DOUBLE_CLICK], 0,
484 row, col, event);
485 }
486
487 /**
488 * e_table_group_right_click
489 * @table_group: #ETableGroup to emit the signal on
490 * @row: The row clicked on (model row)
491 * @col: The col clicked on (model col)
492 * @event: The event that caused this signal
493 *
494 * This routine emits the "right_click" signal.
495 */
496 gboolean
e_table_group_right_click(ETableGroup * e_table_group,gint row,gint col,GdkEvent * event)497 e_table_group_right_click (ETableGroup *e_table_group,
498 gint row,
499 gint col,
500 GdkEvent *event)
501 {
502 gboolean return_val = FALSE;
503
504 g_return_val_if_fail (e_table_group != NULL, FALSE);
505 g_return_val_if_fail (E_IS_TABLE_GROUP (e_table_group), FALSE);
506
507 g_signal_emit (
508 e_table_group,
509 etg_signals[RIGHT_CLICK], 0,
510 row, col, event, &return_val);
511
512 return return_val;
513 }
514
515 /**
516 * e_table_group_click
517 * @table_group: #ETableGroup to emit the signal on
518 * @row: The row clicked on (model row)
519 * @col: The col clicked on (model col)
520 * @event: The event that caused this signal
521 *
522 * This routine emits the "click" signal.
523 */
524 gboolean
e_table_group_click(ETableGroup * table_group,gint row,gint col,GdkEvent * event)525 e_table_group_click (ETableGroup *table_group,
526 gint row,
527 gint col,
528 GdkEvent *event)
529 {
530 gboolean return_val = FALSE;
531
532 g_return_val_if_fail (E_IS_TABLE_GROUP (table_group), FALSE);
533
534 g_signal_emit (
535 table_group,
536 etg_signals[CLICK], 0,
537 row, col, event, &return_val);
538
539 return return_val;
540 }
541
542 /**
543 * e_table_group_key_press
544 * @table_group: #ETableGroup to emit the signal on
545 * @row: The cursor row (model row)
546 * @col: The cursor col (model col)
547 * @event: The event that caused this signal
548 *
549 * This routine emits the "key_press" signal.
550 */
551 gboolean
e_table_group_key_press(ETableGroup * e_table_group,gint row,gint col,GdkEvent * event)552 e_table_group_key_press (ETableGroup *e_table_group,
553 gint row,
554 gint col,
555 GdkEvent *event)
556 {
557 gboolean return_val = FALSE;
558
559 g_return_val_if_fail (e_table_group != NULL, FALSE);
560 g_return_val_if_fail (E_IS_TABLE_GROUP (e_table_group), FALSE);
561
562 g_signal_emit (
563 e_table_group,
564 etg_signals[KEY_PRESS], 0,
565 row, col, event, &return_val);
566
567 return return_val;
568 }
569
570 /**
571 * e_table_group_start_drag
572 * @table_group: #ETableGroup to emit the signal on
573 * @row: The cursor row (model row)
574 * @col: The cursor col (model col)
575 * @event: The event that caused this signal
576 *
577 * This routine emits the "start_drag" signal.
578 */
579 gboolean
e_table_group_start_drag(ETableGroup * e_table_group,gint row,gint col,GdkEvent * event)580 e_table_group_start_drag (ETableGroup *e_table_group,
581 gint row,
582 gint col,
583 GdkEvent *event)
584 {
585 gboolean return_val = FALSE;
586
587 g_return_val_if_fail (e_table_group != NULL, FALSE);
588 g_return_val_if_fail (E_IS_TABLE_GROUP (e_table_group), FALSE);
589
590 g_signal_emit (
591 e_table_group,
592 etg_signals[START_DRAG], 0,
593 row, col, event, &return_val);
594
595 return return_val;
596 }
597
598 /**
599 * e_table_group_get_header
600 * @table_group: #ETableGroup to check
601 *
602 * This routine returns the #ETableGroup's header.
603 *
604 * Returns: The #ETableHeader.
605 */
606 ETableHeader *
e_table_group_get_header(ETableGroup * table_group)607 e_table_group_get_header (ETableGroup *table_group)
608 {
609 g_return_val_if_fail (E_IS_TABLE_GROUP (table_group), NULL);
610
611 return table_group->header;
612 }
613
614 static gint
etg_event(GnomeCanvasItem * item,GdkEvent * event)615 etg_event (GnomeCanvasItem *item,
616 GdkEvent *event)
617 {
618 ETableGroup *table_group = E_TABLE_GROUP (item);
619 gboolean return_val = TRUE;
620
621 switch (event->type) {
622
623 case GDK_FOCUS_CHANGE:
624 table_group->has_focus = event->focus_change.in;
625 return_val = FALSE;
626 break;
627
628 default:
629 return_val = FALSE;
630 }
631 if (return_val == FALSE) {
632 if (GNOME_CANVAS_ITEM_CLASS (e_table_group_parent_class)->event)
633 return GNOME_CANVAS_ITEM_CLASS (e_table_group_parent_class)->event (item, event);
634 }
635 return return_val;
636
637 }
638
639 static gboolean
etg_get_focus(ETableGroup * table_group)640 etg_get_focus (ETableGroup *table_group)
641 {
642 return table_group->has_focus;
643 }
644
645 static void
e_table_group_class_init(ETableGroupClass * class)646 e_table_group_class_init (ETableGroupClass *class)
647 {
648 GnomeCanvasItemClass *item_class = GNOME_CANVAS_ITEM_CLASS (class);
649 GObjectClass *object_class = G_OBJECT_CLASS (class);
650
651 object_class->dispose = etg_dispose;
652 object_class->get_property = etg_get_property;
653
654 item_class->event = etg_event;
655
656 class->cursor_change = NULL;
657 class->cursor_activated = NULL;
658 class->double_click = NULL;
659 class->right_click = NULL;
660 class->click = NULL;
661 class->key_press = NULL;
662 class->start_drag = NULL;
663
664 class->add = NULL;
665 class->add_array = NULL;
666 class->add_all = NULL;
667 class->remove = NULL;
668 class->row_count = NULL;
669 class->increment = NULL;
670 class->decrement = NULL;
671 class->set_focus = NULL;
672 class->get_focus = etg_get_focus;
673 class->get_printable = NULL;
674 class->compute_location = NULL;
675 class->get_mouse_over = NULL;
676 class->get_cell_geometry = NULL;
677
678 g_object_class_install_property (
679 object_class,
680 PROP_IS_EDITING,
681 g_param_spec_boolean (
682 "is-editing",
683 "Whether is in an editing mode",
684 "Whether is in an editing mode",
685 FALSE,
686 G_PARAM_READABLE));
687
688 etg_signals[CURSOR_CHANGE] = g_signal_new (
689 "cursor_change",
690 G_OBJECT_CLASS_TYPE (object_class),
691 G_SIGNAL_RUN_LAST,
692 G_STRUCT_OFFSET (ETableGroupClass, cursor_change),
693 NULL, NULL,
694 g_cclosure_marshal_VOID__INT,
695 G_TYPE_NONE, 1,
696 G_TYPE_INT);
697
698 etg_signals[CURSOR_ACTIVATED] = g_signal_new (
699 "cursor_activated",
700 G_OBJECT_CLASS_TYPE (object_class),
701 G_SIGNAL_RUN_LAST,
702 G_STRUCT_OFFSET (ETableGroupClass, cursor_activated),
703 NULL, NULL,
704 g_cclosure_marshal_VOID__INT,
705 G_TYPE_NONE, 1,
706 G_TYPE_INT);
707
708 etg_signals[DOUBLE_CLICK] = g_signal_new (
709 "double_click",
710 G_OBJECT_CLASS_TYPE (object_class),
711 G_SIGNAL_RUN_LAST,
712 G_STRUCT_OFFSET (ETableGroupClass, double_click),
713 NULL, NULL,
714 e_marshal_VOID__INT_INT_BOXED,
715 G_TYPE_NONE, 3,
716 G_TYPE_INT,
717 G_TYPE_INT,
718 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
719
720 etg_signals[RIGHT_CLICK] = g_signal_new (
721 "right_click",
722 G_OBJECT_CLASS_TYPE (object_class),
723 G_SIGNAL_RUN_LAST,
724 G_STRUCT_OFFSET (ETableGroupClass, right_click),
725 g_signal_accumulator_true_handled, NULL,
726 e_marshal_BOOLEAN__INT_INT_BOXED,
727 G_TYPE_BOOLEAN, 3,
728 G_TYPE_INT,
729 G_TYPE_INT,
730 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
731
732 etg_signals[CLICK] = g_signal_new (
733 "click",
734 G_OBJECT_CLASS_TYPE (object_class),
735 G_SIGNAL_RUN_LAST,
736 G_STRUCT_OFFSET (ETableGroupClass, click),
737 g_signal_accumulator_true_handled, NULL,
738 e_marshal_BOOLEAN__INT_INT_BOXED,
739 G_TYPE_BOOLEAN, 3,
740 G_TYPE_INT,
741 G_TYPE_INT,
742 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
743
744 etg_signals[KEY_PRESS] = g_signal_new (
745 "key_press",
746 G_OBJECT_CLASS_TYPE (object_class),
747 G_SIGNAL_RUN_LAST,
748 G_STRUCT_OFFSET (ETableGroupClass, key_press),
749 g_signal_accumulator_true_handled, NULL,
750 e_marshal_BOOLEAN__INT_INT_BOXED,
751 G_TYPE_BOOLEAN, 3,
752 G_TYPE_INT,
753 G_TYPE_INT,
754 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
755
756 etg_signals[START_DRAG] = g_signal_new (
757 "start_drag",
758 G_OBJECT_CLASS_TYPE (object_class),
759 G_SIGNAL_RUN_LAST,
760 G_STRUCT_OFFSET (ETableGroupClass, start_drag),
761 g_signal_accumulator_true_handled, NULL,
762 e_marshal_BOOLEAN__INT_INT_BOXED,
763 G_TYPE_BOOLEAN, 3,
764 G_TYPE_INT,
765 G_TYPE_INT,
766 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
767 }
768
769 static void
e_table_group_init(ETableGroup * table_group)770 e_table_group_init (ETableGroup *table_group)
771 {
772 /* nothing to do */
773 }
774
775 gboolean
e_table_group_is_editing(ETableGroup * table_group)776 e_table_group_is_editing (ETableGroup *table_group)
777 {
778 static gboolean in = FALSE;
779 gboolean is_editing = FALSE;
780
781 g_return_val_if_fail (E_IS_TABLE_GROUP (table_group), FALSE);
782
783 /* this should be called from the main thread only,
784 * and each descendant overrides the property,
785 * thus might cause no call recursion */
786 if (in) {
787 g_warn_if_reached ();
788 return FALSE;
789 }
790
791 in = TRUE;
792
793 g_object_get (G_OBJECT (table_group), "is-editing", &is_editing, NULL);
794
795 in = FALSE;
796
797 return is_editing;
798 }
799