def __init__(self,parent): global dao super(EditDeliverySlipDialog,self).__init__(parent) title = _("Create delivery slip") self.setWindowTitle(title) top_layout = QVBoxLayout() self.title_widget = TitleWidget(title,self) top_layout.addWidget(self.title_widget) self.info_label = QLabel() self.info_label.setWordWrap(True) top_layout.addWidget(self.info_label) self.buttons = QDialogButtonBox() self.buttons.addButton( QDialogButtonBox.StandardButton.Cancel) self.buttons.addButton( QDialogButtonBox.Ok) order_part_prototype = [] order_part_prototype.append( TextLinePrototype('human_identifier',_('Part n.'),editable=False)) order_part_prototype.append( TextLinePrototype('description',_('Description'),editable=False)) order_part_prototype.append( IntegerNumberPrototype('qty',_('Qty plan.'),editable=False)) order_part_prototype.append( IntegerNumberPrototype('tex2',_('Qty so far'),editable=False)) order_part_prototype.append( IntegerNumberPrototype(None,_('Qty out now'),nullable=True)) self.qty_out_column = len(order_part_prototype) - 1 # order_part_prototype.append( IntegerNumberPrototype(None,_('Reglages'),nullable=True)) # order_part_prototype.append( IntegerNumberPrototype(None,_('Derogation'),nullable=True)) # order_part_prototype.append( IntegerNumberPrototype(None,_('Rebus'),nullable=True)) self.controller_part = PrototypeController(self, order_part_prototype,None,freeze_row_count=True) self.controller_part.view.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents) self.controller_part.view.horizontalHeader().setResizeMode(1,QHeaderView.Stretch) self.controller_part.setModel(TrackingProxyModel(self,order_part_prototype)) self.close_order_checkbox = QCheckBox(_("Close the order")) top_layout.addWidget(self.controller_part.view) # self.time_tracks_view) # top_layout.addWidget(self._make_units_qaulifications_gui()) top_layout.addWidget(self.close_order_checkbox) top_layout.addWidget(self.buttons) self.setLayout(top_layout) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) sg = QDesktopWidget().screenGeometry() self.setMinimumWidth(0.5*sg.width()) self.setMinimumHeight(0.3*sg.height()) self.slip_id = None
def __init__(self, parent, dao, day): super(EditTimeTracksDialog, self).__init__(parent) self.edit_date = day title = _("Time spent on tasks") self.setWindowTitle(title) top_layout = QVBoxLayout() self.title_widget = TitleWidget(title, self) top_layout.addWidget(self.title_widget) hlayout = QHBoxLayout() self.timesheet_info_label = QLabel("Name", self) hlayout.addWidget(self.timesheet_info_label) hlayout.addStretch() top_layout.addLayout(hlayout) info = QLabel( _("On the table below you can have two kinds of line. The grey line which shows the time spent on a task computed on the basis of the actual time recordings. Since those are computed automaticaly, you can't change them. The other lines in black, are those that you will encode have encoded yourself. They represent hours to add or remove to those of the grey lines. So, for example, if you want to remove 3 hours on a task, you encode the task with a duration of three hours." ), self) info.setWordWrap(True) top_layout.addWidget(info) self.buttons = QDialogButtonBox() self.buttons.addButton(QDialogButtonBox.StandardButton.Cancel) self.buttons.addButton(QDialogButtonBox.Ok) if dao.task_dao.tasks_count() > 0: prototype = [] prototype.append( ImputableSelectorPrototype(None, _('Order Part'), nullable=True)) # BUG today is wrong... Must be the imputation date self.task_on_orderpart_prototype = ProxyTaskComboPrototype( 'task', _('Task'), on_date=date.today(), editable=True, nullable=False) prototype.append(self.task_on_orderpart_prototype) prototype.append( DurationPrototype('duration', _('Duration'), format_as_float=False)) prototype.append( ConstrainedMachineSelectorPrototype('machine_id', _('Machine'), nullable=True)) # prototype.append( TimestampPrototype('start_time',_('Start time'),fix_date=day,nullable=True,editable=True)) # prototype.append( TimestampPrototype('encoding_date',_('Recorded at'),editable=False)) self.controller = PrototypeController(self, prototype) self.controller.setModel(TrackingProxyModel(self, prototype)) self.controller.view.horizontalHeader().setResizeMode( 1, QHeaderView.Stretch) self.controller.view.enable_edit_panel() self.controller.model.rowsInserted.connect(self.data_changed_slot) self.controller.model.rowsRemoved.connect(self.data_changed_slot) self.controller.model.dataChanged.connect(self.data_changed_slot) # self.employee_select = QComboBox() # self.employee_select.setModel(self.dao.employee_dao.list_model()) # self.employee_select.setCurrentIndex(0) # self.set_on_selected_employee() # top_layout.addWidget(self.employee_select) top_layout.addWidget( self.controller.view) # self.time_tracks_view) hlayout = QHBoxLayout() self.sum_hours_label = QLabel("12345") self.sum_hours_label.setObjectName("important") # Used for CSS hlayout.addStretch() hlayout.addWidget(QLabel(_("Sum of durations"))) hlayout.addWidget(self.sum_hours_label) top_layout.addLayout(hlayout) top_layout.addWidget(self.buttons) self.setLayout(top_layout) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) # self.employee_select.activated.connect(self.employee_changed) self.resize(800, 400) self.setSizeGripEnabled(True) else: top_layout.addWidget( QLabel( "There are no task in the system " + "for you to report on. Create some " + "tasks first", self)) top_layout.addWidget(self.buttons) self.setLayout(top_layout) self.buttons.accepted.connect(self.accept_direct) self.buttons.rejected.connect(self.reject)
class EditTimeTracksDialog(QDialog): @Slot(QStandardItem) def data_changed_slot(self, item): # mainlog.debug("data_changed_slot") self.model_data_changed = True m = self.controller.model sum_hours = 0 for i in range(m.rowCount()): ndx = m.index(i, 2) #mainlog.debug("editTT : {}: {}".format(i, m.data(ndx,Qt.UserRole))) try: sum_hours = sum_hours + float(m.data(ndx, Qt.UserRole)) except: pass mainlog.debug("Sum = {}".format(sum_hours)) self.sum_hours_label.setText(duration_to_hm(sum_hours)) def __init__(self, parent, dao, day): super(EditTimeTracksDialog, self).__init__(parent) self.edit_date = day title = _("Time spent on tasks") self.setWindowTitle(title) top_layout = QVBoxLayout() self.title_widget = TitleWidget(title, self) top_layout.addWidget(self.title_widget) hlayout = QHBoxLayout() self.timesheet_info_label = QLabel("Name", self) hlayout.addWidget(self.timesheet_info_label) hlayout.addStretch() top_layout.addLayout(hlayout) info = QLabel( _("On the table below you can have two kinds of line. The grey line which shows the time spent on a task computed on the basis of the actual time recordings. Since those are computed automaticaly, you can't change them. The other lines in black, are those that you will encode have encoded yourself. They represent hours to add or remove to those of the grey lines. So, for example, if you want to remove 3 hours on a task, you encode the task with a duration of three hours." ), self) info.setWordWrap(True) top_layout.addWidget(info) self.buttons = QDialogButtonBox() self.buttons.addButton(QDialogButtonBox.StandardButton.Cancel) self.buttons.addButton(QDialogButtonBox.Ok) if dao.task_dao.tasks_count() > 0: prototype = [] prototype.append( ImputableSelectorPrototype(None, _('Order Part'), nullable=True)) # BUG today is wrong... Must be the imputation date self.task_on_orderpart_prototype = ProxyTaskComboPrototype( 'task', _('Task'), on_date=date.today(), editable=True, nullable=False) prototype.append(self.task_on_orderpart_prototype) prototype.append( DurationPrototype('duration', _('Duration'), format_as_float=False)) prototype.append( ConstrainedMachineSelectorPrototype('machine_id', _('Machine'), nullable=True)) # prototype.append( TimestampPrototype('start_time',_('Start time'),fix_date=day,nullable=True,editable=True)) # prototype.append( TimestampPrototype('encoding_date',_('Recorded at'),editable=False)) self.controller = PrototypeController(self, prototype) self.controller.setModel(TrackingProxyModel(self, prototype)) self.controller.view.horizontalHeader().setResizeMode( 1, QHeaderView.Stretch) self.controller.view.enable_edit_panel() self.controller.model.rowsInserted.connect(self.data_changed_slot) self.controller.model.rowsRemoved.connect(self.data_changed_slot) self.controller.model.dataChanged.connect(self.data_changed_slot) # self.employee_select = QComboBox() # self.employee_select.setModel(self.dao.employee_dao.list_model()) # self.employee_select.setCurrentIndex(0) # self.set_on_selected_employee() # top_layout.addWidget(self.employee_select) top_layout.addWidget( self.controller.view) # self.time_tracks_view) hlayout = QHBoxLayout() self.sum_hours_label = QLabel("12345") self.sum_hours_label.setObjectName("important") # Used for CSS hlayout.addStretch() hlayout.addWidget(QLabel(_("Sum of durations"))) hlayout.addWidget(self.sum_hours_label) top_layout.addLayout(hlayout) top_layout.addWidget(self.buttons) self.setLayout(top_layout) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) # self.employee_select.activated.connect(self.employee_changed) self.resize(800, 400) self.setSizeGripEnabled(True) else: top_layout.addWidget( QLabel( "There are no task in the system " + "for you to report on. Create some " + "tasks first", self)) top_layout.addWidget(self.buttons) self.setLayout(top_layout) self.buttons.accepted.connect(self.accept_direct) self.buttons.rejected.connect(self.reject) def keyPressEvent(self, event): # The goal here is to make sure the accept signal is called only # if the user clicks on the "OK" button /with the mouse/ and, # not with the keyboard. if event.key() in (Qt.Key_Enter, Qt.Key_Return): return else: super(EditTimeTracksDialog, self).keyPressEvent(event) def set_employee_and_date( self, employee_id, edit_date ): # FIXME move this into constructore and remove call in using class... Or change the timestamp prototype employee = dao.employee_dao.find_by_id_frozen(employee_id) timetracks = dao.timetrack_dao.all_work_for_employee_date( employee_id, edit_date) self.task_cache = PotentialTasksCache(dao.task_dao, edit_date) mainlog.debug("set_employee_and_date : timetracks are") proxified_timetracks = [] for timetrack in timetracks: mainlog.debug(timetrack) proxified_timetracks.append(TimetrackProxy(timetrack)) mainlog.debug("done") self.edit_date = edit_date self.task_on_orderpart_prototype.on_date = edit_date self.timesheet_info_label.setText( _("Timesheet for <b>{}</b> on <b>{}</b>").format( employee.fullname, date_to_s(edit_date, True))) self.task_on_orderpart_prototype.set_task_cache(self.task_cache) self.controller.model._buildModelFromObjects(proxified_timetracks) self.controller.model.set_row_protect_func( lambda obj, row: obj is not None and obj.managed_by_code, prevent_row_delete_message) self.controller.model.row_update_protect_func = lambda obj, row: obj and obj.managed_by_code self.controller.model.row_update_protect_announce = prevent_row_update_message for i in range(len(timetracks)): row = self.controller.model.table[i] imputable = ImputableProxy(edit_date) imputable.set_on_timetrack(timetracks[i]) row[0] = imputable # for row in self.controller.model.table: # if row[1]: # row[0] = row[1].operation.production_file.order_part # self.controller.model_data_changed = False # FIXME dirty (encapsulate in controller plz) self.current_employee_id_selected = employee_id self.controller.view.setFocus(Qt.OtherFocusReason) self.controller.view.setCurrentIndex(self.controller.model.index(0, 0)) # FIXME Better separate presentation and data layer !!! session().commit() self.data_changed_slot(None) # @Slot(int) # def employee_changed(self,ndx): # # Pay attention ! At this point the rdopdown already report the # # new selection, not the one that is used for the table ! # mainlog.debug("Employee changed to {}, was {}".format(ndx,employee)) # if self.current_employee_selected != ndx: # # Actually changed # if not self.model_data_changed: # self.set_on_selected_employee() # else: # ret = saveCheckBox() # if ret == QMessageBox.Save: # if self.save(): # self.set_on_selected_employee() # else: # self.employee_select.setCurrentIndex(self.current_employee_selected) # elif ret == QMessageBox.Cancel: # # User has cancelled or save didn't work out => we reset to the old value # self.employee_select.setCurrentIndex(self.current_employee_selected) # else: # QMessageBox.Discard # self.set_on_selected_employee() def save(self): mainlog.debug("EditTimeTracksDialog.save()") errors = self.controller.model.validate() if errors: showTableEntryErrorBox(errors) return False tt_start_time = datetime(self.edit_date.year, self.edit_date.month, self.edit_date.day, 6, 0, 0) edited_proxy_tts = self.controller.model.model_to_objects( lambda: TimetrackProxy()) employee_id = self.current_employee_id_selected # for tt in edited_proxy_tts: # mainlog.debug(type(tt)) # mainlog.debug(str(tt)) try: save_proxy_timetracks(edited_proxy_tts, tt_start_time, employee_id) return True except Exception as e: msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Critical) msgBox.setText("There was an error while saving your data") msgBox.setInformativeText(str(e)) msgBox.setStandardButtons(QMessageBox.Ok) # msgBox.setDefaultButton(QMessageBox.Ok); ret = msgBox.exec_() return False @Slot() def accept(self): if self.save(): mainlog.debug("Clearing model {}".format(self.controller.model)) # Don't forget to clear the model so we don't keep any # references to anything self.controller.model.clear() return super(EditTimeTracksDialog, self).accept() else: mainlog.debug("accept was not accepted :-)") @Slot() def accept_direct(self): super(EditTimeTracksDialog, self).accept() self.controller.model.clear() @Slot() def reject(self): super(EditTimeTracksDialog, self).reject() self.controller.model.clear()
class EditSupplyOrderPanel(HorsePanel): supply_order_saved = Signal() def panel_content_hash(self): return (self.current_supply_order_id, self.current_supplier.supplier_id) def needs_close_confirmation(self): return self.model_data_changed def confirm_close(self): return self._save_if_necessary() @Slot() def change_supplier(self): from koi.supply.ChooseSupplierDialog import ChooseSupplierDialog from PySide.QtGui import QDialog d = ChooseSupplierDialog(self) if d.exec_() and d.result( ) == QDialog.Accepted and d.supplier_id != self.current_supplier.supplier_id: mainlog.debug("Supplier chosen {}".format(d.supplier)) self.current_supplier = d.supplier self.supplier_plate_widget.set_contact_data(self.current_supplier) self.data_changed2_slot() @Slot() def print_supply_order(self): if self._save_if_necessary(): try: print_supply_order(self.current_supply_order_id) except Exception as e: showErrorBox(str(e)) def _save_if_necessary(self): """ True if the user has either said he doesn't want to save or he saved successufly. False if the user has cancelled (no save, no "no save") or the save operation has failed """ if self.model_data_changed: ynb = yesNoBox( _("Data were changed"), _("You have changed some of the data in this. Do you want to save before proceeding ?" )) if ynb == QMessageBox.Yes: if self.save( ) != False: # FIXME defensive, make sure it's True # Because when I save, although the order definition is # not meant to change, the order numbers (accounting label, # etc.) might actually change. self.reload() return True else: return False elif ynb == QMessageBox.No: return True elif ynb == QMessageBox.Cancel: return False else: return True def edit_new(self, supplier): """ Start editing a brand new order """ self.current_supplier = supplier self.current_supply_order_id = None self.edit_comment_widget.setText(None) self.delivery_date_widget.set_value(None) self.creation_date_widget.setText("") self.controller_part.model.clear() self.controller_part.model.insertRows(0, 1, QModelIndex()) self.accounting_label = None self._set_view(None, True) mainlog.debug("edit_new : supplier : {}".format( self.current_supplier.supplier_id)) def edit(self, supply_order_id): """ Start editing an existing order """ self._fill_view_with_order_data(supply_order_id) self._set_view(None, False) def reload(self): ndx = self.controller_part.view.currentIndex() self._fill_view_with_order_data(self.current_supply_order_id) self._set_view(ndx, False) def _fill_view_with_order_data(self, order_id): sorder, sorder_parts = supply_order_service.find_by_id(order_id) self.edit_comment_widget.setText(sorder.description) self.delivery_date_widget.set_value(sorder.expected_delivery_date) self.creation_date_widget.setText(date_to_dmy(sorder.creation_date)) self.supplier_reference_widget.setText(sorder.supplier_reference) self.current_supplier = supplier_service.find_by_id(sorder.supplier_id) self.current_supply_order_id = sorder.supply_order_id self.model._buildModelFromObjects(sorder_parts) self.accounting_label = sorder.accounting_label def _set_view(self, ndx=None, start_editing=False): """ Once the data and models are prepared, one comes here to start the editing... """ self.supplier_plate_widget.set_contact_data(self.current_supplier) self.controller_part.view.setFocus() if not ndx: ndx = self.controller_part.model.index(0, 0) # Somehow, editing a cell doesn't set up the currentIndex automatically... self.controller_part.view.setCurrentIndex(ndx) if start_editing: self.controller_part.view.edit(ndx) self.model_data_changed = False self.title_widget.set_modified_flag(False) ref = self.accounting_label or self.supplier_reference_widget.text() if ref: self.set_panel_title(u"{}\n{}".format( ref, self.current_supplier.fullname)) else: self.set_panel_title( _("Supply order") + u"\n" + self.current_supplier.fullname) refs = [] if self.accounting_label: refs.append( u"<span style='color:orange; font-style:normal;'>{}</span>". format(self.accounting_label)) if self.supplier_reference_widget.text(): refs.append( u"<span style='color:black; font-style:normal;'>{}</span>". format(self.supplier_reference_widget.text())) self.in_title_label.setText( _("<h1>Ref. : {}</h1>").format(u" / ".join(refs))) def _validate(self): errs = self.model.validate() if errs: errs = [formatErrorsOnLine(errs)] else: errs = [] if not self.delivery_date_widget.is_valid(): errs.append(_('The date is not valid')) return errs or True def save(self): if self.model_data_changed: focused_widget = QApplication.focusWidget() if isinstance(focused_widget, QLineEdit) and focused_widget.parent() != self: focused_widget.clearFocus() focused_widget = QApplication.focusWidget() validation_results = self._validate() if validation_results != True: showErrorBox(_("The data are not correct"), "<br>-" + "<br>-".join(validation_results)) return False mainlog.debug("save : supplier_id : {}".format( self.current_supplier.supplier_id)) obj = blank_dto(SupplyOrder) obj.supply_order_id = self.current_supply_order_id obj.creation_date = date.today() obj.description = self.edit_comment_widget.toPlainText() obj.supplier_id = self.current_supplier.supplier_id obj.expected_delivery_date = self.delivery_date_widget.value() obj.supplier_reference = self.supplier_reference_widget.text() obj.accounting_label = self.accounting_label def factory(): return blank_dto(SupplyOrderPart) parts_actions = self.model.model_to_objects(factory) try: mainlog.debug("Saving") self.current_supply_order_id = supply_order_service.save( obj, parts_actions) # Reload the data self.reload() mainlog.debug("Emitting change signal") self.supply_order_saved.emit() # self.current_supply_order_id) except Exception as ex: showErrorBox( _("Error while saving"), _("There was an unexpected error while saving your data"), ex, object_name="saveError") if focused_widget: focused_widget.setFocus(Qt.OtherFocusReason) @Slot() def delete(self): if self.current_supply_order_id: s = _("About to delete order {}").format(self.accounting_label) if confirmationBox(s, _("Are you sure ?")): try: supply_order_service.deactivate( self.current_supply_order_id) except Exception as ex: showErrorBox("I could not delete the order", ex=ex) return rep = supply_order_service.find_last_order_id( self.current_supplier.supplier_id) if rep: self.edit(rep) else: self.edit_new(self.current_supplier) else: showErrorBox( _("No order or non-saved order selected"), _("You can only delete an order that has already been saved"), object_name="delete_only_saved_order") return @Slot() def show_actions(self): button = self.action_menu.parent() p = button.mapToGlobal(QPoint(0, button.height())) self.action_menu.exec_(p) @Slot(QStandardItem) def data_changed_slot(self, item): self.model_data_changed = True self.title_widget.set_modified_flag(self.model_data_changed) @Slot() def data_changed2_slot(self): self.model_data_changed = True self.title_widget.set_modified_flag(self.model_data_changed) @Slot() def next_order_for_supplier(self): if self._save_if_necessary(): # This could find nothing if there's no order for the supplier :-) oid = supply_order_service.find_next_for_supplier( self.current_supply_order_id, self.current_supplier.supplier_id) if oid: self.edit(oid) @Slot() def previous_order_for_supplier(self): if self._save_if_necessary(): oid = supply_order_service.find_previous_for_supplier( self.current_supply_order_id, self.current_supplier.supplier_id) if oid: self.edit(oid) def __init__(self, parent): super(EditSupplyOrderPanel, self).__init__(parent) self.current_supply_order_id = None self.proto = [] self.proto.append( TextAreaPrototype('description', _('Description'), editable=True, nullable=False)) self.proto.append( FloatNumberPrototype('quantity', _('Quantity'), editable=True, nullable=False)) self.proto.append( FloatNumberPrototype('unit_price', _('Unit price'), editable=True, nullable=True)) self.delivery_date_prototype = FutureDatePrototype('description', ('Description'), editable=True, nullable=False) self.model = SupplyOrderPartsModel(self, self.proto) self.controller_part = PrototypeController( self, self.proto, ProxyTableView(None, self.proto)) self.controller_part.setModel(self.model) # self.controller_part.view.verticalHeader().hide() self.controller_part.view.horizontalHeader().setResizeMode( 0, QHeaderView.Stretch) self.print_supply_order_action = QAction(_("Print supply order"), self) # , parent self.print_supply_order_action.triggered.connect( self.print_supply_order) self.print_supply_order_action.setShortcut( QKeySequence(Qt.CTRL + Qt.Key_P)) self.print_supply_order_action.setShortcutContext( Qt.WidgetWithChildrenShortcut) self.addAction(self.print_supply_order_action) self.save_supply_order_action = QAction(_("Save supply order"), self) # , parent self.save_supply_order_action.triggered.connect(self.save) self.save_supply_order_action.setShortcut( QKeySequence(Qt.CTRL + Qt.Key_S)) self.save_supply_order_action.setShortcutContext( Qt.WidgetWithChildrenShortcut) self.addAction(self.save_supply_order_action) self.delete_supply_order_action = QAction(_("Deactivate supply order"), self) # , parent self.delete_supply_order_action.triggered.connect(self.delete) self.addAction(self.delete_supply_order_action) self.next_order_for_supplier_action = QAction( _("Next supplier's order"), self) # , parent self.next_order_for_supplier_action.setShortcut( QKeySequence(Qt.CTRL + Qt.Key_PageDown)) self.next_order_for_supplier_action.setShortcutContext( Qt.WidgetWithChildrenShortcut) self.next_order_for_supplier_action.triggered.connect( self.next_order_for_supplier) self.addAction(self.next_order_for_supplier_action) self.previous_order_for_supplier_action = QAction( _("Previous supplier's order"), self) # , parent self.previous_order_for_supplier_action.setShortcut( QKeySequence(Qt.CTRL + Qt.Key_PageDown)) self.previous_order_for_supplier_action.setShortcutContext( Qt.WidgetWithChildrenShortcut) self.previous_order_for_supplier_action.triggered.connect( self.next_order_for_supplier) self.addAction(self.previous_order_for_supplier_action) self.change_supplier_action = QAction(_("Change supplier"), self) # , parent self.change_supplier_action.triggered.connect(self.change_supplier) self.addAction(self.change_supplier_action) # self.controller_operation.view.addAction(self.reprint_delivery_slip) self.controller_part.view.addAction(self.print_supply_order_action) self.controller_part.view.addAction(self.save_supply_order_action) self.controller_part.view.addAction(self.delete_supply_order_action) navigation = NavBar(self, [(self.next_order_for_supplier_action.text(), self.next_order_for_supplier), (self.previous_order_for_supplier_action.text(), self.previous_order_for_supplier), (_("Action"), self.show_actions)]) navigation.buttons[2].setObjectName("specialMenuButton") self.action_menu = QMenu(navigation.buttons[2]) list_actions = [(self.print_supply_order_action, None), (self.save_supply_order_action, None), (self.delete_supply_order_action, None), (self.change_supplier_action, None)] populate_menu(self.action_menu, self, list_actions, context=Qt.WidgetWithChildrenShortcut) self.title_widget = TitleWidget(_("Supply order"), self, navigation) self.supplier_plate_widget = SupplierPlateWidget(self) self.edit_comment_widget = DescribedTextEdit(_("Comments")) self.edit_comment_widget.setMinimumHeight(20) self.edit_comment_widget.setMinimumWidth(600) self.edit_comment_widget.setMaximumHeight(60) self.edit_comment_widget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.supplier_reference_widget = QLineEdit() self.delivery_date_widget = DateEntryWidget() self.delivery_date_widget.setMaximumWidth(100) self.creation_date_widget = QLabel() self.in_title_label = QLabel() top_layout1 = QHBoxLayout() top_layout1.addWidget(self.in_title_label) top_layout1.addStretch() top_layout1.addWidget(self.supplier_plate_widget) hlayout = QHBoxLayout() hlayout.addWidget(QLabel(_("Delivery date"))) hlayout.addWidget(self.delivery_date_widget) hlayout.addStretch() hlayout3 = QHBoxLayout() hlayout3.addWidget(QLabel(_("Creation date"))) hlayout3.addWidget(self.creation_date_widget) hlayout3.addStretch() hlayout2 = QHBoxLayout() hlayout2.addWidget(QLabel(_("Supplier's reference"))) hlayout2.addWidget(self.supplier_reference_widget) hlayout2.addStretch() vlayout = QVBoxLayout() vlayout.addLayout(hlayout) # delivery date vlayout.addLayout(hlayout3) # creation date vlayout.addLayout(hlayout2) # reference vlayout.addStretch() top_layout2 = QHBoxLayout() top_layout2.addLayout(vlayout) top_layout2.addWidget(self.edit_comment_widget) top_layout2.addStretch() top_layout2.setStretch(0, 0) top_layout2.setStretch(1, 0) # For some reason, the stretch added above is not enough # to push the whole layout to the left. I have to set # it's stretch factor too... top_layout2.setStretch(2, 100) vhead_layout = QVBoxLayout() vhead_layout.addWidget(self.title_widget) top_layout1.setContentsMargins(4, 0, 4, 0) # vhead_layout.addLayout(top_layout1) vhead_layout.addWidget(InlineSubFrame(top_layout1, None)) vhead_layout.addLayout(top_layout2) # top_layout2.setContentsMargins(4,4,4,4) #vhead_layout.addWidget(InlineSubFrame(top_layout2,None)) vhead_layout.addWidget(self.controller_part.view) vhead_layout.setStretch(0, 0) vhead_layout.setStretch(1, 0) vhead_layout.setStretch(2, 0) vhead_layout.setStretch(3, 10) self.setLayout(vhead_layout) self.controller_part.view.enable_edit_panel() # Handling changes in the model (helpful to know if saving # is necessary) self.model_data_changed = False self.model.rowsInserted.connect(self.data_changed_slot) self.model.rowsRemoved.connect(self.data_changed_slot) self.model.dataChanged.connect(self.data_changed_slot) self.supplier_reference_widget.textChanged.connect( self.data_changed2_slot) self.edit_comment_widget.textChanged.connect(self.data_changed2_slot) self.delivery_date_widget.textChanged.connect(self.data_changed2_slot)
def __init__(self, parent): super(EditSupplyOrderPanel, self).__init__(parent) self.current_supply_order_id = None self.proto = [] self.proto.append( TextAreaPrototype('description', _('Description'), editable=True, nullable=False)) self.proto.append( FloatNumberPrototype('quantity', _('Quantity'), editable=True, nullable=False)) self.proto.append( FloatNumberPrototype('unit_price', _('Unit price'), editable=True, nullable=True)) self.delivery_date_prototype = FutureDatePrototype('description', ('Description'), editable=True, nullable=False) self.model = SupplyOrderPartsModel(self, self.proto) self.controller_part = PrototypeController( self, self.proto, ProxyTableView(None, self.proto)) self.controller_part.setModel(self.model) # self.controller_part.view.verticalHeader().hide() self.controller_part.view.horizontalHeader().setResizeMode( 0, QHeaderView.Stretch) self.print_supply_order_action = QAction(_("Print supply order"), self) # , parent self.print_supply_order_action.triggered.connect( self.print_supply_order) self.print_supply_order_action.setShortcut( QKeySequence(Qt.CTRL + Qt.Key_P)) self.print_supply_order_action.setShortcutContext( Qt.WidgetWithChildrenShortcut) self.addAction(self.print_supply_order_action) self.save_supply_order_action = QAction(_("Save supply order"), self) # , parent self.save_supply_order_action.triggered.connect(self.save) self.save_supply_order_action.setShortcut( QKeySequence(Qt.CTRL + Qt.Key_S)) self.save_supply_order_action.setShortcutContext( Qt.WidgetWithChildrenShortcut) self.addAction(self.save_supply_order_action) self.delete_supply_order_action = QAction(_("Deactivate supply order"), self) # , parent self.delete_supply_order_action.triggered.connect(self.delete) self.addAction(self.delete_supply_order_action) self.next_order_for_supplier_action = QAction( _("Next supplier's order"), self) # , parent self.next_order_for_supplier_action.setShortcut( QKeySequence(Qt.CTRL + Qt.Key_PageDown)) self.next_order_for_supplier_action.setShortcutContext( Qt.WidgetWithChildrenShortcut) self.next_order_for_supplier_action.triggered.connect( self.next_order_for_supplier) self.addAction(self.next_order_for_supplier_action) self.previous_order_for_supplier_action = QAction( _("Previous supplier's order"), self) # , parent self.previous_order_for_supplier_action.setShortcut( QKeySequence(Qt.CTRL + Qt.Key_PageDown)) self.previous_order_for_supplier_action.setShortcutContext( Qt.WidgetWithChildrenShortcut) self.previous_order_for_supplier_action.triggered.connect( self.next_order_for_supplier) self.addAction(self.previous_order_for_supplier_action) self.change_supplier_action = QAction(_("Change supplier"), self) # , parent self.change_supplier_action.triggered.connect(self.change_supplier) self.addAction(self.change_supplier_action) # self.controller_operation.view.addAction(self.reprint_delivery_slip) self.controller_part.view.addAction(self.print_supply_order_action) self.controller_part.view.addAction(self.save_supply_order_action) self.controller_part.view.addAction(self.delete_supply_order_action) navigation = NavBar(self, [(self.next_order_for_supplier_action.text(), self.next_order_for_supplier), (self.previous_order_for_supplier_action.text(), self.previous_order_for_supplier), (_("Action"), self.show_actions)]) navigation.buttons[2].setObjectName("specialMenuButton") self.action_menu = QMenu(navigation.buttons[2]) list_actions = [(self.print_supply_order_action, None), (self.save_supply_order_action, None), (self.delete_supply_order_action, None), (self.change_supplier_action, None)] populate_menu(self.action_menu, self, list_actions, context=Qt.WidgetWithChildrenShortcut) self.title_widget = TitleWidget(_("Supply order"), self, navigation) self.supplier_plate_widget = SupplierPlateWidget(self) self.edit_comment_widget = DescribedTextEdit(_("Comments")) self.edit_comment_widget.setMinimumHeight(20) self.edit_comment_widget.setMinimumWidth(600) self.edit_comment_widget.setMaximumHeight(60) self.edit_comment_widget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.supplier_reference_widget = QLineEdit() self.delivery_date_widget = DateEntryWidget() self.delivery_date_widget.setMaximumWidth(100) self.creation_date_widget = QLabel() self.in_title_label = QLabel() top_layout1 = QHBoxLayout() top_layout1.addWidget(self.in_title_label) top_layout1.addStretch() top_layout1.addWidget(self.supplier_plate_widget) hlayout = QHBoxLayout() hlayout.addWidget(QLabel(_("Delivery date"))) hlayout.addWidget(self.delivery_date_widget) hlayout.addStretch() hlayout3 = QHBoxLayout() hlayout3.addWidget(QLabel(_("Creation date"))) hlayout3.addWidget(self.creation_date_widget) hlayout3.addStretch() hlayout2 = QHBoxLayout() hlayout2.addWidget(QLabel(_("Supplier's reference"))) hlayout2.addWidget(self.supplier_reference_widget) hlayout2.addStretch() vlayout = QVBoxLayout() vlayout.addLayout(hlayout) # delivery date vlayout.addLayout(hlayout3) # creation date vlayout.addLayout(hlayout2) # reference vlayout.addStretch() top_layout2 = QHBoxLayout() top_layout2.addLayout(vlayout) top_layout2.addWidget(self.edit_comment_widget) top_layout2.addStretch() top_layout2.setStretch(0, 0) top_layout2.setStretch(1, 0) # For some reason, the stretch added above is not enough # to push the whole layout to the left. I have to set # it's stretch factor too... top_layout2.setStretch(2, 100) vhead_layout = QVBoxLayout() vhead_layout.addWidget(self.title_widget) top_layout1.setContentsMargins(4, 0, 4, 0) # vhead_layout.addLayout(top_layout1) vhead_layout.addWidget(InlineSubFrame(top_layout1, None)) vhead_layout.addLayout(top_layout2) # top_layout2.setContentsMargins(4,4,4,4) #vhead_layout.addWidget(InlineSubFrame(top_layout2,None)) vhead_layout.addWidget(self.controller_part.view) vhead_layout.setStretch(0, 0) vhead_layout.setStretch(1, 0) vhead_layout.setStretch(2, 0) vhead_layout.setStretch(3, 10) self.setLayout(vhead_layout) self.controller_part.view.enable_edit_panel() # Handling changes in the model (helpful to know if saving # is necessary) self.model_data_changed = False self.model.rowsInserted.connect(self.data_changed_slot) self.model.rowsRemoved.connect(self.data_changed_slot) self.model.dataChanged.connect(self.data_changed_slot) self.supplier_reference_widget.textChanged.connect( self.data_changed2_slot) self.edit_comment_widget.textChanged.connect(self.data_changed2_slot) self.delivery_date_widget.textChanged.connect(self.data_changed2_slot)
def __init__(self, dao, parent, edit_date): super(EditTaskActionReportsDialog, self).__init__(parent) title = _("Task actions records") self.setWindowTitle(title) self.dao = dao top_layout = QVBoxLayout() self.title_widget = TitleWidget(title, self) top_layout.addWidget(self.title_widget) hlayout = QHBoxLayout() self.timesheet_info_label = QLabel("Name", self) hlayout.addWidget(self.timesheet_info_label) hlayout.addStretch() top_layout.addLayout(hlayout) self.buttons = QDialogButtonBox() self.buttons.addButton(QDialogButtonBox.StandardButton.Cancel) self.buttons.addButton(QDialogButtonBox.Ok) prototype = [] # prototype.append( EmployeePrototype('reporter', _('Description'), dao.employee_dao.all())) prototype.append( OrderPartOnTaskPrototype(None, _('Order Part'), editable=True, nullable=True)) # BUG today is wrong... Must be the imputation date self.task_on_orderpart_prototype = TaskOnOrderPartPrototype( 'task', _('Task'), on_date=date.today(), editable=True, nullable=True) prototype.append(self.task_on_orderpart_prototype) prototype.append( TaskActionTypePrototype('kind', _('Action'), editable=True, nullable=False)) prototype.append( TimestampPrototype('time', _('Hour'), editable=True, nullable=False, fix_date=edit_date)) prototype.append( TimestampPrototype('report_time', _('Recorded at'), editable=False)) prototype.append( TextLinePrototype('origin_location', _('Origin'), editable=False)) prototype.append( TextLinePrototype('editor', _('Editor'), editable=False, default='master')) self.controller = PrototypeController(self, prototype) self.controller.setModel(TrackingProxyModel(self, prototype)) self.controller.view.enable_edit_panel() top_layout.addWidget(self.controller.view) # self.time_tracks_view) top_layout.addWidget(self.buttons) self.setLayout(top_layout) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject)
class EditTaskActionReportsDialog(QDialog): def __init__(self, dao, parent, edit_date): super(EditTaskActionReportsDialog, self).__init__(parent) title = _("Task actions records") self.setWindowTitle(title) self.dao = dao top_layout = QVBoxLayout() self.title_widget = TitleWidget(title, self) top_layout.addWidget(self.title_widget) hlayout = QHBoxLayout() self.timesheet_info_label = QLabel("Name", self) hlayout.addWidget(self.timesheet_info_label) hlayout.addStretch() top_layout.addLayout(hlayout) self.buttons = QDialogButtonBox() self.buttons.addButton(QDialogButtonBox.StandardButton.Cancel) self.buttons.addButton(QDialogButtonBox.Ok) prototype = [] # prototype.append( EmployeePrototype('reporter', _('Description'), dao.employee_dao.all())) prototype.append( OrderPartOnTaskPrototype(None, _('Order Part'), editable=True, nullable=True)) # BUG today is wrong... Must be the imputation date self.task_on_orderpart_prototype = TaskOnOrderPartPrototype( 'task', _('Task'), on_date=date.today(), editable=True, nullable=True) prototype.append(self.task_on_orderpart_prototype) prototype.append( TaskActionTypePrototype('kind', _('Action'), editable=True, nullable=False)) prototype.append( TimestampPrototype('time', _('Hour'), editable=True, nullable=False, fix_date=edit_date)) prototype.append( TimestampPrototype('report_time', _('Recorded at'), editable=False)) prototype.append( TextLinePrototype('origin_location', _('Origin'), editable=False)) prototype.append( TextLinePrototype('editor', _('Editor'), editable=False, default='master')) self.controller = PrototypeController(self, prototype) self.controller.setModel(TrackingProxyModel(self, prototype)) self.controller.view.enable_edit_panel() top_layout.addWidget(self.controller.view) # self.time_tracks_view) top_layout.addWidget(self.buttons) self.setLayout(top_layout) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) # self.resize(640,400) def keyPressEvent(self, event): # The goal here is to make sure the accept signal is called only # if the user clicks on the "OK" button /with the mouse/ and, # not with the keyboard if event.key() in (Qt.Key_Enter, Qt.Key_Return): return else: super(EditTaskActionReportsDialog, self).keyPressEvent(event) def set_employee_date(self, employee, d): self.current_employee = employee self.current_date = d self.timesheet_info_label.setText( _("Time recordings for <b>{}</b> on <b>{}</b>").format( employee.fullname, date_to_s(d, True))) self.controller.model._buildModelFromObjects( dao.task_action_report_dao.get_reports_for_employee_on_date( employee, d)) for i in range(len(self.controller.model.objects)): if self.controller.model.objects[i]: row = self.controller.model.table[i] obj = self.controller.model.objects[i].task if isinstance(obj, TaskOnOrder): row[0] = obj.order elif isinstance(obj, TaskOnOperation): row[0] = obj.operation.production_file.order_part elif isinstance(obj, TaskOnNonBillable): row[0] = "" elif obj is None: row[0] = "" else: raise Exception("Can't work with type {}".format( type(obj))) self.controller.model_data_changed = False # FIXME dirty (encapsulate in controller plz) def save(self): errors = self.controller.model.validate() if errors is not None: showTableEntryErrorBox(errors) return False results = self.controller.model.model_to_objects( lambda: TaskActionReport(), None) def save(self): mainlog.debug("EditTimeTracksDialog.save()") errors = self.controller.model.validate() if errors: showTableEntryErrorBox(errors) return False try: to_delete, to_create, to_update = self.controller.model.filter_db_updates( self.controller.model.model_to_objects( lambda: TaskActionReport())) self.dao.task_action_report_dao.multi_update( to_delete, to_create, to_update, self.current_employee) return True except Exception as e: msgBox = makeErrorBox( _("There was an error while saving your data"), str(e)) msgBox.exec_() return False @Slot() def accept(self): if self.save(): super(EditTaskActionReportsDialog, self).accept() self.deleteLater() @Slot() def reject(self): super(EditTaskActionReportsDialog, self).reject() self.deleteLater()
class TimeTracksOverviewWidget(QWidget): @Slot(QModelIndex) def cell_entered(self,ndx): chrono = datetime.now() employee = self.employees[ndx.row()] a = max(1,ndx.column()) d = date(self.base_date.year,self.base_date.month,min(calendar.monthrange(self.base_date.year,self.base_date.month)[1], max(1,ndx.column()))) # print employee, d # Fill in the timetracks report panel ---------------------------- # First we read the timetrackss and their associated OrderPart t_start = datetime(d.year,d.month,d.day,0,0,0,0) t_end = datetime(d.year,d.month,d.day,23,59,59,999999) # FIXME not abstract enough # FIXME This should be in the DAO tt = session().query(TimeTrack,OrderPart).\ join(TaskOnOperation).join(Operation).join(ProductionFile).join(OrderPart).\ filter(and_(TimeTrack.employee == employee, TimeTrack.start_time >= t_start, TimeTrack.start_time <= t_end)).order_by(asc(TimeTrack.start_time)).all() tt += session().query(TimeTrack,Order).join(TaskOnOrder).join(Order).filter(and_(TimeTrack.employee == employee, TimeTrack.start_time >= t_start, TimeTrack.start_time <= t_end)).order_by(asc(TimeTrack.start_time)).all() tt += session().query(TimeTrack,OperationDefinition).join(TaskOnNonBillable).join(OperationDefinition).filter(and_(TimeTrack.employee == employee, TimeTrack.start_time >= t_start, TimeTrack.start_time <= t_end)).order_by(asc(TimeTrack.start_time)).all() # Fill in the report panel --------------------------------------- self.hours_on_day_subframe.set_title(_("Hours worked on the {} by {}").format(date_to_s(d,True),employee.fullname)) self.controller.model._buildModelFromObjects(map(lambda o : o[0],tt)) # dao.timetrack_dao.all_for_employee(employee)) # self.controller.model.row_protect_func = lambda obj,row: obj is not None and obj.managed_by_code ndx = 0 for row in self.controller.model.table: if row[1]: row[0] = tt[ndx][1] # First column becomes the order ndx += 1 self.controller.view.resizeColumnsToContents() # Fill in the time report panel --------------------------------- self.pointage_timestamp_prototype.set_fix_date(d) self.controller_actions.model._buildModelFromObjects( dao.task_action_report_dao.get_reports_for_employee_on_date(employee,d)) @Slot() def refresh_action(self): global dao self.title_box.set_title(_("Time Records Overview - {}").format(date_to_my(self.base_date,True))) self.employees = dao.employee_dao.all() day_max = calendar.monthrange(self.base_date.year,self.base_date.month)[1] t_start = datetime(self.base_date.year,self.base_date.month,1) t_end = datetime(self.base_date.year,self.base_date.month,day_max,23,59,59,999999) self._table_model.setRowCount( len(self.employees)) self._table_model.setColumnCount( 1+day_max) headers = QStandardItemModel(1, 1+day_max) headers.setHeaderData(0, Qt.Orientation.Horizontal, _("Employee")) for i in range(day_max): headers.setHeaderData(i+1, Qt.Orientation.Horizontal, "{}".format(i+1)) self.headers_view.setModel(headers) # qt's doc : The view does *not* take ownership self.header_model = headers row = 0 for employee in self.employees: # mainlog.debug(u"refresh action employee {}".format(employee)) self._table_model.setData(self._table_model.index(row,0),employee.fullname,Qt.DisplayRole) # FIXME Use a delegate self._table_model.setData(self._table_model.index(row,0),employee,Qt.UserRole) # FIXME Use a delegate tracks = session().query(TimeTrack).filter(and_(TimeTrack.employee_id == employee.employee_id, TimeTrack.start_time >= t_start,TimeTrack.start_time <= t_end)).all() # One bucket per day buckets = [0] * day_max for t in tracks: mainlog.debug("Bucket {}".format(t)) buckets[t.start_time.day - 1] += t.duration for b in range(len(buckets)): if buckets[b] != 0: self._table_model.setData(self._table_model.index(row,b+1),duration_to_s(buckets[b]),Qt.DisplayRole) else: self._table_model.setData(self._table_model.index(row,b+1),None,Qt.DisplayRole) if buckets[b] >= 0: # Clear the background self._table_model.setData(self._table_model.index(row,b+1),None,Qt.BackgroundRole) else: self._table_model.setData(self._table_model.index(row,b+1),QBrush(QColor(255,128,128)),Qt.TextColorRole) self._table_model.setData(self._table_model.index(row,b+1),Qt.AlignRight,Qt.TextAlignmentRole) row += 1 # Compute all mondays indices monday = 0 if t_start.weekday() > 0: monday = 7 - t_start.weekday() all_mondays = [] while monday < day_max: all_mondays.append(monday) monday += 7 today = date.today() for row in range(len(self.employees)): # Mark mondays for col in all_mondays: # col + 1 to account for the employee column self._table_model.setData(self._table_model.index(row,col + 1),QBrush(QColor(230,230,255)),Qt.BackgroundRole) # Mark today if today.month == self.base_date.month and today.year == self.base_date.year: self._table_model.setData(self._table_model.index(row,today.day),QBrush(QColor(255,255,128)),Qt.BackgroundRole) #for i in range(len(all_mondays)): self.table_view.resizeColumnsToContents() # mainlog.debug("Reset selection") ndx = self.table_view.currentIndex() self.table_view.selectionModel().clear() # self.table_view.selectionModel().clearSelection() # self.table_view.selectionModel().select( self.table_view.model().index(ndx.row(),ndx.column()), QItemSelectionModel.Select) # self.table_view.selectionModel().select( self.table_view.model().index(ndx.row(),ndx.column()), QItemSelectionModel.Select) self.table_view.selectionModel().setCurrentIndex( self.table_view.model().index(ndx.row(),ndx.column()), QItemSelectionModel.Select) # self.cell_entered(self.table_view.currentIndex()) @Slot() def month_today(self): self.base_date = date.today() self.refresh_action() @Slot() def month_before(self): m = self.base_date.month if m > 1: self.base_date = date(self.base_date.year,m - 1,self.base_date.day) else: self.base_date = date(self.base_date.year - 1,12,self.base_date.day) self.refresh_action() @Slot() def month_after(self): m = self.base_date.month if self.base_date.year < date.today().year or m < date.today().month: if m < 12: self.base_date = date(self.base_date.year,m + 1,self.base_date.day) else: self.base_date = date(self.base_date.year + 1,1,self.base_date.day) self.refresh_action() @Slot() def edit_timetrack_no_ndx(self): ndx = self.table_view.currentIndex() if ndx.isValid() and ndx.column() >= 0 and ndx.row() >= 0: self.edit_timetrack(ndx) else: showWarningBox(_("Can't edit"),_("You must first select a day/person.")) @Slot(QModelIndex) def edit_timetrack(self,ndx): global dao global user_session if not user_session.has_any_roles(['TimeTrackModify']): return m = self.base_date.month edit_date = date(self.base_date.year,m,ndx.column()) # +1 already in because of employee's names employee = self._table_model.data(self._table_model.index(ndx.row(),0),Qt.UserRole) # FIXME Use a delegate d = EditTimeTracksDialog(self,dao,edit_date) d.set_employee_and_date(employee,edit_date) d.exec_() if d.result() == QDialog.Accepted: self.refresh_action() d.deleteLater() @Slot() def editTaskActionReports(self): if not user_session.has_any_roles(['TimeTrackModify']): return m = self.base_date.month ndx = self.table_view.currentIndex() if ndx.isValid() and ndx.column() >= 0 and ndx.row() >= 0: edit_date = date(self.base_date.year,m,ndx.column()) # +1 already in because of employee's names employee = self._table_model.data(self._table_model.index(ndx.row(),0),Qt.UserRole) # FIXME Use a delegate d = EditTaskActionReportsDialog(dao,self,edit_date) d.set_employee_date(employee, edit_date) d.exec_() if d.result() == QDialog.Accepted: self.refresh_action() d.deleteLater() else: showWarningBox(_("Can't edit"),_("You must first select a day/person.")) @Slot(QModelIndex) def timetrack_changed(self,ndx): selected_timetrack = self.controller.model.object_at(ndx) # Update the colors in the timetrack views # to show what action reports correspond to the # selected timetrack self.controller_actions.model.current_timetrack = selected_timetrack self.controller_actions.model.beginResetModel() self.controller_actions.model.endResetModel() # Make sure the first of the action reports is shown in the # table action_reports = self.controller_actions.model.objects for i in range(len(action_reports)-1,-1,-1): if action_reports[i] and action_reports[i].timetrack == selected_timetrack: self.controller_actions.view.scrollTo(self.controller_actions.model.index(i,0)) break def __init__(self,parent): super(TimeTracksOverviewWidget,self).__init__(parent) self.base_date = date.today() headers = QStandardItemModel(1, 31 + 1) headers.setHeaderData(0, Qt.Orientation.Horizontal, _("Employee")) for i in range(31): headers.setHeaderData(i+1, Qt.Orientation.Horizontal, "{}".format(i+1)) self._table_model = QStandardItemModel(1, 31+1, None) self.headers_view = QHeaderView(Qt.Orientation.Horizontal,self) self.header_model = headers self.headers_view.setResizeMode(QHeaderView.ResizeToContents) self.headers_view.setModel(self.header_model) # qt's doc : The view does *not* take ownership self.table_view = QTableView(None) self.table_view.setModel(self._table_model) self.table_view.setHorizontalHeader(self.headers_view) self.table_view.verticalHeader().hide() self.table_view.setAlternatingRowColors(True) # self.table_view.setSelectionBehavior(QAbstractItemView.SelectRows) self.table_view.setEditTriggers(QAbstractItemView.NoEditTriggers) navbar = NavBar(self, [ (_("Month before"), self.month_before), (_("Today"),self.month_today), (_("Month after"), self.month_after)]) self.title_box = TitleWidget(_("Time Records Overview"),self,navbar) self.vlayout = QVBoxLayout(self) self.vlayout.setObjectName("Vlayout") self.vlayout.addWidget(self.title_box) self.setLayout(self.vlayout) self.hours_per_pers_subframe = SubFrame(_("Hours worked per person"), self.table_view, self) self.vlayout.addWidget(self.hours_per_pers_subframe) hlayout = QHBoxLayout() prototype = [] prototype.append( OrderPartOnTaskPrototype(None, _('Order Part'))) prototype.append( TaskOnOrderPartPrototype('task', _('Task'),on_date=date.today())) prototype.append( DurationPrototype('duration',_('Duration'))) prototype.append( TimestampPrototype('start_time',_('Start time'),fix_date=date.today())) prototype.append( DatePrototype('encoding_date',_('Recorded at'),editable=False)) self.controller = PrototypeController(self,prototype) self.controller.setModel(TrackingProxyModel(self,prototype)) self.controller.view.setColumnWidth(1,300) self.controller.view.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents) self.controller.view.horizontalHeader().setResizeMode(1,QHeaderView.Stretch) navbar = NavBar(self, [ (_("Edit"), self.edit_timetrack_no_ndx)]) self.hours_on_day_subframe = SubFrame(_("Total times on day"), self.controller.view, self,navbar) hlayout.addWidget(self.hours_on_day_subframe) prototype = [] # prototype.append( EmployeePrototype('reporter', _('Description'), dao.employee_dao.all())) prototype.append( TaskDisplayPrototype('task', _('Task'))) self.pointage_timestamp_prototype = TimestampPrototype('time',_('Hour'),editable=False,fix_date=date.today()) prototype.append( self.pointage_timestamp_prototype) prototype.append( TaskActionTypePrototype('kind',_('Action'))) prototype.append( TextLinePrototype('origin_location',_('Origin'))) prototype.append( TextLinePrototype('editor',_('Editor'),editable=False,default='master')) self.controller_actions = PrototypeController(self,prototype) self.controller_actions.setModel(ActionReportModel(self,prototype)) navbar = NavBar(self, [ (_("Edit"), self.editTaskActionReports)]) hlayout.addWidget(SubFrame(_("Time records"),self.controller_actions.view,self,navbar)) self.controller_actions.view.setEditTriggers(QAbstractItemView.NoEditTriggers) self.controller_actions.view.doubleClicked.connect(self.editTaskActionReports) self.controller_actions.view.horizontalHeader().setResizeMode(0,QHeaderView.Stretch) self.controller_actions.view.horizontalHeader().setResizeMode(3,QHeaderView.ResizeToContents) self.controller_actions.view.horizontalHeader().setResizeMode(4,QHeaderView.ResizeToContents) self.vlayout.addLayout(hlayout) self.vlayout.setStretch(0,0) self.vlayout.setStretch(1,300) self.vlayout.setStretch(2,200) # self.table_view.setSelectionBehavior(QAbstractItemView.SelectRows) #self.table_view.entered.connect(self.cell_entered) self.table_view.selectionModel().currentChanged.connect(self.cell_entered) self.table_view.doubleClicked.connect(self.edit_timetrack) self.controller.view.selectionModel().currentChanged.connect(self.timetrack_changed) self.controller.view.setEditTriggers(QAbstractItemView.NoEditTriggers) self.refresh_action()
def __init__(self,parent): super(TimeTracksOverviewWidget,self).__init__(parent) self.base_date = date.today() headers = QStandardItemModel(1, 31 + 1) headers.setHeaderData(0, Qt.Orientation.Horizontal, _("Employee")) for i in range(31): headers.setHeaderData(i+1, Qt.Orientation.Horizontal, "{}".format(i+1)) self._table_model = QStandardItemModel(1, 31+1, None) self.headers_view = QHeaderView(Qt.Orientation.Horizontal,self) self.header_model = headers self.headers_view.setResizeMode(QHeaderView.ResizeToContents) self.headers_view.setModel(self.header_model) # qt's doc : The view does *not* take ownership self.table_view = QTableView(None) self.table_view.setModel(self._table_model) self.table_view.setHorizontalHeader(self.headers_view) self.table_view.verticalHeader().hide() self.table_view.setAlternatingRowColors(True) # self.table_view.setSelectionBehavior(QAbstractItemView.SelectRows) self.table_view.setEditTriggers(QAbstractItemView.NoEditTriggers) navbar = NavBar(self, [ (_("Month before"), self.month_before), (_("Today"),self.month_today), (_("Month after"), self.month_after)]) self.title_box = TitleWidget(_("Time Records Overview"),self,navbar) self.vlayout = QVBoxLayout(self) self.vlayout.setObjectName("Vlayout") self.vlayout.addWidget(self.title_box) self.setLayout(self.vlayout) self.hours_per_pers_subframe = SubFrame(_("Hours worked per person"), self.table_view, self) self.vlayout.addWidget(self.hours_per_pers_subframe) hlayout = QHBoxLayout() prototype = [] prototype.append( OrderPartOnTaskPrototype(None, _('Order Part'))) prototype.append( TaskOnOrderPartPrototype('task', _('Task'),on_date=date.today())) prototype.append( DurationPrototype('duration',_('Duration'))) prototype.append( TimestampPrototype('start_time',_('Start time'),fix_date=date.today())) prototype.append( DatePrototype('encoding_date',_('Recorded at'),editable=False)) self.controller = PrototypeController(self,prototype) self.controller.setModel(TrackingProxyModel(self,prototype)) self.controller.view.setColumnWidth(1,300) self.controller.view.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents) self.controller.view.horizontalHeader().setResizeMode(1,QHeaderView.Stretch) navbar = NavBar(self, [ (_("Edit"), self.edit_timetrack_no_ndx)]) self.hours_on_day_subframe = SubFrame(_("Total times on day"), self.controller.view, self,navbar) hlayout.addWidget(self.hours_on_day_subframe) prototype = [] # prototype.append( EmployeePrototype('reporter', _('Description'), dao.employee_dao.all())) prototype.append( TaskDisplayPrototype('task', _('Task'))) self.pointage_timestamp_prototype = TimestampPrototype('time',_('Hour'),editable=False,fix_date=date.today()) prototype.append( self.pointage_timestamp_prototype) prototype.append( TaskActionTypePrototype('kind',_('Action'))) prototype.append( TextLinePrototype('origin_location',_('Origin'))) prototype.append( TextLinePrototype('editor',_('Editor'),editable=False,default='master')) self.controller_actions = PrototypeController(self,prototype) self.controller_actions.setModel(ActionReportModel(self,prototype)) navbar = NavBar(self, [ (_("Edit"), self.editTaskActionReports)]) hlayout.addWidget(SubFrame(_("Time records"),self.controller_actions.view,self,navbar)) self.controller_actions.view.setEditTriggers(QAbstractItemView.NoEditTriggers) self.controller_actions.view.doubleClicked.connect(self.editTaskActionReports) self.controller_actions.view.horizontalHeader().setResizeMode(0,QHeaderView.Stretch) self.controller_actions.view.horizontalHeader().setResizeMode(3,QHeaderView.ResizeToContents) self.controller_actions.view.horizontalHeader().setResizeMode(4,QHeaderView.ResizeToContents) self.vlayout.addLayout(hlayout) self.vlayout.setStretch(0,0) self.vlayout.setStretch(1,300) self.vlayout.setStretch(2,200) # self.table_view.setSelectionBehavior(QAbstractItemView.SelectRows) #self.table_view.entered.connect(self.cell_entered) self.table_view.selectionModel().currentChanged.connect(self.cell_entered) self.table_view.doubleClicked.connect(self.edit_timetrack) self.controller.view.selectionModel().currentChanged.connect(self.timetrack_changed) self.controller.view.setEditTriggers(QAbstractItemView.NoEditTriggers) self.refresh_action()
class EditDeliverySlipDialog(QDialog): # def _make_units_qaulifications_gui(self): # hlayout = QHBoxLayout() # for qualif in [_("Good"), _("Bad"), _("Test")]: # hlayout.addWidget( QLabel(qualif)) # hlayout.addWidget( QLineEdit()) # # f = QGroupBox(_("Qualification of units")) # f.setLayout(hlayout) # return f def __init__(self,parent): global dao super(EditDeliverySlipDialog,self).__init__(parent) title = _("Create delivery slip") self.setWindowTitle(title) top_layout = QVBoxLayout() self.title_widget = TitleWidget(title,self) top_layout.addWidget(self.title_widget) self.info_label = QLabel() self.info_label.setWordWrap(True) top_layout.addWidget(self.info_label) self.buttons = QDialogButtonBox() self.buttons.addButton( QDialogButtonBox.StandardButton.Cancel) self.buttons.addButton( QDialogButtonBox.Ok) order_part_prototype = [] order_part_prototype.append( TextLinePrototype('human_identifier',_('Part n.'),editable=False)) order_part_prototype.append( TextLinePrototype('description',_('Description'),editable=False)) order_part_prototype.append( IntegerNumberPrototype('qty',_('Qty plan.'),editable=False)) order_part_prototype.append( IntegerNumberPrototype('tex2',_('Qty so far'),editable=False)) order_part_prototype.append( IntegerNumberPrototype(None,_('Qty out now'),nullable=True)) self.qty_out_column = len(order_part_prototype) - 1 # order_part_prototype.append( IntegerNumberPrototype(None,_('Reglages'),nullable=True)) # order_part_prototype.append( IntegerNumberPrototype(None,_('Derogation'),nullable=True)) # order_part_prototype.append( IntegerNumberPrototype(None,_('Rebus'),nullable=True)) self.controller_part = PrototypeController(self, order_part_prototype,None,freeze_row_count=True) self.controller_part.view.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents) self.controller_part.view.horizontalHeader().setResizeMode(1,QHeaderView.Stretch) self.controller_part.setModel(TrackingProxyModel(self,order_part_prototype)) self.close_order_checkbox = QCheckBox(_("Close the order")) top_layout.addWidget(self.controller_part.view) # self.time_tracks_view) # top_layout.addWidget(self._make_units_qaulifications_gui()) top_layout.addWidget(self.close_order_checkbox) top_layout.addWidget(self.buttons) self.setLayout(top_layout) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) sg = QDesktopWidget().screenGeometry() self.setMinimumWidth(0.5*sg.width()) self.setMinimumHeight(0.3*sg.height()) self.slip_id = None def set_data(self,order_id): self.slip_id = None self.order_id = order_id order = dao.order_dao.find_by_id(order_id) parts = list(filter(lambda part:part.qty > 0 and part.tex2 < part.qty, order.parts)) self.controller_part.model._buildModelFromObjects(parts) cn = "" if order.customer_order_name: cn = u" " + _("(customer number <b>{}</b>)").format(order.customer_order_name) self.info_label.setText(_("Creating a new delivery slip for order <b>{}</b>{} of customer <b>{}</b>").format(order.accounting_label,cn,order.customer.fullname)) for p in parts: x = p.order_part_id # Force attribute load session().expunge(p) session().commit() # FIXME let the locks go def _start_edit(self): # Out to allow testing ndx = self.controller_part.model.index(0,self.qty_out_column) self.controller_part.view.setCurrentIndex( ndx) self.controller_part.view.edit( ndx) def exec_(self): # Start editing the table when showing the dialog self._start_edit() super(EditDeliverySlipDialog,self).exec_() def save(self): return True @Slot() def accept(self): # I do this to make sure that if the user was editing some data # in the table, those data will actually be commited once he # pushed the button ndx = self.controller_part.view.currentIndex() self.controller_part.view.setCurrentIndex(self.controller_part.model.index(0,0)) self.controller_part.view.setCurrentIndex(ndx) if self.make_delivery_slip() == True: super(EditDeliverySlipDialog,self).accept() @Slot() def reject(self): super(EditDeliverySlipDialog,self).reject() def _check_unpriced_part(self): t = self.controller_part.model parts = dict() for p in dao.order_part_dao.find_by_order_id(self.order_id): parts[p.order_part_id] = p for i in range(t.rowCount()): if t.objects[i]: qty = t.data( t.index(i,self.qty_out_column), Qt.UserRole) or 0 order_part_id = t.objects[i].order_part_id if qty > 0 and parts[order_part_id].sell_price == 0: return True def _check_for_quantities_too_big(self): t = self.controller_part.model too_big = False order = dao.order_dao.find_by_id(self.order_id) for i in range(t.rowCount()): if t.objects[i]: qty = t.data( t.index(i,self.qty_out_column), Qt.UserRole) or 0 order_part_id = t.objects[i].order_part_id for part in order.parts: if part.order_part_id == order_part_id: if part.tex2 + qty > part.qty: too_big = True break session().commit() return too_big def make_delivery_slip(self): global dao t = self.controller_part.model # mainlog.debug(u"make_delivery_slip() {}".format(t.objects)) # Extract the quantities to get out from the order part table parts_ids_quantities = dict() info = u"" for i in range(t.rowCount()): qty = t.data( t.index(i,self.qty_out_column), Qt.UserRole) or 0 order_part = t.objects[i] mainlog.debug("Line {} qty = {}, order part={} ".format(i,qty, order_part is not None)) if order_part and qty > 0: if order_part.order_part_id not in parts_ids_quantities: parts_ids_quantities[order_part.order_part_id] = 0 parts_ids_quantities[order_part.order_part_id] += qty info = info + ("<li>" + _("For {} {}, quantity {}")\ + "</li>").format(t.data( t.index(i,0), Qt.UserRole), t.data( t.index(i,1), Qt.UserRole), qty) info = u"<ul>{}</ul>".format(info) mainlog.debug("edit_dialog : checking for missing quantities") if len(parts_ids_quantities) == 0: showWarningBox(_("You requested to create a new delivery slip. However, you didn't encode any quantities"),None,None,"quantity_missing") return False mainlog.debug("edit_dialog : checking for quantities") if self._check_for_quantities_too_big(): showErrorBox(_("One quantity is too big"), _("Pay attention ! On some parts, you gave a quantity out that will make the total quantity out bigger than what was ordered. You must either change the quantity out or change the planned quantity."),None,"quantityTooBig") return False if self._check_unpriced_part(): showWarningBox(_("Some of the parts you want to make a delivery slip for have a null sell price. This is not an error but you may want to double check that situation."),None,None,"unpriced_part") mainlog.debug("edit_dialog : confirmationBox to be opened order_id is {}".format(self.order_id)) if confirmationBox(u"<font color='red'><b>{}</b></font>".format(_("<b>You're about to make a new delivery slip. This can't be reversed, please confirm.\n Here are the quantities you're going to record")),info,"confirmDSCreation"): mainlog.debug("confirmationBox was OK") try: self.slip_id = dao.delivery_slip_part_dao.make_delivery_slip_for_order( self.order_id, parts_ids_quantities, datetime.now(), self.close_order_checkbox.checkState() == Qt.Checked) mainlog.debug("A delivery slip was created {}".format(self.slip_id)) return True except Exception as ex: showErrorBox(_("Error while creating the delivery slip"), _("The delivery slip was not created due to an unexpected error."),ex) return False