Exemplo n.º 1
0
    def __init__(self, **kwargs: Any):
        Gtk.ApplicationWindow.__init__(self, **kwargs)
        # noinspection PyCallByClass,PyArgumentList
        self.set_icon(
            GdkPixbuf.Pixbuf.new_from_resource(
                "/org/readmachine/ocrd-browser/icons/icon.png"))
        self.view_manager = ViewManager(self, self.view_container)
        self.current_page_id: Optional[str] = None
        # noinspection PyTypeChecker
        self.document = Document.create(emitter=self.emit)

        self.actions = ActionRegistry(for_widget=self)
        self.actions.create('close')
        self.actions.create('goto_first')
        self.actions.create('go_back')
        self.actions.create('go_forward')
        self.actions.create('goto_last')
        self.actions.create('page_remove')
        self.actions.create('page_properties')
        self.actions.create('close_view', param_type=GLib.VariantType("s"))
        self.actions.create('split_view', param_type=GLib.VariantType("(ssb)"))
        self.actions.create('create_view', param_type=GLib.VariantType("s"))
        self.actions.create('replace_view',
                            param_type=GLib.VariantType("(ss)"))
        self.actions.create('toggle_edit_mode', state=GLib.Variant('b', False))
        self.actions.create('save')
        self.actions.create('save_as')

        self.connect('delete-event', self.on_delete_event)

        self.page_list = PagePreviewList(self.document)
        self.page_list_scroller.add(self.page_list)
        self.page_list.connect('page_activated', self.on_page_activated)
        self.page_list.connect('pages_selected', self.on_pages_selected)

        for id_, view in self.view_registry.get_view_options().items():
            menu_item = Gtk.ModelButton(visible=True,
                                        centered=False,
                                        halign=Gtk.Align.FILL,
                                        label=view,
                                        hexpand=True)
            menu_item.set_detailed_action_name(
                'win.create_view("{}")'.format(id_))
            self.view_menu_box.pack_start(menu_item, True, True, 0)

        self.view_manager.set_root_view(ViewPage)
        # self.view_manager.split(None, ViewPage, False)

        self.update_ui()
