Loads doodles from $HOME/doodle also
[tbo.git] / src / doodle-treeview.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <sys/stat.h>
4 #include <gtk/gtk.h>
5 #include "svgimage.h"
6 #include "ui-drawing.h"
7 #include "frame.h"
8 #include "doodle-treeview.h"
9 #include "dnd.h"
10 #include "tbo-utils.h"
11 #include "tbo-files.h"
12
13 void free_gstring_array (GArray *arr);
14
15 static GArray *TO_FREE = NULL;
16 static TboWindow *TBO = NULL;
17
18 void
19 doodle_free_all ()
20 {
21     int i;
22     if (!TO_FREE) return;
23     for (i=0; i<TO_FREE->len; i++)
24     {
25         free_gstring_array (g_array_index (TO_FREE, GArray*, i));
26     }
27     g_array_free (TO_FREE, TRUE);
28     TO_FREE = NULL;
29 }
30
31 void doodle_add_to_free (GArray *arr)
32 {
33     if (!TO_FREE)
34         TO_FREE = g_array_new (FALSE, FALSE, sizeof(GArray*));
35
36     g_array_append_val (TO_FREE, arr);
37 }
38
39 gboolean
40 on_doodle_click_cb (GtkWidget      *widget,
41                     GdkEventButton *event,
42                     gpointer       *data)
43 {
44     Frame *frame = get_frame_view ();
45     SVGImage *svgimage = tbo_svgimage_new_with_params (0, 0, 0, 0, (char*)data);
46     update_drawing (TBO);
47     tbo_frame_add_obj (frame, svgimage);
48 }
49
50 void
51 free_gstring_array (GArray *arr)
52 {
53     int i;
54     GString *mystr;
55
56     for (i=0; i<arr->len; i++)
57     {
58         mystr = g_array_index (arr, GString*, i);
59         g_string_free (mystr, TRUE);
60     }
61     g_array_free (arr, TRUE);
62 }
63
64 GArray *
65 get_files (gchar *base_dir, gboolean isdir)
66 {
67     GError *error = NULL;
68     gchar complete_dir[255];
69     const gchar *filename;
70     struct stat filestat;
71     int st;
72     GArray *array = g_array_new (FALSE, FALSE, sizeof(GString*));
73
74     st = stat (base_dir, &filestat);
75     if (st)
76         return NULL;
77
78     GDir *dir = g_dir_open (base_dir, 0, &error);
79
80     while (filename = g_dir_read_name (dir))
81     {
82         size_t strsize = sizeof (char) * (strlen (base_dir) + strlen (filename) + 2);
83         snprintf (complete_dir, strsize, "%s/%s", base_dir, filename);
84         st = stat (complete_dir, &filestat);
85
86         if (isdir && S_ISDIR (filestat.st_mode))
87         {
88             GString *dirname_to_append = g_string_new (complete_dir);
89             g_array_append_val (array, dirname_to_append);
90         }
91         else if (!isdir && !S_ISDIR (filestat.st_mode))
92         {
93             GString *filename_to_append = g_string_new (complete_dir);
94             g_array_append_val (array, filename_to_append);
95         }
96     }
97
98     g_dir_close (dir);
99
100     return array;
101 }
102
103 GtkWidget *
104 doodle_add_images (gchar *dir)
105 {
106     int i;
107     gchar *dirname;
108     GtkWidget *table;
109     GtkWidget *image;
110     GtkWidget *ebox;
111     GdkPixbuf *pixbuf;
112     int r, c=2;
113     int left, top;
114     int w=50, h;
115
116     dirname = dir;
117
118     GArray *arr = get_files (dirname, FALSE);
119
120     r = (arr->len / c) + 1;
121     table = gtk_table_new (r, c, TRUE);
122
123     GString *mystr;
124     for (i=0; i<arr->len; i++)
125     {
126         top = i / 2;
127         left = i % 2;
128
129         mystr = g_array_index (arr, GString*, i);
130         image = gtk_image_new_from_file (mystr->str);
131         pixbuf = gtk_image_get_pixbuf (GTK_IMAGE (image));
132
133         h = gdk_pixbuf_get_height (pixbuf) * 50 / (float)gdk_pixbuf_get_width (pixbuf);
134         pixbuf = gdk_pixbuf_scale_simple (pixbuf, w, h, GDK_INTERP_BILINEAR);
135
136         gtk_widget_destroy (GTK_WIDGET (image));
137         image = gtk_image_new_from_pixbuf (pixbuf);
138         ebox = gtk_event_box_new ();
139         gtk_widget_add_events (ebox, GDK_BUTTON_PRESS_MASK |
140                                      GDK_BUTTON_RELEASE_MASK |
141                                      GDK_POINTER_MOTION_MASK);
142
143         //g_signal_connect (ebox, "button_press_event", G_CALLBACK (on_doodle_click_cb), mystr->str);
144
145         // dnd
146         gtk_drag_source_set (ebox,
147                              GDK_BUTTON1_MASK,
148                              TARGET_LIST,
149                              N_TARGETS,
150                              GDK_ACTION_COPY);
151         g_signal_connect (ebox, "drag-data-get", G_CALLBACK (drag_data_get_handl),
152                                                 mystr->str + tbo_files_prefix_len (mystr->str));
153         g_signal_connect (ebox, "drag-begin", G_CALLBACK (drag_begin_handl), mystr->str);
154         g_signal_connect (ebox, "drag-end", G_CALLBACK (drag_end_handl), mystr->str);
155
156         gtk_container_add (GTK_CONTAINER (ebox), image);
157         gtk_table_attach_defaults (GTK_TABLE (table), ebox, left, left + 1, top, top + 1);
158     }
159
160     doodle_add_to_free (arr);
161
162     gtk_widget_show_all (GTK_WIDGET (table));
163     return table;
164 }
165
166 void
167 doodle_add_dir_images (gchar *dir, GtkWidget *box)
168 {
169     char base_name[255];
170     get_base_name (dir, base_name, 255);
171     GtkWidget *expander = gtk_expander_new (base_name);
172     GtkWidget *table = doodle_add_images (dir);
173     gtk_container_add (GTK_CONTAINER (expander), table);
174     gtk_expander_set_expanded (GTK_EXPANDER (expander), TRUE);
175     gtk_container_add (GTK_CONTAINER (box), expander);
176 }
177
178 void
179 on_expand_cb (GtkExpander *expander, GString *str)
180 {
181     GString *mystr2;
182     int i;
183     GtkWidget *vbox = g_list_first (gtk_container_get_children (GTK_CONTAINER (expander)))->data;
184     int numofchilds = g_list_length (gtk_container_get_children (GTK_CONTAINER (vbox)));
185     if (numofchilds == 0)
186     {
187         GArray *subdir = get_files (str->str, TRUE);
188         for (i=0; i<subdir->len; i++)
189         {
190             mystr2 = g_array_index (subdir, GString*, i);
191             doodle_add_dir_images (mystr2->str, vbox);
192         }
193         free_gstring_array (subdir);
194         g_string_free (str, TRUE);
195     }
196     gtk_widget_show_all (GTK_WIDGET (vbox));
197 }
198
199 GtkWidget *
200 doodle_setup_tree (TboWindow *tbo)
201 {
202     GtkWidget *expander;
203     GtkWidget *vbox;
204     GtkWidget *vbox2;
205     gchar *dirname;
206
207     TBO = tbo;
208
209     dirname = malloc (255*sizeof(char));
210     char label_format[255];
211     int i, j, k;
212
213     vbox = gtk_vbox_new (FALSE, 5);
214
215     GArray *arr = NULL;
216     GString *mystr, *mystr2;
217
218     char **possible_dirs = tbo_files_get_dirs ();
219     for (k=0; possible_dirs[k]; k++)
220     {
221         arr = get_files (possible_dirs[k], TRUE);
222         if (!arr) continue;
223
224         for (i=0; i<arr->len; i++)
225         {
226             mystr = g_array_index (arr, GString*, i);
227
228             vbox2 = gtk_vbox_new (FALSE, 5);
229             get_base_name (mystr->str, dirname, 255);
230             snprintf (label_format, 255, "<span underline=\"single\" size=\"large\" weight=\"ultrabold\">%s</span>", dirname);
231             expander = gtk_expander_new (label_format);
232             gtk_expander_set_use_markup (GTK_EXPANDER (expander), TRUE);
233             gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, FALSE, 5);
234             gtk_container_add (GTK_CONTAINER (expander), vbox2);
235
236             mystr2 = g_string_new (mystr->str);
237             g_signal_connect (GTK_EXPANDER (expander), "activate", G_CALLBACK (on_expand_cb), mystr2);
238         }
239         free_gstring_array (arr);
240     }
241     tbo_files_free (possible_dirs);
242
243     free (dirname);
244
245     return vbox;
246 }