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 "e-selection-model.h"
25
26 #include <glib/gi18n.h>
27 #include <gdk/gdkkeysyms.h>
28
29 #include "e-marshal.h"
30
31 G_DEFINE_TYPE (
32 ESelectionModel,
33 e_selection_model,
34 G_TYPE_OBJECT)
35
36 enum {
37 CURSOR_CHANGED,
38 CURSOR_ACTIVATED,
39 SELECTION_CHANGED,
40 SELECTION_ROW_CHANGED,
41 LAST_SIGNAL
42 };
43
44 static guint signals[LAST_SIGNAL] = { 0, };
45
46 enum {
47 PROP_0,
48 PROP_SORTER,
49 PROP_SELECTION_MODE,
50 PROP_CURSOR_MODE
51 };
52
53 inline static void
add_sorter(ESelectionModel * model,ESorter * sorter)54 add_sorter (ESelectionModel *model,
55 ESorter *sorter)
56 {
57 model->sorter = sorter;
58 if (sorter) {
59 g_object_ref (sorter);
60 }
61 }
62
63 inline static void
drop_sorter(ESelectionModel * model)64 drop_sorter (ESelectionModel *model)
65 {
66 if (model->sorter) {
67 g_object_unref (model->sorter);
68 }
69 model->sorter = NULL;
70 }
71
72 static void
selection_model_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)73 selection_model_set_property (GObject *object,
74 guint property_id,
75 const GValue *value,
76 GParamSpec *pspec)
77 {
78 ESelectionModel *model = E_SELECTION_MODEL (object);
79
80 switch (property_id) {
81 case PROP_SORTER:
82 drop_sorter (model);
83 add_sorter (
84 model, g_value_get_object (value) ?
85 E_SORTER (g_value_get_object (value)) : NULL);
86 break;
87
88 case PROP_SELECTION_MODE:
89 model->mode = g_value_get_int (value);
90 if (model->mode == GTK_SELECTION_SINGLE) {
91 gint cursor_row = e_selection_model_cursor_row (model);
92 gint cursor_col = e_selection_model_cursor_col (model);
93 e_selection_model_do_something (model, cursor_row, cursor_col, 0);
94 }
95 break;
96
97 case PROP_CURSOR_MODE:
98 model->cursor_mode = g_value_get_int (value);
99 break;
100 }
101 }
102
103 static void
selection_model_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)104 selection_model_get_property (GObject *object,
105 guint property_id,
106 GValue *value,
107 GParamSpec *pspec)
108 {
109 ESelectionModel *model = E_SELECTION_MODEL (object);
110
111 switch (property_id) {
112 case PROP_SORTER:
113 g_value_set_object (value, model->sorter);
114 break;
115
116 case PROP_SELECTION_MODE:
117 g_value_set_int (value, model->mode);
118 break;
119
120 case PROP_CURSOR_MODE:
121 g_value_set_int (value, model->cursor_mode);
122 break;
123 }
124 }
125
126 static void
selection_model_dispose(GObject * object)127 selection_model_dispose (GObject *object)
128 {
129 ESelectionModel *model;
130
131 model = E_SELECTION_MODEL (object);
132
133 drop_sorter (model);
134
135 /* Chain up to parent's dispose() method. */
136 G_OBJECT_CLASS (e_selection_model_parent_class)->dispose (object);
137 }
138
139 static void
e_selection_model_class_init(ESelectionModelClass * class)140 e_selection_model_class_init (ESelectionModelClass *class)
141 {
142 GObjectClass *object_class;
143
144 object_class = G_OBJECT_CLASS (class);
145 object_class->set_property = selection_model_set_property;
146 object_class->get_property = selection_model_get_property;
147 object_class->dispose = selection_model_dispose;
148
149 signals[CURSOR_CHANGED] = g_signal_new (
150 "cursor_changed",
151 G_OBJECT_CLASS_TYPE (object_class),
152 G_SIGNAL_RUN_LAST,
153 G_STRUCT_OFFSET (ESelectionModelClass, cursor_changed),
154 NULL, NULL,
155 e_marshal_VOID__INT_INT,
156 G_TYPE_NONE, 2,
157 G_TYPE_INT,
158 G_TYPE_INT);
159
160 signals[CURSOR_ACTIVATED] = g_signal_new (
161 "cursor_activated",
162 G_OBJECT_CLASS_TYPE (object_class),
163 G_SIGNAL_RUN_LAST,
164 G_STRUCT_OFFSET (ESelectionModelClass, cursor_activated),
165 NULL, NULL,
166 e_marshal_VOID__INT_INT,
167 G_TYPE_NONE, 2,
168 G_TYPE_INT,
169 G_TYPE_INT);
170
171 signals[SELECTION_CHANGED] = g_signal_new (
172 "selection_changed",
173 G_OBJECT_CLASS_TYPE (object_class),
174 G_SIGNAL_RUN_LAST,
175 G_STRUCT_OFFSET (ESelectionModelClass, selection_changed),
176 NULL, NULL,
177 g_cclosure_marshal_VOID__VOID,
178 G_TYPE_NONE, 0);
179
180 signals[SELECTION_ROW_CHANGED] = g_signal_new (
181 "selection_row_changed",
182 G_OBJECT_CLASS_TYPE (object_class),
183 G_SIGNAL_RUN_LAST,
184 G_STRUCT_OFFSET (ESelectionModelClass, selection_row_changed),
185 NULL, NULL,
186 g_cclosure_marshal_VOID__INT,
187 G_TYPE_NONE, 1,
188 G_TYPE_INT);
189
190 g_object_class_install_property (
191 object_class,
192 PROP_SORTER,
193 g_param_spec_object (
194 "sorter",
195 "Sorter",
196 NULL,
197 E_TYPE_SORTER,
198 G_PARAM_READWRITE));
199
200 g_object_class_install_property (
201 object_class,
202 PROP_SELECTION_MODE,
203 g_param_spec_int (
204 "selection_mode",
205 "Selection Mode",
206 NULL,
207 GTK_SELECTION_NONE,
208 GTK_SELECTION_MULTIPLE,
209 GTK_SELECTION_SINGLE,
210 G_PARAM_READWRITE));
211
212 g_object_class_install_property (
213 object_class,
214 PROP_CURSOR_MODE,
215 g_param_spec_int (
216 "cursor_mode",
217 "Cursor Mode",
218 NULL,
219 E_CURSOR_LINE,
220 E_CURSOR_SPREADSHEET,
221 E_CURSOR_LINE,
222 G_PARAM_READWRITE));
223 }
224
225 static void
e_selection_model_init(ESelectionModel * model)226 e_selection_model_init (ESelectionModel *model)
227 {
228 model->mode = GTK_SELECTION_MULTIPLE;
229 model->cursor_mode = E_CURSOR_SIMPLE;
230 model->old_selection = -1;
231 }
232
233 /**
234 * e_selection_model_is_row_selected
235 * @model: #ESelectionModel to check
236 * @n: The row to check
237 *
238 * This routine calculates whether the given row is selected.
239 *
240 * Returns: %TRUE if the given row is selected
241 */
242 gboolean
e_selection_model_is_row_selected(ESelectionModel * model,gint n)243 e_selection_model_is_row_selected (ESelectionModel *model,
244 gint n)
245 {
246 ESelectionModelClass *class;
247
248 g_return_val_if_fail (E_IS_SELECTION_MODEL (model), FALSE);
249
250 class = E_SELECTION_MODEL_GET_CLASS (model);
251 g_return_val_if_fail (class != NULL, FALSE);
252 g_return_val_if_fail (class->is_row_selected != NULL, FALSE);
253
254 return class->is_row_selected (model, n);
255 }
256
257 /**
258 * e_selection_model_foreach
259 * @model: #ESelectionModel to traverse
260 * @callback: The callback function to call back.
261 * @closure: The closure
262 *
263 * This routine calls the given callback function once for each
264 * selected row, passing closure as the closure.
265 */
266 void
e_selection_model_foreach(ESelectionModel * model,EForeachFunc callback,gpointer closure)267 e_selection_model_foreach (ESelectionModel *model,
268 EForeachFunc callback,
269 gpointer closure)
270 {
271 ESelectionModelClass *class;
272
273 g_return_if_fail (E_IS_SELECTION_MODEL (model));
274 g_return_if_fail (callback != NULL);
275
276 class = E_SELECTION_MODEL_GET_CLASS (model);
277 g_return_if_fail (class != NULL);
278 g_return_if_fail (class->foreach != NULL);
279
280 class->foreach (model, callback, closure);
281 }
282
283 /**
284 * e_selection_model_clear
285 * @model: #ESelectionModel to clear
286 *
287 * This routine clears the selection to no rows selected.
288 */
289 void
e_selection_model_clear(ESelectionModel * model)290 e_selection_model_clear (ESelectionModel *model)
291 {
292 ESelectionModelClass *class;
293
294 g_return_if_fail (E_IS_SELECTION_MODEL (model));
295
296 class = E_SELECTION_MODEL_GET_CLASS (model);
297 g_return_if_fail (class != NULL);
298 g_return_if_fail (class->clear != NULL);
299
300 class->clear (model);
301 }
302
303 /**
304 * e_selection_model_selected_count
305 * @model: #ESelectionModel to count
306 *
307 * This routine calculates the number of rows selected.
308 *
309 * Returns: The number of rows selected in the given model.
310 */
311 gint
e_selection_model_selected_count(ESelectionModel * model)312 e_selection_model_selected_count (ESelectionModel *model)
313 {
314 ESelectionModelClass *class;
315
316 g_return_val_if_fail (E_IS_SELECTION_MODEL (model), 0);
317
318 class = E_SELECTION_MODEL_GET_CLASS (model);
319 g_return_val_if_fail (class != NULL, 0);
320 g_return_val_if_fail (class->selected_count != NULL, 0);
321
322 return class->selected_count (model);
323 }
324
325 /**
326 * e_selection_model_select_all
327 * @model: #ESelectionModel to select all
328 *
329 * This routine selects all the rows in the given
330 * #ESelectionModel.
331 */
332 void
e_selection_model_select_all(ESelectionModel * model)333 e_selection_model_select_all (ESelectionModel *model)
334 {
335 ESelectionModelClass *class;
336
337 g_return_if_fail (E_IS_SELECTION_MODEL (model));
338
339 class = E_SELECTION_MODEL_GET_CLASS (model);
340 g_return_if_fail (class != NULL);
341 g_return_if_fail (class->select_all != NULL);
342
343 class->select_all (model);
344 }
345
346 gint
e_selection_model_row_count(ESelectionModel * model)347 e_selection_model_row_count (ESelectionModel *model)
348 {
349 ESelectionModelClass *class;
350
351 g_return_val_if_fail (E_IS_SELECTION_MODEL (model), 0);
352
353 class = E_SELECTION_MODEL_GET_CLASS (model);
354 g_return_val_if_fail (class != NULL, 0);
355 g_return_val_if_fail (class->row_count != NULL, 0);
356
357 return class->row_count (model);
358 }
359
360 void
e_selection_model_change_one_row(ESelectionModel * model,gint row,gboolean grow)361 e_selection_model_change_one_row (ESelectionModel *model,
362 gint row,
363 gboolean grow)
364 {
365 ESelectionModelClass *class;
366
367 g_return_if_fail (E_IS_SELECTION_MODEL (model));
368
369 class = E_SELECTION_MODEL_GET_CLASS (model);
370 g_return_if_fail (class != NULL);
371 g_return_if_fail (class->change_one_row != NULL);
372
373 return class->change_one_row (model, row, grow);
374 }
375
376 void
e_selection_model_change_cursor(ESelectionModel * model,gint row,gint col)377 e_selection_model_change_cursor (ESelectionModel *model,
378 gint row,
379 gint col)
380 {
381 ESelectionModelClass *class;
382
383 g_return_if_fail (E_IS_SELECTION_MODEL (model));
384
385 class = E_SELECTION_MODEL_GET_CLASS (model);
386 g_return_if_fail (class != NULL);
387 g_return_if_fail (class->change_cursor != NULL);
388
389 class->change_cursor (model, row, col);
390 }
391
392 gint
e_selection_model_cursor_row(ESelectionModel * model)393 e_selection_model_cursor_row (ESelectionModel *model)
394 {
395 ESelectionModelClass *class;
396
397 g_return_val_if_fail (E_IS_SELECTION_MODEL (model), -1);
398
399 class = E_SELECTION_MODEL_GET_CLASS (model);
400 g_return_val_if_fail (class != NULL, -1);
401 g_return_val_if_fail (class->cursor_row != NULL, -1);
402
403 return class->cursor_row (model);
404 }
405
406 gint
e_selection_model_cursor_col(ESelectionModel * model)407 e_selection_model_cursor_col (ESelectionModel *model)
408 {
409 ESelectionModelClass *class;
410
411 g_return_val_if_fail (E_IS_SELECTION_MODEL (model), -1);
412
413 class = E_SELECTION_MODEL_GET_CLASS (model);
414 g_return_val_if_fail (class != NULL, -1);
415 g_return_val_if_fail (class->cursor_col != NULL, -1);
416
417 return class->cursor_col (model);
418 }
419
420 void
e_selection_model_select_single_row(ESelectionModel * model,gint row)421 e_selection_model_select_single_row (ESelectionModel *model,
422 gint row)
423 {
424 ESelectionModelClass *class;
425
426 g_return_if_fail (E_IS_SELECTION_MODEL (model));
427
428 class = E_SELECTION_MODEL_GET_CLASS (model);
429 g_return_if_fail (class != NULL);
430 g_return_if_fail (class->select_single_row != NULL);
431
432 class->select_single_row (model, row);
433 }
434
435 void
e_selection_model_toggle_single_row(ESelectionModel * model,gint row)436 e_selection_model_toggle_single_row (ESelectionModel *model,
437 gint row)
438 {
439 ESelectionModelClass *class;
440
441 g_return_if_fail (E_IS_SELECTION_MODEL (model));
442
443 class = E_SELECTION_MODEL_GET_CLASS (model);
444 g_return_if_fail (class != NULL);
445 g_return_if_fail (class->toggle_single_row != NULL);
446
447 class->toggle_single_row (model, row);
448 }
449
450 void
e_selection_model_move_selection_end(ESelectionModel * model,gint row)451 e_selection_model_move_selection_end (ESelectionModel *model,
452 gint row)
453 {
454 ESelectionModelClass *class;
455
456 g_return_if_fail (E_IS_SELECTION_MODEL (model));
457
458 class = E_SELECTION_MODEL_GET_CLASS (model);
459 g_return_if_fail (class != NULL);
460 g_return_if_fail (class->move_selection_end != NULL);
461
462 class->move_selection_end (model, row);
463 }
464
465 void
e_selection_model_set_selection_end(ESelectionModel * model,gint row)466 e_selection_model_set_selection_end (ESelectionModel *model,
467 gint row)
468 {
469 ESelectionModelClass *class;
470
471 g_return_if_fail (E_IS_SELECTION_MODEL (model));
472
473 class = E_SELECTION_MODEL_GET_CLASS (model);
474 g_return_if_fail (class != NULL);
475 g_return_if_fail (class->set_selection_end != NULL);
476
477 class->set_selection_end (model, row);
478 }
479
480 /**
481 * e_selection_model_do_something
482 * @model: #ESelectionModel to do something to.
483 * @row: The row to do something in.
484 * @col: The col to do something in.
485 * @state: The state in which to do something.
486 *
487 * This routine does whatever is appropriate as if the user clicked
488 * the mouse in the given row and column.
489 */
490 void
e_selection_model_do_something(ESelectionModel * model,guint row,guint col,GdkModifierType state)491 e_selection_model_do_something (ESelectionModel *model,
492 guint row,
493 guint col,
494 GdkModifierType state)
495 {
496 gint shift_p = state & GDK_SHIFT_MASK;
497 gint ctrl_p = state & GDK_CONTROL_MASK;
498 gint row_count;
499
500 g_return_if_fail (E_IS_SELECTION_MODEL (model));
501
502 model->old_selection = -1;
503
504 if (row == -1 && col != -1)
505 row = 0;
506 if (col == -1 && row != -1)
507 col = 0;
508
509 row_count = e_selection_model_row_count (model);
510 if (row_count >= 0 && row < row_count) {
511 switch (model->mode) {
512 case GTK_SELECTION_SINGLE:
513 e_selection_model_select_single_row (model, row);
514 break;
515 case GTK_SELECTION_BROWSE:
516 case GTK_SELECTION_MULTIPLE:
517 if (shift_p) {
518 e_selection_model_set_selection_end (model, row);
519 } else {
520 if (ctrl_p) {
521 e_selection_model_toggle_single_row (model, row);
522 } else {
523 e_selection_model_select_single_row (model, row);
524 }
525 }
526 break;
527 default:
528 g_return_if_reached ();
529 break;
530 }
531 e_selection_model_change_cursor (model, row, col);
532 g_signal_emit (
533 model,
534 signals[CURSOR_CHANGED], 0,
535 row, col);
536 g_signal_emit (
537 model,
538 signals[CURSOR_ACTIVATED], 0,
539 row, col);
540 }
541 }
542
543 /**
544 * e_selection_model_maybe_do_something
545 * @model: #ESelectionModel to do something to.
546 * @row: The row to do something in.
547 * @col: The col to do something in.
548 * @state: The state in which to do something.
549 *
550 * If this row is selected, this routine just moves the cursor row and
551 * column. Otherwise, it does the same thing as
552 * e_selection_model_do_something(). This is for being used on
553 * right clicks and other events where if the user hit the selection,
554 * they don't want it to change.
555 */
556 gboolean
e_selection_model_maybe_do_something(ESelectionModel * model,guint row,guint col,GdkModifierType state)557 e_selection_model_maybe_do_something (ESelectionModel *model,
558 guint row,
559 guint col,
560 GdkModifierType state)
561 {
562 g_return_val_if_fail (E_IS_SELECTION_MODEL (model), FALSE);
563
564 model->old_selection = -1;
565
566 if (e_selection_model_is_row_selected (model, row)) {
567 e_selection_model_change_cursor (model, row, col);
568 g_signal_emit (
569 model,
570 signals[CURSOR_CHANGED], 0,
571 row, col);
572 return FALSE;
573 } else {
574 e_selection_model_do_something (model, row, col, state);
575 return TRUE;
576 }
577 }
578
579 void
e_selection_model_right_click_down(ESelectionModel * model,guint row,guint col,GdkModifierType state)580 e_selection_model_right_click_down (ESelectionModel *model,
581 guint row,
582 guint col,
583 GdkModifierType state)
584 {
585 g_return_if_fail (E_IS_SELECTION_MODEL (model));
586
587 if (model->mode == GTK_SELECTION_SINGLE) {
588 model->old_selection =
589 e_selection_model_cursor_row (model);
590 e_selection_model_select_single_row (model, row);
591 } else {
592 e_selection_model_maybe_do_something (
593 model, row, col, state);
594 }
595 }
596
597 void
e_selection_model_right_click_up(ESelectionModel * model)598 e_selection_model_right_click_up (ESelectionModel *model)
599 {
600 g_return_if_fail (E_IS_SELECTION_MODEL (model));
601
602 if (model->mode != GTK_SELECTION_SINGLE)
603 return;
604
605 if (model->old_selection == -1)
606 return;
607
608 e_selection_model_select_single_row (
609 model, model->old_selection);
610 }
611
612 void
e_selection_model_select_as_key_press(ESelectionModel * model,guint row,guint col,GdkModifierType state)613 e_selection_model_select_as_key_press (ESelectionModel *model,
614 guint row,
615 guint col,
616 GdkModifierType state)
617 {
618 gint cursor_activated = TRUE;
619
620 gint shift_p = state & GDK_SHIFT_MASK;
621 gint ctrl_p = state & GDK_CONTROL_MASK;
622
623 g_return_if_fail (E_IS_SELECTION_MODEL (model));
624
625 model->old_selection = -1;
626
627 switch (model->mode) {
628 case GTK_SELECTION_BROWSE:
629 case GTK_SELECTION_MULTIPLE:
630 if (shift_p) {
631 e_selection_model_set_selection_end (model, row);
632 } else if (!ctrl_p) {
633 e_selection_model_select_single_row (model, row);
634 } else
635 cursor_activated = FALSE;
636 break;
637 case GTK_SELECTION_SINGLE:
638 e_selection_model_select_single_row (model, row);
639 break;
640 default:
641 g_return_if_reached ();
642 break;
643 }
644 if (row != -1) {
645 e_selection_model_change_cursor (model, row, col);
646 g_signal_emit (
647 model,
648 signals[CURSOR_CHANGED], 0,
649 row, col);
650 if (cursor_activated)
651 g_signal_emit (
652 model,
653 signals[CURSOR_ACTIVATED], 0,
654 row, col);
655 }
656 }
657
658 static gint
move_selection(ESelectionModel * model,gboolean up,GdkModifierType state)659 move_selection (ESelectionModel *model,
660 gboolean up,
661 GdkModifierType state)
662 {
663 gint row = e_selection_model_cursor_row (model);
664 gint col = e_selection_model_cursor_col (model);
665 gint row_count;
666
667 /* there is no selected row when row is -1 */
668 if (row != -1 && model->sorter != NULL)
669 row = e_sorter_model_to_sorted (model->sorter, row);
670
671 if (up)
672 row--;
673 else
674 row++;
675 if (row < 0)
676 row = 0;
677 row_count = e_selection_model_row_count (model);
678 if (row >= row_count)
679 row = row_count - 1;
680 if (model->sorter != NULL)
681 row = e_sorter_sorted_to_model (model->sorter, row);
682
683 e_selection_model_select_as_key_press (model, row, col, state);
684 return TRUE;
685 }
686
687 /**
688 * e_selection_model_key_press
689 * @model: #ESelectionModel to affect.
690 * @key: The event.
691 *
692 * This routine does whatever is appropriate as if the user pressed
693 * the given key.
694 *
695 * Returns: %TRUE if the #ESelectionModel used the key.
696 */
697 gboolean
e_selection_model_key_press(ESelectionModel * model,GdkEventKey * key)698 e_selection_model_key_press (ESelectionModel *model,
699 GdkEventKey *key)
700 {
701 g_return_val_if_fail (E_IS_SELECTION_MODEL (model), FALSE);
702 g_return_val_if_fail (key != NULL, FALSE);
703
704 model->old_selection = -1;
705
706 switch (key->keyval) {
707 case GDK_KEY_Up:
708 case GDK_KEY_KP_Up:
709 return move_selection (model, TRUE, key->state);
710 case GDK_KEY_Down:
711 case GDK_KEY_KP_Down:
712 return move_selection (model, FALSE, key->state);
713 case GDK_KEY_space:
714 case GDK_KEY_KP_Space:
715 if (model->mode != GTK_SELECTION_SINGLE) {
716 gint row = e_selection_model_cursor_row (model);
717 gint col = e_selection_model_cursor_col (model);
718 if (row == -1)
719 break;
720
721 e_selection_model_toggle_single_row (model, row);
722 g_signal_emit (
723 model,
724 signals[CURSOR_ACTIVATED], 0,
725 row, col);
726 return TRUE;
727 }
728 break;
729 case GDK_KEY_Return:
730 case GDK_KEY_KP_Enter:
731 if (model->mode != GTK_SELECTION_SINGLE) {
732 gint row = e_selection_model_cursor_row (model);
733 gint col = e_selection_model_cursor_col (model);
734 e_selection_model_select_single_row (model, row);
735 g_signal_emit (
736 model,
737 signals[CURSOR_ACTIVATED], 0,
738 row, col);
739 return TRUE;
740 }
741 break;
742 case GDK_KEY_Home:
743 case GDK_KEY_KP_Home:
744 if (model->cursor_mode == E_CURSOR_LINE) {
745 gint row = 0;
746 gint cursor_col = e_selection_model_cursor_col (model);
747
748 if (model->sorter != NULL)
749 row = e_sorter_sorted_to_model (
750 model->sorter, row);
751 e_selection_model_select_as_key_press (
752 model, row, cursor_col, key->state);
753 return TRUE;
754 }
755 break;
756 case GDK_KEY_End:
757 case GDK_KEY_KP_End:
758 if (model->cursor_mode == E_CURSOR_LINE) {
759 gint row = e_selection_model_row_count (model) - 1;
760 gint cursor_col = e_selection_model_cursor_col (model);
761
762 if (model->sorter != NULL)
763 row = e_sorter_sorted_to_model (
764 model->sorter, row);
765 e_selection_model_select_as_key_press (
766 model, row, cursor_col, key->state);
767 return TRUE;
768 }
769 break;
770 }
771 return FALSE;
772 }
773
774 void
e_selection_model_cursor_changed(ESelectionModel * model,gint row,gint col)775 e_selection_model_cursor_changed (ESelectionModel *model,
776 gint row,
777 gint col)
778 {
779 g_return_if_fail (E_IS_SELECTION_MODEL (model));
780
781 g_signal_emit (model, signals[CURSOR_CHANGED], 0, row, col);
782 }
783
784 void
e_selection_model_cursor_activated(ESelectionModel * model,gint row,gint col)785 e_selection_model_cursor_activated (ESelectionModel *model,
786 gint row,
787 gint col)
788 {
789 g_return_if_fail (E_IS_SELECTION_MODEL (model));
790
791 g_signal_emit (model, signals[CURSOR_ACTIVATED], 0, row, col);
792 }
793
794 void
e_selection_model_selection_changed(ESelectionModel * model)795 e_selection_model_selection_changed (ESelectionModel *model)
796 {
797 g_return_if_fail (E_IS_SELECTION_MODEL (model));
798
799 g_signal_emit (model, signals[SELECTION_CHANGED], 0);
800 }
801
802 void
e_selection_model_selection_row_changed(ESelectionModel * model,gint row)803 e_selection_model_selection_row_changed (ESelectionModel *model,
804 gint row)
805 {
806 g_return_if_fail (E_IS_SELECTION_MODEL (model));
807
808 g_signal_emit (model, signals[SELECTION_ROW_CHANGED], 0, row);
809 }
810