|
@@ -11,6 +11,7 @@ namespace Publicate {
|
|
|
private Leaflet leaflet;
|
|
|
|
|
|
private Ppub.Publication publication;
|
|
|
+ private File publication_file;
|
|
|
private ViewerWindow window;
|
|
|
|
|
|
private FileExplorer file_explorer;
|
|
@@ -18,6 +19,10 @@ namespace Publicate {
|
|
|
private TabView tab_view;
|
|
|
private TabBar tab_bar;
|
|
|
|
|
|
+ private Button save_tab_button;
|
|
|
+
|
|
|
+ private Gee.HashMap<string, Editors.EditorWidget> open_editors = new Gee.HashMap<string, Editors.EditorWidget>();
|
|
|
+
|
|
|
public PpubEditor(ViewerWindow win) {
|
|
|
window = win;
|
|
|
|
|
@@ -28,27 +33,57 @@ namespace Publicate {
|
|
|
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_explorer);
|
|
|
+ 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 ?? "";
|
|
@@ -59,13 +94,70 @@ namespace Publicate {
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
- editor.load_asset(publication, asset);
|
|
|
+ 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<Savable> 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<Savable>(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<Savable>(a => new SavableAsset(publication, a)).to_sequence();
|
|
|
+ to_save.add(new SavableNewAsset(name, mimetype, stream, compression));
|
|
|
+ yield save(to_save);
|
|
|
+
|
|
|
+ }
|
|
|
}
|
|
|
}
|