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()
|
||||
|