Displaying a directory tree with php-gtk is not really simple.
But with a little help, you will be able to create a new Widget
Tree based on GtkTreeView. You can create
new widgets with php-gtk in a few lines of code. This task is
far more involved with pure C/Gtk code.
Introduction
This class is named PhpGtkDirectoryTree.
It is a composite widget inherited from
GtkComposite widget tree. Because it is a
widget, you can add it directly to a
GtkWindow object.
A more complete version is available in Gnope repository ;
this class is named : FileExplorer
Basic class usage
Here is a quick example displaying the directory tree for a
UNIX directory. Windows users, please adapt $dir value.
<?php
# avoid bare errors - reports warning for stupid errors
error_reporting(E_ALL);
# our nice Tree widget class
require_once('PhpGtkDirectoryTree.class.php');
# main part - create a new Tree object and fill it with a directory tree
$tree = new PhpGtkDirectoryTree();
$dir = '/usr/share/doc';
$tree->open_directory($dir);
$tree->set_title($dir);
$window = new GtkWindow();
$window->connect_simple('destroy', array('Gtk','main_quit'));
$window->set_size_request(300, 600 ); # set window size
$window->set_position(Gtk::WIN_POS_CENTER); # place window to screen center
$window->set_title("TreeView directory display example");
$window->add($tree);
# display it
$window->show_all();
Gtk::main();
?>
Todo
- read directory tree as needed, and not all at once
upon creation ; opening a large directory tree when widget is opened (realized)
may block Gtk mainloop and make some troubles in display and other features
managed by mail loop : socket reading, timeout. So we really need to find
a nicer way to open and read directories.
- add event callbacks for selections and folder open-close :
work in progress here and here again :-)
- a complet class framework for directory browsing is available here : http://www.php-gtk.eu/apps/gnope_file_explorer
Class Code
<?php
error_reporting(E_ALL);
# authors :
#
# * class : Marc Quinton - november 2006.
# * main php-gtk2 tricks from kksou : http://www.kksou.com/php-gtk2/
#
# require php-gtk2
#
class PhpGtkDirectoryTree extends GtkVbox {
protected $model;
protected $scrolled_win;
protected $treeview;
protected $column;
protected $icon_folder_open;
protected $icon_folder_closed;
protected $title;
protected $trace;
function __construct() {
parent::__construct();
$this->icon_folder_open = 'folder_open.gif';
$this->icon_folder_closed = 'folder_closed.gif';
$this->trace = false;
$this->build();
}
function build() {
$this->model = new GtkTreeStore(Gtk::TYPE_STRING);
$this->scrolled_win = new GtkScrolledWindow();
$this->scrolled_win->set_policy(
Gtk::POLICY_AUTOMATIC,
Gtk::POLICY_AUTOMATIC);
$this->add($this->scrolled_win);
// set up treeview
$this->treeview = new GtkTreeView($this->model);
$this->scrolled_win->add($this->treeview);
# $this->treeview->set_size_request(400, 320);
//set up treeview columns
$this->column = new GtkTreeViewColumn();
// for image
$cell_renderer = new GtkCellRendererPixbuf();
$this->column->pack_start($cell_renderer, false);
if (file_exists($this->icon_folder_open)
&& file_exists($this->icon_folder_open)) {
$cell_renderer->set_property('pixbuf-expander-open',
GdkPixbuf::new_from_file($this->icon_folder_open));
$cell_renderer->set_property('pixbuf-expander-closed',
GdkPixbuf::new_from_file($this->icon_folder_closed));
} else
trigger_error("PhpGtkDirectoryTree : "
. "icon file for folder not found",
E_USER_WARNING);
// for filename
$cell_renderer = new GtkCellRendererText();
$this->column->pack_start($cell_renderer, true);
$this->column->set_attributes($cell_renderer, 'text', 0);
$this->treeview->append_column($this->column);
}
function open_directory($folder) {
if (!is_dir($folder)) {
trigger_error("PhpGtkDirectoryTree : "
. "directory not found",
E_USER_WARNING);
return false;
}
$this->model->clear();
$root = $folder;
$dir_list = array($root);
$nodes = array();
$nodes[$root] = null;
while (count($dir_list)>0) {
$dir = array_shift($dir_list);
$this->trace("folder = $dir\n");
// add the directories first
if ($handle = opendir($dir)) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
$fullpath = $dir.'/'.$file;
if (is_dir($fullpath)) {
$nodes[$fullpath] = $this->model->append(
$nodes[$dir], array($file));
array_push($dir_list, $fullpath);
}
}
}
closedir($handle);
}
$num_files = 0;
// then add the files
if ($handle = opendir($dir)) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
$fullpath = $dir.'/'.$file;
if (!is_dir($fullpath)) {
$nodes[$fullpath] = $this->model->append(
$nodes[$dir], array($file));
++$num_files;
}
}
}
closedir($handle);
}
# FIXME : bug here when directory is empty (no files or only sub-directories)
if ($num_files==0)
$nodes[$fullpath] = $this->model->append(
$nodes[$dir], array(''));
}
}
function set_title($title) {
$this->title = $title;
$this->column->set_title($title);
}
function trace($txt) {
if ($this->trace)
echo "$txt";
}
}
?>
Class Internals
Bugs
- when reading a directory with only subdirectories (no files) or empty,
there is a problem with modele tree ; tree is displayed with a blank entry.
Hints
- you could get feedback for directory tree reading with
trace() method. Just subclass PhpGtkDirectoryTree widget and display a feedback in a label widget, or perhaps in
title part of PhpGtkDirectoryTree.
Copyright
Main of this class comes from great site from kksou. Please refer to his site for usage.
links
Recent comments
6 weeks 1 day ago
12 weeks 13 hours ago
13 weeks 5 days ago
20 weeks 1 day ago
21 weeks 3 days ago
21 weeks 4 days ago
22 weeks 5 days ago
23 weeks 4 days ago
34 weeks 2 days ago
34 weeks 3 days ago