117 GtkWidget *vbox = ui_gtk_vbox_new(0); |
117 GtkWidget *vbox = ui_gtk_vbox_new(0); |
118 #ifdef UI_LIBADWAITA |
118 #ifdef UI_LIBADWAITA |
119 GtkWidget *toolbar_view = adw_toolbar_view_new(); |
119 GtkWidget *toolbar_view = adw_toolbar_view_new(); |
120 adw_application_window_set_content(ADW_APPLICATION_WINDOW(obj->widget), toolbar_view); |
120 adw_application_window_set_content(ADW_APPLICATION_WINDOW(obj->widget), toolbar_view); |
121 adw_toolbar_view_set_content(ADW_TOOLBAR_VIEW(toolbar_view), vbox); |
121 adw_toolbar_view_set_content(ADW_TOOLBAR_VIEW(toolbar_view), vbox); |
122 |
122 |
123 GtkWidget *headerbar = adw_header_bar_new(); |
123 GtkWidget *headerbar = adw_header_bar_new(); |
124 adw_toolbar_view_add_top_bar(ADW_TOOLBAR_VIEW(toolbar_view), headerbar); |
124 adw_toolbar_view_add_top_bar(ADW_TOOLBAR_VIEW(toolbar_view), headerbar); |
125 |
125 |
126 ui_fill_headerbar(obj, headerbar); |
126 if(!simple) { |
|
127 ui_fill_headerbar(obj, headerbar); |
|
128 } |
127 #elif GTK_MAJOR_VERSION >= 4 |
129 #elif GTK_MAJOR_VERSION >= 4 |
128 WINDOW_SET_CONTENT(obj->widget, vbox); |
130 WINDOW_SET_CONTENT(obj->widget, vbox); |
129 #else |
131 #else |
130 gtk_container_add(GTK_CONTAINER(obj->widget), vbox); |
132 gtk_container_add(GTK_CONTAINER(obj->widget), vbox); |
131 |
133 |
257 |
259 |
258 WINDOW_SHOW(GTK_WIDGET(dialog_w)); |
260 WINDOW_SHOW(GTK_WIDGET(dialog_w)); |
259 } |
261 } |
260 |
262 |
261 |
263 |
262 #if GTK_MAJOR_VERSION >= 4 |
264 #if GTK_MAJOR_VERSION >= 3 |
263 static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, ui_callback file_selected_callback, void *cbdata) { |
265 UiFileList listmodel2filelist(GListModel *selection) { |
264 // TODO |
266 UiFileList flist; |
|
267 flist.files = NULL; |
|
268 flist.nfiles = 0; |
|
269 flist.nfiles = g_list_model_get_n_items(selection); |
|
270 flist.files = calloc(flist.nfiles, sizeof(char*)); |
|
271 for(int i=0;i<flist.nfiles;i++) { |
|
272 GFile *file = g_list_model_get_item(selection, i); |
|
273 char *path = g_file_get_path(file); |
|
274 flist.files[i] = path ? strdup(path) : NULL; |
|
275 g_object_unref(file); |
|
276 } |
|
277 return flist; |
|
278 } |
|
279 #endif |
|
280 |
|
281 |
|
282 #if GTK_CHECK_VERSION(4, 10, 0) |
|
283 |
|
284 #define UI_GTK_FILEDIALOG_OPEN 16 |
|
285 #define UI_GTK_FILEDIALOG_SAVE 32 |
|
286 |
|
287 static void filechooser_opened(GObject *source, GAsyncResult *result, void *data) { |
|
288 UiEventData *event = data; |
|
289 |
|
290 GFile *file = NULL; |
|
291 GListModel *selection = NULL; |
|
292 GError *error = NULL; |
|
293 |
|
294 int mode = event->value; |
|
295 int multi = mode & UI_FILEDIALOG_SELECT_MULTI; |
|
296 if((mode & UI_FILEDIALOG_SELECT_FOLDER) == UI_FILEDIALOG_SELECT_FOLDER) { |
|
297 if(multi) { |
|
298 selection = gtk_file_dialog_select_multiple_folders_finish(GTK_FILE_DIALOG(source), result, &error); |
|
299 } else { |
|
300 file = gtk_file_dialog_select_folder_finish(GTK_FILE_DIALOG(source), result, &error); |
|
301 } |
|
302 } else if((mode & UI_GTK_FILEDIALOG_OPEN) == UI_GTK_FILEDIALOG_OPEN) { |
|
303 if(multi) { |
|
304 selection = gtk_file_dialog_open_multiple_finish(GTK_FILE_DIALOG(source), result, &error); |
|
305 } else { |
|
306 file = gtk_file_dialog_open_finish(GTK_FILE_DIALOG(source), result, &error); |
|
307 } |
|
308 } else { |
|
309 file = gtk_file_dialog_save_finish(GTK_FILE_DIALOG(source), result, &error); |
|
310 } |
|
311 |
|
312 UiEvent evt; |
|
313 evt.obj = event->obj; |
|
314 evt.document = evt.obj->ctx->document; |
|
315 evt.window = evt.obj->window; |
|
316 evt.intval = 0; |
|
317 |
|
318 UiFileList flist; |
|
319 flist.files = NULL; |
|
320 flist.nfiles = 0; |
|
321 evt.eventdata = &flist; |
|
322 |
|
323 if(selection) { |
|
324 flist = listmodel2filelist(selection); |
|
325 g_object_unref(selection); |
|
326 } else if(file) { |
|
327 char *path = g_file_get_path(file); |
|
328 if(path) { |
|
329 flist.nfiles = 1; |
|
330 flist.files = calloc(flist.nfiles, sizeof(char*)); |
|
331 flist.files[0] = strdup(path); |
|
332 } |
|
333 g_object_unref(file); |
|
334 } |
|
335 |
|
336 if(event->callback) { |
|
337 event->callback(&evt, event->userdata); |
|
338 } |
|
339 |
|
340 for(int i=0;i<flist.nfiles;i++) { |
|
341 free(flist.files[i]); |
|
342 } |
|
343 } |
|
344 |
|
345 static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, const char *name, ui_callback file_selected_callback, void *cbdata) { |
|
346 if(action == GTK_FILE_CHOOSER_ACTION_OPEN) { |
|
347 mode |= UI_GTK_FILEDIALOG_OPEN; |
|
348 } else { |
|
349 mode |= UI_GTK_FILEDIALOG_SAVE; |
|
350 } |
|
351 |
|
352 UiEventData *event = malloc(sizeof(UiEventData)); |
|
353 event->callback = file_selected_callback; |
|
354 event->userdata = cbdata; |
|
355 event->customdata = NULL; |
|
356 event->value = mode; |
|
357 event->obj = obj; |
|
358 |
|
359 GtkWindow *parent = GTK_WINDOW(gtk_widget_get_root(obj->widget)); |
|
360 GtkFileDialog *dialog = gtk_file_dialog_new(); |
|
361 if(name) { |
|
362 gtk_file_dialog_set_initial_name(dialog, name); |
|
363 } |
|
364 |
|
365 int multi = mode & UI_FILEDIALOG_SELECT_MULTI; |
|
366 if((mode & UI_FILEDIALOG_SELECT_FOLDER) == UI_FILEDIALOG_SELECT_FOLDER) { |
|
367 if(multi) { |
|
368 gtk_file_dialog_select_multiple_folders(dialog, parent, NULL, filechooser_opened, event); |
|
369 } else { |
|
370 gtk_file_dialog_select_folder(dialog, parent, NULL, filechooser_opened, event); |
|
371 } |
|
372 } else if(action == GTK_FILE_CHOOSER_ACTION_OPEN) { |
|
373 if(multi) { |
|
374 gtk_file_dialog_open_multiple(dialog, parent, NULL, filechooser_opened, event); |
|
375 } else { |
|
376 gtk_file_dialog_open(dialog, parent, NULL, filechooser_opened, event); |
|
377 } |
|
378 } else { |
|
379 gtk_file_dialog_save(dialog, parent, NULL, filechooser_opened, event); |
|
380 } |
|
381 |
|
382 g_object_unref(dialog); |
265 } |
383 } |
266 #else |
384 #else |
267 static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, ui_callback file_selected_callback, void *cbdata) { |
385 |
|
386 |
|
387 |
|
388 static void filechooser_response(GtkDialog* self, gint response_id, UiEventData *data) { |
|
389 UiEvent evt; |
|
390 evt.obj = data->obj; |
|
391 evt.document = evt.obj->ctx->document; |
|
392 evt.window = evt.obj->window; |
|
393 evt.intval = 0; |
|
394 |
|
395 UiFileList flist; |
|
396 flist.files = NULL; |
|
397 flist.nfiles = 0; |
|
398 evt.eventdata = &flist; |
|
399 |
|
400 if(response_id == GTK_RESPONSE_ACCEPT) { |
|
401 #if GTK_CHECK_VERSION(4, 0, 0) |
|
402 GListModel *selection = gtk_file_chooser_get_files(GTK_FILE_CHOOSER(self)); |
|
403 flist = flist = listmodel2filelist(selection); |
|
404 g_object_unref(selection); |
|
405 #else |
|
406 GSList *selection = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(self)); |
|
407 flist.nfiles = g_slist_length(selection); |
|
408 flist.files = calloc(flist.nfiles, sizeof(char*)); |
|
409 int i = 0; |
|
410 while(selection) { |
|
411 char *file = selection->data; |
|
412 flist.files[i] = strdup(file); |
|
413 g_free(file); |
|
414 selection = selection->next; |
|
415 i++; |
|
416 } |
|
417 g_slist_free(selection); |
|
418 #endif |
|
419 } |
|
420 |
|
421 |
|
422 if(data->callback) { |
|
423 data->callback(&evt, data->userdata); |
|
424 } |
|
425 |
|
426 for(int i=0;i<flist.nfiles;i++) { |
|
427 free(flist.files[i]); |
|
428 } |
|
429 |
|
430 WINDOW_DESTROY(GTK_WIDGET(self)); |
|
431 } |
|
432 |
|
433 static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, const char *name, ui_callback file_selected_callback, void *cbdata) { |
268 char *button; |
434 char *button; |
269 char *title; |
435 char *title; |
270 |
436 |
271 GtkWidget *dialog; |
437 GtkWidget *dialog; |
272 if((mode & UI_FILEDIALOG_SELECT_FOLDER) == UI_FILEDIALOG_SELECT_FOLDER) { |
438 if((mode & UI_FILEDIALOG_SELECT_FOLDER) == UI_FILEDIALOG_SELECT_FOLDER) { |
314 UiFileList flist; |
499 UiFileList flist; |
315 flist.files = NULL; |
500 flist.files = NULL; |
316 flist.nfiles = 0; |
501 flist.nfiles = 0; |
317 evt.eventdata = &flist; |
502 evt.eventdata = &flist; |
318 |
503 |
319 int result = gtk_dialog_run(GTK_DIALOG (dialog)); |
504 gtk_widget_show(dialog); |
320 GSList *selection = NULL; |
|
321 if(result == GTK_RESPONSE_ACCEPT) { |
|
322 selection = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); |
|
323 flist.nfiles = g_slist_length(selection); |
|
324 flist.files = calloc(flist.nfiles, sizeof(char*)); |
|
325 int i = 0; |
|
326 while(selection) { |
|
327 flist.files[i] = selection->data; |
|
328 selection = selection->next; |
|
329 i++; |
|
330 } |
|
331 } |
|
332 |
|
333 if(file_selected_callback) { |
|
334 file_selected_callback(&evt, cbdata); |
|
335 } |
|
336 |
|
337 for(int i=0;i<flist.nfiles;i++) { |
|
338 g_free(flist.files[i]); |
|
339 } |
|
340 free(flist.files); |
|
341 g_slist_free(selection); |
|
342 |
|
343 gtk_widget_destroy(dialog); |
|
344 } |
505 } |
345 #endif |
506 #endif |
346 |
507 |
347 void ui_openfiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata) { |
508 void ui_openfiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata) { |
348 ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_OPEN, mode, file_selected_callback, cbdata); |
509 ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_OPEN, mode, NULL, file_selected_callback, cbdata); |
349 } |
510 } |
350 |
511 |
351 void ui_savefiledialog(UiObject *obj, const char *name, ui_callback file_selected_callback, void *cbdata) { |
512 void ui_savefiledialog(UiObject *obj, const char *name, ui_callback file_selected_callback, void *cbdata) { |
352 ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_SAVE, 0, file_selected_callback, cbdata); |
513 ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_SAVE, 0, name, file_selected_callback, cbdata); |
353 } |
514 } |
354 |
515 |