main.py 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996
  1. # -*- coding: utf-8 -*-
  2. # import time
  3. # import module.log as log
  4. import sys
  5. import os
  6. import time
  7. from module.other.log import MyLogger
  8. from UI.main_ui import Ui_MainWindow
  9. from PySide6.QtWidgets import *
  10. from PySide6.QtCore import *
  11. from PySide6.QtGui import *
  12. import settings
  13. from module.module_resize_pic import ResizePic
  14. from module.other.module_setting import ToSetting
  15. from module.other.module_online_data import GetOnlineData
  16. from module.module_login import LoginWindow
  17. from module.remove_bg_pixian import RemoveBgPiXian
  18. from module.deal_cutout import DealCutout
  19. from module.MineMainWindow import MineMainWindow
  20. import requests
  21. from module.module_move_files import MoveFiles
  22. import webbrowser
  23. import io
  24. from PIL import Image
  25. from qt_material import apply_stylesheet,list_themes
  26. """
  27. 抠图软件,使用pixian抠图
  28. """
  29. class MainWindow(MineMainWindow, Ui_MainWindow):
  30. sign_self = Signal(dict)
  31. def __init__(self):
  32. super().__init__()
  33. self.deal_data_info_1 = {"time": time.time(),
  34. "num": 1}
  35. self.to_end = False
  36. self.setupUi(self)
  37. self.login_show(flag="hide")
  38. self.logger = MyLogger().logger
  39. self.setWindowIcon(QIcon("resource\images\icon.png"))
  40. self.setWindowTitle("惠利玛图片抠图工具V{}-{}".format(settings.Version, settings.env))
  41. self.setFixedSize(self.width(), self.height())
  42. # ------------------
  43. self.file_path = ""
  44. self.one_image_path = ""
  45. # ------------------
  46. self.mods_list = []
  47. self.state = 0
  48. self.remaining_times = 0 # 剩余总次数
  49. # ---------------
  50. self.total_num = 0 # 总条数
  51. self.pending_processing = 0 # 待处理
  52. self.processing_failed = 0 # 处理失败
  53. self.processing_successfully = 0 # 处理成功
  54. self.processing_error = 0 # 处理异常
  55. # -------------------
  56. self.state_change(self.state)
  57. self.need_cutout_images = []
  58. self.mods = False
  59. self.r_pixian = RemoveBgPiXian()
  60. self._app = None
  61. self.get_online_data = GetOnlineData()
  62. self.cumulative_frequency_times = 0 # 本次抠图次数
  63. self.qss_style()
  64. self.init()
  65. self.state_change(to_state=0)
  66. QTimer.singleShot(500, self.check_versions) # 检查版本
  67. QTimer.singleShot(1000, self.check_login)
  68. def qss_style(self):
  69. style_sheet = """
  70. /* 滚动条的整体样式 */
  71. QScrollBar {
  72. background-color: #F0F0F0;
  73. width: 5px;
  74. height: 15px;
  75. border: 1px;
  76. margin: 15px 0px 15px 0px;
  77. }
  78. /* 滚动条的滑块 */
  79. QScrollBar::handle {
  80. background-color: #e3e3e3;
  81. min-height: 20px;
  82. border-radius: 15px;
  83. }
  84. /* 滚动条滑块悬停时的样式 */
  85. QScrollBar::handle:hover {
  86. background-color: #555555;
  87. }
  88. /* 滚动条滑块按下时的样式 */
  89. QScrollBar::handle:pressed {
  90. background-color: #444444;
  91. }
  92. /* 滚动条的上下按钮 */
  93. QScrollBar::add-line, QScrollBar::sub-line {
  94. border: none;
  95. background-color: #F0F0F0;
  96. height: 0px;
  97. width: 0px;
  98. subcontrol-position: both-ends;
  99. subcontrol-origin: margin;
  100. }
  101. /* 滚动条的上下按钮不可见 */
  102. QScrollBar::add-page, QScrollBar::sub-page {
  103. background: none;
  104. }
  105. /* 滚动条的滑块到达顶部/底部时的样式 */
  106. QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
  107. height: 0px;
  108. }
  109. /* 滚动条的滑块到达顶部/底部时的样式 */
  110. QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
  111. background: none;
  112. }
  113. """
  114. # 使用QSS设置圆角
  115. self.setStyleSheet(style_sheet)
  116. def login_info_is_false(self):
  117. self.WaringMessage("登录信息已失效")
  118. QTimer.singleShot(500, self.to_logout)
  119. def refresh_times(self, is_online=True, remaining_times=None):
  120. # 刷新剩余次数
  121. if remaining_times is not None:
  122. self.remaining_times = remaining_times
  123. if is_online:
  124. _ = self.get_online_data.get_cutout_image_times()
  125. if _ is False:
  126. self.remaining_times = 0
  127. self.login_info_is_false()
  128. else:
  129. if "balance" in _:
  130. self.remaining_times = _["balance"]
  131. self.label_11.setText("{}".format(self.remaining_times))
  132. self.label_13.setText("{}".format(self.cumulative_frequency_times))
  133. self.label_10.show()
  134. if self.remaining_times <= 0:
  135. return False
  136. return True
  137. def check_path(self, _path):
  138. if not os.path.exists(_path):
  139. os.mkdir(_path)
  140. return True
  141. def show_resize_pic_ui(self, *args):
  142. self.show_resize_pic = ResizePic()
  143. def closeEvent(self, event):
  144. print("to close")
  145. reply = self.comfirmMessage("确定要关闭窗口吗?")
  146. if reply == QMessageBox.Yes:
  147. # 如果用户点击了"是"按钮,则正常关闭窗口
  148. super().closeEvent(event)
  149. os._exit(0)
  150. else:
  151. # 否则取消关闭操作
  152. event.ignore()
  153. def login_show(self, flag="show"):
  154. if flag == "show":
  155. self.label_2.show()
  156. self.label_7.show()
  157. self.label_10.show()
  158. self.label_9.show()
  159. self.label_11.show()
  160. self.label_12.show()
  161. self.label_13.show()
  162. self.label_2.setText("--")
  163. self.label_7.setText("--")
  164. self.label_14.show()
  165. self.label_11.setText("--")
  166. self.label_13.setText("--")
  167. else:
  168. self.label_14.hide()
  169. self.label_2.hide()
  170. self.label_7.hide()
  171. self.label_10.hide()
  172. self.label_9.hide()
  173. self.label_11.hide()
  174. self.label_12.hide()
  175. self.label_13.hide()
  176. def label_refresh_times(self, *args):
  177. self.label_11.setText("--")
  178. self.label_11.show()
  179. time.sleep(0.1)
  180. self.refresh_times()
  181. pass
  182. def init(self):
  183. self.label.setText("未避免重复抠图等软件只允许扣jpg格式图片")
  184. self.label.show()
  185. self.label_5.show()
  186. self.label_5.move(40, 40)
  187. self.label_14.hide()
  188. self.label_14.mousePressEvent = self.label_refresh_times
  189. self.deal_cutout_mode = DealCutout(windows=self)
  190. self.deal_cutout_mode.signal_data.connect(self.deal_sign_data)
  191. self.label_5.mousePressEvent = self.select_file_path
  192. self.label_8.mousePressEvent = self.select_file_path
  193. self.pushButton_6.clicked.connect(self.stop_func) # 停止按钮
  194. self.sign_self.connect(self.deal_sign_data)
  195. self.pushButton.clicked.connect(lambda: self.deal_sign_data({"_type": "run_cutout"}))
  196. self.pushButton_6.hide()
  197. # 菜单
  198. self.action_2.triggered.connect(self.show_resize_pic_ui)
  199. self.action_5.triggered.connect(self.show_move_file_ui)
  200. self.action_10.triggered.connect(self.show_to_setting)
  201. self.action_11.triggered.connect(self.contact_us)
  202. def contact_us(self, *args):
  203. url = 'https://www.valimart.net/'
  204. webbrowser.open(url)
  205. def open_file_path(self, *args, **kwargs):
  206. try:
  207. if self.file_path:
  208. os.startfile(self.file_path)
  209. except:
  210. pass
  211. def deal_sign_data(self, data: dict):
  212. # 进度处理
  213. if data["_type"] == "schedule":
  214. processing_failed, processing_successfully = data["data"]["processing_failed"], data["data"][
  215. "processing_successfully"]
  216. self.pending_processing -= 1
  217. self.processing_successfully += processing_successfully
  218. self.processing_failed += processing_failed
  219. # if processing_successfully > 0:
  220. # # self.remaining_times -= 1
  221. # # self.cumulative_frequency_times += 1
  222. # self.label_13.setText("{}".format(self.cumulative_frequency_times))
  223. self.send_processing()
  224. if self.pending_processing <= 0:
  225. t = time.time() - self.deal_data_info_1["time"]
  226. n = self.deal_data_info_1["num"]
  227. self.logger.info("本次图片张数:{},共计耗时:{}".format(n, t))
  228. data = {"_type": "complete",
  229. "data": ""
  230. }
  231. self.sign_self.emit(data)
  232. if data["_type"] == "refresh_times":
  233. self.cumulative_frequency_times += data["data"]["cumulative_frequency_times_change"]
  234. if data["data"]["cumulative_frequency_times_change"] < 0:
  235. self.remaining_times = self.remaining_times + 1
  236. else:
  237. self.remaining_times = self.remaining_times - 1
  238. print("self.remaining_times:", self.remaining_times)
  239. self.refresh_times(is_online=False, )
  240. if data["_type"] == "run_cutout":
  241. self.pushButton.setEnabled(False)
  242. need_cutout_images = []
  243. for image_item in self.widget_2.findChildren(MyImage):
  244. need_cutout_images.append(image_item.image_data)
  245. if not self.mods:
  246. # self.
  247. a = self.comfirmMessage("无抠图权限,请联系业务员")
  248. if a == QMessageBox.Yes:
  249. pass
  250. self.pushButton.setEnabled(True)
  251. return
  252. n = len([x for x in need_cutout_images if x["need_cutout"]])
  253. if n == 0:
  254. self.WaringMessage("没有需要的处理的图片")
  255. self.pushButton.setEnabled(True)
  256. if n > 0:
  257. # 检查余额是否正确
  258. if self.remaining_times < n:
  259. a = self.comfirmMessage(
  260. "待处理图:{}张,剩余点数:{},余额不足".format(
  261. n, self.remaining_times
  262. )
  263. )
  264. if a == QMessageBox.Yes:
  265. pass
  266. self.pushButton.setEnabled(True)
  267. return
  268. else:
  269. a = self.comfirmMessage("图片总数:{},是否进行抠图处理?".format(n))
  270. if a == QMessageBox.Yes:
  271. self.deal_data_info_1 = {"time": time.time(),
  272. "num": n}
  273. self.label.setText("")
  274. self.state_change(to_state=2)
  275. self.total_num = len([x for x in need_cutout_images if x["need_cutout"]]) # 总条数
  276. self.pending_processing = int(self.total_num) # 待处理
  277. self.processing_failed = 0 # 处理失败
  278. self.processing_successfully = 0 # 处理成功
  279. self.processing_error = 0 # 处理异常
  280. self.deal_cutout_mode.need_cutout_images = need_cutout_images
  281. self.deal_cutout_mode.start()
  282. if data["_type"] == "clean_text":
  283. print("clean_text=========================")
  284. return
  285. if data["_type"] == "info":
  286. self.show_text_browser(data["data"])
  287. return
  288. if data["_type"] == "complete":
  289. if self.state != 1:
  290. self.state_change(to_state=1)
  291. time.sleep(0.2)
  292. self.refresh_times(is_online=True)
  293. return
  294. if data["_type"] == "progress_display":
  295. self.label.setText(data["data"])
  296. if data["show_p"]:
  297. self.progressBar.show()
  298. total_num = data["total_num"]
  299. if total_num > 0:
  300. pending_processing = data["pending_processing"]
  301. # print("total_num:{},pending_processing:{}".format(total_num, pending_processing))
  302. v = int((total_num - pending_processing) / total_num * 100)
  303. # print("progressBar", v)
  304. self.progressBar.setValue(v)
  305. else:
  306. self.progressBar.hide()
  307. return
  308. if data["_type"] == "show_text_browser":
  309. self.show_text_browser(data["data"])
  310. return
  311. if data["_type"] == "show_image_item_info":
  312. if data["data"]["file_path"] in self.all_image_item:
  313. image_item = self.all_image_item[data["data"]["file_path"]]
  314. image_item.set_image_text(data["data"]["text"], data["data"]["info"])
  315. pass
  316. def send_processing(self, show_p=True):
  317. data = {"_type": "progress_display",
  318. "data": "总数:{total_num} 待处理{pending_processing}条 完成{processing_successfully}条 失败{processing_failed}条 系统异常{processing_error}条".format(
  319. total_num=self.total_num,
  320. pending_processing=self.pending_processing,
  321. processing_successfully=self.processing_successfully,
  322. processing_failed=self.processing_failed,
  323. processing_error=self.processing_error
  324. ),
  325. "total_num": self.total_num,
  326. "pending_processing": self.pending_processing,
  327. "show_p": show_p,
  328. }
  329. # print(data)
  330. self.sign_self.emit(data)
  331. def show_label_images(self,show_not_need_images=False):
  332. # 清空元素
  333. self.all_image_item = {}
  334. self.widget_2.move(0, 0)
  335. self.widget_2.width = self.scrollArea.width()
  336. for image_item in self.widget_2.findChildren(MyImage):
  337. image_item.deleteLater()
  338. x, y = 20, 10
  339. for image_data in self.need_cutout_images:
  340. if not show_not_need_images:
  341. if not image_data["need_cutout"]:
  342. continue
  343. image_item = MyImage(parent=self.widget_2, image_data=image_data, windows=self)
  344. self.all_image_item[image_data["file_path"]] = image_item
  345. image_item.signal_data.connect(self.deal_sign_data)
  346. image_item.move(x, y)
  347. image_item.show()
  348. x = x + image_item.width + 9
  349. if x > 300:
  350. x = 20
  351. y = y + 10 + image_item.height
  352. # self.widget_2.height = y + 500
  353. print(self.scrollArea.width(), y + 80)
  354. self.widget_2.resize(self.scrollArea.width(), y + 80)
  355. # 滚动条进行置顶操作
  356. self.scrollArea.verticalScrollBar().setValue(0)
  357. self.scrollAreaWidgetContents.setMinimumSize(0, self.widget_2.height() + 20)
  358. def show_to_setting(self):
  359. self.t_setting = ToSetting(windows=self)
  360. def show_move_file_ui(self, *args, **kwargs):
  361. MoveFiles(windows=self)
  362. pass
  363. def check_versions(self):
  364. def compare_versions(version1, version2):
  365. v1 = list(map(int, version1.split(".")))
  366. v2 = list(map(int, version2.split(".")))
  367. print(v1, v2)
  368. if v1 > v2:
  369. return 1
  370. elif v1 < v2:
  371. return -1
  372. else:
  373. return 0
  374. # todo 版本更新确认
  375. url = "{domain}/api/openai/client_version".format(
  376. domain=settings.DOMAIN,
  377. )
  378. s = requests.get(url=url, params={"type": "client_remove_bg"})
  379. online_version = None
  380. try:
  381. r_data = s.json()
  382. print(r_data["data"])
  383. online_version = r_data["data"]["version"]
  384. except:
  385. # self.label_6.setText("获取抠图软件版本信息错误")
  386. pass
  387. print("online_version:", online_version)
  388. if online_version:
  389. if compare_versions(settings.Version, online_version) == -1:
  390. a = self.comfirmMessage("当前不是最新版本,请下载最新版本")
  391. if a == QMessageBox.Yes:
  392. print("close")
  393. os._exit(0)
  394. # self.close()
  395. return
  396. def check_login(self, *args, **kwargs):
  397. # 验证用户身份有效性
  398. if settings.Account and settings.Key:
  399. self.login_complete()
  400. else:
  401. self.login_show(flag="hide")
  402. self.label_3.setText("登录")
  403. self.label_3.mousePressEvent = self.to_login
  404. def show_text_browser(self, text):
  405. # self.textBrowser.append(text)
  406. pass
  407. def unselect_file_path(self, *args):
  408. if self.state == 1:
  409. self.state_change(to_state=0)
  410. def select_file_path(self, *args):
  411. if not self.checkLogin():
  412. return
  413. if not self.checkMods(self.mods):
  414. return
  415. messageBox = QMessageBox()
  416. messageBox.setWindowTitle(' ')
  417. messageBox.setText('如您选择文件夹,则软件会自动遍历您选择文件下的所有文件夹;为避免重复抠图等软件只允许扣jpg格式图片')
  418. # style_sheet = """
  419. # QMessageBox {
  420. # background-color: #F5F5F5;
  421. # font-family: Arial, sans-serif;
  422. # font-size: 14px;
  423. # color: #333333;
  424. # border-radius: 10px;
  425. # padding: 10px;
  426. # outline: none;
  427. # icon: none;
  428. # }
  429. # QMessageBox QPushButton {
  430. # background-color: #007BFF;
  431. # color: #FFFFFF;
  432. # border: none;
  433. # border-radius: 5px;
  434. # padding: 8px 15px;
  435. # font-size: 16px;
  436. # font-weight: bold;
  437. # margin: 10px;
  438. # }
  439. # QMessageBox QPushButton:hover {
  440. # background-color: #0056b3;
  441. # }
  442. # QMessageBox QPushButton:pressed {
  443. # background-color: #004085;
  444. # }
  445. # QMessageBox QLabel {
  446. # padding: 10px;
  447. # font-size: 16px;
  448. # font-weight: bold;
  449. # }
  450. # QMessageBox QFrame {
  451. # border: 1px solid #DADADA;
  452. # border-radius: 10px;
  453. # }
  454. # """
  455. # messageBox.setStyleSheet(style_sheet)
  456. messageBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
  457. # messageBox.setIcon(QMessageBox.NoIcon) # 设置无图标
  458. buttonY = messageBox.button(QMessageBox.Yes)
  459. buttonY.setText('选择文件夹')
  460. buttonN = messageBox.button(QMessageBox.No)
  461. buttonN.setText('选择图片')
  462. messageBox.exec()
  463. if settings.LastSelectPath:
  464. last_select_path = settings.LastSelectPath
  465. else:
  466. last_select_path = "./"
  467. if messageBox.clickedButton() == buttonY:
  468. file_path = QFileDialog.getExistingDirectory(self, "选取文件夹", last_select_path)
  469. # 存储last_select_path
  470. self.file_path = file_path
  471. self.one_image_path = ""
  472. if not file_path:
  473. return
  474. # 显示文件名称
  475. text = "已选:" + file_path
  476. if len(text) > 28:
  477. text = text[:15] + "..." + text[-10:]
  478. self.label_4.setText(text)
  479. # 检查需要处理的文件数量
  480. self.init_images(file_path=self.file_path)
  481. if len([x for x in self.need_cutout_images if x["need_cutout"]]) == 0:
  482. a = self.comfirmMessage("您所选文件夹下没有jpg图片,或对应图片已扣图")
  483. if a == QMessageBox.Yes:
  484. pass
  485. if len([x for x in self.need_cutout_images if x["need_cutout"]]) > 0:
  486. self.state_change(to_state=1)
  487. else:
  488. # 选择图片
  489. images_path_list = QFileDialog.getOpenFileNames(self, "选择图片", last_select_path,
  490. "*.jpg;;*.jpeg;;All Files(*)")
  491. print("已选images_path_list:", images_path_list)
  492. self.file_path = ""
  493. self.one_image_path = []
  494. _Type = ['.jpg', '.JPG', '.jpeg', '.JPEG', ]
  495. for image_path in images_path_list[0]:
  496. _file = os.path.split(image_path)[1]
  497. _f_e = os.path.splitext(_file)[1]
  498. if _f_e in _Type:
  499. self.one_image_path.append(image_path)
  500. if not self.one_image_path:
  501. return
  502. file_path = os.path.split(self.one_image_path[0])[0]
  503. # 显示文件名称
  504. text = "已选:" + "{}个图片文件".format(len(self.one_image_path))
  505. if len(text) > 28:
  506. text = text[:15] + "..." + text[-10:]
  507. self.label_4.setText(text)
  508. # 检查需要处理的文件数量
  509. self.init_images(image_list=self.one_image_path)
  510. # state_change
  511. if len(self.need_cutout_images) > 0:
  512. self.state_change(to_state=1)
  513. settings.LastSelectPath = file_path
  514. self.file_path = file_path
  515. settings.set_config(data_dict={"last_select_path": last_select_path}, section="basicSetup",
  516. _config_name="config")
  517. self.label_15.mousePressEvent = self.open_file_path
  518. def init_images(self, file_path=None, image_list=None):
  519. self.need_cutout_images = []
  520. self.pushButton.hide()
  521. self.pushButton.setEnabled(False)
  522. self._n = 0
  523. self._n_c = 0
  524. show_not_need_images = False
  525. if file_path:
  526. show_not_need_images = False
  527. self.check_need_cutout_images(root_path=file_path)
  528. if image_list:
  529. show_not_need_images = True
  530. for image_path in image_list:
  531. root_path, file = os.path.split(image_path)
  532. file_name, file_e = os.path.splitext(file)
  533. self.need_cutout_images.append({"file_name": file_name,
  534. "file_e": file_e,
  535. "file_path": image_path,
  536. "file": file,
  537. "root_path": root_path,
  538. "need_cutout": True,
  539. })
  540. for index,image_data in enumerate(self.need_cutout_images):
  541. root_path = image_data["root_path"]
  542. file_name = image_data["file_name"]
  543. _path_1 = "{}/{}.png".format(root_path,file_name)
  544. _path_2 = "{}/已扣图/{}.png".format(root_path,file_name)
  545. if os.path.exists(_path_1):
  546. self.need_cutout_images[index]["need_cutout"] = False
  547. continue
  548. if os.path.exists(_path_2):
  549. self.need_cutout_images[index]["need_cutout"] = False
  550. continue
  551. # print("self.need_cutout_images",self.need_cutout_images)
  552. # if file_path:
  553. # if len([x for x in self.need_cutout_images if x["need_cutout"]]) > 0:
  554. # self.sign_self.emit({"_type": "clean_text"})
  555. # self.pushButton.show()
  556. # self.pushButton.setEnabled(True)
  557. # else:
  558. # if len(self.need_cutout_images) > 0:
  559. # self.sign_self.emit({"_type": "clean_text"})
  560. # self.pushButton.show()
  561. # self.pushButton.setEnabled(True)
  562. self.show_label_images(show_not_need_images)
  563. def check_need_cutout_images(self, root_path):
  564. _Type = ['.jpg', '.JPG', '.jpeg', '.JPEG', ]
  565. _is_cutout = []
  566. for file in os.listdir(root_path):
  567. self._n_c += 1
  568. if self._n_c > 500:
  569. self.need_cutout_images = []
  570. data = {"_type": "show_text_browser",
  571. "data": "目录下文件过多,请检查目录是否正确"
  572. }
  573. self.sign_self.emit(data)
  574. return
  575. file_path = "{}/{}".format(root_path, file)
  576. if os.path.isdir(file_path):
  577. print(file_path)
  578. if file == "已扣图":
  579. # 哪些图片已经有抠图
  580. for x_file in os.listdir(file_path):
  581. x_file_name, x_file_e = os.path.splitext(x_file)
  582. if x_file_e == ".png":
  583. _is_cutout.append(x_file_name)
  584. # ===============================================================
  585. for file in os.listdir(root_path):
  586. file_path = "{}/{}".format(root_path, file)
  587. if os.path.isdir(file_path):
  588. print(file_path)
  589. # 不是已扣图文件夹,则进行遍历
  590. f = True
  591. for i in settings.is_fall_dir:
  592. if i in file:
  593. f = False
  594. break
  595. if f:
  596. self.check_need_cutout_images(file_path)
  597. file_name, file_e = os.path.splitext(file)
  598. if file_e not in _Type:
  599. continue
  600. # 检查文件是否在禁止抠图里
  601. f = True
  602. for i in settings.is_fall_file:
  603. if i in file:
  604. f = False
  605. break
  606. if not f:
  607. continue
  608. need_cutout = False if file_name in _is_cutout else True
  609. if os.path.exists("{}/{}.png".format(root_path, file_name)):
  610. need_cutout = False
  611. # 图片进行处理
  612. self.need_cutout_images.append({"file_name": file_name,
  613. "file_e": file_e,
  614. "file_path": file_path,
  615. "file": file,
  616. "root_path": root_path,
  617. "need_cutout": need_cutout,
  618. })
  619. def to_login(self, *args, **kwargs):
  620. self.login = LoginWindow(windows=self, call_back=self.login_complete)
  621. def login_complete(self, *args, **kwargs):
  622. # settings.get_authorization()
  623. print("登录验证~")
  624. url = "{domain}/api/auth/user".format(
  625. domain=settings.DOMAIN
  626. )
  627. s = requests.session()
  628. _s = s.get(url=url, headers=settings.Headers)
  629. # print(_s)
  630. response_data = _s.json()
  631. code = response_data["code"]
  632. # print(response_data)
  633. if code == 0:
  634. settings.Headers = {
  635. "Authorization": settings.Authorization,
  636. "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",
  637. "Origin": settings.Origin,
  638. "Host": settings.Host,
  639. "Content-Type": "application/json;charset=UTF-8"
  640. }
  641. # print(settings.Headers)
  642. self.login_show(flag="show")
  643. self.label_2.setText(response_data["data"]["real_name"] + "\n" + response_data["data"]["phone"])
  644. self.label_7.setText(response_data["data"]["brand_company_name"])
  645. self.label_3.setText("退出")
  646. self.label_3.mousePressEvent = self.to_logout
  647. settings.IsLogin = True
  648. menu_dict = GetOnlineData().get_current_menu()
  649. # todo 处理操作权限等
  650. self.mods_list = []
  651. # menu_dict = {"HctGood":"111111"}
  652. self.mods = False
  653. if 'DataDashboard' in menu_dict:
  654. if "批量抠图" in menu_dict["DataDashboard"]:
  655. self.mods = True
  656. self.mods_list = menu_dict["DataDashboard"]
  657. print("mods_list:", self.mods_list)
  658. # if "add" in menu_dict["HctGood"]:
  659. self.get_online_data.refresh_headers()
  660. self.refresh_times()
  661. else:
  662. pass
  663. # self.pushButton_5.setText("无抠图权限")
  664. # self.pushButton_5.setEnabled(False)
  665. # self.pushButton_7.hide()
  666. self.mods = False
  667. self.state_change(self.state)
  668. # 存储登录用户手机号
  669. settings.Account = str(response_data["data"]["phone"])
  670. settings.set_config(data_dict={"Account": settings.Account, }, _config_name="config")
  671. return True
  672. else:
  673. self.label_14.hide()
  674. self.login_show(flag="hide")
  675. self.label_3.setText("登录")
  676. self.label_3.mousePressEvent = self.to_login
  677. settings.IsLogin = False
  678. self.mods = False
  679. return False
  680. def to_logout(self, *args, **kwargs):
  681. # http://pcback.cnhqt.com/api/auth/logout
  682. url = "{domain}/api/auth/logout".format(
  683. domain=settings.DOMAIN
  684. )
  685. s = requests.session()
  686. _s = s.post(url=url, headers=settings.Headers)
  687. # response_data = _s.json()
  688. data_dict = {
  689. "account": "",
  690. }
  691. settings.Authorization = ""
  692. settings.set_config(data_dict)
  693. settings.set_key("") # 清空密码
  694. # 初始化
  695. self.login_show(flag="hide")
  696. self.label_3.setText("登录")
  697. self.label_3.mousePressEvent = self.to_login
  698. settings.IsLogin = False
  699. self.mods = False
  700. self.state_change(to_state=0)
  701. def state_change(self, to_state: int):
  702. self.state = to_state
  703. # 初始化
  704. if self.state == 0:
  705. for image_item in self.widget_2.findChildren(MyImage):
  706. image_item.deleteLater()
  707. self.label_5.show()
  708. self.widget_3.move(10, 10)
  709. self.widget_3.hide()
  710. self.widget.move(10, 10)
  711. self.widget.hide()
  712. self.scrollArea.resize(391, 311)
  713. self.scrollArea.move(10, 10)
  714. self.scrollAreaWidgetContents.setMinimumSize(0, 200)
  715. self.progressBar.hide()
  716. self.pushButton_6.hide()
  717. self.file_path = ""
  718. # self.label.setText("")
  719. # self.label.hide()
  720. self.excel_file_dict = {}
  721. self.label_4.setText("")
  722. # self.label_5.hide()
  723. self.pushButton.hide()
  724. # 已选择文件未开始
  725. if self.state == 1:
  726. self.label_5.hide()
  727. self.label_8.show()
  728. self.scrollArea.move(10, 60)
  729. self.scrollArea.resize(391, 261)
  730. self.widget_3.show()
  731. self.widget.hide()
  732. self.progressBar.hide()
  733. self.label.show()
  734. self.pushButton.setEnabled(True)
  735. self.pushButton_6.hide()
  736. self.pushButton.show()
  737. self.label_14.show()
  738. # 进行中处理
  739. if self.state == 2:
  740. self.label_5.hide()
  741. self.label_8.hide()
  742. self.pushButton.setEnabled(False)
  743. self.scrollArea.move(10, 60)
  744. self.scrollArea.resize(391, 261)
  745. self.widget_3.hide()
  746. self.widget.show()
  747. self.progressBar.setValue(0)
  748. self.progressBar.show()
  749. # self.label_5.hide()
  750. # self.label.setText("")
  751. self.label_14.hide()
  752. self.pushButton_6.show()
  753. self.pushButton.hide()
  754. # 隐藏无权限按钮
  755. # if "add" not in self.mods_list:
  756. # self.pushButton.hide()
  757. # if "export" not in self.mods_list:
  758. # self.action_6.setEnabled(False)
  759. # else:
  760. # self.action_6.setEnabled(True)
  761. def stop_func(self):
  762. a = self.comfirmMessage("是否终止当前正在运行?")
  763. if a == QMessageBox.Yes:
  764. self.deal_cutout_mode.state = 2
  765. self.state_change(to_state=1)
  766. class MyImage(QLabel):
  767. signal_data = Signal(dict)
  768. def __init__(self, parent, image_data, windows):
  769. super().__init__(parent)
  770. self.windows = windows
  771. self.image_data = image_data
  772. self.image_path = image_data["file_path"]
  773. self.image_file = os.path.split(image_data["file_path"])[1]
  774. self.resize(61, 81)
  775. self.width = 61
  776. self.height = 81
  777. self.setStyleSheet(
  778. "background-color: rgb(255, 255, 255);border-radius: 5px; border: 2px groove gray;border:0px;")
  779. self.label_2 = QLabel(self)
  780. self.label_2.move(0, 0)
  781. self.label_2.resize(61, 61)
  782. self.label = QLabel(self)
  783. self.label.move(0, 61)
  784. self.label.resize(61, 20)
  785. self.set_label_image()
  786. self.label.setAlignment(Qt.AlignCenter)
  787. self.label.show()
  788. self.label_2.show()
  789. def crop_to_square(self,img):
  790. # 打开图片
  791. width, height = img.size # 获取原始图片的宽度和高度
  792. if width == height:
  793. return img
  794. if width > height:
  795. _x = int((width-height)/2)
  796. img = img.crop((_x, 0, width-_x, height))
  797. else:
  798. _y = int((height-width) / 2)
  799. img = img.crop((0, _y, width, height-_y))
  800. return img
  801. def set_label_image(self):
  802. try:
  803. bytes_io = io.BytesIO()
  804. w, h = self.label_2.width(), self.label_2.height()
  805. _img_raw = Image.open(self.image_path)
  806. _img_raw.thumbnail((w*2, h*2))
  807. _img_raw = self.get_image_orientation(_img_raw)
  808. img_raw = self.crop_to_square(_img_raw)
  809. img_raw = img_raw.resize(size=(w, h))
  810. img_raw.save(bytes_io, "JPEG")
  811. icon = QPixmap()
  812. # icon.loadFromData(img)
  813. icon.loadFromData(bytes_io.getvalue())
  814. # icon = icon.scaled(self.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
  815. self.label_2.setPixmap(icon)
  816. # self.mousePressEvent = lambda x: self.show_one_data(row)
  817. if self.image_data["need_cutout"] is False:
  818. self.set_image_text("有抠图过")
  819. else:
  820. self.set_image_text("未开始")
  821. except:
  822. self.image_data["need_cutout"] = False
  823. self.set_image_text("图异常", info="{} 图片异常无法进行抠图".format(self.image_file))
  824. self.label_2.setStyleSheet("""background-color: rgb(228, 228, 255);color: rgb(0, 0, 0);""")
  825. def get_image_orientation(self,img):
  826. # 获取EXIF数据
  827. exif = img._getexif()
  828. if exif is not None:
  829. # EXIF标签274对应的是Orientation
  830. orientation = exif.get(0x0112)
  831. if orientation == 2:
  832. # 水平翻转
  833. img = img.transpose(Image.FLIP_LEFT_RIGHT)
  834. elif orientation == 3:
  835. # 旋转180度
  836. img = img.rotate(180, expand=True)
  837. elif orientation == 4:
  838. # 垂直翻转
  839. img = img.transpose(Image.FLIP_TOP_BOTTOM)
  840. elif orientation == 5:
  841. # 水平翻转后顺时针旋转90度
  842. img = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_270)
  843. elif orientation == 6:
  844. # 顺时针旋转90度
  845. img = img.transpose(Image.ROTATE_270)
  846. elif orientation == 7:
  847. # 水平翻转后逆时针旋转90度
  848. img = img.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_90)
  849. elif orientation == 8:
  850. # 逆时针旋转90度
  851. img = img.transpose(Image.ROTATE_90)
  852. else:
  853. pass
  854. return img
  855. def set_image_text(self, text, info=""):
  856. s = {
  857. "未开始": """background-color: rgb(255, 255, 255);color: rgb(0, 0, 0);""",
  858. "进行中": """background-color: rgb(255, 255, 255);color: rgb(255, 220, 91);""",
  859. "已完成": """background-color: rgb(255, 255, 255);color: rgb(89, 168, 105);""",
  860. "出错/超时": """background-color: rgb(255, 255, 255);color: rgb(219, 88, 96);""",
  861. "已取消": """background-color: rgb(255, 255, 255);color: rgb(219, 88, 96);""",
  862. "图异常": """background-color: rgb(255, 255, 255);color: rgb(219, 88, 96);""",
  863. "有抠图过": """background-color: rgb(255, 255, 255);color: rgb(53, 36, 137);""",
  864. }
  865. if text in ["已完成", "图异常"]:
  866. self.image_data["need_cutout"] = False
  867. if text in s:
  868. self.label.setStyleSheet(s[text])
  869. self.label.setText(text)
  870. if info:
  871. self.label.setToolTip(info)
  872. if __name__ == '__main__':
  873. QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
  874. app = QApplication(sys.argv)
  875. print(list_themes())
  876. apply_stylesheet(app, theme='light_blue.xml',invert_secondary=True)
  877. main_window = MainWindow()
  878. main_window.show()
  879. sys.exit(app.exec())