Обновить print-labels-gui.py

переделка под графический интерфейс
добавление логики под графический интерфейс
мелкие правки  передачи данных в методы генерации
This commit is contained in:
Юрий Кожушко 2024-10-09 16:37:54 +03:00
parent a57b7f1ea2
commit 6ac996d6c9
2 changed files with 248 additions and 106 deletions

View File

@ -1,106 +0,0 @@
import argparse
import pathlib
import subprocess
import sys
import time
from textwrap import dedent
from PIL import Image, ImageOps, ImageDraw, ImageFont
from barcode import EAN13
from barcode.writer import ImageWriter
PRODUCT_TYPES = {
"comp": ("21", "инвентарный номер для компьютера"),
"mon": ("22", "инвентарный номер для монитора"),
"net": ("23", "инвентарный номер для сетевого оборудования"),
"token": ("24", "инвентарный номер для токена"),
"print": ("25", "инвентарный номер для принтера/МФУ"),
"flash": ("26", "инвентарный номер для флешки"),
"hid": ("27", "инвентарный номер для HID устройств"),
"ups": ("28", "инвентарный номер для UPS устройств"),
"other": ("29", "инвентарный номер для других устройств"),
}
BARCODES_PATH = pathlib.Path().absolute() / "barcodes"
def gen_ean13(ptype: str):
product_code = PRODUCT_TYPES[ptype][0]
digits = product_code + str(round(time.time()))
digits = [int(i) for i in digits]
checksum = (10 - (sum(digits[1::2]) * 3 + sum(digits[::2])) % 10) % 10
return "".join(str(i) for i in (digits + [checksum]))
def create_code_png(filename: str | pathlib.Path, code, text):
if not filename.parent.exists():
filename.parent.mkdir(parents=True)
my_code = EAN13(code, writer=ImageWriter())
image = my_code.render(
writer_options={
"module_height": 11.0,
"module_width": 0.3,
"dpi": 169,
"font_size": 0,
"text_distance": 1,
"write_text": None,
}
)
image = image.convert("1", dither=Image.Dither.NONE)
image = ImageOps.expand(image, border=17, fill=1)
draw = ImageDraw.Draw(image)
dst = "terminus.pil"
font = ImageFont.load(dst)
text_length = draw.textlength(text, font=font)
code_text_length = draw.textlength(code, font=font)
draw.text(((image.width - text_length) / 2, 3), text, fill="black", font=font)
draw.text(
((image.width - code_text_length) / 2, 100),
code,
fill="black",
font=font,
)
image.save(filename)
def parse_args():
help_for_text = """\
code is must be a 13 digit code
or one of the following:
"""
help_for_text = dedent(help_for_text) + "\n".join(
f"{code} - {desc[1]}" for code, desc in PRODUCT_TYPES.items()
)
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument("code", type=str, help=help_for_text)
parser.add_argument(
"text", type=str, nargs="?", default="", help="Description for barcode"
)
parser.add_argument("--print", action=argparse.BooleanOptionalAction, default=True)
return parser.parse_args()
def main():
args = parse_args()
if args.code not in PRODUCT_TYPES:
if args.code.isdigit() and len(args.code) == 13:
barcode = args.code
else:
print("Invalid args")
sys.exit(1)
else:
barcode = gen_ean13(args.code)
filename = BARCODES_PATH / f"{barcode}.png"
print(f"Generated code: {barcode}")
create_code_png(filename, barcode, args.text)
if args.print:
subprocess.run(["ptouch-print", "--image", filename])
if __name__ == "__main__":
main()

248
print-labels-gui.py Executable file
View File