Exemplo n.º 2
0
class MainWindow(Gtk.ApplicationWindow):
    __gtype_name__ = "MainWindow"

    header_bar: Gtk.HeaderBar = Gtk.Template.Child()
    page_list_scroller: Gtk.ScrolledWindow = Gtk.Template.Child()
    panes: Gtk.Paned = Gtk.Template.Child()
    current_page_label: Gtk.Label = Gtk.Template.Child()
    view_container: Gtk.Box = Gtk.Template.Child()
    view_menu_box: Gtk.Box = Gtk.Template.Child()

    def __init__(self, **kwargs: Any):
        Gtk.ApplicationWindow.__init__(self, **kwargs)
        # noinspection PyCallByClass,PyArgumentList
        self.set_icon(
            GdkPixbuf.Pixbuf.new_from_resource(
                "/org/readmachine/ocrd-browser/icons/icon.png"))
        self.view_manager = ViewManager(self, self.view_container)
        self.current_page_id: Optional[str] = None
        # noinspection PyTypeChecker
        self.document = Document.create(emitter=self.emit)

        self.actions = ActionRegistry(for_widget=self)
        self.actions.create('close')
        self.actions.create('goto_first')
        self.actions.create('go_back')
        self.actions.create('go_forward')
        self.actions.create('goto_last')
        self.actions.create('page_remove')
        self.actions.create('page_properties')
        self.actions.create('close_view', param_type=GLib.VariantType("s"))
        self.actions.create('split_view', param_type=GLib.VariantType("(ssb)"))
        self.actions.create('create_view', param_type=GLib.VariantType("s"))
        self.actions.create('replace_view',
                            param_type=GLib.VariantType("(ss)"))
        self.actions.create('toggle_edit_mode', state=GLib.Variant('b', False))
        self.actions.create('save')
        self.actions.create('save_as')

        self.connect('delete-event', self.on_delete_event)

        self.page_list = PagePreviewList(self.document)
        self.page_list_scroller.add(self.page_list)
        self.page_list.connect('page_activated', self.on_page_activated)
        self.page_list.connect('pages_selected', self.on_pages_selected)

        for id_, view in self.view_registry.get_view_options().items():
            menu_item = Gtk.ModelButton(visible=True,
                                        centered=False,
                                        halign=Gtk.Align.FILL,
                                        label=view,
                                        hexpand=True)
            menu_item.set_detailed_action_name(
                'win.create_view("{}")'.format(id_))
            self.view_menu_box.pack_start(menu_item, True, True, 0)

        self.view_manager.set_root_view(ViewPage)
        # self.view_manager.split(None, ViewPage, False)

        self.update_ui()

    def on_page_remove(self, _a: Gio.SimpleAction, _p: None) -> None:
        for page_id in self.page_list.get_selected_ids():
            self.document.delete_page(page_id)

    def on_page_properties(self, _a: Gio.SimpleAction, _p: None) -> None:
        pass

    @Gtk.Template.Callback()
    def on_recent_menu_item_activated(
            self, recent_chooser: Gtk.RecentChooserMenu) -> None:
        app = self.get_application()
        item: Gtk.RecentInfo = recent_chooser.get_current_item()
        app.open_in_window(item.get_uri(), window=self)

    def open(self, uri: str) -> None:
        self.set_title('Loading')
        self.header_bar.set_title('Loading ...')
        self.header_bar.set_subtitle(uri)
        self.update_ui()
        # Give GTK some break to show the Loading message
        GLib.timeout_add(50, self._open, uri)

    def _open(self, uri: str) -> None:
        # noinspection PyTypeChecker
        self.document = Document.load(uri, emitter=self.emit)
        self.page_list.set_document(self.document)

        self.view_manager.set_document(self.document)
        self.update_ui()

        if len(self.document.page_ids):
            self.on_page_activated(None, self.document.page_ids[0])

    @property
    def view_registry(self) -> ViewRegistry:
        return cast(MainWindow, self.get_application()).view_registry

    def on_page_activated(self, _sender: Optional[Gtk.Widget],
                          page_id: str) -> None:
        if self.current_page_id != page_id:
            self.current_page_id = page_id
            self.emit('page_activated', page_id)

    @GObject.Signal(arg_types=[str])
    def page_activated(self, page_id: str) -> None:
        index = self.document.page_ids.index(page_id)
        self.current_page_label.set_text('{}/{}'.format(
            index + 1, len(self.document.page_ids)))
        self.update_ui()
        pass

    def on_pages_selected(self, _sender: Optional[Gtk.Widget],
                          page_ids: List[str]) -> None:
        self.emit('pages_selected', page_ids)

    @GObject.Signal(arg_types=[object])
    def pages_selected(self, page_ids: List[str]) -> None:
        pass

    @GObject.Signal(arg_types=[str, object])
    def document_changed(self, subtype: str, page_ids: List[str]) -> None:
        self.page_list.document_changed(subtype, page_ids)
        self.update_ui()

    @GObject.Signal(arg_types=[object])
    def document_saved(self, _saved: Document) -> None:
        self.update_ui()

    @GObject.Signal(arg_types=[float, object])
    def document_saving(self, progress: float,
                        file: Optional[OcrdFile]) -> None:
        pass

    def update_ui(self) -> None:
        title = self.document.title + (' *' if self.document.modified else '')
        self.set_title(title)
        self.header_bar.set_title(title)
        self.header_bar.set_subtitle(self.document.original_url)

        can_go_back = False
        can_go_forward = False
        if self.current_page_id and self.current_page_id in self.document.page_ids:
            index = self.document.page_ids.index(self.current_page_id)
            last_page = len(self.document.page_ids) - 1
            can_go_back = index > 0
            can_go_forward = index < last_page

        self.actions['goto_first'].set_enabled(can_go_back)
        self.actions['go_back'].set_enabled(can_go_back)
        self.actions['go_forward'].set_enabled(can_go_forward)
        self.actions['goto_last'].set_enabled(can_go_forward)
        self.actions['page_remove'].set_enabled(self.document.editable)
        # noinspection PyCallByClass,PyArgumentList
        self.actions['toggle_edit_mode'].set_state(
            GLib.Variant.new_boolean(self.document.editable))
        self.actions['save'].set_enabled(self.document.modified)
        self.view_manager.update_ui()

    def close_confirm(self) -> bool:
        if self.document.modified:
            # Do you wanna save the changes?
            d = SaveChangesDialog(document=self.document,
                                  transient_for=self,
                                  modal=True)
            save_changes = d.run()
            d.destroy()

            if save_changes == Gtk.ResponseType.NO:
                return True
            elif save_changes == Gtk.ResponseType.CANCEL:
                return False
            elif save_changes == Gtk.ResponseType.YES:
                return self.on_save()
            return False
        else:
            return True

    def on_close(self, _a: Gio.SimpleAction = None, _p: None = None) -> None:
        if self.close_confirm():
            self.destroy()

    def on_delete_event(self, _window: 'MainWindow',
                        _event: Gdk.Event) -> bool:
        return not self.close_confirm()

    def on_goto_first(self,
                      _a: Gio.SimpleAction = None,
                      _p: None = None) -> None:
        self.page_list.goto_index(0)

    def on_go_forward(self,
                      _a: Gio.SimpleAction = None,
                      _p: None = None) -> None:
        self.page_list.skip(1)

    def on_go_back(self, _a: Gio.SimpleAction = None, _p: None = None) -> None:
        self.page_list.skip(-1)

    def on_goto_last(self,
                     _a: Gio.SimpleAction = None,
                     _p: None = None) -> None:
        self.page_list.goto_index(-1)

    def on_create_view(self, _a: Gio.SimpleAction,
                       selected_view_id: GLib.Variant) -> None:
        view_class = self.view_registry.get_view(selected_view_id.get_string())
        self.view_manager.add(view_class)

    def on_replace_view(self, _a: Gio.SimpleAction,
                        arguments: GLib.Variant) -> None:
        (replace_view, new_view_name) = arguments
        new_view_type = self.view_registry.get_view(new_view_name)
        self.view_manager.replace(replace_view, new_view_type)

    def on_close_view(self, _action: Gio.SimpleAction,
                      view_name: GLib.Variant) -> None:
        try:
            self.view_manager.close(view_name.get_string())
        except ValueError:
            # Tried to remove last view
            pass

    def on_split_view(self, _action: Gio.SimpleAction,
                      arguments: GLib.Variant) -> None:
        (split_view, new_view_name, horizontal) = arguments
        new_view_type = self.view_registry.get_view(new_view_name)
        self.view_manager.split(split_view, new_view_type, horizontal)

    def on_save(self, _a: Gio.SimpleAction = None, _p: None = None) -> bool:
        if self.document.original_url:
            return self.save()
        else:
            return self.save_as()

    def on_save_as(self, _a: Gio.SimpleAction = None, _p: None = None) -> None:
        self.save_as()

    def save(self) -> bool:
        self.document.save()
        self.update_ui()
        return True

    def save_as(self) -> bool:
        save_dialog = SaveDialog(application=self.get_application(),
                                 transient_for=self,
                                 modal=True)
        if self.document.original_url:
            save_dialog.set_filename(self.document.original_url)
        else:
            save_dialog.set_current_name('mets.xml')
        response = save_dialog.run()
        should_save = bool(response == Gtk.ResponseType.OK)
        if should_save:
            self.document.save_as(save_dialog.get_uri())
        save_dialog.destroy()
        self.update_ui()
        return should_save

    def on_toggle_edit_mode(self,
                            _a: Gio.SimpleAction = None,
                            _p: None = None) -> None:
        self.document.editable = not self.document.editable
        self.update_ui()
