PDF-Embanner/pdfembannersrc/cat.py

258 lines
11 KiB
Python
Raw Permalink Normal View History

2018-05-18 06:49:19 +00:00
# -*-coding:utf-8 -*
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
from pdfembannersrc.fich import Fich
from pdfembannersrc import subwindows
import logging
import PyPDF2
logger = logging.getLogger()
class Interface(tk.Toplevel):
"""
Main window
"""
def __init__(self, parent, **kwargs):
tk.Toplevel.__init__(self, parent)
self.transient(parent)
self.grab_set()
self.title("PDF Embanner : concatenation")
self.geometry("800x400")
self.protocol("WM_DELETE_WINDOW", self.close)
self.bind("<Escape>", self.close)
self.bind("<Control-o>", self.open)
self.bind("<Control-s>", self.saveas)
self.bind("<Control-m>", self.editmetadata)
self.bind("<Control-Return>", self.do)
self.lfiles = []
self.save_file = None
self.output_produced=False
self.metadata = {'/Title': '',
'/Author': '',
'/Subject': '',
'/Creator': 'PDF Embanner'}
self.f = tk.Frame(self, width=768, height=576, **kwargs)
self.f.pack(fill=tk.BOTH)
# Création de nos widgets
self.f.columnconfigure(2, weight=1)
self.f.rowconfigure(1, weight=1)
tk.Button(self.f, text="Open", command=self.open).grid(row=0, column=0)
tk.Button(self.f, text="Delete all", command=self.delall).grid(row=0, column=1)
vsb = tk.Scrollbar(self.f, orient=tk.VERTICAL)
vsb.grid(row=1, column=5, sticky=tk.N+tk.S)
self.c = tk.Canvas(self.f,yscrollcommand=vsb.set)
self.c.grid(row=1, column=0, columnspan=5, sticky="news")
vsb.config(command=self.c.yview)
self.frame_files = tk.Frame(self.c)
self.c.create_window(0, 0, window=self.frame_files, anchor=tk.NW)
self.frame_files.update_idletasks()
self.c.config(scrollregion=self.c.bbox("all"))
self.frame_files.columnconfigure(4, weight=1)
tk.Button(self.f, text="Save as", command=self.saveas).grid(row=2, column=0)
self.save_label = tk.Label(self.f, text="-" if self.save_file is None else self.save_file)
self.save_label.grid(row=2, column=1, columnspan=2, sticky=tk.W)
tk.Button(self.f, text="Metadata", command=self.editmetadata).grid(row=2, column=4)
tk.Button(self.f, text="Close", command=self.close).grid(row=3, column=3)
tk.Button(self.f, text="Generate PDF", fg="blue", command=self.do).grid(row=3, column=4)
self.message = tk.Label(self.f, text="Welcome !")
self.message.grid(row=4, column=0, columnspan=5, sticky=tk.W)
def open(self, *args):
"""
Ouvrir un fichier
"""
self.message["text"] = "Open..."
ftypes = [('PDF files (Portable Document Format)', '*.pdf'), ('All files', '*')]
lfl = filedialog.askopenfilenames(filetypes = ftypes)
if len(lfl) >0:
for fl in lfl :
self.message["text"] = "Opening {}".format(fl)
try:
flo = Fich(fl)
i = len(self.lfiles)
self.lfiles.append(flo)
self.message["text"] = "Opened {}".format(flo.name)
logger.info("Concatenate : Opened {}".format(fl))
flo.add_widgets(self.frame_files, self, i)
self.frame_files.update_idletasks()
self.c.config(scrollregion=self.c.bbox("all"))
except IOError:
self.message["text"] = "Failed to open {}".format(fl)
logger.warning("Concatenate : Error while opening {}".format(fl))
else:
self.message["text"] = "Nothing to open !"
logger.info("Concatenate : Asked for opening but nothing to open")
def delall(self):
"""
Delete all opened files
"""
if messagebox.askyesno("Delete all", "Are you sure you want to delete all ?"):
for e in self.lfiles:
e.destroy_widgets()
self.lfiles = []
self.message["text"] = "Everything deleted..."
def do(self, *args):
"""
do concatenation of PDFs with correct options !
"""
if(self.save_file is None):
messagebox.showwarning(title="PDF Output", message="Please define the 'Save As' path before !")
else:
self.message["text"] = "Generating PDF..."
nmax=0
for elem in self.lfiles:
nmax+=elem.npages
progress = subwindows.Progress(self, nmax, "Producing PDF {}".format(self.save_file))
output = PyPDF2.PdfFileWriter()
output.addMetadata(self.metadata)
in_f_list = []
currentf=''
try:
for elem in self.lfiles:
currentf=elem.path
in_f = open(elem.path, "rb")
in_f_list.append(in_f)
logger.debug("Concatenate : Processing {}".format(elem.path))
inpdf = PyPDF2.PdfFileReader(in_f)
progress.message["text"] = elem.path
if(elem.use is None):
# All is used
for i in range(elem.npages):
output.addPage(inpdf.getPage(i))
progress.next()
logger.debug("Concatenate : All pages concatenated")
else:
# variables used, order are read. Possible crop or rotation
for i in elem.order:
if(elem.use[i]):
if(i>=elem.npages): # It is a blank page
refpage = inpdf.getPage(0)
refbox = refpage.mediaBox
larg = abs(refbox.upperRight[0]-refbox.upperLeft[0])
haut = abs(refbox.lowerLeft[1]-refbox.upperLeft[1])
if(elem.crop is not None):
larg = larg * (elem.crop[1][0]-elem.crop[0][0])
haut = haut * (elem.crop[1][1]-elem.crop[0][1])
if(elem.rotate==1 or elem.rotate==3):
output.addBlankPage(width=haut, height=larg)
else:
output.addBlankPage(width=larg, height=haut)
else: # Get correspondig page of pdf
page = inpdf.getPage(i)
if(elem.crop is not None):
xmax = page.mediaBox.getUpperRight_x()
ymax = page.mediaBox.getUpperRight_y()
uR = (elem.crop[1][0]*float(xmax), elem.crop[1][1]*float(ymax))
lL = (elem.crop[0][0]*float(xmax), elem.crop[0][1]*float(ymax))
page.cropBox.lowerLeft = lL
page.cropBox.upperRight = uR
if(elem.rotate is not None):
if(elem.rotate==1):
page.rotateClockwise(270)
elif(elem.rotate==2):
page.rotateClockwise(180)
elif(elem.rotate==3):
page.rotateClockwise(90)
output.addPage(page)
progress.next()
logger.debug("Concatenate : Relevant pages concatenated")
currentf=self.save_file
progress.message["text"] = "Saving in {}".format(currentf)
with open(self.save_file, "wb") as out_f:
logger.debug("Concatenate : Writing into file : file open")
output.write(out_f)
logger.debug("Concatenate : Writing into file : done")
self.message["text"] = "Done"
self.output_produced=True
except IOError as e:
logger.warn("Concatenate : Could not open one of the files :: {} {} {}".format(currentf, e.errno, e.strerror))
messagebox.showerror(title="Error",
message="IO Error occured :\nImpossible to open one of the files ({})\nNo output produced!".format(currentf))
self.message["text"] = "An error occured!"
except Exception as e:
logger.warn("Concatenate : Unknown error occured during PDF production. {}".format(str(e)))
messagebox.showerror(title="Error",
message="An Error occured :\n{}\nNo output produced!".format(e))
self.message["text"] = "An error occured!"
finally:
for f in in_f_list:
f.close()
progress.close()
def close(self, *args):
if(self.output_produced or messagebox.askyesno("Quit", "Are you sure you want to quit ?")):
logger.debug("Concatenate : Quit")
self.destroy()
def saveas(self, *args):
fsas = filedialog.asksaveasfilename()
if fsas != '':
self.save_file = fsas
self.save_label["text"] = fsas
def delete(self, ident):
i=0
for i in range(len(self.lfiles)):
if(ident==self.lfiles[i].id):
break
elem = self.lfiles[i]
elem.destroy_widgets()
del self.lfiles[i]
for j in range(i,len(self.lfiles)):
self.lfiles[j].unset_i_widgets()
self.lfiles[j].set_i_widgets(j)
logger.debug("Concatenate : Delete {}".format(i))
def up(self, ident):
if(not self.lfiles[0].id==ident):
for i in range(1, len(self.lfiles)):
if(ident==self.lfiles[i].id):
break
self.lfiles[i-1].unset_i_widgets()
self.lfiles[i].unset_i_widgets()
obj1 = self.lfiles[i]
self.lfiles[i] = self.lfiles[i-1]
self.lfiles[i-1] = obj1
self.lfiles[i].set_i_widgets(i)
self.lfiles[i-1].set_i_widgets(i-1)
logger.debug("Concatenate : Up {}".format(i))
def down(self, ident):
if(not self.lfiles[-1].id==ident):
for i in range(0, len(self.lfiles)-1):
if(ident==self.lfiles[i].id):
break
self.lfiles[i].unset_i_widgets()
self.lfiles[i+1].unset_i_widgets()
obj1 = self.lfiles[i+1]
self.lfiles[i+1] = self.lfiles[i]
self.lfiles[i] = obj1
self.lfiles[i].set_i_widgets(i)
self.lfiles[i+1].set_i_widgets(i+1)
logger.debug("Concatenate : Down {}".format(i))
def editmetadata(self, *args):
interface3 = subwindows.Metadata(self)
logger.debug("Concatenate : Output metadata set")
interface3.mainloop()
interface3.destroy()
logger.debug("Concatenate : End output metadata set with value {}".format(self.metadata))