Files
pdf-reader-demo/reader.py
2024-11-05 09:50:49 +02:00

198 lines
8.4 KiB
Python

#!/usr/bin/env python3
# importing everything from tkinter
from tkinter import *
# importing ttk for styling widgets from tkinter
from tkinter import ttk
# importing filedialog from tkinter
from tkinter import filedialog as fd
# importing os module
import os
from pdfviewer import PDFViewer
class PDFReader:
# initializing the __init__ / special method
def __init__(self, master):
# path for the pdf doc
self.path = None
# state of the pdf doc, open or closed
self.fileisopen = None
# author of the pdf doc
self.author = None
# name for the pdf doc
self.name = None
# the current page for the pdf
self.current_page = 0
# total number of pages for the pdf doc
self.numPages = None
# creating the window
self.master = master
# gives title to the main window
self.master.resizable(True, True)
self.master.title('PDF Reader')
# gives dimensions to main window
# self.master.geometry('580x520+440+180')
# this disables the minimize/maximize button on the main window
# self.master.resizable(width = 0, height = 0)
# loads the icon and adds it to the main window
# self.master.iconbitmap(self.master, 'pdf_file_icon.ico')
# creating the menu
self.menu = Menu(self.master)
# adding it to the main window
self.master.config(menu=self.menu)
# creating a sub menu
self.filemenu = Menu(self.menu)
# giving the sub menu a label
self.menu.add_cascade(label="File", menu=self.filemenu)
# adding a two buttons to the sub menus
self.filemenu.add_command(label="Open File", command=self.open_file)
self.filemenu.add_command(label="Exit", command=self.master.destroy)
# creating the top frame
self.top_frame = ttk.Frame(self.master, width=580, height=460)
# placing the frame using inside main window using grid()
self.top_frame.grid(row=0, column=0)
# the frame will not propagate
self.top_frame.grid_propagate(False)
# creating the bottom frame
self.bottom_frame = ttk.Frame(self.master, width=580, height=50)
# placing the frame using inside main window using grid()
self.bottom_frame.grid(row=1, column=0)
# the frame will not propagate
self.bottom_frame.grid_propagate(False)
# creating a vertical scrollbar
self.scrolly = Scrollbar(self.top_frame, orient=VERTICAL)
# adding the scrollbar
self.scrolly.grid(row=0, column=1, sticky=(N,S))
# creating a horizontal scrollbar
self.scrollx = Scrollbar(self.top_frame, orient=HORIZONTAL)
# adding the scrollbar
self.scrollx.grid(row=1, column=0, sticky=(W, E))
# creating the canvas for display the PDF pages
self.output = Canvas(self.top_frame, bg='#ECE8F3', width=560, height=435)
# inserting both vertical and horizontal scrollbars to the canvas
self.output.configure(yscrollcommand=self.scrolly.set, xscrollcommand=self.scrollx.set)
# adding the canvas
self.output.grid(row=0, column=0)
self.output.rowconfigure(0, weight=1)
self.output.columnconfigure(0, weight=1)
# configuring the horizontal scrollbar to the canvas
self.scrolly.configure(command=self.output.yview)
# configuring the vertical scrollbar to the canvas
self.scrollx.configure(command=self.output.xview)
# loading the button icons
self.uparrow_icon = PhotoImage(file='uparrow.png')
self.downarrow_icon = PhotoImage(file='downarrow.png')
# resizing the icons to fit on buttons
self.uparrow = self.uparrow_icon.subsample(3, 3)
self.downarrow = self.downarrow_icon.subsample(3, 3)
# creating an up button with an icon
self.upbutton = ttk.Button(self.bottom_frame,
image=self.uparrow,
command=self.prev_page)
# adding the button
self.upbutton.grid(row=0, column=1, padx=(270, 5), pady=8)
# creating a down button with an icon
self.downbutton = ttk.Button(self.bottom_frame,
image=self.downarrow,
command=self.next_page)
# adding the button
self.downbutton.grid(row=0, column=3, pady=8)
# label for displaying page numbers
self.page_label = ttk.Label(self.bottom_frame, text='page')
# adding the label
self.page_label.grid(row=0, column=4, padx=5)
self.master.rowconfigure(0, weight=1)
self.master.columnconfigure(0, weight=1)
# self.top_frame.rowconfigure(0, weight=1)
# self.top_frame.columnconfigure(0, weight=1)
self.output.pack(fill="both", expand=True)
self.output.bind("<Configure>", self.on_resize)
# function for opening pdf files
def open_file(self):
# open the file dialog
filepath = fd.askopenfilename(title='Select a PDF file', initialdir=os.getcwd(), filetypes=(('PDF', '*.pdf'), ))
# checking if the file exists
if filepath:
# declaring the path
self.path = filepath
# extracting the pdf file from the path
filename = os.path.basename(self.path)
# passing the path to PDFViewer
self.viewer = PDFViewer(self.path)
# getting data and numPages
data, numPages = self.viewer.get_metadata()
# setting the current page to 0
self.current_page = 0
# checking if numPages exists
if numPages:
# getting the title
self.name = data.get('title', filename[:-4])
# getting the author
self.author = data.get('author', None)
self.numPages = numPages
# setting fileopen to True
self.fileisopen = True
# calling the display_page() function
self.display_page()
# replacing the window title with the PDF document name
self.master.title(self.name)
# the function to display the page
def display_page(self):
# checking if numPages is less than current_page and if current_page is less than
# or equal to 0
if 0 <= self.current_page < self.numPages:
# getting the page using get_page() function from miner
self.img_file = self.viewer.get_page(self.current_page)
# inserting the page image inside the Canvas
self.output.create_image(0, 0, anchor='nw', image=self.img_file)
# the variable to be stringified
self.stringified_current_page = self.current_page + 1
# updating the page label with number of pages
self.page_label['text'] = str(self.stringified_current_page) + ' of ' + str(self.numPages)
# creating a region for inserting the page inside the Canvas
region = self.output.bbox(ALL)
# making the region to be scrollable
self.output.configure(scrollregion=region)
# function for displaying next page
def next_page(self):
# checking if file is open
if self.fileisopen:
# checking if current_page is less than or equal to numPages-1
if self.current_page <= self.numPages - 1:
# updating the page with value 1
self.current_page += 1
# displaying the new page
self.display_page()
def prev_page(self):
# checking if file is open
if self.fileisopen:
# checking if current_page is less than or equal to numPages-1
if self.current_page >= 0:
# updating the page with value 1
self.current_page -= 1
# displaying the new page
self.display_page()
def on_resize(self, event):
# Get the new window dimensions
window_width = root.winfo_width()
window_height = root.winfo_height()
# new_height = event.height
# Update the canvas size
self.output.config(width=window_width, height=window_height)
# creating the root window using Tk() class
root = Tk()
# instantiating/creating object app for class PDFViewer
app = PDFReader(root)
# calling the mainloop to run the app infinitely until user closes it
root.mainloop()