258 lines
11 KiB
Python
258 lines
11 KiB
Python
# -*-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))
|
|
|