using Adw; using Gtk; namespace Publicate { public class PpubEditor : Box { private Adw.HeaderBar header; private WindowTitle header_title; private Leaflet leaflet; private Ppub.Publication publication; private File publication_file; private ViewerWindow window; private FileExplorer file_explorer; private Box tab_box; private TabView tab_view; private TabBar tab_bar; private Button save_tab_button; private Gee.HashMap open_editors = new Gee.HashMap(); public PpubEditor(ViewerWindow win) { window = win; orientation = Orientation.VERTICAL; header = new Adw.HeaderBar(); append(header); header_title = new WindowTitle("Untitled Publication", ""); header.title_widget = header_title; var file_box = new Box(Orientation.VERTICAL, 0); file_box.vexpand = true; file_explorer = new FileExplorer(); file_explorer.asset_selected.connect(open_asset); file_explorer.vexpand = true; file_box.append(file_explorer); var file_buttons = new Box(Orientation.HORIZONTAL, 0); file_buttons.add_css_class("linked"); file_buttons.halign = Align.END; file_buttons.margin_end = 8; file_buttons.margin_bottom = 8; file_buttons.margin_start = 8; file_buttons.margin_top = 8; file_box.append(file_buttons); var new_file_button = new Button.from_icon_name("document-new-symbolic"); file_buttons.append(new_file_button); var add_file_button = new Button.from_icon_name("list-add-symbolic"); file_buttons.append(add_file_button); var remove_file_button = new Button.from_icon_name("user-trash-symbolic"); file_buttons.append(remove_file_button); leaflet = new Leaflet(); leaflet.vexpand = true; leaflet.append(file_box); tab_view = new TabView(); tab_bar = new TabBar(); tab_box = new Box(Orientation.VERTICAL, 0); tab_bar.autohide = false; tab_bar.set_view(tab_view); tab_box.append(tab_bar); tab_box.append(tab_view); leaflet.append(tab_box); save_tab_button = new Button.from_icon_name("document-save-symbolic"); save_tab_button.clicked.connect(save_tab); header.pack_end(save_tab_button); tab_view.notify["selected-page"].connect(() => select_file_from_tab()); append(leaflet); } public async void load_ppub(File file) throws Error { publication = new Ppub.Publication(file.get_path()); publication_file = file; header_title.title = publication.metadata.title ?? "Untitled PPUB"; header_title.subtitle = publication.metadata.author_name ?? ""; window.title = header_title.title + " - Publicate!"; file_explorer.set_assets(publication.assets); } public async void open_asset(Ppub.Asset asset) { if(open_editors.has_key(asset.name)) { tab_view.selected_page = open_editors[asset.name].tab_page; return; } if(asset.mimetype == "text/markdown") { var editor = new Editors.MarkdownEditor(window, tab_view); add_editor(editor, asset); } else if(asset.mimetype.has_prefix("text/")) { var editor = new Editors.PlainTextEditor(window, tab_view); add_editor(editor, asset); } if(asset.mimetype == "application/x-ppub-metadata") { var editor = new Editors.MetadataEditor(window, tab_view); add_editor(editor, asset); } } private void add_editor(Editors.EditorWidget editor, Ppub.Asset asset) { editor.load_asset(publication, asset); open_editors.set(asset.name, editor); tab_view.selected_page = editor.tab_page; } private async void save(Invercargill.Enumerable to_save) { var builder = new Ppub.Builder(); foreach (var item in to_save) { item.save_asset(builder); } var temp_file = File.new_for_path(publication_file.get_path() + ".tmp"); var stream = yield temp_file.replace_async(null, false, FileCreateFlags.REPLACE_DESTINATION, Priority.DEFAULT); builder.write(stream); yield stream.close_async(Priority.DEFAULT, null); yield temp_file.move_async(publication_file, FileCopyFlags.OVERWRITE, Priority.DEFAULT, null, null); yield load_ppub(publication_file); select_file_from_tab(); } private async void save_tab() { var current_editor = (Editors.EditorWidget)tab_view.selected_page.child; var to_save = publication.assets.select(a => a.name == current_editor.asset_name ? (Savable)current_editor : new SavableAsset(publication, a)); yield save(to_save); } private void select_file_from_tab() { var editor = (Editors.EditorWidget)tab_view.selected_page.child; file_explorer.set_selected_item(editor.asset_name); } public async void add_asset (string name, string mimetype, GLib.InputStream stream, Ppub.CompressionInfo compression) { var to_save = publication.assets.select(a => new SavableAsset(publication, a)).to_sequence(); to_save.add(new SavableNewAsset(name, mimetype, stream, compression)); yield save(to_save); } } }