evolution-3.6.4/widgets/misc/e-selection-model.c

No issues found

Incomplete coverage

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