Exemplo n.º 3
0
class OcrdBrowserApplication(Gtk.Application):
    # TODO: Parse arguments (with Gtk or click) to open certain views by mets+page_id+view(view_configuration_dict) and deep filename e.g.
    # OCR-D-OCR-TESS-frk-SEG-LINE-tesseract-ocropy-DEWARP/OCR-D-OCR-TESS-frk-SEG-LINE-tesseract-ocropy-DEWARP_0001.xml ->
    # file_grp => OCR-D-OCR-TESS-frk-SEG-LINE-tesseract-ocropy-DEWARP /     <mets:fileGrp USE="OCR-D-OCR-TESS-frk-SEG-LINE-tesseract-ocropy-DEWARP"><mets:file MIMETYPE="application/vnd.prima.page+xml" ID="OCR-D-OCR-TESS-frk-SEG-LINE-tesseract-ocropy-DEWARP_0001"><mets:FLocat LOCTYPE="OTHER" OTHERLOCTYPE="FILE" xlink:href="OCR-D-OCR-TESS-frk-SEG-LINE-tesseract-ocropy-DEWARP/OCR-D-OCR-TESS-frk-SEG-LINE-tesseract-ocropy-DEWARP_0001.xml"/></mets:file>
    # mimetype => application/vnd.prima.page+xml
    # FILEID => OCR-D-OCR-TESS-frk-SEG-LINE-tesseract-ocropy-DEWARP_0001 /  <mets:fptr FILEID="OCR-D-OCR-TESS-frk-SEG-LINE-tesseract-ocropy-DEWARP_0001"/>
    # page.id => PHYS_0017 / <mets:div TYPE="page" ID="PHYS_0017">
    # mets.xml + page.id + view_by_mimetype(mimetype)(file_grp = (file_grp,mimetype))
    # TODO: Test application startup for all kinds of mets.xml (not necessarily OCR-D mets.xml) and views without crashes
    def __init__(self) -> None:
        Gtk.Application.__init__(self,
                                 application_id='org.readmachine.ocrd-browser',
                                 flags=Gio.ApplicationFlags.HANDLES_OPEN)
        self.actions = ActionRegistry(for_widget=self)
        self.view_registry = ViewRegistry.create_from_entry_points()

    def do_startup(self) -> None:
        Gtk.Application.do_startup(self)
        self.actions.create('new')
        self.actions.create('open')
        self.actions.create('about')
        self.actions.create('quit')

        self.set_accels_for_action('view.zoom_by(1)', ['<Ctrl>plus'])
        self.set_accels_for_action('view.zoom_by(-1)', ['<Ctrl>minus'])
        self.set_accels_for_action('view.zoom_to::original', ['<Ctrl>0'])
        self.set_accels_for_action('view.zoom_to::width', ['<Ctrl>numbersign'])
        self.set_accels_for_action('view.zoom_to::page',
                                   ['<Ctrl><Alt>numbersign'])

        for entry_point in pkg_resources.iter_entry_points('ocrd_browser_ext'):
            (entry_point.load())(self)

        self.load_css()

    def load_css(self) -> None:
        css = Gtk.CssProvider()
        css.load_from_resource('/org/readmachine/ocrd-browser/css/theme.css')
        # noinspection PyArgumentList
        Gtk.StyleContext().add_provider_for_screen(
            Gdk.Screen.get_default(), css, Gtk.STYLE_PROVIDER_PRIORITY_USER)
        # css = Gtk.CssProvider()
        # css.load_from_path('/home/jk/PycharmProjects/ocrd-browser/gresources/css/test.css')
        # Gtk.StyleContext().add_provider_for_screen(Gdk.Screen.get_default(), css, Gtk.STYLE_PROVIDER_PRIORITY_USER)

    def do_activate(self) -> None:

        win = self.get_active_window()
        if not win:
            win = MainWindow(application=self)
        win.present()

    def on_about(self, _action: Gio.SimpleAction, _param: str = None) -> None:
        about_dialog = AboutDialog(application=self,
                                   transient_for=self.get_active_window(),
                                   modal=True)
        about_dialog.present()

    def on_quit(self, _action: Gio.SimpleAction, _param: str = None) -> None:
        open_windows: int = 0
        window: MainWindow
        for window in self.get_windows():
            if isinstance(window, MainWindow) and window.close_confirm(
            ):  # type: ignore[unreachable]
                window.destroy()
            else:
                open_windows += 1
        if open_windows == 0:
            self.quit()

    def on_open(self, _action: Gio.SimpleAction, _param: str = None) -> None:
        open_dialog = OpenDialog(application=self,
                                 transient_for=self.get_active_window(),
                                 modal=True)
        response = open_dialog.run()
        if response == Gtk.ResponseType.OK:
            self.open_in_window(open_dialog.get_uri(),
                                window=open_dialog.get_transient_for())
        open_dialog.destroy()

    def on_new(self, _action: Gio.SimpleAction, _param: str = None) -> None:
        win = MainWindow(application=self)
        win.present()

    def do_open(self, files: List[Gio.File], file_count: int,
                hint: str) -> int:
        for file in files:
            self.open_in_window(file.get_uri(), window=None)
        return 0

    def open_in_window(self, uri: str, window: MainWindow = None) -> None:
        if not window or not window.document.empty:
            window = MainWindow(application=self)
        window.present()
        GLib.timeout_add(10, window.open, uri)
