Compare commits
22 Commits
Author | SHA1 | Date | |
---|---|---|---|
9b1f0b911b | |||
a86ba80bce | |||
062d07ed23 | |||
5b4bb54495 | |||
8dc25f5ca6 | |||
18b5c06b17 | |||
8c4067f34a | |||
ce63907fcd | |||
ffc3f0e2b7 | |||
211629202c | |||
12be98d1a1 | |||
a41aed4f0b | |||
675facb6f7 | |||
6cad1e9408 | |||
98f8dce109 | |||
4a4c8d8c53 | |||
3b114a9622 | |||
c13535ec56 | |||
64b4c90e46 | |||
2dff534f61 | |||
c309c2db56 | |||
|
e1d238c321 |
14
.drone.yml
14
.drone.yml
@ -7,7 +7,7 @@ workspace:
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: git.argideli.com/quertex/docker-win-pyinstaller64:latest
|
||||
image: git.quertex.com/quertex/docker-win-pyinstaller64:latest
|
||||
pull: always
|
||||
commands:
|
||||
# prepare output directory
|
||||
@ -16,7 +16,7 @@ steps:
|
||||
# add dependancies
|
||||
- pacman -Syu --noconfirm
|
||||
#- pacman -Sy --noconfirm --needed wget lib32-gnutls libunwind lib32-expat python3 python-pip python-pipenv gcc-fortran base-devel python-numpy python-pandas gcc-libs gnutls wine-staging
|
||||
- pacman -Sy --noconfirm at-spi2-core gtk3 lib32-gdk-pixbuf2 qt6-base qt6-declarative shiboken6 qt6-3d qt6-charts qt6-connectivity qt6-datavis3d qt6-graphs qt6-httpserver qt6-location qt6-multimedia qt6-networkauth qt6-positioning qt6-quick3d qt6-remoteobjects qt6-scxml qt6-sensors qt6-serialbus qt6-serialport qt6-speech qt6-svg qt6-tools qt6-webchannel qt6-webengine qt6-websockets libxkbcommon lib32-libxkbcommon python-xkbcommon python-cryptography python-pillow python-pycryptodome python-typing_extensions python-build python-flit-core python-installer python-setuptools python-wheel wget lib32-gnutls libunwind lib32-expat python3 python-pip gcc-fortran base-devel gcc-libs gnutls wine-staging
|
||||
- pacman -Sy --noconfirm at-spi2-core gtk3 lib32-gdk-pixbuf2 qt6-base qt6-declarative shiboken6 qt6-3d qt6-charts qt6-connectivity qt6-datavis3d qt6-graphs qt6-httpserver qt6-location qt6-multimedia qt6-networkauth qt6-positioning qt6-quick3d qt6-remoteobjects qt6-scxml qt6-sensors qt6-serialbus qt6-serialport qt6-speech qt6-svg qt6-tools qt6-webchannel qt6-webengine qt6-websockets libxkbcommon lib32-libxkbcommon python-xkbcommon python-cryptography python-pillow python-pycryptodome python-typing_extensions python-build python-flit-core python-installer python-setuptools python-wheel wget lib32-gnutls libunwind lib32-expat python3 python-pip gcc-fortran base-devel gcc-libs gnutls
|
||||
# linux build
|
||||
- cd /drone/src/
|
||||
- python --version
|
||||
@ -29,7 +29,7 @@ steps:
|
||||
- pip3 config set global.trusted-host "pypi.org files.pythonhosted.org pypi.python.org" --trusted-host=pypi.python.org --trusted-host=pypi.org --trusted-host=files.pythonhosted.org
|
||||
- pip3 install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org pip setuptools
|
||||
- pip3 install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --ignore-installed -r requirements.txt
|
||||
- pyinstaller --onefile --name akmi-utils.bin -y --distpath /drone/src/out/ /drone/src/widget.py
|
||||
- pyinstaller --onefile --copy-metadata msoffice2pdf --collect-submodules --name akmi-utils.bin -y --distpath /drone/src/out/ /drone/src/widget.py
|
||||
- deactivate
|
||||
- cp -v out/akmi-utils.bin dist/
|
||||
# clean up
|
||||
@ -37,15 +37,15 @@ steps:
|
||||
- rm -rf /drone/src/out
|
||||
- mkdir -p /drone/src/out/
|
||||
# windows build
|
||||
- wine c:/python/python.exe -m pip config --user set global.progress_bar off
|
||||
- wine c:/python/python.exe -m pip install --prefer-binary -r z:/drone/src/requirements.txt
|
||||
- wine c:/python/Scripts/pyinstaller.exe --onefile --name akmi-utils -y --distpath z:/drone/src/out z:/drone/src/widget.py
|
||||
- wine64 c:/python/python.exe -m pip config --user set global.progress_bar off
|
||||
- wine64 c:/python/python.exe -m pip install --prefer-binary -r z:/drone/src/requirements.txt
|
||||
- wine64 c:/python/Scripts/pyinstaller.exe --onefile --copy-metadata msoffice2pdf --collect-submodules --name akmi-utils -y --distpath z:/drone/src/out z:/drone/src/widget.py
|
||||
- cp -v out/akmi-utils.exe dist/
|
||||
|
||||
- name: gitea_release
|
||||
image: plugins/gitea-release
|
||||
settings:
|
||||
base_url: https://git.argideli.com
|
||||
base_url: https://git.quertex.com
|
||||
api_key:
|
||||
from_secret: gitea_token
|
||||
files: /drone/src/dist/*
|
||||
|
84
form.ui
84
form.ui
@ -9,8 +9,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>742</width>
|
||||
<height>336</height>
|
||||
<width>706</width>
|
||||
<height>534</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -26,13 +26,13 @@
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Επιλογή Αρχείου CSV</string>
|
||||
<string>Επιλογή δεδομένων Excel</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>150</x>
|
||||
<x>140</x>
|
||||
<y>20</y>
|
||||
<width>61</width>
|
||||
<height>61</height>
|
||||
@ -51,7 +51,7 @@
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>240</x>
|
||||
<x>230</x>
|
||||
<y>10</y>
|
||||
<width>431</width>
|
||||
<height>81</height>
|
||||
@ -83,7 +83,7 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Επιλέξτε το αρχείο δεδομένων σε μορφή .csv</string>
|
||||
<string>Επιλέξτε το αρχείο δεδομένων σε μορφή Excel</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="create_button">
|
||||
@ -92,14 +92,14 @@
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>310</x>
|
||||
<y>290</y>
|
||||
<width>111</width>
|
||||
<height>34</height>
|
||||
<x>480</x>
|
||||
<y>250</y>
|
||||
<width>211</width>
|
||||
<height>61</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Δημιουργία pdf</string>
|
||||
<string>Δημιουργία πιστοποιητικών</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="file_template">
|
||||
@ -112,7 +112,7 @@
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Επιλογή Αρχείου PDF</string>
|
||||
<string>Επιλογή προσχέδιου Word</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_4">
|
||||
@ -131,7 +131,65 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Επιλέξτε το PDF αρχείο του προτύπου</string>
|
||||
<string>Επιλέξτε το αρχείο του προτύπου (Word)</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPlainTextEdit" name="oauth2_token">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>320</y>
|
||||
<width>341</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="enable_email">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>260</y>
|
||||
<width>131</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Αποστολή email</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>120</x>
|
||||
<y>290</y>
|
||||
<width>131</width>
|
||||
<height>31</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string><html><head/><body><p>Το αρχείο που έχουμε επιλέξει</p></body></html></string>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Microsoft OAuth2 Token</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPlainTextEdit" name="log_output">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>390</y>
|
||||
<width>681</width>
|
||||
<height>131</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
|
20
requirements.bk
Normal file
20
requirements.bk
Normal file
@ -0,0 +1,20 @@
|
||||
chardet==5.2.0
|
||||
pillow==10.4.0
|
||||
PyPDF2==3.0.1
|
||||
PySide6>=6.7.2
|
||||
PySide6_Addons>=6.7.2
|
||||
PySide6_Essentials>=6.7.2
|
||||
python-dateutil==2.9.0.post0
|
||||
pytz==2024.1
|
||||
reportlab==4.2.2
|
||||
shiboken6>=6.7.2
|
||||
six==1.16.0
|
||||
tzdata==2024.1
|
||||
altgraph==0.17.4
|
||||
packaging==24.1
|
||||
pyinstaller==6.9.0
|
||||
pyinstaller-hooks-contrib==2024.7
|
||||
setuptools==70.3.0
|
||||
python-docx==1.1.2
|
||||
python-docx==1.1.2
|
||||
msoffice2pdf==1.0.0
|
@ -1,17 +1,30 @@
|
||||
altgraph==0.17.4
|
||||
certifi==2024.12.14
|
||||
chardet==5.2.0
|
||||
charset-normalizer==3.4.1
|
||||
et_xmlfile==2.0.0
|
||||
idna==3.10
|
||||
lxml==5.3.0
|
||||
msoffice2pdf>=0.9.0
|
||||
numpy==2.2.1
|
||||
openpyxl==3.1.5
|
||||
packaging==24.1
|
||||
pandas==2.2.3
|
||||
pillow==10.4.0
|
||||
pyinstaller==6.10.0
|
||||
pyinstaller-hooks-contrib==2024.11
|
||||
PyPDF2==3.0.1
|
||||
PySide6>=6.7.2
|
||||
PySide6_Addons>=6.7.2
|
||||
PySide6_Essentials>=6.7.2
|
||||
PySide6==6.8.1
|
||||
PySide6_Addons==6.8.1
|
||||
PySide6_Essentials==6.8.1
|
||||
python-dateutil==2.9.0.post0
|
||||
python-docx==1.1.2
|
||||
pytz==2024.1
|
||||
reportlab==4.2.2
|
||||
shiboken6>=6.7.2
|
||||
six==1.16.0
|
||||
tzdata==2024.1
|
||||
altgraph==0.17.4
|
||||
packaging==24.1
|
||||
pyinstaller==6.9.0
|
||||
pyinstaller-hooks-contrib==2024.7
|
||||
requests==2.32.3
|
||||
setuptools==70.3.0
|
||||
shiboken6==6.8.1
|
||||
six==1.16.0
|
||||
typing_extensions==4.12.2
|
||||
tzdata==2024.1
|
||||
urllib3==2.3.0
|
48
ui_form.py
48
ui_form.py
@ -1,9 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
################################################################################
|
||||
## Form generated from reading UI file 'form.ui'
|
||||
## Form generated from reading UI file 'formrmZXPO.ui'
|
||||
##
|
||||
## Created by: Qt User Interface Compiler version 6.7.2
|
||||
## Created by: Qt User Interface Compiler version 6.8.1
|
||||
##
|
||||
## WARNING! All changes made in this file will be lost when recompiling UI file!
|
||||
################################################################################
|
||||
@ -15,27 +15,27 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
|
||||
QFont, QFontDatabase, QGradient, QIcon,
|
||||
QImage, QKeySequence, QLinearGradient, QPainter,
|
||||
QPalette, QPixmap, QRadialGradient, QTransform)
|
||||
from PySide6.QtWidgets import (QApplication, QLabel, QPushButton, QSizePolicy,
|
||||
QWidget)
|
||||
import rc_resources
|
||||
from PySide6.QtWidgets import (QApplication, QCheckBox, QLabel, QPlainTextEdit,
|
||||
QPushButton, QSizePolicy, QWidget)
|
||||
import resources_rc
|
||||
|
||||
class Ui_Widget(object):
|
||||
def setupUi(self, Widget):
|
||||
if not Widget.objectName():
|
||||
Widget.setObjectName(u"Widget")
|
||||
Widget.setEnabled(True)
|
||||
Widget.resize(742, 336)
|
||||
Widget.resize(706, 534)
|
||||
self.file_selector = QPushButton(Widget)
|
||||
self.file_selector.setObjectName(u"file_selector")
|
||||
self.file_selector.setGeometry(QRect(20, 140, 151, 34))
|
||||
self.label = QLabel(Widget)
|
||||
self.label.setObjectName(u"label")
|
||||
self.label.setGeometry(QRect(150, 20, 61, 61))
|
||||
self.label.setGeometry(QRect(140, 20, 61, 61))
|
||||
self.label.setPixmap(QPixmap(u":/images/logo.png"))
|
||||
self.label.setScaledContents(True)
|
||||
self.label_2 = QLabel(Widget)
|
||||
self.label_2.setObjectName(u"label_2")
|
||||
self.label_2.setGeometry(QRect(240, 10, 431, 81))
|
||||
self.label_2.setGeometry(QRect(230, 10, 431, 81))
|
||||
font = QFont()
|
||||
font.setPointSize(26)
|
||||
font.setBold(True)
|
||||
@ -47,7 +47,7 @@ class Ui_Widget(object):
|
||||
self.create_button = QPushButton(Widget)
|
||||
self.create_button.setObjectName(u"create_button")
|
||||
self.create_button.setEnabled(False)
|
||||
self.create_button.setGeometry(QRect(310, 290, 111, 34))
|
||||
self.create_button.setGeometry(QRect(480, 250, 211, 61))
|
||||
self.file_template = QPushButton(Widget)
|
||||
self.file_template.setObjectName(u"file_template")
|
||||
self.file_template.setGeometry(QRect(20, 190, 151, 34))
|
||||
@ -55,6 +55,21 @@ class Ui_Widget(object):
|
||||
self.label_4.setObjectName(u"label_4")
|
||||
self.label_4.setGeometry(QRect(180, 190, 561, 31))
|
||||
self.label_4.setAutoFillBackground(False)
|
||||
self.oauth2_token = QPlainTextEdit(Widget)
|
||||
self.oauth2_token.setObjectName(u"oauth2_token")
|
||||
self.oauth2_token.setEnabled(False)
|
||||
self.oauth2_token.setGeometry(QRect(20, 320, 341, 41))
|
||||
self.enable_email = QCheckBox(Widget)
|
||||
self.enable_email.setObjectName(u"enable_email")
|
||||
self.enable_email.setGeometry(QRect(20, 260, 131, 20))
|
||||
self.label_5 = QLabel(Widget)
|
||||
self.label_5.setObjectName(u"label_5")
|
||||
self.label_5.setGeometry(QRect(120, 290, 131, 31))
|
||||
self.label_5.setAutoFillBackground(False)
|
||||
self.log_output = QPlainTextEdit(Widget)
|
||||
self.log_output.setObjectName(u"log_output")
|
||||
self.log_output.setEnabled(False)
|
||||
self.log_output.setGeometry(QRect(10, 390, 681, 131))
|
||||
|
||||
self.retranslateUi(Widget)
|
||||
|
||||
@ -63,18 +78,23 @@ class Ui_Widget(object):
|
||||
|
||||
def retranslateUi(self, Widget):
|
||||
Widget.setWindowTitle(QCoreApplication.translate("Widget", u"Widget", None))
|
||||
self.file_selector.setText(QCoreApplication.translate("Widget", u"\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u0391\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 CSV", None))
|
||||
self.file_selector.setText(QCoreApplication.translate("Widget", u"\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd Excel", None))
|
||||
self.label.setText("")
|
||||
self.label_2.setText(QCoreApplication.translate("Widget", u"AKMI Certificate creator", None))
|
||||
#if QT_CONFIG(whatsthis)
|
||||
self.label_3.setWhatsThis(QCoreApplication.translate("Widget", u"<html><head/><body><p>\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03c0\u03bf\u03c5 \u03ad\u03c7\u03bf\u03c5\u03bc\u03b5 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03b5\u03b9</p></body></html>", None))
|
||||
#endif // QT_CONFIG(whatsthis)
|
||||
self.label_3.setText(QCoreApplication.translate("Widget", u"\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd \u03c3\u03b5 \u03bc\u03bf\u03c1\u03c6\u03ae .csv", None))
|
||||
self.create_button.setText(QCoreApplication.translate("Widget", u"\u0394\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 pdf", None))
|
||||
self.file_template.setText(QCoreApplication.translate("Widget", u"\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u0391\u03c1\u03c7\u03b5\u03af\u03bf\u03c5 PDF", None))
|
||||
self.label_3.setText(QCoreApplication.translate("Widget", u"\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd \u03c3\u03b5 \u03bc\u03bf\u03c1\u03c6\u03ae Excel", None))
|
||||
self.create_button.setText(QCoreApplication.translate("Widget", u"\u0394\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 \u03c0\u03b9\u03c3\u03c4\u03bf\u03c0\u03bf\u03b9\u03b7\u03c4\u03b9\u03ba\u03ce\u03bd", None))
|
||||
self.file_template.setText(QCoreApplication.translate("Widget", u"\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u03c0\u03c1\u03bf\u03c3\u03c7\u03ad\u03b4\u03b9\u03bf\u03c5 Word", None))
|
||||
#if QT_CONFIG(whatsthis)
|
||||
self.label_4.setWhatsThis(QCoreApplication.translate("Widget", u"<html><head/><body><p>\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03c0\u03bf\u03c5 \u03ad\u03c7\u03bf\u03c5\u03bc\u03b5 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03b5\u03b9</p></body></html>", None))
|
||||
#endif // QT_CONFIG(whatsthis)
|
||||
self.label_4.setText(QCoreApplication.translate("Widget", u"\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf PDF \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03c4\u03bf\u03c5 \u03c0\u03c1\u03bf\u03c4\u03cd\u03c0\u03bf\u03c5", None))
|
||||
self.label_4.setText(QCoreApplication.translate("Widget", u"\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03c4\u03bf\u03c5 \u03c0\u03c1\u03bf\u03c4\u03cd\u03c0\u03bf\u03c5 (Word)", None))
|
||||
self.enable_email.setText(QCoreApplication.translate("Widget", u"\u0391\u03c0\u03bf\u03c3\u03c4\u03bf\u03bb\u03ae email", None))
|
||||
#if QT_CONFIG(whatsthis)
|
||||
self.label_5.setWhatsThis(QCoreApplication.translate("Widget", u"<html><head/><body><p>\u03a4\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03c0\u03bf\u03c5 \u03ad\u03c7\u03bf\u03c5\u03bc\u03b5 \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03b5\u03b9</p></body></html>", None))
|
||||
#endif // QT_CONFIG(whatsthis)
|
||||
self.label_5.setText(QCoreApplication.translate("Widget", u"Microsoft OAuth2 Token", None))
|
||||
# retranslateUi
|
||||
|
||||
|
175
widget.py
175
widget.py
@ -2,23 +2,22 @@
|
||||
import os
|
||||
import io
|
||||
import sys
|
||||
import csv
|
||||
import shutil
|
||||
from PyPDF2 import PdfReader, PdfWriter
|
||||
from reportlab.pdfgen import canvas
|
||||
from reportlab.lib.pagesizes import A4
|
||||
from reportlab.pdfbase import pdfmetrics
|
||||
from reportlab.pdfbase.ttfonts import TTFont
|
||||
import base64
|
||||
from docx import Document
|
||||
from msoffice2pdf import convert
|
||||
import pandas as pd
|
||||
import requests
|
||||
from PySide6.QtWidgets import QApplication, QWidget, QFileDialog
|
||||
from PySide6.QtCore import QFile, QIODevice
|
||||
|
||||
# Important:
|
||||
# NOTE:
|
||||
# You need to run the following command to generate the ui_form.py file
|
||||
# pyside6-uic form.ui -o ui_form.py, or
|
||||
# pyside2-uic form.ui -o ui_form.py
|
||||
from ui_form import Ui_Widget
|
||||
|
||||
import rc_resources
|
||||
import resources_rc
|
||||
|
||||
|
||||
class Widget(QWidget):
|
||||
@ -30,6 +29,7 @@ class Widget(QWidget):
|
||||
self.ui.file_selector.clicked.connect(self.file_selector)
|
||||
self.ui.file_template.clicked.connect(self.file_template)
|
||||
self.ui.create_button.clicked.connect(self.create_button)
|
||||
self.ui.enable_email.clicked.connect(self.enable_token)
|
||||
self.selected_file = False
|
||||
self.selected_template = False
|
||||
self.filepath_template = ""
|
||||
@ -49,90 +49,141 @@ class Widget(QWidget):
|
||||
if self.selected_file and self.selected_template:
|
||||
self.ui.create_button.setEnabled(True)
|
||||
|
||||
def enable_token(self):
|
||||
print(self.ui.oauth2_token.isEnabled())
|
||||
if self.ui.oauth2_token.isEnabled():
|
||||
self.ui.oauth2_token.setEnabled(False)
|
||||
else:
|
||||
self.ui.oauth2_token.setEnabled(True)
|
||||
|
||||
def file_selector(self):
|
||||
self.filepath = QFileDialog.getOpenFileName(self, "Επιλογή Αρχείου")
|
||||
if self.filepath[0]:
|
||||
ext = os.path.splitext(self.filepath[0])[-1].lower()
|
||||
if ext != ".csv":
|
||||
self.ui.label_3.setText("Το αρχείο πρέπει να είναι της μορφής .csv")
|
||||
self.selected_file = False
|
||||
else:
|
||||
if ext in [".xlsx", ".xls"]:
|
||||
self.ui.log_output.appendPlainText("Επιλέχθηκε το αρχείο δεδομενων: {}".format(self.filepath[0]))
|
||||
self.ui.label_3.setText("{}".format(self.filepath[0]))
|
||||
self.selected_file = True
|
||||
self.in_file = self.filepath[0]
|
||||
self.file_path = os.path.dirname(self.filepath[0])
|
||||
else:
|
||||
self.ui.label_3.setText("Το αρχείο πρέπει να είναι της μορφής .xlsx ή .xls")
|
||||
self.selected_file = False
|
||||
self.enable_create()
|
||||
|
||||
def file_template(self):
|
||||
self.filepath_template = QFileDialog.getOpenFileName(self, "Επιλογή Αρχείου")
|
||||
if self.filepath_template[0]:
|
||||
ext = os.path.splitext(self.filepath_template[0])[-1].lower()
|
||||
if ext != ".pdf":
|
||||
self.ui.label_4.setText("Το αρχείο πρέπει να είναι της μορφής .pdf")
|
||||
self.selected_template = False
|
||||
else:
|
||||
if ext in [".docx", ".doc"]:
|
||||
self.ui.log_output.appendPlainText("Επιλέχθηκε το προσχέδιο: {}".format(self.filepath_template[0]))
|
||||
self.ui.label_4.setText("{}".format(self.filepath_template[0]))
|
||||
self.selected_template = True
|
||||
self.in_template = self.filepath_template[0]
|
||||
self.template_path = os.path.dirname(self.filepath_template[0])
|
||||
else:
|
||||
self.ui.label_4.setText("Το αρχείο πρέπει να είναι της μορφής .docx ή .doc")
|
||||
self.selected_template = False
|
||||
|
||||
self.enable_create()
|
||||
|
||||
def create_button(self):
|
||||
with open(self.in_file) as fin:
|
||||
csvin = csv.DictReader(fin)
|
||||
self.create_certificates(csvin)
|
||||
df = pd.read_excel("{}".format(self.filepath[0]))
|
||||
doc = Document("{}".format(self.filepath_template[0]))
|
||||
self.create_certificates(df, doc)
|
||||
|
||||
def create_certificates(self, csv_dict):
|
||||
count = 0
|
||||
shutil.copyfile(
|
||||
"{}".format(self.filepath_template[0]),
|
||||
"{}/RESULT.pdf".format(self.file_path),
|
||||
)
|
||||
for in_row in csv_dict:
|
||||
count += 1
|
||||
packet = io.BytesIO()
|
||||
pdfmetrics.registerFont(
|
||||
TTFont("NotoMedium", self.qrc_to_bytes(":/FONTS/NotoSans-Medium.ttf"))
|
||||
)
|
||||
pdfmetrics.registerFont(
|
||||
TTFont(
|
||||
"NotoSemiMedium",
|
||||
self.qrc_to_bytes(":/FONTS/NotoSans-SemiCondensedMedium.ttf"),
|
||||
)
|
||||
)
|
||||
# pdfmetrics.registerFont(TTFont('NotoRegular', '{}/NotoSans-Regular.ttf'.format(self.font_dir)))
|
||||
# pdfmetrics.registerFont(TTFont('NotoBold', '{}/NotoSans-Bold.ttf'.format(self.font_dir)))
|
||||
# pdfmetrics.registerFont(TTFont('NotoSemi', '{}/NotoSans-SemiCondensed.ttf'.format(self.font_dir)))
|
||||
# pdfmetrics.registerFont(TTFont('NotoSemiMedium', '{}/NotoSans-SemiCondensedMedium.ttf'.format(self.font_dir)))
|
||||
def replace_text_styled(self, paragraph, key, value):
|
||||
if key in paragraph.text:
|
||||
inline = paragraph.runs
|
||||
for i in range(len(inline)):
|
||||
if key in inline[i].text:
|
||||
text = inline[i].text.replace(key, value)
|
||||
inline[i].text = text
|
||||
|
||||
can = canvas.Canvas(packet, pagesize=A4)
|
||||
can.setFont("NotoMedium", 22)
|
||||
x = can._pagesize[0] / 2
|
||||
can.drawString(x, 315, "{} {}".format(in_row["SURNAME"], in_row["NAME"]))
|
||||
can.setFont("NotoSemiMedium", 18)
|
||||
can.drawString(x, 250, "{}".format(in_row["DEPARTMENT"]))
|
||||
can.save()
|
||||
def send_email(self, data_row, attachement):
|
||||
endpoint = "https://graph.microsoft.com/v1.0/me/sendMail"
|
||||
headers = {
|
||||
"Authorization": "{}".format(self.ui.oauth2_token.toPlainText()),
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
cert_file = open("./OUTPUT/{}".format(attachement), "rb")
|
||||
data = cert_file.read()
|
||||
|
||||
email_data = {
|
||||
"message": {
|
||||
"subject": "ΠΙΣΤΟΠΟΙΗΤΙΚΟ ΠΑΡΑΚΟΛΟΥΘΗΣΗΣ ΣΕΜΙΝΑΡΙΟΥ: {}".format(data_row['ΘΕΜΑ ΣΕΜΙΝΑΡΙΟΥ']),
|
||||
"body": {
|
||||
"contentType": "Text",
|
||||
"content": "Χαίρετε,\nΣτο παρόν email επισυνάπτεται το πιστοποιητικό παρακολούθησης του σεμιναρίου {} που παρακολουθήσατε στη δομή {} το μήνα {}".format(data_row['ΘΕΜΑ ΣΕΜΙΝΑΡΙΟΥ'], data_row['CAMPUS'], data_row['DATE'])
|
||||
},
|
||||
"toRecipients": [
|
||||
{
|
||||
"emailAddress": {
|
||||
"address": "{}".format(data_row['EMAIL'])
|
||||
}
|
||||
}
|
||||
],
|
||||
"attachments": [
|
||||
{
|
||||
"@odata.type": "#microsoft.graph.fileAttachment",
|
||||
"name": "{}".format(attachement),
|
||||
"contentType": "application/pdf",
|
||||
"contentBytes": base64.b64encode(data).decode('utf-8')
|
||||
}
|
||||
]
|
||||
},
|
||||
"saveToSentItems": "true"
|
||||
}
|
||||
|
||||
packet.seek(0)
|
||||
new_pdf = PdfReader(packet)
|
||||
response = requests.post(endpoint, headers=headers, json=email_data)
|
||||
cert_file.close()
|
||||
|
||||
existing_pdf = PdfReader(open("{}/RESULT.pdf".format(self.file_path), "rb"))
|
||||
output = PdfWriter()
|
||||
if response.status_code == 202:
|
||||
self.ui.log_output.appendPlainText("Email στάλθηκε: {}".format(data_row['EMAIL']))
|
||||
else:
|
||||
self.ui.log_output.appendPlainText(f"Αποτυχία αποστολής. Status code: {response.status_code}, Error: {response.text}")
|
||||
|
||||
def create_certificates(self, in_df, in_doc):
|
||||
if not os.path.exists("./OUTPUT"):
|
||||
os.makedirs("./OUTPUT")
|
||||
|
||||
for index, row in in_df.iterrows():
|
||||
if row['ΟΝΟΜΑΤΕΠΩΝΥΜΟ'] in ['EMPTY', None] or pd.isna(row['ΟΝΟΜΑΤΕΠΩΝΥΜΟ']):
|
||||
student_name = "{} {} του {}".format(row['ΕΠΩΝΥΜΟ'],row['ΟΝΟΜΑ'], row['ΠΑΤΡΩΝΥΜΟ'])
|
||||
else:
|
||||
student_name = "{} {} του {}".format(row['ΟΝΟΜΑΤΕΠΩΝΥΜΟ'], row['ΠΑΤΡΩΝΥΜΟ'])
|
||||
|
||||
for page in existing_pdf.pages:
|
||||
output.add_page(page)
|
||||
page = existing_pdf.pages[0]
|
||||
page.merge_page(new_pdf.pages[0])
|
||||
output.add_page(page)
|
||||
mock_data = {
|
||||
'ΟΝΟΜΑΤΕΠΩΝΥΜΟ': student_name,
|
||||
'ΘΕΜΑ_ΣΕΜΙΝΑΡΙΟΥ': row['ΘΕΜΑ ΣΕΜΙΝΑΡΙΟΥ'],
|
||||
'DATE': row['DATE'],
|
||||
'CAMPUS': row['CAMPUS'],
|
||||
'EMAIL': row['EMAIL']
|
||||
}
|
||||
|
||||
outputStream = open("{}/RESULT.pdf".format(self.file_path), "wb")
|
||||
output.write(outputStream)
|
||||
outputStream.close()
|
||||
for paragraph in in_doc.paragraphs:
|
||||
for key in mock_data:
|
||||
self.replace_text_styled(paragraph, key, mock_data[key])
|
||||
|
||||
if os.path.exists("./edit.docx"):
|
||||
os.remove("./edit.docx")
|
||||
in_doc.save('edit.docx')
|
||||
|
||||
output = convert(source="edit.docx", output_dir="./", soft=0)
|
||||
fname = output.rsplit('/')[-1]
|
||||
shutil.move("./{}".format(fname), "./OUTPUT/{}.pdf".format(student_name.replace(" ", "_")))
|
||||
|
||||
print("PDF created: {}.pdf".format(student_name.replace(" ", "_")))
|
||||
if self.ui.enable_email.isChecked():
|
||||
self.send_email(row, attachement="{}.pdf".format(student_name.replace(" ", "_")))
|
||||
self.ui.label_4.setText(
|
||||
"Το αρχείο PDF δημιουργήθηκε εντός του φακέλου του .csv"
|
||||
"Τα αρχείο PDF δημιουργήθηκαν εντός του φακέλου OUTPUT."
|
||||
)
|
||||
self.ui.create_button.setEnabled(False)
|
||||
|
||||
|
||||
if os.path.exists("./edit.docx"):
|
||||
os.remove("./edit.docx")
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
|
Loading…
x
Reference in New Issue
Block a user