2357 lines
51 KiB
Python
2357 lines
51 KiB
Python
#!/usr/bin/python
|
|
|
|
from threading import Thread
|
|
from tkinter import *
|
|
from tkinter.ttk import *
|
|
import asyncio
|
|
import glob
|
|
import json
|
|
import os
|
|
import subprocess as sub
|
|
import tkinter.filedialog
|
|
import tkinter.messagebox
|
|
import tkinter.scrolledtext as scrltxt
|
|
import tkinter.font as tkfont
|
|
|
|
|
|
def check_page_nums(input_pages):
|
|
page_num_list = re.split(',|-|o|e', input_pages)
|
|
|
|
for page_num in page_num_list:
|
|
if len(page_num) > 0 and not page_num.isdigit():
|
|
return FALSE
|
|
return TRUE
|
|
|
|
# GUI construction
|
|
|
|
root = Tk()
|
|
|
|
screen_width = root.winfo_screenwidth()
|
|
screen_height = root.winfo_screenheight()
|
|
|
|
# root.resizable(FALSE, FALSE)
|
|
|
|
root.title('rebook')
|
|
|
|
# main tab
|
|
|
|
base_tab = Notebook(root)
|
|
|
|
conversion_tab = Frame(base_tab)
|
|
base_tab.add(conversion_tab, text='Conversion')
|
|
|
|
log_tab = Frame(base_tab)
|
|
base_tab.add(log_tab, text='Log')
|
|
|
|
base_tab.pack(expand=1, fill='both')
|
|
|
|
# ############################################################################################### #
|
|
# MENU
|
|
# ############################################################################################### #
|
|
|
|
menu_bar = Menu(root)
|
|
root['menu'] = menu_bar
|
|
|
|
def on_command_about_box_cb():
|
|
about_message = \
|
|
'''rebook
|
|
|
|
TclTk GUI for k2pdfopt by Pu Wang
|
|
|
|
The source code can be found at:
|
|
http://github.com/pwang7/rebook/rebook.py'''
|
|
|
|
tkinter.messagebox.showinfo(message=about_message)
|
|
|
|
menu_file = Menu(menu_bar)
|
|
menu_bar.add_cascade(menu=menu_file, label='File')
|
|
menu_file.add_command(label='About', command=on_command_about_box_cb)
|
|
|
|
# root.createcommand('tkAboutDialog', on_command_about_box_cb)
|
|
# root.createcommand('::tk::mac::ShowHelp', on_command_about_box_cb)
|
|
|
|
# global variables and functions
|
|
|
|
k2pdfopt_path = './k2pdfopt'
|
|
custom_preset_file_path = 'rebook_preset.json'
|
|
|
|
|
|
def check_k2pdfopt_path_exists():
|
|
if not os.path.exists(k2pdfopt_path):
|
|
tkinter.messagebox.showerror(
|
|
message='Failed to find k2pdfopt, ' +
|
|
'please put it under the same directory ' +
|
|
'as rebook and then restart.'
|
|
)
|
|
quit()
|
|
|
|
k2pdfopt_cmd_args = {}
|
|
|
|
|
|
def update_cmd_arg_entry_strvar():
|
|
global strvarCmdArgs
|
|
strvarCmdArgs.set(generate_cmd_arg_str())
|
|
|
|
|
|
def add_or_update_one_cmd_arg(arg_key, arg_value):
|
|
global k2pdfopt_cmd_args
|
|
k2pdfopt_cmd_args[arg_key] = arg_value
|
|
|
|
|
|
def remove_one_cmd_arg(arg_key):
|
|
global k2pdfopt_cmd_args
|
|
previous = k2pdfopt_cmd_args.pop(arg_key, None)
|
|
return previous
|
|
|
|
|
|
def load_custom_preset():
|
|
global strvarOutputFilePath
|
|
|
|
if os.path.exists(custom_preset_file_path):
|
|
with open(custom_preset_file_path) as preset_file:
|
|
dict_to_load = json.load(preset_file)
|
|
|
|
if dict_to_load:
|
|
log_string('Load Preset: ' + str(dict_to_load))
|
|
|
|
initialize_vars(dict_to_load)
|
|
|
|
return TRUE
|
|
|
|
return FALSE
|
|
|
|
|
|
def log_string(str_line):
|
|
global stdoutText
|
|
|
|
log_content = str_line.strip()
|
|
if len(log_content) > 0:
|
|
stdoutText.config(state=NORMAL)
|
|
|
|
print('=== ' + log_content) # TODO: remove print
|
|
|
|
stdoutText.insert(END, log_content + '\n')
|
|
stdoutText.config(state=DISABLED)
|
|
|
|
|
|
def clear_logs():
|
|
stdoutText.config(state=NORMAL)
|
|
stdoutText.delete(1.0, END)
|
|
stdoutText.config(state=DISABLED)
|
|
|
|
|
|
def initialize_vars(dict_vars):
|
|
global k2pdfopt_cmd_args
|
|
|
|
for k, v in dict_vars.items():
|
|
for i in range(len(v)):
|
|
arg_var_map[k][i].set(v[i])
|
|
|
|
k2pdfopt_cmd_args = {}
|
|
|
|
for cb_func in arg_cb_map.values():
|
|
if cb_func is not None:
|
|
cb_func()
|
|
# must be after loading preset values
|
|
update_cmd_arg_entry_strvar()
|
|
|
|
|
|
def restore_default_values():
|
|
clear_logs()
|
|
|
|
remove_preview_img_and_clear_canvas()
|
|
|
|
for sv in string_var_list:
|
|
sv.set('')
|
|
|
|
for bv in bool_var_list:
|
|
bv.set(FALSE)
|
|
|
|
for b in combo_box_list:
|
|
b.current(0)
|
|
|
|
initialize_vars(default_var_map)
|
|
|
|
|
|
def start_loop(loop):
|
|
asyncio.set_event_loop(loop)
|
|
loop.run_forever()
|
|
|
|
thread_loop = asyncio.get_event_loop()
|
|
run_loop_thread = Thread(
|
|
target=start_loop,
|
|
args=(thread_loop,),
|
|
daemon=TRUE,
|
|
)
|
|
run_loop_thread.start()
|
|
|
|
background_process = None
|
|
background_future = None
|
|
|
|
device_argument_map = {
|
|
0: 'k2',
|
|
1: 'dx',
|
|
2: 'kpw',
|
|
3: 'kp2',
|
|
4: 'kp3',
|
|
5: 'kv',
|
|
6: 'ko2',
|
|
7: 'pb2',
|
|
8: 'nookst',
|
|
9: 'kbt',
|
|
10: 'kbg',
|
|
11: 'kghd',
|
|
12: 'kghdfs',
|
|
13: 'kbm',
|
|
14: 'kba',
|
|
15: 'kbhd',
|
|
16: 'kbh2o',
|
|
17: 'kbh2ofs',
|
|
18: 'kao',
|
|
19: 'nex7',
|
|
20: None,
|
|
}
|
|
|
|
device_choice_map = {
|
|
0: 'Kindle 1-5',
|
|
1: 'Kindle DX',
|
|
2: 'Kindle Paperwhite',
|
|
3: 'Kindle Paperwhite 2',
|
|
4: 'Kindle Paperwhite 3',
|
|
5: 'Kindle Voyage/PW3+/Oasis',
|
|
6: 'Kindle Oasis 2',
|
|
7: 'Pocketbook Basic 2',
|
|
8: 'Nook Simple Touch',
|
|
9: 'Kobo Touch',
|
|
10: 'Kobo Glo',
|
|
11: 'Kobo Glo HD',
|
|
12: 'Kobo Glo HD Full Screen',
|
|
13: 'Kobo Mini',
|
|
14: 'Kobo Aura',
|
|
15: 'Kobo Aura HD',
|
|
16: 'Kobo H2O',
|
|
17: 'Kobo H2O Full Screen',
|
|
18: 'Kobo Aura One',
|
|
19: 'Nexus 7',
|
|
20: 'Other (specify width & height)',
|
|
}
|
|
|
|
mode_argument_map = {
|
|
0: 'def',
|
|
1: 'copy',
|
|
2: 'fp',
|
|
3: 'fw',
|
|
4: '2col',
|
|
5: 'tm',
|
|
6: 'crop',
|
|
7: 'concat',
|
|
}
|
|
|
|
mode_choice_map = {
|
|
0: 'Default',
|
|
1: 'Copy',
|
|
2: 'Fit Page',
|
|
3: 'Fit Width',
|
|
4: '2 Columns',
|
|
5: 'Trim Margins',
|
|
6: 'Crop',
|
|
7: 'Concat',
|
|
}
|
|
|
|
unit_argument_map = {
|
|
0: 'in',
|
|
1: 'cm',
|
|
2: 's',
|
|
3: 't',
|
|
4: 'p',
|
|
5: 'x',
|
|
}
|
|
|
|
unit_choice_map = {
|
|
0: 'Inches',
|
|
1: 'Centimeters',
|
|
2: 'Source Page Size',
|
|
3: 'Trimmed Source Region Size',
|
|
4: 'Pixels',
|
|
5: 'Relative to the OCR Text Layer',
|
|
}
|
|
|
|
|
|
def generate_cmd_arg_str():
|
|
must_have_args = '-a- -ui- -x'
|
|
|
|
device_arg = k2pdfopt_cmd_args.pop(device_arg_name, None)
|
|
if device_arg is None:
|
|
width_arg = k2pdfopt_cmd_args.pop(width_arg_name)
|
|
height_arg = k2pdfopt_cmd_args.pop(height_arg_name)
|
|
|
|
mode_arg = k2pdfopt_cmd_args.pop(conversion_mode_arg_name)
|
|
|
|
arg_list = [mode_arg] + list(k2pdfopt_cmd_args.values())
|
|
|
|
k2pdfopt_cmd_args[conversion_mode_arg_name] = mode_arg
|
|
if device_arg is not None:
|
|
arg_list.append(device_arg)
|
|
|
|
k2pdfopt_cmd_args[device_arg_name] = device_arg
|
|
else:
|
|
arg_list.append(width_arg)
|
|
arg_list.append(height_arg)
|
|
|
|
k2pdfopt_cmd_args[width_arg_name] = width_arg
|
|
k2pdfopt_cmd_args[height_arg_name] = height_arg
|
|
|
|
arg_list.append(must_have_args)
|
|
|
|
log_string('Generate Argument List: ' + str(arg_list))
|
|
|
|
cmd_arg_str = ' '.join(arg_list)
|
|
|
|
return cmd_arg_str
|
|
|
|
|
|
def convert_pdf_file(output_arg):
|
|
check_k2pdfopt_path_exists()
|
|
|
|
async def async_run_cmd_and_log(exec_cmd):
|
|
global background_process
|
|
|
|
executed = exec_cmd.strip()
|
|
|
|
def log_bytes(log_btyes):
|
|
log_string(log_btyes.decode('utf-8'))
|
|
|
|
log_string(executed)
|
|
|
|
p = await asyncio.create_subprocess_shell(
|
|
executed,
|
|
stdout=asyncio.subprocess.PIPE,
|
|
stderr=asyncio.subprocess.PIPE,
|
|
)
|
|
background_process = p
|
|
|
|
while True:
|
|
line = await p.stdout.readline()
|
|
|
|
log_bytes(line)
|
|
|
|
if not line:
|
|
break
|
|
if line == '' and p.returncode is not None:
|
|
break
|
|
|
|
input_pdf_path = strvarFilePath.get().strip()
|
|
if ' ' in input_pdf_path:
|
|
# in case the file name contains space
|
|
input_pdf_path = '\"' + input_pdf_path + '\"'
|
|
|
|
executed = ' '.join([
|
|
k2pdfopt_path,
|
|
input_pdf_path,
|
|
output_arg,
|
|
generate_cmd_arg_str(),
|
|
])
|
|
future = asyncio.run_coroutine_threadsafe(
|
|
async_run_cmd_and_log(executed),
|
|
thread_loop,
|
|
)
|
|
return future
|
|
|
|
|
|
def check_pdf_conversion_done():
|
|
if (background_future is None) or (background_future.done()):
|
|
if ((background_process is None) or
|
|
(background_process.returncode is not None)):
|
|
return TRUE
|
|
|
|
tkinter.messagebox.showerror(
|
|
message='Background Conversion Not Finished Yet! Please Wait.',
|
|
)
|
|
return FALSE
|
|
|
|
# conversion tab
|
|
conversion_tab_left_part_column_num = 0
|
|
conversion_tab_left_part_row_num = -1
|
|
|
|
|
|
# ############################################################################################### #
|
|
# REQUIRED INPUTS
|
|
# ############################################################################################### #
|
|
conversion_tab_left_part_row_num += 1
|
|
|
|
device_arg_name = '-dev' # -dev <name>
|
|
width_arg_name = '-w' # -w <width>[in|cm|s|t|p]
|
|
height_arg_name = '-h' # -h <height>[in|cm|s|t|p|x]
|
|
conversion_mode_arg_name = '-mode' # -mode <mode>
|
|
output_path_arg_name = '-o' # -o <namefmt>
|
|
output_pdf_suffix = '-output.pdf'
|
|
screen_unit_prefix = '-screen_unit'
|
|
|
|
strvarFilePath = StringVar()
|
|
strvarDevice = StringVar()
|
|
strvarConversionMode = StringVar()
|
|
strvarScreenUnit = StringVar()
|
|
strvarScreenWidth = StringVar()
|
|
strvarScreenHeight = StringVar()
|
|
|
|
# fontStyle = tkfont.Font(family="Lucida Grande", size=20)
|
|
# style = Style()
|
|
# # creating the theme with the
|
|
# style.theme_create('style_class',
|
|
|
|
# # getting the settings
|
|
# settings={
|
|
|
|
# # getting through the Labelframe
|
|
# # widget
|
|
# 'TLabelframe': {
|
|
|
|
# # configure the changes
|
|
# 'configure': {
|
|
# 'background': 'green'
|
|
# }
|
|
# },
|
|
|
|
# # getting through the Labelframe's
|
|
# # label widget
|
|
# 'TLabelframe.Label': {
|
|
# 'configure': {
|
|
# 'background': 'green'
|
|
# }
|
|
# }
|
|
# }
|
|
# )
|
|
# style.theme_use('style_class')
|
|
required_input_frame = Labelframe(conversion_tab, text='Required Inputs')
|
|
required_input_frame.grid(
|
|
column=conversion_tab_left_part_column_num,
|
|
row=conversion_tab_left_part_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
required_frame_row_num = 0
|
|
|
|
inputPathEntry = Entry(
|
|
required_input_frame,
|
|
state='readonly',
|
|
textvariable=strvarFilePath,
|
|
)
|
|
inputPathEntry.grid(
|
|
column=0,
|
|
row=required_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
|
|
def on_command_open_pdf_file_cb():
|
|
supported_formats = [('PDF files', '*.pdf'), ('DJVU files', '*.djvu')]
|
|
|
|
filename = tkinter.filedialog.askopenfilename(
|
|
parent=root,
|
|
filetypes=supported_formats,
|
|
title='Select your file',
|
|
)
|
|
|
|
if filename is not None and len(filename.strip()) > 0:
|
|
strvarFilePath.set(filename)
|
|
(base_path, file_ext) = os.path.splitext(filename)
|
|
strvarOutputFilePath.set(base_path + output_pdf_suffix)
|
|
|
|
openButton = Button(
|
|
required_input_frame,
|
|
text='Choose a File',
|
|
command=on_command_open_pdf_file_cb,
|
|
)
|
|
openButton.grid(
|
|
column=1,
|
|
row=required_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
required_frame_row_num += 1
|
|
|
|
deviceText = Label(required_input_frame, text='Device')
|
|
deviceText.grid(
|
|
column=0,
|
|
row=required_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
|
|
def update_device_unit_width_height():
|
|
if deviceComboBox.current() != 20: # non-other type
|
|
deviceType = device_argument_map[deviceComboBox.current()]
|
|
arg = device_arg_name + ' ' + deviceType
|
|
add_or_update_one_cmd_arg(device_arg_name, arg)
|
|
|
|
remove_one_cmd_arg(width_arg_name)
|
|
remove_one_cmd_arg(height_arg_name)
|
|
else:
|
|
screen_unit = unit_argument_map[unitComboBox.current()]
|
|
|
|
width_arg = (
|
|
width_arg_name + ' ' +
|
|
strvarScreenWidth.get().strip() + screen_unit
|
|
)
|
|
add_or_update_one_cmd_arg(width_arg_name, width_arg)
|
|
|
|
height_arg = (
|
|
height_arg_name + ' ' +
|
|
strvarScreenHeight.get().strip() + screen_unit
|
|
)
|
|
add_or_update_one_cmd_arg(height_arg_name, height_arg)
|
|
|
|
remove_one_cmd_arg(device_arg_name)
|
|
|
|
|
|
def on_bind_event_device_unit_cb(e=None):
|
|
update_device_unit_width_height()
|
|
|
|
deviceComboBox = Combobox(
|
|
required_input_frame,
|
|
state='readonly',
|
|
textvariable=strvarDevice,
|
|
)
|
|
deviceComboBox['values'] = list(device_choice_map.values())
|
|
deviceComboBox.current(0)
|
|
deviceComboBox.bind('<<ComboboxSelected>>', on_bind_event_device_unit_cb)
|
|
deviceComboBox.grid(
|
|
column=1,
|
|
row=required_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
required_frame_row_num += 1
|
|
|
|
unitTextLabel = Label(required_input_frame, text='Unit')
|
|
unitTextLabel.grid(
|
|
column=0,
|
|
row=required_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
unitComboBox = Combobox(
|
|
required_input_frame,
|
|
state='readonly',
|
|
textvariable=strvarScreenUnit,
|
|
)
|
|
unitComboBox['values'] = list(unit_choice_map.values())
|
|
unitComboBox.current(0)
|
|
unitComboBox.bind('<<ComboboxSelected>>', on_bind_event_device_unit_cb)
|
|
unitComboBox.grid(
|
|
column=1,
|
|
row=required_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
required_frame_row_num += 1
|
|
|
|
|
|
def on_command_width_height_cb():
|
|
update_device_unit_width_height()
|
|
|
|
widthTextLabel = Label(required_input_frame, text='Width')
|
|
widthTextLabel.grid(
|
|
column=0,
|
|
row=required_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
widthSpinBox = Spinbox(
|
|
required_input_frame,
|
|
from_=0,
|
|
to=10000,
|
|
increment=0.1,
|
|
# state='readonly',
|
|
textvariable=strvarScreenWidth,
|
|
command=on_command_width_height_cb,
|
|
)
|
|
widthSpinBox.grid(
|
|
column=1,
|
|
row=required_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
required_frame_row_num += 1
|
|
|
|
heightTextLabel = Label(required_input_frame, text='Height')
|
|
heightTextLabel.grid(
|
|
column=0,
|
|
row=required_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
heightSpinBox = Spinbox(
|
|
required_input_frame,
|
|
from_=0,
|
|
to=10000,
|
|
increment=0.1,
|
|
# state='readonly',
|
|
textvariable=strvarScreenHeight,
|
|
command=on_command_width_height_cb,
|
|
)
|
|
heightSpinBox.grid(
|
|
column=1,
|
|
row=required_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
required_frame_row_num += 1
|
|
|
|
|
|
def on_bind_event_mode_cb(e=None):
|
|
conversionMode = mode_argument_map[modeComboBox.current()]
|
|
arg = (
|
|
conversion_mode_arg_name + ' ' +
|
|
conversionMode
|
|
)
|
|
add_or_update_one_cmd_arg(conversion_mode_arg_name, arg)
|
|
|
|
modeTextLabel = Label(required_input_frame, text='Conversion Mode')
|
|
modeTextLabel.grid(
|
|
column=0,
|
|
row=required_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
modeComboBox = Combobox(
|
|
required_input_frame,
|
|
state='readonly',
|
|
textvariable=strvarConversionMode,
|
|
)
|
|
modeComboBox['values'] = list(mode_choice_map.values())
|
|
modeComboBox.current(0)
|
|
modeComboBox.bind('<<ComboboxSelected>>', on_bind_event_mode_cb)
|
|
modeComboBox.grid(
|
|
column=1,
|
|
row=required_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
# info frame
|
|
conversion_tab_left_part_row_num += 1
|
|
|
|
strvarOutputFilePath = StringVar()
|
|
strvarCmdArgs = StringVar()
|
|
|
|
infoFrame = Labelframe(conversion_tab, text='Related Info')
|
|
infoFrame.grid(
|
|
column=conversion_tab_left_part_column_num,
|
|
row=conversion_tab_left_part_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
|
|
def on_command_save_cb():
|
|
with open(custom_preset_file_path, 'w') as preset_file:
|
|
dict_to_save = {}
|
|
for k, v in arg_var_map.items():
|
|
dict_to_save[k] = [var.get() for var in v]
|
|
|
|
json.dump(dict_to_save, preset_file)
|
|
|
|
saveTextLabel = Label(infoFrame, text='Save Current Setting as Preset')
|
|
saveTextLabel.grid(column=0, row=0, sticky=N+W, pady=0, padx=5)
|
|
|
|
saveButton = Button(infoFrame, text='Save', command=on_command_save_cb)
|
|
saveButton.grid(column=1, row=0, sticky=N+W, pady=0, padx=5)
|
|
|
|
outputTextLabel = Label(infoFrame, text='Output Pdf File Path')
|
|
outputTextLabel.grid(column=0, row=1, sticky=N+W, pady=0, padx=5)
|
|
|
|
outputPathEntry = Entry(
|
|
infoFrame,
|
|
state='readonly',
|
|
textvariable=strvarOutputFilePath,
|
|
)
|
|
outputPathEntry.grid(column=1, row=1, sticky=N+W, pady=0, padx=5)
|
|
|
|
cmdArgTextLabel = Label(infoFrame, text='Command-line Options')
|
|
cmdArgTextLabel.grid(column=0, row=2, sticky=N+W, pady=0, padx=5)
|
|
|
|
|
|
def on_bind_event_cmd_args_cb(e=None):
|
|
update_cmd_arg_entry_strvar()
|
|
|
|
cmdArgEntry = Entry(
|
|
infoFrame,
|
|
state='readonly',
|
|
textvariable=strvarCmdArgs,
|
|
)
|
|
cmdArgEntry.bind('<Button-1>', on_bind_event_cmd_args_cb)
|
|
cmdArgEntry.grid(column=1, row=2, sticky=N+W, pady=0, padx=5)
|
|
|
|
|
|
# ############################################################################################### #
|
|
# PARAMETERS FRAME
|
|
# ############################################################################################### #
|
|
# conversion_tab_left_part_row_num += 1
|
|
|
|
column_num_arg_name = '-col' # -col <maxcol>
|
|
resolution_multiplier_arg_name = '-dr' # -dr <value>
|
|
crop_margin_arg_name = '-cbox' # -cbox[<pagelist>|u|-]
|
|
dpi_arg_name = '-dpi' # -dpi <dpival>
|
|
page_num_arg_name = '-p' # -p <pagelist>
|
|
|
|
isColumnNum = BooleanVar()
|
|
isResolutionMultipler = BooleanVar()
|
|
isCropMargin = BooleanVar()
|
|
isDPI = BooleanVar()
|
|
|
|
strvarColumnNum = StringVar()
|
|
strvarResolutionMultiplier = StringVar()
|
|
strvarCropPageRange = StringVar()
|
|
strvarLeftMargin = StringVar()
|
|
strvarRightMargin = StringVar()
|
|
strvarTopMargin = StringVar()
|
|
strvarBottomMargin = StringVar()
|
|
strvarDPI = StringVar()
|
|
strvarPageNums = StringVar()
|
|
|
|
parameters_frame = Labelframe(conversion_tab, text='Parameters')
|
|
parameters_frame.grid(
|
|
column=conversion_tab_left_part_column_num,
|
|
row=conversion_tab_left_part_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
para_frame_row_num = 0
|
|
|
|
|
|
def on_command_column_num_cb():
|
|
if isColumnNum.get():
|
|
arg = (
|
|
column_num_arg_name + ' ' +
|
|
strvarColumnNum.get().strip()
|
|
)
|
|
add_or_update_one_cmd_arg(column_num_arg_name, arg)
|
|
else:
|
|
remove_one_cmd_arg(column_num_arg_name)
|
|
|
|
colNumCheckButton = Checkbutton(
|
|
parameters_frame,
|
|
text='Max Columns',
|
|
variable=isColumnNum,
|
|
command=on_command_column_num_cb,
|
|
)
|
|
colNumCheckButton.grid(
|
|
column=0,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
colNumSpinBox = Spinbox(
|
|
parameters_frame,
|
|
from_=1,
|
|
to=10,
|
|
increment=1,
|
|
state='readonly',
|
|
textvariable=strvarColumnNum,
|
|
command=on_command_column_num_cb,
|
|
)
|
|
colNumSpinBox.grid(
|
|
column=1,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
para_frame_row_num += 1
|
|
|
|
|
|
def on_command_resolution_multipler_cb():
|
|
if isResolutionMultipler.get():
|
|
arg = (
|
|
resolution_multiplier_arg_name + ' ' +
|
|
strvarResolutionMultiplier.get().strip()
|
|
)
|
|
add_or_update_one_cmd_arg(resolution_multiplier_arg_name, arg)
|
|
else:
|
|
remove_one_cmd_arg(resolution_multiplier_arg_name)
|
|
|
|
resolutionCheckButton = Checkbutton(
|
|
parameters_frame,
|
|
text='Document Resolution Factor',
|
|
variable=isResolutionMultipler,
|
|
command=on_command_resolution_multipler_cb,
|
|
)
|
|
resolutionCheckButton.grid(
|
|
column=0,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
resolutionSpinBox = Spinbox(
|
|
parameters_frame,
|
|
from_=0.1,
|
|
to=10.0,
|
|
increment=0.1,
|
|
state='readonly',
|
|
textvariable=strvarResolutionMultiplier,
|
|
command=on_command_resolution_multipler_cb,
|
|
)
|
|
resolutionSpinBox.grid(
|
|
column=1,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
para_frame_row_num += 1
|
|
|
|
|
|
def on_command_and_validate_crop_margin_cb():
|
|
if (len(strvarCropPageRange.get().strip()) > 0 and
|
|
not check_page_nums(strvarCropPageRange.get().strip())):
|
|
remove_one_cmd_arg(crop_margin_arg_name)
|
|
strvarCropPageRange.set('')
|
|
|
|
tkinter.messagebox.showerror(
|
|
message='Invalide Crop Page Range! Should be like 2-5e,3-7o,9-',
|
|
)
|
|
|
|
return FALSE
|
|
|
|
if isCropMargin.get():
|
|
page_range_arg = strvarCropPageRange.get().strip()
|
|
margin_args = [
|
|
strvarLeftMargin.get(),
|
|
strvarTopMargin.get(),
|
|
strvarRightMargin.get(),
|
|
strvarBottomMargin.get(),
|
|
]
|
|
arg = (
|
|
# no space between -cbox and page range
|
|
crop_margin_arg_name + page_range_arg + ' '
|
|
+ 'in,'.join(map(str.strip, margin_args)) + 'in'
|
|
)
|
|
add_or_update_one_cmd_arg(crop_margin_arg_name, arg)
|
|
else:
|
|
remove_one_cmd_arg(crop_margin_arg_name)
|
|
|
|
marginCheckButton = Checkbutton(
|
|
parameters_frame,
|
|
text='Crop Margins (in)',
|
|
variable=isCropMargin,
|
|
command=on_command_and_validate_crop_margin_cb,
|
|
)
|
|
marginCheckButton.grid(
|
|
column=0,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
para_frame_row_num += 1
|
|
|
|
cropPageRangeTextLabel = Label(parameters_frame, text=' Page Range')
|
|
cropPageRangeTextLabel.grid(
|
|
column=0,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
cropPageRangeEntry = Entry(
|
|
parameters_frame,
|
|
textvariable=strvarCropPageRange,
|
|
validate='focusout',
|
|
validatecommand=on_command_and_validate_crop_margin_cb,
|
|
)
|
|
cropPageRangeEntry.grid(
|
|
column=1,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
para_frame_row_num += 1
|
|
|
|
leftMarginTextLabel = Label(parameters_frame, text=' Left Margin')
|
|
leftMarginTextLabel.grid(
|
|
column=0,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
leftMarginSpinBox = Spinbox(
|
|
parameters_frame,
|
|
from_=0,
|
|
to=100,
|
|
increment=0.01,
|
|
# state='readonly',
|
|
textvariable=strvarLeftMargin,
|
|
command=on_command_and_validate_crop_margin_cb,
|
|
)
|
|
leftMarginSpinBox.grid(
|
|
column=1,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
para_frame_row_num += 1
|
|
|
|
topMarginTextLabel = Label(parameters_frame, text=' Top Margin')
|
|
topMarginTextLabel.grid(
|
|
column=0,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
topMarginSpinBox = Spinbox(
|
|
parameters_frame,
|
|
from_=0,
|
|
to=100,
|
|
increment=0.01,
|
|
# state='readonly',
|
|
textvariable=strvarTopMargin,
|
|
command=on_command_and_validate_crop_margin_cb,
|
|
)
|
|
topMarginSpinBox.grid(
|
|
column=1,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
para_frame_row_num += 1
|
|
|
|
rightMarginTextLabel = Label(parameters_frame, text=' Width')
|
|
rightMarginTextLabel.grid(
|
|
column=0,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
rightMarginSpinBox = Spinbox(
|
|
parameters_frame,
|
|
from_=0,
|
|
to=100,
|
|
increment=0.01,
|
|
# state='readonly',
|
|
textvariable=strvarRightMargin,
|
|
command=on_command_and_validate_crop_margin_cb,
|
|
)
|
|
rightMarginSpinBox.grid(
|
|
column=1,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
para_frame_row_num += 1
|
|
|
|
bottomMarginTextLabel = Label(parameters_frame, text=' Height')
|
|
bottomMarginTextLabel.grid(
|
|
column=0,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
bottomMarginSpinBox = Spinbox(
|
|
parameters_frame,
|
|
from_=0,
|
|
to=100,
|
|
increment=0.01,
|
|
# state='readonly',
|
|
textvariable=strvarBottomMargin,
|
|
command=on_command_and_validate_crop_margin_cb,
|
|
)
|
|
bottomMarginSpinBox.grid(
|
|
column=1,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
para_frame_row_num += 1
|
|
|
|
|
|
def on_command_dpi_cb():
|
|
if isDPI.get():
|
|
arg = dpi_arg_name + ' ' + strvarDPI.get().strip()
|
|
add_or_update_one_cmd_arg(dpi_arg_name, arg)
|
|
else:
|
|
remove_one_cmd_arg(dpi_arg_name)
|
|
|
|
dpiCheckButton = Checkbutton(
|
|
parameters_frame,
|
|
text='DPI',
|
|
variable=isDPI,
|
|
command=on_command_dpi_cb,
|
|
)
|
|
dpiCheckButton.grid(
|
|
column=0,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
dpiSpinBox = Spinbox(
|
|
parameters_frame,
|
|
from_=0,
|
|
to=1000,
|
|
increment=1,
|
|
# state='readonly',
|
|
textvariable=strvarDPI,
|
|
command=on_command_dpi_cb,
|
|
)
|
|
dpiSpinBox.grid(
|
|
column=1,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
para_frame_row_num += 1
|
|
|
|
|
|
def validate_and_update_page_nums():
|
|
if (len(strvarPageNums.get().strip()) > 0 and
|
|
not check_page_nums(strvarPageNums.get().strip())):
|
|
remove_one_cmd_arg(page_num_arg_name)
|
|
strvarPageNums.set('')
|
|
|
|
tkinter.messagebox.showerror(
|
|
message='Invalide Page Argument! Should be like 2-5e,3-7o,9-',
|
|
)
|
|
|
|
return FALSE
|
|
|
|
if len(strvarPageNums.get().strip()) > 0:
|
|
arg = page_num_arg_name + ' ' + strvarPageNums.get().strip()
|
|
add_or_update_one_cmd_arg(page_num_arg_name, arg)
|
|
else:
|
|
remove_one_cmd_arg(page_num_arg_name)
|
|
|
|
return TRUE
|
|
|
|
pageNumTextLabel = Label(
|
|
parameters_frame,
|
|
text='Pages to Convert',
|
|
)
|
|
pageNumTextLabel.grid(
|
|
column=0,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
|
|
def on_validate_page_nums_cb():
|
|
validate_and_update_page_nums()
|
|
|
|
pageNumEntry = Entry(
|
|
parameters_frame,
|
|
textvariable=strvarPageNums,
|
|
validate='focusout',
|
|
validatecommand=on_validate_page_nums_cb,
|
|
)
|
|
pageNumEntry.grid(
|
|
column=1,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
fixed_font_size_arg_name = '-fs' # -fs 0/-fs <font size>[+]
|
|
ocr_arg_name = '-ocr' # -ocr-/-ocr t
|
|
ocr_cpu_arg_name = '-nt' # -nt -50/-nt <percentage>
|
|
landscape_arg_name = '-ls' # -ls[-][pagelist]
|
|
linebreak_arg_name = '-ws' # -ws <spacing>
|
|
|
|
isFixedFontSize = BooleanVar()
|
|
isOCR = BooleanVar()
|
|
isLandscape = BooleanVar()
|
|
isLinebreak = BooleanVar() # -ws 0.01~10
|
|
|
|
strvarFixedFontSize = StringVar()
|
|
strvarOcrCpuPercentage = StringVar()
|
|
strvarLandscapePages = StringVar() # 1,3,5-10
|
|
strvarLinebreakSpace = StringVar()
|
|
|
|
# checkbox with value options
|
|
para_frame_row_num += 1
|
|
|
|
|
|
def on_command_fixed_font_size_cb():
|
|
if isFixedFontSize.get():
|
|
arg = (
|
|
fixed_font_size_arg_name + ' ' +
|
|
strvarFixedFontSize.get().strip()
|
|
)
|
|
add_or_update_one_cmd_arg(
|
|
fixed_font_size_arg_name,
|
|
arg,
|
|
)
|
|
else:
|
|
remove_one_cmd_arg(fixed_font_size_arg_name)
|
|
|
|
fontSizeCheckButton = Checkbutton(
|
|
parameters_frame,
|
|
text='Fixed Output Font Size',
|
|
variable=isFixedFontSize,
|
|
command=on_command_fixed_font_size_cb,
|
|
)
|
|
fontSizeCheckButton.grid(
|
|
column=0,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
fontSizeSpinBox = Spinbox(
|
|
parameters_frame,
|
|
from_=0,
|
|
to=100,
|
|
increment=1,
|
|
state='readonly',
|
|
textvariable=strvarFixedFontSize,
|
|
command=on_command_fixed_font_size_cb,
|
|
)
|
|
fontSizeSpinBox.grid(
|
|
column=1,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
para_frame_row_num += 1
|
|
|
|
|
|
def on_command_ocr_and_cpu_cb():
|
|
if isOCR.get():
|
|
# ocr conflicts with native pdf
|
|
isNativePdf.set(FALSE)
|
|
remove_one_cmd_arg(native_pdf_arg_name)
|
|
|
|
ocr_arg = ocr_arg_name
|
|
add_or_update_one_cmd_arg(ocr_arg_name, ocr_arg)
|
|
|
|
# negtive integer means percentage
|
|
ocr_cpu_arg = (
|
|
ocr_cpu_arg_name + '-' +
|
|
strvarOcrCpuPercentage.get().strip()
|
|
)
|
|
add_or_update_one_cmd_arg(
|
|
ocr_cpu_arg_name,
|
|
ocr_cpu_arg,
|
|
)
|
|
else:
|
|
remove_one_cmd_arg(ocr_arg_name)
|
|
remove_one_cmd_arg(ocr_cpu_arg_name)
|
|
|
|
ocrCheckButton = Checkbutton(
|
|
parameters_frame,
|
|
text='OCR (Tesseract) and CPU %',
|
|
variable=isOCR,
|
|
command=on_command_ocr_and_cpu_cb,
|
|
)
|
|
ocrCheckButton.grid(
|
|
column=0,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
ocrCpuSpinBox = Spinbox(
|
|
parameters_frame,
|
|
from_=0,
|
|
to=100,
|
|
increment=1,
|
|
state='readonly',
|
|
textvariable=strvarOcrCpuPercentage,
|
|
command=on_command_ocr_and_cpu_cb,
|
|
)
|
|
ocrCpuSpinBox.grid(
|
|
column=1,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
para_frame_row_num += 1
|
|
|
|
|
|
def on_command_and_validate_landscape_cb():
|
|
if (len(strvarLandscapePages.get().strip()) > 0 and
|
|
not check_page_nums(strvarLandscapePages.get().strip())):
|
|
remove_one_cmd_arg(landscape_arg_name)
|
|
strvarLandscapePages.set('')
|
|
|
|
tkinter.messagebox.showerror(
|
|
message='Invalide Landscape Page Argument!',
|
|
)
|
|
|
|
return FALSE
|
|
|
|
if isLandscape.get():
|
|
arg = '-ls'
|
|
if len(strvarLandscapePages.get().strip()) > 0:
|
|
# no space between -ls and page numbers
|
|
arg += strvarLandscapePages.get()
|
|
|
|
add_or_update_one_cmd_arg(landscape_arg_name, arg.strip())
|
|
else:
|
|
remove_one_cmd_arg(landscape_arg_name)
|
|
|
|
return TRUE
|
|
|
|
landscapeCheckButton = Checkbutton(
|
|
parameters_frame,
|
|
text='Output in Landscape',
|
|
variable=isLandscape,
|
|
command=on_command_and_validate_landscape_cb,
|
|
)
|
|
landscapeCheckButton.grid(
|
|
column=0,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
landscapePageNumEntry = Entry(
|
|
parameters_frame,
|
|
textvariable=strvarLandscapePages,
|
|
validate='focusout',
|
|
validatecommand=on_command_and_validate_landscape_cb,
|
|
)
|
|
landscapePageNumEntry.grid(
|
|
column=1,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
para_frame_row_num += 1
|
|
|
|
|
|
def on_command_line_break_cb():
|
|
if isLinebreak.get():
|
|
arg = (
|
|
linebreak_arg_name + ' ' +
|
|
strvarLinebreakSpace.get().strip()
|
|
)
|
|
add_or_update_one_cmd_arg(linebreak_arg_name, arg)
|
|
else:
|
|
remove_one_cmd_arg(linebreak_arg_name)
|
|
|
|
lineBreakCheckButton = Checkbutton(
|
|
parameters_frame,
|
|
text='Smart Line Breaks',
|
|
variable=isLinebreak,
|
|
command=on_command_line_break_cb,
|
|
)
|
|
lineBreakCheckButton.grid(
|
|
column=0,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
lineBreakSpinBox = Spinbox(
|
|
parameters_frame,
|
|
from_=0.01,
|
|
to=2.00,
|
|
increment=0.01,
|
|
state='readonly',
|
|
textvariable=strvarLinebreakSpace,
|
|
command=on_command_line_break_cb,
|
|
)
|
|
lineBreakSpinBox.grid(
|
|
column=1,
|
|
row=para_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
# right side of conversion tab
|
|
conversion_tab_right_part_column_num = 1
|
|
conversion_tab_right_part_row_num = -1
|
|
|
|
|
|
# ############################################################################################### #
|
|
# OPTIONS FRAME
|
|
# ############################################################################################### #
|
|
conversion_tab_right_part_row_num += 1
|
|
|
|
auto_straignten_arg_name = '-as' # -as-/-as
|
|
break_page_avoid_overlap_arg_name = '-bp' # -bp-/-bp
|
|
color_output_arg_name = '-c' # -c-/-c
|
|
native_pdf_arg_name = '-n' # -n-/-n
|
|
right_to_left_arg_name = '-r' # -r-/-r
|
|
post_gs_arg_name = '-ppgs' # -ppgs-/-ppgs
|
|
marked_source_arg_name = '-sm' # -sm-/-sm
|
|
reflow_text_arg_name = '-wrap' # -wrap+/-wrap-
|
|
erase_vertical_line_arg_name = '-evl' # -evl 0/-evl 1
|
|
erase_horizontal_line_arg_name = '-ehl' # -ehl 0/-ehl 1
|
|
fast_preview_arg_name = '-rt' # -rt /-rt 0
|
|
ign_small_defects_arg_name = '-de' # -de 1.0/-de 1.5
|
|
auto_crop_arg_name = '-ac' # -ac-/-ac
|
|
|
|
isAutoStraighten = BooleanVar()
|
|
isBreakPage = BooleanVar()
|
|
isColorOutput = BooleanVar()
|
|
isNativePdf = BooleanVar()
|
|
isRight2Left = BooleanVar()
|
|
isPostGs = BooleanVar()
|
|
isMarkedSrc = BooleanVar()
|
|
isReflowText = BooleanVar()
|
|
isEraseVerticalLine = BooleanVar()
|
|
isEraseHorizontalLine = BooleanVar()
|
|
isFastPreview = BooleanVar()
|
|
isAvoidOverlap = BooleanVar()
|
|
isIgnSmallDefects = BooleanVar()
|
|
isAutoCrop = BooleanVar()
|
|
|
|
options_frame = Labelframe(
|
|
conversion_tab,
|
|
text='Options',
|
|
)
|
|
options_frame.grid(
|
|
column=conversion_tab_right_part_column_num,
|
|
row=conversion_tab_right_part_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
option_frame_left_part_col_num = 0
|
|
option_frame_row_num = 0
|
|
|
|
|
|
def on_command_auto_straighten_cb():
|
|
if isAutoStraighten.get():
|
|
arg = auto_straignten_arg_name
|
|
add_or_update_one_cmd_arg(auto_straignten_arg_name, arg)
|
|
else:
|
|
remove_one_cmd_arg(auto_straignten_arg_name)
|
|
|
|
|
|
opt1 = Checkbutton(
|
|
options_frame,
|
|
text='Autostraighten',
|
|
variable=isAutoStraighten,
|
|
command=on_command_auto_straighten_cb,
|
|
)
|
|
opt1.grid(
|
|
column=option_frame_left_part_col_num,
|
|
row=option_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
option_frame_row_num += 1
|
|
|
|
|
|
def on_command_break_page_cb():
|
|
if isBreakPage.get():
|
|
# break page conflicts with avoid overlap since they are both -bp flag
|
|
isAvoidOverlap.set(FALSE)
|
|
remove_one_cmd_arg(break_page_avoid_overlap_arg_name)
|
|
|
|
arg = break_page_avoid_overlap_arg_name
|
|
add_or_update_one_cmd_arg(
|
|
break_page_avoid_overlap_arg_name,
|
|
arg,
|
|
)
|
|
else:
|
|
remove_one_cmd_arg(break_page_avoid_overlap_arg_name)
|
|
|
|
opt2 = Checkbutton(
|
|
options_frame,
|
|
text='Break After Each Source Page',
|
|
variable=isBreakPage,
|
|
command=on_command_break_page_cb,
|
|
)
|
|
opt2.grid(
|
|
column=option_frame_left_part_col_num,
|
|
row=option_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
option_frame_row_num += 1
|
|
|
|
|
|
def on_command_color_output_cb():
|
|
if isColorOutput.get():
|
|
arg = color_output_arg_name
|
|
add_or_update_one_cmd_arg(color_output_arg_name, arg)
|
|
else:
|
|
remove_one_cmd_arg(color_output_arg_name)
|
|
|
|
opt3 = Checkbutton(
|
|
options_frame,
|
|
text='Color Output',
|
|
variable=isColorOutput,
|
|
command=on_command_color_output_cb,
|
|
)
|
|
opt3.grid(
|
|
column=option_frame_left_part_col_num,
|
|
row=option_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
option_frame_row_num += 1
|
|
|
|
|
|
def on_command_native_pdf_cb():
|
|
if isNativePdf.get():
|
|
# native pdf conflicts with ocr and reflow text
|
|
isOCR.set(FALSE)
|
|
remove_one_cmd_arg(ocr_arg_name)
|
|
remove_one_cmd_arg(ocr_cpu_arg_name)
|
|
|
|
isReflowText.set(FALSE)
|
|
remove_one_cmd_arg(reflow_text_arg_name)
|
|
|
|
arg = native_pdf_arg_name
|
|
add_or_update_one_cmd_arg(native_pdf_arg_name, arg)
|
|
else:
|
|
remove_one_cmd_arg(native_pdf_arg_name)
|
|
|
|
opt4 = Checkbutton(
|
|
options_frame,
|
|
text='Native PDF Output',
|
|
variable=isNativePdf,
|
|
command=on_command_native_pdf_cb,
|
|
)
|
|
opt4.grid(
|
|
column=option_frame_left_part_col_num,
|
|
row=option_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
option_frame_row_num += 1
|
|
|
|
|
|
def on_command_right_to_left_cb():
|
|
if isRight2Left.get():
|
|
arg = right_to_left_arg_name
|
|
add_or_update_one_cmd_arg(right_to_left_arg_name, arg)
|
|
else:
|
|
remove_one_cmd_arg(right_to_left_arg_name)
|
|
|
|
opt5 = Checkbutton(
|
|
options_frame,
|
|
text='Right-to-Left Text',
|
|
variable=isRight2Left,
|
|
command=on_command_right_to_left_cb,
|
|
)
|
|
opt5.grid(
|
|
column=option_frame_left_part_col_num,
|
|
row=option_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
option_frame_row_num += 1
|
|
|
|
|
|
def on_command_post_gs_cb():
|
|
if isPostGs.get():
|
|
arg = post_gs_arg_name
|
|
add_or_update_one_cmd_arg(post_gs_arg_name, arg)
|
|
else:
|
|
remove_one_cmd_arg(post_gs_arg_name)
|
|
|
|
opt6 = Checkbutton(
|
|
options_frame,
|
|
text='Post Process w/GhostScript',
|
|
variable=isPostGs,
|
|
command=on_command_post_gs_cb,
|
|
)
|
|
opt6.grid(
|
|
column=option_frame_left_part_col_num,
|
|
row=option_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
option_frame_row_num += 1
|
|
|
|
|
|
def on_command_marked_src_cb():
|
|
if isMarkedSrc.get():
|
|
arg = marked_source_arg_name
|
|
add_or_update_one_cmd_arg(
|
|
marked_source_arg_name,
|
|
arg,
|
|
)
|
|
else:
|
|
remove_one_cmd_arg(marked_source_arg_name)
|
|
|
|
opt7 = Checkbutton(
|
|
options_frame,
|
|
text='Generate Marked-up Source',
|
|
variable=isMarkedSrc,
|
|
command=on_command_marked_src_cb,
|
|
)
|
|
opt7.grid(
|
|
column=option_frame_left_part_col_num,
|
|
row=option_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
option_frace_right_part_col_num = 1
|
|
option_frame_row_num = 0
|
|
|
|
|
|
def on_command_reflow_text_cb():
|
|
if isReflowText.get():
|
|
# reflow text conflicts with native pdf
|
|
isNativePdf.set(FALSE)
|
|
remove_one_cmd_arg(native_pdf_arg_name)
|
|
|
|
arg = reflow_text_arg_name + '+'
|
|
add_or_update_one_cmd_arg(
|
|
reflow_text_arg_name,
|
|
arg,
|
|
)
|
|
else:
|
|
remove_one_cmd_arg(reflow_text_arg_name)
|
|
|
|
opt8 = Checkbutton(
|
|
options_frame,
|
|
text='Re-flow Text',
|
|
variable=isReflowText,
|
|
command=on_command_reflow_text_cb,
|
|
)
|
|
opt8.grid(
|
|
column=option_frace_right_part_col_num,
|
|
row=option_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
option_frame_row_num += 1
|
|
|
|
|
|
def on_command_erase_vertical_line_cb():
|
|
if isEraseVerticalLine.get():
|
|
arg = erase_vertical_line_arg_name + ' 1'
|
|
add_or_update_one_cmd_arg(
|
|
erase_vertical_line_arg_name,
|
|
arg,
|
|
)
|
|
else:
|
|
remove_one_cmd_arg(erase_vertical_line_arg_name)
|
|
|
|
opt9 = Checkbutton(
|
|
options_frame,
|
|
text='Erase Vertical Lines',
|
|
variable=isEraseVerticalLine,
|
|
command=on_command_erase_vertical_line_cb,
|
|
)
|
|
opt9.grid(
|
|
column=option_frace_right_part_col_num,
|
|
row=option_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
option_frame_row_num += 1
|
|
|
|
|
|
def on_command_erase_horizontal_line_cb():
|
|
if isEraseHorizontalLine.get():
|
|
arg = erase_horizontal_line_arg_name + ' 1'
|
|
add_or_update_one_cmd_arg(
|
|
erase_horizontal_line_arg_name,
|
|
arg,
|
|
)
|
|
else:
|
|
remove_one_cmd_arg(erase_horizontal_line_arg_name)
|
|
|
|
opt14 = Checkbutton(
|
|
options_frame,
|
|
text='Erase Horizontal Lines',
|
|
variable=isEraseHorizontalLine,
|
|
command=on_command_erase_horizontal_line_cb,
|
|
)
|
|
opt14.grid(
|
|
column=option_frace_right_part_col_num,
|
|
row=option_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
option_frame_row_num += 1
|
|
|
|
|
|
def on_command_fast_preview_cb():
|
|
if isFastPreview.get():
|
|
arg = fast_preview_arg_name + ' 0'
|
|
add_or_update_one_cmd_arg(fast_preview_arg_name, arg)
|
|
else:
|
|
remove_one_cmd_arg(fast_preview_arg_name)
|
|
|
|
opt10 = Checkbutton(
|
|
options_frame,
|
|
text='Fast Preview',
|
|
variable=isFastPreview,
|
|
command=on_command_fast_preview_cb,
|
|
)
|
|
opt10.grid(
|
|
column=option_frace_right_part_col_num,
|
|
row=option_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
option_frame_row_num += 1
|
|
|
|
|
|
def on_command_avoid_text_selection_overlap_cb():
|
|
if isAvoidOverlap.get():
|
|
# avoid overlap conflicts with break page since they are both -bp flag
|
|
isBreakPage.set(FALSE)
|
|
remove_one_cmd_arg(break_page_avoid_overlap_arg_name)
|
|
|
|
arg = break_page_avoid_overlap_arg_name + ' m'
|
|
add_or_update_one_cmd_arg(
|
|
break_page_avoid_overlap_arg_name,
|
|
arg,
|
|
)
|
|
else:
|
|
remove_one_cmd_arg(break_page_avoid_overlap_arg_name)
|
|
|
|
opt11 = Checkbutton(
|
|
options_frame,
|
|
text='Avoid Text Selection Overlap',
|
|
variable=isAvoidOverlap,
|
|
command=on_command_avoid_text_selection_overlap_cb,
|
|
)
|
|
opt11.grid(
|
|
column=option_frace_right_part_col_num,
|
|
row=option_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
option_frame_row_num += 1
|
|
|
|
|
|
def on_command_ign_small_defect_cb():
|
|
if isIgnSmallDefects.get():
|
|
arg = (
|
|
ign_small_defects_arg_name + ' 1.5'
|
|
)
|
|
add_or_update_one_cmd_arg(
|
|
ign_small_defects_arg_name,
|
|
arg,
|
|
)
|
|
else:
|
|
remove_one_cmd_arg(ign_small_defects_arg_name)
|
|
|
|
opt12 = Checkbutton(
|
|
options_frame,
|
|
text='Ignore Small Defects',
|
|
variable=isIgnSmallDefects,
|
|
command=on_command_ign_small_defect_cb,
|
|
)
|
|
opt12.grid(
|
|
column=option_frace_right_part_col_num,
|
|
row=option_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
option_frame_row_num += 1
|
|
|
|
|
|
def on_command_auto_crop_cb():
|
|
if isAutoCrop.get():
|
|
arg = auto_crop_arg_name
|
|
add_or_update_one_cmd_arg(auto_crop_arg_name, arg)
|
|
else:
|
|
remove_one_cmd_arg(auto_crop_arg_name)
|
|
|
|
opt13 = Checkbutton(
|
|
options_frame,
|
|
text='Auto-Crop',
|
|
variable=isAutoCrop,
|
|
command=on_command_auto_crop_cb,
|
|
)
|
|
opt13.grid(
|
|
column=option_frace_right_part_col_num,
|
|
row=option_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
option_frame_row_num += 1
|
|
|
|
|
|
# ############################################################################################### #
|
|
# PREVIEW AND CONVERT FRAME
|
|
# ############################################################################################### #
|
|
conversion_tab_right_part_row_num += 1
|
|
|
|
preview_output_arg_name = '-bmp'
|
|
preview_image_path = './k2pdfopt_out.png'
|
|
current_preview_page_index = 1
|
|
|
|
# global variable to hold opened preview image to prevent gc collecting it
|
|
preview_img = None
|
|
canvas_image_tag = None
|
|
|
|
strvarCurrentPreviewPageNum = StringVar()
|
|
|
|
def remove_preview_img_and_clear_canvas():
|
|
global canvas_image_tag
|
|
global strvarCurrentPreviewPageNum
|
|
|
|
if os.path.exists(preview_image_path):
|
|
os.remove(preview_image_path)
|
|
|
|
previewImageCanvas.delete(ALL)
|
|
canvas_image_tag = None
|
|
|
|
|
|
def load_image_to_canvas(photo_img, canvas):
|
|
load_image_to_canvas(preview_img, previewImageCanvas)
|
|
|
|
|
|
def load_preview_image(img_path, preview_page_index):
|
|
# PhotoImage must be global var to prevent gc collect it
|
|
global preview_img
|
|
global previewImageCanvas
|
|
|
|
if os.path.exists(img_path):
|
|
preview_img = PhotoImage(file=img_path)
|
|
|
|
canvas_image_tag = previewImageCanvas.create_image(
|
|
(0, 0),
|
|
anchor=NW,
|
|
image=preview_img,
|
|
tags='preview',
|
|
)
|
|
|
|
(left_pos, top_pos, right_pos, bottom_pos) = (
|
|
0,
|
|
0,
|
|
preview_img.width(),
|
|
preview_img.height(),
|
|
)
|
|
previewImageCanvas.config(
|
|
scrollregion=(left_pos, top_pos, right_pos, bottom_pos),
|
|
)
|
|
# canvas.scale('preview', 0, 0, 0.1, 0.1)
|
|
strvarCurrentPreviewPageNum.set('Page: ' + str(preview_page_index))
|
|
else:
|
|
strvarCurrentPreviewPageNum.set('No Page ' + str(preview_page_index))
|
|
|
|
|
|
def generate_one_preview_image(preview_page_index):
|
|
global background_future
|
|
|
|
if not check_pdf_conversion_done():
|
|
return
|
|
|
|
if not os.path.exists(strvarFilePath.get().strip()):
|
|
tkinter.messagebox.showerror(
|
|
message=(
|
|
"Failed to Find Input PDF File to convert for Preview: %s"
|
|
%
|
|
strvarFilePath.get().strip()
|
|
),
|
|
)
|
|
return
|
|
|
|
remove_preview_img_and_clear_canvas()
|
|
|
|
(base_path, file_ext) = os.path.splitext(strvarFilePath.get().strip())
|
|
output_arg = ' '.join([preview_output_arg_name, str(preview_page_index)])
|
|
background_future = convert_pdf_file(output_arg)
|
|
strvarCurrentPreviewPageNum.set('Preview Generating...')
|
|
|
|
def preview_image_future_cb(bgf):
|
|
load_preview_image(preview_image_path, preview_page_index)
|
|
log_string(
|
|
"Preview generation for page %d finished" %
|
|
preview_page_index
|
|
)
|
|
|
|
background_future.add_done_callback(preview_image_future_cb)
|
|
|
|
preview_frame = Labelframe(conversion_tab, text='Preview & Convert')
|
|
preview_frame.grid(
|
|
column=conversion_tab_right_part_column_num,
|
|
row=conversion_tab_right_part_row_num,
|
|
rowspan=3,
|
|
sticky=N+S+E+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
preview_frame_row_num = 0
|
|
|
|
|
|
def on_command_restore_default_cb():
|
|
restore_default_values()
|
|
|
|
reset_button = Button(
|
|
preview_frame,
|
|
text='Reset default',
|
|
command=on_command_restore_default_cb,
|
|
)
|
|
reset_button.grid(
|
|
column=0,
|
|
row=preview_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
|
|
def on_command_abort_conversion_cb():
|
|
global background_future
|
|
global background_process
|
|
|
|
if background_future is not None:
|
|
background_future.cancel()
|
|
|
|
if (background_process is not None and
|
|
background_process.returncode is None):
|
|
background_process.terminate()
|
|
|
|
cancel_button = Button(
|
|
preview_frame,
|
|
text='Abort',
|
|
command=on_command_abort_conversion_cb,
|
|
)
|
|
cancel_button.grid(
|
|
column=1,
|
|
row=preview_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
|
|
def on_command_convert_pdf_cb():
|
|
if not check_pdf_conversion_done():
|
|
return
|
|
|
|
global background_future
|
|
|
|
pdf_output_arg = output_path_arg_name + ' %s' + output_pdf_suffix
|
|
background_future = convert_pdf_file(pdf_output_arg)
|
|
|
|
convert_button = Button(
|
|
preview_frame,
|
|
text='Convert',
|
|
command=on_command_convert_pdf_cb,
|
|
)
|
|
convert_button.grid(
|
|
column=2,
|
|
row=preview_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
preview_frame_row_num += 1
|
|
|
|
current_preview_page_num_entry = Entry(
|
|
preview_frame,
|
|
state='readonly',
|
|
textvariable=strvarCurrentPreviewPageNum)
|
|
current_preview_page_num_entry.grid(
|
|
column=0,
|
|
row=preview_frame_row_num,
|
|
columnspan=2,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
|
|
def on_command_ten_page_up_cb():
|
|
global current_preview_page_index
|
|
current_preview_page_index -= 10
|
|
if current_preview_page_index < 1:
|
|
current_preview_page_index = 1
|
|
generate_one_preview_image(current_preview_page_index)
|
|
|
|
preview_button = Button(
|
|
preview_frame,
|
|
text='Preview',
|
|
command=on_command_ten_page_up_cb,
|
|
)
|
|
preview_button.grid(
|
|
column=2,
|
|
row=preview_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
preview_frame_column_num = 0
|
|
preview_frame_row_num += 1
|
|
|
|
first_button = Button(
|
|
preview_frame,
|
|
text='<<',
|
|
command=on_command_ten_page_up_cb,
|
|
)
|
|
first_button.grid(
|
|
column=preview_frame_column_num,
|
|
row=preview_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
preview_frame_column_num += 1
|
|
|
|
|
|
def on_command_page_up_cb():
|
|
global current_preview_page_index
|
|
if current_preview_page_index > 1:
|
|
current_preview_page_index -= 1
|
|
generate_one_preview_image(current_preview_page_index)
|
|
|
|
previous_button = Button(
|
|
preview_frame,
|
|
text='<',
|
|
command=on_command_page_up_cb,
|
|
)
|
|
previous_button.grid(
|
|
column=preview_frame_column_num,
|
|
row=preview_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
preview_frame_column_num += 1
|
|
|
|
|
|
def on_command_page_down_cb():
|
|
global current_preview_page_index
|
|
current_preview_page_index += 1
|
|
generate_one_preview_image(current_preview_page_index)
|
|
|
|
next_button = Button(
|
|
preview_frame,
|
|
text='>',
|
|
command=on_command_page_down_cb,
|
|
)
|
|
next_button.grid(
|
|
column=preview_frame_column_num,
|
|
row=preview_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
preview_frame_column_num += 1
|
|
|
|
|
|
def on_command_ten_page_down_cb():
|
|
global current_preview_page_index
|
|
current_preview_page_index += 10
|
|
generate_one_preview_image(current_preview_page_index)
|
|
|
|
last_button = Button(
|
|
preview_frame,
|
|
text='>>',
|
|
command=on_command_ten_page_down_cb,
|
|
)
|
|
last_button.grid(
|
|
column=preview_frame_column_num,
|
|
row=preview_frame_row_num,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
preview_frame_column_num += 1
|
|
preview_frame_row_num += 1
|
|
|
|
xScrollBar = Scrollbar(preview_frame, orient=HORIZONTAL)
|
|
xScrollBar.grid(
|
|
column=0,
|
|
row=preview_frame_row_num+1,
|
|
columnspan=preview_frame_column_num,
|
|
sticky=E+W,
|
|
)
|
|
|
|
yScrollBar = Scrollbar(preview_frame)
|
|
yScrollBar.grid(
|
|
column=preview_frame_column_num,
|
|
row=preview_frame_row_num,
|
|
sticky=N+S,
|
|
)
|
|
|
|
previewImageCanvas = Canvas(
|
|
preview_frame,
|
|
bd=0,
|
|
xscrollcommand=xScrollBar.set,
|
|
yscrollcommand=yScrollBar.set,
|
|
)
|
|
previewImageCanvas.grid(
|
|
column=0,
|
|
row=preview_frame_row_num,
|
|
columnspan=preview_frame_column_num,
|
|
sticky=N+S+E+W,
|
|
)
|
|
|
|
xScrollBar.config(command=previewImageCanvas.xview)
|
|
yScrollBar.config(command=previewImageCanvas.yview)
|
|
|
|
conversion_tab.columnconfigure(
|
|
conversion_tab_right_part_column_num,
|
|
weight=1,
|
|
)
|
|
conversion_tab.rowconfigure(
|
|
conversion_tab_right_part_row_num,
|
|
weight=1,
|
|
)
|
|
preview_frame.columnconfigure(0, weight=1)
|
|
preview_frame.rowconfigure(preview_frame_row_num, weight=1)
|
|
|
|
|
|
def yscroll_canvas(event):
|
|
previewImageCanvas.yview_scroll(-1 * event.delta, 'units')
|
|
|
|
|
|
def xscroll_canvas(event):
|
|
previewImageCanvas.xview_scroll(-1 * event.delta, 'units')
|
|
|
|
previewImageCanvas.bind('<MouseWheel>', yscroll_canvas)
|
|
previewImageCanvas.bind("<Shift-MouseWheel>", xscroll_canvas)
|
|
|
|
preview_frame_row_num += 1
|
|
|
|
# collect all vars
|
|
|
|
bool_var_list = [
|
|
isColumnNum,
|
|
isResolutionMultipler,
|
|
isCropMargin,
|
|
isDPI,
|
|
isFixedFontSize,
|
|
isOCR,
|
|
isLandscape,
|
|
isLinebreak,
|
|
|
|
isAutoStraighten,
|
|
isBreakPage,
|
|
isColorOutput,
|
|
isNativePdf,
|
|
isRight2Left,
|
|
isPostGs,
|
|
isMarkedSrc,
|
|
isReflowText,
|
|
isEraseVerticalLine,
|
|
isEraseHorizontalLine,
|
|
isFastPreview,
|
|
isAvoidOverlap,
|
|
isIgnSmallDefects,
|
|
isAutoCrop,
|
|
]
|
|
|
|
string_var_list = [
|
|
strvarFilePath,
|
|
strvarDevice,
|
|
strvarConversionMode,
|
|
strvarScreenUnit,
|
|
strvarScreenWidth,
|
|
strvarScreenHeight,
|
|
|
|
strvarOutputFilePath,
|
|
strvarCmdArgs,
|
|
|
|
strvarColumnNum,
|
|
strvarResolutionMultiplier,
|
|
strvarCropPageRange,
|
|
strvarLeftMargin,
|
|
strvarRightMargin,
|
|
strvarTopMargin,
|
|
strvarBottomMargin,
|
|
strvarDPI,
|
|
strvarPageNums,
|
|
|
|
strvarFixedFontSize,
|
|
strvarOcrCpuPercentage,
|
|
strvarLandscapePages,
|
|
strvarLinebreakSpace,
|
|
|
|
strvarCurrentPreviewPageNum,
|
|
]
|
|
|
|
combo_box_list = [
|
|
deviceComboBox,
|
|
modeComboBox,
|
|
unitComboBox,
|
|
]
|
|
|
|
entry_list = [
|
|
inputPathEntry,
|
|
outputPathEntry,
|
|
cmdArgEntry,
|
|
pageNumEntry,
|
|
landscapePageNumEntry,
|
|
current_preview_page_num_entry,
|
|
]
|
|
|
|
default_var_map = {
|
|
device_arg_name: ['Kindle Paperwhite 3'],
|
|
screen_unit_prefix: ['Pixels'],
|
|
width_arg_name: ['1024'],
|
|
height_arg_name: ['768'],
|
|
conversion_mode_arg_name: ['Default'],
|
|
output_path_arg_name: [''],
|
|
|
|
column_num_arg_name: [FALSE, '2'],
|
|
resolution_multiplier_arg_name: [FALSE, '1.0'],
|
|
crop_margin_arg_name: [
|
|
FALSE,
|
|
'',
|
|
'0.00',
|
|
'0.00',
|
|
'0.00',
|
|
'0.00',
|
|
],
|
|
dpi_arg_name: [TRUE, '300'],
|
|
page_num_arg_name: [''],
|
|
fixed_font_size_arg_name: [FALSE, '12'],
|
|
ocr_arg_name: [FALSE, '50'],
|
|
ocr_cpu_arg_name: [FALSE, '50'],
|
|
landscape_arg_name: [FALSE, ''],
|
|
linebreak_arg_name: [TRUE, '0.200'],
|
|
|
|
auto_straignten_arg_name: [FALSE],
|
|
break_page_avoid_overlap_arg_name: [FALSE, FALSE],
|
|
color_output_arg_name: [FALSE],
|
|
native_pdf_arg_name: [FALSE],
|
|
right_to_left_arg_name: [FALSE],
|
|
post_gs_arg_name: [FALSE],
|
|
marked_source_arg_name: [TRUE],
|
|
reflow_text_arg_name: [TRUE],
|
|
erase_vertical_line_arg_name: [TRUE],
|
|
erase_horizontal_line_arg_name: [TRUE],
|
|
fast_preview_arg_name: [TRUE],
|
|
ign_small_defects_arg_name: [FALSE],
|
|
auto_crop_arg_name: [FALSE],
|
|
|
|
preview_output_arg_name: []
|
|
}
|
|
|
|
arg_var_map = {
|
|
device_arg_name: [strvarDevice],
|
|
screen_unit_prefix: [strvarScreenUnit],
|
|
width_arg_name: [strvarScreenWidth],
|
|
height_arg_name: [strvarScreenHeight],
|
|
conversion_mode_arg_name: [strvarConversionMode],
|
|
output_path_arg_name: [strvarOutputFilePath],
|
|
|
|
column_num_arg_name: [
|
|
isColumnNum,
|
|
strvarColumnNum,
|
|
],
|
|
resolution_multiplier_arg_name: [
|
|
isResolutionMultipler,
|
|
strvarResolutionMultiplier,
|
|
],
|
|
crop_margin_arg_name: [
|
|
isCropMargin,
|
|
strvarCropPageRange,
|
|
strvarLeftMargin,
|
|
strvarTopMargin,
|
|
strvarRightMargin,
|
|
strvarBottomMargin,
|
|
],
|
|
dpi_arg_name: [
|
|
isDPI,
|
|
strvarDPI,
|
|
],
|
|
page_num_arg_name: [
|
|
strvarPageNums,
|
|
],
|
|
|
|
fixed_font_size_arg_name: [
|
|
isFixedFontSize,
|
|
strvarFixedFontSize,
|
|
],
|
|
ocr_arg_name: [
|
|
isOCR,
|
|
strvarOcrCpuPercentage,
|
|
],
|
|
ocr_cpu_arg_name: [
|
|
isOCR,
|
|
strvarOcrCpuPercentage,
|
|
],
|
|
landscape_arg_name: [
|
|
isLandscape,
|
|
strvarLandscapePages,
|
|
],
|
|
linebreak_arg_name: [
|
|
isLinebreak,
|
|
strvarLinebreakSpace,
|
|
],
|
|
|
|
auto_straignten_arg_name: [isAutoStraighten],
|
|
break_page_avoid_overlap_arg_name: [isBreakPage, isAvoidOverlap],
|
|
color_output_arg_name: [isColorOutput],
|
|
native_pdf_arg_name: [isNativePdf],
|
|
right_to_left_arg_name: [isRight2Left],
|
|
post_gs_arg_name: [isPostGs],
|
|
marked_source_arg_name: [isMarkedSrc],
|
|
reflow_text_arg_name: [isReflowText],
|
|
erase_vertical_line_arg_name: [isEraseVerticalLine],
|
|
erase_horizontal_line_arg_name: [isEraseHorizontalLine],
|
|
fast_preview_arg_name: [isFastPreview],
|
|
# break_page_avoid_overlap_arg_name: []
|
|
ign_small_defects_arg_name: [isIgnSmallDefects],
|
|
auto_crop_arg_name: [isAutoCrop],
|
|
preview_output_arg_name: []
|
|
}
|
|
|
|
arg_cb_map = {
|
|
device_arg_name: on_bind_event_device_unit_cb,
|
|
width_arg_name: on_command_width_height_cb,
|
|
height_arg_name: on_command_width_height_cb,
|
|
conversion_mode_arg_name: on_bind_event_mode_cb,
|
|
output_path_arg_name: None,
|
|
|
|
column_num_arg_name: on_command_column_num_cb,
|
|
resolution_multiplier_arg_name: on_command_resolution_multipler_cb,
|
|
crop_margin_arg_name: on_command_and_validate_crop_margin_cb,
|
|
dpi_arg_name: on_command_dpi_cb,
|
|
page_num_arg_name: on_validate_page_nums_cb,
|
|
|
|
fixed_font_size_arg_name: on_command_fixed_font_size_cb,
|
|
ocr_arg_name: on_command_ocr_and_cpu_cb,
|
|
ocr_cpu_arg_name: on_command_ocr_and_cpu_cb,
|
|
landscape_arg_name: on_command_and_validate_landscape_cb,
|
|
linebreak_arg_name: on_command_line_break_cb,
|
|
|
|
auto_straignten_arg_name: on_command_auto_straighten_cb,
|
|
break_page_avoid_overlap_arg_name: on_command_break_page_cb,
|
|
color_output_arg_name: on_command_color_output_cb,
|
|
native_pdf_arg_name: on_command_native_pdf_cb,
|
|
right_to_left_arg_name: on_command_right_to_left_cb,
|
|
post_gs_arg_name: on_command_post_gs_cb,
|
|
marked_source_arg_name: on_command_marked_src_cb,
|
|
reflow_text_arg_name: on_command_reflow_text_cb,
|
|
erase_vertical_line_arg_name: on_command_erase_vertical_line_cb,
|
|
erase_horizontal_line_arg_name: on_command_erase_horizontal_line_cb,
|
|
fast_preview_arg_name: on_command_fast_preview_cb,
|
|
ign_small_defects_arg_name: on_command_ign_small_defect_cb,
|
|
auto_crop_arg_name: on_command_auto_crop_cb,
|
|
|
|
preview_output_arg_name: None
|
|
}
|
|
|
|
# k2pdfopt stdout
|
|
|
|
output_frame = Labelframe(log_tab, text='k2pdfopt STDOUT')
|
|
output_frame.pack(expand=1, fill='both')
|
|
|
|
def on_command_clear_log_cb():
|
|
clear_logs()
|
|
|
|
clearButton = Button(
|
|
output_frame,
|
|
text='Clear',
|
|
command=on_command_clear_log_cb)
|
|
clearButton.grid(
|
|
column=0,
|
|
row=0,
|
|
sticky=N+W,
|
|
pady=0,
|
|
padx=5,
|
|
)
|
|
|
|
stdoutText = scrltxt.ScrolledText(
|
|
output_frame,
|
|
state=DISABLED,
|
|
wrap='word',
|
|
)
|
|
stdoutText.grid(column=0, row=1, sticky=N+S+E+W)
|
|
output_frame.columnconfigure(0, weight=1)
|
|
output_frame.rowconfigure(1, weight=1)
|
|
# stdoutText.pack(expand=1, fill='both')
|
|
|
|
# initialization
|
|
|
|
def initialize():
|
|
check_k2pdfopt_path_exists()
|
|
|
|
if not load_custom_preset():
|
|
restore_default_values()
|
|
|
|
pwd = os.getcwd()
|
|
log_string('Current directory: ' + pwd)
|
|
|
|
initialize()
|
|
|
|
# start TclTk loop
|
|
|
|
root.mainloop()
|