20241019165800
This commit is contained in:
parent
11b7c0dc2f
commit
c2427efb42
112
main.py
112
main.py
|
@ -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()
|
||||
|
|
96
rules.json
96
rules.json
|
@ -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}$"
|
||||
]
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue