First commit
This commit is contained in:
commit
171db182aa
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
*.pyc
|
||||
*.pdf
|
||||
.*.swp
|
||||
*__pycache__*
|
20
README.md
Normal file
20
README.md
Normal file
@ -0,0 +1,20 @@
|
||||
# PDF Embanner
|
||||
|
||||
## Presentation
|
||||
This is a GUI software designed to manipulate existing pdf. It allows to :
|
||||
* Concatenate several PDF files, changing page order and selecting only relevant pages and adding blank pages
|
||||
* Rotate and/or crop PDF pages
|
||||
* Editting PDF metadata
|
||||
* Watermarking of PDF with other existing pdf or with custom text
|
||||
* Extracting text from PDF
|
||||
* Splitting a single PDF file into a file per page
|
||||
* Encrypting PDF and decrypting if the encryption method is supported by python PyPDF2 package
|
||||
|
||||
## Installation
|
||||
Simply clone or download this repository, and copy it on your computer.
|
||||
On linux systems simply type `./pdfembanner` should work, else you will have to launch pdfembanner with python3 manually.
|
||||
|
||||
You have to have a python 3.5+ installed, and for watermarking with custom text a Latex installation is also necessary. To tell PDF embanner which latex compiler to use, please edit the `pdfembannersrc/compiler.conf`.
|
||||
|
||||
## Licence and credits
|
||||
This software is distributed under GNU/GPL v3 licence, see www.gnu.org/licenses/
|
62
pdfembanner
Executable file
62
pdfembanner
Executable file
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*-coding:utf-8 -*
|
||||
|
||||
import tkinter as tk
|
||||
from pdfembannersrc import choice
|
||||
import logging
|
||||
import argparse
|
||||
|
||||
#TODO :
|
||||
# * Remove Forms
|
||||
|
||||
parser = argparse.ArgumentParser(description="""
|
||||
PDF Embanner
|
||||
Program to manipulate PDFs based on PyPDF2 python library
|
||||
|
||||
use pdfembanner to launch GUI
|
||||
""", formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
parser.add_argument('--verbose', '-v', action='count')
|
||||
args = parser.parse_args()
|
||||
|
||||
# Logger
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
console_handler = logging.StreamHandler()
|
||||
if(args.verbose is not None):
|
||||
if(args.verbose==1):
|
||||
console_handler.setLevel(logging.WARN)
|
||||
elif(args.verbose==2):
|
||||
console_handler.setLevel(logging.INFO)
|
||||
elif(args.verbose>=3):
|
||||
console_handler.setLevel(logging.DEBUG)
|
||||
else:
|
||||
console_handler.setLevel(logging.ERROR)
|
||||
formatter = logging.Formatter('%(levelname)s :: %(message)s')
|
||||
console_handler.setFormatter(formatter)
|
||||
logger.addHandler(console_handler)
|
||||
|
||||
if(args.verbose>=2):
|
||||
logger.info("Logger level set to {}".format("INFO" if args.verbose==2 else "DEBUG"))
|
||||
logger.debug("Launching app")
|
||||
|
||||
|
||||
# Main window
|
||||
fenetre = tk.Tk()
|
||||
fenetre.geometry("+400+200")
|
||||
fenetre.title("PDF Embanner")
|
||||
interface = choice.Choice(fenetre)
|
||||
fenetre.resizable(0,0)
|
||||
fenetre.bind("<Escape>", interface.close)
|
||||
fenetre.bind("1", interface.do1)
|
||||
fenetre.bind("2", interface.do2)
|
||||
fenetre.bind("3", interface.do3)
|
||||
fenetre.bind("4", interface.do4)
|
||||
fenetre.bind("5", interface.do5)
|
||||
fenetre.bind("6", interface.do6)
|
||||
fenetre.bind("7", interface.do7)
|
||||
logger.debug("App launched")
|
||||
|
||||
fenetre.mainloop()
|
||||
logger.debug("App closed")
|
||||
|
0
pdfembannersrc/__init__.py
Normal file
0
pdfembannersrc/__init__.py
Normal file
257
pdfembannersrc/cat.py
Normal file
257
pdfembannersrc/cat.py
Normal file
@ -0,0 +1,257 @@
|
||||
# -*-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))
|
||||
|
91
pdfembannersrc/choice.py
Normal file
91
pdfembannersrc/choice.py
Normal file
@ -0,0 +1,91 @@
|
||||
# -*-coding:utf-8 -*
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import messagebox
|
||||
import logging
|
||||
from pdfembannersrc import cat, help, encrypt, full_split, get_text, watermark
|
||||
logger = logging.getLogger()
|
||||
|
||||
class Choice(tk.Frame):
|
||||
"""
|
||||
Window to chose what to do...
|
||||
"""
|
||||
|
||||
def __init__(self, fenetre, **kwargs):
|
||||
self.parent = fenetre
|
||||
|
||||
tk.Frame.__init__(self, fenetre, **kwargs)
|
||||
self.pack(fill=tk.BOTH)
|
||||
|
||||
# Création de nos widgets
|
||||
crocus = tk.PhotoImage(file='pdfembannersrc/crocus.png')
|
||||
img1 = tk.Label(self, image=crocus)
|
||||
img1.image=crocus
|
||||
img1.grid(row=0, column=0, rowspan=10, sticky=tk.W)
|
||||
pdfem = tk.PhotoImage(file='pdfembannersrc/pdfembanner.png')
|
||||
img2 = tk.Label(self, image=pdfem)
|
||||
img2.image=pdfem
|
||||
img2.grid(row=0, column=1, sticky=tk.W+tk.N)
|
||||
|
||||
self.bouton_open = tk.Button(self, text="1. Concatenate", command=self.do1)
|
||||
self.bouton_open.grid(row=1, column=1, sticky=tk.W+tk.E)
|
||||
self.bouton_open = tk.Button(self, text="2. Watermark", command=self.do2)
|
||||
self.bouton_open.grid(row=2, column=1, sticky=tk.W+tk.E)
|
||||
self.bouton_open = tk.Button(self, text="3. Encryption", command=self.do3)
|
||||
self.bouton_open.grid(row=3, column=1, sticky=tk.W+tk.E)
|
||||
self.bouton_open = tk.Button(self, text="4. Extract text", command=self.do4)
|
||||
self.bouton_open.grid(row=4, column=1, sticky=tk.W+tk.E)
|
||||
self.bouton_open = tk.Button(self, text="5. Full split", command=self.do5)
|
||||
self.bouton_open.grid(row=5, column=1, sticky=tk.W+tk.E)
|
||||
self.bouton_open = tk.Button(self, text="6. Forms", command=self.do6)
|
||||
self.bouton_open.grid(row=6, column=1, sticky=tk.W+tk.E)
|
||||
self.bouton_open = tk.Button(self, text="7. Help", command=self.do7)
|
||||
self.bouton_open.grid(row=7, column=1, sticky=tk.W+tk.E)
|
||||
self.bouton_open = tk.Button(self, text="Close", command=self.quit)
|
||||
self.bouton_open.grid(row=8, column=1, sticky=tk.W+tk.E)
|
||||
|
||||
|
||||
def do1(self, *args):
|
||||
"""
|
||||
Open concatenation interface
|
||||
"""
|
||||
cat.Interface(self.parent)
|
||||
|
||||
def do2(self, *args):
|
||||
"""
|
||||
Open Watermerk interface
|
||||
"""
|
||||
watermark.Interface(self.parent)
|
||||
|
||||
def do3(self, *args):
|
||||
"""
|
||||
Open encryption interface
|
||||
"""
|
||||
encrypt.Interface(self.parent)
|
||||
|
||||
def do4(self, *args):
|
||||
"""
|
||||
Open Text extraction interface
|
||||
"""
|
||||
get_text.Interface(self.parent)
|
||||
|
||||
def do5(self, *args):
|
||||
"""
|
||||
Open Full split interface
|
||||
"""
|
||||
full_split.Interface(self.parent)
|
||||
|
||||
def do6(self, *args):
|
||||
"""
|
||||
Open Forms interface
|
||||
"""
|
||||
messagebox.showwarning(title="Warning", message="Not yet implemented!")
|
||||
|
||||
def do7(self, *args):
|
||||
"""
|
||||
Open help interface
|
||||
"""
|
||||
help.Interface(self.parent)
|
||||
|
||||
def close(self, *args):
|
||||
self.quit()
|
304
pdfembannersrc/editfich.py
Normal file
304
pdfembannersrc/editfich.py
Normal file
@ -0,0 +1,304 @@
|
||||
# -*-coding:utf-8 -*
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import messagebox
|
||||
from tkinter import simpledialog
|
||||
from pdfembannersrc import subwindows
|
||||
import logging
|
||||
logger = logging.getLogger()
|
||||
|
||||
class InterfaceEdit(tk.Toplevel):
|
||||
"""
|
||||
Edition window
|
||||
"""
|
||||
|
||||
def __init__(self, parent, fichobj, **kwargs):
|
||||
tk.Toplevel.__init__(self, parent)
|
||||
self.transient(parent)
|
||||
self.grab_set()
|
||||
self.geometry("800x400")
|
||||
self.bind("<Return>", self.ok)
|
||||
|
||||
self.fich = fichobj
|
||||
|
||||
self.title("Edit {}".format(self.fich.name))
|
||||
|
||||
if(self.fich.use is None):
|
||||
self.fich.use = []
|
||||
if(self.fich.order is None):
|
||||
self.fich.order = []
|
||||
|
||||
self.pages = []
|
||||
|
||||
self.f = tk.Frame(self, width=768, height=576, **kwargs)
|
||||
self.f.pack(fill=tk.BOTH)
|
||||
|
||||
# Création de nos widgets
|
||||
self.f.columnconfigure(7, weight=1)
|
||||
self.f.rowconfigure(3, weight=1)
|
||||
|
||||
info1 = tk.Label(self.f, text="Choose used pages :", fg="white", padx=20, bg="blue")
|
||||
info1.grid(row=0, column=0, columnspan=10, sticky=tk.W)
|
||||
|
||||
tk.Button(self.f, text="Select all", command=self.selectall).grid(row=1, column=0)
|
||||
tk.Button(self.f, text="Unselect all", command=self.deselectall).grid(row=2, column=0)
|
||||
tk.Button(self.f, text="Select range", command=self.selectrange).grid(row=1, column=1)
|
||||
tk.Button(self.f, text="Unselect range", command=self.deselectrange).grid(row=2, column=1)
|
||||
tk.Button(self.f, text="Select pair", command=self.selectpair).grid(row=1, column=2)
|
||||
tk.Button(self.f, text="Unselect pair", command=self.unselectpair).grid(row=2, column=2)
|
||||
tk.Button(self.f, text="Select impair", command=self.selectimpair).grid(row=1, column=3)
|
||||
tk.Button(self.f, text="Unselect impair", command=self.unselectimpair).grid(row=2, column=3)
|
||||
tk.Button(self.f, text="Toggle", command=self.toggle).grid(row=1, column=4)
|
||||
tk.Button(self.f, text="Add blank page", command=self.addblankpage).grid(row=1, column=10)
|
||||
|
||||
vsb = tk.Scrollbar(self.f, orient=tk.VERTICAL)
|
||||
vsb.grid(row=3, column=11, sticky=tk.N+tk.S)
|
||||
self.c = tk.Canvas(self.f, yscrollcommand=vsb.set)
|
||||
self.c.grid(row=3, column=0, columnspan=10, sticky="news")
|
||||
vsb.config(command=self.c.yview)
|
||||
self.frame_pages = tk.Frame(self.c)
|
||||
self.frame_pages.columnconfigure(4, weight=1)
|
||||
|
||||
for e in range(self.fich.npages+self.fich.nblankpages):
|
||||
if(len(self.fich.use)<=e):
|
||||
self.fich.use.append(True)
|
||||
if(len(self.fich.order)<=e):
|
||||
self.fich.order.append(e)
|
||||
page = Page(self, e)
|
||||
self.pages.append(page)
|
||||
page.add_widgets(self.frame_pages)
|
||||
|
||||
self.c.create_window(0, 0, window=self.frame_pages, anchor=tk.NW)
|
||||
self.frame_pages.update_idletasks()
|
||||
self.c.config(scrollregion=self.c.bbox("all"))
|
||||
|
||||
info1 = tk.Label(self.f, text="Options on the whole file :", fg="white", padx=20, bg="blue")
|
||||
info1.grid(row=4, column=0, columnspan=10, sticky=tk.W)
|
||||
|
||||
tk.Button(self.f, text="Rotate", command=self.rotate).grid(row=5, column=0)
|
||||
tk.Button(self.f, text="Crop", command=self.crop).grid(row=5, column=1)
|
||||
|
||||
tk.Button(self.f, text="Ok", command=self.ok).grid(row=6, column=10)
|
||||
|
||||
self.message = tk.Label(self.f, text="Editing {}".format(self.fich.name))
|
||||
self.message.grid(row=7, column=0, columnspan=11, sticky=tk.W)
|
||||
|
||||
|
||||
def ok(self, *args):
|
||||
"""
|
||||
Save and quit
|
||||
"""
|
||||
self.message["text"] = "Done"
|
||||
self.quit()
|
||||
self.destroy()
|
||||
|
||||
def up(self, i):
|
||||
pos = self.fich.order[i]
|
||||
if(pos>0 and pos<self.fich.npages):
|
||||
for toech in range(self.fich.npages):
|
||||
if(self.fich.order[toech]==pos-1):
|
||||
break
|
||||
self.fich.order[i] -= 1
|
||||
self.fich.order[toech] += 1
|
||||
self.pages[i].unset_i_widgets()
|
||||
self.pages[toech].unset_i_widgets()
|
||||
self.pages[i].set_i_widgets(pos-1)
|
||||
self.pages[toech].set_i_widgets(pos)
|
||||
|
||||
def down(self, i):
|
||||
pos = self.fich.order[i]
|
||||
if(pos<self.fich.npages-1):
|
||||
for toech in range(self.fich.npages):
|
||||
if(self.fich.order[toech]==pos+1):
|
||||
break
|
||||
self.fich.order[i] += 1
|
||||
self.fich.order[toech] -= 1
|
||||
self.pages[i].unset_i_widgets()
|
||||
self.pages[toech].unset_i_widgets()
|
||||
self.pages[i].set_i_widgets(pos+1)
|
||||
self.pages[toech].set_i_widgets(pos)
|
||||
|
||||
def selectall(self):
|
||||
for i in range(self.fich.npages):
|
||||
self.fich.use[i] = True
|
||||
self.pages[i].select()
|
||||
|
||||
def deselectall(self):
|
||||
for i in range(self.fich.npages):
|
||||
self.fich.use[i] = False
|
||||
self.pages[i].deselect()
|
||||
|
||||
def selectrange(self):
|
||||
selstr = simpledialog.askstring("Select range", "Range to select (ex 0-2;4):")
|
||||
for e1 in selstr.split(';'):
|
||||
e1 = e1.split('-')
|
||||
if(len(e1)==1 and e1[0].isdigit() and int(e1[0])>0 and int(e1[0])<=len(self.fich.use)):
|
||||
i = int(e1[0])
|
||||
self.fich.use[i-1] = True
|
||||
self.pages[i-1].select()
|
||||
elif(len(e1)==2 and e1[0].isdigit() and e1[1].isdigit()):
|
||||
i = int(e1[0])
|
||||
j = int(e1[1])
|
||||
if(i>0 and i<j and j<=len(self.fich.use)):
|
||||
for k in range(i,j+1):
|
||||
self.fich.use[k-1] = True
|
||||
self.pages[k-1].select()
|
||||
else:
|
||||
messagebox.showwarning(title="Warning", message="Some ranges could not be interpeted, skipped.")
|
||||
logger.info("Concatenate : Select range : Could not interpret : {}".format(e1))
|
||||
else:
|
||||
messagebox.showwarning(title="Warning", message="Some ranges could not be interpeted, skipped.")
|
||||
logger.info("Concatenate : Select range : Could not interpret_ : {}".format(e1))
|
||||
|
||||
def deselectrange(self):
|
||||
selstr = simpledialog.askstring("Select range", "Range to select (ex 0-2;4):")
|
||||
for e1 in selstr.split(';'):
|
||||
e1 = e1.split('-')
|
||||
if(len(e1)==1 and e1[0].isdigit() and int(e1[0])>0 and int(e1[0])<=len(self.fich.use)):
|
||||
i = int(e1[0])
|
||||
self.fich.use[i-1] = False
|
||||
self.pages[i-1].deselect()
|
||||
elif(len(e1)==2 and e1[0].isdigit() and e1[1].isdigit()):
|
||||
i = int(e1[0])
|
||||
j = int(e1[1])
|
||||
if(i>0 and i<j and j<=len(self.fich.use)):
|
||||
for k in range(i,j+1):
|
||||
self.fich.use[k-1] = False
|
||||
self.pages[k-1].deselect()
|
||||
else:
|
||||
messagebox.showwarning(title="Warning", message="Some ranges could not be interpeted, skipped.")
|
||||
logger.info("Concatenate : Select range : Could not interpret : {}".format(e1))
|
||||
else:
|
||||
messagebox.showwarning(title="Warning", message="Some ranges could not be interpeted, skipped.")
|
||||
logger.info("Concatenate : Select range : Could not interpret_ : {}".format(e1))
|
||||
|
||||
def selectpair(self):
|
||||
for i in range(self.fich.npages):
|
||||
if((i+1)%2==0):
|
||||
self.fich.use[i] = True
|
||||
self.pages[i].select()
|
||||
|
||||
def selectimpair(self):
|
||||
for i in range(self.fich.npages):
|
||||
if((i+1)%2==1):
|
||||
self.fich.use[i] = True
|
||||
self.pages[i].select()
|
||||
|
||||
def unselectpair(self):
|
||||
for i in range(self.fich.npages):
|
||||
if((i+1)%2==0):
|
||||
self.fich.use[i] = False
|
||||
self.pages[i].deselect()
|
||||
|
||||
def unselectimpair(self):
|
||||
for i in range(self.fich.npages):
|
||||
if((i+1)%2==1):
|
||||
self.fich.use[i] = False
|
||||
self.pages[i].deselect()
|
||||
|
||||
def toggle(self):
|
||||
for i in range(self.fich.npages):
|
||||
self.pages[i].Wcheck.toggle()
|
||||
self.pages[i].toggle()
|
||||
|
||||
def crop(self):
|
||||
interface = subwindows.SetCrop(self, self.fich)
|
||||
logger.debug("Concatenate : Crop set")
|
||||
interface.mainloop()
|
||||
interface.destroy()
|
||||
logger.debug("Concatenate : End crop set with value {}".format(self.fich.crop))
|
||||
|
||||
def rotate(self):
|
||||
interfaceRotate = subwindows.Rotate(self, self.fich)
|
||||
logger.debug("Rotate {}".format(self.fich.path))
|
||||
interfaceRotate.mainloop()
|
||||
interfaceRotate.destroy()
|
||||
logger.debug("End Rotate {} with value {}".format(self.fich.path, self.fich.rotate))
|
||||
|
||||
def addblankpage(self):
|
||||
values={"nr":0, "after":[]}
|
||||
fen = subwindows.AskBlankPage(self, self.fich, values)
|
||||
fen.mainloop()
|
||||
fen.destroy()
|
||||
if(values["nr"]>0):
|
||||
added=0
|
||||
for e in values["after"]:
|
||||
e = e+added
|
||||
# Decalage vers le bas des pages suivantes
|
||||
for i in range(e,len(self.fich.order)):
|
||||
self.pages[self.fich.order[i]].unset_i_widgets()
|
||||
self.pages[self.fich.order[i]].set_i_widgets(i+1+values["nr"])
|
||||
# Ajout des pages blanches
|
||||
part1 = self.fich.order[:e]
|
||||
part2 = self.fich.order[e:]
|
||||
for i in range(values["nr"]):
|
||||
self.fich.use.append(True)
|
||||
self.fich.nblankpages+=1
|
||||
added+=1
|
||||
self.fich.order.append(self.fich.npages+self.fich.nblankpages-1)
|
||||
page = Page(self, self.fich.npages+self.fich.nblankpages-1)
|
||||
self.pages.append(page)
|
||||
page.add_widgets(self.frame_pages)
|
||||
page.unset_i_widgets()
|
||||
page.set_i_widgets(e+i)
|
||||
part1.append(self.fich.npages+self.fich.nblankpages-1)
|
||||
self.fich.order = part1 + part2
|
||||
self.frame_pages.update_idletasks()
|
||||
self.c.config(scrollregion=self.c.bbox("all"))
|
||||
|
||||
|
||||
class Page:
|
||||
def __init__(self, parent, i):
|
||||
self.num = i
|
||||
self.parent = parent
|
||||
|
||||
self.Wlabel = None
|
||||
self.Wcheck = None
|
||||
self.Wup = None
|
||||
self.Wdown = None
|
||||
|
||||
def add_widgets(self, frame):
|
||||
if self.num>=self.parent.fich.npages:
|
||||
self.Wlabel = tk.Label(frame, text="Blank page")
|
||||
else:
|
||||
self.Wlabel = tk.Label(frame, text="Page {}".format(self.num+1))
|
||||
self.Wnum = tk.Label(frame, text="{}.".format(self.num+1))
|
||||
self.Wup = tk.Button(frame, text="Up", command=lambda: self.parent.up(self.num))
|
||||
self.Wdown = tk.Button(frame, text="Down", command=lambda: self.parent.down(self.num))
|
||||
self.Wcheck = tk.Checkbutton(frame, command=self.toggle)
|
||||
if(self.parent.fich.use[self.num]):
|
||||
self.select()
|
||||
else:
|
||||
self.deselect()
|
||||
self.set_i_widgets(self.parent.fich.order[self.num])
|
||||
|
||||
def set_i_widgets(self, i):
|
||||
self.Wnum["text"] = "{}.".format(i+1)
|
||||
self.Wnum.grid(row=i, column=0, sticky=tk.W)
|
||||
self.Wlabel.grid(row=i, column=4)
|
||||
self.Wcheck.grid(row=i, column=1)
|
||||
self.Wup.grid(row=i, column=2)
|
||||
self.Wdown.grid(row=i, column=3)
|
||||
|
||||
def unset_i_widgets(self):
|
||||
self.Wnum.grid_forget()
|
||||
self.Wlabel.grid_forget()
|
||||
self.Wcheck.grid_forget()
|
||||
self.Wup.grid_forget()
|
||||
self.Wdown.grid_forget()
|
||||
|
||||
def toggle(self):
|
||||
if(self.parent.fich.use[self.num]):
|
||||
self.deselect()
|
||||
self.parent.fich.use[self.num] = False
|
||||
else:
|
||||
self.select()
|
||||
self.parent.fich.use[self.num] = True
|
||||
|
||||
def select(self):
|
||||
self.Wlabel.config(fg="black")
|
||||
self.Wcheck.select()
|
||||
|
||||
def deselect(self):
|
||||
self.Wlabel.config(fg="grey")
|
||||
self.Wcheck.deselect()
|
260
pdfembannersrc/editwmark.py
Normal file
260
pdfembannersrc/editwmark.py
Normal file
@ -0,0 +1,260 @@
|
||||
# -*-coding:utf-8 -*
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import messagebox
|
||||
from tkinter import ttk
|
||||
from pdfembannersrc import strings
|
||||
import logging
|
||||
logger = logging.getLogger()
|
||||
|
||||
class InterfaceEdit(tk.Toplevel):
|
||||
"""
|
||||
Edition for wmark
|
||||
"""
|
||||
|
||||
def __init__(self, parent, wmark, **kwargs):
|
||||
tk.Toplevel.__init__(self, parent)
|
||||
self.transient(parent)
|
||||
self.grab_set()
|
||||
self.geometry("500x300")
|
||||
self.bind("<Return>", self.ok)
|
||||
self.bind("<Escape>", self.close)
|
||||
self.bind('<<ComboboxSelected>>', self.comboselectmaj)
|
||||
|
||||
self.wmark = wmark
|
||||
|
||||
self.name = tk.StringVar()
|
||||
if(self.wmark.name is not None):self.name.set(self.wmark.name)
|
||||
self.position = tk.StringVar()
|
||||
if(self.wmark.position is not None):self.position.set(self.wmark.position)
|
||||
self.userposition = tk.StringVar()
|
||||
if(self.wmark.userposition is not None and self.position.get()==strings.custom):
|
||||
self.userposition.set("{},{}".format(self.wmark.userposition[0],self.wmark.userposition[1]))
|
||||
self.text = tk.StringVar()
|
||||
if(self.wmark.text is not None):self.text.set(self.wmark.text)
|
||||
self.size = tk.StringVar()
|
||||
if(self.wmark.size is not None):self.size.set(self.wmark.size)
|
||||
self.notfirstpage = self.wmark.notfirstpage
|
||||
self.notlastpage = self.wmark.notlastpage
|
||||
self.onlyfirstpage = self.wmark.onlyfirstpage
|
||||
self.onlylastpage = self.wmark.onlylastpage
|
||||
self.notpages = tk.StringVar()
|
||||
if(self.wmark.notpages is not None):self.notpages.set(self.wmark.notpages)
|
||||
self.onlypages = tk.StringVar()
|
||||
if(self.wmark.onlypages is not None):self.onlypages.set(self.wmark.onlypages)
|
||||
self.bold = self.wmark.bold
|
||||
self.italic = self.wmark.italic
|
||||
self.boxed = self.wmark.boxed
|
||||
self.lined = self.wmark.lined
|
||||
|
||||
self.title("Edit {}".format(self.wmark.name))
|
||||
|
||||
self.f = tk.Frame(self, width=768, height=576, **kwargs)
|
||||
self.f.pack(fill=tk.BOTH)
|
||||
|
||||
# Création de nos widgets
|
||||
self.f.columnconfigure(1, weight=1)
|
||||
self.f.rowconfigure(10, weight=1)
|
||||
|
||||
tk.Label(self.f, text="Name:").grid(row=0, column=0)
|
||||
tk.Entry(self.f, textvariable=self.name).grid(row=0, column=1, columnspan=2, sticky=tk.W+tk.E)
|
||||
tk.Label(self.f, text="Text:", fg="red").grid(row=1, column=0)
|
||||
tk.Entry(self.f, textvariable=self.text).grid(row=1, column=1, columnspan=2, sticky=tk.W+tk.E)
|
||||
tk.Label(self.f, text="Position:").grid(row=2, column=0)
|
||||
ttk.Combobox(self.f, state='readonly', textvariable=self.position, values=strings.positionlist).grid(row=2, column=1, columnspan=2, sticky=tk.W+tk.E)
|
||||
self.Wuserposition = tk.Entry(self.f, textvariable=self.userposition, state='readonly')
|
||||
self.Wuserposition.grid(row=3, column=1, columnspan=2, sticky=tk.W+tk.E)
|
||||
if(self.position.get()==strings.custom):self.Wuserposition['state']='normal'
|
||||
self.sf = ttk.Labelframe(self.f, text='Text formatting')
|
||||
self.sf.grid(row=4, column=0, columnspan=3, sticky=tk.W+tk.E)
|
||||
self.pf = ttk.Labelframe(self.f, text='Pages to apply')
|
||||
self.pf.grid(row=5, column=0, columnspan=3, sticky=tk.W+tk.E)
|
||||
|
||||
self.pf.columnconfigure(0, weight=1)
|
||||
self.pf.columnconfigure(1, weight=1)
|
||||
self.Wnotfirstpage = tk.Checkbutton(self.pf, text="Not on first page", command=self.toggle_notfirstpage)
|
||||
self.Wnotfirstpage.grid(row=0, column=0)
|
||||
if(self.notfirstpage):self.Wnotfirstpage.select()
|
||||
self.Wonlyfirstpage = tk.Checkbutton(self.pf, text="Only on first page", command=self.toggle_onlyfirstpage)
|
||||
self.Wonlyfirstpage.grid(row=0, column=1)
|
||||
if(self.onlyfirstpage):self.Wonlyfirstpage.select()
|
||||
self.Wnotlastpage = tk.Checkbutton(self.pf, text="Not on last page", command=self.toggle_notlastpage)
|
||||
self.Wnotlastpage.grid(row=1, column=0)
|
||||
if(self.notlastpage):self.Wnotlastpage.select()
|
||||
self.Wonlylastpage = tk.Checkbutton(self.pf, text="Only on last page", command=self.toggle_onlylastpage)
|
||||
self.Wonlylastpage.grid(row=1, column=1)
|
||||
if(self.onlylastpage):self.Wonlylastpage.select()
|
||||
tk.Label(self.pf, text="Not on pages:").grid(row=2, column=0)
|
||||
tk.Entry(self.pf, textvariable=self.notpages).grid(row=2, column=1)
|
||||
tk.Label(self.pf, text="Only on pages:").grid(row=3, column=0)
|
||||
tk.Entry(self.pf, textvariable=self.onlypages).grid(row=3, column=1)
|
||||
|
||||
self.sf.columnconfigure(0, weight=1)
|
||||
self.sf.columnconfigure(1, weight=1)
|
||||
self.sf.columnconfigure(2, weight=1)
|
||||
tk.Label(self.sf, text="Size:").grid(row=0, column=0)
|
||||
ttk.Combobox(self.sf, state='readonly', textvariable=self.size, values=strings.sizelist).grid(row=0, column=1, columnspan=2)
|
||||
self.Wbold = tk.Checkbutton(self.sf, text="Bold", command=self.toggle_bold)
|
||||
self.Wbold.grid(row=1, column=0)
|
||||
if(self.bold):self.Wbold.select()
|
||||
self.Witalic = tk.Checkbutton(self.sf, text="Italic", command=self.toggle_italic)
|
||||
self.Witalic.grid(row=1, column=1)
|
||||
if(self.italic):self.Witalic.select()
|
||||
self.Wboxed = tk.Checkbutton(self.sf, text="Boxed", command=self.toggle_boxed)
|
||||
self.Wboxed.grid(row=2, column=0)
|
||||
if(self.boxed):self.Wboxed.select()
|
||||
self.Wlined = tk.Checkbutton(self.sf, text="Lined", command=self.toggle_lined)
|
||||
self.Wlined.grid(row=2, column=1)
|
||||
if(self.lined):self.Wlined.select()
|
||||
|
||||
tk.Button(self.f, text="Ok", command=self.ok).grid(row=10, column=1, columnspan=2, sticky=tk.W+tk.E)
|
||||
tk.Button(self.f, text="Close", command=self.close).grid(row=10, column=0)
|
||||
|
||||
ttk.Separator(self.f, orient="vertical").grid(row=0, column=3, rowspan=7, sticky=tk.N+tk.S, padx=5, pady=5)
|
||||
|
||||
self.tf = ttk.Labelframe(self.f, text='Text directives')
|
||||
self.tf.grid(row=0, column=4, columnspan=2, rowspan=4)
|
||||
tk.Label(self.tf, text="%p").grid(row=1, column=0)
|
||||
tk.Label(self.tf, text="%P").grid(row=2, column=0)
|
||||
tk.Label(self.tf, text="Page number").grid(row=1, column=1, sticky=tk.W)
|
||||
tk.Label(self.tf, text="Total page number").grid(row=2, column=1, sticky=tk.W)
|
||||
|
||||
self.tf = ttk.Labelframe(self.f, text='Text directives')
|
||||
self.tf.grid(row=4, column=4, columnspan=2, rowspan=2)
|
||||
tk.Label(self.tf, text="Custom position:", bg="grey").grid(row=1, column=0, sticky=tk.W+tk.E)
|
||||
tk.Label(self.tf, text="coma-separated coord-").grid(row=2, column=0, sticky=tk.W)
|
||||
tk.Label(self.tf, text="inates between 0 and 1").grid(row=3, column=0, sticky=tk.W)
|
||||
tk.Label(self.tf, text="Not/only on pages:", bg="grey").grid(row=4, column=0, sticky=tk.W+tk.E)
|
||||
tk.Label(self.tf, text="use e for even pages").grid(row=5, column=0, sticky=tk.W)
|
||||
tk.Label(self.tf, text="and o for even pages").grid(row=6, column=0, sticky=tk.W)
|
||||
tk.Label(self.tf, text="end is the last page").grid(row=7, column=0, sticky=tk.W)
|
||||
tk.Label(self.tf, text="Separator: ; ranges: -").grid(row=8, column=0, sticky=tk.W)
|
||||
|
||||
def ok(self, *args):
|
||||
"""
|
||||
Save and quit
|
||||
"""
|
||||
self.wmark.name = self.name.get()
|
||||
if(self.position.get()==''):
|
||||
self.wmark.position = None
|
||||
else:
|
||||
self.wmark.position = self.position.get()
|
||||
if(self.position.get()==strings.custom):
|
||||
up = self.userposition.get().split(',')
|
||||
if(len(up)==2):
|
||||
x = up[0]
|
||||
y = up[1]
|
||||
try:
|
||||
x = float(x)
|
||||
y = float(y)
|
||||
except:
|
||||
messagebox.showwarning(title="Position", message="User defined position have to be coma-separated coordinates between 0 and 1")
|
||||
return
|
||||
if(x>=0. and y>=0. and y<=1. and x<=1.):
|
||||
self.wmark.userposition = (x, y)
|
||||
else:
|
||||
messagebox.showwarning(title="Position", message="User defined position have to be coma-separated coordinates between 0 and 1")
|
||||
return
|
||||
else:
|
||||
messagebox.showwarning(title="Position", message="User defined position have to be coma-separated coordinates between 0 and 1")
|
||||
return
|
||||
else:
|
||||
self.wmark.userposition = None
|
||||
self.wmark.text = self.text.get()
|
||||
if(self.size.get()==''):
|
||||
self.wmark.size=None
|
||||
else:
|
||||
self.wmark.size = self.size.get()
|
||||
self.wmark.notfirstpage = self.notfirstpage
|
||||
self.wmark.notlastpage = self.notlastpage
|
||||
self.wmark.notpages = self.notpages.get()
|
||||
self.wmark.onlyfirstpage = self.onlyfirstpage
|
||||
self.wmark.onlylastpage = self.onlylastpage
|
||||
self.wmark.onlypages = self.onlypages.get()
|
||||
self.wmark.Wlabel["text"] = self.wmark.name
|
||||
self.wmark.bold = self.bold
|
||||
self.wmark.italic = self.italic
|
||||
self.wmark.boxed = self.boxed
|
||||
self.wmark.lined = self.lined
|
||||
self.close()
|
||||
|
||||
def close(self, *args):
|
||||
self.destroy()
|
||||
|
||||
def toggle_notfirstpage(self):
|
||||
if(self.notfirstpage):
|
||||
self.notfirstpage = False
|
||||
self.Wnotfirstpage.deselect()
|
||||
else:
|
||||
self.notfirstpage = True
|
||||
self.onlyfirstpage=False
|
||||
self.Wnotfirstpage.select()
|
||||
self.Wonlyfirstpage.deselect()
|
||||
|
||||
def toggle_notlastpage(self):
|
||||
if(self.notlastpage):
|
||||
self.notlastpage = False
|
||||
self.Wnotlastpage.deselect()
|
||||
else:
|
||||
self.notlastpage = True
|
||||
self.onlylastpage = False
|
||||
self.Wnotlastpage.select()
|
||||
self.Wonlylastpage.deselect()
|
||||
|
||||
def toggle_onlyfirstpage(self):
|
||||
if(self.onlyfirstpage):
|
||||
self.onlyfirstpage = False
|
||||
self.Wonlyfirstpage.deselect()
|
||||
else:
|
||||
self.onlyfirstpage = True
|
||||
self.notfirstpage = False
|
||||
self.Wonlyfirstpage.select()
|
||||
self.Wnotfirstpage.deselect()
|
||||
|
||||
def toggle_onlylastpage(self):
|
||||
if(self.onlylastpage):
|
||||
self.onlylastpage = False
|
||||
self.Wonlylastpage.deselect()
|
||||
else:
|
||||
self.onlylastpage = True
|
||||
self.notlastpage = False
|
||||
self.Wonlylastpage.select()
|
||||
self.Wnotlastpage.deselect()
|
||||
|
||||
def toggle_bold(self):
|
||||
if(self.bold):
|
||||
self.bold = False
|
||||
self.Wbold.deselect()
|
||||
else:
|
||||
self.bold = True
|
||||
self.Wbold.select()
|
||||
|
||||
def toggle_italic(self):
|
||||
if(self.italic):
|
||||
self.italic = False
|
||||
self.Witalic.deselect()
|
||||
else:
|
||||
self.italic = True
|
||||
self.Witalic.select()
|
||||
|
||||
def toggle_boxed(self):
|
||||
if(self.boxed):
|
||||
self.boxed = False
|
||||
self.Wboxed.deselect()
|
||||
else:
|
||||
self.boxed = True
|
||||
self.Wboxed.select()
|
||||
|
||||
def toggle_lined(self):
|
||||
if(self.lined):
|
||||
self.lined = False
|
||||
self.Wlined.deselect()
|
||||
else:
|
||||
self.lined = True
|
||||
self.Wlined.select()
|
||||
|
||||
def comboselectmaj(self, *args):
|
||||
if(self.position.get()==strings.custom):
|
||||
self.Wuserposition['state']='normal'
|
||||
else:
|
||||
self.Wuserposition['state']='readonly'
|
199
pdfembannersrc/encrypt.py
Normal file
199
pdfembannersrc/encrypt.py
Normal file
@ -0,0 +1,199 @@
|
||||
# -*-coding:utf-8 -*
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog
|
||||
from tkinter import messagebox
|
||||
from tkinter import simpledialog
|
||||
from tkinter import ttk
|
||||
from pdfembannersrc import subwindows
|
||||
import logging
|
||||
import PyPDF2
|
||||
logger = logging.getLogger()
|
||||
|
||||
class Interface(tk.Toplevel):
|
||||
"""
|
||||
Main encryption window
|
||||
Allows to :
|
||||
* Encrypt a pdf
|
||||
* Decrypt a pdf
|
||||
"""
|
||||
|
||||
def __init__(self, parent, **kwargs):
|
||||
tk.Toplevel.__init__(self, parent)
|
||||
self.transient(parent)
|
||||
self.grab_set()
|
||||
self.title("PDF Embanner : encryption")
|
||||
self.geometry("800x300")
|
||||
self.protocol("WM_DELETE_WINDOW", self.close)
|
||||
self.bind("<Escape>", self.close)
|
||||
|
||||
self.enc_file = None
|
||||
self.dec_file = None
|
||||
self.enc_saveas = None
|
||||
self.dec_saveas = None
|
||||
|
||||
self.f = tk.Frame(self, width=768, height=576, **kwargs)
|
||||
self.f.pack(fill=tk.BOTH)
|
||||
|
||||
# Création de nos widgets
|
||||
self.f.columnconfigure(1, weight=1)
|
||||
self.f.rowconfigure(12, weight=1)
|
||||
|
||||
tk.Label(self.f, text="Encryption...", bg="blue", fg="white", padx=20).grid(row=0, column=0, columnspan=3, sticky=tk.W)
|
||||
|
||||
tk.Button(self.f, text="Open", command=self.enc_open).grid(row=1, column=0)
|
||||
self.enc_open_label = tk.Label(self.f, text="-" if self.enc_file is None else self.enc_file)
|
||||
self.enc_open_label.grid(row=1, column=1, columnspan=3, sticky=tk.W)
|
||||
tk.Button(self.f, text="Save as", command=self.set_enc_saveas).grid(row=2, column=0)
|
||||
self.enc_save_label = tk.Label(self.f, text="-" if self.enc_saveas is None else self.enc_saveas)
|
||||
self.enc_save_label.grid(row=2, column=1, columnspan=3, sticky=tk.W)
|
||||
tk.Button(self.f, text="Encrypt", command=self.enc_do, fg="blue").grid(row=4, column=3)
|
||||
|
||||
ttk.Separator(self.f, orient="horizontal").grid(row=5, column=0, columnspan=4, sticky=tk.W+tk.E, padx=5, pady=10)
|
||||
|
||||
tk.Label(self.f, text="Decrypt...", bg="blue", fg="white", padx=20).grid(row=6, column=0, columnspan=3, sticky=tk.W)
|
||||
|
||||
tk.Button(self.f, text="Open", command=self.dec_open).grid(row=7, column=0)
|
||||
self.dec_open_label = tk.Label(self.f, text="-" if self.dec_file is None else self.dec_file)
|
||||
self.dec_open_label.grid(row=7, column=1, columnspan=3, sticky=tk.W)
|
||||
tk.Button(self.f, text="Save as", command=self.set_dec_saveas).grid(row=8, column=0)
|
||||
self.dec_save_label = tk.Label(self.f, text="-" if self.dec_saveas is None else self.dec_saveas)
|
||||
self.dec_save_label.grid(row=8, column=1, columnspan=3, sticky=tk.W)
|
||||
tk.Button(self.f, text="Decrypt", command=self.dec_do, fg="blue").grid(row=9, column=3)
|
||||
|
||||
ttk.Separator(self.f, orient="horizontal").grid(row=10, column=0, columnspan=4, sticky=tk.W+tk.E, padx=5, pady=10)
|
||||
|
||||
tk.Button(self.f, text="Close", command=self.close).grid(row=11, column=3)
|
||||
|
||||
self.message = tk.Label(self.f, text="Welcome!")
|
||||
self.message.grid(row=13, column=0, columnspan=4, sticky=tk.W)
|
||||
|
||||
|
||||
def enc_open(self, *args):
|
||||
ftypes = [('PDF files (Portable Document Format)', '*.pdf'), ('All files', '*')]
|
||||
fl = filedialog.askopenfilename(filetypes = ftypes)
|
||||
if fl!='':
|
||||
self.enc_file = fl
|
||||
self.enc_open_label["text"] = fl
|
||||
|
||||
def dec_open(self, *args):
|
||||
ftypes = [('PDF files (Portable Document Format)', '*.pdf'), ('All files', '*')]
|
||||
fl = filedialog.askopenfilename(filetypes = ftypes)
|
||||
if fl!='':
|
||||
self.dec_file = fl
|
||||
self.dec_open_label["text"] = fl
|
||||
|
||||
def enc_do(self, *args):
|
||||
if(self.enc_file is None):
|
||||
messagebox.showwarning(title="PDF Output", message="Please open the PDF to encrypt before !")
|
||||
elif(self.enc_saveas is None):
|
||||
messagebox.showwarning(title="PDF Output", message="Please define the 'Save As' path before !")
|
||||
else:
|
||||
pwd1 = simpledialog.askstring("Encryption", "Password:", show='*')
|
||||
if(pwd1 is not None):
|
||||
pwd2 = simpledialog.askstring("Encryption", "Re-type password:", show='*')
|
||||
if(pwd2 is None):
|
||||
return
|
||||
elif(pwd1==pwd2):
|
||||
pwd=pwd1
|
||||
else:
|
||||
messagebox.showwarning(title="Encryption", message="Passwords do not match!")
|
||||
return
|
||||
else:
|
||||
return
|
||||
currentf = self.enc_file
|
||||
progress = subwindows.Progress(self, 4, "Producing PDF...")
|
||||
progress.message["text"] = 'Reading files'
|
||||
self.message["text"] = "Encrypting"
|
||||
try:
|
||||
with open(self.enc_file, 'rb') as in_f:
|
||||
inpdf = PyPDF2.PdfFileReader(in_f)
|
||||
progress.next()
|
||||
output = PyPDF2.PdfFileWriter()
|
||||
output.addMetadata(inpdf.getDocumentInfo())
|
||||
output.appendPagesFromReader(inpdf)
|
||||
progress.next()
|
||||
output.encrypt(pwd)
|
||||
progress.next()
|
||||
currentf = self.enc_saveas
|
||||
with open(self.enc_saveas, 'wb') as out_f:
|
||||
logger.debug("Encrypt : Writing into file : start")
|
||||
progress.message["text"] = 'Encryption and writing file'
|
||||
output.write(out_f)
|
||||
logger.debug("Encrypt : Writing into file : done")
|
||||
self.message["text"] = "Done"
|
||||
progress.next()
|
||||
except IOError:
|
||||
logger.warn("Encrypt : 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))
|
||||
except Exception as e:
|
||||
logger.warn("Encrypt : Unknown error occured during PDF production. {}".format(str(e)))
|
||||
messagebox.showerror(title="Error",
|
||||
message="An Error occured :\n{}\nNo output produced!".format(e))
|
||||
finally:
|
||||
progress.close()
|
||||
|
||||
def dec_do(self, *args):
|
||||
if(self.dec_file is None):
|
||||
messagebox.showwarning(title="PDF Output", message="Please open the PDF to encrypt before !")
|
||||
elif(self.dec_saveas is None):
|
||||
messagebox.showwarning(title="PDF Output", message="Please define the 'Save As' path before !")
|
||||
else:
|
||||
pwd = simpledialog.askstring("Encrypted", "Password:", show='*')
|
||||
if(pwd is None):
|
||||
return
|
||||
currentf = self.dec_file
|
||||
progress = subwindows.Progress(self, 4, "Producing PDF...")
|
||||
progress.message["text"] = 'Reading file'
|
||||
self.message["text"] = "Decrypting"
|
||||
try:
|
||||
with open(self.dec_file, 'rb') as in_f:
|
||||
inpdf = PyPDF2.PdfFileReader(in_f)
|
||||
progress.next()
|
||||
okpwd = inpdf.decrypt(pwd)
|
||||
if(okpwd==0):
|
||||
messagebox.showwarning(title="Encrypted", message="Incorrect password!")
|
||||
return
|
||||
progress.next()
|
||||
output = PyPDF2.PdfFileWriter()
|
||||
output.addMetadata(inpdf.getDocumentInfo())
|
||||
output.appendPagesFromReader(inpdf)
|
||||
progress.next()
|
||||
currentf = self.dec_saveas
|
||||
with open(self.dec_saveas, 'wb') as out_f:
|
||||
logger.debug("Decrypt : Writing into file : start")
|
||||
output.write(out_f)
|
||||
logger.debug("Decrypt : Writing into file : done")
|
||||
self.message["text"] = "Done"
|
||||
progress.next()
|
||||
except IOError as e:
|
||||
logger.warn("Encrypt : 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))
|
||||
except NotImplementedError as e:
|
||||
logger.warn("Decrypt : Not supported encryption method :: {}".format(e))
|
||||
messagebox.showerror(title="Error",
|
||||
message="The encryption method is not supported! Sorry :(")
|
||||
except Exception as e:
|
||||
logger.warn("Encrypt : Unknown error occured during PDF production. {}".format(str(e)))
|
||||
messagebox.showerror(title="Error",
|
||||
message="An Error occured :\n{}\nNo output produced!".format(e))
|
||||
finally:
|
||||
progress.close()
|
||||
|
||||
def set_enc_saveas(self, *args):
|
||||
fsas = filedialog.asksaveasfilename()
|
||||
if fsas != '':
|
||||
self.enc_saveas = fsas
|
||||
self.enc_save_label["text"] = fsas
|
||||
|
||||
def set_dec_saveas(self, *args):
|
||||
fsas = filedialog.asksaveasfilename()
|
||||
if fsas != '':
|
||||
self.dec_saveas = fsas
|
||||
self.dec_save_label["text"] = fsas
|
||||
|
||||
def close(self, *args):
|
||||
self.destroy()
|
||||
|
93
pdfembannersrc/fich.py
Normal file
93
pdfembannersrc/fich.py
Normal file
@ -0,0 +1,93 @@
|
||||
# -*-coding:utf-8 -*
|
||||
|
||||
from PyPDF2 import PdfFileReader, utils as PyPDF2utils
|
||||
import tkinter as tk
|
||||
from pdfembannersrc import editfich
|
||||
import logging
|
||||
logger = logging.getLogger()
|
||||
|
||||
class Fich:
|
||||
"""
|
||||
Class to store data on a pdf file
|
||||
"""
|
||||
count = 0
|
||||
def __init__(self, filename):
|
||||
self.id = Fich.count
|
||||
Fich.count += 1
|
||||
|
||||
self.name = None
|
||||
self.path = None
|
||||
self.npages = 0
|
||||
self.nblankpages = 0
|
||||
|
||||
self.use = None
|
||||
self.order = None
|
||||
self.rotate = None
|
||||
self.crop = None
|
||||
|
||||
self.Wnum =None
|
||||
self.Wlabel = None
|
||||
self.Wedit = None
|
||||
self.Wdel = None
|
||||
self.Wup = None
|
||||
self.Wdown = None
|
||||
|
||||
if(filename is not None):
|
||||
self._initFromFile(filename)
|
||||
|
||||
def _initFromFile(self, filename):
|
||||
self.path = filename
|
||||
self.name = filename.split('/')[-1]
|
||||
try:
|
||||
with open(filename, "rb") as in_f:
|
||||
input1 = PdfFileReader(in_f)
|
||||
self.npages = input1.getNumPages()
|
||||
except (PyPDF2utils.PdfReadError, EOFError, IOError, NotImplementedError):
|
||||
raise IOError("Impossible to read file {}".format(filename))
|
||||
|
||||
def print1l(self):
|
||||
if(self.name is not None):
|
||||
return self.name
|
||||
else:
|
||||
return '-'
|
||||
|
||||
def edit(self, parent):
|
||||
interface2 = editfich.InterfaceEdit(parent, self)
|
||||
logger.debug("Concatenate : Editting {}".format(self.path))
|
||||
interface2.mainloop()
|
||||
interface2.destroy()
|
||||
logger.debug("Concatenate : End Editting {}".format(self.path))
|
||||
|
||||
def add_widgets(self, frame, parent, i):
|
||||
self.Wnum = tk.Label(frame, text="{}.".format(i+1))
|
||||
self.Wlabel = tk.Label(frame, text=self.print1l())
|
||||
self.Wedit = tk.Button(frame, text="Edit", command=lambda: self.edit(parent))
|
||||
self.Wdel = tk.Button(frame, text="Del", command=lambda: parent.delete(self.id))
|
||||
self.Wup = tk.Button(frame, text="Up", command=lambda: parent.up(self.id))
|
||||
self.Wdown = tk.Button(frame, text="Down", command=lambda: parent.down(self.id))
|
||||
self.set_i_widgets(i)
|
||||
|
||||
def unset_i_widgets(self):
|
||||
self.Wnum.grid_forget()
|
||||
self.Wlabel.grid_forget()
|
||||
self.Wedit.grid_forget()
|
||||
self.Wdel.grid_forget()
|
||||
self.Wup.grid_forget()
|
||||
self.Wdown.grid_forget()
|
||||
|
||||
def set_i_widgets(self, i):
|
||||
self.Wnum.grid(row=i, column=0, sticky=tk.W)
|
||||
self.Wnum["text"] = "{}.".format(i+1)
|
||||
self.Wlabel.grid(row=i, column=5, sticky=tk.W)
|
||||
self.Wedit.grid(row=i, column=1)
|
||||
self.Wdel.grid(row=i, column=2)
|
||||
self.Wup.grid(row=i, column=3)
|
||||
self.Wdown.grid(row=i, column=4)
|
||||
|
||||
def destroy_widgets(self):
|
||||
self.Wnum.destroy()
|
||||
self.Wlabel.destroy()
|
||||
self.Wedit.destroy()
|
||||
self.Wdel.destroy()
|
||||
self.Wup.destroy()
|
||||
self.Wdown.destroy()
|
99
pdfembannersrc/full_split.py
Normal file
99
pdfembannersrc/full_split.py
Normal file
@ -0,0 +1,99 @@
|
||||
# -*-coding:utf-8 -*
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog
|
||||
from tkinter import messagebox
|
||||
from tkinter import ttk
|
||||
from pdfembannersrc import subwindows
|
||||
import logging
|
||||
import PyPDF2
|
||||
import os
|
||||
logger = logging.getLogger()
|
||||
|
||||
class Interface(tk.Toplevel):
|
||||
"""
|
||||
Full split interace
|
||||
"""
|
||||
|
||||
def __init__(self, parent, **kwargs):
|
||||
tk.Toplevel.__init__(self, parent)
|
||||
self.transient(parent)
|
||||
self.grab_set()
|
||||
self.title("PDF Embanner : full split")
|
||||
self.geometry("800x160")
|
||||
self.protocol("WM_DELETE_WINDOW", self.close)
|
||||
self.bind("<Escape>", self.close)
|
||||
|
||||
self.file = None
|
||||
|
||||
self.f = tk.Frame(self, width=768, height=576, **kwargs)
|
||||
self.f.pack(fill=tk.BOTH)
|
||||
|
||||
# Création de nos widgets
|
||||
self.f.columnconfigure(1, weight=1)
|
||||
self.f.rowconfigure(12, weight=1)
|
||||
|
||||
tk.Label(self.f, text="Full split", bg="blue", fg="white", padx=20).grid(row=0, column=0, columnspan=3, sticky=tk.W)
|
||||
tk.Label(self.f, text="Split a PDF file in single-page PDF files stored in a new folder").grid(row=1, column=0, columnspan=3, sticky=tk.W)
|
||||
|
||||
tk.Button(self.f, text="Open", command=self.open).grid(row=2, column=0)
|
||||
self.open_label = tk.Label(self.f, text="-" if self.file is None else self.file)
|
||||
self.open_label.grid(row=2, column=1, columnspan=3, sticky=tk.W)
|
||||
tk.Button(self.f, text="Split", command=self.do, fg="blue").grid(row=3, column=3)
|
||||
|
||||
ttk.Separator(self.f, orient="horizontal").grid(row=5, column=0, columnspan=4, sticky=tk.W+tk.E, padx=5, pady=10)
|
||||
|
||||
tk.Button(self.f, text="Close", command=self.close).grid(row=11, column=3)
|
||||
|
||||
self.message = tk.Label(self.f, text="Welcome!")
|
||||
self.message.grid(row=13, column=0, columnspan=4, sticky=tk.W)
|
||||
|
||||
|
||||
def open(self, *args):
|
||||
ftypes = [('PDF files (Portable Document Format)', '*.pdf'), ('All files', '*')]
|
||||
fl = filedialog.askopenfilename(filetypes = ftypes)
|
||||
if fl!='':
|
||||
self.file = fl
|
||||
self.open_label["text"] = fl
|
||||
|
||||
def do(self, *args):
|
||||
if(self.file is None):
|
||||
messagebox.showwarning(title="PDF Output", message="Please open the PDF to split before !")
|
||||
else:
|
||||
self.message["text"] = "Splitting"
|
||||
outfoldername=self.file[:-4]
|
||||
outbasename=self.file[:-4]+"/"+self.file.split('/')[-1][:-4]
|
||||
try:
|
||||
os.mkdir(outfoldername)
|
||||
except OSError as e:
|
||||
logger.warn("Full Split : Could not create folder {} :: {}".format(outfoldername, e))
|
||||
messagebox.showerror(title="Error",
|
||||
message="Folder {} already exists or could not be created folder".format(outfoldername))
|
||||
progress = None
|
||||
try:
|
||||
with open(self.file, 'rb') as in_f:
|
||||
inpdf = PyPDF2.PdfFileReader(in_f)
|
||||
progress = subwindows.Progress(self, inpdf.getNumPages(), "Producing PDFs...")
|
||||
progress.message["text"] = 'Reading files'
|
||||
for i in range(inpdf.getNumPages()):
|
||||
output = PyPDF2.PdfFileWriter()
|
||||
output.addPage(inpdf.getPage(i))
|
||||
progress.next()
|
||||
with open("{}_{:03d}.pdf".format(outbasename, i), 'wb') as out_f:
|
||||
output.write(out_f)
|
||||
self.message["text"] = "Done"
|
||||
except IOError:
|
||||
logger.warn("Encrypt : Could not open one of the files.")
|
||||
messagebox.showerror(title="Error",
|
||||
message="IO Error occured :\nImpossible to open one of the files\nNo output produced!")
|
||||
except Exception as e:
|
||||
logger.warn("Encrypt : Unknown error occured during PDF production. {}".format(str(e)))
|
||||
messagebox.showerror(title="Error",
|
||||
message="An Error occured :\n{}\nNo output produced!".format(e))
|
||||
finally:
|
||||
if(progress is not None):
|
||||
progress.close()
|
||||
|
||||
def close(self, *args):
|
||||
self.destroy()
|
||||
|
139
pdfembannersrc/get_text.py
Normal file
139
pdfembannersrc/get_text.py
Normal file
@ -0,0 +1,139 @@
|
||||
# -*-coding:utf-8 -*
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog
|
||||
from tkinter import messagebox
|
||||
from tkinter import ttk
|
||||
from pdfembannersrc import subwindows
|
||||
import logging
|
||||
import PyPDF2
|
||||
import os
|
||||
logger = logging.getLogger()
|
||||
|
||||
class Interface(tk.Toplevel):
|
||||
"""
|
||||
Full split interace
|
||||
"""
|
||||
|
||||
def __init__(self, parent, **kwargs):
|
||||
tk.Toplevel.__init__(self, parent)
|
||||
self.transient(parent)
|
||||
self.grab_set()
|
||||
self.title("PDF Embanner : full split")
|
||||
self.geometry("800x160")
|
||||
self.protocol("WM_DELETE_WINDOW", self.close)
|
||||
self.bind("<Escape>", self.close)
|
||||
|
||||
self.file = None
|
||||
|
||||
self.f = tk.Frame(self, width=768, height=576, **kwargs)
|
||||
self.f.pack(fill=tk.BOTH)
|
||||
|
||||
# Création de nos widgets
|
||||
self.f.columnconfigure(1, weight=1)
|
||||
self.f.rowconfigure(12, weight=1)
|
||||
|
||||
tk.Label(self.f, text="Extract text", bg="blue", fg="white", padx=20).grid(row=0, column=0, columnspan=3, sticky=tk.W)
|
||||
tk.Label(self.f, text="Return the text in PDF in one or several text files").grid(row=1, column=0, columnspan=3, sticky=tk.W)
|
||||
|
||||
tk.Button(self.f, text="Open", command=self.open).grid(row=2, column=0)
|
||||
self.open_label = tk.Label(self.f, text="-" if self.file is None else self.file)
|
||||
self.open_label.grid(row=2, column=1, columnspan=3, sticky=tk.W)
|
||||
tk.Button(self.f, text="Extract text in one file", command=self.do_one, fg="blue").grid(row=3, column=3)
|
||||
tk.Button(self.f, text="Extract text per page", command=self.do_ppage, fg="blue").grid(row=3, column=2)
|
||||
|
||||
ttk.Separator(self.f, orient="horizontal").grid(row=5, column=0, columnspan=4, sticky=tk.W+tk.E, padx=5, pady=10)
|
||||
|
||||
tk.Button(self.f, text="Close", command=self.close).grid(row=11, column=3)
|
||||
|
||||
self.message = tk.Label(self.f, text="Welcome!")
|
||||
self.message.grid(row=13, column=0, columnspan=4, sticky=tk.W)
|
||||
|
||||
|
||||
def open(self, *args):
|
||||
ftypes = [('PDF files (Portable Document Format)', '*.pdf'), ('All files', '*')]
|
||||
fl = filedialog.askopenfilename(filetypes = ftypes)
|
||||
if fl!='':
|
||||
self.file = fl
|
||||
self.open_label["text"] = fl
|
||||
|
||||
def do_one(self, *args):
|
||||
if(self.file is None):
|
||||
messagebox.showwarning(title="PDF Output", message="Please open the PDF to split before !")
|
||||
else:
|
||||
self.message["text"] = "Extracting"
|
||||
outbasename=self.file[:-4]+".txt"
|
||||
progress = None
|
||||
try:
|
||||
with open(self.file, 'rb') as in_f:
|
||||
inpdf = PyPDF2.PdfFileReader(in_f)
|
||||
progress = subwindows.Progress(self, inpdf.getNumPages(), "Producing PDFs...")
|
||||
progress.message["text"] = 'Reading files'
|
||||
output = ""
|
||||
for i in range(inpdf.getNumPages()):
|
||||
output+=inpdf.getPage(i).extractText() + "\n"
|
||||
progress.next()
|
||||
except IOError:
|
||||
logger.warn("Text extraction : Could not open PDF file {}.".format(self.file))
|
||||
messagebox.showerror(title="Error",
|
||||
message="Impossible to open PDF file {}".format(self.file))
|
||||
except Exception as e:
|
||||
logger.warn("Text extraction : Unknown error occured during PDF production. {}".format(str(e)))
|
||||
messagebox.showerror(title="Error",
|
||||
message="An Error occured :\n{}\nNo output produced!".format(e))
|
||||
finally:
|
||||
if(progress is not None):
|
||||
progress.close()
|
||||
try:
|
||||
with open(outbasename, 'w') as out_f:
|
||||
out_f.write(output)
|
||||
self.message["text"] = "Done"
|
||||
except IOError:
|
||||
logger.warn("Text extraction : Could not open output file {}.".format(outbasename))
|
||||
messagebox.showerror(title="Error",
|
||||
message="Impossible to open output file {}".format(outbasename))
|
||||
except Exception as e:
|
||||
logger.warn("Text extraction : Unknown error occured during PDF production. {}".format(str(e)))
|
||||
messagebox.showerror(title="Error",
|
||||
message="An Error occured :\n{}\nNo output produced!".format(e))
|
||||
|
||||
def do_ppage(self, *args):
|
||||
if(self.file is None):
|
||||
messagebox.showwarning(title="PDF Output", message="Please open the PDF to split before !")
|
||||
else:
|
||||
self.message["text"] = "Splitting"
|
||||
outfoldername=self.file[:-4]
|
||||
outbasename=self.file[:-4]+"/"+self.file.split('/')[-1][:-4]
|
||||
try:
|
||||
os.mkdir(outfoldername)
|
||||
except OSError as e:
|
||||
logger.warn("Text extraction : Could not create folder {} :: {}".format(outfoldername, e))
|
||||
messagebox.showerror(title="Error",
|
||||
message="Folder {} already exists or could not be created".format(outfoldername))
|
||||
progress = None
|
||||
try:
|
||||
with open(self.file, 'rb') as in_f:
|
||||
inpdf = PyPDF2.PdfFileReader(in_f)
|
||||
progress = subwindows.Progress(self, inpdf.getNumPages(), "Producing PDFs...")
|
||||
progress.message["text"] = 'Reading files'
|
||||
for i in range(inpdf.getNumPages()):
|
||||
output = inpdf.getPage(i).extractText()
|
||||
progress.next()
|
||||
with open("{}_{:03d}.txt".format(outbasename, i), 'w') as out_f:
|
||||
out_f.write(output)
|
||||
self.message["text"] = "Done"
|
||||
except IOError:
|
||||
logger.warn("Text extraction : Could not open one of the files.")
|
||||
messagebox.showerror(title="Error",
|
||||
message="IO Error occured :\nImpossible to open one of the files\nNo output produced!")
|
||||
except Exception as e:
|
||||
logger.warn("Text extraction : Unknown error occured during PDF production. {}".format(str(e)))
|
||||
messagebox.showerror(title="Error",
|
||||
message="An Error occured :\n{}\nNo output produced!".format(e))
|
||||
finally:
|
||||
if(progress is not None):
|
||||
progress.close()
|
||||
|
||||
def close(self, *args):
|
||||
self.destroy()
|
||||
|
63
pdfembannersrc/help.py
Normal file
63
pdfembannersrc/help.py
Normal file
@ -0,0 +1,63 @@
|
||||
# -*-coding:utf-8 -*
|
||||
|
||||
import tkinter as tk
|
||||
import logging
|
||||
logger = logging.getLogger()
|
||||
|
||||
class Interface(tk.Toplevel):
|
||||
"""
|
||||
Help window
|
||||
"""
|
||||
|
||||
def __init__(self, parent, **kwargs):
|
||||
tk.Toplevel.__init__(self, parent)
|
||||
self.transient(parent)
|
||||
self.grab_set()
|
||||
self.title("PDF Embanner : help and credits")
|
||||
self.geometry("700x300")
|
||||
self.protocol("WM_DELETE_WINDOW", self.close)
|
||||
self.bind("<Escape>", self.close)
|
||||
self.bind("<Return>", self.close)
|
||||
|
||||
self.f = tk.Frame(self)
|
||||
self.f.pack(fill=tk.BOTH)
|
||||
self.f.columnconfigure(0, weight=1)
|
||||
self.f.rowconfigure(0, weight=1)
|
||||
|
||||
# Création de nos widgets
|
||||
vsb = tk.Scrollbar(self.f, orient=tk.VERTICAL)
|
||||
vsb.grid(row=0, column=1, sticky=tk.N+tk.S)
|
||||
hsb = tk.Scrollbar(self.f, orient=tk.HORIZONTAL)
|
||||
hsb.grid(row=1, column=0, sticky=tk.W+tk.E)
|
||||
c = tk.Canvas(self.f,yscrollcommand=vsb.set, xscrollcommand=hsb.set)
|
||||
c.grid(row=0, column=0, sticky=tk.W+tk.E+tk.N+tk.S)
|
||||
vsb.config(command=c.yview)
|
||||
hsb.config(command=c.xview)
|
||||
self.frame_text = tk.Frame(c)
|
||||
self.frame_text.columnconfigure(0, weight=1)
|
||||
|
||||
i=0
|
||||
with open('pdfembannersrc/help.md', 'r') as f:
|
||||
for l in f.readlines():
|
||||
if(l[0]=='#'):
|
||||
if(l[1]=='#'):
|
||||
if(l[2]=='#'):
|
||||
tk.Label(self.frame_text, text=l[3:-1], font=(None, 15)).grid(row=i, column=0, sticky=tk.W)
|
||||
else:
|
||||
tk.Label(self.frame_text, text=l[2:-1], font=(None,18)).grid(row=i, column=0, sticky=tk.W)
|
||||
else:
|
||||
tk.Label(self.frame_text, text=l[1:-1], font=(None, 23)).grid(row=i, column=0, sticky=tk.W)
|
||||
else:
|
||||
tk.Label(self.frame_text, text=l[:-1]).grid(row=i, column=0, sticky=tk.W)
|
||||
i+=1
|
||||
|
||||
c.create_window(0, 0, window=self.frame_text, anchor=tk.NW)
|
||||
self.frame_text.update_idletasks()
|
||||
c.config(scrollregion=c.bbox("all"))
|
||||
|
||||
self.bouton_close = tk.Button(self.f, text="Close", command=self.close)
|
||||
self.bouton_close.grid(row=2, column=0, sticky=tk.E)
|
||||
|
||||
def close(self, *args):
|
||||
self.destroy()
|
||||
|
45
pdfembannersrc/strings.py
Normal file
45
pdfembannersrc/strings.py
Normal file
@ -0,0 +1,45 @@
|
||||
|
||||
custom ="Custom"
|
||||
topleft = "Top Left"
|
||||
topcenter = "Top Center"
|
||||
topright = "Top Right"
|
||||
top = [topleft, topcenter, topright]
|
||||
botleft = "Bottom Left"
|
||||
botcenter = "Bottom Center"
|
||||
botright = "Bottom Right"
|
||||
bot = [botleft, botcenter, botright]
|
||||
positionlist = [topleft, topcenter, topright, botleft, botcenter, botright, custom]
|
||||
|
||||
tex_size={}
|
||||
size_8 = "-2"
|
||||
tex_size[size_8] = "\\footnotesize"
|
||||
size_9 = "-1"
|
||||
tex_size[size_9] = "\\small"
|
||||
size_norm = "Normal"
|
||||
tex_size[size_norm] = "\\normalsize"
|
||||
size_1 = "+1"
|
||||
tex_size[size_1] = "\\large"
|
||||
size_2 = "+2"
|
||||
tex_size[size_2] = "\\Large"
|
||||
size_3 = "+3"
|
||||
tex_size[size_3] = "\\LARGE"
|
||||
size_4 = "+4"
|
||||
tex_size[size_4] = "\\huge"
|
||||
sizelist = [size_8, size_9, size_norm, size_1, size_2, size_3, size_4]
|
||||
|
||||
tex_entete = """\\documentclass[12pt]{report}
|
||||
|
||||
\\usepackage[utf8]{inputenc}
|
||||
\\usepackage[T1]{fontenc}
|
||||
\\usepackage[left=2cm,right=2cm,top=2cm,bottom=2cm,includeheadfoot]{geometry}
|
||||
\\usepackage{lastpage}
|
||||
\\usepackage[absolute]{textpos}
|
||||
|
||||
\\usepackage{fancyhdr}
|
||||
\\pagestyle{fancy}
|
||||
|
||||
\\setlength{\\TPHorizModule}{1cm}
|
||||
\\setlength{\\TPVertModule}{1cm}
|
||||
\\begin{document}
|
||||
"""
|
||||
tex_end = "\n\\end{document}"
|
327
pdfembannersrc/subwindows.py
Normal file
327
pdfembannersrc/subwindows.py
Normal file
@ -0,0 +1,327 @@
|
||||
# -*-coding:utf-8 -*
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from tkinter import messagebox
|
||||
import logging
|
||||
logger = logging.getLogger()
|
||||
|
||||
class Rotate(tk.Toplevel):
|
||||
"""
|
||||
Window for asking rotation parameters
|
||||
"""
|
||||
|
||||
def __init__(self, parent, fichobj):
|
||||
tk.Toplevel.__init__(self, parent)
|
||||
self.transient(parent)
|
||||
self.grab_set()
|
||||
self.bind("<Return>", self.ok)
|
||||
self.bind("<Escape>", self.close)
|
||||
|
||||
self.fich = fichobj
|
||||
|
||||
self.title("Rotate {}".format(self.fich.name))
|
||||
|
||||
self.f = tk.Frame(self)
|
||||
self.f.pack(fill=tk.BOTH)
|
||||
|
||||
# Création de nos widgets
|
||||
self.f.columnconfigure(0, weight=1)
|
||||
self.f.rowconfigure(5, weight=1)
|
||||
|
||||
info1 = tk.Label(self.f, text="Rotation :", fg="white", padx=20, bg="blue")
|
||||
info1.grid(row=0, column=0, sticky=tk.W)
|
||||
|
||||
self.rota = tk.IntVar()
|
||||
if(self.fich.rotate is not None):
|
||||
self.rota.set(self.fich.rotate)
|
||||
else:
|
||||
self.rota.set(0)
|
||||
bouton_sel = tk.Radiobutton(self.f, text="No rotation", variable=self.rota, value=0)
|
||||
bouton_sel.grid(row=1, column=0)
|
||||
bouton_sel = tk.Radiobutton(self.f, text="+Pi/2", variable=self.rota, value=1)
|
||||
bouton_sel.grid(row=2, column=0)
|
||||
bouton_sel = tk.Radiobutton(self.f, text="+Pi", variable=self.rota, value=2)
|
||||
bouton_sel.grid(row=3, column=0)
|
||||
bouton_sel = tk.Radiobutton(self.f, text="-Pi/2", variable=self.rota, value=3)
|
||||
bouton_sel.grid(row=4, column=0)
|
||||
|
||||
bouton_do = tk.Button(self.f, text="Ok", command=self.ok)
|
||||
bouton_do.grid(row=6, column=0)
|
||||
|
||||
|
||||
def ok(self):
|
||||
"""
|
||||
Save and quit
|
||||
"""
|
||||
self.fich.rotate = self.rota.get()
|
||||
self.destroy()
|
||||
|
||||
def close(self, *args):
|
||||
self.destroy()
|
||||
|
||||
class Metadata(tk.Toplevel):
|
||||
"""
|
||||
Window for asking metadata
|
||||
"""
|
||||
|
||||
def __init__(self, parent):
|
||||
tk.Toplevel.__init__(self, parent)
|
||||
self.transient(parent)
|
||||
self.grab_set()
|
||||
self.title("Metadata")
|
||||
|
||||
self.outobj = parent
|
||||
|
||||
self.f = tk.Frame(self)
|
||||
self.f.pack(fill=tk.BOTH)
|
||||
|
||||
self.bind("<Return>", self.ok)
|
||||
self.bind("<Escape>", self.close)
|
||||
|
||||
# Création de nos widgets
|
||||
self.f.columnconfigure(1, weight=1)
|
||||
self.f.rowconfigure(5, weight=1)
|
||||
|
||||
info1 = tk.Label(self.f, text="PDF Metadata :", fg="white", padx=20, bg="blue")
|
||||
info1.grid(row=0, column=0, sticky=tk.W)
|
||||
|
||||
tk.Label(self.f, text="Title: ").grid(row=1, column=0)
|
||||
tk.Label(self.f, text="Author: ").grid(row=2, column=0)
|
||||
tk.Label(self.f, text="Subject: ").grid(row=3, column=0)
|
||||
tk.Label(self.f, text="Creator: ").grid(row=4, column=0)
|
||||
|
||||
self.title = tk.StringVar()
|
||||
self.author = tk.StringVar()
|
||||
self.subject = tk.StringVar()
|
||||
self.creator = tk.StringVar()
|
||||
self.title.set(self.outobj.metadata['/Title'])
|
||||
self.author.set(self.outobj.metadata['/Author'])
|
||||
self.subject.set(self.outobj.metadata['/Subject'])
|
||||
self.creator.set(self.outobj.metadata['/Creator'])
|
||||
|
||||
tk.Entry(self.f, textvariable=self.title).grid(row=1, column=1)
|
||||
tk.Entry(self.f, textvariable=self.author).grid(row=2, column=1)
|
||||
tk.Entry(self.f, textvariable=self.subject).grid(row=3, column=1)
|
||||
tk.Entry(self.f, textvariable=self.creator).grid(row=4, column=1)
|
||||
|
||||
tk.Button(self.f, text="Annuler", command=self.quit).grid(row=6, column=0)
|
||||
tk.Button(self.f, text="Ok", command=self.ok).grid(row=6, column=1)
|
||||
|
||||
|
||||
def ok(self, *args):
|
||||
"""
|
||||
Save and quit
|
||||
"""
|
||||
self.outobj.metadata['/Title'] = self.title.get()
|
||||
self.outobj.metadata['/Author'] = self.author.get()
|
||||
self.outobj.metadata['/Subject'] = self.subject.get()
|
||||
self.outobj.metadata['/Creator'] = self.creator.get()
|
||||
|
||||
self.quit()
|
||||
|
||||
def close(self, *args):
|
||||
self.destroy()
|
||||
|
||||
class Progress(tk.Toplevel):
|
||||
"""
|
||||
Progress bar window for production of PDF
|
||||
"""
|
||||
|
||||
def __init__(self, parent, nmax, text):
|
||||
tk.Toplevel.__init__(self, parent)
|
||||
self.transient(parent)
|
||||
self.grab_set()
|
||||
self.title("Producing PDF...")
|
||||
|
||||
self.nmax = nmax
|
||||
|
||||
self.outobj = parent
|
||||
|
||||
self.f = tk.Frame(self)
|
||||
self.f.pack(fill=tk.BOTH)
|
||||
|
||||
|
||||
info1 = tk.Label(self.f, text=text, padx=20)
|
||||
info1.grid(row=0, column=0, sticky=tk.W)
|
||||
|
||||
self.progress = ttk.Progressbar(self.f, orient="horizontal", length=300)
|
||||
self.progress["maximum"] = nmax
|
||||
self.progress.grid(row=2, column=0)
|
||||
|
||||
self.message = tk.Label(self.f, text="Starting production...")
|
||||
self.message.grid(row=3, column=0, sticky=tk.W)
|
||||
|
||||
def next(self):
|
||||
self.progress["value"]+=1
|
||||
self.progress.update_idletasks()
|
||||
|
||||
def close(self):
|
||||
self.destroy()
|
||||
|
||||
class AskBlankPage(tk.Toplevel):
|
||||
"""
|
||||
Ask for position and number for adding blank pages
|
||||
"""
|
||||
|
||||
def __init__(self, parent, fich, values):
|
||||
tk.Toplevel.__init__(self, parent)
|
||||
self.transient(parent)
|
||||
self.grab_set()
|
||||
self.title("Adding blank pages")
|
||||
self.bind("<Return>", self.ok)
|
||||
self.bind("<Escape>", self.close)
|
||||
|
||||
self.fich = fich
|
||||
self.values = values
|
||||
self.after = tk.StringVar()
|
||||
self.nr = tk.StringVar()
|
||||
self.nr.set("1")
|
||||
|
||||
self.f = tk.Frame(self)
|
||||
self.f.pack(fill=tk.BOTH)
|
||||
|
||||
tk.Label(self.f, text="Add after page:", padx=20).grid(row=0, column=0, sticky=tk.W)
|
||||
tk.Label(self.f, text="Nr of blank pages:", padx=20).grid(row=1, column=0, sticky=tk.W)
|
||||
tk.Entry(self.f, textvariable=self.after).grid(row=0, column=1)
|
||||
tk.Entry(self.f, textvariable=self.nr).grid(row=1, column=1)
|
||||
|
||||
tk.Button(self.f, text="Annuler", command=self.close).grid(row=3, column=0)
|
||||
tk.Button(self.f, text="Ok", command=self.ok).grid(row=3, column=1)
|
||||
|
||||
def ok(self, *args):
|
||||
self.values["after"] = []
|
||||
self.values["nr"] = 0
|
||||
for e in self.after.get().split(';'):
|
||||
if(e.isdigit()):
|
||||
i = int(e)
|
||||
if(i<=0 or i>self.fich.npages+self.fich.nblankpages):
|
||||
messagebox.showwarning(title="Warning", message="Number out of range, please correct it !")
|
||||
return
|
||||
else:
|
||||
self.values["after"].append(i)
|
||||
else:
|
||||
messagebox.showwarning(title="Warning", message="Non-number entry (1st line), please correct it !")
|
||||
return
|
||||
nr = self.nr.get()
|
||||
if(nr.isdigit()):
|
||||
nr = int(nr)
|
||||
if(nr>0):
|
||||
self.values["nr"] = nr
|
||||
else:
|
||||
messagebox.showwarning(title="Warning", message="Non-number entry (2nd line), please correct it !")
|
||||
return
|
||||
self.close()
|
||||
logger.debug("Concatenate : Add blank pages : End with values {}".format(self.values))
|
||||
|
||||
def close(self, *args):
|
||||
self.quit()
|
||||
|
||||
class SetCrop(tk.Toplevel):
|
||||
"""
|
||||
Edition for crop box
|
||||
"""
|
||||
|
||||
def __init__(self, parent, fich, **kwargs):
|
||||
tk.Toplevel.__init__(self, parent)
|
||||
self.transient(parent)
|
||||
self.grab_set()
|
||||
self.geometry("400x150")
|
||||
self.bind("<Return>", self.ok)
|
||||
self.bind("<Escape>", self.close)
|
||||
|
||||
self.fich = fich
|
||||
|
||||
self.enabled = False
|
||||
self.llx = tk.StringVar()
|
||||
self.lly = tk.StringVar()
|
||||
self.urx = tk.StringVar()
|
||||
self.ury = tk.StringVar()
|
||||
if(self.fich.crop is not None):
|
||||
self.enabled = True
|
||||
self.llx.set(self.fich.crop[0][0])
|
||||
self.lly.set(self.fich.crop[0][1])
|
||||
self.urx.set(self.fich.crop[1][0])
|
||||
self.ury.set(self.fich.crop[1][1])
|
||||
|
||||
self.title("Crop {}".format(self.fich.name))
|
||||
|
||||
self.f = tk.Frame(self, width=768, height=576, **kwargs)
|
||||
self.f.pack(fill=tk.BOTH)
|
||||
|
||||
# Création de nos widgets
|
||||
self.f.columnconfigure(1, weight=1)
|
||||
self.f.columnconfigure(2, weight=1)
|
||||
self.f.rowconfigure(4, weight=1)
|
||||
|
||||
self.Wenable = tk.Checkbutton(self.f, text="Enable cropping", command=self.toggle_enable)
|
||||
self.Wenable.grid(row=0, column=0, columnspan=3)
|
||||
if(self.enabled):
|
||||
self.Wenable.select()
|
||||
tk.Label(self.f, text="Lower Left bound (x and y):").grid(row=1, column=0)
|
||||
tk.Label(self.f, text="Upper Right bound (x and y):").grid(row=2, column=0)
|
||||
tk.Label(self.f, text="Bounds are given in fraction of page size (between 0 and 1).").grid(row=3, column=0, columnspan=3)
|
||||
self.Wllx = tk.Entry(self.f, textvariable=self.llx)
|
||||
self.Wllx.grid(row=1, column=1, sticky=tk.W+tk.E)
|
||||
self.Wlly = tk.Entry(self.f, textvariable=self.lly)
|
||||
self.Wlly.grid(row=1, column=2, sticky=tk.W+tk.E)
|
||||
self.Wurx = tk.Entry(self.f, textvariable=self.urx)
|
||||
self.Wurx.grid(row=2, column=1, sticky=tk.W+tk.E)
|
||||
self.Wury = tk.Entry(self.f, textvariable=self.ury)
|
||||
self.Wury.grid(row=2, column=2, sticky=tk.W+tk.E)
|
||||
|
||||
if(not self.enabled):
|
||||
self.Wllx['state']='readonly'
|
||||
self.Wlly['state']='readonly'
|
||||
self.Wurx['state']='readonly'
|
||||
self.Wury['state']='readonly'
|
||||
|
||||
tk.Button(self.f, text="Ok", command=self.ok).grid(row=5, column=2, sticky=tk.W+tk.E)
|
||||
tk.Button(self.f, text="Close", command=self.close).grid(row=5, column=0)
|
||||
|
||||
def ok(self, *args):
|
||||
"""
|
||||
Save and quit
|
||||
"""
|
||||
if(self.enabled):
|
||||
try:
|
||||
llx = float(self.llx.get())
|
||||
lly = float(self.lly.get())
|
||||
urx = float(self.urx.get())
|
||||
ury = float(self.ury.get())
|
||||
except:
|
||||
messagebox.showwarning(title="Cropping", message="You have to enter float only for x and y cropping limits !")
|
||||
return
|
||||
if(llx<0 or llx>1 or lly<0 or lly>1 or urx<0 or urx>1 or ury<0 or ury>1):
|
||||
messagebox.showwarning(title="Cropping", message="Values have to be between 0 and 1 !")
|
||||
return
|
||||
if(llx>=urx or lly>=ury):
|
||||
messagebox.showwarning(title="Cropping", message="Bounds not in correct order !")
|
||||
return
|
||||
self.fich.crop=[[llx,lly],[urx,ury]]
|
||||
else:
|
||||
self.fich.crop = None
|
||||
self.close()
|
||||
|
||||
def close(self, *args):
|
||||
self.quit()
|
||||
|
||||
def toggle_enable(self):
|
||||
if(self.enabled):
|
||||
self.enabled = False
|
||||
self.Wenable.deselect()
|
||||
self.llx.set('')
|
||||
self.lly.set('')
|
||||
self.urx.set('')
|
||||
self.ury.set('')
|
||||
self.Wllx['state']='readonly'
|
||||
self.Wlly['state']='readonly'
|
||||
self.Wurx['state']='readonly'
|
||||
self.Wury['state']='readonly'
|
||||
else:
|
||||
self.enabled = True
|
||||
self.Wenable.select()
|
||||
self.Wllx['state']='normal'
|
||||
self.Wlly['state']='normal'
|
||||
self.Wurx['state']='normal'
|
||||
self.Wury['state']='normal'
|
595
pdfembannersrc/watermark.py
Normal file
595
pdfembannersrc/watermark.py
Normal file
@ -0,0 +1,595 @@
|
||||
# -*-coding:utf-8 -*
|
||||
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog
|
||||
from tkinter import messagebox
|
||||
from tkinter import ttk
|
||||
from pdfembannersrc.wmark import Wmark
|
||||
import configparser
|
||||
from subprocess import Popen, CalledProcessError
|
||||
from pdfembannersrc import strings
|
||||
from pdfembannersrc import subwindows
|
||||
import shlex
|
||||
import os.path
|
||||
import random
|
||||
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 : watermark")
|
||||
self.geometry("800x400")
|
||||
self.protocol("WM_DELETE_WINDOW", self.close)
|
||||
self.bind("<Escape>", self.close)
|
||||
self.bind("<Control-o>", self.open)
|
||||
self.bind("<Control-f>", self.open_markfile)
|
||||
self.bind("<Control-s>", self.saveas)
|
||||
self.bind("<Control-m>", self.editmetadata)
|
||||
self.bind("<Control-a>", self.add)
|
||||
self.bind("<Control-Return>", self.do)
|
||||
|
||||
self.file = None
|
||||
self.npages=0
|
||||
self.box=None
|
||||
self.markfile = None
|
||||
self.save_file = None
|
||||
self.wmarks = []
|
||||
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(1, weight=1)
|
||||
self.f.rowconfigure(8, weight=1)
|
||||
|
||||
tk.Button(self.f, text="Open", command=self.open).grid(row=0, column=0)
|
||||
tk.Button(self.f, text="Close", command=self.close).grid(row=0, column=4, sticky=tk.E)
|
||||
self.file_label = tk.Label(self.f, text="-" if self.file is None else self.file)
|
||||
self.file_label.grid(row=0, column=1, columnspan=4, sticky=tk.W)
|
||||
|
||||
ttk.Separator(self.f, orient="horizontal").grid(row=1, column=0, columnspan=6, sticky=tk.W+tk.E, padx=5, pady=5)
|
||||
|
||||
tk.Label(self.f, text="Watermark with an other PDF", bg="blue", fg="white", padx=20).grid(row=2, column=0, columnspan=5, sticky=tk.W)
|
||||
tk.Button(self.f, text="File", command=self.open_markfile).grid(row=3, column=0)
|
||||
self.markfile_label = tk.Label(self.f, text="-" if self.markfile is None else self.markfile)
|
||||
self.markfile_label.grid(row=3, column=1, columnspan=2, sticky=tk.W)
|
||||
tk.Label(self.f, text="Select pages").grid(row=3, column=3, sticky=tk.W)
|
||||
self.select_page_markfile = tk.StringVar()
|
||||
tk.Entry(self.f, textvariable=self.select_page_markfile).grid(row=3, column=4)
|
||||
self.all_pages_markfile = tk.IntVar()
|
||||
self.all_pages_markfile.set(0)
|
||||
tk.Radiobutton(self.f, text="Apply on first page(s) only", variable=self.all_pages_markfile, value=0).grid(row=4, column=0, columnspan=2, sticky=tk.W)
|
||||
tk.Radiobutton(self.f, text="Apply on all pages", variable=self.all_pages_markfile, value=1).grid(row=5, column=0, columnspan=2, sticky=tk.W)
|
||||
self.markfile_bottom = tk.IntVar()
|
||||
self.markfile_bottom.set(0)
|
||||
tk.Radiobutton(self.f, text="Apply on top", variable=self.markfile_bottom, value=0).grid(row=4, column=2, columnspan=3, sticky=tk.W)
|
||||
tk.Radiobutton(self.f, text="Apply on bottom", variable=self.markfile_bottom, value=1).grid(row=5, column=2, columnspan=3, sticky=tk.W)
|
||||
|
||||
ttk.Separator(self.f, orient="horizontal").grid(row=6, column=0, columnspan=6, sticky=tk.W+tk.E, padx=5, pady=5)
|
||||
|
||||
tk.Label(self.f, text="Text watermark", bg="blue", fg="white", padx=20).grid(row=7, column=0, columnspan=5, sticky=tk.W)
|
||||
tk.Button(self.f, text="Add", command=self.add).grid(row=7, column=4)
|
||||
|
||||
vsb = tk.Scrollbar(self.f, orient=tk.VERTICAL)
|
||||
vsb.grid(row=8, column=5, sticky=tk.N+tk.S)
|
||||
self.c = tk.Canvas(self.f,yscrollcommand=vsb.set)
|
||||
self.c.grid(row=8, column=0, columnspan=5, sticky="news")
|
||||
vsb.config(command=self.c.yview)
|
||||
self.frame_wmark = tk.Frame(self.c)
|
||||
self.c.create_window(0, 0, window=self.frame_wmark, anchor=tk.NW)
|
||||
self.frame_wmark.update_idletasks()
|
||||
self.c.config(scrollregion=self.c.bbox("all"))
|
||||
self.frame_wmark.columnconfigure(3, weight=1)
|
||||
|
||||
ttk.Separator(self.f, orient="horizontal").grid(row=9, column=0, columnspan=6, sticky=tk.W+tk.E, padx=5, pady=5)
|
||||
|
||||
tk.Button(self.f, text="Save as", command=self.saveas).grid(row=10, 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=10, column=1, columnspan=3, sticky=tk.W)
|
||||
tk.Button(self.f, text="Metadata", command=self.editmetadata).grid(row=10, column=4, sticky=tk.E)
|
||||
tk.Button(self.f, text="Generate PDF", fg="blue", command=self.do).grid(row=11, column=3, columnspan=3, sticky=tk.E)
|
||||
|
||||
self.message = tk.Label(self.f, text="Welcome !")
|
||||
self.message.grid(row=12, column=0, columnspan=6, sticky=tk.W)
|
||||
|
||||
def add(self, *args):
|
||||
"""
|
||||
Add watermark
|
||||
"""
|
||||
wm = Wmark(None)
|
||||
i = len(self.wmarks)
|
||||
self.wmarks.append(wm)
|
||||
wm.add_widgets(self.frame_wmark, self, i)
|
||||
self.frame_wmark.update_idletasks()
|
||||
self.c.config(scrollregion=self.c.bbox("all"))
|
||||
self.message["text"] = "Added watermark"
|
||||
|
||||
def do(self, *args):
|
||||
"""
|
||||
Do watermarking with correct options !
|
||||
"""
|
||||
if(self.file is None):
|
||||
messagebox.showwarning(title="PDF Output", message="Please open an input PDF file before !")
|
||||
return
|
||||
elif(self.save_file is None):
|
||||
messagebox.showwarning(title="PDF Output", message="Please define the 'Save As' path before !")
|
||||
return
|
||||
if(len(self.wmarks)>0):
|
||||
# Generate PDF for watermarking with Latex
|
||||
err, use_pages_generated, pdfgeneratedname = generate_pdf(self.wmarks, self.save_file, self.npages)
|
||||
if(err>0 and err<100):
|
||||
self.message["text"] = "Error : no output generated"
|
||||
if(err==1):
|
||||
logger.error("Watermark :: Could not write in output folder")
|
||||
messagebox.showerror(title="PDF Output", message="Could not write in output folder")
|
||||
elif(err==2):
|
||||
logger.error("Watermark :: Could not parse compiler config file")
|
||||
messagebox.showerror(title="PDF Output", message="Could not parse compiler config file")
|
||||
elif(err==3):
|
||||
logger.error("Watermark :: No latex compiler found")
|
||||
messagebox.showerror(title="PDF Output", message="No latex compiler found. Check your compiler.conf file")
|
||||
elif(err==4):
|
||||
logger.error("Watermark :: Latex compilation error")
|
||||
messagebox.showerror(title="PDF Output", message="Latex compilation error. You may have put an incorrect caracter in text area.")
|
||||
elif(err==5):
|
||||
logger.error("Watermark :: IOError during compilation")
|
||||
messagebox.showerror(title="PDF Output", message="IOError during compilation. Check rights on output folder.")
|
||||
return
|
||||
elif(err==100):
|
||||
logger.info("Watermark :: There were errors in your page ranges. Some page ranges not taken in consideration.")
|
||||
messagebox.showinfo(title="PDF Output", message="There were errors in your page ranges. Some page ranges not taken in consideration.")
|
||||
genpdf=True
|
||||
else:
|
||||
genpdf=False
|
||||
logger.debug("Genpdf is set to {}".format(genpdf))
|
||||
|
||||
if(self.markfile is not None):
|
||||
try:
|
||||
self.message["text"] = "Opening {}".format(self.markfile)
|
||||
with open(self.markfile, "rb") as in_f:
|
||||
input2 = PyPDF2.PdfFileReader(in_f)
|
||||
markf_npages = input2.getNumPages()
|
||||
correct, use_pages_markf = parse_range(self.select_page_markfile.get(), markf_npages)
|
||||
if(not correct):
|
||||
messagebox.showerror(title="Watermark file", message="Incorrect 'Select page' range. Please correct it!".format(self.markfile))
|
||||
return
|
||||
if(len(use_pages_markf)==0):
|
||||
use_pages_markf = list(range(1,markf_npages+1))
|
||||
except (PyPDF2.utils.PdfReadError, EOFError, IOError, NotImplementedError):
|
||||
self.message["text"] = "Failed to open {}".format(self.markfile)
|
||||
messagebox.showerror(title="PDF Open", message="Impossible to read PDF input file ! {}".format(self.markfile))
|
||||
logger.warning("Wartermark : Error while opening {}".format(self.markfile))
|
||||
return
|
||||
markf = True
|
||||
else:
|
||||
markf=False
|
||||
use_pages_markf = []
|
||||
logger.debug("Markf is set to {} with pages {}".format(markf, use_pages_markf))
|
||||
|
||||
genpdf_f = None
|
||||
markf_f = None
|
||||
try:
|
||||
if(markf):
|
||||
markf_f = open(self.markfile, 'rb')
|
||||
input_mark = PyPDF2.PdfFileReader(markf_f)
|
||||
if(genpdf):
|
||||
genpdf_f = open(pdfgeneratedname, 'rb')
|
||||
input_gen = PyPDF2.PdfFileReader(genpdf_f)
|
||||
output = PyPDF2.PdfFileWriter()
|
||||
with open(self.file,'rb') as in_f:
|
||||
input_ref = PyPDF2.PdfFileReader(in_f)
|
||||
for i in range(self.npages):
|
||||
# Adding i-th page !
|
||||
if(markf and (self.all_pages_markfile.get()==1 or i<len(use_pages_markf))):
|
||||
if(self.all_pages_markfile):
|
||||
print("add 1 on {}".format(i))
|
||||
if(self.markfile_bottom.get()):
|
||||
page = input_mark.getPage(use_pages_markf[i%len(use_pages_markf)]-1)
|
||||
page.mergePage(input_ref.getPage(i))
|
||||
else:
|
||||
page = input_ref.getPage(i)
|
||||
page2 = input_mark.getPage(use_pages_markf[i%len(use_pages_markf)]-1)
|
||||
page.mergePage(page2)
|
||||
else:
|
||||
print("add 2 on {}".format(i))
|
||||
if(self.markfile_bottom.get()):
|
||||
page = input_mark.getPage(use_pages_markf[i]-1)
|
||||
page.mergePage(input_ref.getPage(i))
|
||||
else:
|
||||
page = input_ref.getPage(i)
|
||||
page2 = input_mark.getPage(use_pages_markf[i]-1)
|
||||
page.mergePage(page2)
|
||||
else:
|
||||
page = input_ref.getPage(i)
|
||||
if(genpdf and use_pages_generated[i]):
|
||||
page3 = input_gen.getPage(i)
|
||||
sp3 = page3.mediaBox
|
||||
if(self.box is not None):
|
||||
try:
|
||||
sx = float(self.box.upperRight[0] - self.box.upperLeft[0])/float(sp3.upperRight[0] - sp3.upperLeft[0])
|
||||
sy = float(self.box.lowerRight[1] - self.box.upperRight[1])/float(sp3.lowerRight[1] - sp3.upperRight[1])
|
||||
page3.scale(sx,sy)
|
||||
except:
|
||||
logger.warn("Watermark :: Error during rescaling of pages")
|
||||
page.mergePage(page3)
|
||||
output.addPage(page)
|
||||
|
||||
# Writing output file
|
||||
try:
|
||||
with open(self.save_file, 'wb') as out_f:
|
||||
output.write(out_f)
|
||||
except IOError:
|
||||
logger.error("Watermark :: IOError :: Could not write output file {}".format(self.save_file))
|
||||
self.message["text"] = "Could not write into {}".format(self.save_file)
|
||||
messagebox.showerror(title="PDF Open", message="Impossible to write in output file ! {}".format(self.save_file))
|
||||
except IOError:
|
||||
logger.error("Watermark :: IOError :: Could not open one of the input file")
|
||||
self.message["text"] = "Failed to open input file(s)".format(self.markfile)
|
||||
messagebox.showerror(title="PDF Open", message="Impossible to read PDF input file(s) !")
|
||||
except PyPDF2.utils.PdfReadError:
|
||||
logger.error("Watermark :: Invalid PDF")
|
||||
self.message["text"] = "Invalid input PDF".format(self.markfile)
|
||||
messagebox.showerror(title="PDF Open", message="Invalid PDF as input file!")
|
||||
finally:
|
||||
if(genpdf_f is not None):
|
||||
genpdf_f.close()
|
||||
# Removing genpdf file
|
||||
try:
|
||||
os.remove(pdfgeneratedname)
|
||||
except:
|
||||
logger.warn("Watermark :: Error while cleaning generated PDF")
|
||||
if(markf_f is not None):
|
||||
markf_f.close()
|
||||
self.message["text"] = "Done"
|
||||
|
||||
def close(self, *args):
|
||||
if(self.output_produced or messagebox.askyesno("Quit", "Are you sure you want to quit ?")):
|
||||
logger.debug("Watermark: Quit")
|
||||
self.destroy()
|
||||
|
||||
def open(self, *args):
|
||||
self.message["text"] = "Open..."
|
||||
ftypes = [('PDF files (Portable Document Format)', '*.pdf'), ('All files', '*')]
|
||||
fl = filedialog.askopenfilename(filetypes = ftypes)
|
||||
if fl != '':
|
||||
try:
|
||||
self.message["text"] = "Opening {}".format(fl)
|
||||
with open(fl, "rb") as in_f:
|
||||
input1 = PyPDF2.PdfFileReader(in_f)
|
||||
self.npages = input1.getNumPages()
|
||||
self.box = input1.getPage(0).mediaBox
|
||||
self.file = fl
|
||||
self.file_label["text"] = fl
|
||||
self.message["text"] = "Opened {}".format(fl)
|
||||
except (PyPDF2.utils.PdfReadError, EOFError, IOError, NotImplementedError):
|
||||
self.message["text"] = "Failed to open {}".format(fl)
|
||||
messagebox.showwarning(title="PDF Open", message="Impossible to read PDF input file ! {}".format(fl))
|
||||
logger.warning("Watermark: Error while opening {}".format(fl))
|
||||
else:
|
||||
self.message["text"] = "Nothing to open"
|
||||
|
||||
def open_markfile(self, *args):
|
||||
self.message["text"] = "File..."
|
||||
ftypes = [('PDF files (Portable Document Format)', '*.pdf'), ('All files', '*')]
|
||||
fl = filedialog.askopenfilename(filetypes = ftypes)
|
||||
if fl != '':
|
||||
self.markfile = fl
|
||||
self.markfile_label["text"] = fl
|
||||
self.message["text"] = "Watermark file set to {}".format(fl)
|
||||
else:
|
||||
self.message["text"] = "Nothing to open"
|
||||
|
||||
def saveas(self, *args):
|
||||
self.message["text"] = "Save as..."
|
||||
fsas = filedialog.asksaveasfilename()
|
||||
if fsas != '':
|
||||
self.save_file = fsas
|
||||
self.save_label["text"] = fsas
|
||||
self.message["text"] = "Save as set to {}".format(fsas)
|
||||
else:
|
||||
self.message["text"] = "Aborted save as"
|
||||
|
||||
def delete(self, ident):
|
||||
i=0
|
||||
for i in range(len(self.wmarks)):
|
||||
if(ident==self.wmarks[i].id):
|
||||
break
|
||||
self.wmarks[i].destroy_widgets()
|
||||
del self.wmarks[i]
|
||||
for j in range(i,len(self.wmarks)):
|
||||
self.wmarks[j].unset_i_widgets()
|
||||
self.wmarks[j].set_i_widgets(j)
|
||||
self.message["text"] = "Deleted."
|
||||
|
||||
def editmetadata(self, *args):
|
||||
self.message["text"] = "Edit Metadata..."
|
||||
interface3 = subwindows.Metadata(self)
|
||||
logger.debug("Watermark : Output metadata set")
|
||||
interface3.mainloop()
|
||||
interface3.destroy()
|
||||
logger.debug("Watermark : End output metadata set with value {}".format(self.metadata))
|
||||
self.message["text"] = "Edited Metadata"
|
||||
|
||||
###############################################################################################
|
||||
|
||||
def parse_range(srange, nmax):
|
||||
"""
|
||||
Parse a text as a range of pages
|
||||
separated by ; and -
|
||||
Recognise 'e' for even pages, 'o' for odd pages and 'end'
|
||||
|
||||
srange : string to be parsed
|
||||
nmax : page maximum number
|
||||
|
||||
NB : Pages are numbered from 1 to nmax
|
||||
"""
|
||||
correct=True
|
||||
ret = []
|
||||
for e in srange.split(';'):
|
||||
e = e.split('-')
|
||||
if(len(e)==1):
|
||||
if(e[0].lower()=='e'): # Even/pair
|
||||
ret+=list(range(1,nmax,2))
|
||||
elif(e[0].lower()=='o'): # Odd/impair
|
||||
ret+=list(range(0,nmax,2))
|
||||
elif(e[0].lower()=='end'): # Odd/impair
|
||||
ret.append(nmax)
|
||||
elif(e[0].isdigit() and int(e[0])>0 and int(e[0])<nmax):
|
||||
ret+=[int(e[0])]
|
||||
else:
|
||||
correct=False
|
||||
elif(len(e)==2):
|
||||
if(e[0].isdigit() and e[1].isdigit()):
|
||||
i = int(e[0])
|
||||
j = int(e[1])
|
||||
if(i>0 and i<j and j<nmax):
|
||||
ret+=list(range(i,j+1))
|
||||
elif(i>0 and i<j):
|
||||
ret+=list(range(i,nmax))
|
||||
correct=False
|
||||
else:
|
||||
correct=False
|
||||
if(e[0].isdigit() and e[1].lower()=='end'):
|
||||
i = int(e[0])
|
||||
if(i>0 and i<nmax):
|
||||
ret+=list(range(i,nmax))
|
||||
else:
|
||||
correct=False
|
||||
else:
|
||||
correct=False
|
||||
else:
|
||||
correct=False
|
||||
return correct, ret
|
||||
|
||||
def generate_pdf(wmarks, save_file, npages):
|
||||
"""
|
||||
Generate a PDF with Latex with appropriate marks on it
|
||||
|
||||
npages : total number of pages
|
||||
wmarks : list of Wmark objects to be placed on pages
|
||||
save_file : name of the program output file, used to
|
||||
choose a name for pdf output
|
||||
|
||||
Return errnum, pdf_output_name
|
||||
errnum:
|
||||
1 : Could not write in output folder
|
||||
2 : Could not parse config file
|
||||
3 : No compiler available
|
||||
4 : Error during compilation
|
||||
5 : IOError
|
||||
100 : Warning : Error in Wmark range
|
||||
"""
|
||||
err=0
|
||||
use_pages_generated=[]
|
||||
|
||||
# Test file to write
|
||||
texoutname = save_file + ".tex"
|
||||
if(os.path.exists(texoutname)):
|
||||
texoutname = save_file + "_" + str(random.randint(0,100000)) + ".tex"
|
||||
if(os.path.exists(texoutname)):
|
||||
return 1, None, None
|
||||
f_tex = None
|
||||
reussi, markbypage = wmbypage(wmarks, npages)
|
||||
if(not reussi):
|
||||
err = 100
|
||||
# Writting Tex file
|
||||
try:
|
||||
f_tex = open(texoutname, 'w')
|
||||
f_tex.write(strings.tex_entete)
|
||||
for i in range(npages):
|
||||
f_tex.write(genpagetex(markbypage[i]))
|
||||
if(len(markbypage[i])==0):
|
||||
use_pages_generated.append(False)
|
||||
else:
|
||||
use_pages_generated.append(True)
|
||||
f_tex.write(strings.tex_end)
|
||||
# Compiling Tex file
|
||||
except IOError:
|
||||
return 1, None, None
|
||||
finally:
|
||||
if(f_tex is not None):
|
||||
f_tex.close()
|
||||
erreurs, pdfgeneratedname = compiletex(texoutname, deletetex=True)
|
||||
if(erreurs>0):
|
||||
return erreurs+1, None, None
|
||||
return err, use_pages_generated, pdfgeneratedname
|
||||
|
||||
def wmbypage(wmarks, npages):
|
||||
"""
|
||||
Return a list indexed by page number (from 0 to npages-1)
|
||||
in which element i is a list of Wmark to put on the i+1 page.
|
||||
"""
|
||||
ret = []
|
||||
correct = True
|
||||
for i in range(npages):
|
||||
ret.append([])
|
||||
for m in wmarks:
|
||||
correct1, onlyp = parse_range(m.onlypages, npages)
|
||||
correct2, notp = parse_range(m.notpages, npages)
|
||||
correct = correct and correct1 and correct2
|
||||
if((1 not in notp and m.onlyfirstpage) or (1 in onlyp) or (len(onlyp)==0 and not m.onlyfirstpage and not m.onlylastpage and 1 not in notp)):
|
||||
ret[0].append(m)
|
||||
for i in range(1,npages-1):
|
||||
if((i+1 not in notp and len(onlyp)==0 and not m.onlyfirstpage and not m.onlylastpage) or (i+1 in onlyp)):
|
||||
ret[i].append(m)
|
||||
if((npages not in notp and m.onlylastpage) or (npages in onlyp) or (len(onlyp)==0 and not m.onlyfirstpage and not m.onlylastpage and npages not in notp)):
|
||||
ret[-1].append(m)
|
||||
return correct, ret
|
||||
|
||||
def genpagetex(wmarks):
|
||||
"""
|
||||
Return a string to be inserted in tex file
|
||||
to generate one page with marks given in
|
||||
wmarks (list of Wmark)
|
||||
"""
|
||||
headrule = False
|
||||
footrule = False
|
||||
lhead =[]
|
||||
chead =[]
|
||||
rhead =[]
|
||||
lfoot =[]
|
||||
cfoot =[]
|
||||
rfoot =[]
|
||||
custom = []
|
||||
for m in wmarks:
|
||||
if(m.position==strings.topleft):
|
||||
lhead.append(m.format_tex())
|
||||
elif(m.position==strings.topcenter):
|
||||
chead.append(m.format_tex())
|
||||
elif(m.position==strings.topright):
|
||||
rhead.append(m.format_tex())
|
||||
elif(m.position==strings.botleft):
|
||||
lfoot.append(m.format_tex())
|
||||
elif(m.position==strings.botcenter):
|
||||
cfoot.append(m.format_tex())
|
||||
elif(m.position==strings.botright):
|
||||
rfoot.append(m.format_tex())
|
||||
elif(m.position==strings.custom):
|
||||
custom.append([m.userposition, m.format_tex()])
|
||||
else:
|
||||
rhead.append(m.format_tex())
|
||||
if(m.lined and m.position in [strings.top]):
|
||||
headrule = True
|
||||
elif(m.lined and m.position in [strings.bot]):
|
||||
footrule = True
|
||||
s = "\n\\newpage"
|
||||
s += "\n\\lhead{" + ' '.join(lhead) + "}"
|
||||
s += "\n\\chead{" + ' '.join(chead) + "}"
|
||||
s += "\n\\rhead{" + ' '.join(rhead) + "}"
|
||||
s += "\n\\lfoot{" + ' '.join(lfoot) + "}"
|
||||
s += "\n\\cfoot{" + ' '.join(cfoot) + "}"
|
||||
s += "\n\\rfoot{" + ' '.join(rfoot) + "}"
|
||||
if(headrule):
|
||||
s += "\n\\renewcommand{\\headrulewidth}{0.4pt}"
|
||||
else:
|
||||
s += "\n\\renewcommand{\\headrulewidth}{0pt}"
|
||||
if(footrule):
|
||||
s += "\n\\renewcommand{\\footrulewidth}{0.4pt}"
|
||||
else:
|
||||
s += "\n\\renewcommand{\\footrulewidth}{0pt}"
|
||||
for e in custom:
|
||||
s += "\n\\begin{textblock}{1}"+"({},{})".format(e[0][0]*21, e[0][1]*29.7)
|
||||
s += "\n" + e[1]
|
||||
s += "\n\\end{textblock}"
|
||||
s += "\n\\null\n"
|
||||
return s
|
||||
|
||||
def compiletex(texoutname, deletetex=False, deletetemp=True):
|
||||
"""
|
||||
Compile the tex file texoutname
|
||||
|
||||
Rerurns :
|
||||
error number, pdf_filename
|
||||
|
||||
error number :
|
||||
0 : No error
|
||||
1 : Could not parse config file
|
||||
2 : No compiler available
|
||||
3 : Error during compilation
|
||||
4 : IOError
|
||||
"""
|
||||
err = 0
|
||||
pdfgeneratedname = texoutname[:-4] + ".pdf"
|
||||
curdir = os.getcwd()
|
||||
os.chdir(os.path.dirname(texoutname))
|
||||
texbasename = os.path.basename(texoutname)
|
||||
try:
|
||||
config = configparser.ConfigParser()
|
||||
config.read('pdfembannersrc/compiler.conf')
|
||||
except configparser.Error:
|
||||
logger.error("Watermark :: configparser failed to parse compiler.conf")
|
||||
return 1, None
|
||||
|
||||
for compiler in config.sections():
|
||||
if 'cmd' not in config[compiler]:
|
||||
logger.error("Watermark :: cmd entry not found for compiler {}".format(compiler))
|
||||
return 1, None
|
||||
cmd1 = config[compiler]['cmd']
|
||||
if 'args' in config[compiler]:
|
||||
cmd1 += ' ' + config[compiler]['args']
|
||||
cmd1+=' '+texbasename
|
||||
cmd = shlex.split(cmd1)
|
||||
try:
|
||||
logger.debug("Try {}".format(cmd1))
|
||||
p = Popen(cmd)
|
||||
p.wait()
|
||||
p = Popen(cmd)
|
||||
p.wait()
|
||||
if(p.returncode>0):
|
||||
logger.error("Watermark :: Latex Error")
|
||||
return 3, None
|
||||
logger.info("Watermark :: Compiled successfully with {}".format(cmd1))
|
||||
break # On a trouve le bon compilo
|
||||
except OSError:
|
||||
logger.warn("Watermark :: Failed to compile with {}. Compiler not found.".format(cmd1))
|
||||
continue
|
||||
except ValueError:
|
||||
logger.warn("Watermark :: Failed to compile with {}. Value Error.".format(cmd1))
|
||||
continue
|
||||
except CalledProcessError:
|
||||
return 3, None
|
||||
except IOError:
|
||||
logger.error("Watermark :: IOError during compilation")
|
||||
return 4, None
|
||||
else:
|
||||
logger.error("Watermark :: No latex compilater found after trying all!")
|
||||
return 2, None
|
||||
|
||||
# Delete temp files
|
||||
if(deletetemp):
|
||||
if('clean_ext' in config[compiler]):
|
||||
for ext in config[compiler]['clean_ext'].split():
|
||||
todel = texoutname[:-4]+'.'+ext
|
||||
logger.debug("Trying to del {}".format(todel))
|
||||
if(os.path.exists(todel)):
|
||||
try:
|
||||
os.remove(todel)
|
||||
except (OSError, IOError):
|
||||
logger.error("Watermark :: Error while deleting {}".format(todel))
|
||||
|
||||
# Delete tex file
|
||||
if(deletetex):
|
||||
try:
|
||||
os.remove(texoutname)
|
||||
except (OSError, IOError):
|
||||
logger.error("Error while deleting {}".format(texoutname))
|
||||
|
||||
os.chdir(curdir)
|
||||
|
||||
return err, pdfgeneratedname
|
||||
|
||||
|
88
pdfembannersrc/wmark.py
Normal file
88
pdfembannersrc/wmark.py
Normal file
@ -0,0 +1,88 @@
|
||||
# -*-coding:utf-8 -*
|
||||
|
||||
import tkinter as tk
|
||||
from pdfembannersrc import editwmark
|
||||
from pdfembannersrc import strings
|
||||
import logging
|
||||
logger = logging.getLogger()
|
||||
|
||||
class Wmark:
|
||||
"""
|
||||
Class to store data on a watermark
|
||||
"""
|
||||
count = 0
|
||||
default_name = "New watermark"
|
||||
def __init__(self, filename):
|
||||
self.id = Wmark.count
|
||||
Wmark.count += 1
|
||||
|
||||
self.name = Wmark.default_name + " {}".format(self.id+1)
|
||||
self.position = None
|
||||
self.userposition = None
|
||||
self.text = None
|
||||
self.size = None
|
||||
self.notfirstpage = False
|
||||
self.notlastpage = False
|
||||
self.notpages = None
|
||||
self.onlyfirstpage = False
|
||||
self.onlylastpage = False
|
||||
self.onlypages = None
|
||||
self.bold = False
|
||||
self.italic = False
|
||||
self.boxed = False
|
||||
self.lined = False
|
||||
|
||||
self.Wnum =None
|
||||
self.Wlabel = None
|
||||
self.Wedit = None
|
||||
self.Wdel = None
|
||||
|
||||
def edit(self, parent):
|
||||
parent.message["text"] = "Edit Watermark"
|
||||
interface2 = editwmark.InterfaceEdit(parent, self)
|
||||
|
||||
def add_widgets(self, frame, parent, i):
|
||||
self.Wnum = tk.Label(frame, text="{}.".format(i+1))
|
||||
self.Wlabel = tk.Label(frame, text=self.name)
|
||||
self.Wedit = tk.Button(frame, text="Edit", command=lambda: self.edit(parent))
|
||||
self.Wdel = tk.Button(frame, text="Del", command=lambda: parent.delete(self.id))
|
||||
self.set_i_widgets(i)
|
||||
|
||||
def unset_i_widgets(self):
|
||||
self.Wnum.grid_forget()
|
||||
self.Wlabel.grid_forget()
|
||||
self.Wedit.grid_forget()
|
||||
self.Wdel.grid_forget()
|
||||
|
||||
def set_i_widgets(self, i):
|
||||
self.Wnum.grid(row=i, column=0, sticky=tk.W)
|
||||
self.Wnum["text"] = "{}.".format(i+1)
|
||||
self.Wlabel.grid(row=i, column=3, sticky=tk.W)
|
||||
self.Wedit.grid(row=i, column=1)
|
||||
self.Wdel.grid(row=i, column=2)
|
||||
|
||||
def destroy_widgets(self):
|
||||
self.Wnum.destroy()
|
||||
self.Wlabel.destroy()
|
||||
self.Wedit.destroy()
|
||||
self.Wdel.destroy()
|
||||
|
||||
def format_tex(self):
|
||||
s = self.text
|
||||
s = s.replace(" %p ", "~\\thepage~")
|
||||
s = s.replace("%p ", "\\thepage~")
|
||||
s = s.replace(" %p", "~\\thepage")
|
||||
s = s.replace("%p", "\\thepage")
|
||||
s = s.replace(" %P", "~\\pageref{LastPage}")
|
||||
s = s.replace("%P", "\\pageref{LastPage}")
|
||||
if(self.size is not None):
|
||||
s = strings.tex_size[self.size]+ " " + s
|
||||
if(self.bold):
|
||||
s = "\\bfseries " + s
|
||||
if(self.italic):
|
||||
s = "\\itshape " + s
|
||||
if(self.size is not None or self.bold or self.italic):
|
||||
s = "{" + s + "}"
|
||||
if(self.boxed):
|
||||
s = "\\framebox[1.1\\width]{" + s + "}"
|
||||
return s
|
Loading…
Reference in New Issue
Block a user