Creating a File Tree with Gtk+
I thought that today, rather than going for an in-depth tutorial, I would post a useful snippet of code for anyone out there doing GUI development with GTK+. Although Gtk+ is a nice toolkit, one thing that I found that it was lacking was a nice widget to automatically display directories. I had hoped that since it had such a nice file open dialog, there might be something out there, but alas I was unable to find anything. So, I present here a useful function to automatically populate a GtkTreeView with a directory structure.
void fill_tree(char* dirname, char* shortname, GtkTreeStore* store, GtkTreeIter* parent_iter, int level)
{
DIR* dir = NULL;
//defined in dirent.h
struct dirent* entry;
//allocate a string with 255 characters per directory name, plus 1 character for the / between directories.
char* path = (char*)malloc( ((255*(level+1))+level+1) * sizeof(char) );
//this will become the parent node for subsequent calls
//and gets placed under the parent node that was sent to us
GtkTreeIter my_iter;
strcpy(path,dirname);
strcat(path,"/");
if(NULL != (dir = opendir(dirname)))//make sure we can open the directory
{
//create a node on the tree for the directory
gtk_tree_store_append(store,&my_iter,parent_iter);
//add the current directory to the list
gtk_tree_store_set(store,&my_iter,COL_NAME,shortname,-1);
//start to read the subdirectories
while( (entry = readdir(dir)) != NULL)
{
//skip hidden files, . and ..
if( (entry->d_name)[0]==‘.’)
{
continue;
}
//create the full path to the subdirecotry
strcat(path,entry->d_name);
//recursively call fill with this subdirectory
fill_tree(path,entry->d_name,store,&my_iter,level+1);
//reset the path to the path of this directory
strcpy(path,dirname);
strcat(path,"/");
}
}
//close the file handle and free memory
closedir(dir);
free(path);
path=NULL;
}
Using the function is pretty simple. Just copy and paste into your application, with the path for the top of the directory structure you want to display, and a name for it. Pass in a pointer to a GtkTreeStore you’ve allocated, and NULL and 0 for the parent_iter and level (unless you want to display the tree under some heading). Here is an example:
fill_tree("/home/tuxtips","Home Directory",my_tree_store,NULL,0);
If you are loading a large directory structure (for example, /) you might consider spawning this off into it’s own thread, as it can take a bit of time. For something a bit more dynamic, consider removing the recursive functionality, and calling the function in response to a user clicking on an entry. Also note that, for simplicity, I’ve used 255 as the maximum directory entry size, but this is a variable set in dirent.h and varies from system to system, so be sure to look that up!
Until Next Time, Happy Hacking.