libxputty 0.1
Loading...
Searching...
No Matches
xsavefile-dialoge.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#ifdef __linux__
35#include <pwd.h>
36#endif
37
38#include <libgen.h>
39
40#include "xfile-dialog.h"
41#include "xmessage-dialog.h"
42
43
44static void file_released_callback(void *w_, void* user_data);
45static void combo_response(void *w_, void* user_data);
46static void set_selected_file(FileDialog *file_dialog, int reload);
47
48static void draw_window(void *w_, void* user_data) {
49 Widget_t *w = (Widget_t*)w_;
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);
58 cairo_fill (w->crb);
59
61 cairo_set_font_size (w->crb, 12.0);
62 cairo_move_to (w->crb, 20, 35);
63 cairo_show_text(w->crb, _("Base Directory"));
64 cairo_move_to (w->crb, 20, 85);
65 cairo_show_text(w->crb, _("Places"));
66 cairo_move_to (w->crb, 130, 85);
67 cairo_show_text(w->crb, _("Entries"));
68 cairo_move_to (w->crb, 20, 340-w->scale.scale_y);
69 cairo_show_text(w->crb, _("Load: "));
70 cairo_move_to (w->crb, 45, 380-w->scale.scale_y);
71 cairo_show_text(w->crb, _("Show hidden files"));
72}
73
74static void button_quit_callback(void *w_, void* user_data) {
75 Widget_t *w = (Widget_t*)w_;
76 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
77
78 if (w->flags & HAS_POINTER && !adj_get_value(w->adj)){
79 file_dialog->parent->func.dialog_callback(file_dialog->parent,NULL);
80 file_dialog->send_clear_func = false;
81 destroy_widget(file_dialog->w,file_dialog->w->app);
82 }
83}
84
85static inline int set_files(FileDialog *file_dialog) {
86 listview_set_list(file_dialog->ft,file_dialog->fp->file_names , (int)file_dialog->fp->file_counter);
87 int ret = -1;
88 int i = 0;
89 for (; i<(int)file_dialog->fp->file_counter; i++) {
90 if(file_dialog->fp->selected_file && strcmp(file_dialog->fp->file_names[i],
91 basename(file_dialog->fp->selected_file))==0 ) ret = i;
92 }
93 return ret;
94}
95
96static void set_dirs(FileDialog *file_dialog) {
97 int i = 0;
98 for (; i<(int)file_dialog->fp->dir_counter; i++) {
99 combobox_add_entry(file_dialog->ct,file_dialog->fp->dir_names[i]);
100 }
101}
102
103static void get_entry(Widget_t *w) {
104 Widget_t *p = (Widget_t*)w->parent;
105 FileDialog *file_dialog = (FileDialog *)p->parent_struct;
106 if (strlen( file_dialog->text_entry->input_label))
107 file_dialog->text_entry->input_label[strlen( file_dialog->text_entry->input_label)-1] = 0;
108 file_dialog->text_entry->label = file_dialog->text_entry->input_label;
109}
110
111static void file_released_b_callback(void *w_, void *button, void* user_data) {
112 Widget_t *w = (Widget_t*)w_;
113 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
114 set_selected_file(file_dialog, 1);
115 if(file_dialog->fp->selected_file) {
116 file_dialog->w->label = file_dialog->fp->selected_file;
117 expose_widget(file_dialog->w);
118 }
119}
120
121static void dummy(void *w_, void* user_data) {
122
123}
124
125static void reload_from_dir(FileDialog *file_dialog) {
126 file_dialog->ft->func.value_changed_callback = dummy;
127 assert(file_dialog->fp->path != NULL);
128 listview_remove_list(file_dialog->ft);
129 combobox_delete_entrys(file_dialog->ct);
130 int ds = fp_get_files(file_dialog->fp,file_dialog->fp->path, 1, 1);
131 file_dialog->ft->func.button_release_callback = file_released_b_callback;
132 int set_f = set_files(file_dialog);
133 set_dirs(file_dialog);
134 combobox_set_active_entry(file_dialog->ct, ds);
135 if (set_f != -1) {
136 listview_set_active_entry(file_dialog->ft, set_f);
137 } else {
138 listview_unset_active_entry(file_dialog->ft);
139 }
141 expose_widget(file_dialog->ft);
142 expose_widget(file_dialog->ct);
143 expose_widget(file_dialog->xdg_dirs);
144}
145
146static void set_selected_file(FileDialog *file_dialog, int reload) {
147 Widget_t* menu = file_dialog->ct->childlist->childs[1];
148 Widget_t* view_port = menu->childlist->childs[0];
149 ComboBox_t *comboboxlist = (ComboBox_t*)view_port->parent_struct;
150 if ((int)adj_get_value(file_dialog->ct->adj) < 0) return;
151 free(file_dialog->fp->selected_file);
152 file_dialog->fp->selected_file = NULL;
153 get_entry(file_dialog->text_entry);
154 if (strlen(file_dialog->text_entry->label)) {
155 asprintf(&file_dialog->fp->selected_file, "%s%s%s", comboboxlist->list_names[(int)adj_get_value(file_dialog->ct->adj)],
156 PATH_SEPARATOR,
157 file_dialog->text_entry->label);
158 } else if(file_dialog->fp->file_counter ) {
159
160 if (os_is_directory(file_dialog->fp->file_names[(int)adj_get_value(file_dialog->ft->adj)])) {
161 asprintf(&file_dialog->fp->path, "%s",file_dialog->fp->file_names[(int)adj_get_value(file_dialog->ft->adj)]);
162 if (reload) reload_from_dir(file_dialog);
163 return;
164 }
165 asprintf(&file_dialog->fp->selected_file, "%s%s%s", comboboxlist->list_names[(int)adj_get_value(file_dialog->ct->adj)],
166 PATH_SEPARATOR,
167 file_dialog->fp->file_names[(int)adj_get_value(file_dialog->ft->adj)]);
168 }
169}
170
171static void file_released_callback(void *w_, void* user_data) {
172 Widget_t *w = (Widget_t*)w_;
173 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
174 set_selected_file(file_dialog, 1);
175 if(file_dialog->fp->selected_file) {
176 file_dialog->w->label = file_dialog->fp->selected_file;
177 expose_widget(file_dialog->w);
178 }
179}
180
181static void forward_key_press(void *w_, void *key_, void *user_data) {
182 Widget_t *w = (Widget_t*)w_;
183 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
184 file_dialog->text_entry->func.key_press_callback(file_dialog->text_entry, key_, user_data);
185}
186
187static void reload_file_entrys(FileDialog *file_dialog) {
188 listview_remove_list(file_dialog->ft);
189 fp_get_files(file_dialog->fp,file_dialog->fp->path, 0, 1);
190 int set_f = set_files(file_dialog);
191 if (set_f != -1) {
192 listview_set_active_entry(file_dialog->ft, set_f);
193 } else {
194 listview_unset_active_entry(file_dialog->ft);
195 }
196 file_dialog->ft->func.value_changed_callback = file_released_callback;
197 expose_widget(file_dialog->ft);
198}
199
200static void combo_response(void *w_, void* user_data) {
201 Widget_t *w = (Widget_t*)w_;
202 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
203 Widget_t* menu = w->childlist->childs[1];
204 Widget_t* view_port = menu->childlist->childs[0];
205 ComboBox_t *comboboxlist = (ComboBox_t*)view_port->parent_struct;
206 if ((int)adj_get_value(w->adj) < 0) return;
207 free(file_dialog->fp->path);
208 file_dialog->fp->path = NULL;
209 asprintf(&file_dialog->fp->path, "%s",comboboxlist->list_names[(int)adj_get_value(w->adj)]);
210 assert(file_dialog->fp->path != NULL);
211 reload_from_dir(file_dialog);
212}
213
214static void save_and_exit(void *w_) {
215 Widget_t *w = (Widget_t*)w_;
216 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
217 if(file_dialog->fp->selected_file) {
218 file_dialog->parent->func.dialog_callback(file_dialog->parent,&file_dialog->fp->selected_file);
219 file_dialog->send_clear_func = false;
220 destroy_widget(file_dialog->w,file_dialog->w->app);
221 } else {
222 open_message_dialog(w, INFO_BOX, _("INFO"),
223 _("Please enter a file name"),NULL);
224 }
225
226}
227
228static void question_response(void *w_, void* user_data) {
229 if(user_data !=NULL) {
230 int response = *(int*)user_data;
231 if(response == 0) {
232 save_and_exit(w_);
233 }
234 }
235}
236
237static void button_ok_callback(void *w_, void* user_data) {
238 Widget_t *w = (Widget_t*)w_;
239 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
240 if (w->flags & HAS_POINTER && !*(int*)user_data){
241 set_selected_file(file_dialog, 0);
242 if( access(file_dialog->fp->selected_file, F_OK ) != -1 ) {
244 _("File already exists, would you overwrite it?"),NULL);
245 w->func.dialog_callback = question_response;
246 } else {
247 save_and_exit(w_);
248 }
249 }
250}
251
252static void save_on_enter(void *w_) {
253 Widget_t *w = (Widget_t*)w_;
254 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
255 set_selected_file(file_dialog, 0);
256 if( access(file_dialog->fp->selected_file, F_OK ) != -1 ) {
258 _("File already exists, would you overwrite it?"),NULL);
259 w->func.dialog_callback = question_response;
260 } else {
261 save_and_exit(w_);
262 }
263
264}
265
266static void reload_all(FileDialog *file_dialog) {
267 file_dialog->ft->func.value_changed_callback = dummy;
268 Widget_t* menu = file_dialog->ct->childlist->childs[1];
269 Widget_t* view_port = menu->childlist->childs[0];
270 ComboBox_t *comboboxlist = (ComboBox_t*)view_port->parent_struct;
271 if ((int)adj_get_value(file_dialog->ct->adj) < 0) return;
272 free(file_dialog->fp->path);
273 file_dialog->fp->path = NULL;
274 asprintf(&file_dialog->fp->path, "%s",comboboxlist->list_names[(int)adj_get_value(file_dialog->ct->adj)]);
275 assert(file_dialog->fp->path != NULL);
276 listview_remove_list(file_dialog->ft);
277 combobox_delete_entrys(file_dialog->ct);
278 int ds = fp_get_files(file_dialog->fp,file_dialog->fp->path, 1, 1);
279 int set_f = set_files(file_dialog);
280 set_dirs(file_dialog);
281 combobox_set_active_entry(file_dialog->ct, ds);
282 if (set_f != -1) {
283 listview_set_active_entry(file_dialog->ft, set_f);
284 } else {
285 listview_unset_active_entry(file_dialog->ft);
286 }
287 file_dialog->ft->func.value_changed_callback = file_released_callback;
288 expose_widget(file_dialog->ft);
289}
290
291static void open_dir_callback(void *w_, void* user_data) {
292 Widget_t *w = (Widget_t*)w_;
293 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
294 if (w->flags & HAS_POINTER && !*(int*)user_data){
295 reload_all(file_dialog);
296 }
297}
298
299static void button_hidden_callback(void *w_, void* user_data) {
300 Widget_t *w = (Widget_t*)w_;
301 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
302 if (w->flags & HAS_POINTER) {
303 file_dialog->fp->show_hidden = adj_get_value(w->adj) ? true : false;
304 reload_all(file_dialog);
305 }
306}
307
308static void set_filter_callback(void *w_, void* user_data) {
309 Widget_t *w = (Widget_t*)w_;
310 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
311 if (file_dialog->fp->use_filter != (int)adj_get_value(w->adj)) {
312 file_dialog->fp->use_filter = (int)adj_get_value(w->adj);
313 Widget_t* menu = w->childlist->childs[1];
314 Widget_t* view_port = menu->childlist->childs[0];
315 ComboBox_t *comboboxlist = (ComboBox_t*)view_port->parent_struct;
316 if ((int)adj_get_value(w->adj) < 0) return;
317 free(file_dialog->fp->filter);
318 file_dialog->fp->filter = NULL;
319 asprintf(&file_dialog->fp->filter, "%s",comboboxlist->list_names[(int)adj_get_value(w->adj)]);
320 assert(file_dialog->fp->filter != NULL);
321
322 reload_file_entrys(file_dialog);
323 }
324}
325
326static void draw_entry(void *w_, void* user_data) {
327 Widget_t *w = (Widget_t*)w_;
328 if (!w) return;
329 Metrics_t metrics;
330 os_get_window_metrics(w, &metrics);
331 int width = metrics.width-2;
332 int height = metrics.height-2;
333 if (!metrics.visible) return;
334
336 cairo_rectangle(w->cr,0,0,width,height);
337 cairo_fill_preserve (w->cr);
339 cairo_set_line_width(w->cr, 2.0);
340 cairo_stroke(w->cr);
341
342 cairo_set_font_size (w->cr, 9.0);
343
344 cairo_move_to (w->cr, 2, 9);
345 cairo_show_text(w->cr, " ");
346}
347
348static void entry_add_text(void *w_, void *label_) {
349 Widget_t *w = (Widget_t*)w_;
350 if (!w) return;
351 char *label = (char*)label_;
352 if (!label) {
353 label = (char*)"";
354 }
355 draw_entry(w,NULL);
356 cairo_text_extents_t extents;
358 cairo_set_font_size (w->cr, 11.0);
359 if (strlen( w->input_label))
360 w->input_label[strlen( w->input_label)-1] = 0;
361 if (strlen( w->input_label)<30) {
362 if (strlen(label))
363 strcat( w->input_label, label);
364 }
365 w->label = w->input_label;
366 strcat( w->input_label, "|");
367 cairo_set_font_size (w->cr, 12.0);
368 cairo_text_extents(w->cr, w->input_label , &extents);
369
370 cairo_move_to (w->cr, 2, 12.0+extents.height);
371 cairo_show_text(w->cr, w->input_label);
372
373}
374
375static void entry_clip(Widget_t *w) {
376 draw_entry(w,NULL);
377 cairo_text_extents_t extents;
379 cairo_set_font_size (w->cr, 11.0);
380
381 // check for UTF 8 char
382 if (strlen( w->input_label)>=2) {
383 int i = strlen( w->input_label)-1;
384 int j = 0;
385 int u = 0;
386 for(;i>0;i--) {
387 if(IS_UTF8(w->input_label[i])) {
388 u++;
389 }
390 j++;
391 if (u == 1) break;
392 if (j>2) break;
393 }
394 if (!u) j =2;
395
396 memset(&w->input_label[strlen( w->input_label)-(sizeof(char)*(j))],0,sizeof(char)*(j));
397 strcat( w->input_label, "|");
398 }
399 cairo_set_font_size (w->cr, 12.0);
400 cairo_text_extents(w->cr, w->input_label , &extents);
401
402 cairo_move_to (w->cr, 2, 12.0+extents.height);
403 cairo_show_text(w->cr, w->input_label);
404
405}
406
407static void entry_get_text(void *w_, void *key_, void *user_data) {
408 Widget_t *w = (Widget_t*)w_;
409 if (!w) return;
410 XKeyEvent *key = (XKeyEvent*)key_;
411 if (!key) return;
412 int nk = key_mapping(w->app->dpy, key);
413 if (nk == 11) {
414 entry_clip(w);
415 } else {
416 char buf[32];
417 bool status = os_get_keyboard_input(w, key, buf, sizeof(buf) - 1);
418 if (key_mapping(w->app->dpy, key) == 10) {
419 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
420 save_on_enter(file_dialog->w_okay);
421 return;
422 }
423 if(status){
424 entry_add_text(w, buf);
425 }
426 }
427}
428
429static void fd_mem_free(void *w_, void* user_data) {
430 Widget_t *w = (Widget_t*)w_;
431 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
432 if(file_dialog->send_clear_func)
433 file_dialog->parent->func.dialog_callback(file_dialog->parent,NULL);
434 fp_free(file_dialog->fp);
435 free(file_dialog->fp);
436 free(file_dialog);
437}
438
439#ifdef __linux__
440static int starts_with(const char *restrict string, const char *restrict prefix) {
441 while(*prefix)
442 {
443 if(*prefix++ != *string++)
444 return 0;
445 }
446
447 return 1;
448}
449
450static int strremove(char *string, const char *restrict find){
451 if(strstr(string, find) == NULL) return 0;
452 char *temporaryString = malloc(strlen(strstr(string, find) + strlen(find)) + 1);
453 strcpy(temporaryString, strstr(string, find) + strlen(find));
454 char* rep = strstr(string, find);
455 *rep = '\0';
456 //strcat(string, replaceWith);
457 strcat(string, temporaryString);
458 free(temporaryString);
459 return 1;
460}
461
462static void parse_xdg_dirs(FileDialog *file_dialog) {
463
464 char xdg_dir[204];
465 file_dialog->home_dir = getenv("HOME");
466 if (file_dialog->home_dir == NULL) {
467 file_dialog->home_dir = getpwuid(getuid())->pw_dir;
468 }
469 if (file_dialog->home_dir == NULL) return;
470 sprintf(xdg_dir,"%s/.config/user-dirs.dirs", file_dialog->home_dir);
471 FILE * fp = NULL;
472 char * line = NULL;
473 size_t len = 0;
474 ssize_t read;
475
476 file_dialog->xdg_user_dirs = (char **)realloc(file_dialog->xdg_user_dirs,
477 (file_dialog->xdg_dir_counter + 1) * sizeof(char *));
478 assert(file_dialog->xdg_user_dirs != NULL);
479 asprintf(&file_dialog->xdg_user_dirs[file_dialog->xdg_dir_counter++], "%s", _("Home"));
480 assert(file_dialog->xdg_user_dirs[file_dialog->xdg_dir_counter-1] != NULL);
481
482 fp = fopen(xdg_dir, "r");
483 if (fp != NULL) {
484 while ((read = getline(&line, &len, fp)) != -1) {
485 if(starts_with(line,"XDG_")) {
486 char* xdg = strstr(line, "$HOME/");
487 if (!strremove(xdg, "$HOME/")) continue;
488 char* rep = strstr(xdg, "\"");
489 *rep = '\0';
490 file_dialog->xdg_user_dirs = (char **)realloc(file_dialog->xdg_user_dirs,
491 (file_dialog->xdg_dir_counter + 1) * sizeof(char *));
492 assert(file_dialog->xdg_user_dirs != NULL);
493 asprintf(&file_dialog->xdg_user_dirs[file_dialog->xdg_dir_counter++], "%s", xdg);
494 assert(file_dialog->xdg_user_dirs[file_dialog->xdg_dir_counter-1] != NULL);
495 }
496 }
497 }
498
499 file_dialog->xdg_user_dirs = (char **)realloc(file_dialog->xdg_user_dirs,
500 (file_dialog->xdg_dir_counter + 1) * sizeof(char *));
501 assert(file_dialog->xdg_user_dirs != NULL);
502 asprintf(&file_dialog->xdg_user_dirs[file_dialog->xdg_dir_counter++], "%s", _("Computer"));
503 assert(file_dialog->xdg_user_dirs[file_dialog->xdg_dir_counter-1] != NULL);
504
505 fclose(fp);
506 if (line)
507 free(line);
508}
509
510static void xdg_dir_select_callback(void *w_, void *button, void* user_data) {
511 Widget_t *w = (Widget_t*)w_;
512 FileDialog *file_dialog = (FileDialog *)w->parent_struct;
513 int v = (int)adj_get_value(w->adj);
514 if (v == 0) {
515 free(file_dialog->fp->path);
516 file_dialog->fp->path = NULL;
517 asprintf(&file_dialog->fp->path, "%s",file_dialog->home_dir);
518 assert(file_dialog->fp->path != NULL);
519 } else if (v == file_dialog->xdg_dir_counter) {
520 free(file_dialog->fp->path);
521 file_dialog->fp->path = NULL;
522 asprintf(&file_dialog->fp->path, "%s",PATH_SEPARATOR);
523 assert(file_dialog->fp->path != NULL);
524 } else {
525 free(file_dialog->fp->path);
526 file_dialog->fp->path = NULL;
527 asprintf(&file_dialog->fp->path, "%s/%s",file_dialog->home_dir,file_dialog->xdg_user_dirs[v]);
528 assert(file_dialog->fp->path != NULL);
529 }
530 reload_from_dir(file_dialog);
531}
532
533static void add_xdg_dirs(FileDialog *file_dialog) {
534 file_dialog->xdg_dirs = add_listview(file_dialog->w, "", 20, 90, 100, 225);
535 file_dialog->xdg_dirs->parent_struct = file_dialog;
536 file_dialog->xdg_dirs->scale.gravity = EASTNORTH;
537 file_dialog->xdg_dirs->func.key_press_callback = forward_key_press;
538 listview_set_list(file_dialog->xdg_dirs, file_dialog->xdg_user_dirs, (int)file_dialog->xdg_dir_counter);
539 file_dialog->xdg_dirs->func.button_release_callback = xdg_dir_select_callback;
541}
542#endif
543
544Widget_t *save_file_dialog(Widget_t *w, const char *path, const char *filter) {
545 FileDialog *file_dialog = (FileDialog*)malloc(sizeof(FileDialog));
546
547 file_dialog->xdg_user_dirs = NULL;
548 file_dialog->xdg_dir_counter = 0;
549 file_dialog->fp = (FilePicker*)malloc(sizeof(FilePicker));
550
551#ifdef __linux__
552 parse_xdg_dirs(file_dialog);
553 struct stat sb;
554 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
555 fp_init(file_dialog->fp, path);
556 } else if (stat(file_dialog->home_dir, &sb) == 0 && S_ISDIR(sb.st_mode)) {
557 fp_init(file_dialog->fp, file_dialog->home_dir);
558 } else {
559 fp_init(file_dialog->fp, "/");
560 }
561#else
562 DWORD attr = GetFileAttributes(path);
563 if (attr&FILE_ATTRIBUTE_DIRECTORY) {
564 fp_init(file_dialog->fp, path);
565 } else {
566 fp_init(file_dialog->fp, "c:\\");
567 }
568
569#endif
570
571 file_dialog->parent = w;
572 file_dialog->send_clear_func = true;
573
574 file_dialog->w = create_window(w->app, os_get_root_window(w->app, IS_WINDOW), 0, 0, 660, 420);
575#ifdef __linux__
576 XSizeHints* win_size_hints;
577 win_size_hints = XAllocSizeHints();
578 win_size_hints->flags = PMinSize|PBaseSize|PMaxSize|PWinGravity;
579 win_size_hints->min_width = 660;
580 win_size_hints->min_height = 420;
581 win_size_hints->base_width = 660;
582 win_size_hints->base_height = 420;
583 win_size_hints->max_width = 660;
584 win_size_hints->max_height = 840;
585 win_size_hints->win_gravity = CenterGravity;
586 XSetWMNormalHints(file_dialog->w->app->dpy, file_dialog->w->widget, win_size_hints);
587 XFree(win_size_hints);
588#endif
589 file_dialog->w->flags |= HAS_MEM;
590 file_dialog->w->parent_struct = file_dialog;
591 widget_set_title(file_dialog->w, _("File Save"));
592 file_dialog->w->func.expose_callback = draw_window;
593 file_dialog->w->func.key_press_callback = forward_key_press;
594 file_dialog->w->func.mem_free_callback = fd_mem_free;
595 widget_set_icon_from_png(file_dialog->w,LDVAR(directory_png));
596
597 file_dialog->ct = add_combobox(file_dialog->w, "", 20, 40, 550, 30);
598 file_dialog->ct->parent_struct = file_dialog;
599 file_dialog->ct->scale.gravity = NORTHEAST;
600 file_dialog->ct->func.value_changed_callback = combo_response;
601 file_dialog->ct->func.key_press_callback = forward_key_press;
602
603 file_dialog->sel_dir = add_button(file_dialog->w, _("Open"), 580, 40, 60, 30);
604 file_dialog->sel_dir->parent_struct = file_dialog;
605 file_dialog->sel_dir->scale.gravity = WESTNORTH;
606 add_tooltip(file_dialog->sel_dir,_("Open sub-directory's"));
607 file_dialog->sel_dir->func.value_changed_callback = open_dir_callback;
608 file_dialog->sel_dir->func.key_press_callback = forward_key_press;
609
610 file_dialog->ft = add_listview(file_dialog->w, "", 130, 90, 510, 225);
611 file_dialog->ft->parent_struct = file_dialog;
612 file_dialog->ft->scale.gravity = NORTHWEST;
613 listview_set_check_dir(file_dialog->ft, 1);
614 file_dialog->ft->func.key_press_callback = forward_key_press;
615
616 int ds = fp_get_files(file_dialog->fp,file_dialog->fp->path, 1, 1);
617 int set_f = set_files(file_dialog);
618 set_dirs(file_dialog);
619 combobox_set_active_entry(file_dialog->ct, ds);
620 if (set_f != -1) {
621 listview_set_active_entry(file_dialog->ft, set_f);
622 } else {
623 listview_unset_active_entry(file_dialog->ft);
624 }
625 file_dialog->ft->func.value_changed_callback = file_released_callback;
626
627#ifdef __linux__
628 add_xdg_dirs(file_dialog);
629#endif
630 file_dialog->text_entry = create_widget(file_dialog->w->app, file_dialog->w, 130, 320, 200, 30);
631 memset(file_dialog->text_entry->input_label, 0, 32 * (sizeof file_dialog->text_entry->input_label[0]) );
632 file_dialog->text_entry->func.expose_callback = entry_add_text;
633 file_dialog->text_entry->func.key_press_callback = entry_get_text;
634 file_dialog->text_entry->flags &= ~USE_TRANSPARENCY;
635 file_dialog->text_entry->scale.gravity = EASTWEST;
636 file_dialog->text_entry->parent_struct = file_dialog;
637#ifdef __linux__
638 Cursor c = XCreateFontCursor(file_dialog->w->app->dpy, XC_xterm);
639 XDefineCursor (file_dialog->w->app->dpy, file_dialog->text_entry->widget, c);
640 XFreeCursor(file_dialog->w->app->dpy, c);
641#endif
642
643 file_dialog->w_quit = add_button(file_dialog->w, _("Cancel"), 580, 350, 60, 60);
644 file_dialog->w_quit->parent_struct = file_dialog;
645 file_dialog->w_quit->scale.gravity = SOUTHWEST;
646 add_tooltip(file_dialog->w_quit,_("Exit File Saver"));
647 file_dialog->w_quit->func.value_changed_callback = button_quit_callback;
648 file_dialog->w_quit->func.key_press_callback = forward_key_press;
649
650 file_dialog->w_okay = add_button(file_dialog->w, _("Save"), 490, 350, 80, 60);
651 file_dialog->w_okay->parent_struct = file_dialog;
652 file_dialog->w_okay->scale.gravity = SOUTHWEST;
653 add_tooltip(file_dialog->w_okay,_("Save as selected file"));
654 file_dialog->w_okay->func.value_changed_callback = button_ok_callback;
655 file_dialog->w_okay->func.key_press_callback = forward_key_press;
656
657 file_dialog->set_filter = add_combobox(file_dialog->w, "", 340, 355, 120, 30);
658 file_dialog->set_filter->parent_struct = file_dialog;
659 file_dialog->set_filter->scale.gravity = SOUTHWEST;
660 combobox_add_entry(file_dialog->set_filter,_("all"));
661 combobox_add_entry(file_dialog->set_filter,_("application"));
662 combobox_add_entry(file_dialog->set_filter,_("audio"));
663 combobox_add_entry(file_dialog->set_filter,_("font"));
664 combobox_add_entry(file_dialog->set_filter,_("image"));
665 combobox_add_entry(file_dialog->set_filter,_("text"));
666 combobox_add_entry(file_dialog->set_filter,_("video"));
667 combobox_add_entry(file_dialog->set_filter,_("x-content"));
668 if(filter !=NULL && strlen(filter))
669 combobox_add_entry(file_dialog->set_filter,filter);
670 combobox_set_active_entry(file_dialog->set_filter, 0);
671 file_dialog->set_filter->func.key_press_callback = forward_key_press;
672 file_dialog->set_filter->func.value_changed_callback = set_filter_callback;
673 if(filter !=NULL && strlen(filter))
674 combobox_set_active_entry(file_dialog->set_filter, 8);
675 add_tooltip(file_dialog->set_filter->childlist->childs[0], _("File filter type"));
676
677 file_dialog->w_hidden = add_check_button(file_dialog->w, "", 20, 365, 20, 20);
678 file_dialog->w_hidden->parent_struct = file_dialog;
679 file_dialog->w_hidden->scale.gravity = EASTWEST;
680 add_tooltip(file_dialog->w_hidden,_("Show hidden files and folders"));
681 file_dialog->w_hidden->func.key_press_callback = forward_key_press;
682 file_dialog->w_hidden->func.value_changed_callback = button_hidden_callback;
683
684 widget_show_all(file_dialog->w);
685 return file_dialog->w;
686}
687
688/*---------------------------------------------------------------------
689-----------------------------------------------------------------------
690 add_file_button
691-----------------------------------------------------------------------
692----------------------------------------------------------------------*/
693
694static void fdialog_response(void *w_, void* user_data) {
695 Widget_t *w = (Widget_t*)w_;
696 FileButton *filebutton = (FileButton *)w->parent_struct;
697 if(user_data !=NULL) {
698 char *tmp = strdup(*(const char**)user_data);
699 free(filebutton->last_path);
700 filebutton->last_path = NULL;
701 filebutton->last_path = strdup(dirname(tmp));
702 filebutton->path = filebutton->last_path;
703 free(tmp);
704 }
705 w->func.user_callback(w,user_data);
706 filebutton->is_active = false;
707 adj_set_value(w->adj,0.0);
708}
709
710static void fbutton_callback(void *w_, void* user_data) {
711 Widget_t *w = (Widget_t*)w_;
712 FileButton *filebutton = (FileButton *)w->parent_struct;
713 if (w->flags & HAS_POINTER && adj_get_value(w->adj)){
714 filebutton->w = save_file_dialog(w,filebutton->path,filebutton->filter);
715 filebutton->is_active = true;
716 } else if (w->flags & HAS_POINTER && !adj_get_value(w->adj)){
717 if(filebutton->is_active)
718 destroy_widget(filebutton->w,w->app);
719 }
720}
721
722static void fbutton_mem_free(void *w_, void* user_data) {
723 Widget_t *w = (Widget_t*)w_;
724 FileButton *filebutton = (FileButton *)w->parent_struct;
725 free(filebutton->last_path);
726 filebutton->last_path = NULL;
727 free(filebutton);
728 filebutton = NULL;
729}
730
731Widget_t *add_save_file_button(Widget_t *parent, int x, int y, int width, int height,
732 const char *path, const char *filter) {
733 FileButton *filebutton = (FileButton*)malloc(sizeof(FileButton));
734 filebutton->path = path;
735 filebutton->filter = filter;
736 filebutton->last_path = NULL;
737 filebutton->w = NULL;
738 filebutton->is_active = false;
739 Widget_t *fbutton = add_image_toggle_button(parent, "", x, y, width, height);
740 fbutton->parent_struct = filebutton;
741 fbutton->flags |= HAS_MEM;
742 widget_get_png(fbutton, LDVAR(directory_open_png));
743 fbutton->scale.gravity = CENTER;
744 fbutton->func.mem_free_callback = fbutton_mem_free;
745 fbutton->func.value_changed_callback = fbutton_callback;
746 fbutton->func.dialog_callback = fdialog_response;
747 return fbutton;
748}
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 * w_okay
Widget_t * text_entry
char ** xdg_user_dirs
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 key_press_callback
Definition xwidget.h:104
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_...
float scale_y
Definition xwidget.h:359
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
XColor_t * color_scheme
Definition xwidget.h:467
Adjustment_t * adj
Definition xwidget.h:497
void * parent
Definition xwidget.h:471
Window widget
Definition xwidget.h:469
cairo_t * crb
Definition xwidget.h:489
Childlist_t * childlist
Definition xwidget.h:499
long long flags
Definition xwidget.h:461
char input_label[32]
Definition xwidget.h:459
const char * label
Definition xwidget.h:463
cairo_t * cr
Definition xwidget.h:485
void * parent_struct
Definition xwidget.h:473
Func_t func
Definition xwidget.h:481
Xputty * app
Definition xwidget.h:465
Colors normal
Definition xcolor.h:106
Colors selected
Definition xcolor.h:108
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
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
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_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
void use_base_color_scheme(Widget_t *w, Color_state st)
use_base_color_scheme - use base Colors to paint on Widget_t
Definition xcolor.c:259
@ 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
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 ...
@ QUESTION_BOX
@ INFO_BOX
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
Widget_t * save_file_dialog(Widget_t *w, const char *path, const char *filter)
save_file_dialog - open a non blocking dialog window, to select a file. The path to open the file-sel...
Widget_t * add_save_file_button(Widget_t *parent, int x, int y, int width, int height, const char *path, const char *filter)
add_save_file_button - add a pre-defined button which will pop-up a file dialog when pressed....
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
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
bool os_get_keyboard_input(Widget_t *w, XKeyEvent *key, char *buf, size_t bufsize)
os_ get_keyboard_input - Get the Keyboard input and convert it to utf8
void widget_set_title(Widget_t *w, const char *title)
widget_set_title - set window title for a Widget_t
Definition xwidget.c:359
Widget_t * create_widget(Xputty *app, Widget_t *win, int x, int y, int width, int height)
*create_widget - create a widget A Widget_t could only be created as child of a other Widget_t To...
Definition xwidget.c:265
int key_mapping(Display *dpy, XKeyEvent *xkey)
_key_mapping - modifier key's mapped to a integer value
Definition xwidget.c:37
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
@ 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
@ 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