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
12 static GtkWidget *window = NULL;
13
14 #define FOLDER_NAME "/iconview/gnome-fs-directory.png"
15 #define FILE_NAME "/iconview/gnome-fs-regular.png"
16
17 enum
18 {
19 COL_PATH,
20 COL_DISPLAY_NAME,
21 COL_PIXBUF,
22 COL_IS_DIRECTORY,
23 NUM_COLS
24 };
25
26
27 static GdkPixbuf *file_pixbuf, *folder_pixbuf;
28 char *parent;
29 GtkWidget *up_button;
30
31 /* Loads the images for the demo and returns whether the operation succeeded */
32 static void
load_pixbufs(void)33 load_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
46 static void
fill_store(GtkListStore * store)47 fill_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 (store);
55
56 /* Now go through the directory and extract all the file
57 * information */
58 dir = g_dir_open (parent, 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 (parent, name, NULL);
72
73 is_dir = g_file_test (path, G_FILE_TEST_IS_DIR);
74
75 display_name = g_filename_to_utf8 (name, -1, NULL, NULL, NULL);
76
77 gtk_list_store_append (store, &iter);
78 gtk_list_store_set (store, &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 (path);
85 g_free (display_name);
86 }
87
88 name = g_dir_read_name (dir);
89 }
90 g_dir_close (dir);
91 }
92
93 static int
sort_func(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer user_data)94 sort_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 (model, a,
109 COL_IS_DIRECTORY, &is_dir_a,
110 COL_DISPLAY_NAME, &name_a,
111 -1);
112
113 gtk_tree_model_get (model, 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 (name_a, name_b);
125 }
126
127 g_free (name_a);
128 g_free (name_b);
129
130 return ret;
131 }
132
133 static GtkListStore *
create_store(void)134 create_store (void)
135 {
136 GtkListStore *store;
137
138 store = gtk_list_store_new (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 GTK_SORT_ASCENDING);
151
152 return store;
153 }
154
155 static void
item_activated(GtkIconView * icon_view,GtkTreePath * tree_path,gpointer user_data)156 item_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, tree_path);
169 gtk_tree_model_get (GTK_TREE_MODEL (store), &iter,
170 COL_PATH, &path,
171 COL_IS_DIRECTORY, &is_dir,
172 -1);
173
174 if (!is_dir)
175 {
176 g_free (path);
177 return;
178 }
179
180 /* Replace parent with path and re-fill the model*/
181 g_free (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
190 static void
up_clicked(GtkButton * item,gpointer user_data)191 up_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 (parent);
200 g_free (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 strcmp (parent, "/") != 0);
209 }
210
211 static void
home_clicked(GtkButton * item,gpointer user_data)212 home_clicked (GtkButton *item,
213 gpointer user_data)
214 {
215 GtkListStore *store;
216
217 store = GTK_LIST_STORE (user_data);
218
219 g_free (parent);
220 parent = g_strdup (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
close_window(void)229 static void close_window(void)
230 {
231 gtk_window_destroy (GTK_WINDOW (window));
232 window = NULL;
233
234 g_object_unref (file_pixbuf);
235 file_pixbuf = NULL;
236
237 g_object_unref (folder_pixbuf);
238 folder_pixbuf = NULL;
239 }
240
241 GtkWidget *
do_iconview(GtkWidget * do_widget)242 do_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), 650, 400);
255
256 gtk_window_set_display (GTK_WINDOW (window),
257 gtk_widget_get_display (do_widget));
258 gtk_window_set_title (GTK_WINDOW (window), "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 (GTK_ORIENTATION_VERTICAL, 0);
266 gtk_window_set_child (GTK_WINDOW (window), vbox);
267
268 tool_bar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
269 gtk_box_append (GTK_BOX (vbox), tool_bar);
270
271 up_button = gtk_button_new_with_mnemonic ("_Up");
272 gtk_widget_set_sensitive (GTK_WIDGET (up_button), FALSE);
273 gtk_box_append (GTK_BOX (tool_bar), up_button);
274
275 home_button = gtk_button_new_with_mnemonic ("_Home");
276 gtk_box_append (GTK_BOX (tool_bar), 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 GTK_POLICY_AUTOMATIC,
283 GTK_POLICY_AUTOMATIC);
284 gtk_widget_set_vexpand (sw, TRUE);
285
286 gtk_box_append (GTK_BOX (vbox), sw);
287
288 /* Create the store and fill it with the contents of '/' */
289 parent = g_strdup ("/");
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 GTK_SELECTION_MULTIPLE);
296 g_object_unref (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), COL_DISPLAY_NAME);
310 gtk_icon_view_set_pixbuf_column (GTK_ICON_VIEW (icon_view), 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), icon_view);
316
317 gtk_widget_grab_focus (icon_view);
318 }
319
320 if (!gtk_widget_get_visible (window))
321 gtk_widget_show (window);
322 else
323 gtk_window_destroy (GTK_WINDOW (window));
324
325 return window;
326 }
327