def __init__(self, app, parent=None): super(Form, self).__init__(parent) self.current_focus = None self.app = app self.connect(self.app, SIGNAL('focusChanged(QWidget*, QWidget*)'), self.focus_changed) self.setWindowFlags(self.windowFlags() | Qt.WindowMinMaxButtonsHint) self.resize(920, 670) self.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.setLayout(self.gen_main_layout()) self.le_worker_name.setFixedSize(100, 30) self.set_time_attributes() for _le_attr in ['le_waste_sum', 'le_labor_hour_sum', 'le_assist_sum', 'le_labor_hour_aux']: self.__getattribute__(_le_attr).setReadOnly(True) self.make_connections() self.worker_dict = dict(ExcelOperator(config.XLS_PATH).get_id_name_pairs(0)) self.set_tab_orders() self.le_worker_id.setFocus() self.db_operator = SQLiteOperator(self.worker_dict, unicode(self.dt.day)) self.validate_worker_id = lambda text: self._validate_text(text, u'请检查员工信息!') self.validate_day = lambda text: self._validate_text(text, u'请检查日期!')
class Form(QDialog, object): _font = QFont(u'Consolas', 14) _le_attributes = [[['day', 'month', 'labor_hour_sum'], ['worker_id', 'worker_name', 'waste_sum']], [['waste_1', 'waste_2', 'waste_3'], ['assist_1', 'assist_2', 'assist_sum'], ['worker_id_aux', 'worker_name_aux', 'labor_hour_aux']]] _le_attributes = map(lambda sub_list: map(lambda l: map(lambda item: 'le_' + item, l), sub_list), _le_attributes) _le_labels = [[[u'日期', u'月份', u'工时合计'], [u'编号', u'姓名', u'废品合计']], [[u'废品1', u'废品2', u'废品3'], [u'辅助1', u'辅助2', u'辅助合计'], [u'编号', u'姓名', u'工时']]] _max_le_amount = config.max_pair_num _pair_widget_range = range(1, _max_le_amount + 1) _waste_widget_range = range(1, 4) _assist_widget_range = range(1, 3) _labor_hour_prf = 'le_labor_hour_' _real_amount_prf = 'le_real_amount_' _labor_hour_attrs = map(concat_prf(_labor_hour_prf), _pair_widget_range) _real_amount_attrs = map(concat_prf(_real_amount_prf), _pair_widget_range) _hour_amount_pair = zip(_labor_hour_attrs, _real_amount_attrs) _waste_attrs = map(concat_prf('le_waste_'), _waste_widget_range) _assist_attrs = map(concat_prf('le_assist_'), _assist_widget_range) _btn_attributes = ['ok', 'find', 'fix', 'reset'] _btn_labels = [u'确定', u'找回', u'改正', u'重置'] _editable_widget_attrs = list(interleave(_labor_hour_attrs, _real_amount_attrs)) +\ _waste_attrs + _assist_attrs + ['le_worker_id_aux'] def __init__(self, app, parent=None): super(Form, self).__init__(parent) self.current_focus = None self.app = app self.connect(self.app, SIGNAL('focusChanged(QWidget*, QWidget*)'), self.focus_changed) self.setWindowFlags(self.windowFlags() | Qt.WindowMinMaxButtonsHint) self.resize(920, 670) self.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) self.setLayout(self.gen_main_layout()) self.le_worker_name.setFixedSize(100, 30) self.set_time_attributes() for _le_attr in ['le_waste_sum', 'le_labor_hour_sum', 'le_assist_sum', 'le_labor_hour_aux']: self.__getattribute__(_le_attr).setReadOnly(True) self.make_connections() self.worker_dict = dict(ExcelOperator(config.XLS_PATH).get_id_name_pairs(0)) self.set_tab_orders() self.le_worker_id.setFocus() self.db_operator = SQLiteOperator(self.worker_dict, unicode(self.dt.day)) self.validate_worker_id = lambda text: self._validate_text(text, u'请检查员工信息!') self.validate_day = lambda text: self._validate_text(text, u'请检查日期!') def focus_changed(self, _, now): self.current_focus = now _sqlite_attrs = ['le_worker_id'] +\ list(interleave(_labor_hour_attrs, _real_amount_attrs)) +\ _waste_attrs + _assist_attrs +\ ['le_worker_id_aux'] _sqlite_col_names = map(lambda s: unicode(s[3:]), _sqlite_attrs) def dump_all(self): result = {} for key, attr in zip(Form._sqlite_col_names, Form._sqlite_attrs): text = unicode(self.__getattribute__(attr).text()) if attr == 'le_worker_id': if not self.validate_worker_id(text): return {} if text.isdigit(): result[key] = int(text) else: if config.FORCE_OVERRIDE: result[key] = None return result def make_connections(self): self.connect(self.le_worker_id, SIGNAL('textEdited(QString)'), partial(self.update_worker_name, which_one=self.le_worker_name)) self.connect(self.le_worker_id_aux, SIGNAL('textEdited(QString)'), partial(self.update_worker_name, which_one=self.le_worker_name_aux)) self.connect(self.le_worker_id_aux, SIGNAL('textEdited(QString)'), self.update_labor_hour_aux) self.connect(self.le_worker_name, SIGNAL('textEdited(QString)'), partial(self.update_worker_id, which_one=self.le_worker_id)) self.connect(self.le_worker_name_aux, SIGNAL('textEdited(QString)'), partial(self.update_worker_id, which_one=self.le_worker_id_aux)) self.connect_lot(Form._waste_attrs, self.le_waste_sum) self.connect_lot(Form._assist_attrs, self.le_assist_sum) self.connect_group() self.connect(self.btn_ok, SIGNAL('clicked()'), self.btn_ok_clicked) self.connect(self.btn_find, SIGNAL('clicked()'), self.btn_find_clicked) self.connect(self.le_labor_hour_sum, SIGNAL('textChanged(QString)'), self.update_labor_hour_aux) self.connect(self.btn_fix, SIGNAL('clicked()'), partial(self.btn_ok_clicked, override=True)) def update_labor_hour_aux(self): if not self.le_worker_id_aux.text(): self.le_labor_hour_aux.setText(u'') return content = self.le_labor_hour_sum.text() if content: content = float(content) if content < 8: hour_aux = 4 elif 8 <= content < 12: hour_aux = 6 elif 12 <= content < 16: hour_aux = 8 else: hour_aux = 10 self.le_labor_hour_aux.setText(unicode(hour_aux)) def update_labor_hour_aux_from_db(self, day): if not self.le_worker_id_aux.text(): self.le_labor_hour_aux.setText(u'') return _, aux, _, _ = self.db_operator.get_data_per_day(int(self.le_worker_id_aux.text()), unicode(day)) if aux: self.le_labor_hour_aux.setText(unicode(aux)) def _validate_text(self, text, error_msg): if (not text) or (text == u'0'): QMessageBox.critical(self, u'错误', error_msg, QMessageBox.Ok) return False return True def keyPressEvent(self, event): if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter: if event.modifiers() == Qt.ControlModifier: event.accept() self.btn_ok_clicked() return if isinstance(self.current_focus, QPushButton): event.accept() self.btn_ok_clicked() return if any(map(self.current_focus.name.startswith, ['le_labor_hour', 'le_real_amount', 'le_waste', 'le_assist', 'le_worker_id'])): self.current_focus.tab_next.setFocus() event.accept() elif isinstance(self.current_focus, QPushButton): event.accept() else: event.ignore() def clear_all_editable(self, except_=('le_worker_name',)): for attr in Form._editable_widget_attrs + ['le_worker_name', 'le_worker_name_aux']: if attr in except_: continue self.__getattribute__(attr).setText(u'') def query_last_worker_aux(self, worker_id, day): result = self.db_operator.retrieve(worker_id, day) if result: result = result['worker_id_aux'] if result: return result return False def btn_ok_clicked(self, override=False): day = unicode(self.le_day.text()) if not self.validate_day(day): return dumped = self.dump_all() if not override: if not self.db_operator.is_empty_row(worker_id=dumped['worker_id'], day=day): QMessageBox.critical(self, u'错误', u'修改请用改正按钮!', QMessageBox.Ok) return # 先清除上个辅助工人的工时 last_worker_id_aux = self.query_last_worker_aux(dumped['worker_id'], day) if last_worker_id_aux: self.db_operator.write_back_single( last_worker_id_aux, None, day ) if dumped: self.db_operator.write_back(dumped, day) worker_aux = unicode(self.le_worker_id_aux.text()) if worker_aux: worker_aux = int(worker_aux) self.update_labor_hour_sum() self.update_labor_hour_aux() labor_hour_aux = int(self.le_labor_hour_aux.text()) self.db_operator.write_back_single(worker_aux, labor_hour_aux, day) self.clear_all_editable(except_=()) self.le_worker_id.setFocus() self.le_worker_id.setText(u'') def btn_find_clicked(self): worker_id = unicode(self.le_worker_id.text()) day = unicode(self.le_day.text()) if not self.validate_worker_id(worker_id): return else: worker_id = int(worker_id) if not self.validate_day(day): return results = self.db_operator.retrieve(worker_id, day) if results: results = results.items() _, labor_hour_aux_to = results[-1] self.clear_all_editable() for attr, (_, item) in zip(Form._editable_widget_attrs, results[1:-1]): if item: self.__getattribute__(attr).setText(unicode(item)) self.update_worker_name(self.le_worker_id_aux.text(), self.le_worker_name_aux) self.update_labor_hour_aux_from_db(day) self.update_worker_name(self.le_worker_id.text(), self.le_worker_name) def connect_lot(self, attrs, sum_widget): target_func = self.gen_update_sum_slot(attrs, sum_widget) for attr in attrs: widget = self.__getattribute__(attr) self.connect(widget, SIGNAL('textChanged(QString)'), target_func) # self.connect(widget, # SIGNAL('returnPressed()'), # self.go_to_next_tab) def connect_group(self): for attrs in Form._hour_amount_pair: for attr in attrs: widget = self.__getattribute__(attr) self.connect(widget, SIGNAL('textChanged(QString)'), self.update_labor_hour_sum) # self.connect(widget, # SIGNAL('returnPressed()'), # self.go_to_next_tab) def go_to_next_tab(self): self.sender().tab_next.setFocus() def update_labor_hour_sum(self): labor_hour_sum = .0 for lb_attr, ra_attr in Form._hour_amount_pair: labor_hour = unicode(self.__getattribute__(lb_attr).text()) real_amount = unicode(self.__getattribute__(ra_attr).text()) if labor_hour and real_amount: labor_hour, real_amount = map(float, (labor_hour, real_amount)) if labor_hour: labor_hour_sum += (real_amount / labor_hour) if labor_hour else .0 labor_hour_sum *= 8 labor_hour_sum = round(labor_hour_sum, 1) self.le_labor_hour_sum.setText(unicode(labor_hour_sum)) def update_worker_id(self, worker_name, which_one): inverted = {value: key for key, value in self.worker_dict.iteritems()} text = '' worker_name = unicode(worker_name) if worker_name in inverted: text = inverted[worker_name] elif worker_name: text = u'查无此人' which_one.setText(text) _tab_order = list(chain( ['le_worker_id'], # , 'le_worker_name'], interleave(_labor_hour_attrs, _real_amount_attrs), _waste_attrs, _assist_attrs, ['le_worker_id_aux'],#, 'le_worker_name_aux', # 'le_labor_hour_aux'], map(concat_prf('btn_'), _btn_attributes))) def set_tab_orders(self): for prev, succ in take_adj(Form._tab_order): if succ: prev_widget = self.__getattribute__(prev) succ_widget = self.__getattribute__(succ) prev_widget.tab_next = succ_widget prev_widget.setFocusPolicy(Qt.StrongFocus) succ_widget.setFocusPolicy(Qt.StrongFocus) self.setTabOrder(prev_widget, succ_widget) self.setTabOrder(self.btn_reset, self.le_worker_id) self.le_day.setFocusPolicy(Qt.StrongFocus ^ Qt.TabFocus) self.le_month.setFocusPolicy(Qt.StrongFocus ^ Qt.TabFocus) self.le_worker_name.setFocusPolicy(Qt.StrongFocus ^ Qt.TabFocus) self.le_worker_name_aux.setFocusPolicy(Qt.StrongFocus ^ Qt.TabFocus) self.le_real_amount_3.tab_next = self.le_waste_1 def update_worker_name(self, worker_id, which_one): worker_id = unicode(worker_id) text = '' if worker_id in self.worker_dict: text = self.worker_dict[worker_id] elif worker_id: text = u'查无此人' which_one.setText(text) def gen_update_sum_slot(self, target_attrs, sum_widget): def _(): values = map(int, filter(lambda x: x, map(lambda attr: self.__getattribute__(attr).text(), target_attrs))) sum_widget.setText(unicode(sum(values))) return _ def gen_main_layout(self): v_layout = QVBoxLayout() title = QLabel(u'<center><font color="blue"><b>保 持 架 分 厂 工 时 录 入 系 统</b></font></center>') title.setFont(QFont(u'Arial', 30)) v_layout.addWidget(title) v_layout.addStretch() for _ in (self.gen_g_layout(Form._le_attributes[0], Form._le_labels[0]), self.gen_labor_hour_layout(), self.gen_g_layout(Form._le_attributes[1], Form._le_labels[1])): v_layout.addLayout(_) v_layout.addStretch() h_layout = QHBoxLayout() h_layout.addStretch() for attr, label in zip(Form._btn_attributes, Form._btn_labels): btn = QPushButton(label) btn.setFont(Form._font) btn.setFixedSize(150, 50) btn.setAutoDefault(False) h_layout.addWidget(btn) h_layout.addStretch() self.__setattr__('btn_' + attr, btn) layout = QVBoxLayout() layout.addLayout(v_layout) layout.addLayout(h_layout) return layout def gen_label(self, label): l = QLabel(label) l.setFont(Form._font) return l def gen_labor_hour_layout(self): h_layout = QHBoxLayout() h_layout.addStretch() for col_num, nums in enumerate(take(Form._pair_widget_range, by=3)): gl = QGridLayout() gl.addWidget(self.gen_label(u'班产'), 0, 0, Qt.AlignLeft) gl.addWidget(self.gen_label(u'数量'), 0, 1, Qt.AlignLeft) for cnt, num in enumerate(nums): def _(attr_prefix, col): line_edit = self.produce_eligible_line_edit(True) line_edit.name = attr_prefix + str(num) gl.addWidget(line_edit, cnt + 1, col) self.__setattr__(attr_prefix + str(num), line_edit) _(Form._labor_hour_prf, 0) _(Form._real_amount_prf, 1) h_layout.addLayout(gl) # if col_num < 2: h_layout.addStretch() return h_layout def set_time_attributes(self): self.dt = get_today() self.le_day.setText(unicode(self.dt.day)) self.le_day.last_content = self.le_day.text() self.le_month.setText(unicode(self.dt.month)) self.le_month.last_content = self.le_month.text() self.le_day.maximum = get_month_day_num() self.le_month.maximum = 12 self.connect(self.le_day, SIGNAL('textEdited(QString)'), self.restrict_content) self.connect(self.le_month, SIGNAL('textEdited(QString)'), self.restrict_content) self.connect(self.le_month, SIGNAL('textEdited(QString)'), self.update_le_day_maximum) def update_le_day_maximum(self, content): content = unicode(content) if content: self.le_day.maximum = calendar.monthrange(self.dt.year, int(content))[1] def restrict_content(self, content): maximum = self.sender().maximum content = unicode(content) if content: if not content.isdigit(): self.sender().setText(self.sender().last_content) else: if int(content) > int(maximum): self.sender().setText(unicode(maximum)) self.sender().last_content = self.sender().text() def gen_g_layout(self, le_attrs, le_labels): gls = [QGridLayout() for _ in range(len(le_attrs[0]))] for row, (attrs, labels) in enumerate(zip(le_attrs, le_labels)): for i, (attr, label) in enumerate(zip(attrs, labels)): gls[i].addWidget(self.gen_label(label), row, 0) numeric_only = False if ('name' in attr) or ('sum' in attr) else True line_edit = self.produce_eligible_line_edit(numeric_only) line_edit.name = attr gls[i].addWidget(line_edit, row, 1) self.__setattr__(attr, line_edit) h_layout = QHBoxLayout() h_layout.addStretch() for gl in gls: h_layout.addLayout(gl) h_layout.addStretch() return h_layout def produce_eligible_line_edit(self, numeric_only, width=80): line_edit = QLineEdit() line_edit.setText(config.DEFAULT_TEXT) line_edit.setFixedSize(width, 30) line_edit.setAlignment(Qt.AlignRight) line_edit.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)) line_edit.setFont(self._font) line_edit.setFocusPolicy(Qt.NoFocus) if numeric_only: line_edit.setValidator(QIntValidator()) return line_edit