def __init__(self): super().__init__() self.ui = MainForm() self.ui.setupUi(self) try: self.settings = settings.get_ini_settings( os.path.join(self.get_application_path(), "settings.ini")) ini_ok = True except BadIniException: ini_ok = False QtWidgets.QMessageBox.critical(self, Text.get("err"), Text.get("ini_err")) if ini_ok: self.settings.restore_qwidget_state(self) self.settings.restore_qwidget_state(self.ui.mw_splitter_1) self.settings.restore_qwidget_state(self.ui.measures_table) self.ui.download_progress_bar.setHidden(True) if ENGLISH_VERSION: self.ui.russian_language_action.setVisible(False) self.settings.language = Text.Lang.EN self.translator = QtCore.QTranslator( QtWidgets.QApplication.instance()) self.install_translator(self.settings.language) if self.settings.language == Text.Lang.EN: self.ui.english_language_action.setChecked(True) else: self.ui.russian_language_action.setChecked(True) self.set_up_logger() self.ui.measures_table.setItemDelegate( TransparentPainterForView(self.ui.measures_table, "#d4d4ff")) self.ui.download_path_edit.setText(self.settings.save_folder_path) self.ui.ip_combobox.setEditText(self.settings.ip) self.ui.download_path_edit.setText(self.settings.path) self.ui.name_template_edit.setText(self.settings.name_template) self.ui.save_folder_edit.setText(self.settings.save_folder) self.db = UpmsDatabase( os.path.join(self.get_application_path(), "database.db")) self.measures_table_model = None self.proxy = None self.update_model() self.bcast_sockets = {} self.get_broadcast_ips() self.show() self.connect_all() self.ui.get_ip_button.click() else: self.close()
class UpmsMeasure: class MeasureType(IntEnum): MECH_STOPWATCH = 1 ELEC_STOPWATCH = 2 CLOCK = 3 TYPE_TO_STR = { MeasureType.MECH_STOPWATCH: Text.get("m_stopwatch"), MeasureType.ELEC_STOPWATCH: Text.get("e_stopwatch"), MeasureType.CLOCK: Text.get("clock"), } def __init__(self, a_id: int, a_user_id: int, a_type: int, a_date: str, a_comment: str, a_interval: str, a_result: str, a_other: str): self.id = int(a_id) self.user_id = int(a_user_id) self.type = int(a_type) self.date = a_date self.comment = a_comment self.interval = a_interval self.result = a_result self.other = a_other def __eq__(self, other): if isinstance(other, UpmsMeasure): return self.id == other.id and \ self.user_id == other.user_id and \ self.type == other.type and \ self.date == other.date and \ self.comment == other.comment and \ self.interval == other.interval and \ self.result == other.result and \ self.other == other.other else: return NotImplemented def __repr__(self): return "id: {}, "\ "user_id: {}, "\ "type: {}, "\ "date: {}, "\ "comment: {}, "\ "interval: {}, "\ "result: {}, "\ "other: {}".format(self.id, self.user_id, self.type, self.date, self.comment, self.interval, self.result, self.other) def __str__(self): return "{}: {}, " \ "{}: {}, " \ "{}: {}, " \ "{}: {}, " \ "{}: {}, " \ "{}: {}, " \ "{}: {}, ".format(Text.get('id'), self.id, Text.get('uid'), self.user_id, Text.get('type'), UpmsMeasure.TYPE_TO_STR[self.type], Text.get('date'), self.date, Text.get('comment'), self.comment, Text.get('interval'), self.interval, Text.get('result'), self.result)
def get_files_list(a_ip: str) -> Optional[List[str]]: tftp_client = tftpy.TftpClient(a_ip, 69) try: tftp_client.download("ls.txt", __files_list_filename, timeout=1) except tftpy.TftpTimeout: logging.error(Text.get("get_files_list_err")) if os.path.isfile(__files_list_filename): tftp_client.context.end() os.remove(__files_list_filename) return None except Exception: if os.path.isfile(__files_list_filename): tftp_client.context.end() os.remove(__files_list_filename) raise else: with open(__files_list_filename, encoding='cp1251') as files_list_file: files_list = [] for filename in files_list_file: for word in __exclude_words: if word in filename: break else: files_list.append(filename.strip()) os.remove(__files_list_filename) return files_list
def __init__(self, a_upms_measure: UpmsMeasure, a_images_file_path: str, a_settings: QtSettings, a_parent=None): super().__init__(a_parent) self.ui = ResultInputForm() self.ui.setupUi(self) self.settings = a_settings a_image_path = a_images_file_path.rstrip(os.sep) + os.sep + "{}.jpg".format(a_upms_measure.id) if os.path.isfile(a_image_path): self.ui.photo_layout.removeItem(self.ui.photo_layout.itemAt(0)) image = QtGui.QImage(a_image_path) image_label = QtWidgets.QLabel("") image_label.setPixmap(QtGui.QPixmap.fromImage(image)) image_label.adjustSize() self.ui.photo_layout.addWidget(image_label) else: logging.warning(Text.get("photo_not_found").format(a_image_path)) self.ui.id_label.setText(str(a_upms_measure.id)) self.ui.interval_label.setText(a_upms_measure.interval) self.ui.result_edit.setText(a_upms_measure.result) self.settings.restore_qwidget_state(self) self.ui.next_button.clicked.connect(self.accept) self.ui.cancel_button.clicked.connect(self.reject)
def remove_selected_button_clicked(self, _): rows = self.ui.measures_table.selectionModel().selectedRows() if rows: res = QtWidgets.QMessageBox.question( self, Text.get("confirm"), Text.get("delete_confirm"), QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel, QtWidgets.QMessageBox.Cancel) if res == QtWidgets.QMessageBox.Ok: real_rows = [self.proxy.mapToSource(r).row() for r in rows] real_rows.sort(reverse=True) for row in real_rows: self.measures_table_model.remove_row(row) else: QtWidgets.QMessageBox.information(self, Text.get("info"), Text.get("selection_info"), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok)
def download_measures_list(self, a_download_filepath: str) -> bool: result = False ip = self.ui.ip_combobox.currentText() try: socket.inet_aton(ip) except socket.error: QtWidgets.QMessageBox.critical(self, Text.get("err"), Text.get("ip_format_err"), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) else: try: files_list = upms_tftp.get_files_list( self.ui.ip_combobox.currentText()) except ConnectionResetError: QtWidgets.QMessageBox.critical(self, Text.get("err"), Text.get("connection_err"), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) else: if files_list is not None: if self.measures_filename in files_list: try: upms_tftp.download_file_by_tftp( ip, self.measures_filename, a_download_filepath) result = True except FileNotFoundError: QtWidgets.QMessageBox.critical( self, Text.get("err"), Text.get("path_err"), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) else: QtWidgets.QMessageBox.critical( self, Text.get("err"), Text.get("main_table_not_found_err").format( self.measures_filename), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) else: QtWidgets.QMessageBox.critical(self, Text.get("err"), Text.get("download_err"), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) return result
def data(self, index, role=Qt.DisplayRole): if not index.isValid() or (self.rowCount() < index.row()) or \ (role != Qt.DisplayRole and role != Qt.EditRole and role != Qt.BackgroundRole): return QVariant() if role == Qt.BackgroundRole: return QtCore.QVariant(QtGui.QBrush(UpmsDatabaseModel.TABLE_COLOR)) else: cell_value = self.__records[index.row()].__getattribute__( UpmsDatabaseModel.COLUMN_TO_UPMS_MEASURE_ATTR[index.column()]) if index.column() == UpmsDatabaseModel.Column.TYPE: type_to_str = { UpmsMeasure.MeasureType.MECH_STOPWATCH: Text.get("m_stopwatch"), UpmsMeasure.MeasureType.ELEC_STOPWATCH: Text.get("e_stopwatch"), UpmsMeasure.MeasureType.CLOCK: Text.get("clock"), } cell_value = type_to_str[cell_value] return str(cell_value)
def create_report(self, a_name_template, a_save_folder, a_measure_type: UpmsMeasure.MeasureType, a_photos_path, a_upms_measures: List[UpmsMeasure]): protocol_generators = [] if True: generator = self.create_protocol_generator( a_name_template, a_save_folder, a_measure_type, pg.ExcelProtocolGenerator) if generator is not None: protocol_generators.append(generator) if False: generator = self.create_protocol_generator( a_name_template, a_save_folder, a_measure_type, pg.CalcProtocolGenerator) if generator is not None: protocol_generators.append(generator) for protocol_gen in protocol_generators: if protocol_gen.is_template_ok(): protocol_gen.insert_measures(a_upms_measures) protocol_gen.insert_extra_parameters(self.db.get_parameters()) protocol_gen.insert_photos(a_photos_path, a_upms_measures) protocol_gen.save() QtWidgets.QMessageBox.information( self, Text.get("info"), Text.get("success_generated").format( protocol_gen.get_report_path()), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) if os.name == 'nt': os.startfile(protocol_gen.get_report_path()) else: opener = "open" if sys.platform == "darwin" else "xdg-open" subprocess.call([opener, protocol_gen.get_report_path()]) else: QtWidgets.QMessageBox.critical( self, Text.get("err"), Text.get("data_sheet_not_found").format( protocol_gen.get_report_path()), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok)
def __init__(self, a_parent=None): super().__init__(a_parent) self.ui = AboutForm() self.ui.setupUi(self) self.show() self.ui.version_label.setText( Text.get("version").format(revisions.Revisions.upms_1v_pc)) self.ui.close_button.clicked.connect(self.reject)
def __str__(self): return "{}: {}, " \ "{}: {}, " \ "{}: {}, " \ "{}: {}, " \ "{}: {}, " \ "{}: {}, " \ "{}: {}, ".format(Text.get('id'), self.id, Text.get('uid'), self.user_id, Text.get('type'), UpmsMeasure.TYPE_TO_STR[self.type], Text.get('date'), self.date, Text.get('comment'), self.comment, Text.get('interval'), self.interval, Text.get('result'), self.result)
def create_protocol_generator( self, a_name_template, a_save_folder, a_measure_type, a_generator: Type[pg.UpmsProtocolGenerator] ) -> Optional[pg.UpmsProtocolGenerator]: extension = a_generator.protocol_ext() template_files = \ list(filter(lambda s: s.endswith(extension), self.MEASURE_TYPE_TO_TEMPLATE_PATH[a_measure_type])) template_filename = os.path.join(self.get_application_path(), template_files[0]) if os.path.isfile(template_filename): filename = self.get_accessible_name(a_name_template, a_save_folder, extension) report_path = os.path.join(a_save_folder.rstrip(os.sep), filename) shutil.copyfile(template_filename, report_path) return a_generator(report_path) else: QtWidgets.QMessageBox.critical( self, Text.get("err"), Text.get("templates_are_not_found").format(template_filename), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) return None
def input_result_button_clicked(self, _): rows = self.ui.measures_table.selectionModel().selectedRows() if rows: for idx in rows: real_row = self.proxy.mapToSource(idx).row() self.ui.measures_table.selectionModel().setCurrentIndex( self.measures_table_model.index(idx.row(), 0), QtCore.QItemSelectionModel.ClearAndSelect | QtCore.QItemSelectionModel.Rows) files_path = self.ui.download_path_edit.text() if files_path and os.path.isdir(files_path): upms_measure = self.measures_table_model.get_upms_measure_by_row( real_row) dialog = ResultInputDialog(upms_measure, files_path, self.settings, self) res = dialog.exec() if res == QtWidgets.QDialog.Accepted: new_result = dialog.get_result() self.measures_table_model.update_result( real_row, new_result) logging.warning(upms_measure.result) # Для сохранения состояния (иначе не вызывается closeEvent) dialog.close() else: break else: QtWidgets.QMessageBox.critical(self, Text.get("err"), Text.get("path_err"), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) else: QtWidgets.QMessageBox.information(self, Text.get("info"), Text.get("selection_info"), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok)
def download_file_by_tftp(a_ip: str, a_filename: str, a_dst_filepath: str, a_tries_count=1) -> bool: tftp_client = tftpy.TftpClient(a_ip, 69) try_number = 0 while try_number < a_tries_count: try: tftp_client.download(a_filename, a_dst_filepath, timeout=1) return True except tftpy.TftpTimeout: try_number += 1 logging.error( Text.get("download_file_by_tftp_err").format( a_filename, try_number, a_tries_count)) return False
def create_report_button_clicked(self, _): rows = self.ui.measures_table.selectionModel().selectedRows() if rows: types = [ self.measures_table_model.get_type( self.proxy.mapToSource(idx).row()) for idx in rows ] if len(types) == types.count(types[0]): save_folder = self.ui.save_folder_edit.text() if save_folder and os.path.isdir(save_folder): if self.ui.download_path_edit.text(): name_template = self.ui.name_template_edit.text() if self.ui.name_template_edit.text() else \ self.default_name_template upms_measures = [ self.measures_table_model.get_upms_measure_by_row( self.proxy.mapToSource(idx).row()) for idx in rows ] self.create_report(name_template, save_folder, types[0], self.ui.download_path_edit.text(), upms_measures) else: QtWidgets.QMessageBox.critical( self, Text.get("err"), Text.get("path_err"), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) else: QtWidgets.QMessageBox.critical( self, Text.get("err"), Text.get("save_folder_error"), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) else: QtWidgets.QMessageBox.critical(self, Text.get("err"), Text.get("same_type_err"), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) else: QtWidgets.QMessageBox.information(self, Text.get("info"), Text.get("selection_info"), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok)
def fridge_point_click(): click_time = datetime.datetime.now() try: user = users.get_current_user() if (not user): return json.dumps( {"error": True, "errorMessage": "User not logged in."}) current_fridge_entity = get_current_fridge_entity() if (current_fridge_entity.state == 1): total_points = increment_user_point(user, current_fridge_entity) if (total_points is not None): return json.dumps({"error": False, "points": total_points}) else: return json.dumps({"error": True, "errorMessage": Text.get(Text.ALREADY_GOT_POINT), "time": str(click_time)}) else: return json.dumps( {"error": True, "errorMessage": "Fridge is closed :("}) except Exception as e: return process_exception(e)
def insert_photos(self, a_photos_path: str, a_upms_measures: List[UpmsMeasure]): if self.template_is_ok: if self.photo_sheet in self.workbook.sheetnames: sheet = self.workbook.get_sheet_by_name(self.photo_sheet) else: sheet = self.workbook.create_sheet(self.photo_sheet) vertical_start = 3 vertical_step = 27 horizontal_start = 2 horizontal_step = 9 for idx, upms_measure in enumerate(a_upms_measures): photo_path = a_photos_path.rstrip( os.sep) + os.sep + "{}.jpg".format(upms_measure.id) try: img = openpyxl.drawing.image.Image(photo_path) new_height = img.height * 2 / 3 new_width = img.width * 2 / 3 img.height = new_height img.width = new_width row = vertical_start + idx // 2 * vertical_step if idx % 2 == 0 else \ vertical_start + idx // 2 * vertical_step + 1 col = horizontal_start if idx % 2 == 0 else \ (horizontal_start + horizontal_step) sheet.add_image(img, sheet.cell(row, col).coordinate) cell_font = openpyxl.styles.Font(size='15') sheet.cell(row - 1, col, value=Text.get("measure").format( upms_measure.id)).font = cell_font except FileNotFoundError: logging.warning("File {} is not found".format(photo_path))
def headerData(self, section: int, orientation: Qt.Orientation, role=Qt.DisplayRole): if role != Qt.DisplayRole: return QVariant() if orientation == QtCore.Qt.Horizontal: if section == UpmsDatabaseModel.Column.ID: text = Text.get("id") elif section == UpmsDatabaseModel.Column.USER_ID: text = Text.get("uid_2") elif section == UpmsDatabaseModel.Column.TYPE: text = Text.get("type") elif section == UpmsDatabaseModel.Column.DATE: text = Text.get("date") elif section == UpmsDatabaseModel.Column.COMMENT: text = Text.get("comment") elif section == UpmsDatabaseModel.Column.INTERVAL: text = Text.get("interval") else: # section == UpmsDatabaseModel.Column.RESULT: text = Text.get("result") return text return QVariant()
def download_from_upms_button_clicked(self, _): download_folder = self.ui.download_path_edit.text() if download_folder and os.path.isdir(download_folder): download_filepath = download_folder.rstrip( os.sep) + os.sep + self.measures_filename if self.download_measures_list(download_filepath): with open(download_filepath, 'r', encoding='utf8') as measures_list_file: # Первая строка - заголовок measures_list = [ file for idx, file in enumerate(measures_list_file) if idx != 0 ] update_all = False upms_files_list = upms_tftp.get_files_list( self.ui.ip_combobox.currentText()) self.ui.download_progress_bar.setHidden(False) for number, measure in enumerate(measures_list): self.ui.download_progress_bar.setValue( number / (len(upms_files_list) - 1) * self.ui.download_progress_bar.maximum()) measure_params = [ meas.strip() for meas in measure.strip().split(',') ] upms_measure = UpmsMeasure(*measure_params) upms_prev_measure = self.db.get(upms_measure.id) if upms_measure != upms_prev_measure: if upms_prev_measure is None: self.db.add(upms_measure) self.download_photo(upms_measure.id, upms_files_list, download_folder) else: if update_all: res = QtWidgets.QMessageBox.Yes else: res = QtWidgets.QMessageBox.question( self, Text.get("warning"), Text.get("ask_overwrite").format( upms_measure.id), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.YesAll | QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Cancel, QtWidgets.QMessageBox.Yes) if res == QtWidgets.QMessageBox.Yes: self.db.update(upms_measure) self.download_photo(upms_measure.id, upms_files_list, download_folder) elif res == QtWidgets.QMessageBox.YesAll: self.db.update(upms_measure) self.download_photo(upms_measure.id, upms_files_list, download_folder) update_all = True elif res == QtWidgets.QMessageBox.Cancel: QtWidgets.QMessageBox.warning( self, Text.get("warning"), Text.get("download_canceled"), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) break elif not os.path.isfile( os.path.join(download_folder.rstrip(os.sep), "{}.jpg".format(upms_measure.id))): # Докачиваем файл, если запись в БД есть, а файла нет self.download_photo(upms_measure.id, upms_files_list, download_folder) else: QtWidgets.QMessageBox.information( self, Text.get("info"), Text.get("success_download"), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) self.ui.download_progress_bar.setValue(0) self.ui.download_progress_bar.setHidden(True) self.update_model() else: QtWidgets.QMessageBox.critical(self, Text.get("err"), Text.get("path_err"), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok)
class UpmsDatabaseModel(QAbstractTableModel): class Column(IntEnum): ID = 0 USER_ID = 1 TYPE = 2 DATE = 3 COMMENT = 4 INTERVAL = 5 RESULT = 6 COUNT = 7 COLUMN_TO_NAME = { Column.ID: Text.get("id"), Column.USER_ID: Text.get("uid_2"), Column.TYPE: Text.get("type"), Column.DATE: Text.get("date"), Column.COMMENT: Text.get("comment"), Column.INTERVAL: Text.get("interval"), Column.RESULT: Text.get("result"), } COLUMN_TO_UPMS_MEASURE_ATTR = { Column.ID: "id", Column.USER_ID: "user_id", Column.TYPE: "type", Column.DATE: "date", Column.COMMENT: "comment", Column.INTERVAL: "interval", Column.RESULT: "result", } TABLE_COLOR = QColor(255, 255, 255) def __init__(self, a_db: UpmsDatabase, a_parent=None): super().__init__(a_parent) self.__db = a_db self.__records = self.__db.get_all() def rowCount(self, parent=QModelIndex()): return len(self.__records) def columnCount(self, parent=QModelIndex()): return UpmsDatabaseModel.Column.COUNT def headerData(self, section: int, orientation: Qt.Orientation, role=Qt.DisplayRole): if role != Qt.DisplayRole: return QVariant() if orientation == QtCore.Qt.Horizontal: if section == UpmsDatabaseModel.Column.ID: text = Text.get("id") elif section == UpmsDatabaseModel.Column.USER_ID: text = Text.get("uid_2") elif section == UpmsDatabaseModel.Column.TYPE: text = Text.get("type") elif section == UpmsDatabaseModel.Column.DATE: text = Text.get("date") elif section == UpmsDatabaseModel.Column.COMMENT: text = Text.get("comment") elif section == UpmsDatabaseModel.Column.INTERVAL: text = Text.get("interval") else: # section == UpmsDatabaseModel.Column.RESULT: text = Text.get("result") return text return QVariant() def get_id_by_row(self, a_row): return self.__records[a_row].__getattribute__(UpmsDatabaseModel.COLUMN_TO_UPMS_MEASURE_ATTR[self.Column.ID]) def get_upms_measure_by_row(self, a_row) -> UpmsMeasure: return deepcopy(self.__records[a_row]) def remove_row(self, a_row: int): self.beginRemoveRows(QModelIndex(), a_row, a_row) self.__db.remove(self.__records[a_row].id) del self.__records[a_row] self.endRemoveRows() def update_result(self, a_row: int, a_value: str): self.__records[a_row].result = a_value self.__db.update(self.__records[a_row]) def get_type(self, a_row: int): return self.__records[a_row].type def data(self, index, role=Qt.DisplayRole): if not index.isValid() or (self.rowCount() < index.row()) or \ (role != Qt.DisplayRole and role != Qt.EditRole and role != Qt.BackgroundRole): return QVariant() if role == Qt.BackgroundRole: return QtCore.QVariant(QtGui.QBrush(UpmsDatabaseModel.TABLE_COLOR)) else: cell_value = self.__records[index.row()].__getattribute__( UpmsDatabaseModel.COLUMN_TO_UPMS_MEASURE_ATTR[index.column()]) if index.column() == UpmsDatabaseModel.Column.TYPE: type_to_str = { UpmsMeasure.MeasureType.MECH_STOPWATCH: Text.get("m_stopwatch"), UpmsMeasure.MeasureType.ELEC_STOPWATCH: Text.get("e_stopwatch"), UpmsMeasure.MeasureType.CLOCK: Text.get("clock"), } cell_value = type_to_str[cell_value] return str(cell_value) def setData(self, index: QModelIndex, value: str, role=Qt.EditRole): self.__records[index.row()].__setattr__( UpmsDatabaseModel.COLUMN_TO_UPMS_MEASURE_ATTR[index.column()], value) self.__db.update(self.__records[index.row()]) return True def flags(self, index): item_flags = super().flags(index) if index.isValid(): if index.column() in (UpmsDatabaseModel.Column.COMMENT, UpmsDatabaseModel.Column.RESULT): item_flags |= Qt.ItemIsEditable return item_flags
def choose_download_path_button_clicked(self): new_path = QtWidgets.QFileDialog.getExistingDirectory( self, Text.get("download_folder"), self.settings.path) if new_path: self.ui.download_path_edit.setText(new_path)
def choose_save_folder_path_button_clicked(self): new_path = QtWidgets.QFileDialog.getExistingDirectory( self, Text.get("save_folder"), self.settings.save_folder) if new_path: self.ui.save_folder_edit.setText(new_path)