我最近一直在尝试在GTK中创建项目视图时遇到问题。问题是我的程序不断删除文件并将文件添加到项目目录,但是要考虑到这些更改,需要清除并重新填充项目树视图的TreeStore。清除并重新填充TreeStore后,项目TreeView将折叠其所有标头。请看以下示例:
这是项目视图,程序将在MainProject下添加另一个名为“ SubProject2”的文件夹,清除TreeModel,然后使用相同目录重新填充它。
请注意,文件夹“ SubProject2”已正确添加到“ MainProject”下,但是TreeView折叠了“ MainProject”。
我当前用于重新填充TreeView的代码如下:
String input = io.readInput();
int[] arr = new int[5];
if(input.length() >= 5){
String[] c = input.split(" ");
for(int i = 0; i < c.length(); i++){
arr[i] = Integer.parseInt(c[i]);
}
}
每次更改项目目录时,我都会这样调用该函数:
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);
}
我曾考虑过使用libfswatch(located here)之类的库来实时检测目录更改,并在每次更改时更改项目TreeView,但是它需要多线程。我不知道我是否可以忽略GtkTreeView中的某些内容,但是这种琐碎的内容应该不会那么困难。如果您有任何问题或反馈,请发布。
谢谢你, 维卡斯
答案 0 :(得分:1)
我解决此问题的方法是在清除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);
希望这可以帮助遇到相同问题的任何人。