|
@@ -0,0 +1,1002 @@
|
|
|
+# -*- coding: utf-8 -*-
|
|
|
+# import time
|
|
|
+# import module.log as log
|
|
|
+import sys
|
|
|
+import os
|
|
|
+import time
|
|
|
+from module.other.log import MyLogger
|
|
|
+from UI.main_ui import Ui_MainWindow
|
|
|
+from PySide6.QtWidgets import *
|
|
|
+from PySide6.QtCore import *
|
|
|
+from PySide6.QtGui import *
|
|
|
+import settings
|
|
|
+
|
|
|
+from module.module_resize_pic import ResizePic
|
|
|
+from module.other.module_setting import ToSetting
|
|
|
+from module.other.module_online_data import GetOnlineData
|
|
|
+from module.module_login import LoginWindow
|
|
|
+from module.remove_bg_pixian import RemoveBgPiXian
|
|
|
+from module.deal_cutout import DealCutout
|
|
|
+
|
|
|
+import requests
|
|
|
+from module.module_move_files import MoveFiles
|
|
|
+import webbrowser
|
|
|
+import io
|
|
|
+from PIL import Image
|
|
|
+from qt_material import apply_stylesheet,list_themes
|
|
|
+
|
|
|
+"""
|
|
|
+抠图软件,使用pixian抠图
|
|
|
+"""
|
|
|
+
|
|
|
+
|
|
|
+class MainWindow(QMainWindow, Ui_MainWindow):
|
|
|
+ sign_self = Signal(dict)
|
|
|
+
|
|
|
+ def __init__(self):
|
|
|
+ super().__init__()
|
|
|
+ self.deal_data_info_1 = {"time": time.time(),
|
|
|
+ "num": 1}
|
|
|
+ self.to_end = False
|
|
|
+ self.setupUi(self)
|
|
|
+ self.login_show(flag="hide")
|
|
|
+ self.logger = MyLogger().logger
|
|
|
+ self.setWindowIcon(QIcon("resource\images\icon.png"))
|
|
|
+ self.setWindowTitle("惠利玛图片抠图工具V{}-{}".format(settings.Version, settings.env))
|
|
|
+ self.setFixedSize(self.width(), self.height())
|
|
|
+ # ------------------
|
|
|
+ self.file_path = ""
|
|
|
+ self.one_image_path = ""
|
|
|
+ # ------------------
|
|
|
+ self.mods_list = []
|
|
|
+ self.state = 0
|
|
|
+ self.remaining_times = 0 # 剩余总次数
|
|
|
+ # ---------------
|
|
|
+ self.total_num = 0 # 总条数
|
|
|
+ self.pending_processing = 0 # 待处理
|
|
|
+ self.processing_failed = 0 # 处理失败
|
|
|
+ self.processing_successfully = 0 # 处理成功
|
|
|
+ self.processing_error = 0 # 处理异常
|
|
|
+ # -------------------
|
|
|
+
|
|
|
+ self.state_change(self.state)
|
|
|
+ self.need_cutout_images = []
|
|
|
+ self.mods = False
|
|
|
+ self.r_pixian = RemoveBgPiXian()
|
|
|
+ self._app = None
|
|
|
+ self.get_online_data = GetOnlineData()
|
|
|
+ self.cumulative_frequency_times = 0 # 本次抠图次数
|
|
|
+ self.qss_style()
|
|
|
+ self.init()
|
|
|
+ self.state_change(to_state=0)
|
|
|
+ QTimer.singleShot(500, self.check_versions) # 检查版本
|
|
|
+ QTimer.singleShot(1000, self.check_login)
|
|
|
+
|
|
|
+ def qss_style(self):
|
|
|
+ style_sheet = """
|
|
|
+ /* 滚动条的整体样式 */
|
|
|
+ QScrollBar {
|
|
|
+ background-color: #F0F0F0;
|
|
|
+ width: 5px;
|
|
|
+ height: 15px;
|
|
|
+ border: 1px;
|
|
|
+ margin: 15px 0px 15px 0px;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 滚动条的滑块 */
|
|
|
+ QScrollBar::handle {
|
|
|
+ background-color: #e3e3e3;
|
|
|
+ min-height: 20px;
|
|
|
+ border-radius: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 滚动条滑块悬停时的样式 */
|
|
|
+ QScrollBar::handle:hover {
|
|
|
+ background-color: #555555;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 滚动条滑块按下时的样式 */
|
|
|
+ QScrollBar::handle:pressed {
|
|
|
+ background-color: #444444;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 滚动条的上下按钮 */
|
|
|
+ QScrollBar::add-line, QScrollBar::sub-line {
|
|
|
+ border: none;
|
|
|
+ background-color: #F0F0F0;
|
|
|
+ height: 0px;
|
|
|
+ width: 0px;
|
|
|
+ subcontrol-position: both-ends;
|
|
|
+ subcontrol-origin: margin;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 滚动条的上下按钮不可见 */
|
|
|
+ QScrollBar::add-page, QScrollBar::sub-page {
|
|
|
+ background: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 滚动条的滑块到达顶部/底部时的样式 */
|
|
|
+ QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
|
|
|
+ height: 0px;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 滚动条的滑块到达顶部/底部时的样式 */
|
|
|
+ QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
|
|
|
+ background: none;
|
|
|
+ }
|
|
|
+ """
|
|
|
+ # 使用QSS设置圆角
|
|
|
+ self.setStyleSheet(style_sheet)
|
|
|
+
|
|
|
+ def login_info_is_false(self):
|
|
|
+ reply = QMessageBox.question(self, '确认', "登录信息已失效", QMessageBox.Yes)
|
|
|
+ QTimer.singleShot(500, self.to_logout)
|
|
|
+
|
|
|
+ def refresh_times(self, is_online=True, remaining_times=None):
|
|
|
+ # 刷新剩余次数
|
|
|
+ if remaining_times is not None:
|
|
|
+ self.remaining_times = remaining_times
|
|
|
+
|
|
|
+ if is_online:
|
|
|
+ _ = self.get_online_data.get_cutout_image_times()
|
|
|
+ if _ is False:
|
|
|
+ self.remaining_times = 0
|
|
|
+ self.login_info_is_false()
|
|
|
+ else:
|
|
|
+ if "balance" in _:
|
|
|
+ self.remaining_times = _["balance"]
|
|
|
+ self.label_11.setText("{}".format(self.remaining_times))
|
|
|
+ self.label_13.setText("{}".format(self.cumulative_frequency_times))
|
|
|
+ self.label_10.show()
|
|
|
+
|
|
|
+ if self.remaining_times <= 0:
|
|
|
+ return False
|
|
|
+ return True
|
|
|
+
|
|
|
+ def check_path(self, _path):
|
|
|
+ if not os.path.exists(_path):
|
|
|
+ os.mkdir(_path)
|
|
|
+ return True
|
|
|
+
|
|
|
+ def show_resize_pic_ui(self, *args):
|
|
|
+ self.show_resize_pic = ResizePic()
|
|
|
+
|
|
|
+ def closeEvent(self, event):
|
|
|
+ print("to close")
|
|
|
+ reply = QMessageBox.question(self, '确认', "确定要关闭窗口吗?", QMessageBox.Yes | QMessageBox.No)
|
|
|
+ if reply == QMessageBox.Yes:
|
|
|
+ # 如果用户点击了"是"按钮,则正常关闭窗口
|
|
|
+ super().closeEvent(event)
|
|
|
+ os._exit(0)
|
|
|
+ else:
|
|
|
+ # 否则取消关闭操作
|
|
|
+ event.ignore()
|
|
|
+
|
|
|
+ def login_show(self, flag="show"):
|
|
|
+ if flag == "show":
|
|
|
+ self.label_2.show()
|
|
|
+ self.label_7.show()
|
|
|
+ self.label_10.show()
|
|
|
+ self.label_9.show()
|
|
|
+ self.label_11.show()
|
|
|
+ self.label_12.show()
|
|
|
+ self.label_13.show()
|
|
|
+ self.label_2.setText("--")
|
|
|
+ self.label_7.setText("--")
|
|
|
+ self.label_14.show()
|
|
|
+ self.label_11.setText("--")
|
|
|
+ self.label_13.setText("--")
|
|
|
+ else:
|
|
|
+ self.label_14.hide()
|
|
|
+ self.label_2.hide()
|
|
|
+ self.label_7.hide()
|
|
|
+ self.label_10.hide()
|
|
|
+ self.label_9.hide()
|
|
|
+ self.label_11.hide()
|
|
|
+ self.label_12.hide()
|
|
|
+ self.label_13.hide()
|
|
|
+
|
|
|
+ def label_refresh_times(self, *args):
|
|
|
+ self.label_11.setText("--")
|
|
|
+ self.label_11.show()
|
|
|
+ time.sleep(0.1)
|
|
|
+ self.refresh_times()
|
|
|
+ pass
|
|
|
+
|
|
|
+ def init(self):
|
|
|
+
|
|
|
+ self.label.setText("未避免重复抠图等软件只允许扣jpg格式图片")
|
|
|
+ self.label.show()
|
|
|
+ self.label_5.show()
|
|
|
+ self.label_5.move(40, 40)
|
|
|
+ self.label_14.hide()
|
|
|
+ self.label_14.mousePressEvent = self.label_refresh_times
|
|
|
+
|
|
|
+ self.deal_cutout_mode = DealCutout(windows=self)
|
|
|
+ self.deal_cutout_mode.signal_data.connect(self.deal_sign_data)
|
|
|
+ self.label_5.mousePressEvent = self.select_file_path
|
|
|
+ self.label_8.mousePressEvent = self.select_file_path
|
|
|
+
|
|
|
+ self.pushButton_6.clicked.connect(self.stop_func) # 停止按钮
|
|
|
+
|
|
|
+ self.sign_self.connect(self.deal_sign_data)
|
|
|
+ self.pushButton.clicked.connect(lambda: self.deal_sign_data({"_type": "run_cutout"}))
|
|
|
+ self.pushButton_6.hide()
|
|
|
+
|
|
|
+ # 菜单
|
|
|
+ self.action_2.triggered.connect(self.show_resize_pic_ui)
|
|
|
+ self.action_5.triggered.connect(self.show_move_file_ui)
|
|
|
+ self.action_10.triggered.connect(self.show_to_setting)
|
|
|
+ self.action_11.triggered.connect(self.contact_us)
|
|
|
+
|
|
|
+ def contact_us(self, *args):
|
|
|
+ url = 'https://www.valimart.net/'
|
|
|
+ webbrowser.open(url)
|
|
|
+
|
|
|
+ def open_file_path(self, *args, **kwargs):
|
|
|
+ try:
|
|
|
+ if self.file_path:
|
|
|
+ os.startfile(self.file_path)
|
|
|
+ except:
|
|
|
+ pass
|
|
|
+
|
|
|
+ def deal_sign_data(self, data: dict):
|
|
|
+ # 进度处理
|
|
|
+ if data["_type"] == "schedule":
|
|
|
+ processing_failed, processing_successfully = data["data"]["processing_failed"], data["data"][
|
|
|
+ "processing_successfully"]
|
|
|
+ self.pending_processing -= 1
|
|
|
+ self.processing_successfully += processing_successfully
|
|
|
+
|
|
|
+ self.processing_failed += processing_failed
|
|
|
+
|
|
|
+ # if processing_successfully > 0:
|
|
|
+ # # self.remaining_times -= 1
|
|
|
+ # # self.cumulative_frequency_times += 1
|
|
|
+ # self.label_13.setText("{}".format(self.cumulative_frequency_times))
|
|
|
+
|
|
|
+ self.send_processing()
|
|
|
+
|
|
|
+ if self.pending_processing <= 0:
|
|
|
+ t = time.time() - self.deal_data_info_1["time"]
|
|
|
+ n = self.deal_data_info_1["num"]
|
|
|
+ self.logger.info("本次图片张数:{},共计耗时:{}".format(n, t))
|
|
|
+
|
|
|
+ data = {"_type": "complete",
|
|
|
+ "data": ""
|
|
|
+ }
|
|
|
+ self.sign_self.emit(data)
|
|
|
+
|
|
|
+ if data["_type"] == "refresh_times":
|
|
|
+ self.cumulative_frequency_times += data["data"]["cumulative_frequency_times_change"]
|
|
|
+
|
|
|
+ if data["data"]["cumulative_frequency_times_change"] < 0:
|
|
|
+ self.remaining_times = self.remaining_times + 1
|
|
|
+ else:
|
|
|
+ self.remaining_times = self.remaining_times - 1
|
|
|
+
|
|
|
+ print("self.remaining_times:", self.remaining_times)
|
|
|
+ self.refresh_times(is_online=False, )
|
|
|
+
|
|
|
+ if data["_type"] == "run_cutout":
|
|
|
+ self.pushButton.setEnabled(False)
|
|
|
+ need_cutout_images = []
|
|
|
+ for image_item in self.widget_2.findChildren(MyImage):
|
|
|
+ need_cutout_images.append(image_item.image_data)
|
|
|
+
|
|
|
+ if not self.mods:
|
|
|
+ a = QMessageBox.question(self, '确认', '无抠图权限,请联系业务员'.format(),
|
|
|
+ QMessageBox.Yes)
|
|
|
+ if a == QMessageBox.Yes:
|
|
|
+ pass
|
|
|
+ self.pushButton.setEnabled(True)
|
|
|
+ return
|
|
|
+
|
|
|
+ n = len([x for x in need_cutout_images if x["need_cutout"]])
|
|
|
+ if n == 0:
|
|
|
+ a = QMessageBox.question(self, '确认', '没有需要的处理的图片'.format(),
|
|
|
+ QMessageBox.Yes)
|
|
|
+ self.pushButton.setEnabled(True)
|
|
|
+
|
|
|
+ if n > 0:
|
|
|
+ # 检查余额是否正确
|
|
|
+ if self.remaining_times < n:
|
|
|
+ a = QMessageBox.question(self, '确认', '待处理图:{}张,剩余点数:{},余额不足'.format(n, self.remaining_times),
|
|
|
+ QMessageBox.Yes)
|
|
|
+ if a == QMessageBox.Yes:
|
|
|
+ pass
|
|
|
+ self.pushButton.setEnabled(True)
|
|
|
+ return
|
|
|
+ else:
|
|
|
+ a = QMessageBox.question(self, '确认', '图片总数:{},是否进行抠图处理?'.format(n),
|
|
|
+ QMessageBox.Yes | QMessageBox.No)
|
|
|
+ if a == QMessageBox.Yes:
|
|
|
+ self.deal_data_info_1 = {"time": time.time(),
|
|
|
+ "num": n}
|
|
|
+ self.label.setText("")
|
|
|
+ self.state_change(to_state=2)
|
|
|
+ self.total_num = len([x for x in need_cutout_images if x["need_cutout"]]) # 总条数
|
|
|
+ self.pending_processing = int(self.total_num) # 待处理
|
|
|
+ self.processing_failed = 0 # 处理失败
|
|
|
+ self.processing_successfully = 0 # 处理成功
|
|
|
+ self.processing_error = 0 # 处理异常
|
|
|
+ self.deal_cutout_mode.need_cutout_images = need_cutout_images
|
|
|
+ self.deal_cutout_mode.start()
|
|
|
+
|
|
|
+ if data["_type"] == "clean_text":
|
|
|
+ print("clean_text=========================")
|
|
|
+ return
|
|
|
+
|
|
|
+ if data["_type"] == "info":
|
|
|
+ self.show_text_browser(data["data"])
|
|
|
+ return
|
|
|
+
|
|
|
+ if data["_type"] == "complete":
|
|
|
+ if self.state != 1:
|
|
|
+ self.state_change(to_state=1)
|
|
|
+ time.sleep(0.2)
|
|
|
+ self.refresh_times(is_online=True)
|
|
|
+ return
|
|
|
+
|
|
|
+ if data["_type"] == "progress_display":
|
|
|
+ self.label.setText(data["data"])
|
|
|
+ if data["show_p"]:
|
|
|
+ self.progressBar.show()
|
|
|
+ total_num = data["total_num"]
|
|
|
+ if total_num > 0:
|
|
|
+ pending_processing = data["pending_processing"]
|
|
|
+ # print("total_num:{},pending_processing:{}".format(total_num, pending_processing))
|
|
|
+ v = int((total_num - pending_processing) / total_num * 100)
|
|
|
+ # print("progressBar", v)
|
|
|
+ self.progressBar.setValue(v)
|
|
|
+ else:
|
|
|
+ self.progressBar.hide()
|
|
|
+ return
|
|
|
+
|
|
|
+ if data["_type"] == "show_text_browser":
|
|
|
+ self.show_text_browser(data["data"])
|
|
|
+ return
|
|
|
+
|
|
|
+ if data["_type"] == "show_image_item_info":
|
|
|
+ if data["data"]["file_path"] in self.all_image_item:
|
|
|
+ image_item = self.all_image_item[data["data"]["file_path"]]
|
|
|
+ image_item.set_image_text(data["data"]["text"], data["data"]["info"])
|
|
|
+ pass
|
|
|
+
|
|
|
+ def send_processing(self, show_p=True):
|
|
|
+ data = {"_type": "progress_display",
|
|
|
+ "data": "总数:{total_num} 待处理{pending_processing}条 完成{processing_successfully}条 失败{processing_failed}条 系统异常{processing_error}条".format(
|
|
|
+ total_num=self.total_num,
|
|
|
+ pending_processing=self.pending_processing,
|
|
|
+ processing_successfully=self.processing_successfully,
|
|
|
+ processing_failed=self.processing_failed,
|
|
|
+ processing_error=self.processing_error
|
|
|
+ ),
|
|
|
+ "total_num": self.total_num,
|
|
|
+ "pending_processing": self.pending_processing,
|
|
|
+ "show_p": show_p,
|
|
|
+ }
|
|
|
+ # print(data)
|
|
|
+ self.sign_self.emit(data)
|
|
|
+
|
|
|
+ def show_label_images(self,show_not_need_images=False):
|
|
|
+ # 清空元素
|
|
|
+ self.all_image_item = {}
|
|
|
+ self.widget_2.move(0, 0)
|
|
|
+ self.widget_2.width = self.scrollArea.width()
|
|
|
+ for image_item in self.widget_2.findChildren(MyImage):
|
|
|
+ image_item.deleteLater()
|
|
|
+
|
|
|
+ x, y = 20, 10
|
|
|
+ for image_data in self.need_cutout_images:
|
|
|
+ if not show_not_need_images:
|
|
|
+ if not image_data["need_cutout"]:
|
|
|
+ continue
|
|
|
+ image_item = MyImage(parent=self.widget_2, image_data=image_data, windows=self)
|
|
|
+ self.all_image_item[image_data["file_path"]] = image_item
|
|
|
+ image_item.signal_data.connect(self.deal_sign_data)
|
|
|
+ image_item.move(x, y)
|
|
|
+ image_item.show()
|
|
|
+ x = x + image_item.width + 9
|
|
|
+ if x > 300:
|
|
|
+ x = 20
|
|
|
+ y = y + 10 + image_item.height
|
|
|
+
|
|
|
+ # self.widget_2.height = y + 500
|
|
|
+ print(self.scrollArea.width(), y + 80)
|
|
|
+ self.widget_2.resize(self.scrollArea.width(), y + 80)
|
|
|
+ # 滚动条进行置顶操作
|
|
|
+ self.scrollArea.verticalScrollBar().setValue(0)
|
|
|
+ self.scrollAreaWidgetContents.setMinimumSize(0, self.widget_2.height() + 20)
|
|
|
+
|
|
|
+ def show_to_setting(self):
|
|
|
+ self.t_setting = ToSetting(windows=self)
|
|
|
+
|
|
|
+ def show_move_file_ui(self, *args, **kwargs):
|
|
|
+ MoveFiles(windows=self)
|
|
|
+ pass
|
|
|
+
|
|
|
+ def check_versions(self):
|
|
|
+ def compare_versions(version1, version2):
|
|
|
+ v1 = list(map(int, version1.split(".")))
|
|
|
+ v2 = list(map(int, version2.split(".")))
|
|
|
+ print(v1, v2)
|
|
|
+ if v1 > v2:
|
|
|
+ return 1
|
|
|
+ elif v1 < v2:
|
|
|
+ return -1
|
|
|
+ else:
|
|
|
+ return 0
|
|
|
+ # todo 版本更新确认
|
|
|
+ url = "{domain}/api/openai/client_version".format(
|
|
|
+ domain=settings.DOMAIN,
|
|
|
+ )
|
|
|
+
|
|
|
+ s = requests.get(url=url, params={"type": "client_remove_bg"})
|
|
|
+ online_version = None
|
|
|
+ try:
|
|
|
+ r_data = s.json()
|
|
|
+ print(r_data["data"])
|
|
|
+ online_version = r_data["data"]["version"]
|
|
|
+ except:
|
|
|
+ # self.label_6.setText("获取抠图软件版本信息错误")
|
|
|
+ pass
|
|
|
+ print("online_version:", online_version)
|
|
|
+ if online_version:
|
|
|
+ if compare_versions(settings.Version, online_version) == -1:
|
|
|
+ a = QMessageBox.question(self, '确认', '当前不是最新版本,请下载最新版本',
|
|
|
+ QMessageBox.Yes)
|
|
|
+ if a == QMessageBox.Yes:
|
|
|
+ print("close")
|
|
|
+ os._exit(0)
|
|
|
+ # self.close()
|
|
|
+ return
|
|
|
+
|
|
|
+ def check_login(self, *args, **kwargs):
|
|
|
+ # 验证用户身份有效性
|
|
|
+ if settings.Account and settings.Key:
|
|
|
+ self.login_complete()
|
|
|
+ else:
|
|
|
+ self.login_show(flag="hide")
|
|
|
+ self.label_3.setText("登录")
|
|
|
+ self.label_3.mousePressEvent = self.to_login
|
|
|
+
|
|
|
+ def show_text_browser(self, text):
|
|
|
+ # self.textBrowser.append(text)
|
|
|
+ pass
|
|
|
+
|
|
|
+ def unselect_file_path(self, *args):
|
|
|
+ if self.state == 1:
|
|
|
+ self.state_change(to_state=0)
|
|
|
+
|
|
|
+ def select_file_path(self, *args):
|
|
|
+
|
|
|
+ if not settings.IsLogin:
|
|
|
+ a = QMessageBox.question(self, '确认', '请先登录',
|
|
|
+ QMessageBox.Yes)
|
|
|
+ return
|
|
|
+
|
|
|
+ if not self.mods:
|
|
|
+ a = QMessageBox.question(self, '确认', '无抠图软件权限,请联系管理员',
|
|
|
+ QMessageBox.Yes)
|
|
|
+ return
|
|
|
+
|
|
|
+ messageBox = QMessageBox()
|
|
|
+ messageBox.setWindowTitle(' ')
|
|
|
+ messageBox.setText('如您选择文件夹,则软件会自动遍历您选择文件下的所有文件夹;为避免重复抠图等软件只允许扣jpg格式图片')
|
|
|
+ # style_sheet = """
|
|
|
+ # QMessageBox {
|
|
|
+ # background-color: #F5F5F5;
|
|
|
+ # font-family: Arial, sans-serif;
|
|
|
+ # font-size: 14px;
|
|
|
+ # color: #333333;
|
|
|
+ # border-radius: 10px;
|
|
|
+ # padding: 10px;
|
|
|
+ # outline: none;
|
|
|
+ # icon: none;
|
|
|
+ # }
|
|
|
+ # QMessageBox QPushButton {
|
|
|
+ # background-color: #007BFF;
|
|
|
+ # color: #FFFFFF;
|
|
|
+ # border: none;
|
|
|
+ # border-radius: 5px;
|
|
|
+ # padding: 8px 15px;
|
|
|
+ # font-size: 16px;
|
|
|
+ # font-weight: bold;
|
|
|
+ # margin: 10px;
|
|
|
+ # }
|
|
|
+ # QMessageBox QPushButton:hover {
|
|
|
+ # background-color: #0056b3;
|
|
|
+ # }
|
|
|
+ # QMessageBox QPushButton:pressed {
|
|
|
+ # background-color: #004085;
|
|
|
+ # }
|
|
|
+ # QMessageBox QLabel {
|
|
|
+ # padding: 10px;
|
|
|
+ # font-size: 16px;
|
|
|
+ # font-weight: bold;
|
|
|
+ # }
|
|
|
+ # QMessageBox QFrame {
|
|
|
+ # border: 1px solid #DADADA;
|
|
|
+ # border-radius: 10px;
|
|
|
+ # }
|
|
|
+ # """
|
|
|
+ # messageBox.setStyleSheet(style_sheet)
|
|
|
+ messageBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
|
|
|
+ # messageBox.setIcon(QMessageBox.NoIcon) # 设置无图标
|
|
|
+ buttonY = messageBox.button(QMessageBox.Yes)
|
|
|
+ buttonY.setText('选择文件夹')
|
|
|
+ buttonN = messageBox.button(QMessageBox.No)
|
|
|
+ buttonN.setText('选择图片')
|
|
|
+ messageBox.exec()
|
|
|
+
|
|
|
+ if settings.LastSelectPath:
|
|
|
+ last_select_path = settings.LastSelectPath
|
|
|
+ else:
|
|
|
+ last_select_path = "./"
|
|
|
+
|
|
|
+ if messageBox.clickedButton() == buttonY:
|
|
|
+ file_path = QFileDialog.getExistingDirectory(self, "选取文件夹", last_select_path)
|
|
|
+ # 存储last_select_path
|
|
|
+ self.file_path = file_path
|
|
|
+ self.one_image_path = ""
|
|
|
+ if not file_path:
|
|
|
+ return
|
|
|
+ # 显示文件名称
|
|
|
+ text = "已选:" + file_path
|
|
|
+ if len(text) > 28:
|
|
|
+ text = text[:15] + "..." + text[-10:]
|
|
|
+ self.label_4.setText(text)
|
|
|
+
|
|
|
+ # 检查需要处理的文件数量
|
|
|
+ self.init_images(file_path=self.file_path)
|
|
|
+ if len([x for x in self.need_cutout_images if x["need_cutout"]]) == 0:
|
|
|
+ a = QMessageBox.question(self, '确认', '您所选文件夹下没有jpg图片,或对应图片已扣图',
|
|
|
+ QMessageBox.Yes)
|
|
|
+ if a == QMessageBox.Yes:
|
|
|
+ pass
|
|
|
+
|
|
|
+ if len([x for x in self.need_cutout_images if x["need_cutout"]]) > 0:
|
|
|
+ self.state_change(to_state=1)
|
|
|
+ else:
|
|
|
+ # 选择图片
|
|
|
+ images_path_list = QFileDialog.getOpenFileNames(self, "选择图片", last_select_path,
|
|
|
+ "*.jpg;;*.jpeg;;All Files(*)")
|
|
|
+
|
|
|
+ print("已选images_path_list:", images_path_list)
|
|
|
+
|
|
|
+ self.file_path = ""
|
|
|
+
|
|
|
+ self.one_image_path = []
|
|
|
+ _Type = ['.jpg', '.JPG', '.jpeg', '.JPEG', ]
|
|
|
+ for image_path in images_path_list[0]:
|
|
|
+ _file = os.path.split(image_path)[1]
|
|
|
+ _f_e = os.path.splitext(_file)[1]
|
|
|
+ if _f_e in _Type:
|
|
|
+ self.one_image_path.append(image_path)
|
|
|
+
|
|
|
+ if not self.one_image_path:
|
|
|
+ return
|
|
|
+ file_path = os.path.split(self.one_image_path[0])[0]
|
|
|
+
|
|
|
+ # 显示文件名称
|
|
|
+ text = "已选:" + "{}个图片文件".format(len(self.one_image_path))
|
|
|
+ if len(text) > 28:
|
|
|
+ text = text[:15] + "..." + text[-10:]
|
|
|
+ self.label_4.setText(text)
|
|
|
+
|
|
|
+ # 检查需要处理的文件数量
|
|
|
+ self.init_images(image_list=self.one_image_path)
|
|
|
+ # state_change
|
|
|
+ if len(self.need_cutout_images) > 0:
|
|
|
+ self.state_change(to_state=1)
|
|
|
+
|
|
|
+ settings.LastSelectPath = file_path
|
|
|
+ self.file_path = file_path
|
|
|
+ settings.set_config(data_dict={"last_select_path": last_select_path}, section="basicSetup",
|
|
|
+ _config_name="config")
|
|
|
+
|
|
|
+ self.label_15.mousePressEvent = self.open_file_path
|
|
|
+
|
|
|
+ def init_images(self, file_path=None, image_list=None):
|
|
|
+ self.need_cutout_images = []
|
|
|
+ self.pushButton.hide()
|
|
|
+ self.pushButton.setEnabled(False)
|
|
|
+ self._n = 0
|
|
|
+ self._n_c = 0
|
|
|
+ show_not_need_images = False
|
|
|
+ if file_path:
|
|
|
+ show_not_need_images = False
|
|
|
+ self.check_need_cutout_images(root_path=file_path)
|
|
|
+
|
|
|
+ if image_list:
|
|
|
+ show_not_need_images = True
|
|
|
+ for image_path in image_list:
|
|
|
+ root_path, file = os.path.split(image_path)
|
|
|
+ file_name, file_e = os.path.splitext(file)
|
|
|
+ self.need_cutout_images.append({"file_name": file_name,
|
|
|
+ "file_e": file_e,
|
|
|
+ "file_path": image_path,
|
|
|
+ "file": file,
|
|
|
+ "root_path": root_path,
|
|
|
+ "need_cutout": True,
|
|
|
+ })
|
|
|
+
|
|
|
+ for index,image_data in enumerate(self.need_cutout_images):
|
|
|
+ root_path = image_data["root_path"]
|
|
|
+ file_name = image_data["file_name"]
|
|
|
+ _path_1 = "{}/{}.png".format(root_path,file_name)
|
|
|
+ _path_2 = "{}/已扣图/{}.png".format(root_path,file_name)
|
|
|
+ if os.path.exists(_path_1):
|
|
|
+ self.need_cutout_images[index]["need_cutout"] = False
|
|
|
+ continue
|
|
|
+ if os.path.exists(_path_2):
|
|
|
+ self.need_cutout_images[index]["need_cutout"] = False
|
|
|
+ continue
|
|
|
+
|
|
|
+ # print("self.need_cutout_images",self.need_cutout_images)
|
|
|
+ # if file_path:
|
|
|
+ # if len([x for x in self.need_cutout_images if x["need_cutout"]]) > 0:
|
|
|
+ # self.sign_self.emit({"_type": "clean_text"})
|
|
|
+ # self.pushButton.show()
|
|
|
+ # self.pushButton.setEnabled(True)
|
|
|
+ # else:
|
|
|
+ # if len(self.need_cutout_images) > 0:
|
|
|
+ # self.sign_self.emit({"_type": "clean_text"})
|
|
|
+ # self.pushButton.show()
|
|
|
+ # self.pushButton.setEnabled(True)
|
|
|
+ self.show_label_images(show_not_need_images)
|
|
|
+
|
|
|
+ def check_need_cutout_images(self, root_path):
|
|
|
+ _Type = ['.jpg', '.JPG', '.jpeg', '.JPEG', ]
|
|
|
+ _is_cutout = []
|
|
|
+ for file in os.listdir(root_path):
|
|
|
+ self._n_c += 1
|
|
|
+ if self._n_c > 500:
|
|
|
+ self.need_cutout_images = []
|
|
|
+ data = {"_type": "show_text_browser",
|
|
|
+ "data": "目录下文件过多,请检查目录是否正确"
|
|
|
+ }
|
|
|
+ self.sign_self.emit(data)
|
|
|
+ return
|
|
|
+ file_path = "{}/{}".format(root_path, file)
|
|
|
+ if os.path.isdir(file_path):
|
|
|
+ print(file_path)
|
|
|
+ if file == "已扣图":
|
|
|
+ # 哪些图片已经有抠图
|
|
|
+ for x_file in os.listdir(file_path):
|
|
|
+ x_file_name, x_file_e = os.path.splitext(x_file)
|
|
|
+ if x_file_e == ".png":
|
|
|
+ _is_cutout.append(x_file_name)
|
|
|
+
|
|
|
+ # ===============================================================
|
|
|
+ for file in os.listdir(root_path):
|
|
|
+ file_path = "{}/{}".format(root_path, file)
|
|
|
+ if os.path.isdir(file_path):
|
|
|
+ print(file_path)
|
|
|
+ # 不是已扣图文件夹,则进行遍历
|
|
|
+ f = True
|
|
|
+ for i in settings.is_fall_dir:
|
|
|
+ if i in file:
|
|
|
+ f = False
|
|
|
+ break
|
|
|
+ if f:
|
|
|
+ self.check_need_cutout_images(file_path)
|
|
|
+
|
|
|
+ file_name, file_e = os.path.splitext(file)
|
|
|
+ if file_e not in _Type:
|
|
|
+ continue
|
|
|
+
|
|
|
+ # 检查文件是否在禁止抠图里
|
|
|
+ f = True
|
|
|
+ for i in settings.is_fall_file:
|
|
|
+ if i in file:
|
|
|
+ f = False
|
|
|
+ break
|
|
|
+ if not f:
|
|
|
+ continue
|
|
|
+
|
|
|
+ need_cutout = False if file_name in _is_cutout else True
|
|
|
+ if os.path.exists("{}/{}.png".format(root_path, file_name)):
|
|
|
+ need_cutout = False
|
|
|
+
|
|
|
+ # 图片进行处理
|
|
|
+ self.need_cutout_images.append({"file_name": file_name,
|
|
|
+ "file_e": file_e,
|
|
|
+ "file_path": file_path,
|
|
|
+ "file": file,
|
|
|
+ "root_path": root_path,
|
|
|
+ "need_cutout": need_cutout,
|
|
|
+ })
|
|
|
+
|
|
|
+ def to_login(self, *args, **kwargs):
|
|
|
+ self.login = LoginWindow(windows=self, call_back=self.login_complete)
|
|
|
+
|
|
|
+ def login_complete(self, *args, **kwargs):
|
|
|
+ # settings.get_authorization()
|
|
|
+ print("登录验证~")
|
|
|
+ url = "{domain}/api/auth/user".format(
|
|
|
+ domain=settings.DOMAIN
|
|
|
+ )
|
|
|
+ s = requests.session()
|
|
|
+ _s = s.get(url=url, headers=settings.Headers)
|
|
|
+ # print(_s)
|
|
|
+ response_data = _s.json()
|
|
|
+ code = response_data["code"]
|
|
|
+ # print(response_data)
|
|
|
+ if code == 0:
|
|
|
+ settings.Headers = {
|
|
|
+ "Authorization": settings.Authorization,
|
|
|
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
|
|
|
+ "Origin": settings.Origin,
|
|
|
+ "Host": settings.Host,
|
|
|
+ "Content-Type": "application/json;charset=UTF-8"
|
|
|
+ }
|
|
|
+ # print(settings.Headers)
|
|
|
+ self.login_show(flag="show")
|
|
|
+ self.label_2.setText(response_data["data"]["real_name"] + "\n" + response_data["data"]["phone"])
|
|
|
+ self.label_7.setText(response_data["data"]["brand_company_name"])
|
|
|
+ self.label_3.setText("退出")
|
|
|
+ self.label_3.mousePressEvent = self.to_logout
|
|
|
+ settings.IsLogin = True
|
|
|
+ menu_dict = GetOnlineData().get_current_menu()
|
|
|
+ # todo 处理操作权限等
|
|
|
+ self.mods_list = []
|
|
|
+ # menu_dict = {"HctGood":"111111"}
|
|
|
+ self.mods = False
|
|
|
+ if 'DataDashboard' in menu_dict:
|
|
|
+ if "批量抠图" in menu_dict["DataDashboard"]:
|
|
|
+ self.mods = True
|
|
|
+
|
|
|
+ self.mods_list = menu_dict["DataDashboard"]
|
|
|
+ print("mods_list:", self.mods_list)
|
|
|
+ # if "add" in menu_dict["HctGood"]:
|
|
|
+ self.get_online_data.refresh_headers()
|
|
|
+ self.refresh_times()
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ # self.pushButton_5.setText("无抠图权限")
|
|
|
+ # self.pushButton_5.setEnabled(False)
|
|
|
+ # self.pushButton_7.hide()
|
|
|
+ self.mods = False
|
|
|
+
|
|
|
+ self.state_change(self.state)
|
|
|
+ # 存储登录用户手机号
|
|
|
+ settings.Account = str(response_data["data"]["phone"])
|
|
|
+ settings.set_config(data_dict={"Account": settings.Account, }, _config_name="config")
|
|
|
+ return True
|
|
|
+
|
|
|
+ else:
|
|
|
+ self.label_14.hide()
|
|
|
+ self.login_show(flag="hide")
|
|
|
+ self.label_3.setText("登录")
|
|
|
+ self.label_3.mousePressEvent = self.to_login
|
|
|
+ settings.IsLogin = False
|
|
|
+ self.mods = False
|
|
|
+ return False
|
|
|
+
|
|
|
+ def to_logout(self, *args, **kwargs):
|
|
|
+ # http://pcback.cnhqt.com/api/auth/logout
|
|
|
+ url = "{domain}/api/auth/logout".format(
|
|
|
+ domain=settings.DOMAIN
|
|
|
+ )
|
|
|
+ s = requests.session()
|
|
|
+ _s = s.post(url=url, headers=settings.Headers)
|
|
|
+ # response_data = _s.json()
|
|
|
+ data_dict = {
|
|
|
+ "account": "",
|
|
|
+ }
|
|
|
+ settings.Authorization = ""
|
|
|
+ settings.set_config(data_dict)
|
|
|
+ settings.set_key("") # 清空密码
|
|
|
+
|
|
|
+ # 初始化
|
|
|
+ self.login_show(flag="hide")
|
|
|
+ self.label_3.setText("登录")
|
|
|
+ self.label_3.mousePressEvent = self.to_login
|
|
|
+ settings.IsLogin = False
|
|
|
+ self.mods = False
|
|
|
+ self.state_change(to_state=0)
|
|
|
+
|
|
|
+ def state_change(self, to_state: int):
|
|
|
+ self.state = to_state
|
|
|
+
|
|
|
+ # 初始化
|
|
|
+ if self.state == 0:
|
|
|
+ for image_item in self.widget_2.findChildren(MyImage):
|
|
|
+ image_item.deleteLater()
|
|
|
+
|
|
|
+ self.label_5.show()
|
|
|
+ self.widget_3.move(10, 10)
|
|
|
+ self.widget_3.hide()
|
|
|
+ self.widget.move(10, 10)
|
|
|
+ self.widget.hide()
|
|
|
+ self.scrollArea.resize(391, 311)
|
|
|
+ self.scrollArea.move(10, 10)
|
|
|
+ self.scrollAreaWidgetContents.setMinimumSize(0, 200)
|
|
|
+ self.progressBar.hide()
|
|
|
+ self.pushButton_6.hide()
|
|
|
+ self.file_path = ""
|
|
|
+ # self.label.setText("")
|
|
|
+ # self.label.hide()
|
|
|
+ self.excel_file_dict = {}
|
|
|
+ self.label_4.setText("")
|
|
|
+ # self.label_5.hide()
|
|
|
+ self.pushButton.hide()
|
|
|
+
|
|
|
+ # 已选择文件未开始
|
|
|
+ if self.state == 1:
|
|
|
+ self.label_5.hide()
|
|
|
+ self.label_8.show()
|
|
|
+ self.scrollArea.move(10, 60)
|
|
|
+ self.scrollArea.resize(391, 261)
|
|
|
+ self.widget_3.show()
|
|
|
+ self.widget.hide()
|
|
|
+ self.progressBar.hide()
|
|
|
+ self.label.show()
|
|
|
+ self.pushButton.setEnabled(True)
|
|
|
+ self.pushButton_6.hide()
|
|
|
+ self.pushButton.show()
|
|
|
+ self.label_14.show()
|
|
|
+
|
|
|
+ # 进行中处理
|
|
|
+ if self.state == 2:
|
|
|
+ self.label_5.hide()
|
|
|
+ self.label_8.hide()
|
|
|
+ self.pushButton.setEnabled(False)
|
|
|
+ self.scrollArea.move(10, 60)
|
|
|
+ self.scrollArea.resize(391, 261)
|
|
|
+ self.widget_3.hide()
|
|
|
+ self.widget.show()
|
|
|
+ self.progressBar.setValue(0)
|
|
|
+ self.progressBar.show()
|
|
|
+ # self.label_5.hide()
|
|
|
+ # self.label.setText("")
|
|
|
+ self.label_14.hide()
|
|
|
+ self.pushButton_6.show()
|
|
|
+ self.pushButton.hide()
|
|
|
+
|
|
|
+ # 隐藏无权限按钮
|
|
|
+ # if "add" not in self.mods_list:
|
|
|
+ # self.pushButton.hide()
|
|
|
+ # if "export" not in self.mods_list:
|
|
|
+ # self.action_6.setEnabled(False)
|
|
|
+ # else:
|
|
|
+ # self.action_6.setEnabled(True)
|
|
|
+
|
|
|
+ def stop_func(self):
|
|
|
+ a = QMessageBox.question(self, '确认', '是否终止当前正在运行?',
|
|
|
+ QMessageBox.Yes | QMessageBox.No)
|
|
|
+ if a == QMessageBox.Yes:
|
|
|
+ self.deal_cutout_mode.state = 2
|
|
|
+ self.state_change(to_state=1)
|
|
|
+
|
|
|
+class MyImage(QLabel):
|
|
|
+ signal_data = Signal(dict)
|
|
|
+
|
|
|
+ def __init__(self, parent, image_data, windows):
|
|
|
+ super().__init__(parent)
|
|
|
+ self.windows = windows
|
|
|
+ self.image_data = image_data
|
|
|
+ self.image_path = image_data["file_path"]
|
|
|
+ self.image_file = os.path.split(image_data["file_path"])[1]
|
|
|
+
|
|
|
+ self.resize(61, 81)
|
|
|
+ self.width = 61
|
|
|
+ self.height = 81
|
|
|
+ self.setStyleSheet(
|
|
|
+ "background-color: rgb(255, 255, 255);border-radius: 5px; border: 2px groove gray;border:0px;")
|
|
|
+ self.label_2 = QLabel(self)
|
|
|
+ self.label_2.move(0, 0)
|
|
|
+ self.label_2.resize(61, 61)
|
|
|
+
|
|
|
+ self.label = QLabel(self)
|
|
|
+ self.label.move(0, 61)
|
|
|
+ self.label.resize(61, 20)
|
|
|
+ self.set_label_image()
|
|
|
+ self.label.setAlignment(Qt.AlignCenter)
|
|
|
+ self.label.show()
|
|
|
+ self.label_2.show()
|
|
|
+
|
|
|
+ def crop_to_square(self,img):
|
|
|
+ # 打开图片
|
|
|
+ width, height = img.size # 获取原始图片的宽度和高度
|
|
|
+ if width == height:
|
|
|
+ return img
|
|
|
+ if width > height:
|
|
|
+ _x = int((width-height)/2)
|
|
|
+ img = img.crop((_x, 0, width-_x, height))
|
|
|
+ else:
|
|
|
+ _y = int((height-width) / 2)
|
|
|
+ img = img.crop((0, _y, width, height-_y))
|
|
|
+ return img
|
|
|
+
|
|
|
+ def set_label_image(self):
|
|
|
+ try:
|
|
|
+ bytes_io = io.BytesIO()
|
|
|
+ w, h = self.label_2.width(), self.label_2.height()
|
|
|
+
|
|
|
+ _img_raw = Image.open(self.image_path)
|
|
|
+ _img_raw.thumbnail((w*2, h*2))
|
|
|
+ _img_raw = self.get_image_orientation(_img_raw)
|
|
|
+ img_raw = self.crop_to_square(_img_raw)
|
|
|
+ img_raw = img_raw.resize(size=(w, h))
|
|
|
+ img_raw.save(bytes_io, "JPEG")
|
|
|
+ icon = QPixmap()
|
|
|
+ # icon.loadFromData(img)
|
|
|
+ icon.loadFromData(bytes_io.getvalue())
|
|
|
+ # icon = icon.scaled(self.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
|
|
+ self.label_2.setPixmap(icon)
|
|
|
+ # self.mousePressEvent = lambda x: self.show_one_data(row)
|
|
|
+
|
|
|
+ if self.image_data["need_cutout"] is False:
|
|
|
+ self.set_image_text("有抠图过")
|
|
|
+ else:
|
|
|
+ self.set_image_text("未开始")
|
|
|
+ except:
|
|
|
+ self.image_data["need_cutout"] = False
|
|
|
+ self.set_image_text("图异常", info="{} 图片异常无法进行抠图".format(self.image_file))
|
|
|
+ self.label_2.setStyleSheet("""background-color: rgb(228, 228, 255);color: rgb(0, 0, 0);""")
|
|
|
+
|
|
|
+ def get_image_orientation(self,img):
|
|
|
+ # 获取EXIF数据
|
|
|
+ exif = img._getexif()
|
|
|
+ if exif is not None:
|
|
|
+ # EXIF标签274对应的是Orientation
|
|
|
+ orientation = exif.get(0x0112)
|
|
|
+ if orientation == 2:
|
|
|
+ # 水平翻转
|
|
|
+ img = img.transpose(Image.FLIP_LEFT_RIGHT)
|
|
|
+ elif orientation == 3:
|
|
|
+ # 旋转180度
|
|
|
+ img = img.rotate(180, expand=True)
|
|
|
+ elif orientation == 4:
|
|
|
+ # 垂直翻转
|
|
|
+ img = img.transpose(Image.FLIP_TOP_BOTTOM)
|
|
|
+ elif orientation == 5:
|
|
|
+ # 水平翻转后顺时针旋转90度
|
|
|
+ img = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_270)
|
|
|
+ elif orientation == 6:
|
|
|
+ # 顺时针旋转90度
|
|
|
+ img = img.transpose(Image.ROTATE_270)
|
|
|
+ elif orientation == 7:
|
|
|
+ # 水平翻转后逆时针旋转90度
|
|
|
+ img = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_90)
|
|
|
+ elif orientation == 8:
|
|
|
+ # 逆时针旋转90度
|
|
|
+ img = img.transpose(Image.ROTATE_90)
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+
|
|
|
+ return img
|
|
|
+
|
|
|
+ def set_image_text(self, text, info=""):
|
|
|
+ s = {
|
|
|
+ "未开始": """background-color: rgb(255, 255, 255);color: rgb(0, 0, 0);""",
|
|
|
+ "进行中": """background-color: rgb(255, 255, 255);color: rgb(255, 220, 91);""",
|
|
|
+ "已完成": """background-color: rgb(255, 255, 255);color: rgb(89, 168, 105);""",
|
|
|
+ "出错/超时": """background-color: rgb(255, 255, 255);color: rgb(219, 88, 96);""",
|
|
|
+ "已取消": """background-color: rgb(255, 255, 255);color: rgb(219, 88, 96);""",
|
|
|
+ "图异常": """background-color: rgb(255, 255, 255);color: rgb(219, 88, 96);""",
|
|
|
+ "有抠图过": """background-color: rgb(255, 255, 255);color: rgb(53, 36, 137);""",
|
|
|
+ }
|
|
|
+ if text in ["已完成", "图异常"]:
|
|
|
+ self.image_data["need_cutout"] = False
|
|
|
+
|
|
|
+ if text in s:
|
|
|
+ self.label.setStyleSheet(s[text])
|
|
|
+
|
|
|
+ self.label.setText(text)
|
|
|
+ if info:
|
|
|
+ self.label.setToolTip(info)
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == '__main__':
|
|
|
+ QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
|
|
|
+ app = QApplication(sys.argv)
|
|
|
+ print(list_themes())
|
|
|
+
|
|
|
+ apply_stylesheet(app, theme='light_blue.xml',invert_secondary=True)
|
|
|
+ main_window = MainWindow()
|
|
|
+ main_window.show()
|
|
|
+ sys.exit(app.exec())
|