@ -0,0 +1,248 @@
#!/usr/bin/python3
"""
Скрипт с графическим интерфейсом
для печати этикеток на принтере серий brother p-touch,
на основе https://gitea.basealt.ru/polkovnikovaav/ptouch-print-labels
подробности и настройки в README.md
"""
from PySide6.QtWidgets import QApplication
from PySide6 import QtGui,QtWidgets
from PySide6.QtWidgets import QMainWindow, QWidget, QLabel,QVBoxLayout, QPushButton,QGridLayout,QLineEdit, QComboBox,QMessageBox
import subprocess
import time
import os
import sys
from PIL import Image, ImageOps, ImageDraw, ImageFont
from barcode import EAN13
from barcode.writer import ImageWriter
# главное окно
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.conf="barcode2-gui.ini"
self.setWindowTitle('Печать стикеров')
self.q_button_start = QPushButton('печать')
self.q_button_start.clicked.connect(self.start_print)
self.q_label1 = QLabel()
self.q_label2 = QLabel()
self.q_label3 = QLabel()
self.q_label1.setText("Введите текст:")
self.q_label2.setText("Введите SN (не вводить - генерация):")
self.q_label3.setText("Выберите тип устройства:")
self.q_combo = QComboBox(self)
self.q_combo.addItem("компьютер")
self.q_combo.addItem("монитор")
self.q_combo.addItem("сетевое об.")
self.q_combo.addItem("токен")
self.q_combo.addItem("принтер/МФУ")
self.q_combo.addItem("флешка")
self.q_combo.addItem("HID")
self.q_combo.addItem("UPS")
self.q_combo.addItem("другое")
self.q_button_start=QPushButton("печать")
self.q_button_start.setMinimumSize(20,80)
self.q_button_start.clicked.connect(self.start_print)
self.grid_layout = QGridLayout()
self.layout1 = QVBoxLayout()
self.q_edit1=QLineEdit() # текст (над ШК)
self.q_edit2=QLineEdit() # вводимый свой серийник (если не нужна генерациия)
self.q_edit3=QLineEdit() # выводимый SN для справки
self.q_edit3.setReadOnly(True)
self.layout1.addWidget(self.q_label1)
self.layout1.addWidget(self.q_edit1)
self.layout1.addWidget(self.q_label2)
self.layout1.addWidget(self.q_edit2)
self.layout1.addWidget(self.q_label3)
self.layout1.addWidget(self.q_combo)
self.layout1.addWidget(self.q_button_start)
self.layout1.addWidget(self.q_edit3)
self.grid_layout.setRowStretch(5,0)
self.grid_layout.setRowStretch(20,1)
self.grid_layout.setRowStretch(1,2)
self.grid_layout.setRowStretch(1,3)
self.grid_layout.setRowStretch(1,4)
self.grid_layout.setRowStretch(100,5)
self.grid_layout.setRowStretch(1,6)
self.grid_layout.addWidget(self.q_label1, 0,0)
self.grid_layout.addWidget(self.q_edit1, 1,0)
self.grid_layout.addWidget(self.q_label2, 2,0)
self.grid_layout.addWidget(self.q_edit2, 3,0)
self.grid_layout.addWidget(self.q_label3, 4,0)
self.grid_layout.addWidget(self.q_combo, 5,0)
self.grid_layout.addWidget(self.q_button_start,6,0)
self.grid_layout.addWidget(self.q_edit3,7,0) # шк-код текстом
self.content_widget = QWidget()
self.content_widget.setLayout(self.grid_layout)
self.setCentralWidget(self.content_widget)
# выпадающий список типов и кодовые соответствия
self.combo_type_items = {
"компьютер":"21",
"монитор":"22",
"сетевое об.":"23",
"токен":"24",
"принтер/МФУ":"25",
"флешка":"26",
"HID":"27",
"UPS":"28",
"другое":"29",
}
# получаем текущий каталог и переходим в него
def set_current_location(self):
path_there = os.path.dirname(os.path.realpath(__file__))
os.chdir(path_there)
# генерация штрих-кода с контрльной суммой
def gen_ean13(self,product_code: str):
# добавляем псевдослучаное значение (от времени к коду продукта)
digits_s= product_code + str(round(time.time()))
# строка продукта в список чисел
digits = [int(i) for i in digits_s]
# контрольная сумма по алгоритму ЛУна
checksum = (10 - (sum(digits[1::2]) * 3 + sum(digits[::2])) % 10) % 10
return "".join(str(i) for i in (digits + [checksum]))
# генерация картинки
def create_code_png(self,filename, code, text):
self.set_current_location()
ean13_code = EAN13(code, writer=ImageWriter())
image = ean13_code.render(
writer_options={
"module_height": 11.0,
"module_width": 0.3,
"dpi": 169,
"font_size": 0,
"text_distance": 1,
"write_text": None,
}
)
image = image.convert("1", dither=Image.Dither.NONE)
image = ImageOps.expand(image, border=17, fill=1)
draw = ImageDraw.Draw(image)
# загружаем шрифт
dst = "terminus.pil"
font = ImageFont.load(dst)
text_length = draw.textlength(text, font=font)
code_text_length = draw.textlength(code, font=font)
draw.text(((image.width - text_length) / 2, 3), text, fill="black", font=font)
draw.text(
((image.width - code_text_length) / 2, 100),
code,
fill="black",
font=font,
)
image.save(filename)
#запуск всего процесса (генерация и печать)
def start_print(self):
# берем ID по типу оборудования
type_device=self.combo_type_items[self.q_combo.currentText()]
# берем текст подписи
text_data=self.q_edit1.text()
barcode = self.gen_ean13(type_device)
# если ввели свой SN, передаем его в создание ШК
if len(self.q_edit2.text())>0:
if len(self.q_edit2.text())==12:
barcode=self.q_edit2.text()
else:
msg = QMessageBox()
msg.setWindowTitle("Внимание")
msg.setText("Должно быть 12 знаков")
msg.setIcon(QMessageBox.Warning)
msg.exec_()
exit(0)
if len(self.q_edit2.text())==0:
self.q_edit3.setText(barcode)
self.create_code_png("temp.png", barcode, text_data)
self.start_process()
# запуск непосредственно печати, с SUDO
def start_process(self):
password, ok = QtWidgets.QInputDialog.getText(None, "SUDO", "Введите пароль:",QLineEdit.Password)
if ok:
subprocess.run(["sudo", "-S", "ptouch-print", "--image", "temp.png"], input=password.encode() + b"\n")
# если без sudo
# def start_process(self):
# subprocess.run(["sudo","ptouch-print", "--image", "temp.png"])
if __name__ == '__main__':
app = QApplication(sys.argv)
configparser = ChildProcessError
# таблица стилей (задаем размер шрифта)
style_sheet01 = """
* {
font-size: 11pt;
}
"""
# Применение таблицы стилей (размер шрифта) ко всему приложению
app.setStyleSheet(style_sheet01)
window = MainWindow()
# Установить размер окна
window.resize(500, 300)
# Получить допустимое разрешение
SrcSize = QtGui.QScreen.availableGeometry(QApplication.primaryScreen())
frmX = (SrcSize.width() - window.width())/2
frmY = (SrcSize.height() - window.height())/2
window.move(frmX, frmY)
window.show()
sys.exit(app.exec_())