Я решил эту проблему, сохранив развернутые строки в структуре данных перед очисткой TreeView.Я использовал список данных с ключами, чтобы связать имя расширенной строки и соответствующую ей глубину (имя строки - это ключ, а глубина - это значение).Затем я очищаю TreeView и снова заполняю его как обычно.После этого я пересекаю TreeModel строка за строкой.Если имя строки является ключом в списке данных с ключами, а глубина строки равна значению глубины списка данных с ключами, я расширяю эту строку.Вот код:
num
{
COL_NAME = 0,
NUM_COLS
};
void populate_directory_tree_store(GtkTreeStore *treestore, const char *directory, GtkTreeIter *toplevel) {
DIR *dir;
struct dirent *entry;
GtkTreeIter child;
if (!(dir = opendir(directory)))
return;
while ((entry = readdir(dir)) != NULL) {
if (entry->d_type == DT_DIR) {
char path[1024];
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
snprintf(path, sizeof(path), "%s/%s", directory, entry->d_name);
gtk_tree_store_append(treestore, &child, toplevel);
gtk_tree_store_set(treestore, &child,
0, entry->d_name,
-1);
populate_directory_tree_store(treestore, path, &child);
}
else {
gtk_tree_store_append(treestore, &child, toplevel);
gtk_tree_store_set(treestore, &child,
0, entry->d_name,
-1);
}
}
closedir(dir);
}
void foreach_expanded_row(GtkTreeView *tree_view, GtkTreePath *path, gpointer user_data) {
GData **datalist = user_data;
GtkTreeStore *treestore = GTK_TREE_STORE(gtk_tree_view_get_model(tree_view));
GValue key = G_VALUE_INIT;
char *treePathString = gtk_tree_path_to_string(path);
GtkTreeIter treeIter;
gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(treestore), &treeIter, treePathString);
gtk_tree_model_get_value(GTK_TREE_MODEL(treestore), &treeIter, COL_NAME, &key);
g_datalist_id_set_data(datalist, g_quark_from_string(g_value_get_string(&key)), GINT_TO_POINTER(gtk_tree_path_get_depth(path)));
}
gboolean foreach_tree_model_row(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) {
struct combined_data {
GData **datalist;
GtkTreeView *treeview;
};
struct combined_data *cd = data;
GData **datalist = cd->datalist;
GtkTreeView *treeview = cd->treeview;
GValue key = G_VALUE_INIT;
char *treePathString = gtk_tree_path_to_string(path);
GtkTreeIter treeIter;
gtk_tree_model_get_iter_from_string(model, &treeIter, treePathString);
gtk_tree_model_get_value(model, &treeIter, COL_NAME, &key);
int depth = g_datalist_get_data(datalist, g_value_get_string(&key));
if (depth && gtk_tree_path_get_depth(path) == depth) {
gtk_tree_view_expand_row(treeview, path, FALSE);
}
return FALSE;
}
void refresh_tree_view(GtkTreeView *treeview, GtkTreeStore *treestore) {
GData *datalist;
g_datalist_init(&datalist);
gtk_tree_view_map_expanded_rows(treeview, foreach_expanded_row, &datalist);
GtkTreeIter toplevel;
gtk_tree_store_clear(treestore);
gtk_tree_store_append(treestore, &toplevel, NULL);
gtk_tree_store_set(treestore, &toplevel, 0, "MainProject", -1);
populate_directory_tree_store(treestore, "C:\\Projects, &toplevel);
struct combined_data {
GData **datalist;
GtkTreeView *treeview;
};
struct combined_data *cd = malloc(sizeof(struct combined_data));
cd->datalist = &datalist;
cd->treeview = treeview;
gtk_tree_model_foreach(GTK_TREE_MODEL(treestore), foreach_tree_model_row, cd);
free(cd);
}
Каждый раз, когда мне нужно обновить представление проекта с текущими каталогами, я просто звоню
refresh_tree_view(treeview, treestore);
Надеюсь, это поможет любому с той же проблемой.