static void
restore_cursor (ETreeSelectionModel *etsm,
                ETreeModel *etm)
{
	clear_selection (etsm);
	etsm->priv->cursor_path = NULL;

	if (etsm->priv->cursor_save_id) {
		etsm->priv->cursor_path = e_tree_model_get_node_by_id (
			etm, etsm->priv->cursor_save_id);
		if (etsm->priv->cursor_path != NULL && etsm->priv->cursor_col == -1)
			etsm->priv->cursor_col = 0;

		select_single_path (etsm, etsm->priv->cursor_path);
	}

	e_selection_model_selection_changed (E_SELECTION_MODEL (etsm));

	if (etsm->priv->cursor_path) {
		gint cursor_row = get_cursor_row (etsm);
		e_selection_model_cursor_changed (
			E_SELECTION_MODEL (etsm),
			cursor_row, etsm->priv->cursor_col);
	} else {
		e_selection_model_cursor_changed (
			E_SELECTION_MODEL (etsm), -1, -1);
		e_selection_model_cursor_activated (
			E_SELECTION_MODEL (etsm), -1, -1);

	}

	free_id (etsm);
}
static void
tree_selection_model_select_all (ESelectionModel *selection)
{
	ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL (selection);
	ETreePath root;

	root = e_tree_model_get_root (etsm->priv->model);
	if (root == NULL)
		return;

	clear_selection (etsm);

	/* We want to select ALL rows regardless of expanded state.
	 * ETreeTableAdapter pretends that collapsed rows don't exist,
	 * so instead we need to iterate over the ETreeModel directly. */

	e_tree_model_node_traverse (
		etsm->priv->model, root,
		tree_selection_model_traverse_cb,
		selection);

	if (etsm->priv->cursor_path == NULL)
		etsm->priv->cursor_path = e_tree_table_adapter_node_at_row (
			etsm->priv->etta, 0);

	e_selection_model_selection_changed (E_SELECTION_MODEL (etsm));

	e_selection_model_cursor_changed (
		E_SELECTION_MODEL (etsm),
		get_cursor_row (etsm), etsm->priv->cursor_col);
}
static void
tree_selection_model_clear (ESelectionModel *selection)
{
	ETreeSelectionModel *etsm = E_TREE_SELECTION_MODEL (selection);

	clear_selection (etsm);

	etsm->priv->cursor_path = NULL;
	e_selection_model_selection_changed (E_SELECTION_MODEL (etsm));
	e_selection_model_cursor_changed (E_SELECTION_MODEL (etsm), -1, -1);
}
static gint
model_changed_idle (ETableSelectionModel *etsm)
{
	ETableModel *etm = etsm->model;

	e_selection_model_clear (E_SELECTION_MODEL (etsm));

	if (etsm->cursor_id && etm && e_table_model_has_save_id (etm)) {
		gint row_count = e_table_model_row_count (etm);
		gint cursor_row = -1;
		gint cursor_col = -1;
		gint i;
		e_selection_model_array_confirm_row_count (E_SELECTION_MODEL_ARRAY (etsm));
		for (i = 0; i < row_count; i++) {
			gchar *save_id = e_table_model_get_save_id (etm, i);
			if (g_hash_table_lookup (etsm->hash, save_id))
				e_selection_model_change_one_row (E_SELECTION_MODEL (etsm), i, TRUE);

			if (etsm->cursor_id && !strcmp (etsm->cursor_id, save_id)) {
				cursor_row = i;
				cursor_col = e_selection_model_cursor_col (E_SELECTION_MODEL (etsm));
				if (cursor_col == -1) {
					if (etsm->eth) {
						cursor_col = e_table_header_prioritized_column (etsm->eth);
					} else
						cursor_col = 0;
				}
				e_selection_model_change_cursor (E_SELECTION_MODEL (etsm), cursor_row, cursor_col);
				g_free (etsm->cursor_id);
				etsm->cursor_id = NULL;
			}
			g_free (save_id);
		}
		free_hash (etsm);
		e_selection_model_cursor_changed (E_SELECTION_MODEL (etsm), cursor_row, cursor_col);
		e_selection_model_selection_changed (E_SELECTION_MODEL (etsm));
	}
	etsm->model_changed_idle_id = 0;
	return FALSE;
}