# -*-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("", self.close) self.bind("", self.open) self.bind("", self.saveas) self.bind("", self.editmetadata) self.bind("", 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))