1/* Icon View/Icon View Basics
2 *
3 * The GtkIconView widget is used to display and manipulate icons.
4 * It uses a GtkTreeModel for data storage, so the list store
5 * example might be helpful.
6 */
7
8#include <glib/gi18n.h>
9#include <gtk/gtk.h>
10#include <string.h>
11
12static GtkWidget *window = NULL;
13
14#define FOLDER_NAME "/iconview/gnome-fs-directory.png"
15#define FILE_NAME "/iconview/gnome-fs-regular.png"
16
17enum
18{
19 COL_PATH,
20 COL_DISPLAY_NAME,
21 COL_PIXBUF,
22 COL_IS_DIRECTORY,
23 NUM_COLS
24};
25
26
27static GdkPixbuf *file_pixbuf, *folder_pixbuf;
28char *parent;
29GtkWidget *up_button;
30
31/* Loads the images for the demo and returns whether the operation succeeded */
32static void
33load_pixbufs (void)
34{
35 if (file_pixbuf)
36 return; /* already loaded earlier */
37
38 file_pixbuf = gdk_pixbuf_new_from_resource (FILE_NAME, NULL);
39 /* resources must load successfully */
40 g_assert (file_pixbuf);
41
42 folder_pixbuf = gdk_pixbuf_new_from_resource (FOLDER_NAME, NULL);
43 g_assert (folder_pixbuf);
44}
45
46static void
47fill_store (GtkListStore *store)
48{
49 GDir *dir;
50 const char *name;
51 GtkTreeIter iter;
52
53 /* First clear the store */
54 gtk_list_store_clear (list_store: store);
55
56 /* Now go through the directory and extract all the file
57 * information */
58 dir = g_dir_open (path: parent, flags: 0, NULL);
59 if (!dir)
60 return;
61
62 name = g_dir_read_name (dir);
63 while (name != NULL)
64 {
65 char *path, *display_name;
66 gboolean is_dir;
67
68 /* We ignore hidden files that start with a '.' */
69 if (name[0] != '.')
70 {
71 path = g_build_filename (first_element: parent, name, NULL);
72
73 is_dir = g_file_test (filename: path, test: G_FILE_TEST_IS_DIR);
74
75 display_name = g_filename_to_utf8 (opsysstring: name, len: -1, NULL, NULL, NULL);
76
77 gtk_list_store_append (list_store: store, iter: &iter);
78 gtk_list_store_set (list_store: store, iter: &iter,
79 COL_PATH, path,
80 COL_DISPLAY_NAME, display_name,
81 COL_IS_DIRECTORY, is_dir,
82 COL_PIXBUF, is_dir ? folder_pixbuf : file_pixbuf,
83 -1);
84 g_free (mem: path);
85 g_free (mem: display_name);
86 }
87
88 name = g_dir_read_name (dir);
89 }
90 g_dir_close (dir);
91}
92
93static int
94sort_func (GtkTreeModel *model,
95 GtkTreeIter *a,
96 GtkTreeIter *b,
97 gpointer user_data)
98{
99 gboolean is_dir_a, is_dir_b;
100 char *name_a, *name_b;
101 int ret;
102
103 /* We need this function because we want to sort
104 * folders before files.
105 */
106
107
108 gtk_tree_model_get (tree_model: model, iter: a,
109 COL_IS_DIRECTORY, &is_dir_a,
110 COL_DISPLAY_NAME, &name_a,
111 -1);
112
113 gtk_tree_model_get (tree_model: model, iter: b,
114 COL_IS_DIRECTORY, &is_dir_b,
115 COL_DISPLAY_NAME, &name_b,
116 -1);
117
118 if (!is_dir_a && is_dir_b)
119 ret = 1;
120 else if (is_dir_a && !is_dir_b)
121 ret = -1;
122 else
123 {
124 ret = g_utf8_collate (str1: name_a, str2: name_b);
125 }
126
127 g_free (mem: name_a);
128 g_free (mem: name_b);
129
130 return ret;
131}
132
133static GtkListStore *
134create_store (void)
135{
136 GtkListStore *store;
137
138 store = gtk_list_store_new (n_columns: NUM_COLS,
139 G_TYPE_STRING,
140 G_TYPE_STRING,
141 GDK_TYPE_PIXBUF,
142 G_TYPE_BOOLEAN);
143
144 /* Set sort column and function */
145 gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (store),
146 sort_func,
147 NULL, NULL);
148 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
149 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
150 order: GTK_SORT_ASCENDING);
151
152 return store;
153}
154
155static void
156item_activated (GtkIconView *icon_view,
157 GtkTreePath *tree_path,
158 gpointer user_data)
159{
160 GtkListStore *store;
161 char *path;
162 GtkTreeIter iter;
163 gboolean is_dir;
164
165 store = GTK_LIST_STORE (user_data);
166
167 gtk_tree_model_get_iter (GTK_TREE_MODEL (store),
168 iter: &iter, path: tree_path);
169 gtk_tree_model_get (GTK_TREE_MODEL (store), iter: &iter,
170 COL_PATH, &path,
171 COL_IS_DIRECTORY, &is_dir,
172 -1);
173
174 if (!is_dir)
175 {
176 g_free (mem: path);
177 return;
178 }
179
180 /* Replace parent with path and re-fill the model*/
181 g_free (mem: parent);
182 parent = path;
183
184 fill_store (store);
185
186 /* Sensitize the up button */
187 gtk_widget_set_sensitive (GTK_WIDGET (up_button), TRUE);
188}
189
190static void
191up_clicked (GtkButton *item,
192 gpointer user_data)
193{
194 GtkListStore *store;
195 char *dir_name;
196
197 store = GTK_LIST_STORE (user_data);
198
199 dir_name = g_path_get_dirname (file_name: parent);
200 g_free (mem: parent);
201
202 parent = dir_name;
203
204 fill_store (store);
205
206 /* Maybe de-sensitize the up button */
207 gtk_widget_set_sensitive (GTK_WIDGET (up_button),
208 sensitive: strcmp (s1: parent, s2: "/") != 0);
209}
210
211static void
212home_clicked (GtkButton *item,
213 gpointer user_data)
214{
215 GtkListStore *store;
216
217 store = GTK_LIST_STORE (user_data);
218
219 g_free (mem: parent);
220 parent = g_strdup (str: g_get_home_dir ());
221
222 fill_store (store);
223
224 /* Sensitize the up button */
225 gtk_widget_set_sensitive (GTK_WIDGET (up_button),
226 TRUE);
227}
228
229static void close_window(void)
230{
231 gtk_window_destroy (GTK_WINDOW (window));
232 window = NULL;
233
234 g_object_unref (object: file_pixbuf);
235 file_pixbuf = NULL;
236
237 g_object_unref (object: folder_pixbuf);
238 folder_pixbuf = NULL;
239}
240
241GtkWidget *
242do_iconview (GtkWidget *do_widget)
243{
244 if (!window)
245 {
246 GtkWidget *sw;
247 GtkWidget *icon_view;
248 GtkListStore *store;
249 GtkWidget *vbox;
250 GtkWidget *tool_bar;
251 GtkWidget *home_button;
252
253 window = gtk_window_new ();
254 gtk_window_set_default_size (GTK_WINDOW (window), width: 650, height: 400);
255
256 gtk_window_set_display (GTK_WINDOW (window),
257 display: gtk_widget_get_display (widget: do_widget));
258 gtk_window_set_title (GTK_WINDOW (window), title: "Icon View Basics");
259
260 g_signal_connect (window, "destroy",
261 G_CALLBACK (close_window), NULL);
262
263 load_pixbufs ();
264
265 vbox = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 0);
266 gtk_window_set_child (GTK_WINDOW (window), child: vbox);
267
268 tool_bar = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 0);
269 gtk_box_append (GTK_BOX (vbox), child: tool_bar);
270
271 up_button = gtk_button_new_with_mnemonic (label: "_Up");
272 gtk_widget_set_sensitive (GTK_WIDGET (up_button), FALSE);
273 gtk_box_append (GTK_BOX (tool_bar), child: up_button);
274
275 home_button = gtk_button_new_with_mnemonic (label: "_Home");
276 gtk_box_append (GTK_BOX (tool_bar), child: home_button);
277
278
279 sw = gtk_scrolled_window_new ();
280 gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE);
281 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
282 hscrollbar_policy: GTK_POLICY_AUTOMATIC,
283 vscrollbar_policy: GTK_POLICY_AUTOMATIC);
284 gtk_widget_set_vexpand (widget: sw, TRUE);
285
286 gtk_box_append (GTK_BOX (vbox), child: sw);
287
288 /* Create the store and fill it with the contents of '/' */
289 parent = g_strdup (str: "/");
290 store = create_store ();
291 fill_store (store);
292
293 icon_view = gtk_icon_view_new_with_model (GTK_TREE_MODEL (store));
294 gtk_icon_view_set_selection_mode (GTK_ICON_VIEW (icon_view),
295 mode: GTK_SELECTION_MULTIPLE);
296 g_object_unref (object: store);
297
298 /* Connect to the "clicked" signal of the "Up" tool button */
299 g_signal_connect (up_button, "clicked",
300 G_CALLBACK (up_clicked), store);
301
302 /* Connect to the "clicked" signal of the "Home" tool button */
303 g_signal_connect (home_button, "clicked",
304 G_CALLBACK (home_clicked), store);
305
306 /* We now set which model columns that correspond to the text
307 * and pixbuf of each item
308 */
309 gtk_icon_view_set_text_column (GTK_ICON_VIEW (icon_view), column: COL_DISPLAY_NAME);
310 gtk_icon_view_set_pixbuf_column (GTK_ICON_VIEW (icon_view), column: COL_PIXBUF);
311
312 /* Connect to the "item-activated" signal */
313 g_signal_connect (icon_view, "item-activated",
314 G_CALLBACK (item_activated), store);
315 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), child: icon_view);
316
317 gtk_widget_grab_focus (widget: icon_view);
318 }
319
320 if (!gtk_widget_get_visible (widget: window))
321 gtk_widget_show (widget: window);
322 else
323 gtk_window_destroy (GTK_WINDOW (window));
324
325 return window;
326}
327

source code of gtk/demos/gtk-demo/iconview.c