如何更改 GtkTreeModel 的数据(在 "edited" 回调中)

How to change data of a GtkTreeModel (within "edited" callback)

我正在捕获我的 GtkCellRenderer 的 "edited" 信号:

GtkTreeModel * sortmodel; // contains a sorted model of GtkListStore

// ...

GtkCellRenderer * renderer;

// ...

g_object_set(renderer, "editable", TRUE, NULL);    
g_signal_connect(renderer, "edited",
                G_CALLBACK(onEdited_name), sortmodel);

我现在想相应地更改单元格的内容,但我没有找到任何可以更改 GtkTreeModel 单元格内容的函数。

void onEdited_name(GtkCellRendererText *cell,
                        gchar * path_string,
                        gchar * new_text,
                        gpointer treemodel)
{
  GtkTreeModel * model = GTK_TREE_MODEL(treemodel);

  GtkTreeIter iter;
  gtk_tree_model_get_iter_from_string(model, &iter, path_string);  

  // TODO: set the value according to iter.
  // gtk_list_store_set will not work of course, because
  //  we're operating on a GtkTreeModel   
}  

这个问题是关于:Changing the content of a GTK Tree View

您的第一个代码片段是正确的。

  1. 不能更改 GtkTreeModel 的值。
  2. 您只能更改 "raw" 模型(基本模型,如 GtkListStore 或 GtkTreeStore)的值。

理论 - 很高兴知道

Gtk 层次结构

下图显示了GtkTreeModel层次结构以及它们提供的(重要)功能

如您所见,如果要更改单元格的值,则需要区分您实际处理的模型类型。

GtkCellRenderer 和 "edited" 信号/回调

一个渲染器应该只"assigned"到一列。否则你不知道用户试图更改哪一列。

更改 GtkTreeStore

的 GtkTreeModelSort 的值

参见下面的 GtkListStore 示例,并将 GtkListStore 替换为 GtkTreeStore。这应该可以解决问题。

更改 GtkListStore

的 GtkTreeModelSort 的值
void 
onEdited_name (GtkCellRendererText * cell,
               gchar               * path_string,
               gchar               * new_text,
               gpointer              p_model_sorted)
{       
    // we need to convert to GtkListStore, because GtkTreeModel does not
    //  provide an interface for cell content changing.


    // convert raw data to the actual type
    GtkTreeModelSort * model_sorted = GTK_TREE_MODEL_SORT(p_model_sorted);

    // get the iterator within the sorted model
    GtkTreeIter iter_sortedModel;
    gtk_tree_model_get_iter_from_string((GtkTreeModel*)model_sorted,
                  &iter_sortedModel, path_string);          

    // convert sorted model to raw model
    GtkListStore * model_raw;       
    model_raw = GTK_LIST_STORE(gtk_tree_model_sort_get_model(model_sorted));

    // convert the iterator to one of the raw model.
    // (Otherwise the wrong cell will change)
    GtkTreeIter iter_rawModel;
    gtk_tree_model_sort_convert_iter_to_child_iter(model_sorted, &iter_rawModel, &iter_sortedModel);


    gtk_list_store_set(model_raw, &iter_rawModel,
                                LIST_COL_NAME, new_text, -1);
} 

更改 GtkListStore

的 GtkListStore 或 GtkTreeModelSort 的值

假设您有两个基于同一模型的 GtkTreeView。一个已排序,另一个未排序。此功能将向您展示如何管理这些。

请注意,我们现在传递 GtkTreeView 作为 gpointer,而不是 GtkTreeModel。

void onEdited_name(GtkCellRendererText *cell,
                        gchar * path_string,
                        gchar * new_text,
                        gpointer _treeview) // <--- GtkTreeView now!!!!
{
    // we HAVE TO use GtkTreeView within gpointer!
    //  otherwise we could not differntiate the model type!
    GtkTreeView * treeview = GTK_TREE_VIEW(_treeview);
    GtkTreeModel * treeModel = gtk_tree_view_get_model(treeview);

    // we need to use GtkListStore, because GtkTreeModel does not
    //  provide an interface for cell changing.
    GtkListStore * model;   
    GtkTreeIter iter_rawModel;

    // check if we're working on the raw model or on a sorted version
    //  of it
    if(GTK_IS_LIST_STORE(treeModel)){
        // just use the model as is    
        model = GTK_LIST_STORE(treeModel);

        // retrieve the iterator for the cell, that should be changed
        gtk_tree_model_get_iter_from_string((GtkTreeModel*)model,
                                            &iter_rawModel, path_string);

    } else { // we're working on a sorted model   
        // We need to change to a usual model.
        GtkTreeModelSort * sortedModel = GTK_TREE_MODEL_SORT(treeModel);
        model = GTK_LIST_STORE(gtk_tree_model_sort_get_model(sortedModel));

        // get the iterator within the sorted model
        GtkTreeIter iter_sortedModel;
        gtk_tree_model_get_iter_from_string((GtkTreeModel*)sortedModel,
                              &iter_sortedModel, path_string);  

        // convert the iterator to one of the raw model.
        // (Otherwise the wrong cell will change)
        gtk_tree_model_sort_convert_iter_to_child_iter(sortedModel, &iter_rawModel, &iter_sortedModel);
    }


    gtk_list_store_set(GTK_LIST_STORE(model), &iter_rawModel,
                LIST_COL_NAME, new_text, -1);

}   

This is a fully functional example code for a sorted model