Exemplo n.º 4
0
 def __init__(self) -> None:
     Gtk.Application.__init__(self,
                              application_id='org.readmachine.ocrd-browser',
                              flags=Gio.ApplicationFlags.HANDLES_OPEN)
     self.actions = ActionRegistry(for_widget=self)
     self.view_registry = ViewRegistry.create_from_entry_points()
Exemplo n.º 5
0
class OcrdBrowserApplication(Gtk.Application):
    def __init__(self) -> None:
        Gtk.Application.__init__(self, application_id='org.readmachine.ocrd-browser',
                                 flags=Gio.ApplicationFlags.HANDLES_OPEN)
        self.actions = ActionRegistry(for_widget=self)
        self.view_registry = ViewRegistry.create_from_entry_points()

    def do_startup(self) -> None:
        Gtk.Application.do_startup(self)
        self.actions.create('new')
        self.actions.create('open')
        self.actions.create('about')
        self.actions.create('quit')
        for entry_point in pkg_resources.iter_entry_points('ocrd_browser_ext'):
            (entry_point.load())(self)

        self.load_css()

    def load_css(self) -> None:
        css = Gtk.CssProvider()
        css.load_from_resource('/org/readmachine/ocrd-browser/css/theme.css')
        Gtk.StyleContext().add_provider_for_screen(Gdk.Screen.get_default(), css, Gtk.STYLE_PROVIDER_PRIORITY_USER)
        # css = Gtk.CssProvider()
        # css.load_from_path('/home/jk/PycharmProjects/ocrd-browser/gresources/css/test.css')
        # Gtk.StyleContext().add_provider_for_screen(Gdk.Screen.get_default(), css, Gtk.STYLE_PROVIDER_PRIORITY_USER)

    def do_activate(self) -> None:

        win = self.get_active_window()
        if not win:
            win = MainWindow(application=self)
        win.present()

    def on_about(self, _action: Gio.SimpleAction, _param: str = None) -> None:
        about_dialog = AboutDialog(application=self, transient_for=self.get_active_window(), modal=True)
        about_dialog.present()

    def on_quit(self, _action: Gio.SimpleAction, _param: str = None) -> None:
        open_windows: int = 0
        window: MainWindow
        for window in self.get_windows():
            if isinstance(window, MainWindow) and window.close_confirm():  # type: ignore[unreachable]
                window.destroy()
            else:
                open_windows += 1
        if open_windows == 0:
            self.quit()

    def on_open(self, _action: Gio.SimpleAction, _param: str = None) -> None:
        open_dialog = OpenDialog(application=self, transient_for=self.get_active_window(), modal=True)
        response = open_dialog.run()
        if response == Gtk.ResponseType.OK:
            self.open_in_window(open_dialog.get_uri(), window=open_dialog.get_transient_for())
        open_dialog.destroy()

    def on_new(self, _action: Gio.SimpleAction, _param: str = None) -> None:
        win = MainWindow(application=self)
        win.present()

    def do_open(self, files: List[Gio.File], file_count: int, hint: str) -> int:
        for file in files:
            self.open_in_window(file.get_uri(), window=None)
        return 0

    def open_in_window(self, uri: str, window: MainWindow = None) -> None:
        if not window or not window.document.empty:
            window = MainWindow(application=self)
        window.present()
        GLib.timeout_add(10, window.open, uri)