diff --git a/gnome/gnome.TODO b/gnome/gnome.TODO index e0e725a52..796422bbc 100644 --- a/gnome/gnome.TODO +++ b/gnome/gnome.TODO @@ -5,8 +5,6 @@ Other features requested: - Remove extra space on the panels (the in-between icons) - - Default font for the icon list - - Remove the bottom scrollabar on the views. - Status line uses too much space, it might be fixed @@ -51,15 +49,8 @@ Other features requested: IMPORTANTE: ->>>>> When something is dragged, the panel is not being refreshed <<<< - file actions dont cause panels to be refreshed automatically -All: - -- Session management - - EXTENSIONS: - Add special destkop entries ("Network neighborhood") diff --git a/gnome/gtree.c b/gnome/gtree.c new file mode 100644 index 000000000..7aa6b6c15 --- /dev/null +++ b/gnome/gtree.c @@ -0,0 +1,335 @@ +/* + * GtkDTree: A directory tree view + * + * Original version by Daniel Lacroix (LACROIX@wanadoo.fr) + * + * Adapted to the Midnight Commander by Miguel. + * + */ +#include +#include +#include "gtree.h" + +#include +#include +#include +#include + +#include "dir-open.xpm" +#include "dir-close.xpm" + +#define TREE_SPACING 5 + +static GtkCTreeClass *parent_class = NULL; + +enum { + DIRECTORY_CHANGED, + LAST_SIGNAL +}; + +static guint gtk_dtree_signals [LAST_SIGNAL] = { 0 }; + +static char * +gtk_dtree_get_row_path (GtkCTree *ctree, GtkCTreeNode *row, gint column) +{ + char *node_text, *path; + + path = g_strdup (""); + do { + char *new_path; + + gtk_ctree_node_get_pixtext ( + ctree, row, column, + &node_text, NULL, NULL, NULL); + + new_path = g_concat_dir_and_file (node_text, path); + g_free (path); + path = new_path; + + row = GTK_CTREE_ROW (row)->parent; + } while (row); + + return path; +} + +static gboolean +gtk_dtree_load_path (GtkDTree *dtree, char *path, GtkCTreeNode *parent, int level) +{ + DIR *dir; + struct dirent *dirent; + char *full_name; + + g_assert (path); + g_assert (parent); + g_assert (dtree); + + dir = opendir (path); + if (!dir) + return FALSE; + + for (; (dirent = readdir (dir)) != NULL; ){ + GtkCTreeNode *sibling; + struct stat s; + char *full_name; + char *text [1]; + int res; + + if (dirent->d_name [0] == '.'){ + if (dirent->d_name [1] == '.'){ + if (dirent->d_name [2] == 0) + continue; + } else if (dirent->d_name [1] == 0) + continue; + } + + full_name = g_concat_dir_and_file (path, dirent->d_name); + res = stat (full_name, &s); + printf ("Statting %s\n", full_name); + + if (res == -1){ + g_free (full_name); + continue; + } + + if (!S_ISDIR (s.st_mode)){ + g_free (full_name); + continue; + } + + text [0] = dirent->d_name; + + sibling = gtk_ctree_insert_node ( + GTK_CTREE (dtree), parent, NULL, + text, TREE_SPACING, + dtree->pixmap_close, + dtree->bitmap_close, + dtree->pixmap_open, + dtree->bitmap_open, + FALSE, FALSE); + if (level) + gtk_dtree_load_path (dtree, full_name, sibling, level-1); + + g_free (full_name); + } + + closedir (dir); +} + +static void +gtk_dtree_select_row (GtkCTree *ctree, GtkCTreeNode *row, gint column) +{ + GtkDTree *dtree = GTK_DTREE (ctree); + GtkCTreeNode *last_node; + char *path; + + parent_class->tree_select_row (ctree, row, column); + + gtk_clist_freeze (GTK_CLIST (ctree)); + while (row == dtree->root_node) + return; + + if (row == dtree->last_node) + return; + + dtree->last_node = row; + + path = gtk_dtree_get_row_path (ctree, row, column); + if (dtree->current_path) + g_free (dtree->current_path); + + dtree->current_path = path; + + gtk_signal_emit (GTK_OBJECT (ctree), gtk_dtree_signals [DIRECTORY_CHANGED], path); + + last_node = GTK_CTREE_ROW (row)->children; + while (last_node){ + char *np, *text; + + gtk_ctree_node_get_pixtext ( + ctree, last_node, column, &text, + NULL, NULL, NULL); + + np = g_concat_dir_and_file (path, text); + gtk_dtree_load_path (dtree, np, last_node, 0); + g_free (np); + + last_node = GTK_CTREE_NODE_NEXT (last_node); + } + + gtk_clist_thaw (GTK_CLIST (ctree)); +} + +static void +gtk_dtree_expand (GtkCTree *ctree, GtkCTreeNode *node) +{ + parent_class->tree_expand (ctree, node); + gtk_dtree_select_row (ctree, node, 0); +} + +static void +gtk_dtree_destroy (GtkObject *object) +{ + GtkDTree *dtree = GTK_DTREE (object); + + gdk_pixmap_unref (dtree->pixmap_open); + gdk_pixmap_unref (dtree->pixmap_close); + gdk_bitmap_unref (dtree->bitmap_open); + gdk_bitmap_unref (dtree->bitmap_close); + + (GTK_OBJECT_CLASS (parent_class))->destroy (object); +} + +static void +gtk_dtree_class_init (GtkDTreeClass *klass) +{ + GtkObjectClass *object_class = (GtkObjectClass *) klass; + GtkCTreeClass *ctree_class = (GtkCTreeClass *) klass; + + parent_class = gtk_type_class (GTK_TYPE_CTREE); + + gtk_dtree_signals [DIRECTORY_CHANGED] = + gtk_signal_new ( + "directory_changed", + GTK_RUN_FIRST, object_class->type, + GTK_SIGNAL_OFFSET (GtkDTreeClass, directory_changed), + gtk_marshal_NONE__POINTER, + GTK_TYPE_NONE, + 1, + GTK_TYPE_POINTER); + + gtk_object_class_add_signals (object_class, gtk_dtree_signals, LAST_SIGNAL); + + object_class->destroy = gtk_dtree_destroy; + + ctree_class->tree_select_row = gtk_dtree_select_row; + ctree_class->tree_expand = gtk_dtree_expand; +} + +static void +gtk_dtree_load_root_tree (GtkDTree *dtree) +{ + char *root_dir [1] = { "/" }; + + g_assert (dtree); + + gtk_clist_freeze (GTK_CLIST (dtree)); + gtk_clist_clear (GTK_CLIST (dtree)); + + dtree->root_node = gtk_ctree_insert_node ( + GTK_CTREE (dtree), NULL, NULL, + root_dir, TREE_SPACING, + dtree->pixmap_close, + dtree->bitmap_close, + dtree->pixmap_open, + dtree->bitmap_open, + FALSE, TRUE); + + gtk_dtree_load_path (dtree, "/", dtree->root_node, 1); + + dtree->last_node = dtree->root_node; + + if (dtree->current_path != NULL) + g_free (dtree->current_path); + + /* Set current_path to "/" */ + dtree->current_path = g_malloc (2); + dtree->current_path [0] = '/'; + dtree->current_path [1] = 0; + + /* Select root node */ + gtk_ctree_select (GTK_CTREE (dtree), dtree->root_node); + + gtk_clist_thaw (GTK_CLIST (dtree)); +} + +static void +gtk_dtree_load_pixmap (char *pix [], GdkPixmap **pixmap, GdkBitmap **bitmap) +{ + g_assert (pix); + g_assert (pixmap); + g_assert (bitmap); + + *pixmap = gdk_pixmap_colormap_create_from_xpm_d ( + NULL, /* NULL window */ + gtk_widget_get_default_colormap (), + bitmap, + NULL, + pix); +} + +/* + * FIXME: This uses the current colormap and pixmap. + * This means that at widget *creation* time the proper + * colormap and visual should be set, dont wait till + * realize for that + */ +static void +gdk_dtree_load_pixmaps (GtkDTree *dtree) +{ + g_assert (dtree); + + gtk_dtree_load_pixmap ( + DIRECTORY_OPEN_XPM, + &dtree->pixmap_open, &dtree->bitmap_open); + gtk_dtree_load_pixmap ( + DIRECTORY_CLOSE_XPM, + &dtree->pixmap_close, &dtree->bitmap_close); +} + +static void +gtk_dtree_init (GtkDTree *dtree) +{ + dtree->current_path = NULL; +} + +void +gtk_dtree_construct (GtkDTree *dtree) +{ + g_return_if_fail (dtree != NULL); + g_return_if_fail (GTK_IS_DTREE (dtree)); + + gtk_ctree_construct (GTK_CTREE (dtree), 1, 0, NULL); + + gtk_ctree_set_line_style (GTK_CTREE (dtree), GTK_CTREE_LINES_DOTTED); + gtk_ctree_set_reorderable (GTK_CTREE (dtree), TRUE); + gtk_clist_set_selection_mode(GTK_CLIST (dtree), GTK_SELECTION_BROWSE); + gdk_dtree_load_pixmaps (dtree); + gtk_dtree_load_root_tree (dtree); + +} + +GtkWidget * +gtk_dtree_new (void) +{ + GtkWidget *widget; + + widget = gtk_type_new (GTK_TYPE_DTREE); + gtk_dtree_construct (GTK_DTREE (widget)); + + return widget; +} + +GtkType +gtk_dtree_get_type (void) +{ + static GtkType dtree_type = 0; + + if (!dtree_type) + { + GtkTypeInfo dtree_info = + { + "GtkDTree", + sizeof (GtkDTree), + sizeof (GtkDTreeClass), + (GtkClassInitFunc) gtk_dtree_class_init, + (GtkObjectInitFunc) gtk_dtree_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + dtree_type = gtk_type_unique (GTK_TYPE_CTREE, &dtree_info); + } + + return dtree_type; +} diff --git a/gnome/gtree.h b/gnome/gtree.h new file mode 100644 index 000000000..6c9e8129d --- /dev/null +++ b/gnome/gtree.h @@ -0,0 +1,43 @@ +#ifndef _GNOME_TREE_H +#define _GNOME_TREE_H + +#include + +#define GTK_TYPE_DTREE (gtk_dtree_get_type ()) +#define GTK_DTREE(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_DTREE, GtkDTree)) +#define GTK_DTREE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_DTREE, GtkDTreeClass)) +#define GTK_IS_DTREE(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_DTREE)) +#define GTK_IS_DTREE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_DTREE)) + +typedef struct { + GtkCTree ctree; + + char *current_path; + GtkCTreeNode *root_node; /* root node */ + GtkCTreeNode *last_node; /* last visited node */ + + /* Pixmaps for showing directories */ + GdkPixmap *pixmap_open; + GdkPixmap *pixmap_close; + + /* Masks */ + GdkBitmap *bitmap_open; + GdkBitmap *bitmap_close; +} GtkDTree; + +typedef struct { + GtkCTreeClass parent_class; + + void (* directory_changed) (GtkDTree *dtree, char *directory); +} GtkDTreeClass; + +guint gtk_dtree_get_type (void); +GtkWidget *gtk_dtree_new (); +void gtk_dtree_select_parent (GtkDTree *dtree, + char *directory); +void gtk_dtree_select_child (GtkDTree *dtree); +gboolean gtk_dtree_add_dir_by_name (GtkDTree *dtree, + char *directory); +void gtk_dtree_remove_dir_by_name (GtkDTree *dtree, + gchar *directory); +#endif