using Gee; using Gdk; using Gtk; using Dino.Entities; namespace Dino.Ui { [GtkTemplate (ui = "/im/dino/Dino/file_default_widget.ui")] public class FileDefaultWidget : Box { public signal void clicked(); public signal void open_file(); public signal void save_file_as(); public signal void cancel_download(); [GtkChild] public unowned Stack image_stack; [GtkChild] public unowned Label name_label; [GtkChild] public unowned Label mime_label; [GtkChild] public unowned Image content_type_image; [GtkChild] public unowned Spinner spinner; [GtkChild] public unowned MenuButton file_menu; private FileTransfer.State state; class construct { install_action("file.open", null, (widget, action_name) => { ((FileDefaultWidget) widget).open_file(); }); install_action("file.save_as", null, (widget, action_name) => { ((FileDefaultWidget) widget).save_file_as(); }); install_action("file.cancel", null, (widget, action_name) => { ((FileDefaultWidget) widget).cancel_download(); }); } public FileDefaultWidget() { EventControllerMotion this_motion_events = new EventControllerMotion(); this.add_controller(this_motion_events); this_motion_events.enter.connect(on_pointer_entered_event); this_motion_events.leave.connect(on_pointer_left_event); GestureClick gesture_click_controller = new GestureClick(); gesture_click_controller.set_button(1); // listen for left clicks this.add_controller(gesture_click_controller); gesture_click_controller.pressed.connect((n_press, x, y) => { // Check whether the click was inside the file menu. Otherwise, open the file. double x_button, y_button; this.translate_coordinates(file_menu, x, y, out x_button, out y_button); if (file_menu.contains(x_button, y_button)) return; this.clicked(); }); } public void update_file_info(string? mime_type, FileTransfer.State state, long size) { this.state = state; spinner.stop(); // A hidden spinning spinner still uses CPU. Deactivate asap content_type_image.icon_name = get_file_icon_name(mime_type); string? mime_description = mime_type != null ? ContentType.get_description(mime_type) : null; switch (state) { case FileTransfer.State.COMPLETE: mime_label.label = mime_description; image_stack.set_visible_child_name("content_type_image"); // Create a menu Menu menu_model = new Menu(); menu_model.append(_("Open"), "file.open"); menu_model.append(_("Save as…"), "file.save_as"); Gtk.PopoverMenu popover_menu = new Gtk.PopoverMenu.from_model(menu_model); file_menu.popover = popover_menu; popover_menu.closed.connect(on_pointer_left); break; case FileTransfer.State.IN_PROGRESS: mime_label.label = _("Downloading %s…").printf(get_size_string(size)); spinner.start(); image_stack.set_visible_child_name("spinner"); // Create a menu Menu menu_model = new Menu(); menu_model.append(_("Cancel"), "file.cancel_download"); Gtk.PopoverMenu popover_menu = new Gtk.PopoverMenu.from_model(menu_model); file_menu.popover = popover_menu; popover_menu.closed.connect(on_pointer_left); break; case FileTransfer.State.NOT_STARTED: if (mime_description != null) { mime_label.label = _("%s offered: %s").printf(mime_description, get_size_string(size)); } else if (size != -1) { mime_label.label = _("File offered: %s").printf(get_size_string(size)); } else { mime_label.label = _("File offered"); } image_stack.set_visible_child_name("content_type_image"); break; case FileTransfer.State.FAILED: mime_label.use_markup = true; mime_label.label = "" + _("File transfer failed") + ""; image_stack.set_visible_child_name("content_type_image"); break; } } private void on_pointer_entered_event() { this.set_cursor_from_name("pointer"); content_type_image.opacity = 0.7; if (state == FileTransfer.State.NOT_STARTED) { image_stack.set_visible_child_name("download_image"); } if (state == FileTransfer.State.COMPLETE || state == FileTransfer.State.IN_PROGRESS) { file_menu.opacity = 1; } } private void on_pointer_left_event() { if (file_menu.popover != null && file_menu.popover.visible) return; this.set_cursor(null); on_pointer_left(); } private void on_pointer_left() { content_type_image.opacity = 0.5; if (state == FileTransfer.State.NOT_STARTED) { image_stack.set_visible_child_name("content_type_image"); } file_menu.opacity = 0; } private static string get_file_icon_name(string? mime_type) { if (mime_type == null) return "dino-file-symbolic"; string generic_icon_name = ContentType.get_generic_icon_name(mime_type) ?? ""; switch (generic_icon_name) { case "audio-x-generic": return "dino-file-music-symbolic"; case "image-x-generic": return "dino-file-image-symbolic"; case "text-x-generic": return "dino-file-document-symbolic"; case "text-x-generic-template": return "dino-file-document-symbolic"; case "video-x-generic": return "dino-file-video-symbolic"; case "x-office-document": return "dino-file-document-symbolic"; case "x-office-spreadsheet": return "dino-file-table-symbolic"; default: return "dino-file-symbolic"; } } private static string get_size_string(long size) { if (size < 1024) { return @"$(size) B"; } else if (size < 1000 * 1000) { return @"$(size / 1000) kB"; } else if (size < 1000 * 1000 * 1000) { return @"$(size / 1000 / 1000) MB"; } else { return @"$(size / 1000 / 1000 / 1000) GB"; } } } }