簡體   English   中英

如何在GTK中創建項目目錄樹視圖和樹存儲?

[英]How do you create a project directory tree view and tree store in GTK?

我最近一直在嘗試在GTK中創建項目視圖時遇到問題。 問題是我的程序不斷刪除文件並將文件添加到項目目錄,但是要考慮到這些更改,需要清除並重新填充項目樹視圖的TreeStore。 清除並重新填充TreeStore后,項目TreeView將折疊其所有標頭。 請看以下示例:

在此處輸入圖片說明

在程序在MainProject下添加另一個名為“ SubProject2”的文件夾,清除TreeModel並用相同目錄重新填充之前,這是項目視圖。

這是以下項目視圖: 在此處輸入圖片說明

請注意,文件夾“ SubProject2”已正確添加到“ MainProject”下,但是TreeView折疊了“ MainProject”。

我當前用於重新填充TreeView的代碼如下:

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

每次更改項目目錄時,我都會這樣調用該函數:

gtk_tree_store_clear(treestore);
populate_directory_tree_store(treestore, "C:\\Projects", &topIterator);

我曾考慮過使用libfswatch之類的庫( 位於此處 )來實時檢測目錄更改,並在每次更改時更改項目TreeView,但是它需要多線程。 我不知道我是否可以忽略GtkTreeView中的某些內容,但是這種瑣碎的內容應該不會那么困難。 如果您有任何疑問或反饋,請發布。

謝謝Vikas

我解決此問題的方法是在清除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);

希望這對遇到同樣問題的人有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM