20241019165800

This commit is contained in:
zhaoyafan 2024-10-19 16:58:07 +08:00
parent 11b7c0dc2f
commit c2427efb42
2 changed files with 187 additions and 21 deletions

112
main.py
View File

@ -13,12 +13,12 @@ import pywintypes
import hashlib
import win32com.client
import win32print
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QLabel, QComboBox, QCheckBox, QLineEdit, QAction, QMenu, QMessageBox, QPushButton, QVBoxLayout, QHBoxLayout, QFileDialog
from PyQt5.QtCore import Qt, QCoreApplication
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QLabel, QComboBox, QCheckBox, QLineEdit, QAction, QMenu, \
QMessageBox, QPushButton, QVBoxLayout, QHBoxLayout, QFileDialog, QDialog
from PyQt5.QtCore import Qt, QCoreApplication, QTimer, QPropertyAnimation
from PyQt5.QtGui import QPixmap, QIntValidator
from threading import RLock
sys.path.append(os.path.dirname(__file__))
clr.AddReference('BarTender')
try:
@ -93,12 +93,14 @@ if os.name == 'nt':
PVOID = c_void_p
class _OFFSET(Structure):
_fields_ = [
('Offset', DWORD),
('OffsetHigh', DWORD)
]
class _OFFSET_UNION(Union):
_fields_ = [
('_offset', _OFFSET),
@ -106,6 +108,7 @@ if os.name == 'nt':
]
_anonymous_ = ['_offset']
class OVERLAPPED(Structure):
_fields_ = [
('Internal', ULONG_PTR),
@ -115,6 +118,7 @@ if os.name == 'nt':
]
_anonymous_ = ['_offset_union']
LPOVERLAPPED = POINTER(OVERLAPPED)
LockFileEx = windll.kernel32.LockFileEx
LockFileEx.restype = BOOL
@ -148,6 +152,7 @@ if os.name == 'nt':
else:
try:
import fcntl
LOCK_SH = fcntl.LOCK_SH
LOCK_NB = fcntl.LOCK_NB
LOCK_EX = fcntl.LOCK_EX
@ -155,6 +160,7 @@ else:
except (ImportError, AttributeError):
LOCK_EX = LOCK_SH = LOCK_NB = 0
def flock(f, flags):
return flags == LOCK_UN
else:
@ -454,10 +460,13 @@ class BarTenderPrint:
self.bt_format.PrintOut(False, False)
def generate_preview(self):
path = os.path.abspath(os.path.join(tempfile.gettempdir(), '%s%s.png' % ('preview_', int(round(time.time() * 1000)))))
path = os.path.abspath(
os.path.join(tempfile.gettempdir(), '%s%s.png' % ('preview_', int(round(time.time() * 1000)))))
if (self.bt_format is not None) == 1:
self.logger.i('%s%s' % ('Generate preview to ', path))
self.bt_format.ExportToFile(path, 'PNG', BarTender.BtColors.btColors24Bit, BarTender.BtResolution.btResolutionPrinter, BarTender.BtSaveOptions.btDoNotSaveChanges)
self.bt_format.ExportToFile(path, 'PNG', BarTender.BtColors.btColors24Bit,
BarTender.BtResolution.btResolutionPrinter,
BarTender.BtSaveOptions.btDoNotSaveChanges)
return path
def quit(self):
@ -518,7 +527,8 @@ class CustomPushButton(QPushButton):
class CustomLabel(QLabel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setStyleSheet('font-size: 12px; font-family: \'Microsoft YaHei\'; color: #0C0C0C; border: 1px solid #0C0C0C;')
self.setStyleSheet(
'font-size: 12px; font-family: \'Microsoft YaHei\'; color: #0C0C0C; border: 1px solid #0C0C0C;')
class CustomComboBox(QComboBox):
@ -549,12 +559,17 @@ class MainWindow(QMainWindow):
def __init__(self, logger: Logger):
super().__init__()
self.app_name = '标签打印'
self.app_version = ('1.0.3', '20240810', 'zhaoyafan', 'zhaoyafan@foxmail.com', 'https://www.fanscloud.net/')
self.app_version = ('1.0.4', '20241019', 'zhaoyafan', 'zhaoyafan@foxmail.com', 'https://www.fanscloud.net/')
self.logger = logger
self.setting = Setting(os.path.abspath(os.path.join(tempfile.gettempdir(), '%s.config' % self.md5(__file__)[:16])), {})
self.toast = ToastNotification()
self.setting = Setting(
os.path.abspath(os.path.join(tempfile.gettempdir(), '%s.config' % self.md5(__file__)[:16])), {})
self.bt = BarTenderPrint(logger=self.logger)
self.sv = ScanVerify(logger=self.logger, rule_file=os.path.abspath(os.path.join(os.path.dirname(__file__), 'rules.json')))
self.ditto = Ditto(db_file=os.path.abspath(os.path.join(tempfile.gettempdir(), '%s.db' % self.md5(__file__)[:16])), class_name='LabelPrint', limit_time=7776000, limit_rows=100000)
self.sv = ScanVerify(logger=self.logger,
rule_file=os.path.abspath(os.path.join(os.path.dirname(__file__), 'rules.json')))
self.ditto = Ditto(
db_file=os.path.abspath(os.path.join(tempfile.gettempdir(), '%s.db' % self.md5(__file__)[:16])),
class_name='LabelPrint', limit_time=7776000, limit_rows=100000)
self.last_opened_template = ['', '']
self.input_convert_letter = 0
self.input_scan_prohibited_enter = 0
@ -666,7 +681,8 @@ class MainWindow(QMainWindow):
r_layout_2.addWidget(self.chkDET)
# Scan
self.edtSCN = CustomLineEdit('')
self.edtSCN.setStyleSheet('QLineEdit {font-size: 28px; font-family: \'Microsoft YaHei\'; color: #000000; background-color: #FFFFCC;}')
self.edtSCN.setStyleSheet(
'QLineEdit {font-size: 28px; font-family: \'Microsoft YaHei\'; color: #000000; background-color: #FFFFCC;}')
self.edtSCN.setFixedSize(455, 45)
r_layout_3.addWidget(self.edtSCN)
# Print button
@ -683,7 +699,8 @@ class MainWindow(QMainWindow):
self.setFixedSize(self.minimumSizeHint())
screen_rect = QApplication.desktop().availableGeometry()
window_rect = self.geometry()
self.move(int((screen_rect.width() - window_rect.width()) * 0.5), int((screen_rect.height() - window_rect.height()) * 0.5))
self.move(int((screen_rect.width() - window_rect.width()) * 0.5),
int((screen_rect.height() - window_rect.height()) * 0.5))
self.edtSCN.setFocus()
self.show()
self.load_setting()
@ -696,7 +713,8 @@ class MainWindow(QMainWindow):
# load blockRepeat
self.blockRepeatAction.setChecked(bool(self.setting['blockRepeat']))
# load printer
self.slcSPT.setCurrentIndex(next((index for index, item in enumerate(self.bt.printer_list) if item == self.setting['printer']), 0))
self.slcSPT.setCurrentIndex(
next((index for index, item in enumerate(self.bt.printer_list) if item == self.setting['printer']), 0))
# load checker
self.slcSVR.setCurrentIndex(self.setting['checker'] or 0)
# load printCopies
@ -714,7 +732,7 @@ class MainWindow(QMainWindow):
def clearRecordActionFunction(self):
count = self.ditto.clear()
if (count > 0) == 1:
QMessageBox.information(self, '提示', '打印记录已经清空:%s' % (count,))
self.toast.show_toast('已成功清空%s条打印记录' % (count,))
def designStateActionFunction(self, checked):
if (not self.bt.bt_app) == 1:
@ -745,7 +763,8 @@ class MainWindow(QMainWindow):
def aboutWindowActionFunction(self):
_c = self.app_version
if (not _c) == 0:
QMessageBox.information(self, '关于', "" 'version: %s, build: %s, author: %s, email: %s, site: %s' % (_c[0], _c[1], _c[2], _c[3], '<a href=\'%s\'>%s</a>' % (_c[4], _c[4])))
QMessageBox.information(self, '关于', "" 'version: %s, build: %s, author: %s, email: %s, site: %s' % (
_c[0], _c[1], _c[2], _c[3], '<a href=\'%s\'>%s</a>' % (_c[4], _c[4])))
@staticmethod
def md5(input_data):
@ -792,7 +811,8 @@ class MainWindow(QMainWindow):
def set_preview(self, preview_image: str):
if (preview_image and os.path.exists(preview_image)) == 1:
pixmap = QPixmap(preview_image)
pixmap = pixmap.scaled(self.labPRV.size(), aspectRatioMode=Qt.KeepAspectRatio, transformMode=Qt.SmoothTransformation)
pixmap = pixmap.scaled(self.labPRV.size(), aspectRatioMode=Qt.KeepAspectRatio,
transformMode=Qt.SmoothTransformation)
self.labPRV.setPixmap(pixmap)
if (tempfile.gettempdir() in preview_image) == 1:
rm(preview_image)
@ -809,6 +829,7 @@ class MainWindow(QMainWindow):
self.set_preview(self.bt.generate_preview())
self.last_opened_template[0] = file
self.last_opened_template[1] = self.md5(open(file, 'rb'))
self.toast.show_toast('模板加载成功')
except pywintypes.com_error as e:
t = str(e.args[1])
m = str(e.args[2][2] if isinstance(e.args[2], tuple) else e.args[2])
@ -822,7 +843,8 @@ class MainWindow(QMainWindow):
QMessageBox.critical(self, '错误', '%s' % e)
def on_open_template_file(self):
filename, _ = QFileDialog.getOpenFileName(self, '打开文件', os.path.dirname(self.last_opened_template[0]), 'BarTender 文档 (*.btw)')
filename, _ = QFileDialog.getOpenFileName(self, '打开文件', os.path.dirname(self.last_opened_template[0]),
'BarTender 文档 (*.btw)')
if (filename and os.path.exists(filename)) == 1:
self.load_template(filename)
self.setting['template'] = filename
@ -833,7 +855,7 @@ class MainWindow(QMainWindow):
self.bt.start_printing_template()
self.set_preview(self.bt.generate_preview())
return None
QMessageBox.critical(self, '错误', '请先加载模板文件')
self.toast.show_toast('请先加载模板文件')
except pywintypes.com_error as e:
t = str(e.args[1])
m = str(e.args[2][2] if isinstance(e.args[2], tuple) else e.args[2])
@ -903,14 +925,18 @@ class MainWindow(QMainWindow):
def on_convert_letter_changed(self, checked):
if (checked == 2) == 1:
self.input_convert_letter = 1
self.toast.show_toast('强制大写开启')
else:
self.input_convert_letter = 0
self.toast.show_toast('强制大写关闭')
def on_prohibit_enter_changed(self, checked):
if (checked == 2) == 1:
self.input_scan_prohibited_enter = 1
self.toast.show_toast('禁用回车开启')
else:
self.input_scan_prohibited_enter = 0
self.toast.show_toast('禁用回车关闭')
def on_print_scan_enter(self):
self.input_scan_prohibited_enter or self.on_start_printing()
@ -923,13 +949,15 @@ class MainWindow(QMainWindow):
text = edit.text().strip()
edit.setText(text)
if (self.bt.bt_format is None) == 1:
self.toast.show_toast('未加载模板文件')
edit.selectAll()
return None
if (text == '') == 1:
self.toast.show_toast('输入的内容为空')
edit.selectAll()
return None
if (not self.sv.verify(text)) == 1:
QMessageBox.critical(self, '错误', '打印的内容不符合验证规则:\n\n%s' % (text,))
self.toast.show_toast('输入的内容不符合验证规则')
edit.selectAll()
return None
if (not self.ditto.addit(text) and self.setting['blockRepeat']) == 1:
@ -953,10 +981,52 @@ class MainWindow(QMainWindow):
QMessageBox.critical(self, '错误', '%s' % e)
class ToastNotification(QDialog):
def __init__(self):
super().__init__()
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.WindowType.Tool)
layout = QVBoxLayout()
layout.setContentsMargins(5, 705, 5, 5)
self.label = QLabel("")
self.label.setStyleSheet("font-family: 'Microsoft YaHei'; font-size: 24px; color: #ffffff;")
layout.addWidget(self.label)
self.setLayout(layout)
self.setAttribute(Qt.WA_TranslucentBackground)
self.setStyleSheet("background-color: rgba(65, 65, 65, 180); border-radius: 5px; padding: 10px 16px 10px 16px")
self.adjustSize()
self.timer = QTimer(self)
self.timer.setInterval(2000)
self.timer.timeout.connect(self.close)
self.fade_animation = QPropertyAnimation(self, b"windowOpacity")
self.fade_animation.setDuration(500)
def show_toast(self, message):
self.close()
self.label.setText(message)
self.timer.isActive() and self.timer.stop()
self.timer.start()
self.adjustSize()
self.fade_animation.setStartValue(0.0)
self.fade_animation.setEndValue(1.0)
self.show()
self.fade_animation.start()
def closeEvent(self, event):
if self.timer.isActive():
self.timer.stop()
super().closeEvent(event)
if __name__ == '__main__':
if (os.path.basename(__file__).lower().endswith('.int')) == 1:
QCoreApplication.addLibraryPath(os.path.abspath(os.path.join(os.path.dirname(__file__), 'site-packages/PyQt5/Qt5/plugins')))
f_lock = open(file=os.path.abspath(os.path.join(tempfile.gettempdir(), '%s.lock' % hashlib.md5(bytes(__file__, encoding='utf-8')).hexdigest()[:16])), mode='w', encoding='utf-8')
QCoreApplication.addLibraryPath(
os.path.abspath(os.path.join(os.path.dirname(__file__), 'site-packages/PyQt5/Qt5/plugins')))
f_lock = open(file=os.path.abspath(os.path.join(tempfile.gettempdir(), '%s.lock' % hashlib.md5(
bytes(__file__, encoding='utf-8')).hexdigest()[:16])), mode='w', encoding='utf-8')
if (not flock(f_lock, LOCK_EX | LOCK_NB)) == 1:
app = QApplication(sys.argv)
msg = QMessageBox()

