main.py 38 KB

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