Example #1
0
static void
scroll_new_row (ScrollFixture *fixture,
		gconstpointer  test_data)
{
	GtkTreeIter scroll_iter;
	GtkTreePath *scroll_path;
	GtkTreeModel *model;
	GList *renderers;
	GtkTreeViewColumn *column;
	GtkWidget *editable;

	/* The aim of this test is creating a new row at several places,
	 * and immediately put the cursor on it.  TreeView should correctly
	 * scroll to the row and show the editable widget.
	 *
	 * See #81627.
	 */

	g_test_bug ("81627");

	gtk_widget_show_all (fixture->window);

	while (gtk_events_pending ())
		gtk_main_iteration ();

	/* Create the new row and scroll to it */
	model = gtk_tree_view_get_model (GTK_TREE_VIEW (fixture->tree_view));
	create_new_row (GTK_LIST_STORE (model), GPOINTER_TO_INT (test_data),
			&scroll_iter);

	/* Set up a signal handler to acquire the editable widget */
	column = gtk_tree_view_get_column (GTK_TREE_VIEW (fixture->tree_view), 0);
	renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));

	g_signal_connect (G_OBJECT (renderers->data), "editing-started",
			  G_CALLBACK (scroll_new_row_editing_started),
			  &editable);

	/* Now set the cursor on the path and start editing */
	scroll_path = gtk_tree_model_get_path (model, &scroll_iter);
	gtk_tree_view_set_cursor (GTK_TREE_VIEW (fixture->tree_view),
				  scroll_path,
				  column,
				  TRUE);

	while (gtk_events_pending ())
		gtk_main_iteration ();

	/* Test position */
	test_position (GTK_TREE_VIEW (fixture->tree_view), scroll_path,
		       FALSE, 0.0);
	test_editable_position (fixture->tree_view, editable, scroll_path);

	gtk_tree_path_free (scroll_path);
}
static void
iter_row_changed_cb (GdaDataModelIter *iter, gint row, GdaDataAccessWrapper *model)
{
	g_assert (model->priv->rows);

	/*g_print ("%s(%d)\n", __FUNCTION__, row);*/
	if (gda_data_model_iter_is_valid (iter)) {
		model->priv->iter_row = row;
		if (model->priv->last_row < row)
			model->priv->last_row = row;

		if (! (model->priv->model_access_flags & GDA_DATA_MODEL_ACCESS_CURSOR_BACKWARD) ||
		    ! (model->priv->model_access_flags & GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD)) {
			/* keep the changes in rows */
			GdaRow *gda_row;
			gint tmp;
			tmp = row;
			gda_row = g_hash_table_lookup (model->priv->rows, &tmp);
			if (!gda_row)
				create_new_row (model);
		}
	}
}
static const GValue *
gda_data_access_wrapper_get_value_at (GdaDataModel *model, gint col, gint row, GError **error)
{
	GdaDataAccessWrapper *imodel;

	g_return_val_if_fail (GDA_IS_DATA_ACCESS_WRAPPER (model), NULL);
	imodel = (GdaDataAccessWrapper*) model;
	g_return_val_if_fail (imodel->priv, NULL);
	g_return_val_if_fail (imodel->priv->model, NULL);
	g_return_val_if_fail (row >= 0, NULL);

	if (col >= imodel->priv->nb_cols) {
		g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_COLUMN_OUT_OF_RANGE_ERROR,
			     _("Column %d out of range (0-%d)"), col, imodel->priv->nb_cols - 1);
		return NULL;
	}

	if (!imodel->priv->rows) {
		/* imodel->priv->model is a random access model, use it */
		if (imodel->priv->rows_mapping)
			return gda_data_model_get_value_at (imodel->priv->model, imodel->priv->rows_mapping [col],
							    row, error);
		else
			return gda_data_model_get_value_at (imodel->priv->model, col, row, error);
	}
	else {
		GdaRow *gda_row;
		gint tmp;
		tmp = row;
		gda_row = g_hash_table_lookup (imodel->priv->rows, &tmp);
		if (gda_row) {
			GValue *val = gda_row_get_value (gda_row, col);
			if (gda_row_value_is_valid (gda_row, val))
				return val;
			else
				return NULL;
		}
		else {
			g_assert (imodel->priv->iter);
			if (imodel->priv->iter_row < 0) {
				if (gda_data_model_iter_move_next (imodel->priv->iter)) {
					tmp = row;
					gda_row = g_hash_table_lookup (imodel->priv->rows, &tmp);
					if (row == imodel->priv->iter_row) {
						GValue *val = gda_row_get_value (gda_row, col);
						if (gda_row_value_is_valid (gda_row, val))
							return val;
						else
							return NULL;
					}
				}
				else {
					g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR,
						      "%s", _("Can't set iterator's position"));
					return NULL;
				}
			}
				
			gda_row = NULL;
			if (row != imodel->priv->iter_row) {
				if (row > imodel->priv->iter_row) {
					/* need to move forward */
					while ((imodel->priv->iter_row < row) && 
					       gda_data_model_iter_move_next (imodel->priv->iter));
				}
				else {
					/* need to move backwards */
					g_assert (imodel->priv->model_access_flags & GDA_DATA_MODEL_ACCESS_CURSOR_BACKWARD);
					while ((imodel->priv->iter_row > row) && 
					       gda_data_model_iter_move_prev (imodel->priv->iter)) ;
				}
			}

			if (! (imodel->priv->model_access_flags & GDA_DATA_MODEL_ACCESS_CURSOR_BACKWARD) ||
			    ! (imodel->priv->model_access_flags & GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD)) {
				tmp = row;
				gda_row = g_hash_table_lookup (imodel->priv->rows, &tmp);

				if (gda_row) {
					GValue *val = gda_row_get_value (gda_row, col);
					if (gda_row_value_is_valid (gda_row, val))
						return val;
					else
						return NULL;
				}
			}
			else {
				/* in this case iter can be moved forward and backward at will => we only
				 * need to keep a pool of GdaRow for performances reasons */
				tmp = row;
				gda_row = g_hash_table_lookup (imodel->priv->rows, &tmp);

				if (!gda_row) {
					if (! imodel->priv->rows_buffer_array) {
						imodel->priv->rows_buffer_array = g_array_sized_new (FALSE, FALSE, 
												     sizeof (GdaRow*),
												     ROWS_POOL_SIZE);
						imodel->priv->rows_buffer_index = g_array_sized_new (FALSE, FALSE, 
												     sizeof (gint), 
												     ROWS_POOL_SIZE);
					}
					else if (imodel->priv->rows_buffer_array->len == ROWS_POOL_SIZE) {
						/* get rid of the oldest row (was model's index_row row)*/
						gint index_row;

						index_row = g_array_index (imodel->priv->rows_buffer_index, gint,
									   ROWS_POOL_SIZE - 1);
						g_array_remove_index (imodel->priv->rows_buffer_array,
								      ROWS_POOL_SIZE - 1);
						g_array_remove_index (imodel->priv->rows_buffer_index,
								      ROWS_POOL_SIZE - 1);
						g_hash_table_remove (imodel->priv->rows, &index_row);
					}
					if (gda_data_model_iter_move_to_row (imodel->priv->iter, row)) {
						gda_row = create_new_row (imodel);
						g_array_prepend_val (imodel->priv->rows_buffer_array, gda_row);
						g_array_prepend_val (imodel->priv->rows_buffer_index, imodel->priv->iter_row);
					}
				}

				GValue *val;
				val = gda_row ? gda_row_get_value (gda_row, col) : NULL;
				if (gda_row && gda_row_value_is_valid (gda_row, val))
					return val;
				else
					return NULL;
			}
		}
	}

	g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR,
		      "%s", _("Can't access data"));
	return NULL;
}