PK>HhTiiedocuments/process.py# -*- coding: utf-8 -*- import os import re from tempfile import NamedTemporaryFile from subprocess import check_call from shutil import copyfile import edocuments def process( names, filename=None, destination_filename=None, in_extention=None, progress=None, progress_text=""): cmds = edocuments.config.get("cmds", {}) out_ext = in_extention original_filename = filename if destination_filename is None: destination_filename = filename for no, name in enumerate(names): cmd = cmds.get(name) if cmd is None: raise "Missing command '%s' in `cmds`" % name if isinstance(cmd, str): cmd = dict(cmd=cmd) if cmd.get('type') == 'rename': destination_filename = _rename(cmd, destination_filename) else: if 'out_ext' in cmd: out_ext = cmd['out_ext'] inplace = cmd.get('inplace', False) cmd_cmd = cmd.get('cmd') if inplace: out_name = filename else: if out_ext is None: out_name = NamedTemporaryFile(mode='w+b').name else: out_name = NamedTemporaryFile( mode='w+b', suffix='.' + out_ext ).name params = {} if filename is not None: params["in"] = "'%s'" % filename.replace("'", "'\''") if not inplace: params["out"] = "'%s'" % out_name.replace("'", "'\''") cmd_cmd = cmd_cmd.format(**params) print("{name}: {cmd}".format(name=name, cmd=cmd_cmd)) if progress is not None: progress.setLabelText(progress_text.format(name=name, **cmd)) if progress.wasCanceled(): return check_call(cmd_cmd, shell=True) if progress is not None: progress.setValue(no + 1) filename = out_name if original_filename is not None and original_filename != filename: os.unlink(original_filename) if out_ext is not None: destination_filename = "%s.%s" % (re.sub( r"\.[a-z0-9A-Z]{2,5}$", "", destination_filename ), out_ext) if filename != destination_filename: directory = os.path.dirname(destination_filename) print(directory) if not os.path.exists(directory): os.makedirs(directory) copyfile(filename, destination_filename) os.unlink(filename) return destination_filename def _rename(cmd, destination_filename): from_re = cmd.get('from') to_re = cmd.get('to') if cmd.get('format') in ['upper', 'lower']: def format_term(term): if cmd.get('format') == 'upper': return term.upper() else: return term.lower() to_re = lambda m: format_term(m.group(0)) return re.sub(from_re, to_re, destination_filename) def destination_filename(names, filename, extention=None): cmds = edocuments.config.get("cmds", {}) for name in names: cmd = cmds.get(name) if cmd is None: raise "Missing command '%s' in `cmds`" % name if isinstance(cmd, str): cmd = {} if cmd.get('type') == 'rename': filename = _rename(cmd, filename) else: if 'out_ext' in cmd: extention = cmd['out_ext'] if extention is not None: filename = "%s.%s" % (re.sub( r"\.[a-z0-9A-Z]{2,5}$", "", filename ), extention) return filename PK>HOedocuments/label_dialog.py# -*- coding: utf-8 -*- from PyQt5.QtWidgets import QDialog from PyQt5.QtGui import QPixmap from edocuments.ui.label_dialog import Ui_Dialog class Dialog(QDialog): def __init__(self): super().__init__() self.ui = Ui_Dialog() self.ui.setupUi(self) def set_image(self, image_filename): size = 800 pixmap = QPixmap(image_filename) if pixmap.width() > pixmap.height(): if pixmap.width() > size: pixmap = pixmap.scaledToWidth(size) else: if pixmap.height() > size: pixmap = pixmap.scaledToHeight(size) self.ui.label.setPixmap(pixmap) self.ui.label.setMask(pixmap.mask()) self.ui.label.show() PKa?Hb}edocuments/__init__.py# -*- coding: utf-8 -*- import os import sys from yaml import load from autoupgrade import AutoUpgrade from PyQt5.QtCore import QSettings from PyQt5.QtWidgets import QApplication from edocuments.main_widget import MainWindow CONFIG_FILENAME = "edocuments.yaml" if 'APPDATA' in os.environ: CONFIG_PATH = os.path.join(os.environ['APPDATA'], CONFIG_FILENAME) elif 'XDG_CONFIG_HOME' in os.environ: CONFIG_PATH = os.path.join(os.environ['XDG_CONFIG_HOME'], CONFIG_FILENAME) else: CONFIG_PATH = os.path.join(os.environ['HOME'], '.config', CONFIG_FILENAME) config = {} root_folder = None settings = None def gui_main(): global config, root_folder, settings with open(CONFIG_PATH) as f: config = load(f.read()) root_folder = "%s/%s/" % ( os.path.expanduser('~'), config.get("root_folder"), ) settings = QSettings("org", "edocuments") app = QApplication(sys.argv) mw = MainWindow() if settings.value("geometry") is not None: mw.restoreGeometry(settings.value("geometry")) if settings.value("state") is not None: mw.restoreState(settings.value("state")) au = AutoUpgrade('edocuments') if au.check(): msg = QMessageBox(self) msg.setWindowTitle("eDocuments - Upgrade") msg.setText("A new version is available") msg.setInformativeText("Do you want to do anupdate and restart?") msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) ret = msg.exec() if ret == QMessageBox.Yes: au.upgrade(dependencies=True) au.restart() mw.show() app.exec() settings.setValue("geometry", mw.saveGeometry()) settings.setValue("state", mw.saveState()) settings.sync() PK^?Hqedocuments/main_widget.py# -*- coding: utf-8 -*- import re import pathlib from os import path from threading import Thread from subprocess import call from PyQt5.Qt import Qt from PyQt5.QtWidgets import QMainWindow, QFileDialog, \ QErrorMessage, QMessageBox, QProgressDialog import edocuments from edocuments.process import process, destination_filename from edocuments.ui.main import Ui_MainWindow from edocuments.label_dialog import Dialog class MainWindow(QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.scan_comments.setText(edocuments.config.get("scan_comments")) default_index = 0 for s in edocuments.config.get("scans", []): if s.get("default") is True: default_index = self.ui.scan_type.count() self.ui.scan_type.addItem(s.get("name"), s) self.ui.scan_type.setCurrentIndex(default_index) self.ui.scan_browse.clicked.connect(self.scan_browse) self.ui.scan_to.returnPressed.connect(self.scan_start) self.ui.scan_to.editingFinished.connect(self.scan_start) self.ui.scan_start.clicked.connect(self.scan_start) self.image_dialog = Dialog() def scan_browse(self, event): filename = QFileDialog.getSaveFileName( self, "Scan to", directory=self.filename() )[0] filename = re.sub(r"\.[a-z0-9A-Z]{2,5}$", "", filename) if filename[:len(edocuments.root_folder)] == edocuments.root_folder: filename = filename[len(edocuments.root_folder):] self.ui.scan_to.setText(filename) def filename(self): filename = self.ui.scan_to.text() if len(filename) == 0 or filename[0] != '/': filename = path.join(edocuments.root_folder, filename) return filename def scan_start(self, event): if pathlib.Path(self.filename()).is_dir(): err = QErrorMessage(self) err.setWindowTitle("eDocuments - Error") err.showMessage("The destination is a directory!") return destination = destination_filename( self.ui.scan_type.currentData().get("cmds"), self.filename() ) if pathlib.Path(destination).is_file(): msg = QMessageBox(self) msg.setWindowTitle("Scanning...") msg.setText("The destination file already exists") msg.setInformativeText("Do you want to overwrite it?") msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel | QMessageBox.Open) ret = msg.exec() if ret == QMessageBox.Ok: self._scan() elif ret == QMessageBox.Open: cmd = edocuments.config.get('open_cmd').split(' ') cmd.append(destination) call(cmd) else: self._scan() def _scan(self): cmds = self.ui.scan_type.currentData().get("cmds") self.progress = QProgressDialog("Scanning...", "Cancel", 0, len(cmds), self) self.progress.setWindowTitle("Scanning...") self.progress.setWindowModality(Qt.WindowModal) self.progress.show() t = Thread(target=self._do_scan) t.start() def _do_scan(self): cmds = self.ui.scan_type.currentData().get("cmds") filename = process( cmds, destination_filename=self.filename(), progress=self.progress, progress_text='{display}' ) self.progress.hide() self.image_dialog.set_image(filename) self.image_dialog.exec() PK>H"..edocuments/ui/label_dialog.py# -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'edocuments/ui/label_dialog.ui' # # Created by: PyQt5 UI code generator 5.4.2 # # WARNING! All changes made in this file will be lost! from PyQt5 import QtCore, QtGui, QtWidgets class Ui_Dialog(object): def setupUi(self, Dialog): Dialog.setObjectName("Dialog") Dialog.resize(194, 70) self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) self.verticalLayout.setObjectName("verticalLayout") self.label = QtWidgets.QLabel(Dialog) self.label.setText("") self.label.setObjectName("label") self.verticalLayout.addWidget(self.label) self.buttonBox = QtWidgets.QDialogButtonBox(Dialog) self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok) self.buttonBox.setObjectName("buttonBox") self.verticalLayout.addWidget(self.buttonBox) self.retranslateUi(Dialog) self.buttonBox.accepted.connect(Dialog.accept) self.buttonBox.rejected.connect(Dialog.reject) QtCore.QMetaObject.connectSlotsByName(Dialog) def retranslateUi(self, Dialog): _translate = QtCore.QCoreApplication.translate Dialog.setWindowTitle(_translate("Dialog", "Dialog")) PKx>H<`\1edocuments/ui/main.py# -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'edocuments/ui/main.ui' # # Created by: PyQt5 UI code generator 5.4.2 # # WARNING! All changes made in this file will be lost! from PyQt5 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(583, 525) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget) self.verticalLayout.setObjectName("verticalLayout") self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) self.tabWidget.setEnabled(True) self.tabWidget.setObjectName("tabWidget") self.search = QtWidgets.QWidget() self.search.setObjectName("search") self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.search) self.verticalLayout_4.setObjectName("verticalLayout_4") self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) self.horizontalLayout.setObjectName("horizontalLayout") self.search_text = QtWidgets.QLineEdit(self.search) self.search_text.setObjectName("search_text") self.horizontalLayout.addWidget(self.search_text) self.search_btn = QtWidgets.QPushButton(self.search) self.search_btn.setObjectName("search_btn") self.horizontalLayout.addWidget(self.search_btn) self.verticalLayout_4.addLayout(self.horizontalLayout) self.groupBox_2 = QtWidgets.QGroupBox(self.search) self.groupBox_2.setObjectName("groupBox_2") self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.groupBox_2) self.verticalLayout_7.setObjectName("verticalLayout_7") self.advance_query = QtWidgets.QPlainTextEdit(self.groupBox_2) self.advance_query.setObjectName("advance_query") self.verticalLayout_7.addWidget(self.advance_query) self.verticalLayout_4.addWidget(self.groupBox_2) self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.search_result_list = QtWidgets.QListWidget(self.search) self.search_result_list.setObjectName("search_result_list") self.horizontalLayout_2.addWidget(self.search_result_list) self.verticalLayout_5 = QtWidgets.QVBoxLayout() self.verticalLayout_5.setObjectName("verticalLayout_5") self.search_result_test = QtWidgets.QTextBrowser(self.search) self.search_result_test.setObjectName("search_result_test") self.verticalLayout_5.addWidget(self.search_result_test) self.search_result_graphics = QtWidgets.QGraphicsView(self.search) self.search_result_graphics.setObjectName("search_result_graphics") self.verticalLayout_5.addWidget(self.search_result_graphics) self.horizontalLayout_2.addLayout(self.verticalLayout_5) self.horizontalLayout_2.setStretch(0, 1) self.verticalLayout_4.addLayout(self.horizontalLayout_2) self.tabWidget.addTab(self.search, "") self.scan = QtWidgets.QWidget() self.scan.setObjectName("scan") self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.scan) self.verticalLayout_2.setObjectName("verticalLayout_2") self.horizontalLayout_3 = QtWidgets.QHBoxLayout() self.horizontalLayout_3.setObjectName("horizontalLayout_3") self.label = QtWidgets.QLabel(self.scan) self.label.setObjectName("label") self.horizontalLayout_3.addWidget(self.label) self.scan_type = QtWidgets.QComboBox(self.scan) self.scan_type.setObjectName("scan_type") self.horizontalLayout_3.addWidget(self.scan_type) self.verticalLayout_2.addLayout(self.horizontalLayout_3) self.direct = QtWidgets.QGroupBox(self.scan) self.direct.setObjectName("direct") self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.direct) self.horizontalLayout_5.setObjectName("horizontalLayout_5") self.scan_to = QtWidgets.QLineEdit(self.direct) self.scan_to.setObjectName("scan_to") self.horizontalLayout_5.addWidget(self.scan_to) self.scan_browse = QtWidgets.QPushButton(self.direct) self.scan_browse.setObjectName("scan_browse") self.horizontalLayout_5.addWidget(self.scan_browse) self.scan_start = QtWidgets.QPushButton(self.direct) self.scan_start.setObjectName("scan_start") self.horizontalLayout_5.addWidget(self.scan_start) self.verticalLayout_2.addWidget(self.direct) self.groupBox = QtWidgets.QGroupBox(self.scan) self.groupBox.setObjectName("groupBox") self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.groupBox) self.verticalLayout_6.setObjectName("verticalLayout_6") self.scan_comments = QtWidgets.QLabel(self.groupBox) self.scan_comments.setText("") self.scan_comments.setObjectName("scan_comments") self.verticalLayout_6.addWidget(self.scan_comments) self.verticalLayout_2.addWidget(self.groupBox) spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.verticalLayout_2.addItem(spacerItem) self.tabWidget.addTab(self.scan, "") self.verticalLayout.addWidget(self.tabWidget) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 583, 24)) self.menubar.setObjectName("menubar") self.menuUpdate_library = QtWidgets.QMenu(self.menubar) self.menuUpdate_library.setObjectName("menuUpdate_library") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.actionUpdate = QtWidgets.QAction(MainWindow) self.actionUpdate.setObjectName("actionUpdate") self.menuUpdate_library.addAction(self.actionUpdate) self.menubar.addAction(self.menuUpdate_library.menuAction()) self.retranslateUi(MainWindow) self.tabWidget.setCurrentIndex(1) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "eDocuments - a Simple and Productive Personal Documents Library")) self.search_btn.setText(_translate("MainWindow", "Search")) self.groupBox_2.setTitle(_translate("MainWindow", "Advance query")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.search), _translate("MainWindow", "Search")) self.label.setText(_translate("MainWindow", "Scan type")) self.direct.setTitle(_translate("MainWindow", "Scan")) self.scan_browse.setText(_translate("MainWindow", "Browse...")) self.scan_start.setText(_translate("MainWindow", "Scan")) self.groupBox.setTitle(_translate("MainWindow", "Comments")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.scan), _translate("MainWindow", "Scan")) self.menuUpdate_library.setTitle(_translate("MainWindow", "&Library")) self.actionUpdate.setText(_translate("MainWindow", "&Update")) PK=Hedocuments/ui/__init__.pyPKc?H99*edocuments-0.1.0.dist-info/DESCRIPTION.rstA sample and productive personal documents library * Scan your documents * Auto rotate * index them on the file name and on the content (OCR) * Mange your pdf * index them on the file name and on the content * Search in your library `Sources `_ PKc?Hc088+edocuments-0.1.0.dist-info/entry_points.txt[console_scripts] edocuments-gui = edocuments:gui_main PKc?H: (edocuments-0.1.0.dist-info/metadata.json{"classifiers": ["Programming Language :: Python :: 3"], "extensions": {"python.commands": {"wrap_console": {"edocuments-gui": "edocuments:gui_main"}}, "python.details": {"contacts": [{"email": "stephane.brunner@gmail.com", "name": "St\u00e9phane Brunner", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/sbrunner/epaper/"}}, "python.exports": {"console_scripts": {"edocuments-gui": "edocuments:gui_main"}}}, "extras": [], "generator": "bdist_wheel (0.26.0)", "keywords": ["simple", "productive", "personal", "documents", "library", "scan", "index", "search"], "metadata_version": "2.0", "name": "edocuments", "run_requires": [{"requires": ["PyYAML", "autoupgrade"]}], "summary": "EDocuments - a simple and productive personal documents library", "test_requires": [{"requires": ["PyYAML", "autoupgrade"]}], "version": "0.1.0"}PKc?H^x (edocuments-0.1.0.dist-info/top_level.txtedocuments PKc?H''\\ edocuments-0.1.0.dist-info/WHEELWheel-Version: 1.0 Generator: bdist_wheel (0.26.0) Root-Is-Purelib: true Tag: py2-none-any PKc?H.`_ PKc?HA}Ǜ!edocuments-0.1.0.dist-info/RECORDedocuments/__init__.py,sha256=zJ8x4NHsw4KJoFhYBNO9kedl7SrnT5-OJGSTwmFMntI,1744 edocuments/label_dialog.py,sha256=5gKnx_3ov0YnNO2yTieT_ojGfrhLyXtYCY6KXmwnaqI,736 edocuments/main_widget.py,sha256=uIK6RihTL-EnoShHNdpUVEPKKSvtuMIbqj--0z5hhyQ,3611 edocuments/process.py,sha256=j_GjbMu7yABW0fVeOeqlb6TWSlaxVpdzFHoCvYyTvEQ,3689 edocuments/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 edocuments/ui/label_dialog.py,sha256=Xwrsrq7chUq55Lk7OI-AqYWI0GV_2e_BhyiwuSiY0w0,1326 edocuments/ui/main.py,sha256=Q390s4dyK_hixf-VCcJ3rvfBU9ecN2cGawUgL4LVELs,7587 edocuments-0.1.0.dist-info/DESCRIPTION.rst,sha256=NNmNRtKhPkR7y8ziKTDcRske1amQTOFlUSC3wpyqXPw,313 edocuments-0.1.0.dist-info/METADATA,sha256=_DiiwdgJjH8uRVXuEh_1eSKJZ4luhbDNW88ZxVDF52I,760 edocuments-0.1.0.dist-info/RECORD,, edocuments-0.1.0.dist-info/WHEEL,sha256=JTb7YztR8fkPg6aSjc571Q4eiVHCwmUDlX8PhuuqIIE,92 edocuments-0.1.0.dist-info/entry_points.txt,sha256=Zu3PrcJ2l2YWUF5IDRpdNtZYXxrEtj2IR2TgpKC5cko,56 edocuments-0.1.0.dist-info/metadata.json,sha256=iGSHhHZQk4VP1ZQCphAFwXaKVOjE1NRUrVwBNsbKcQ4,897 edocuments-0.1.0.dist-info/top_level.txt,sha256=yvF7f7apfBqVzBbWZQP6Pp2iqiVAHWruuNkQ7SDS2mg,11 PK>HhTiiedocuments/process.pyPK>HOedocuments/label_dialog.pyPKa?Hb}edocuments/__init__.pyPK^?Hqedocuments/main_widget.pyPK>H".. 'edocuments/ui/label_dialog.pyPKx>H<`\1s,edocuments/ui/main.pyPK=HIJedocuments/ui/__init__.pyPKc?H99*Jedocuments-0.1.0.dist-info/DESCRIPTION.rstPKc?Hc088+Ledocuments-0.1.0.dist-info/entry_points.txtPKc?H: (Ledocuments-0.1.0.dist-info/metadata.jsonPKc?H^x (IPedocuments-0.1.0.dist-info/top_level.txtPKc?H''\\ Pedocuments-0.1.0.dist-info/WHEELPKc?H.