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; }