mainwindow.md

2023/10/08 categories:Code| tags:Code|

記事に戻る

# -*- coding: utf-8 -*-
import fitz
import math
import json
import typing
from datetime import datetime
from PyQt6 import QtCore, QtGui, QtWidgets
from pathlib import Path

from coordinates import Coordinates
from files import Files
from output_settings import OutputSettings
from pdf_preview import PdfPreview
from stamp_preview import StampPreview
from stamp_settings import StampSettings
from error_dialog import ErrorDialog
from stamp_to_page import stamp_to_page

class Mainwindow(QtWidgets.QMainWindow):
    def __init__(self, parent: typing.Optional[QtWidgets.QWidget] = None) -> None:
        super().__init__(parent)

        self.pdf_path = Path()
        self.page_number = 0
        self.errors = []

        self.files = Files()
        self.output = OutputSettings()
        self.settings = StampSettings()
        self.preview = StampPreview()
        self.coordinates = Coordinates()
        self.pdf_preview = PdfPreview()
        self.error_dialog = ErrorDialog()

        self.setCentralWidget( QtWidgets.QWidget() )
        self.centralWidget().setLayout( QtWidgets.QGridLayout() )
        self.centralWidget().layout().addWidget(self.files,       0, 0, 4, 1)
        self.centralWidget().layout().addWidget(self.output,      0, 1, 1, 2)
        self.centralWidget().layout().addWidget(self.settings,    1, 1, 1, 1)
        self.centralWidget().layout().addWidget(self.preview,     1, 2, 1, 1)
        self.centralWidget().layout().addWidget(self.coordinates, 2, 1, 1, 2)

        self.setAcceptDrops(True)
        self.settings.changed.connect(self.settings_changed)
        self.coordinates.changed.connect(lambda : self.pdf_preview_update())
        self.files.stamp_all.clicked.connect(self.stamp_all)
        self.files.pdf_double_clicked.connect(self.pdf_clicked)
        self.files.result_double_clicked.connect(self.result_clicked)
        self.pdf_preview.next.connect(lambda : self.page_changed(1))
        self.pdf_preview.prev.connect(lambda : self.page_changed(-1))

        self.load_json()

    def page_changed(self, value):
        doc = fitz.open(self.pdf_path)
        if 0 <= self.page_number + value < doc.page_count:
            self.page_number = self.page_number + value
            self.pdf_preview_update()

    def load_json(self):
        try:
            with open('settings.json', mode='r') as f:
                datas = json.load(f)
            self.output.from_dict(datas['OutputSettings'])
            self.settings.from_dict(datas['StampSettings'])
        except:
            self.output = OutputSettings()
            self.settings = StampSettings()

    def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
        self.pdf_preview.close()
        self.error_dialog.close()
        data = {}
        data['OutputSettings'] = self.output.to_dict()
        data['StampSettings'] = self.settings.to_dict()
        with open('settings.json', mode='w') as f:
            json.dump(data, f)
        return super().closeEvent(a0)

    def dragEnterEvent(self, a0: QtGui.QDragEnterEvent) -> None:
        if a0.mimeData().hasUrls():
            a0.accept()
        return super().dragEnterEvent(a0)

    def dropEvent(self, a0: QtGui.QDropEvent) -> None:
        for url in a0.mimeData().urls():
            p = Path( url.toLocalFile() )
            if p.suffix == '.pdf':
                doc = fitz.open(p)
                page = doc.load_page(0)
                w = page.mediabox_size.x * 25.4 / 72.0
                h = page.mediabox_size.y * 25.4 / 72.0
                paper = self.paper_size(w, h)
                self.files.append(paper, p)
        return super().dropEvent(a0)

    def paper_size(self, w, h):
        if math.isclose(w, 1189, abs_tol=1.0) and math.isclose(h, 841, abs_tol=1.0):
            return 'A0'
        if math.isclose(w, 841, abs_tol=1.0) and math.isclose(h, 594, abs_tol=1.0):
            return 'A1'
        if math.isclose(w, 594, abs_tol=1.0) and math.isclose(h, 420, abs_tol=1.0):
            return 'A2'
        if math.isclose(w, 420, abs_tol=1.0) and math.isclose(h, 297, abs_tol=1.0):
            return 'A3'
        if math.isclose(w, 210, abs_tol=1.0) and math.isclose(h, 297, abs_tol=1.0):
            return 'A4'
        return None

    def pdf_clicked(self, pdf_path: Path):
        self.pdf_path = pdf_path
        doc = fitz.open(self.pdf_path)
        self.page_number = 0
        page = doc.load_page(self.page_number)
        self.stamp_to_page(page)

        pix = page.get_pixmap(matrix=fitz.Matrix(2, 2))
        byte_array = QtCore.QByteArray( pix.tobytes() )
        qpixmap = QtGui.QPixmap()
        qpixmap.loadFromData(byte_array)

        self.pdf_preview.set_pixmap(qpixmap)
        self.pdf_preview.set_page_text(self.page_number+1, doc.page_count)
        self.pdf_preview.show()

    def result_clicked(self, row: int):
        error = self.errors[row]
        if error is not None:
            self.error_dialog.set_text(str(error))
            self.error_dialog.show()

    def settings_changed(self):
        self.preview.preview(
            self.settings.radius.value(), 
            self.settings.line_width.value(),
            (1.0, 0.0, 0.0),
            self.settings.str_u.toPlainText(), 
            self.settings.str_m.text(), 
            self.settings.str_b.toPlainText(), 
            self.settings.fontsize_u.value(), 
            self.settings.fontsize_m.value(), 
            self.settings.fontsize_b.value()
        )
        self.pdf_preview_update()

    def pdf_preview_update(self):
        if self.pdf_preview.isVisible():
            doc = fitz.open(self.pdf_path)
            page = doc.load_page(self.page_number)
            self.stamp_to_page(page)
            pix = page.get_pixmap(matrix=fitz.Matrix(2, 2))
            byte_array = QtCore.QByteArray( pix.tobytes() )
            qpixmap = QtGui.QPixmap()
            qpixmap.loadFromData(byte_array)
            self.pdf_preview.set_pixmap(qpixmap)
            self.pdf_preview.set_page_text(self.page_number+1, doc.page_count)

    def showEvent(self, a0: QtGui.QShowEvent) -> None:
        self.settings_changed()
        return super().showEvent(a0)

    def stamp_all(self):
        folder_text = datetime.now().strftime('outputs/%Y%m%d_%H%M%S')
        self.output.folder.setText(folder_text)
        self.errors = []
        p0 = Path(folder_text)
        if not Path('outputs').exists(): Path('outputs').mkdir()
        if not p0.exists(): p0.mkdir()
        permissions = self.output.permissions()
        owner_pw = self.output.owner_pw()
        user_pw = self.output.user_pw()
        encryption = self.output.encryption()
        marge_pdfs = fitz.open()

        for row, p1 in enumerate(self.files.paths()):
            try:
                doc1 = fitz.open(p1)
                page = doc1.load_page(0)
                self.stamp_to_page(page)
                
                doc2 = fitz.open()
                doc2.insert_pdf(doc1)
                doc2.save(p0/p1.name, permissions=permissions, encryption=encryption, owner_pw=owner_pw, user_pw=user_pw)

                self.files.set_result(row, '完了', Exception())
                self.errors.append(None)
                marge_pdfs.insert_pdf(doc1)
                self.files.set_current(row, 0)
                QtWidgets.QApplication.processEvents()
            except Exception as e:
                self.files.set_result(row, 'エラー', e)
        marge_pdfs.save(p0/'__all__.pdf', permissions=permissions, encryption=encryption, owner_pw=owner_pw, user_pw=user_pw)

        with open(p0/'__password__.txt', mode='w') as f:
            f.write('オーナーパスワード:{}\nユーザーパスワード:{}\n暗号化:{}'.format(owner_pw, user_pw, self.output.encryption_text.currentText()))
    
    def stamp_to_page(self, page: fitz.Page):
        w = page.mediabox_size.x * 25.4 / 72.0
        h = page.mediabox_size.y * 25.4 / 72.0
        origin, x, y = self.coordinates.values( self.paper_size(w, h) )

        if origin == '左上':
            x = x * 72.0 / 25.4
            y = y * 72.0 / 25.4
        if origin == '右上':
            x = (w - x) * 72.0 / 25.4
            y = y * 72.0 / 25.4
        if origin == '左下':
            x = x * 72.0 / 25.4
            y = (h - y) * 72.0 / 25.4
        if origin == '右下':
            x = (w - x) * 72.0 / 25.4
            y = (h - y) * 72.0 / 25.4

        line_width = self.settings.line_width.value()
        r2 = self.settings.radius.value() - line_width / 2

        stamp_to_page(
            page, x, y, r2, line_width,
            (1.0, 0.0, 0.0),
            self.settings.str_u.toPlainText(),
            self.settings.str_m.text(),
            self.settings.str_b.toPlainText(),
            self.settings.fontsize_u.value(),
            self.settings.fontsize_m.value(),
            self.settings.fontsize_b.value()
        )
        
if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = Mainwindow()
    window.show()
    app.exec()

Share post

Related Posts

コメント