import sys import traceback from typing import Dict, List, Optional, Sequence, Tuple, TypeAlias import gi gi.require_version("Gtk", "3.0") from gi.repository import GLib, Gio, Gtk, GObject gi.require_foreign("cairo") import cairo import fitz TEST_FILENAME = "/home/luna/Documents/Resources/Praca Licencjacka/sources/2018_Torres-Benitez_Metabolomic analysis Parmotrema.pdf" Coords: TypeAlias = Tuple[float, float] class Selection: def __init__(self, bounds: Tuple[Coords, Coords], columns: Optional[Sequence[float]] = None): self.bounds = bounds self.columns = columns class Document: def __init__(self, filename: str): self.filename = filename self.document = fitz.Document(filename) self.selections: Dict[int, List[Selection]] = {} class State(): pass class PdfPage(Gtk.DrawingArea): def __init__(self, page, *args, **kwargs): super().__init__(*args, **kwargs) self.page: fitz.Page = page pix = self.page.get_pixmap(dpi=300) # type: ignore self.set_size_request(pix.width, pix.height) self.set_app_paintable(True) # type: ignore self.connect("draw", self.on_draw, {}) def on_draw(self, widget, cr: cairo.Context, data: GObject.GPointer): #app: Application = widget.get_window().get_application() # type: ignore width = self.get_allocated_width() height = self.get_allocated_height() sctx = self.get_style_context() Gtk.render_background(sctx, cr, 0, 0, width, height) pix = self.page.get_pixmap(dpi=300) # type: ignore png = pix.tobytes("png") ims = cairo.ImageSurface.create_from_png(png) cr.set_source_surface(ims, 0, 0) cr.paint() cr.set_source_rgba(255, 0, 0) cr.set_line_width(10) cr.move_to(0, 0) cr.line_to(width, height) cr.stroke() @Gtk.Template.from_file("MainWindow.glade") class MainWindow(Gtk.ApplicationWindow): __gtype_name__ = "main_window" open_button: Gtk.Button = Gtk.Template.Child() # type: ignore header_bar: Gtk.HeaderBar = Gtk.Template.Child() # type: ignore main_paned: Gtk.Paned = Gtk.Template.Child() # type: ignore pdf_list_box: Gtk.ListBox = Gtk.Template.Child() # type: ignore pdfFileFilter: Gtk.FileFilter = Gtk.Template.Child() # type: ignore def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.app: Application = self.get_application() # type: ignore assert self.app is not None self.app.connect("notify::document", self.on_document_updated) #self.pdf_list_box.add(PdfPage()) #@Gtk.Template.Callback() #def example_button_released_cb(self, widget: Gtk.Button, **kwargs): # assert self.example_button == widget # print(widget.get_label()) # widget.set_label("woah") @Gtk.Template.Callback() def on_open_button_clicked(self, widget, *args, **kwargs): dialog = Gtk.FileChooserDialog( title="Choose PDF File to open", transient_for=self, # equivalent to parent= action=Gtk.FileChooserAction.OPEN, filter=self.pdfFileFilter, modal=True, ) dialog.add_button("Cancel", Gtk.ResponseType.CANCEL) dialog.add_button("Open", Gtk.ResponseType.ACCEPT) response = dialog.run() # type: ignore if response == Gtk.ResponseType.ACCEPT: filename: str = dialog.get_filename() # type: ignore try: self.app.set_property("document", Document(filename)) except Exception as e: message_dialog = Gtk.MessageDialog( title="An error has occured.", transient_for=self, modal=True, message_type=Gtk.MessageType.ERROR, text=repr(e), secondary_text=traceback.format_exc(), buttons=Gtk.ButtonsType.OK, ) message_dialog.run() # type: ignore message_dialog.destroy() dialog.destroy() # Note: this won't run unless a new document object is put into place # editing an existing one won't trigger it def on_document_updated(self, recvobj, gparamstring): document: Document = self.app.get_property("document") self.header_bar.set_title(document.filename.split("/")[-1]) # type: ignore self.header_bar.set_subtitle(document.filename) # type: ignore for i in document.document.pages(): # type: ignore page = PdfPage(i) box = Gtk.Box() box.pack_start(page, True, True, 20) self.pdf_list_box.add(box) # type: ignore @Gtk.Template.Callback() def on_open_button_small_clicked(self, widget, **kwargs): pass class Application(Gtk.Application): document = GObject.Property(type=GObject.TYPE_PYOBJECT, flags=GObject.ParamFlags.READWRITE) def __init__(self, *args, **kwargs): super().__init__( *args, application_id="zone.lunareclipse.pdf_table_extractor", flags=Gio.ApplicationFlags.FLAGS_NONE, #flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE, # TODO **kwargs ) self.window = None def do_activate(self): self.window = self.window or MainWindow(application=self) self.window.show_all() # type: ignore if __name__ == "__main__": app = Application() app.run(sys.argv)