libxputty 0.1
Loading...
Searching...
No Matches
xfile-dialog.c
Go to the documentation of this file.
1/*
2 * 0BSD
3 *
4 * BSD Zero Clause License
5 *
6 * Copyright (c) 2019 Hermann Meyer
7 *
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted.
10
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 *
19 */
20
21
22/*
23#ifndef _GNU_SOURCE
24#define _GNU_SOURCE 1
25#endif
26*/
27
28#include <dirent.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <stdarg.h>
32#include <string.h>
33#include <unistd.h>
34
35#ifdef __linux__
36#include <pwd.h>
37#endif
38
39#include <libgen.h>
40
41#include "xfile-dialog.h"
42#include "xmessage-dialog.h"
43
44static void combo_response(void *w_, void* user_data);
45static void set_selected_file(FileDialog *file_dialog);
46
47static void draw_window(void *w_, void* user_data) {
48 Widget_t *w = (Widget_t*)w_;
49 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
50 Metrics_t metrics;
51 os_get_window_metrics(w, &metrics);
52 int width = metrics.width;
53 int height = metrics.height;
54 if (!metrics.visible) return;
55
56 cairo_rectangle(w->crb,0,0,width,height);
57 set_pattern(w,&w->color_scheme->selected,&w->color_scheme->normal,BACKGROUND_);
58 cairo_fill (w->crb);
59
60 //widget_set_scale(w);
62 cairo_set_font_size (w->crb, 12.0);
63 cairo_move_to (w->crb, 20, 35);
64 cairo_show_text(w->crb, _("Base Directory"));
65 cairo_move_to (w->crb, 20, 85);
66 cairo_show_text(w->crb, _("Places"));
67 cairo_move_to (w->crb, 130, 85);
68 cairo_show_text(w->crb, _("Entries"));
69 cairo_move_to (w->crb, 20, 330-w->scale.scale_y);
70 cairo_show_text(w->crb, _("Load: "));
71 cairo_move_to (w->crb, 45, 360-w->scale.scale_y);
72 cairo_show_text(w->crb, _("Show hidden files"));
73 cairo_move_to (w->crb, 45, 390-w->scale.scale_y);
74 cairo_show_text(w->crb, _("List view"));
75 if (w->label) {
76 char *file = utf8_from_locale(file_dialog->fp->selected_file);
77 cairo_move_to (w->crb, 60, 330-w->scale.scale_y);
78 cairo_show_text(w->crb, file);
79 free(file);
80 }
81 //widget_reset_scale(w);
82 if (w->image) {
83 cairo_set_source_surface (w->crb, w->image, 180, 332-w->scale.scale_y);
84 cairo_paint (w->crb);
85 }
86}
87
88static void draw_fd_hslider(void *w_, void* user_data) {
89 Widget_t *w = (Widget_t*)w_;
90
91 int width = w->width-2;
92 int height = w->height-2;
93 float center = (float)height/2;
94
95 float sliderstate = adj_get_state(w->adj_x);
96
98 cairo_move_to (w->crb, 0.0, center);
99 cairo_line_to(w->crb,width,center);
100 cairo_set_line_width(w->crb,center/10);
101 cairo_stroke(w->crb);
102
104 cairo_rectangle(w->crb, (width-height)*sliderstate,0,height, height);
105 cairo_fill(w->crb);
106 cairo_new_path (w->crb);
107
109 cairo_set_line_width(w->crb,3);
110 cairo_move_to (w->crb,((width-height)*sliderstate)+center, 0.0);
111 cairo_line_to(w->crb,((width-height)*sliderstate)+center,height);
112 cairo_stroke(w->crb);
113 cairo_new_path (w->crb);
114}
115
116static void button_quit_callback(void *w_, void* user_data) {
117 Widget_t *w = (Widget_t*)w_;
118 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
119
120 if (w->flags & HAS_POINTER && !adj_get_value(w->adj)){
121 file_dialog->parent->func.dialog_callback(file_dialog->parent,NULL);
122 file_dialog->send_clear_func = false;
123 destroy_widget(file_dialog->w,file_dialog->w->app);
124 }
125}
126
127static inline int set_files(FileDialog *file_dialog) {
128 if (file_dialog->list_view) {
129 listview_set_list(file_dialog->ft,file_dialog->fp->file_names , (int)file_dialog->fp->file_counter);
130 } else {
131 multi_listview_set_list(file_dialog->ft,file_dialog->fp->file_names , (int)file_dialog->fp->file_counter);
132 }
133 int ret = -1;
134 int i = 0;
135 for (; i<(int)file_dialog->fp->file_counter; i++) {
136 if(file_dialog->fp->selected_file && strcmp(file_dialog->fp->file_names[i],
137 basename(file_dialog->fp->selected_file))==0 ) ret = i;
138 //fprintf(stderr, "Files %s\n", file_dialog->fp->file_names[i]);
139 }
140 return ret;
141}
142
143static void set_dirs(FileDialog *file_dialog) {
144 int i = 0;
145 //combobox_add_entry(file_dialog->ct,"c:\\");
146 for (; i<(int)file_dialog->fp->dir_counter; i++) {
147 char *label = utf8_from_locale(file_dialog->fp->dir_names[i]);
148 combobox_add_entry(file_dialog->ct,label);
149 free(label);
150 //fprintf(stderr, "dirs %s\n", file_dialog->fp->dir_names[i]);
151 }
152}
153
154static void file_released_b_callback(void *w_, void *button_, void* user_data) {
155 Widget_t *w = (Widget_t*)w_;
156 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
157 XButtonEvent *xbutton = (XButtonEvent*)button_;
158 if(xbutton->button == Button1) {
159 set_selected_file(file_dialog);
160 if(file_dialog->fp->selected_file) {
161 file_dialog->w->label = file_dialog->fp->selected_file;
162 expose_widget(file_dialog->w);
163 }
164 }
165}
166
167static void null_callback(void *w, void* user_data) {
168
169}
170
171static void reload_from_dir(FileDialog *file_dialog) {
172 assert(file_dialog->fp->path != NULL);
173 if (file_dialog->list_view) {
174 listview_remove_list(file_dialog->ft);
175 } else {
176 multi_listview_remove_list(file_dialog->ft);
177 }
178 combobox_delete_entrys(file_dialog->ct);
179 int ds = fp_get_files(file_dialog->fp,file_dialog->fp->path, 1, 1);
180 int set_f = set_files(file_dialog);
181 set_dirs(file_dialog);
182 file_dialog->ct->func.value_changed_callback = null_callback;
183 combobox_set_active_entry(file_dialog->ct, ds);
184 file_dialog->ct->func.value_changed_callback = combo_response;
185
186 if (set_f != -1) {
187 if (file_dialog->list_view) {
188 listview_set_active_entry(file_dialog->ft, set_f);
189 } else {
190 multi_listview_set_active_entry(file_dialog->ft, set_f);
191 }
192 } else {
193 if (file_dialog->list_view) {
194 listview_unset_active_entry(file_dialog->ft);
195 } else {
197 }
198 }
199 //listview_unset_active_entry(file_dialog->xdg_dirs);
200
201 expose_widget(file_dialog->ft);
202 expose_widget(file_dialog->ct);
203 // expose_widget(file_dialog->xdg_dirs);
204}
205
206static void show_preview(FileDialog *file_dialog, const char* file_name) {
207 Widget_t* w = file_dialog->w;
208 cairo_surface_t *getpng = cairo_image_surface_create_from_png (file_name);
209 int width, height;
210 os_get_surface_size(getpng, &width, &height);
211 int width_t = 80;
212 int height_t = 80;
213 double x = (double)width_t/(double)width;
214 double y = (double)height_t/(double)height;
215 if (width > 20*height)
216 x = y = (double)width_t/(double)height;
217 cairo_surface_destroy(w->image);
218 w->image = NULL;
219
220 w->image = cairo_surface_create_similar (w->surface,
221 CAIRO_CONTENT_COLOR_ALPHA, width_t, height_t);
222 cairo_t *cri = cairo_create (w->image);
223 cairo_scale(cri, x,y);
224 cairo_set_source_surface (cri, getpng,0,0);
225 cairo_paint (cri);
226 cairo_surface_destroy(getpng);
227 cairo_destroy(cri);
228 expose_widget(w);
229}
230
231static void show_svg_preview(FileDialog *file_dialog, const char* file_name) {
232 Widget_t* w = file_dialog->w;
233 widget_get_scaled_svg_from_file(w, file_name, 80, 80);
234 expose_widget(w);
235}
236
237static void set_selected_file(FileDialog *file_dialog) {
238 if(adj_get_value(file_dialog->ft->adj)<0 ||
239 adj_get_value(file_dialog->ft->adj) > file_dialog->fp->file_counter) return;
240
241 if (os_is_directory(file_dialog->fp->file_names[(int)adj_get_value(file_dialog->ft->adj)])) {
242 asprintf(&file_dialog->fp->path, "%s",file_dialog->fp->file_names[(int)adj_get_value(file_dialog->ft->adj)]);
243 reload_from_dir(file_dialog);
244 return;
245 }
246
247 if ((int)adj_get_value(file_dialog->ct->adj) < 0) return;
248 free(file_dialog->fp->selected_file);
249 file_dialog->fp->selected_file = NULL;
250 if (strlen(file_dialog->fp->dir_names[(int)adj_get_value(file_dialog->ct->adj)]) > 1) {
251 asprintf(&file_dialog->fp->selected_file, "%s%s%s",
252 file_dialog->fp->dir_names[(int)adj_get_value(file_dialog->ct->adj)],
253 PATH_SEPARATOR,
254 file_dialog->fp->file_names[(int)adj_get_value(file_dialog->ft->adj)]);
255 } else {
256 asprintf(&file_dialog->fp->selected_file, "%s%s", PATH_SEPARATOR,
257 file_dialog->fp->file_names[(int)adj_get_value(file_dialog->ft->adj)]);
258 }
259 assert(file_dialog->fp->selected_file != NULL);
260 if (strstr(file_dialog->fp->selected_file, ".png")) {
261 show_preview(file_dialog, file_dialog->fp->selected_file);
262 } else if (strstr(file_dialog->fp->selected_file, ".svg")) {
263 show_svg_preview(file_dialog, file_dialog->fp->selected_file);
264 } else if (file_dialog->w->image) {
265 cairo_surface_destroy(file_dialog->w->image);
266 file_dialog->w->image = NULL;
267 expose_widget(file_dialog->w);
268 }
269}
270
271static void reload_file_entrys(FileDialog *file_dialog) {
272 if (file_dialog->list_view) {
273 listview_remove_list(file_dialog->ft);
274 } else {
275 multi_listview_remove_list(file_dialog->ft);
276 }
277 fp_get_files(file_dialog->fp,file_dialog->fp->path, 0, 1);
278 if (!file_dialog->fp->file_counter)
279 fp_get_files(file_dialog->fp,file_dialog->fp->path, 1, 1);
280 int set_f = set_files(file_dialog);
281 if (set_f != -1) {
282 if (file_dialog->list_view) {
283 listview_set_active_entry(file_dialog->ft, set_f);
284 } else {
285 multi_listview_set_active_entry(file_dialog->ft, set_f);
286 }
287 } else {
288 if (file_dialog->list_view) {
289 listview_unset_active_entry(file_dialog->ft);
290 } else {
292 }
293 }
294 expose_widget(file_dialog->ft);
295}
296
297static void combo_response(void *w_, void* user_data) {
298 Widget_t *w = (Widget_t*)w_;
299 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
300 Widget_t* menu = w->childlist->childs[1];
301 Widget_t* view_port = menu->childlist->childs[0];
302 ComboBox_t *comboboxlist = (ComboBox_t*)view_port->parent_struct;
303 if ((int)adj_get_value(file_dialog->ct->adj) < 0) return;
304 free(file_dialog->fp->path);
305 file_dialog->fp->path = NULL;
306 asprintf(&file_dialog->fp->path, "%s",comboboxlist->list_names[(int)adj_get_value(w->adj)]);
307 assert(file_dialog->fp->path != NULL);
308 reload_from_dir(file_dialog);
309}
310
311static void button_ok_callback(void *w_, void* user_data) {
312 Widget_t *w = (Widget_t*)w_;
313 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
314 if (w->flags & HAS_POINTER && !*(int*)user_data){
315 if(file_dialog->fp->selected_file) {
316 file_dialog->parent->func.dialog_callback(file_dialog->parent,&file_dialog->fp->selected_file);
317 file_dialog->send_clear_func = false;
318 } else {
319 Widget_t *dia = open_message_dialog(w, INFO_BOX, _("INFO"), _("Please select a file"),NULL);
320 os_set_transient_for_hint(file_dialog->w, dia);
321 return;
322 }
323 destroy_widget(file_dialog->w,file_dialog->w->app);
324 }
325}
326
327static void file_double_click_callback(void *w_, void *button, void* user_data) {
328 Widget_t *w = (Widget_t*)w_;
329 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
330 if(!file_dialog->fp->selected_file) {
331 set_selected_file(file_dialog);
332 }
333 if(file_dialog->fp->selected_file) {
334 file_dialog->parent->func.dialog_callback(file_dialog->parent,&file_dialog->fp->selected_file);
335 file_dialog->send_clear_func = false;
336 } else {
337 Widget_t *dia = open_message_dialog(w, INFO_BOX, _("INFO"), _("Please select a file"),NULL);
338 os_set_transient_for_hint(file_dialog->w, dia);
339 return;
340 }
341 destroy_widget(file_dialog->w,file_dialog->w->app);
342}
343
344static void reload_all(FileDialog *file_dialog) {
345 Widget_t* menu = file_dialog->ct->childlist->childs[1];
346 Widget_t* view_port = menu->childlist->childs[0];
347 ComboBox_t *comboboxlist = (ComboBox_t*)view_port->parent_struct;
348 if ((int)adj_get_value(file_dialog->ct->adj) < 0) return;
349 free(file_dialog->fp->path);
350 file_dialog->fp->path = NULL;
351 asprintf(&file_dialog->fp->path, "%s",comboboxlist->list_names[(int)adj_get_value(file_dialog->ct->adj)]);
352 assert(file_dialog->fp->path != NULL);
353 if (file_dialog->list_view) {
354 listview_remove_list(file_dialog->ft);
355 } else {
356 multi_listview_remove_list(file_dialog->ft);
357 }
358 combobox_delete_entrys(file_dialog->ct);
359 int ds = fp_get_files(file_dialog->fp,file_dialog->fp->path, 1, 1);
360 int set_f = set_files(file_dialog);
361 set_dirs(file_dialog);
362 combobox_set_active_entry(file_dialog->ct, ds);
363 if (set_f != -1) {
364 if (file_dialog->list_view) {
365 listview_set_active_entry(file_dialog->ft, set_f);
366 } else {
367 multi_listview_set_active_entry(file_dialog->ft, set_f);
368 }
369 } else {
370 if (file_dialog->list_view) {
371 listview_unset_active_entry(file_dialog->ft);
372 } else {
374 }
375 }
376 expose_widget(file_dialog->ft);
377}
378
379static void set_scale_factor_callback(void *w_, void* user_data) {
380 Widget_t *w = (Widget_t*)w_;
381 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
382 float v = adj_get_value(w->adj);
383 if (!file_dialog->list_view) {
384 multi_listview_set_item_size(file_dialog->ft, v);
385 }
386}
387
388static void open_dir_callback(void *w_, void* user_data) {
389 Widget_t *w = (Widget_t*)w_;
390 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
391 if (w->flags & HAS_POINTER && !*(int*)user_data){
392 reload_from_dir(file_dialog);
393 }
394}
395
396static void button_hidden_callback(void *w_, void* user_data) {
397 Widget_t *w = (Widget_t*)w_;
398 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
399 if (w->flags & HAS_POINTER) {
400 file_dialog->fp->show_hidden = adj_get_value(w->adj) ? true : false;
401 reload_all(file_dialog);
402 }
403}
404
405static void button_view_callback(void *w_, void* user_data) {
406 Widget_t *w = (Widget_t*)w_;
407 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
408 if (w->flags & HAS_POINTER) {
409 file_dialog->list_view = adj_get_value(w->adj) ? true : false;
410 }
411 if (file_dialog->list_view) {
412 destroy_widget(file_dialog->ft, w->app);
413 file_dialog->ft = add_listview(file_dialog->w, "", 130, 90, 510, 225);
414 file_dialog->ft->parent_struct = file_dialog;
415 file_dialog->ft->scale.gravity = NORTHWEST;
416 file_dialog->ft->flags |= NO_PROPAGATE;
417 listview_set_check_dir(file_dialog->ft, 1);
418 file_dialog->ft->func.button_release_callback = file_released_b_callback;
419 file_dialog->ft->func.double_click_callback = file_double_click_callback;
420 int set_f = set_files(file_dialog);
421 if (set_f != -1) {
422 listview_set_active_entry(file_dialog->ft, set_f);
423 } else {
424 listview_unset_active_entry(file_dialog->ft);
425 }
426 resize_childs(file_dialog->w);
427 widget_show_all(file_dialog->ft);
428 } else {
429 destroy_widget(file_dialog->ft, w->app);
430 file_dialog->ft = add_multi_listview(file_dialog->w, "", 130, 90, 510, 225);
431 file_dialog->ft->parent_struct = file_dialog;
432 file_dialog->ft->scale.gravity = NORTHWEST;
433 file_dialog->ft->flags |= NO_PROPAGATE;
434 multi_listview_set_check_dir(file_dialog->ft, 1);
435 file_dialog->ft->func.button_release_callback = file_released_b_callback;
436 file_dialog->ft->func.double_click_callback = file_double_click_callback;
437 int set_f = set_files(file_dialog);
438 if (set_f != -1) {
439 multi_listview_set_active_entry(file_dialog->ft, set_f);
440 } else {
442 }
443 multi_listview_set_item_size(file_dialog->ft,adj_get_value(file_dialog->scale_size->adj));
444 resize_childs(file_dialog->w);
445 widget_show_all(file_dialog->ft);
446 }
447
448}
449
450static void set_filter_callback(void *w_, void* user_data) {
451 Widget_t *w = (Widget_t*)w_;
452 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
453 if (file_dialog->fp->use_filter != (int)adj_get_value(w->adj)) {
454 file_dialog->fp->use_filter = (int)adj_get_value(w->adj);
455 Widget_t* menu = w->childlist->childs[1];
456 Widget_t* view_port = menu->childlist->childs[0];
457 ComboBox_t *comboboxlist = (ComboBox_t*)view_port->parent_struct;
458 if ((int)adj_get_value(file_dialog->ct->adj) < 0) return;
459 free(file_dialog->fp->filter);
460 file_dialog->fp->filter = NULL;
461 asprintf(&file_dialog->fp->filter, "%s",comboboxlist->list_names[(int)adj_get_value(w->adj)]);
462 assert(file_dialog->fp->filter != NULL);
463
464 reload_file_entrys(file_dialog);
465 }
466}
467
468static void fd_mem_free(void *w_, void* user_data) {
469 Widget_t *w = (Widget_t*)w_;
470 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
471 if(file_dialog->send_clear_func)
472 file_dialog->parent->func.dialog_callback(file_dialog->parent,NULL);
473 fp_free(file_dialog->fp);
474 free(file_dialog->fp);
475#ifdef __linux__
476 for (int i = 0; i<sizeof(file_dialog->xdg_user_dirs);i++) {
477 free(file_dialog->xdg_user_dirs[i]);
478 }
479 free(file_dialog->xdg_user_dirs);
480 for (int i = 0; i<sizeof(file_dialog->xdg_user_dirs_path);i++) {
481 free(file_dialog->xdg_user_dirs_path[i]);
482 }
483 free(file_dialog->xdg_user_dirs_path);
484#endif
485 free(file_dialog);
486}
487
488#ifdef __linux__
489static int starts_with(const char *restrict string, const char *restrict prefix) {
490 while(*prefix)
491 {
492 if(*prefix++ != *string++)
493 return 0;
494 }
495
496 return 1;
497}
498
499static int strremove(char *string, const char *restrict find){
500 if(strstr(string, find) == NULL) return 0;
501 char *temporaryString = malloc(strlen(strstr(string, find) + strlen(find)) + 1);
502 strcpy(temporaryString, strstr(string, find) + strlen(find));
503 char* rep = strstr(string, find);
504 *rep = '\0';
505 //strcat(string, replaceWith);
506 strcat(string, temporaryString);
507 free(temporaryString);
508 return 1;
509}
510
511static void parse_xdg_dirs(FileDialog *file_dialog) {
512
513 char xdg_dir[204];
514 file_dialog->home_dir = getenv("HOME");
515 if (file_dialog->home_dir == NULL) {
516 file_dialog->home_dir = getpwuid(getuid())->pw_dir;
517 }
518 if (file_dialog->home_dir == NULL) return;
519 sprintf(xdg_dir,"%s/.config/user-dirs.dirs", file_dialog->home_dir);
520 FILE * fp = NULL;
521 char * line = NULL;
522 size_t len = 0;
523 ssize_t read;
524 int p = 2;
525 fp = fopen(xdg_dir, "r");
526 if (fp != NULL) {
527 while ((read = getline(&line, &len, fp)) != -1) {
528 if(starts_with(line,"XDG_")) {
529 p++;
530 }
531 }
532 }
533 file_dialog->xdg_user_dirs_path = (char **)realloc(file_dialog->xdg_user_dirs_path,
534 p * sizeof(char *));
535 file_dialog->xdg_user_dirs = (char **)realloc(file_dialog->xdg_user_dirs,
536 p * sizeof(char *));
537 p = 0;
538
539 assert(file_dialog->xdg_user_dirs_path != NULL);
540 asprintf(&file_dialog->xdg_user_dirs_path[p], "%s", file_dialog->home_dir);
541
542 assert(file_dialog->xdg_user_dirs != NULL);
543 asprintf(&file_dialog->xdg_user_dirs[file_dialog->xdg_dir_counter++], "%s", _("Home"));
544
545 if (fp != NULL) {
546 rewind(fp);
547 while ((read = getline(&line, &len, fp)) != -1) {
548 if(starts_with(line,"XDG_")) {
549 p++;
550 char* xdg = strstr(line, "$HOME/");
551 if (xdg == NULL) {
552 xdg = strrchr(line, '/')+1;
553 char* path = strstr(line, "/");
554 char* re = strstr(path, "\"");
555 *re = '\0';
556 asprintf(&file_dialog->xdg_user_dirs_path[p], "%s", strstr(line, "/"));
557 asprintf(&file_dialog->xdg_user_dirs[file_dialog->xdg_dir_counter++], "%s", xdg);
558 } else if (!strremove(xdg, "$HOME/")) {
559 continue;
560 } else {
561 char* rep = strstr(xdg, "\"");
562 if (rep) *rep = '\0';
563 asprintf(&file_dialog->xdg_user_dirs_path[p], "%s/%s", file_dialog->home_dir, xdg);
564 asprintf(&file_dialog->xdg_user_dirs[file_dialog->xdg_dir_counter++], "%s", xdg);
565 }
566 }
567 }
568 fclose(fp);
569 }
570 p++;
571 asprintf(&file_dialog->xdg_user_dirs_path[p], "%s", PATH_SEPARATOR);
572 asprintf(&file_dialog->xdg_user_dirs[file_dialog->xdg_dir_counter++], "%s", _("Computer"));
573
574 if (line)
575 free(line);
576}
577
578static void xdg_dir_select_callback(void *w_, void *button, void* user_data) {
579 Widget_t *w = (Widget_t*)w_;
580 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
581 int v = (int)adj_get_value(w->adj);
582 free(file_dialog->fp->path);
583 file_dialog->fp->path = NULL;
584 asprintf(&file_dialog->fp->path, "%s",file_dialog->xdg_user_dirs_path[v]);
585 assert(file_dialog->fp->path != NULL);
586 reload_from_dir(file_dialog);
587}
588
589static void add_xdg_dirs(FileDialog *file_dialog) {
590 file_dialog->xdg_dirs = add_listview(file_dialog->w, "", 20, 90, 100, 225);
591 file_dialog->xdg_dirs->parent_struct = file_dialog;
592 file_dialog->xdg_dirs->scale.gravity = EASTNORTH;
593 file_dialog->xdg_dirs->flags |= NO_PROPAGATE;
594 listview_set_list(file_dialog->xdg_dirs, file_dialog->xdg_user_dirs, (int)file_dialog->xdg_dir_counter);
595 file_dialog->xdg_dirs->func.button_release_callback = xdg_dir_select_callback;
597}
598#endif
599Widget_t *open_file_dialog(Widget_t *w, const char *path, const char *filter) {
600 FileDialog *file_dialog = (FileDialog*)malloc(sizeof(FileDialog));
601
602 file_dialog->xdg_user_dirs = NULL;
603 file_dialog->xdg_user_dirs_path = NULL;
604 file_dialog->xdg_dir_counter = 0;
605 file_dialog->fp = (FilePicker*)malloc(sizeof(FilePicker));
606
607#ifdef __linux__
608 parse_xdg_dirs(file_dialog);
609
610 struct stat sb;
611 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
612 fp_init(file_dialog->fp, path);
613 } else if (stat(file_dialog->home_dir, &sb) == 0 && S_ISDIR(sb.st_mode)) {
614 fp_init(file_dialog->fp, file_dialog->home_dir);
615 } else {
616 fp_init(file_dialog->fp, "/");
617 }
618#else
619 DWORD attr = GetFileAttributes(path);
620 if (attr&FILE_ATTRIBUTE_DIRECTORY) {
621 fp_init(file_dialog->fp, path);
622 } else {
623 fp_init(file_dialog->fp, "C:\\");
624 }
625
626#endif
627 file_dialog->parent = w;
628 file_dialog->send_clear_func = true;
629 file_dialog->list_view = false;
630
631 file_dialog->w = create_window(w->app, os_get_root_window(w->app, IS_WINDOW), 0, 0, 660, 415);
632#ifdef __linux__
633 XSizeHints* win_size_hints;
634 win_size_hints = XAllocSizeHints();
635 win_size_hints->flags = PMinSize|PBaseSize|PMaxSize|PWinGravity;
636 win_size_hints->min_width = 660;
637 win_size_hints->min_height = 415;
638 win_size_hints->base_width = 660;
639 win_size_hints->base_height = 415;
640 win_size_hints->max_width = 960;
641 win_size_hints->max_height = 865;
642 win_size_hints->win_gravity = CenterGravity;
643 XSetWMNormalHints(file_dialog->w->app->dpy, file_dialog->w->widget, win_size_hints);
644 XFree(win_size_hints);
645#endif
646
647 file_dialog->w->flags |= HAS_MEM;
648 file_dialog->w->parent_struct = file_dialog;
649 file_dialog->w->flags |= NO_PROPAGATE;
650 widget_set_title(file_dialog->w, _("File Selector"));
651 file_dialog->w->func.expose_callback = draw_window;
652 file_dialog->w->func.mem_free_callback = fd_mem_free;
653 widget_set_icon_from_png(file_dialog->w, LDVAR(directory_png));
654
655 file_dialog->ct = add_combobox(file_dialog->w, "", 20, 40, 550, 30);
656 file_dialog->ct->parent_struct = file_dialog;
657 file_dialog->ct->scale.gravity = NORTHEAST;
658 file_dialog->ct->flags |= NO_PROPAGATE;
659
660 file_dialog->sel_dir = add_button(file_dialog->w, _("Open"), 580, 40, 60, 30);
661 file_dialog->sel_dir->parent_struct = file_dialog;
662 file_dialog->sel_dir->scale.gravity = WESTNORTH;
663 file_dialog->sel_dir->flags |= NO_PROPAGATE;
664 add_tooltip(file_dialog->sel_dir,_("Open sub-directory's"));
665 file_dialog->sel_dir->func.value_changed_callback = open_dir_callback;
666
667 file_dialog->scale_size = add_hslider(file_dialog->w, "", 580, 10, 60, 15);
668 set_adjustment(file_dialog->scale_size->adj, 0.2, 0.2, 0.1, 0.4, 0.01, CL_CONTINUOS);
669 file_dialog->scale_size->parent_struct = file_dialog;
670 file_dialog->scale_size->scale.gravity = WESTNORTH;
671 file_dialog->scale_size->flags |= NO_PROPAGATE;
672 file_dialog->scale_size->func.expose_callback = draw_fd_hslider;
673 add_tooltip(file_dialog->scale_size,_("Set Icon scale factor"));
674 file_dialog->scale_size->func.value_changed_callback = set_scale_factor_callback;
675
676 file_dialog->ft = add_multi_listview(file_dialog->w, "", 130, 90, 510, 225);
677 file_dialog->ft->parent_struct = file_dialog;
678 file_dialog->ft->scale.gravity = NORTHWEST;
679 file_dialog->ft->flags |= NO_PROPAGATE;
680 multi_listview_set_check_dir(file_dialog->ft, 1);
681 file_dialog->ft->func.button_release_callback = file_released_b_callback;
682 file_dialog->ft->func.double_click_callback = file_double_click_callback;
683
684 int ds = fp_get_files(file_dialog->fp,file_dialog->fp->path, 1, 1);
685 int set_f = set_files(file_dialog);
686 set_dirs(file_dialog);
687 combobox_set_active_entry(file_dialog->ct, ds);
688 if (set_f != -1) {
689 multi_listview_set_active_entry(file_dialog->ft, set_f);
690 } else {
692 }
693 file_dialog->ct->func.value_changed_callback = combo_response;
694
695#ifdef __linux__
696 add_xdg_dirs(file_dialog);
697#endif
698 file_dialog->w_quit = add_button(file_dialog->w, _("Cancel"), 580, 340, 60, 60);
699 file_dialog->w_quit->parent_struct = file_dialog;
700 file_dialog->w_quit->scale.gravity = SOUTHWEST;
701 file_dialog->w_quit->flags |= NO_PROPAGATE;
702 add_tooltip(file_dialog->w_quit,_("Exit file selector"));
703 file_dialog->w_quit->func.value_changed_callback = button_quit_callback;
704
705 file_dialog->w_okay = add_button(file_dialog->w, _("Load"), 510, 340, 60, 60);
706 file_dialog->w_okay->parent_struct = file_dialog;
707 file_dialog->w_okay->scale.gravity = SOUTHWEST;
708 file_dialog->w_okay->flags |= NO_PROPAGATE;
709 add_tooltip(file_dialog->w_okay,_("Load selected file"));
710 file_dialog->w_okay->func.value_changed_callback = button_ok_callback;
711
712 file_dialog->set_filter = add_combobox(file_dialog->w, "", 360, 345, 120, 30);
713 file_dialog->set_filter->parent_struct = file_dialog;
714 file_dialog->set_filter->scale.gravity = SOUTHWEST;
715 file_dialog->set_filter->flags |= NO_PROPAGATE;
716 combobox_add_entry(file_dialog->set_filter,_("all"));
717 combobox_add_entry(file_dialog->set_filter,_("application"));
718 combobox_add_entry(file_dialog->set_filter,_("audio"));
719 combobox_add_entry(file_dialog->set_filter,_("font"));
720 combobox_add_entry(file_dialog->set_filter,_("image"));
721 combobox_add_entry(file_dialog->set_filter,_("text"));
722 combobox_add_entry(file_dialog->set_filter,_("video"));
723 combobox_add_entry(file_dialog->set_filter,_("x-content"));
724 if(filter !=NULL && strlen(filter))
725 combobox_add_entry(file_dialog->set_filter,filter);
726 combobox_set_active_entry(file_dialog->set_filter, 0);
727 file_dialog->set_filter->func.value_changed_callback = set_filter_callback;
728 if(filter !=NULL && strlen(filter))
729 combobox_set_active_entry(file_dialog->set_filter, 8);
730 add_tooltip(file_dialog->set_filter->childlist->childs[0], _("File filter type"));
731
732 file_dialog->w_hidden = add_check_button(file_dialog->w, "", 20, 345, 20, 20);
733 file_dialog->w_hidden->parent_struct = file_dialog;
734 file_dialog->w_hidden->scale.gravity = EASTWEST;
735 file_dialog->w_hidden->flags |= NO_PROPAGATE;
736 add_tooltip(file_dialog->w_hidden,_("Show hidden files and folders"));
737 file_dialog->w_hidden->func.value_changed_callback = button_hidden_callback;
738
739 file_dialog->view = add_check_button(file_dialog->w, "", 20, 375, 20, 20);
740 file_dialog->view->parent_struct = file_dialog;
741 file_dialog->view->scale.gravity = EASTWEST;
742 file_dialog->view->flags |= NO_PROPAGATE;
743 add_tooltip(file_dialog->view,_("Show entries in list view"));
744 file_dialog->view->func.value_changed_callback = button_view_callback;
745
746 widget_show_all(file_dialog->w);
747 return file_dialog->w;
748}
749
750/*---------------------------------------------------------------------
751-----------------------------------------------------------------------
752 add_file_button
753-----------------------------------------------------------------------
754----------------------------------------------------------------------*/
755
756static void fdialog_response(void *w_, void* user_data) {
757 Widget_t *w = (Widget_t*)w_;
758 FileButton *filebutton = (FileButton *)w->private_struct;
759 if(user_data !=NULL) {
760 char *tmp = strdup(*(const char**)user_data);
761 free(filebutton->last_path);
762 filebutton->last_path = NULL;
763 filebutton->last_path = strdup(dirname(tmp));
764 filebutton->path = filebutton->last_path;
765 free(tmp);
766 }
767 w->func.user_callback(w,user_data);
768 filebutton->is_active = false;
769 adj_set_value(w->adj,0.0);
770}
771
772static void fbutton_callback(void *w_, void* user_data) {
773 Widget_t *w = (Widget_t*)w_;
774 FileButton *filebutton = (FileButton *)w->private_struct;
775 if (w->flags & HAS_POINTER && adj_get_value(w->adj)){
776 filebutton->w = open_file_dialog(w,filebutton->path,filebutton->filter);
777#ifdef __linux__
778 Atom wmStateAbove = XInternAtom(w->app->dpy, "_NET_WM_STATE_ABOVE", 1 );
779 Atom wmNetWmState = XInternAtom(w->app->dpy, "_NET_WM_STATE", 1 );
780 XChangeProperty(w->app->dpy, filebutton->w->widget, wmNetWmState, XA_ATOM, 32,
781 PropModeReplace, (unsigned char *) &wmStateAbove, 1);
782#endif
783 filebutton->is_active = true;
784 } else if (w->flags & HAS_POINTER && !adj_get_value(w->adj)){
785 if(filebutton->is_active)
786 destroy_widget(filebutton->w,w->app);
787 }
788}
789
790static void fbutton_mem_free(void *w_, void* user_data) {
791 Widget_t *w = (Widget_t*)w_;
792 FileButton *filebutton = (FileButton *)w->private_struct;
793 free(filebutton->last_path);
794 filebutton->last_path = NULL;
795 free(filebutton);
796 filebutton = NULL;
797}
798
799Widget_t *add_file_button(Widget_t *parent, int x, int y, int width, int height,
800 const char *path, const char *filter) {
801 FileButton *filebutton = (FileButton*)malloc(sizeof(FileButton));
802 filebutton->path = path;
803 filebutton->filter = filter;
804 filebutton->last_path = NULL;
805 filebutton->w = NULL;
806 filebutton->is_active = false;
807 Widget_t *fbutton = add_image_toggle_button(parent, "", x, y, width, height);
808 fbutton->private_struct = filebutton;
809 fbutton->flags |= HAS_MEM;
810 widget_get_png(fbutton, LDVAR(directory_open_png));
811 fbutton->scale.gravity = CENTER;
812 fbutton->func.mem_free_callback = fbutton_mem_free;
813 fbutton->func.value_changed_callback = fbutton_callback;
814 fbutton->func.dialog_callback = fdialog_response;
815 return fbutton;
816}
Widget_t ** childs
Definition xchildlist.h:51
ComboBox_t - struct to hold information for the combobox.
Definition xcombobox.h:45
const char * path
Widget_t * w
char * last_path
const char * filter
const char * home_dir
Widget_t * ft
Widget_t * w_quit
FilePicker * fp
bool send_clear_func
Widget_t * sel_dir
Widget_t * ct
Widget_t * w
unsigned int xdg_dir_counter
Widget_t * scale_size
Widget_t * w_okay
Widget_t * view
char ** xdg_user_dirs
char ** xdg_user_dirs_path
Widget_t * xdg_dirs
Widget_t * w_hidden
Widget_t * set_filter
Widget_t * parent
unsigned int file_counter
Definition xfilepicker.h:69
char * filter
Definition xfilepicker.h:64
bool show_hidden
Definition xfilepicker.h:72
char * selected_file
Definition xfilepicker.h:66
char * path
Definition xfilepicker.h:65
unsigned int dir_counter
Definition xfilepicker.h:70
char ** dir_names
Definition xfilepicker.h:68
char ** file_names
Definition xfilepicker.h:67
evfunc button_release_callback
Definition xwidget.h:101
xevfunc expose_callback
Definition xwidget.h:85
evfunc double_click_callback
Definition xwidget.h:102
xevfunc value_changed_callback
Definition xwidget.h:90
xevfunc user_callback
Definition xwidget.h:91
xevfunc mem_free_callback
Definition xwidget.h:92
xevfunc dialog_callback
Definition xwidget.h:96
Metrics_t - struct to receive window size, position & visibility Pass this struct to os_get_window_...
Gravity gravity
Definition xwidget.h:347
Widget_t - struct to hold the basic Widget_t info.
Definition xwidget.h:457
Resize_t scale
Definition xwidget.h:525
Adjustment_t * adj_x
Definition xwidget.h:493
int width
Definition xwidget.h:521
cairo_surface_t * image
Definition xwidget.h:491
Adjustment_t * adj
Definition xwidget.h:497
Window widget
Definition xwidget.h:469
cairo_surface_t * surface
Definition xwidget.h:483
cairo_t * crb
Definition xwidget.h:489
Childlist_t * childlist
Definition xwidget.h:499
long long flags
Definition xwidget.h:461
void * private_struct
Definition xwidget.h:475
const char * label
Definition xwidget.h:463
void * parent_struct
Definition xwidget.h:473
int height
Definition xwidget.h:523
Func_t func
Definition xwidget.h:481
Xputty * app
Definition xwidget.h:465
int button
Display * dpy
Definition xputty.h:232
void adj_set_value(Adjustment_t *adj, float value)
adj_set_value - set the current value to the Adjustment_t
float adj_get_value(Adjustment_t *adj)
adj_get_value - get the current value of the Adjustment_t
void set_adjustment(Adjustment_t *adj, float std_value, float value, float min_value, float max_value, float step, CL_type type)
*set_adjustment - set a new range to a existing Adjustment_t or create if it not exists yet
Definition xadjustment.c:80
@ CL_CONTINUOS
Definition xadjustment.h:49
float adj_get_state(Adjustment_t *adj)
adj_get_state - get the current state of the Adjustment_t
int asprintf(char *strp[], const char *fmt,...)
Definition xasprintf.c:36
Widget_t * add_check_button(Widget_t *parent, const char *label, int x, int y, int width, int height)
add_check_button - add a button to a Widget_t connect to func.value_changed_callback to implement you...
Definition xbutton.c:121
Widget_t * add_button(Widget_t *parent, const char *label, int x, int y, int width, int height)
add_button - add a button to a Widget_t connect to func.value_changed_callback to implement your acti...
Definition xbutton.c:26
Widget_t * add_image_toggle_button(Widget_t *parent, const char *label, int x, int y, int width, int height)
add_image_toggle_button - add a button to a Widget_t connect to func.value_changed_callback to implem...
Definition xbutton.c:89
Color_state get_color_state(Widget_t *wid)
get_color_state - get the Color_state to use in relation to the Widget_t state
Definition xcolor.c:222
void use_text_color_scheme(Widget_t *w, Color_state st)
use_text_color_scheme - use text Colors to paint on Widget_t
Definition xcolor.c:266
@ BACKGROUND_
Definition xcolor.h:65
void use_bg_color_scheme(Widget_t *w, Color_state st)
use_bg_color_scheme - use background Colors to paint on Widget_t
Definition xcolor.c:252
void use_fg_color_scheme(Widget_t *w, Color_state st)
use_fg_color_scheme - use forground Colors to paint on Widget_t
Definition xcolor.c:245
void set_pattern(Widget_t *w, Colors *from, Colors *to, Color_mod mod)
set_pattern - set pattern for the selected Colors
Definition xcolor.c:308
@ NORMAL_
Definition xcolor.h:44
void combobox_set_active_entry(Widget_t *w, int active)
combobox_set_active_entry - set the active combobox entry
Definition xcombobox.c:27
void combobox_delete_entrys(Widget_t *combobox)
combobox_delete_entrys - free the list hold the combobox entrys
Definition xcombobox.c:67
void combobox_add_entry(Widget_t *wid, const char *label)
combobox_add_entry - add a entry to the combobox
Definition xcombobox.c:175
Widget_t * add_combobox(Widget_t *parent, const char *label, int x, int y, int width, int height)
add_combobox - add a combobox
Definition xcombobox.c:152
Widget_t * add_file_button(Widget_t *parent, int x, int y, int width, int height, const char *path, const char *filter)
add_file_button - add a pre-defined button which will pop-up a file dialog when pressed....
Widget_t * open_file_dialog(Widget_t *w, const char *path, const char *filter)
open_file_dialog - open a non blocking dialog window, to select a file. The path to open the file-sel...
void fp_init(FilePicker *filepicker, const char *path)
fp_init - set default values used by the filepicker
int fp_get_files(FilePicker *filepicker, char *path, int get_dirs, int get_files)
fp_get_files - fill file_names and dir_names with the results from readdir path
void fp_free(FilePicker *filepicker)
fp_free - release all memory used by the filepicker
void listview_remove_list(Widget_t *listview)
listview_remove_list - remove the list from a listview Widget_t
Definition xlistview.c:109
Widget_t * add_listview(Widget_t *parent, const char *label, int x, int y, int width, int height)
add_label - add a listview to a Widget_t
Definition xlistview.c:72
void listview_set_check_dir(Widget_t *listview, int set)
listview_set_check_dir - set optional check if list item is a directory
Definition xlistview.c:134
void listview_set_active_entry(Widget_t *w, int active)
listview_set_active_entry - set the active listview entry
Definition xlistview.c:28
void listview_unset_active_entry(Widget_t *w)
listview_unset_active_entry - unset the active listview entry
Definition xlistview.c:39
void listview_set_list(Widget_t *listview, char **list, int list_size)
listview_set_list - set a list to a listview Widget_t
Definition xlistview.c:123
Widget_t * open_message_dialog(Widget_t *w, int style, const char *title, const char *message, const char *choices)
open_message_dialog - open a non blocking dialog window, lines in message chould be separated by the ...
@ INFO_BOX
void multi_listview_set_item_size(Widget_t *listview, float set)
multi_listview_set_item_size - set size for the icons in the viewport
void multi_listview_set_active_entry(Widget_t *w, int active)
multi_listview_set_active_entry - set the active listview entry
void multi_listview_unset_active_entry(Widget_t *w)
multi_listview_unset_active_entry - unset the active listview entry
Widget_t * add_multi_listview(Widget_t *parent, const char *label, int x, int y, int width, int height)
add_label - add a listview to a Widget_t
void multi_listview_set_list(Widget_t *listview, char **list, int list_size)
multi_listview_set_multi_list - set a list to a listview Widget_t
void multi_listview_set_check_dir(Widget_t *listview, int set)
multi_listview_set_check_dir - set optional check if list item is a directory
void multi_listview_remove_list(Widget_t *listview)
multi_listview_remove_list - remove the list from a listview Widget_t
void widget_get_png(Widget_t *w, const unsigned char *name)
widget_get_png - read png into Widget_t xlib surface
Definition xpngloader.c:75
void widget_set_icon_from_png(Widget_t *w, const unsigned char *name)
widget_set_icon_from_png - set icon image from png binary to Widget_t those icon will be used in the ...
Definition xpngloader.c:159
unsigned long int Atom
Widget_t * add_hslider(Widget_t *parent, const char *label, int x, int y, int width, int height)
add_hslider - add a horizontal slider to a Widget_t connect to func.value_changed_callback to impleme...
Definition xslider.c:51
void widget_get_scaled_svg_from_file(Widget_t *w, const char *filename, int width_t, int height_t)
widget_get_scaled_svg_from_file - read svg into Widget_t xlib surface
Definition xsvgloader.c:321
void add_tooltip(Widget_t *w, const char *label)
add_tooltip - add a tooltip to Widget_t
Definition xtooltip.c:41
void os_get_window_metrics(Widget_t *w, Metrics_t *metrics)
os_get_window_metrics - Get the Merics_t struct related to a Widget_t
char * utf8_from_locale(char *localestr)
utf8_from_locale - convert active codepage to utf8 must be freed by the caller
Window os_get_root_window(Xputty *main, int flag)
os_get_root_window - get a pointer to the root window (desktop)
bool os_is_directory(const char *filename)
os_is directory - check if a given path is a directory or a file
void os_set_transient_for_hint(Widget_t *parent, Widget_t *w)
os_set_ transient_for_hint - set a Widget_t transient to a other Widget_t only work on linux,...
void os_get_surface_size(cairo_surface_t *surface, int *width, int *height)
os_get_surface_size - get the size of the cairo surface
void widget_set_title(Widget_t *w, const char *title)
widget_set_title - set window title for a Widget_t
Definition xwidget.c:359
void expose_widget(Widget_t *w)
expose_widgets - send a expose event (EXPOSE) to a Widget_t
Definition xwidget.c:445
Widget_t * create_window(Xputty *app, Window win, int x, int y, int width, int height)
*create_window - create a Window You need to create as least minimun one Window to get started....
Definition xwidget.c:163
void resize_childs(Widget_t *wid)
resize_childs - intern check if child widgets needs resizing
Definition xwidget.c:151
@ CENTER
Definition xwidget.h:320
@ EASTWEST
Definition xwidget.h:310
@ SOUTHWEST
Definition xwidget.h:304
@ NORTHEAST
Definition xwidget.h:302
@ NORTHWEST
Definition xwidget.h:300
@ WESTNORTH
Definition xwidget.h:316
@ EASTNORTH
Definition xwidget.h:312
@ HAS_POINTER
Definition xwidget.h:402
@ HAS_MEM
Definition xwidget.h:406
@ NO_PROPAGATE
Definition xwidget.h:416
@ IS_WINDOW
Definition xwidget.h:390
void widget_show_all(Widget_t *w)
widget_show_all - map/show Widget_t with all childs
Definition xwidget.c:386
void destroy_widget(Widget_t *w, Xputty *main)
destroy_widget - destroy a widget When a Widget_t receive a destroy_widget() call,...
Definition xwidget.c:86