add_card_window.py 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. import datetime
  2. import os
  3. import uuid
  4. from json import loads, dumps
  5. import requests
  6. from PyQt5 import uic
  7. from PyQt5.QtCore import QTimer, pyqtSignal, QThread
  8. from PyQt5.QtGui import QPixmap
  9. from PyQt5.QtWidgets import QMainWindow, QSpinBox, QDateEdit, QPushButton, QTableWidgetItem, QFileDialog, QMessageBox, \
  10. QListWidgetItem, QRadioButton
  11. from src.parse_text import parser_text
  12. from view_card_window import ViewCardWin
  13. PATH_TO_DATA_FILE = 'data.json'
  14. class AddCardWin(QMainWindow):
  15. response_received = pyqtSignal(name='response_received')
  16. def __init__(self, parent):
  17. super().__init__()
  18. uic.loadUi('ui/AddCardWin.ui', self)
  19. self.par = parent
  20. self.pushButton.clicked.connect(self.back)
  21. self.dateEdit_2.setDate(datetime.date.today())
  22. self.pushButton_2.clicked.connect(self.lets_scan)
  23. self.pushButton_3.clicked.connect(self.save_data)
  24. self.pushButton_4.clicked.connect(self.add_row)
  25. self.tableWidget.verticalHeader().setVisible(False)
  26. self.pushButton_5.clicked.connect(self.dump_data)
  27. self.pushButton_6.setVisible(False)
  28. self.widget.setVisible(False)
  29. self.widget_2.setVisible(False)
  30. self.widget_3.setVisible(False)
  31. self.parsed_texts = []
  32. self.all_words = []
  33. QTimer.singleShot(100, self.resize_table)
  34. def delete_row(self):
  35. sender = self.sender()
  36. self.tableWidget.removeRow(sender.row)
  37. for row in range(sender.row, self.tableWidget.rowCount()):
  38. self.tableWidget.cellWidget(row, 4).row -= 1
  39. def add_row(self):
  40. self.tableWidget.setRowCount(self.tableWidget.rowCount() + 1)
  41. number_spin_box = QSpinBox(self)
  42. number_spin_box.setMinimum(1)
  43. number_spin_box.setMaximum(100000)
  44. number_spin_box.setValue(self.tableWidget.rowCount())
  45. self.tableWidget.setCellWidget(self.tableWidget.rowCount() - 1, 0, number_spin_box)
  46. date_edit = QDateEdit()
  47. date_edit.setDate(datetime.date.today())
  48. date_edit.setMaximumDate(datetime.date.today())
  49. date_edit.setCalendarPopup(True)
  50. self.tableWidget.setCellWidget(self.tableWidget.rowCount() - 1, 1, date_edit)
  51. delete_button = QPushButton()
  52. delete_button.setText('Удалить')
  53. delete_button.row = self.tableWidget.rowCount() - 1
  54. delete_button.clicked.connect(self.delete_row)
  55. self.tableWidget.setCellWidget(self.tableWidget.rowCount() - 1, 4, delete_button)
  56. self.tableWidget.setItem(self.tableWidget.rowCount() - 1, 2, QTableWidgetItem(''))
  57. self.tableWidget.setItem(self.tableWidget.rowCount() - 1, 3, QTableWidgetItem(''))
  58. self.resize_table()
  59. def resize_table(self):
  60. if self.tableWidget.rowCount():
  61. row_height = min([90, max([50, self.tableWidget.height() // self.tableWidget.rowCount()])])
  62. for row in range(self.tableWidget.rowCount()):
  63. self.tableWidget.setRowHeight(row, row_height)
  64. column_width = max([100, self.tableWidget.width() // self.tableWidget.columnCount()])
  65. for column in range(self.tableWidget.columnCount()):
  66. self.tableWidget.setColumnWidth(column, column_width)
  67. def resizeEvent(self, a0, QResizeEvent=None):
  68. self.resize_table()
  69. def save_data(self):
  70. card_info = {
  71. "uuid": str(uuid.uuid4()),
  72. "title": {
  73. "serial": self.lineEdit.text(),
  74. "number": self.lineEdit_2.text(),
  75. "first_name": self.lineEdit_4.text(),
  76. "last_name": self.lineEdit_3.text(),
  77. "patronymic": self.lineEdit_5.text(),
  78. "birthday": str(self.dateEdit.date().toPyDate()),
  79. "issue_date": str(self.dateEdit_2.date().toPyDate()),
  80. "profession": self.lineEdit_6.text(),
  81. "education": self.lineEdit_7.text()
  82. },
  83. "job": [
  84. {
  85. "number": self.tableWidget.cellWidget(row, 0).value(),
  86. "date": str(self.tableWidget.cellWidget(row, 1).date().toPyDate()),
  87. "job_info": self.tableWidget.item(row, 2).text(),
  88. "basis": self.tableWidget.item(row, 3).text()
  89. }
  90. for row in range(self.tableWidget.rowCount())
  91. ]
  92. }
  93. with open(PATH_TO_DATA_FILE, 'r', encoding='utf-8') as file:
  94. data = loads(file.read())
  95. data.append(card_info)
  96. with open(PATH_TO_DATA_FILE, 'w', encoding='utf-8') as write_file:
  97. write_file.write(dumps(data))
  98. self.view_win = ViewCardWin(self.par, card_info)
  99. self.view_win.show()
  100. self.close()
  101. def dump_data(self):
  102. card_info = {
  103. "title": {
  104. "serial": self.lineEdit.text(),
  105. "number": self.lineEdit_2.text(),
  106. "first_name": self.lineEdit_4.text(),
  107. "last_name": self.lineEdit_3.text(),
  108. "patronymic": self.lineEdit_5.text(),
  109. "birthday": str(self.dateEdit.date().toPyDate()),
  110. "issue_date": str(self.dateEdit_2.date().toPyDate()),
  111. "profession": self.lineEdit_6.text(),
  112. "education": self.lineEdit_7.text()
  113. },
  114. "job": [
  115. {
  116. "number": self.tableWidget.cellWidget(row, 0).value(),
  117. "date": str(self.tableWidget.cellWidget(row, 1).date().toPyDate()),
  118. "job_info": self.tableWidget.item(row, 2).text(),
  119. "basis": self.tableWidget.item(row, 3).text()
  120. }
  121. for row in range(self.tableWidget.rowCount())
  122. ]
  123. }
  124. options = QFileDialog.Options()
  125. directory = QFileDialog.getExistingDirectory(self, "Выберите путь сохранения", options=options)
  126. if directory:
  127. file_name = os.path.join(directory,
  128. f'{card_info["title"]["last_name"]}_{card_info["title"]["first_name"]}.json')
  129. with open(file_name, 'w', encoding='utf-8') as file:
  130. file.write(dumps(card_info))
  131. QMessageBox.information(self, 'Данные выгружены', 'Данные успешно выгружены в файл')
  132. def lets_scan(self):
  133. options = QFileDialog.Options()
  134. file_name, _ = QFileDialog.getOpenFileName(self, "Select Image File", "", "Images (*.png *.jpg *.jpeg *.bmp)",
  135. options=options)
  136. if file_name:
  137. self.all_words = []
  138. self.parsed_texts = []
  139. layout = self.widget_3.children()[0]
  140. count = layout.count()
  141. for i in range(count):
  142. item = layout.itemAt(i)
  143. if item.widget():
  144. item.widget().close()
  145. self.image_path = file_name
  146. self.start_ocr_thread()
  147. pixmap = QPixmap(self.image_path)
  148. self.widget.setVisible(True)
  149. self.label_11.setPixmap(pixmap)
  150. def start_ocr_thread(self):
  151. self.ocr_thread = OCRThread(self.image_path)
  152. self.ocr_thread.ocr_completed.connect(self.on_ocr_completed)
  153. self.ocr_thread.start()
  154. def on_ocr_completed(self, result):
  155. if 'Error: ' in result[0]:
  156. QMessageBox.warning(self, 'Ошибка оцифровки', result[0])
  157. return
  158. self.widget_2.setVisible(True)
  159. self.widget_3.setVisible(True)
  160. layout = self.widget_3.children()[0]
  161. count = layout.count()
  162. for i in range(count):
  163. item = layout.itemAt(i)
  164. if item.widget():
  165. item.widget().close()
  166. for variant_index in range(len(result)):
  167. parsed_text, all_word = parser_text(result[variant_index])
  168. self.parsed_texts.append(parsed_text)
  169. self.all_words.append(all_word)
  170. radio_button = QRadioButton()
  171. radio_button.setText(f'Вариант {str(variant_index + 1)}')
  172. radio_button.toggled.connect(self.render_result)
  173. radio_button.index = variant_index
  174. self.widget_3.children()[0].addWidget(radio_button)
  175. if variant_index == 0:
  176. radio_button.setChecked(True)
  177. def render_result(self):
  178. self.listWidget.clear()
  179. sender = self.sender()
  180. parsed_text = self.parsed_texts[sender.index]
  181. all_word = self.all_words[sender.index]
  182. self.lineEdit.setText(parsed_text['title']['serial'])
  183. self.lineEdit_2.setText(parsed_text['title']['number'])
  184. self.lineEdit_3.setText(parsed_text['title']['last_name'])
  185. self.lineEdit_4.setText(parsed_text['title']['first_name'])
  186. self.lineEdit_5.setText(parsed_text['title']['patronymic'])
  187. self.lineEdit_6.setText(parsed_text['title']['profession'])
  188. self.lineEdit_7.setText(parsed_text['title']['education'])
  189. for word in all_word:
  190. list_item = QListWidgetItem()
  191. list_item.setText(word)
  192. self.listWidget.addItem(list_item)
  193. self.resize_table()
  194. def back(self):
  195. self.par.show()
  196. self.close()
  197. class OCRThread(QThread):
  198. ocr_completed = pyqtSignal(list, name='ocr_completed')
  199. def __init__(self, image_path):
  200. super().__init__()
  201. self.image_path = image_path
  202. def run(self):
  203. url = 'http://localhost:6543/recognition'
  204. files = {'image': open(self.image_path, 'rb')}
  205. try:
  206. response = requests.post(url, files=files)
  207. except Exception:
  208. text = [f"Error: Ошибка подключения к серверу"]
  209. self.ocr_completed.emit(text)
  210. return
  211. if response.status_code == 200:
  212. text = response.json()
  213. else:
  214. text = [f"Error: {response.status_code}"]
  215. self.ocr_completed.emit(text)