Skip to content

Commit

Permalink
Finishing touches for first release
Browse files Browse the repository at this point in the history
  • Loading branch information
teschmitt committed May 12, 2018
1 parent 2b8e85a commit 6b8adc8
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 46 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
*.pdf

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
20 changes: 15 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# PyPDF Builder

A cross-platform clone of [PDFTK Builder](http://angusj.com/pdftkb/) written in Python. Yes, Python!
A cross-platform utility to join, split, stamp, and rotate PDFs written in Python. Yes, Python!

The project's goal is a simple, end-user friendly GUI for the [PyPDF2](https://github.com/mstamy2/PyPDF2) package that can join, split, stamp/number, and rotate PDFs.
This project is inspired by Angus Johnson's [PDFTK Builder](http://angusj.com/pdftkb/). Its goal is a GUI that builds on [PyPDF2](https://github.com/mstamy2/PyPDF2) as well as other PDF related libraries and offers a unified and simple experience for end-users.

![](screenshot.png)

Expand All @@ -12,10 +12,10 @@ Grab a copy of `virtualenv` or `virtualenvwrapper` and set up a virtual environm

```
git clone https://github.com/mrgnth/PyPDF-Builder.git
pip install -r requirements
pip install -r requirements.txt
```

These instructions will get you a copy of the project up and running on your local machine for development ~~and testing~~ purposes. ~~See deployment for notes on how to deploy the project on a live system.~~
These instructions will get you a copy of the project up and running on your local machine for development purposes.

### Prerequisites

Expand All @@ -35,7 +35,16 @@ Python 3.6 was used in development… I haven't checked for compatibility with l

## Deployment

Distributable application for Windows, Linux and Mac OS using pyInstaller or similiar tool. This isn't all too clear yet.
Distributable application for Windows, Linux and Mac OS using [PyInstaller](https://pyinstaller.readthedocs.io/en/stable/):

```
pyinstaller --onefile --clean --windowed --add-data="mainwindow.ui:." \
--hidden-import="pygubu.builder.ttkstdwidgets" \
--hidden-import="pygubu.builder.widgets.dialog" \
pypdfbuilder.py
```

Subsequent builds can be managed by editing the `.spec` file created by the first build and then simply running `pyinstaller pypdfbuilder.spec` to build the executable.

Long term: Inclusion in Debian repos for direct installation on end-user systems.

Expand All @@ -46,6 +55,7 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
## Acknowledgments

* [Matthew Stamy](https://github.com/mstamy2): Creator and current maintainer of the PyPDF2 Python package
* Angus Johnson: Creator of [PDFTK Builder](http://angusj.com/pdftkb/)

## To Do

Expand Down
4 changes: 2 additions & 2 deletions mainwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@
<child>
<object class="ttk.Button" id="RotateSaveButton">
<property name="command">rotatetab_save_as</property>
<property name="text" translatable="yes">Save As…</property>
<property name="text" translatable="yes">Save As …</property>
<layout>
<property name="column">0</property>
<property name="padx">10</property>
Expand Down Expand Up @@ -763,7 +763,6 @@
</layout>
<child>
<object class="ttk.Label" id="StatusText">
<property name="text" translatable="yes">PyPDF v1.0</property>
<property name="textvariable">string:application_status_text</property>
<layout>
<property name="column">0</property>
Expand Down Expand Up @@ -908,6 +907,7 @@
</layout>
<child>
<object class="ttk.Checkbutton" id="UsePopplerCheckbutton_1">
<property name="state">disabled</property>
<property name="text" translatable="yes">Use Poppler PDF Tools if available</property>
<property name="variable">boolean:settings_use_poppler</property>
<layout>
Expand Down
85 changes: 47 additions & 38 deletions pypdfbuilder.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/python

import os
import sys
import appdirs
import json
from pathlib import Path as plPath
Expand All @@ -9,12 +10,18 @@

from tkinter import filedialog
from pygubu import Builder as pgBuilder
from pygubu.builder import ttkstdwidgets

# if dist fails to start because it's missing these, uncomment these two imports
# import pygubu.builder.ttkstdwidgets
# import pygubu.builder.widgets.dialog

from PyPDF2 import PdfFileMerger, PdfFileReader, PdfFileWriter

APPNAME = 'pypdfbuilder'
CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
# check to see if we're running from stand-alone one-file executable:
if hasattr(sys, '_MEIPASS'):
CURRENT_DIR = sys._MEIPASS
else:
CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))
USER_DIR = str(plPath.home())
CONFIG_DIR = appdirs.user_config_dir(APPNAME)
DATA_DIR = appdirs.user_data_dir(APPNAME)
Expand Down Expand Up @@ -185,7 +192,7 @@ def concat_filename(self, max_length=35):
'''
basename = os.path.basename(self.__filepath)
concat_filename = f'{basename[0:35]}'
concat_filename = f'{basename[0:max_length]}'
if len(basename) > max_length:
concat_filename += '…'
return concat_filename
Expand Down Expand Up @@ -513,17 +520,17 @@ def __init__(self):
self.builder = pgBuilder()
self.builder.add_from_file(os.path.join(CURRENT_DIR, 'mainwindow.ui'))

self.mainwindow = self.builder.get_object('MainWindow')
self.settings_dialog = self.builder.get_object('SettingsDialog', self.mainwindow)
self.notebook = self.builder.get_object('AppNotebook')
self.tabs = {
self.__mainwindow = self.builder.get_object('MainWindow')
self.__settings_dialog = self.builder.get_object('SettingsDialog', self.__mainwindow)
self.__notebook = self.builder.get_object('AppNotebook')
self.__tabs = {
'join': self.builder.get_object('JoinFrame'),
'split': self.builder.get_object('SplitFrame'),
'bg': self.builder.get_object('BgFrame'),
'rotate': self.builder.get_object('RotateFrame'),
}
self.mainmenu = self.builder.get_object('MainMenu')
self.mainwindow.config(menu=self.mainmenu)
self.__mainmenu = self.builder.get_object('MainMenu')
self.__mainwindow.config(menu=self.__mainmenu)
self.__status_text_variable = self.builder.get_variable('application_status_text')
self.__settings_use_poppler_variable = self.builder.get_variable('settings_use_poppler')
self.status_text = None
Expand All @@ -532,10 +539,12 @@ def __init__(self):
self.user_data = UserData()
self.settings_data = SettingsData()

self.jointab = JoinTabManager(self)
self.splittab = SplitTabManager(self)
self.bgtab = BgTabManager(self)
self.rotatetab = RotateTabManager(self)
self.__jointab = JoinTabManager(self)
self.__splittab = SplitTabManager(self)
self.__bgtab = BgTabManager(self)
self.__rotatetab = RotateTabManager(self)

self.status_text = DEFAULT_STATUS

@property
def status_text(self):
Expand All @@ -549,55 +558,55 @@ def status_text(self, val):
def select_tab_join(self, *args, **kwargs):
'''Gets called when menu item "View > Join Files" is selected.
Pops appropriate tab into view.'''
self.notebook.select(self.tabs['join'])
self.__notebook.select(self.__tabs['join'])

def select_tab_split(self, *args, **kwargs):
'''Gets called when menu item "View > Split File" is selected.
Pops appropriate tab into view.'''
self.notebook.select(self.tabs['split'])
self.__notebook.select(self.__tabs['split'])

def select_tab_bg(self, *args, **kwargs):
'''Gets called when menu item "View > Background/Stamp/Number" is selected.
Pops appropriate tab into view.'''
self.notebook.select(self.tabs['bg'])
self.__notebook.select(self.__tabs['bg'])

def select_tab_rotate(self, *args, **kwargs):
'''Gets called when menu item "View > Rotate Pages" is selected.
Pops appropriate tab into view.'''
self.notebook.select(self.tabs['rotate'])
self.__notebook.select(self.__tabs['rotate'])

def jointab_add_file(self):
self.jointab.add_file()
self.__jointab.add_file()

def jointab_on_file_select(self, event):
self.jointab.on_file_select(event)
self.__jointab.on_file_select(event)

def jointab_enter_page_selection(self, event):
self.jointab.enter_page_selection(event)
self.__jointab.enter_page_selection(event)

def jointab_save_as(self):
self.jointab.save_as()
self.__jointab.save_as()

def jointab_move_up(self):
self.jointab.move_up()
self.__jointab.move_up()

def jointab_move_down(self):
self.jointab.move_down()
self.__jointab.move_down()

def jointab_remove(self):
self.jointab.remove_file()
self.__jointab.remove_file()

def splittab_open_file(self):
self.splittab.open_file()
self.__splittab.open_file()

def splittab_save_as(self):
self.splittab.save_as()
self.__splittab.save_as()

def bgtab_choose_bg_option(self):
self.bgtab.choose_bg_option()
self.__bgtab.choose_bg_option()

def bgtab_choose_stamp_option(self):
self.bgtab.choose_stamp_option()
self.__bgtab.choose_stamp_option()

def bgtab_choose_number_option(self):
'''
Expand All @@ -607,19 +616,19 @@ def bgtab_choose_number_option(self):
pass

def bgtab_choose_source_file(self):
self.bgtab.choose_source_file()
self.__bgtab.choose_source_file()

def bgtab_choose_bg_file(self):
self.bgtab.choose_bg_file()
self.__bgtab.choose_bg_file()

def bgtab_save_as(self):
self.bgtab.save_as()
self.__bgtab.save_as()

def rotatetab_open_file(self):
self.rotatetab.open_file()
self.__rotatetab.open_file()

def rotatetab_save_as(self):
self.rotatetab.save_as()
self.__rotatetab.save_as()

def save_success(self, status_text=DEFAULT_STATUS):
'''Gets called when a PDF file was processed successfully. Currently only
Expand All @@ -633,12 +642,12 @@ def show_settings(self, *args, **kwargs):
and all the settings management is handled there. Args and kwargs are included in
method definition in case it is triggered by the keyboard shortcut, in which
case `event` gets passed into the call.'''
self.settings_dialog.run()
self.__settings_dialog.run()
self.__settings_use_poppler_variable.set(self.settings_data.use_poppler_tools)

def close_settings(self, *args, **kwargs):
self.settings_data.use_poppler_tools = self.__settings_use_poppler_variable.get()
self.settings_dialog.close()
self.__settings_dialog.close()

def cancel_settings(self, *args, **kwargs):
pass
Expand All @@ -657,10 +666,10 @@ def get_file_dialog(self, func, widget_title='Choose File(s) …'):
return f

def quit(self, event=None):
self.mainwindow.quit()
self.__mainwindow.quit()

def run(self):
self.mainwindow.mainloop()
self.__mainwindow.mainloop()


if __name__ == '__main__':
Expand Down
5 changes: 4 additions & 1 deletion settings.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
APPNAME = 'pypdfbuilder'
APPVERSION = '0.9'

# Constants for indexing into the values stored in the TreeView (e.g. in the Join View)

PDF_FILENAME = 0
Expand All @@ -12,4 +15,4 @@
JOIN_FILE_SUCCESS = 'Files joined successfully to {}!'
ROTATE_FILE_SUCCESS = 'Pages in {} rotated successfully!'
BG_FILE_SUCCESS = 'File saved successfully to {}!'
DEFAULT_STATUS = 'PyPDF Builder v1.0'
DEFAULT_STATUS = F'PyPDF Builder v{APPVERSION}'

0 comments on commit 6b8adc8

Please sign in to comment.