View File

@ -66,5 +66,101 @@
[
"24位长度",
"^.{24}$"
],
[
"25位长度",
"^.{25}$"
],
[
"26位长度",
"^.{26}$"
],
[
"27位长度",
"^.{27}$"
],
[
"28位长度",
"^.{28}$"
],
[
"29位长度",
"^.{29}$"
],
[
"30位长度",
"^.{30}$"
],
[
"31位长度",
"^.{31}$"
],
[
"32位长度",
"^.{32}$"
],
[
"33位长度",
"^.{33}$"
],
[
"34位长度",
"^.{34}$"
],
[
"35位长度",
"^.{35}$"
],
[
"36位长度",
"^.{36}$"
],
[
"37位长度",
"^.{37}$"
],
[
"38位长度",
"^.{38}$"
],
[
"39位长度",
"^.{39}$"
],
[
"40位长度",
"^.{40}$"
],
[
"41位长度",
"^.{41}$"
],
[
"42位长度",
"^.{42}$"
],
[
"43位长度",
"^.{43}$"
],
[
"44位长度",
"^.{44}$"
],
[
"45位长度",
"^.{45}$"
],
[
"46位长度",
"^.{46}$"
],
[
"47位长度",
"^.{47}$"
],
[
"48位长度",
"^.{48}$"
]
]