diff options
author | Anders Carlsson <andersca@gnome.org> | 2004-07-04 20:35:35 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@src.gnome.org> | 2004-07-04 20:35:35 +0000 |
commit | 57f0d6a21f61616acef6589eb47e518ce85ab40e (patch) | |
tree | a920293a3dd5093ec153e1fb6f2ca1d99ddfb089 /demos | |
parent | 89570b5a31036cddf91ce71429b77b4df2a3caa9 (diff) | |
download | gdk-pixbuf-57f0d6a21f61616acef6589eb47e518ce85ab40e.tar.gz |
Add a simple file browser based on the icon view.
2004-07-04 Anders Carlsson <andersca@gnome.org>
* demos/gtk-demo/Makefile.am:
* demos/gtk-demo/gnome-fs-directory.png:
* demos/gtk-demo/gnome-fs-regular.png:
* demos/gtk-demo/iconview.c: (load_pixbufs), (fill_store),
(sort_func), (create_store), (item_activated), (up_clicked),
(home_clicked), (do_iconview):
Add a simple file browser based on the icon view.
* gtk/gtk.h:
Add gtk/gtkiconview.h
* gtk/gtkiconview.c: (gtk_icon_view_layout),
(gtk_icon_view_item_new), (gtk_icon_view_item_activated):
Fix a few bugs discovered while writing the demo.
Diffstat (limited to 'demos')
-rw-r--r-- | demos/gtk-demo/Makefile.am | 5 | ||||
-rw-r--r-- | demos/gtk-demo/gnome-fs-directory.png | bin | 0 -> 2044 bytes | |||
-rw-r--r-- | demos/gtk-demo/gnome-fs-regular.png | bin | 0 -> 1795 bytes | |||
-rw-r--r-- | demos/gtk-demo/iconview.c | 358 |
4 files changed, 362 insertions, 1 deletions
diff --git a/demos/gtk-demo/Makefile.am b/demos/gtk-demo/Makefile.am index c139feb3d..7557fb91b 100644 --- a/demos/gtk-demo/Makefile.am +++ b/demos/gtk-demo/Makefile.am @@ -15,6 +15,7 @@ demos = \ entry_completion.c \ expander.c \ hypertext.c \ + iconview.c \ images.c \ list_store.c \ menus.c \ @@ -72,12 +73,14 @@ IMAGEFILES= alphatest.png \ floppybuddy.gif \ gnome-applets.png \ gnome-calendar.png \ + gnome-fs-directory.png \ + gnome-fs-regular.png \ gnome-foot.png \ gnome-gimp.png \ gnome-gmush.png \ gnome-gsame.png \ gnu-keys.png \ - gtk-logo-rgb.gif + gtk-logo-rgb.gif democode_DATA = $(demos) $(IMAGEFILES) diff --git a/demos/gtk-demo/gnome-fs-directory.png b/demos/gtk-demo/gnome-fs-directory.png Binary files differnew file mode 100644 index 000000000..05921a668 --- /dev/null +++ b/demos/gtk-demo/gnome-fs-directory.png diff --git a/demos/gtk-demo/gnome-fs-regular.png b/demos/gtk-demo/gnome-fs-regular.png Binary files differnew file mode 100644 index 000000000..0f5019c89 --- /dev/null +++ b/demos/gtk-demo/gnome-fs-regular.png diff --git a/demos/gtk-demo/iconview.c b/demos/gtk-demo/iconview.c new file mode 100644 index 000000000..56e74da74 --- /dev/null +++ b/demos/gtk-demo/iconview.c @@ -0,0 +1,358 @@ +/* Icon View + * + * The GtkIconView widget is used to display and manipulate icons. It + * uses a GtkTreeModel for data storage, so the list store example + * might be helpful. + */ + +#include <config.h> +#include <gtk/gtk.h> +#include <string.h> +#include "demo-common.h" + +static GtkWidget *window = NULL; + +#define FOLDER_NAME "gnome-fs-directory.png" +#define FILE_NAME "gnome-fs-regular.png" + +enum +{ + COL_PATH, + COL_DISPLAY_NAME, + COL_PIXBUF, + COL_IS_DIRECTORY, + NUM_COLS +}; + + +static GdkPixbuf *file_pixbuf, *folder_pixbuf; +gchar *parent; +GtkToolItem *up_button; + +/* Loads the images for the demo and returns whether the operation succeeded */ +static gboolean +load_pixbufs (GError **error) +{ + char *filename; + + if (file_pixbuf) + return TRUE; /* already loaded earlier */ + + /* demo_find_file() looks in the the current directory first, + * so you can run gtk-demo without installing GTK, then looks + * in the location where the file is installed. + */ + filename = demo_find_file (FILE_NAME, error); + if (!filename) + return FALSE; /* note that "error" was filled in and returned */ + + file_pixbuf = gdk_pixbuf_new_from_file (filename, error); + g_free (filename); + + if (!file_pixbuf) + return FALSE; /* Note that "error" was filled with a GError */ + + filename = demo_find_file (FOLDER_NAME, error); + if (!filename) + return FALSE; /* note that "error" was filled in and returned */ + + folder_pixbuf = gdk_pixbuf_new_from_file (filename, error); + g_free (filename); + + return TRUE; +} + +static void +fill_store (GtkListStore *store) +{ + GDir *dir; + const gchar *name; + GtkTreeIter iter; + + /* First clear the store */ + gtk_list_store_clear (store); + + /* Now go through the directory and extract all the file + * information */ + dir = g_dir_open (parent, 0, NULL); + if (!dir) + return; + + name = g_dir_read_name (dir); + while (name != NULL) + { + gchar *path, *display_name; + gboolean is_dir; + + /* We ignore hidden files that start with a '.' */ + if (name[0] != '.') + { + path = g_build_filename (parent, name, NULL); + + is_dir = g_file_test (path, G_FILE_TEST_IS_DIR); + + display_name = g_filename_to_utf8 (name, -1, NULL, NULL, NULL); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + COL_PATH, path, + COL_DISPLAY_NAME, display_name, + COL_IS_DIRECTORY, is_dir, + COL_PIXBUF, is_dir ? folder_pixbuf : file_pixbuf, + -1); + g_free (path); + g_free (display_name); + } + + name = g_dir_read_name (dir); + } +} + +static gint +sort_func (GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer user_data) +{ + gboolean is_dir_a, is_dir_b; + gchar *name_a, *name_b; + int ret; + + /* We need this function because we want to sort + * folders before files. + */ + + + gtk_tree_model_get (model, a, + COL_IS_DIRECTORY, &is_dir_a, + COL_DISPLAY_NAME, &name_a, + -1); + + gtk_tree_model_get (model, b, + COL_IS_DIRECTORY, &is_dir_b, + COL_DISPLAY_NAME, &name_b, + -1); + + if (!is_dir_a && is_dir_b) + ret = 1; + else if (is_dir_a && !is_dir_b) + ret = -1; + else + { + ret = g_utf8_collate (name_a, name_b); + } + + g_free (name_a); + g_free (name_b); + + return ret; +} + +GtkListStore * +create_store (void) +{ + GtkListStore *store; + + store = gtk_list_store_new (NUM_COLS, + G_TYPE_STRING, + G_TYPE_STRING, + GDK_TYPE_PIXBUF, + G_TYPE_BOOLEAN); + + /* Set sort column and function */ + gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (store), + sort_func, + NULL, NULL); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), + GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, + GTK_SORT_ASCENDING); + + return store; +} + +static void +item_activated (GtkIconView *icon_view, + GtkTreePath *tree_path, + gpointer user_data) +{ + GtkListStore *store; + gchar *path; + GtkTreeIter iter; + gboolean is_dir; + + store = GTK_LIST_STORE (user_data); + + gtk_tree_model_get_iter (GTK_TREE_MODEL (store), + &iter, tree_path); + gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, + COL_PATH, &path, + COL_IS_DIRECTORY, &is_dir, + -1); + + if (!is_dir) + { + g_free (path); + return; + } + + /* Replace parent with path and re-fill the model*/ + g_free (parent); + parent = path; + + fill_store (store); + + /* Sensitize the up button */ + gtk_widget_set_sensitive (GTK_WIDGET (up_button), TRUE); +} + +static void +up_clicked (GtkToolItem *item, + gpointer user_data) +{ + GtkListStore *store; + gchar *dir_name; + + store = GTK_LIST_STORE (user_data); + + dir_name = g_path_get_dirname (parent); + g_free (parent); + + parent = dir_name; + + fill_store (store); + + /* Maybe de-sensitize the up button */ + gtk_widget_set_sensitive (GTK_WIDGET (up_button), + strcmp (parent, "/") != 0); +} + +static void +home_clicked (GtkToolItem *item, + gpointer user_data) +{ + GtkListStore *store; + + store = GTK_LIST_STORE (user_data); + + g_free (parent); + parent = g_strdup (g_get_home_dir ()); + + fill_store (store); + + /* Sensitize the up button */ + gtk_widget_set_sensitive (GTK_WIDGET (up_button), + TRUE); +} + +GtkWidget * +do_iconview (GtkWidget *do_widget) +{ + if (!window) + { + GError *error; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_default_size (GTK_WINDOW (window), 650, 400); + + gtk_window_set_screen (GTK_WINDOW (window), + gtk_widget_get_screen (do_widget)); + gtk_window_set_title (GTK_WINDOW (window), "GtkIconView demo"); + + g_signal_connect (window, "destroy", + G_CALLBACK (gtk_widget_destroyed), &window); + + error = NULL; + if (!load_pixbufs (&error)) + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Failed to load an image: %s", + error->message); + + g_error_free (error); + + g_signal_connect (dialog, "response", + G_CALLBACK (gtk_widget_destroy), NULL); + + gtk_widget_show (dialog); + } + else + { + GtkWidget *sw; + GtkWidget *icon_view; + GtkListStore *store; + GtkWidget *vbox; + GtkWidget *tool_bar; + GtkToolItem *home_button; + + vbox = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (window), vbox); + + tool_bar = gtk_toolbar_new (); + gtk_box_pack_start (GTK_BOX (vbox), tool_bar, FALSE, FALSE, 0); + + up_button = gtk_tool_button_new_from_stock (GTK_STOCK_GO_UP); + gtk_tool_item_set_is_important (up_button, TRUE); + gtk_widget_set_sensitive (GTK_WIDGET (up_button), FALSE); + gtk_toolbar_insert (GTK_TOOLBAR (tool_bar), up_button, -1); + + home_button = gtk_tool_button_new_from_stock (GTK_STOCK_HOME); + gtk_tool_item_set_is_important (home_button, TRUE); + gtk_toolbar_insert (GTK_TOOLBAR (tool_bar), home_button, -1); + + + sw = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), + GTK_SHADOW_ETCHED_IN); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0); + + /* Create the store and fill it with the contents of '/' */ + parent = g_strdup ("/"); + store = create_store (); + fill_store (store); + + icon_view = gtk_icon_view_new_with_model (GTK_TREE_MODEL (store)); + g_object_unref (store); + + /* Connect to the "clicked" signal of the "Up" tool button */ + g_signal_connect (up_button, "clicked", + G_CALLBACK (up_clicked), store); + + /* Connect to the "clicked" signal of the "Home" tool button */ + g_signal_connect (home_button, "clicked", + G_CALLBACK (home_clicked), store); + + /* We now set which model columns that correspont to the text + * and pixbuf of each item + */ + gtk_icon_view_set_text_column (GTK_ICON_VIEW (icon_view), COL_DISPLAY_NAME); + gtk_icon_view_set_pixbuf_column (GTK_ICON_VIEW (icon_view), COL_PIXBUF); + + /* Connect to the "item_activated" signal */ + g_signal_connect (icon_view, "item_activated", + G_CALLBACK (item_activated), store); + gtk_container_add (GTK_CONTAINER (sw), icon_view); + + gtk_widget_grab_focus (icon_view); + } + } + + if (!GTK_WIDGET_VISIBLE (window)) + gtk_widget_show_all (window); + else + { + gtk_widget_destroy (window); + window = NULL; + } + + return window; +} + |