Example #1
0
 def create_size_menu(self):
     """ Create the toolbar's buttons size menu
     """
     menu = QMenu(self)
     group = QActionGroup(self)
     sizes = (_("Tiny"), 16), (_("Small"), 32), (_("Medium"),
                                                 48), (_("Big"), 64)
     for name, size in sizes:
         action = QAction(name, menu)
         action.setCheckable(True)
         if size == self.base.toolbar_size:
             action.setChecked(True)
         action.triggered.connect(partial(self.set_btn_size, size))
         group.addAction(action)
         menu.addAction(action)
     return menu
Example #2
0
    def __init__(self, parent=None):
        super(Status, self).__init__(parent)
        self.setupUi(self)
        self.base = parent

        self.wait_anim = QMovie(":/stuff/wait.gif")
        self.anim_lbl.setMovie(self.wait_anim)
        self.anim_lbl.hide()

        self.show_menu = QMenu(self)
        for i in [
                self.act_page, self.act_date, self.act_text, self.act_comment
        ]:
            self.show_menu.addAction(i)
            # noinspection PyUnresolvedReferences
            i.triggered.connect(self.on_show_items)
            i.setChecked(True)

        sort_menu = QMenu(self)
        ico_sort = QIcon(":/stuff/sort.png")
        group = QActionGroup(self)

        action = QAction(_("Date"), sort_menu)
        action.setCheckable(True)
        action.setChecked(not self.base.high_by_page)
        action.triggered.connect(self.base.set_highlight_sort)
        action.setData(False)
        group.addAction(action)
        sort_menu.addAction(action)

        action = QAction(_("Page"), sort_menu)
        action.setCheckable(True)
        action.setChecked(self.base.high_by_page)
        action.triggered.connect(self.base.set_highlight_sort)
        action.setData(True)
        group.addAction(action)
        sort_menu.addAction(action)

        sort_menu.setIcon(ico_sort)
        sort_menu.setTitle(_("Sort by"))
        self.show_menu.addMenu(sort_menu)

        self.show_items_btn.setMenu(self.show_menu)
class PluginBaseInstruments(IPlugin):
    def __init__(self, data_singleton):
        self.data_singleton = data_singleton
        self.mw = self.data_singleton.mainWindow
        self.menu_instruments = None
        self.base_inst_tool_bar = None
        self.base_inst_action_group = None
        self.instruments = []

    def name(self):
        return 'Base Instruments'

    def version(self):
        return '0.0.1'

    def description(self):
        return 'Base Instruments'

    def initialize(self):
        self.instruments.append(EraserInstrument(self.data_singleton))
        self.instruments.append(PencilInstrument(self.data_singleton))
        self.instruments.append(LineInstrument(self.data_singleton))
        self.instruments.append(RectangleInstrument(self.data_singleton))
        self.instruments.append(FillInstrument(self.data_singleton))

        self.base_inst_tool_bar = self.mw.addToolBar(self.description())
        self.base_inst_tool_bar.setObjectName(self.name())
        self.base_inst_tool_bar.setToolButtonStyle(Qt.ToolButtonIconOnly)

        self.base_inst_action_group = QActionGroup(self.base_inst_tool_bar)
        self.base_inst_action_group.setExclusive(True)
        self.base_inst_action_group.triggered.connect(lambda x: self.triggered_action_instrument(x))

        self.menu_instruments = self.mw.ui.menuInstruments

        for inst in self.instruments:
            act = self.base_inst_tool_bar.addAction(inst.name())
            # TODO: objectName вида <class 'baseinstruments.rectangleinstrument.RectangleInstrument'>
            # кажется неудобным, может другое значение составлять
            act.setObjectName(str(type(inst)))
            act.setToolTip(inst.description())
            if inst.icon():
                act.setIcon(inst.icon())
            act.setCheckable(True)

            self.base_inst_action_group.addAction(act)
            self.menu_instruments.addActions(self.base_inst_action_group.actions())
            self.data_singleton.action_inst_dict[act] = inst

    def destroy(self):
        self.instruments.clear()

        self.mw.removeToolBar(self.base_inst_tool_bar)

        # base_inst_tool_bar удалит и base_inst_action_group, и действия
        self.base_inst_tool_bar.deleteLater()
        self.base_inst_tool_bar = None
        self.base_inst_action_group = None

        self.data_singleton.action_inst_dict.clear()
        self.data_singleton.current_instrument = None

    def triggered_action_instrument(self, action):
        instrument = self.data_singleton.action_inst_dict[action]
        self.data_singleton.current_instrument = instrument
    def handleEvents(self, event, signals):
        att = self.axisOrder[self.findAxisIndex(event.x)]
        # context menu
        if event.contextRequested:
            contextMenu = QMenu(self)
            
            contextMenu.addAction(u'Select all')
            contextMenu.addAction(u'Select none')
            
            contextMenu.addSeparator()
            
            
            act = QAction(u'Hide Axis', self)
            contextMenu.addAction(act)
            if len(self.axisOrder) <= 1:
                act.setEnabled(False)
            
            axesMenu = QMenu(u'Show/Hide Axes', self)
            axesActions = QActionGroup(self)
            for a in self.axisOrder:
                act = QAction(a,self,checkable=True)
                if self.axes[a].visible:
                    act.toggle()
                if len(self.axisOrder) <= 1:
                    act.setEnabled(False)
                axesActions.addAction(act)
            for act in axesActions.actions():
                axesMenu.addAction(act)
            contextMenu.addMenu(axesMenu)
            
            contextMenu.addSeparator()
            
            contextMenu.addAction(u'Use as X axis')
            contextMenu.addAction(u'Use as Y axis')
            
            resultAction = contextMenu.exec_(QCursor.pos())
            
            if resultAction != None and resultAction != 0:
                # Select all
                if resultAction.text() == u'Select all':
                    self.app.intMan.newOperation(operation.ALL,att=att.dataAxis)
                
                # Select none
                if resultAction.text() == u'Select none':
                    self.app.intMan.newOperation(operation.NONE,att=att.dataAxis)
                
                # Hide axis
                if resultAction.text() == u'Hide Axis':
                    self.toggleVisible(att)
                
                # Toggle axis
                if resultAction.actionGroup() == axesActions:
                    self.toggleVisible(resultAction.text())

                # X axis
                if resultAction.text() == u'Use as X axis':
                    if self.app.currentYattribute != self.app.currentXattribute:
                        self.axes[self.app.currentXattribute].visAxis.handle.background.setAttribute('fill',self.normalHandleColor)
                        self.axes[self.app.currentXattribute].visAxis.handle.originalBackgroundColor = self.normalHandleColor
                    self.axes[att].visAxis.handle.background.setAttribute('fill',self.activeHandleColor)
                    self.axes[att].visAxis.handle.originalBackgroundColor = self.activeHandleColor
                    
                    self.app.notifyAxisChange(att,xAxis=True)
                
                # Y axis
                if resultAction.text() == u'Use as Y axis':
                    if self.app.currentXattribute != self.app.currentYattribute:
                        self.axes[self.app.currentYattribute].visAxis.handle.background.setAttribute('fill',self.normalHandleColor)
                        self.axes[self.app.currentYattribute].visAxis.handle.originalBackgroundColor = self.normalHandleColor
                    self.axes[att].visAxis.handle.background.setAttribute('fill',self.activeHandleColor)
                    self.axes[att].visAxis.handle.originalBackgroundColor = self.activeHandleColor
                    
                    self.app.notifyAxisChange(att,xAxis=False)
        
        #if linesMoved:
        #    self.highlightedLayer.refreshLines(self.app.highlightedRsNumbers)
        
        return signals
Example #5
0
class Actions:

    def __init__(self, window, fontSizeSpinBox=None):
        self.window = window
        self.state = window.state
        self.fontSizeSpinBox = fontSizeSpinBox
        if self.fontSizeSpinBox is not None:
            self.fontSizeSpinBox.valueChanged.connect(self.setFontSize)
        self.boldAction = Lib.createAction(
            window, ":/format-text-bold.svg", "&Bold", self.toggleBold,
            QKeySequence.Bold, """<p><b>Format→Bold</b> ({})</p>
<p>Toggle bold on or off.</p>""".format(QKeySequence(
                                        QKeySequence.Bold).toString()))
        self.italicAction = Lib.createAction(
            window, ":/format-text-italic.svg", "&Italic",
            self.toggleItalic, QKeySequence.Italic, """\
<p><b>Format→Italic</b> ({})</p>
<p>Toggle italic on or off.</p>""".format(QKeySequence(
                                          QKeySequence.Italic).toString()))
        self.underlineAction = Lib.createAction(
            window, ":/format-text-underline.svg", "&Underline",
            self.toggleUnderline, QKeySequence.Underline, """\
<p><b>Format→Underline</b> ({})</p>
<p>Toggle underline on or off.</p>""".format(
                QKeySequence(QKeySequence.Underline).toString()))
        self.noSuperSubscriptAction = Lib.createAction(
            window, ":/nosupersubscript.svg",
            "&No Superscript or Subscript", self.noSuperSubscript,
            tooltip="""\
<p><b>Format→No superscript or subscript</b></p>
<p>Clear superscript or subscript and return to normal.</p>""")
        self.superscriptAction = Lib.createAction(
            window, ":/superscript.svg", "Su&perscript",
            self.setSuperscript, tooltip="""<p><b>Format→Superscript</b></p>
<p>Set superscript on.</p>""")
        self.subscriptAction = Lib.createAction(
            window, ":/subscript.svg", "Subs&cript", self.setSubscript,
            tooltip="""<p><b>Format→Subscript</b></p>
<p>Set subscript on.</p>""")
        self.superSubGroup = QActionGroup(self.window)
        self.superSubGroup.setExclusive(True)
        for action in (self.superscriptAction, self.subscriptAction,
                       self.noSuperSubscriptAction):
            self.superSubGroup.addAction(action)
        self.stdFontAction = Lib.createAction(
            window, ":/font-std.svg", "&Standard Font", self.setStdFont,
            tooltip="""<p><b>Format→Standard Font</b></p>
<p>Set the standard font.</p>""")
        self.altFontAction = Lib.createAction(
            window, ":/font-alt.svg", "&Alternate Font", self.setAltFont,
            tooltip="""<p><b>Format→Alternate Font</b></p>
<p>Set the alternate font.</p>""")
        self.monoFontAction = Lib.createAction(
            window, ":/font-mono.svg", "&Monospace Font", self.setMonoFont,
            tooltip="""<p><b>Format→Monospace Font</b></p>
<p>Set the monospace font.</p>""")
        self.fontGroup = QActionGroup(self.window)
        self.fontGroup.setExclusive(True)
        for action in (self.stdFontAction, self.altFontAction,
                       self.monoFontAction):
            self.fontGroup.addAction(action)
        for action in (self.boldAction, self.italicAction,
                       self.underlineAction, self.superscriptAction,
                       self.subscriptAction, self.noSuperSubscriptAction,
                       self.stdFontAction, self.altFontAction,
                       self.monoFontAction):
            action.setCheckable(True)
        self.noSuperSubscriptAction.setChecked(True)
        self.stdFontAction.setChecked(True)


    def forMenu(self):
        return (self.boldAction, self.italicAction,
                self.underlineAction, None, self.noSuperSubscriptAction,
                self.superscriptAction, self.subscriptAction, None,
                self.stdFontAction, self.altFontAction,
                self.monoFontAction)


    def forToolbar(self):
        return (self.boldAction, self.italicAction,
                self.underlineAction, None, self.noSuperSubscriptAction,
                self.superscriptAction, self.subscriptAction, None,
                self.stdFontAction, self.altFontAction,
                self.monoFontAction)


    def updateEnabled(self):
        enable = False
        for editor in self.state.editors:
            if editor.hasFocus():
                enable = hasattr(editor, "toggleBold")
                break
        for action in (self.boldAction, self.italicAction,
                       self.underlineAction,
                       self.noSuperSubscriptAction,
                       self.superscriptAction, self.subscriptAction,
                       self.stdFontAction, self.altFontAction,
                       self.monoFontAction):
            action.setEnabled(enable)
        if self.fontSizeSpinBox is not None:
            self.fontSizeSpinBox.setEnabled(enable)
        return enable


    def update(self, bold, italic, underline, superscript, subscript,
               family, size=None):
        enable = self.updateEnabled()
        if enable:
            self.boldAction.setChecked(bold)
            self.italicAction.setChecked(italic)
            self.underlineAction.setChecked(underline)
            self.superscriptAction.setChecked(superscript)
            self.subscriptAction.setChecked(subscript)
            self.noSuperSubscriptAction.setChecked(
                not superscript and not subscript)
            family = family.casefold()
            if family == self.state.altFontFamily.casefold():
                self.altFontAction.setChecked(True)
            elif family == self.state.monoFontFamily.casefold():
                self.monoFontAction.setChecked(True)
            else:
                self.stdFontAction.setChecked(True)
            if size is not None and self.fontSizeSpinBox is not None:
                self.fontSizeSpinBox.setValue(size)


    def toggleBold(self):
        for editor in self.state.editors:
            if editor.hasFocus():
                if hasattr(editor, "toggleBold"):
                    editor.toggleBold()
                break


    def toggleItalic(self):
        for editor in self.state.editors:
            if editor.hasFocus():
                if hasattr(editor, "toggleItalic"):
                    editor.toggleItalic()
                break


    def toggleUnderline(self):
        for editor in self.state.editors:
            if editor.hasFocus():
                if hasattr(editor, "toggleUnderline"):
                    editor.toggleUnderline()
                break


    def setSuperscript(self):
        for editor in self.state.editors:
            if editor.hasFocus():
                if hasattr(editor, "setSuperscript"):
                    editor.setSuperscript()
                break


    def setSubscript(self):
        for editor in self.state.editors:
            if editor.hasFocus():
                if hasattr(editor, "setSubscript"):
                    editor.setSubscript()
                break


    def noSuperSubscript(self):
        for editor in self.state.editors:
            if editor.hasFocus():
                if hasattr(editor, "noSuperSubscript"):
                    editor.noSuperSubscript()
                break


    def setStdFont(self):
        for editor in self.state.editors:
            if editor.hasFocus():
                if hasattr(editor, "setStdFont"):
                    editor.setStdFont()
                break


    def setAltFont(self):
        for editor in self.state.editors:
            if editor.hasFocus():
                if hasattr(editor, "setAltFont"):
                    editor.setAltFont()
                break


    def setMonoFont(self):
        for editor in self.state.editors:
            if editor.hasFocus():
                if hasattr(editor, "setMonoFont"):
                    editor.setMonoFont()
                break


    def setFontSize(self, size):
        if self.fontSizeSpinBox is None:
            return
        for editor in self.state.editors:
            if editor.hasFocus():
                if hasattr(editor, "setFontSize"):
                    editor.setFontSize(size)
                break
Example #6
0
class PresenceOverviewWidget(HorsePanel):
    @Slot(QModelIndex)
    def cell_entered(self, ndx):
        employee_id = self._employee_id_on_row(ndx)

        if not employee_id:
            self._show_totals_day_off(None)

        elif employee_id:
            chrono.chrono_start()

            employee = None
            for i in self.employees:
                if i.employee_id == employee_id:
                    employee = i
                    break

            self.detail_subframe.set_title(employee.fullname)
            self._show_totals_day_off(employee_id)

            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())))

            chrono.chrono_click("Retrieveing data")
            tars = dao.task_action_report_dao.get_reports_for_employee_id_on_date(
                employee_id, d)
            work_timetracks = dao.timetrack_dao.all_work_for_employee_date_manual(
                employee_id, d)
            presence_timetracks = dao.timetrack_dao.all_presence_for_employee_date_managed_by_code_full(
                employee_id, d)
            # employee = dao.employee_dao.find_by_id(employee_id)
            special_activities = dao.special_activity_dao.find_on_day(
                employee_id, d)

            chrono.chrono_click("Redrawing")
            self.time_report_view.redraw(datetime(d.year, d.month, d.day, 6,
                                                  0),
                                         tars,
                                         employee_id,
                                         work_timetracks,
                                         presence_timetracks,
                                         special_activities,
                                         view_title=_("Work on {}").format(
                                             date_to_dmy(d, full_month=True)))
            session().close(
            )  # FIXME Put his one line above; but that's tough ! SQLA doesn't help us much here !
            chrono.chrono_click("Session closed")

            # for event_type, duration in self.day_event_totals[employee_id].items():
            #     mainlog.debug("{}{}".format(event_type, duration))

        self._toggle_days_off_actions()

    def _employee_id_on_row(self, row_or_ndx):
        r = row_or_ndx
        if type(r) != int:
            r = row_or_ndx.row()

        return self._table_model.data(self._table_model.index(r, 0),
                                      Qt.UserRole)

    DAY_EVENT_PALETTE = {
        DayEventType.holidays: (Qt.GlobalColor.white, Qt.GlobalColor.red),
        DayEventType.day_off: (Qt.GlobalColor.white, Qt.GlobalColor.darkRed),
        DayEventType.unpaid_day_off:
        (Qt.GlobalColor.black, Qt.GlobalColor.magenta),
        DayEventType.free_day:
        (Qt.GlobalColor.white, Qt.GlobalColor.darkMagenta),
        DayEventType.overtime: (Qt.GlobalColor.black, Qt.GlobalColor.green),
        DayEventType.recuperation:
        (Qt.GlobalColor.white, Qt.GlobalColor.darkGreen),
        DayEventType.unemployment: (Qt.GlobalColor.white, Qt.GlobalColor.blue),
        DayEventType.unemployment_short:
        (Qt.GlobalColor.white, Qt.GlobalColor.darkBlue),
        DayEventType.work_accident: (Qt.GlobalColor.black,
                                     Qt.GlobalColor.yellow),
        DayEventType.sick_leave: (Qt.GlobalColor.white,
                                  Qt.GlobalColor.darkYellow)
    }

    MONTH_EVENT_COLUMN = 2
    YEAR_EVENT_COLUMN = 3

    def _make_total_days_off_panel(self):

        widget = QFrame()
        widget.setObjectName('HorseRegularFrame')

        widget.setFrameShape(QFrame.Panel)
        widget.setFrameShadow(QFrame.Sunken)
        layout = QVBoxLayout()

        #layout.addWidget(QLabel(_("Days off to date")))
        self.day_off_total_duration_labels = dict()
        self.day_off_month_duration_labels = dict()
        self.day_off_labels = dict()

        self._day_off_table_model = QStandardItemModel(10, 3)
        self._day_off_table_model.setHorizontalHeaderLabels(
            [None, None, _("This\nmonth"),
             _("Before")])
        self.day_off_table_view = QTableView(None)
        self.day_off_table_view.setModel(self._day_off_table_model)

        # self.day_off_table_view.setHorizontalHeader(self.headers_view)
        self.day_off_table_view.verticalHeader().hide()
        self.day_off_table_view.setAlternatingRowColors(True)
        self.day_off_table_view.setEditTriggers(
            QAbstractItemView.NoEditTriggers)

        self.day_off_table_view.hide()

        row = 0
        for det in DayEventType.symbols():
            ndx = self._day_off_table_model.index(row, 0)
            self._day_off_table_model.setData(ndx, det.description,
                                              Qt.DisplayRole)

            ndx = self._day_off_table_model.index(row, 1)
            fg, bg = self.DAY_EVENT_PALETTE[det]
            self._day_off_table_model.setData(ndx, QBrush(bg),
                                              Qt.BackgroundRole)
            self._day_off_table_model.setData(ndx, QBrush(fg),
                                              Qt.TextColorRole)
            self._day_off_table_model.setData(ndx,
                                              DayEventType.short_code(det),
                                              Qt.DisplayRole)

            row += 1

        layout.addWidget(self.day_off_table_view)

        grid = QGridLayout()
        self.days_off_layout = grid
        grid.setColumnStretch(3, 1)
        row = 0

        grid.addWidget(QLabel(_('Year')), row, self.YEAR_EVENT_COLUMN)
        grid.addWidget(QLabel(_('Month')), row, self.MONTH_EVENT_COLUMN)
        row += 1

        for det in DayEventType.symbols():
            self.day_off_total_duration_labels[det] = QLabel("-")
            self.day_off_month_duration_labels[det] = QLabel("-")
            self.day_off_labels[det] = QLabel(det.description)

            hlayout = QHBoxLayout()

            sl = QLabel()
            fg, bg = self.DAY_EVENT_PALETTE[det]

            def to_html_rgb(color):
                i = color.red() * 256 * 256 + color.green() * 256 + color.blue(
                )
                return "#{:06X}".format(i)

            p = QPalette()
            p.setColor(QPalette.Window, QColor(bg))
            p.setColor(QPalette.WindowText, QColor(fg))
            sl.setPalette(p)
            sl.setAlignment(Qt.AlignCenter)
            sl.setStyleSheet("border: 2px solid black; background: {}".format(
                to_html_rgb(QColor(bg))))

            t = DayEventType.short_code(det)
            mainlog.debug(t)
            sl.setAutoFillBackground(True)
            sl.setText(t)

            grid.addWidget(sl, row, 0)
            grid.addWidget(self.day_off_labels[det], row, 1)
            grid.addWidget(self.day_off_total_duration_labels[det], row,
                           self.YEAR_EVENT_COLUMN)
            grid.addWidget(self.day_off_month_duration_labels[det], row,
                           self.MONTH_EVENT_COLUMN)

            hlayout.addStretch()

            row += 1

        layout.addLayout(grid)
        layout.addStretch()

        self.day_off_table_view.resizeColumnsToContents()
        # self.day_off_table_view.setMinimumWidth( self.day_off_table_view.width())
        # self.day_off_table_view.resize( self.day_off_table_view.minimumWidth(),
        #                                 self.day_off_table_view.minimumHeight(),)

        widget.setLayout(layout)
        return widget

    def _show_totals_day_off(self, employee_id):

        mainlog.debug("_show_totals_day_off : {}".format(employee_id))

        def form_layout_row_set_visible(layout, row_ndx, is_visible):
            for i in range(layout.columnCount()):
                l = layout.itemAtPosition(row_ndx, i)
                if l and l.widget():
                    l.widget().setVisible(is_visible)

        det_to_show = dict()

        row = 0
        for det in DayEventType.symbols():

            yearly = 0
            if employee_id in self.all_events_in_year:
                if det in self.all_events_in_year[employee_id]:
                    yearly = nice_round(
                        self.all_events_in_year[employee_id][det])

            monthly = 0
            if employee_id in self.day_event_totals:
                if det in self.day_event_totals[employee_id]:
                    monthly = nice_round(
                        self.day_event_totals[employee_id][det])

                # ndx = self._day_off_table_model.index(row,self.YEAR_EVENT_COLUMN)
                # self._day_off_table_model.setData(ndx, v, Qt.DisplayRole)

            if yearly or monthly:
                det_to_show[det] = {'monthly': monthly, 'yearly': yearly}

        if det_to_show:
            # If there are some days spent on some counters, then we display
            # those counters *only*
            mainlog.debug("_show_totals_day_off : showing some events ".format(
                str(det_to_show)))
            row = 0
            for det in DayEventType.symbols():
                if det in det_to_show:
                    monthly = det_to_show[det]['monthly']
                    yearly = det_to_show[det]['yearly']
                    form_layout_row_set_visible(self.days_off_layout, row + 1,
                                                True)
                    self.day_off_total_duration_labels[det].setText(yearly
                                                                    or '-')
                    self.day_off_month_duration_labels[det].setText(monthly
                                                                    or '-')
                else:
                    form_layout_row_set_visible(self.days_off_layout, row + 1,
                                                False)
        else:
            # If there are no days spent on any counter, then we display
            # all counters at the 0 mark.
            mainlog.debug("_show_totals_day_off : showing no event")
            row = 0
            for det in DayEventType.symbols():
                form_layout_row_set_visible(self.days_off_layout, row + 1,
                                            True)
                row += 1

        # self.day_off_table_view.resizeColumnsToContents()

        self.days_off_panel.parent().update()

    @Slot()
    def refresh_action(self):
        global dao

        # mainlog.debug("refresh action started")
        self.hours_per_pers_subframe.set_title(date_to_my(
            self.base_date, True))

        chrono.chrono_start()
        all_events_in_month = people_admin_service.events_for_month(
            self.base_date)

        employee_with_events = [
            event.employee_id for event in all_events_in_month
        ]

        # mainlog.debug(all_events_in_month)

        self.all_events_in_year = people_admin_service.events_for_year(
            self.base_date.year)
        self.all_presences = all_presences = dao.employee_dao.presence_overview_for_month(
            self.base_date)

        all_correction_times = dict()
        for s in dao.month_time_synthesis_dao.load_all_synthesis(
                self.base_date.year, self.base_date.month):
            all_correction_times[s.employee_id] = s.correction_time

        special_activities = dao.special_activity_dao.find_on_month(
            self.base_date)

        employees = list(
            filter(
                lambda e: e.is_active or e.employee_id in all_presences or e.
                employee_id in all_correction_times or e.employee_id in
                special_activities or e.employee_id in employee_with_events,
                dao.employee_dao.list_overview()))
        self.employees = employees

        chrono.chrono_click()

        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(employees))
        self._table_model.setColumnCount(1 + day_max + 3)

        headers = QStandardItemModel(1, 1 + day_max + 3)

        headers.setHeaderData(0, Qt.Orientation.Horizontal, _("Employee"))
        for i in range(day_max):
            headers.setHeaderData(i + 1, Qt.Orientation.Horizontal,
                                  "{}".format(i + 1))
        headers.setHeaderData(day_max + 1, Qt.Orientation.Horizontal,
                              _("Correction"))
        headers.setHeaderData(day_max + 2, Qt.Orientation.Horizontal,
                              _("Total"))
        headers.setHeaderData(day_max + 3, Qt.Orientation.Horizontal,
                              _("Days off"))

        self.headers_view.setModel(
            headers)  # qt's doc : The view does *not* take ownership
        self.header_model = headers
        self.headers_view.setModel(
            self.header_model)  # qt's doc : The view does *not* take ownership

        # 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()

        # mainlog.debug("Running on employees")
        for row in range(self._table_model.rowCount()):

            # Clear the line
            for col in range(0, 32):
                ndx = self._table_model.index(row, col)
                self._table_model.setData(ndx, None, Qt.BackgroundRole)
                self._table_model.setData(ndx, QBrush(Qt.GlobalColor.black),
                                          Qt.TextColorRole)
                self._table_model.setData(ndx, None, Qt.DisplayRole)
                self._table_model.setData(ndx, None, Qt.UserRole)
                self._table_model.setData(ndx, None, Qt.UserRole + 1)
                #     else:
                #         self._table_model.setData(ndx,None,Qt.BackgroundRole)

                # else:
                #     self._table_model.setData(ndx,None,Qt.DisplayRole)
                #     self._table_model.setData(ndx,None,Qt.BackgroundRole)

            # 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)

        row = 0
        for employee in employees:  # employees are sorted

            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.employee_id,
                                      Qt.UserRole)  # FIXME Use a delegate

            correction = 0
            if employee.employee_id in all_correction_times:
                correction = all_correction_times[employee.employee_id]
                self._table_model.setData(
                    self._table_model.index(row, day_max + 1),
                    duration_to_hm(correction, short_unit=True),
                    Qt.DisplayRole)
            else:
                self._table_model.setData(
                    self._table_model.index(row, day_max + 1), None,
                    Qt.DisplayRole)

            presence = 0
            if employee.employee_id in all_presences and len(
                    all_presences[employee.employee_id]) > 0:
                import functools
                presence = functools.reduce(
                    lambda acc, s: acc + s,
                    all_presences[employee.employee_id], 0)
            presence += correction

            if presence != 0:
                self._table_model.setData(ndx, QBrush(Qt.GlobalColor.black),
                                          Qt.TextColorRole)
                self._table_model.setData(
                    self._table_model.index(row, day_max + 2),
                    duration_to_hm(presence, short_unit=True), Qt.DisplayRole)
            else:
                self._table_model.setData(
                    self._table_model.index(row, day_max + 2), None,
                    Qt.DisplayRole)

            if employee.employee_id in all_presences and len(
                    all_presences[employee.employee_id]) > 0:
                for b in range(len(all_presences[employee.employee_id])):
                    ndx = self._table_model.index(row, b + 1)

                    p = all_presences[employee.employee_id][b]

                    if p > 0:
                        self._table_model.setData(
                            ndx, duration_to_hm(p, short_unit=True),
                            Qt.DisplayRole)
                        self._table_model.setData(ndx, p, Qt.UserRole)

                        if p >= 4 and p <= 8:
                            # Regular work load
                            self._table_model.setData(
                                ndx, QBrush(QColor(192, 255, 192)),
                                Qt.BackgroundRole)
                        elif p > 8 or (p < 4 and p > 0):
                            # Problematic work load
                            self._table_model.setData(
                                ndx, QBrush(QColor(255, 192, 192)),
                                Qt.BackgroundRole)

            if employee.employee_id in special_activities:
                sa_of_employee = special_activities[employee.employee_id]

                for sa in sa_of_employee:
                    start = max(t_start, sa.start_time)
                    end = min(t_end, sa.end_time)

                    for i in range(start.day, end.day + 1):
                        ndx = self._table_model.index(row, i)
                        self._table_model.setData(ndx,
                                                  QBrush(QColor(255, 128, 0)),
                                                  Qt.BackgroundRole)

                # self._table_model.setData(self._table_model.index(row,b+1),Qt.AlignRight | Qt.AlignVCenter,Qt.TextAlignmentRole)
            row += 1

        # Display day events

        employee_id_to_row = dict()  # little accelerator
        for row in range(len(employees)):
            employee_id_to_row[employees[row].employee_id] = row

        # Compute days off totals and show them

        self.day_event_totals = dict([(e.employee_id, dict())
                                      for e in employees])
        for day_event in all_events_in_month:
            # mainlog.debug("employee_id = {}".format(day_event.employee_id))
            # if day_event.employee_id not in self.day_event_totals:
            #    mainlog.debug(self.day_event_totals)

            t = self.day_event_totals[day_event.employee_id]
            if day_event.event_type not in t:
                t[day_event.event_type] = day_event.duration
            else:
                t[day_event.event_type] += day_event.duration

        for employee in employees:  # employees are sorted
            t = self.day_event_totals[employee.employee_id]
            mainlog.debug(t)
            total_off = sum(t.values())
            mainlog.debug(total_off)
            row = employee_id_to_row[employee.employee_id]
            mainlog.debug(row)
            if total_off:
                self._table_model.setData(
                    self._table_model.index(row, day_max + 3),
                    nice_round(total_off), Qt.DisplayRole)
            else:
                self._table_model.setData(
                    self._table_model.index(row, day_max + 3), None,
                    Qt.DisplayRole)

        # Show days off

        for day_event in all_events_in_month:
            row = employee_id_to_row[day_event.employee_id]
            col = day_event.date.day

            fg = bg = None
            if day_event.event_type in self.DAY_EVENT_PALETTE:
                fg, bg = self.DAY_EVENT_PALETTE[day_event.event_type]
            else:
                fg, bg = Qt.GlobalColor.red, Qt.GlobalColor.gray

            ndx = self._table_model.index(row, col)

            self._table_model.setData(ndx, day_event.day_event_id,
                                      Qt.UserRole + 1)

            # The problem here is to nicely blend the fact
            # that you can have a day event mixed with actual work
            # the very same day. Here's a poor man solution.

            active_time = self._table_model.data(ndx, Qt.UserRole)
            if not active_time:
                self._table_model.setData(
                    ndx, DayEventType.short_code(day_event.event_type),
                    Qt.DisplayRole)

                self._table_model.setData(ndx, QBrush(fg), Qt.TextColorRole)
                self._table_model.setData(ndx, QBrush(bg), Qt.BackgroundRole)
            else:
                self._table_model.setData(ndx, QBrush(fg), Qt.TextColorRole)
                self._table_model.setData(ndx, QBrush(bg), Qt.BackgroundRole)

                self._table_model.setData(
                    ndx,
                    duration_to_hm(active_time, short_unit=True) +
                    DayEventType.short_code(day_event.event_type),
                    Qt.DisplayRole)

        chrono.chrono_click()

        #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 edit_tars(self):

        employee_id = self._employee_id_on_row(self.table_view.currentIndex())

        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())))

        dialog = TimeReportingScannerDialog(self)
        dialog.set_data(datetime(d.year, d.month, d.day, 6, 0), employee_id)
        dialog.exec_()

        if dialog.result() == QDialog.Accepted:
            # pub.sendMessage('time_report.changed')
            self.timetrack_changed.emit()
            self.refresh_action()

    @Slot()
    def show_actions(self):
        button = self.action_menu.parent()
        p = button.mapToGlobal(QPoint(0, button.height()))
        self.action_menu.exec_(p)

    @Slot()
    def delete_holidays(self):
        ndx = self.table_view.currentIndex()
        employee_id = self._employee_id_on_row(ndx)
        d = date(self.base_date.year, self.base_date.month, ndx.column())

        if dao.special_activity_dao.delete_by_employee_and_date(
                employee_id, d):
            self.refresh_panel()

    @Slot()
    def create_holidays(self):
        employee_id = self._employee_id_on_row(self.table_view.currentIndex())

        left_col = 1000
        right_col = 0
        for ndx in self.table_view.selectionModel().selectedIndexes():
            c = ndx.column()
            left_col = min(c, left_col)
            right_col = max(c, right_col)

        d_start = date(
            self.base_date.year, self.base_date.month,
            min(
                calendar.monthrange(self.base_date.year,
                                    self.base_date.month)[1], max(1,
                                                                  left_col)))

        d_end = date(
            self.base_date.year, self.base_date.month,
            min(
                calendar.monthrange(self.base_date.year,
                                    self.base_date.month)[1],
                max(1, right_col)))

        dialog = HolidaysDialog(self)

        sa = SpecialActivity()
        sa.employee_id = employee_id
        sa.reporter_id = user_session.user_id
        sa.encoding_date = date.today()
        sa.start_time = datetime(d_start.year, d_start.month, d_start.day, 6,
                                 0)
        sa.end_time = datetime(d_end.year, d_end.month, d_end.day, 14, 0)

        dialog.setup(sa, dao.employee_dao.find_by_id(employee_id).fullname)

        # dialog.set_data(employee,self.base_date,c)
        dialog.exec_()
        if dialog.result() == QDialog.Accepted:
            dao.special_activity_dao.save(sa)
            self.refresh_action()

    @Slot()
    def edit_month_correction(self):
        employee_id = self._employee_id_on_row(self.table_view.currentIndex())

        if employee_id:
            employee = dao.employee_dao.find_by_id(employee_id)
            c = dao.month_time_synthesis_dao.load_correction_time(
                employee_id, self.base_date.year, self.base_date.month)

            dialog = MonthTimeCorrectionDialog(self)
            dialog.set_data(employee.fullname, self.base_date, c)
            dialog.exec_()
            if dialog.result() == QDialog.Accepted:
                c = dao.month_time_synthesis_dao.save(employee_id,
                                                      self.base_date.year,
                                                      self.base_date.month,
                                                      dialog.correction_time)
                self.refresh_action()

    @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, 1)
        else:
            self.base_date = date(self.base_date.year - 1, 12, 1)
        self.refresh_action()

    @Slot()
    def month_after(self):
        m = self.base_date.month

        if self.base_date.year < date.today().year + 1 \
                or m < date.today().month:
            if m < 12:
                self.base_date = date(self.base_date.year, m + 1, 1)
            else:
                self.base_date = date(self.base_date.year + 1, 1, 1)
            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."))

    timetrack_changed = Signal()

    @Slot(QModelIndex)
    def edit_timetrack(self, ndx):
        global dao
        global user_session

        if ndx.column() >= 1:
            edit_date = date(
                self.base_date.year, self.base_date.month,
                ndx.column())  # +1 already in because of employee's names
            employee_id = self._employee_id_on_row(ndx)

            tars = dao.task_action_report_dao.get_reports_for_employee_id_on_date(
                employee_id, edit_date)

            if len(tars) == 0:

                d = EditTimeTracksDialog(self, dao, edit_date)
                d.set_employee_and_date(employee_id, edit_date)
                d.exec_()
                if d.result() == QDialog.Accepted:
                    self.refresh_action()
                    self.timetrack_changed.emit()
                d.deleteLater()

            else:
                edit_date = datetime(self.base_date.year,
                                     self.base_date.month,
                                     ndx.column(),
                                     hour=6)
                from koi.TimeReportingScanner import TimeReportingScannerDialog
                d = TimeReportingScannerDialog(self)
                d.set_data(edit_date, employee_id)  # or 16
                d.exec_()
                if d.result() == QDialog.Accepted:
                    self.refresh_action()
                    self.timetrack_changed.emit()
                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 _make_table_header(self):
        pass

    def __init__(self, parent, find_order_action_slot):
        super(PresenceOverviewWidget, self).__init__(parent)

        self.set_panel_title(_("Presence overview"))
        self.base_date = date.today()

        headers = QStandardItemModel(1, 31 + 3)
        self._table_model = QStandardItemModel(1, 31 + 3, 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 = TableViewSignaledEvents(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.setEditTriggers(QAbstractItemView.NoEditTriggers)

        self.table_view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.table_view.customContextMenuRequested.connect(
            self.popup_context_menu)

        self.copy_action = QAction(_("Copy order parts"), self.table_view)
        self.copy_action.triggered.connect(self.copy_slot)
        self.copy_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_C))
        self.copy_action.setShortcutContext(Qt.WidgetWithChildrenShortcut)
        self.table_view.addAction(self.copy_action)

        self.select_all_action = QAction(_("Select all"), self.table_view)
        self.select_all_action.triggered.connect(self.select_all_slot)
        self.select_all_action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_A))
        self.select_all_action.setShortcutContext(
            Qt.WidgetWithChildrenShortcut)
        self.table_view.addAction(self.select_all_action)

        # self.table_view.setSelectionBehavior(QAbstractItemView.SelectItems)
        # self.table_view.setSelectionMode(QAbstractItemView.SingleSelection)

        navbar = NavBar(self, [(_("Month before"), self.month_before),
                               (_("Today"), self.month_today),
                               (_("Action"), self.show_actions),
                               (_("Month after"), self.month_after),
                               (_("Find"), find_order_action_slot)])

        self.action_menu = QMenu(navbar.buttons[2])
        navbar.buttons[2].setObjectName("specialMenuButton")
        navbar.buttons[4].setObjectName("specialMenuButton")

        self._make_days_off_menu_and_action_group()

        list_actions = [  # (_("Edit"),self.edit_tars, None, None),
            (_("Edit"), self.edit_timetrack_no_ndx, None, None),
            (_("Month correction"), self.edit_month_correction, None,
             [RoleType.modify_monthly_time_track_correction]),
            (self.days_off_menu, None), (self.copy_action, None),
            (self.select_all_action, None)
        ]

        # (_("Insert holidays"),self.create_holidays, None, None),
        # (_("Delete holidays"),self.delete_holidays, None, None) ]

        populate_menu(self.action_menu, self, list_actions)

        # mainlog.debug("tile widget")
        self.title_box = TitleWidget(_("Presence Overview"), self, navbar)
        self.vlayout = QVBoxLayout(self)
        self.vlayout.setObjectName("Vlayout")
        self.vlayout.addWidget(self.title_box)

        self.hours_per_pers_subframe = SubFrame(_("Overview"), self.table_view,
                                                self)
        self.vlayout.addWidget(self.hours_per_pers_subframe)

        self.time_report_view = TimeReportView(self)

        self.days_off_panel = self._make_total_days_off_panel()
        vbox = QVBoxLayout()
        vbox.addWidget(self.days_off_panel)
        vbox.addStretch()
        vbox.setStretch(0, 0)
        vbox.setStretch(1, 1)

        hlayout = QHBoxLayout()
        hlayout.addWidget(self.time_report_view)
        hlayout.addLayout(vbox)
        hlayout.setStretch(0, 1)
        self.detail_subframe = SubFrame(_("Day"), hlayout, self)

        self.vlayout.addWidget(self.detail_subframe)

        self.setLayout(self.vlayout)

        # dbox = QVBoxLayout()
        # dbox.addWidget(QLabel("kjkljkj"))

        # self.total_active_hours = LabeledValue(_("Total activity"))
        # dbox.addWidget(self.total_active_hours)

        # hbox = QHBoxLayout()
        # hbox.addWidget(self.table_view)
        # hbox.addLayout(dbox)

        # self.selection_model = self.table_view.selectionModel()
        # mainlog.debug(m)
        #sm = QItemSelectionModel(self.table_view.model())
        #sm.setModel(self.table_view.model())
        # self.table_view.setSelectionModel(self.selection_model)

        self.table_view.selectionModel().currentChanged.connect(
            self.cell_entered)

        self.table_view.doubleClickedCell.connect(self.edit_timetrack)

    def _selection_to_period(self):
        left_col = 1000
        right_col = 0
        for ndx in self.table_view.selectionModel().selectedIndexes():
            c = ndx.column()
            left_col = min(c, left_col)
            right_col = max(c, right_col)

        d_start = date(
            self.base_date.year, self.base_date.month,
            min(
                calendar.monthrange(self.base_date.year,
                                    self.base_date.month)[1], max(1,
                                                                  left_col)))

        d_end = date(
            self.base_date.year, self.base_date.month,
            min(
                calendar.monthrange(self.base_date.year,
                                    self.base_date.month)[1],
                max(1, right_col)))

        return d_start, d_end

    def _toggle_days_off_actions(self):
        day_max = calendar.monthrange(self.base_date.year,
                                      self.base_date.month)[1]

        ndx = self.table_view.currentIndex()

        can_add = can_remove = False

        if ndx.column() >= 1 and ndx.column() <= day_max:

            day_event_id = ndx.data(Qt.UserRole + 1)

            can_add = True

            # if not day_event_id:
            #     day = ndx.column() - 1
            #
            #     employee_id = self._employee_id_on_row(ndx)
            #     if employee_id in self.all_presences:
            #         if not self.all_presences[employee_id][day]:
            #             can_add = True
            #         else:
            #             can_add = True
            #     else:
            #         can_add = True

            can_remove = day_event_id is not None

        self.days_off_add_submenu.setEnabled(can_add)
        for actions in self.days_off_action_group.actions():
            actions.setEnabled(can_add)

        self.day_off_remove_action.setEnabled(can_remove)

    def _add_day_off(self, action):

        if action.data() != 'Remove':

            day_event_type, day_event_duration = action.data()
            day_event_type = DayEventType.from_str(day_event_type)

            mainlog.debug("selected action {} {}".format(
                day_event_type, day_event_duration))

            ndx = self.table_view.currentIndex()
            day_event_id = ndx.data(Qt.UserRole + 1)

            # if day_event_id:
            #     showWarningBox(_("There's already a day off here"))
            #     return

            employee_id = self._employee_id_on_row(ndx)
            if employee_id in self.all_presences:
                day = ndx.column() - 1
                mainlog.debug("_add_day_off : employee_id={}, day={}".format(
                    employee_id, day))
                mainlog.debug(self.all_presences[employee_id])
                mainlog.debug(type(self.all_presences[employee_id]))

                # if self.all_presences[employee_id][day]:
                #     showWarningBox(_("One can't add day off where there is activity"))
                #     return
            else:
                mainlog.debug(
                    "_add_day_off : employee_id={} not yet known".format(
                        employee_id))

            day_event = DayEvent()
            day_event.employee_id = employee_id
            day_event.event_type = day_event_type

            day, last_day = self._selection_to_period()

            if day_event_duration in (0.5, 1):
                days_durations = [(day, day_event_duration)]
            else:
                days_durations = []
                day, last_day = self._selection_to_period()
                while day <= last_day:
                    days_durations.append(
                        (day, 1))  # One full work day on the day
                    day += timedelta(1)

            # mainlog.debug(days_durations)
            mainlog.debug("Creating day event of type {}".format(
                day_event.event_type))

            try:
                people_admin_service.set_event_on_days(day_event,
                                                       days_durations)
            except ServerException as ex:
                showErrorBox(ex.translated_message)

            self.refresh_action()

    def _remove_day_off(self):
        # Grab all the selected events

        event_ids = []
        for ndx in self.table_view.selectionModel().selectedIndexes():
            day_event_id = ndx.data(Qt.UserRole + 1)
            if day_event_id:
                mainlog.debug("Removing event: {}".format(day_event_id))
                event_ids.append(day_event_id)

        # Remove them

        if event_ids:
            people_admin_service.remove_events(event_ids)
            self.refresh_action()

    def _make_days_off_menu_and_action_group(self):
        # We use a action group to be able to use the data() of actions
        # when action is tigerred

        # Call this ONLY ONCE because there are signal/slot connections.

        self.days_off_menu = QMenu(_("Day off"))
        self.days_off_add_submenu = QMenu(_("Set day off"))
        self.days_off_action_group = QActionGroup(self)

        for det in DayEventType.symbols():
            a_one = QAction(_("Set one day"), self.days_off_action_group)
            a_one.setData((det.value, 1))

            a_half = QAction(_("Set half day"), self.days_off_action_group)
            a_half.setData((det.value, 0.5))

            a_period = QAction(_("Set period"), self.days_off_action_group)
            a_period.setData((det.value, 2))

            self.days_off_action_group.addAction(a_one)
            self.days_off_action_group.addAction(a_half)
            self.days_off_action_group.addAction(a_period)

            m = QMenu(_("Set time off for {}").format(det.description))
            m.addAction(a_one)
            m.addAction(a_half)
            m.addAction(a_period)
            self.days_off_add_submenu.addMenu(m)

        self.days_off_action_group.triggered.connect(self._add_day_off)

        self.day_off_remove_action = QAction(_("Remove day off"), self)
        self.day_off_remove_action.triggered.connect(self._remove_day_off)

        # Now we have the actions, we build the menu

        self.days_off_menu.addMenu(self.days_off_add_submenu)
        self.days_off_menu.addAction(self.day_off_remove_action)

    @Slot(QPoint)
    def popup_context_menu(self, position):
        self.days_off_menu.exec_(QCursor.pos())

    @Slot()
    def select_all_slot(self):
        m = self.table_view.model()
        all = QItemSelection(m.index(0, 0),
                             m.index(m.rowCount() - 1,
                                     m.columnCount() - 1))
        self.table_view.selectionModel().select(all,
                                                QItemSelectionModel.Select)

    @Slot()
    def copy_slot(self):

        # Collect the rows indices

        indices = self.table_view.selectedIndexes()

        if not indices:
            return

        min_row = max_row = indices[0].row()
        min_col = max_col = indices[0].column()

        def min_max(minimum, v, maximum):
            if v < minimum:
                return v, maximum
            elif v > maximum:
                return minimum, v
            else:
                return minimum, maximum

        for ndx in self.table_view.selectedIndexes():
            min_row, max_row = min_max(min_row, ndx.row(), max_row)
            min_col, max_col = min_max(min_col, ndx.column(), max_col)

        mainlog.debug("Copy from {},{} to {},{}".format(
            min_row, min_col, max_row, max_col))

        day_max = calendar.monthrange(self.base_date.year,
                                      self.base_date.month)[1]

        s = ""
        for r in range(min_row, max_row + 1):
            d = []
            for c in range(min_col, max_col + 1):
                ndx = self._table_model.item(r, c)

                if c == 0 or c > day_max:
                    d.append(ndx.data(Qt.DisplayRole) or "")
                else:
                    t = ndx.data(Qt.UserRole + 1)  # Day off
                    if t:
                        t = ndx.data(Qt.DisplayRole)
                    else:
                        hours = ndx.data(Qt.UserRole)  # Activity hours
                        if hours is not None:
                            t = str(hours).replace('.', ',')
                        else:
                            t = ""

                    d.append(t)

            s += "\t".join(d) + u"\n"

        QApplication.clipboard().setText(s)
Example #7
0
class SimpleEditor(QMainWindow):
    """
    A simple editor window that can open/save files.

    The ui has been designed in Qt Designer and use the promoted widgets system
    to instantiate a GenericEditor. (self.ui.genericEditor)
    """

    def __init__(self):
        QMainWindow.__init__(self)
        # setup ui (the pcef GenericEditor is created there using
        # the promoted widgets system)
        self.ui = simple_editor_ui.Ui_MainWindow()
        self.ui.setupUi(self)
        self.setWindowTitle("PCEF - Generic Example")
        editor = self.ui.genericEditor

        # open this file
        try:
            openFileInEditor(self.ui.genericEditor, __file__)
        except:
            pass

        # install Panel where user can add its own markers
        p = UserMarkersPanel()
        editor.installPanel(p, editor.PANEL_ZONE_LEFT)

        # add a fold indicator around our class and the main
        editor.foldPanel.addIndicator(136, 141)

        # add styles actions
        allStyles = styles.getAllStyles()
        allStyles.sort()
        self.styleActionGroup = QActionGroup(self)
        for style in allStyles:
            action = QAction(unicode(style), self.ui.menuStyle)
            action.setCheckable(True)
            action.setChecked(style == "Default")
            self.styleActionGroup.addAction(action)
            self.ui.menuStyle.addAction(action)
        self.styleActionGroup.triggered.connect(
            self.on_styleActionGroup_triggered)

        # add panels actions
        allPanels = self.ui.genericEditor.panels()
        allPanels.sort()
        self.panels_actions = []
        for panel in allPanels:
            action = QAction(unicode(panel), self.ui.menuPanels)
            action.setCheckable(True)
            action.setChecked(panel.enabled)
            self.ui.menuPanels.addAction(action)
            self.panels_actions.append(action)
            action.triggered.connect(self.onPanelActionTriggered)

        # add panels actions
        allModes = self.ui.genericEditor.modes()
        allModes.sort()
        self.modes_actions = []
        for mode in allModes:
            action = QAction(unicode(mode), self.ui.menuModes)
            action.setCheckable(True)
            action.setChecked(mode.enabled)
            self.ui.menuModes.addAction(action)
            self.modes_actions.append(action)
            action.triggered.connect(self.onModeActionTriggered)

    def onModeActionTriggered(self):
        """ Enables/Disables a mode """
        modes = self.ui.genericEditor.modes()
        modes.sort()
        for mode, action in zip(modes, self.modes_actions):
            mode.enabled = action.isChecked()

    def onPanelActionTriggered(self):
        """ Enables/Disables a Panel """
        panels = self.ui.genericEditor.panels()
        panels.sort()
        for panel, action in zip(panels, self.panels_actions):
            panel.enabled = action.isChecked()

    def on_styleActionGroup_triggered(self, action):
        """ Change current editor style """
        self.ui.genericEditor.currentStyle = styles.getStyle(action.text())
        stylesheet = ""
        if action.text() == "Dark":
            try:
                import qdarkstyle
                stylesheet = qdarkstyle.load_stylesheet()
            except ImportError:
                print "Failed to use the qdarkstyle. Please execute <pip install qdarkstyle> to fully use this theme."
        QApplication.instance().setStyleSheet(stylesheet)

    @Slot()
    def on_actionSave_triggered(self):
        """ Save the current file """
        saveFileFromEditor(self.ui.genericEditor)

    @Slot()
    def on_actionSave_as_triggered(self):
        """ Save the current file as"""
        filename = QFileDialog.getSaveFileName(self)[0]
        if filename != "":
            saveFileFromEditor(self.ui.genericEditor, filename)

    @Slot()
    def on_actionOpen_triggered(self):
        """ Open a new file in the editor """
        filename = QFileDialog.getOpenFileName(self)[0]
        if filename != "":
            openFileInEditor(self.ui.genericEditor, filename)
Example #8
0
class LogFilter(QFrame):
    def __init__(self, parent=None):
        super(LogFilter, self).__init__(parent=parent)
        setup_ui(self)
        self.filter_model = FilterModel(parent=self)
        self._viewer = None
        self.revs_menu = QMenu(parent=self)
        self.revs_separator = None
        self.rev_actions = QActionGroup(self)
        self.rev_actions.addAction(self.action_all_refs)
        self.select_revs_button.setMenu(self.revs_menu)
        self.action_all_refs.revs = None
        self.action_all_refs.triggered.connect(self.show_all_refs)
        self.action_select_branches.triggered.connect(self.pick_branches)
        self.filter_text.textEdited.connect(self.filter_text_edited)

    @property
    def source_model(self):
        return self.filter_model.sourceModel()

    @source_model.setter
    def source_model(self, model):
        self.filter_model.setSourceModel(model)
        self.revs_menu.clear()
        for action in self.rev_actions.actions():
            if action is not self.action_all_refs:
                self.rev_actions.removeAction(action)
        self.revs_menu.addAction(self.action_all_refs)
        if not model.repo.head_ref:
            self.revs_menu.addAction(self.create_rev_action(model.repo, 'HEAD'))
        for branch in model.repo.branches:
            self.revs_menu.addAction(self.create_rev_action(model.repo, branch))
        if model.all:
            self._select_action(self.action_all_refs)
        else:
            selected_revs = model.revs
            if not selected_revs:
                if model.repo.head_ref:
                    selected_revs = (model.repo.head_ref,)
                else:
                    selected_revs = ('HEAD',)
            action = self._find_rev_action(selected_revs)
            if not action:
                action = self.create_rev_action(model.repo, model.revs)
                self.revs_menu.addAction(action)
            self._select_action(action)
        self.revs_separator = self.revs_menu.addSeparator()
        self.revs_menu.addAction(self.action_select_branches)

    @property
    def viewer(self):
        return self._viewer

    @viewer.setter
    def viewer(self, new_viewer):
        self._viewer = new_viewer
        self._viewer.setModel(self.filter_model)

    def create_rev_action(self, repo, *revs):
        action = QAction(self.revs_menu)
        action.revs = revs
        action.setText(', '.join(str(rev) for rev in revs))
        action.setCheckable(True)
        action.setActionGroup(self.rev_actions)
        action.triggered.connect(self._revs_action_triggered)
        return action

    def show_all_refs(self):
        self._select_action(self.action_all_refs)
        with busy_cursor():
            self.source_model.revs = ()
            self.source_model.all = True
            self.source_model.refresh()

    def pick_branches(self):
        dialog = PickBranchesDialog(repo=self.source_model.repo, parent=self)
        if dialog.exec_() == dialog.Accepted:
            self.show_revs(*dialog.selected_branches)

    def _select_action(self, action):
        action.setChecked(True)
        self.select_revs_button.setText(action.text())

    def _revs_action_triggered(self):
        self._select_action(self.sender())
        with busy_cursor():
            self.source_model.revs = self.sender().revs
            self.source_model.all = False
            self.source_model.refresh()

    def _find_rev_action(self, revs):
        return next((action for action in self.rev_actions.actions()
            if action.revs == revs), None)

    def show_revs(self, *revs):
        action = self._find_rev_action(revs)
        if not action:
            action = self.create_rev_action(self.source_model.repo, *revs)
            self.revs_menu.insertAction(self.revs_separator, action)
        self._select_action(action)
        with busy_cursor():
            self.source_model.revs = revs
            self.source_model.all = False
            self.source_model.refresh()

    def filter_text_edited(self, text):
        if text:
            self.viewer.hideColumn(0)
            self.filter_model.filters += self.filter_graph_row
        else:
            self.filter_model.filters -= self.filter_graph_row
            self.viewer.showColumn(0)

    def filter_graph_row(self, graph_row):
        return commit_matches_text(graph_row.log_entry, self.filter_text.text())
Example #9
0
class GenericPythonEditor(QMainWindow):
    """
    A simple editor window that can open/save files.

    The ui has been designed in Qt Designer and use the promoted widgets system
    to instantiate a GenericEditor. (self.ui.genericEditor)
    """

    def __init__(self):
        QMainWindow.__init__(self)
        # setup ui (the pcef PythonEditor is created in the Ui_MainWindow using
        # the promoted widgets system)
        self.ui = simple_python_editor_ui.Ui_MainWindow()
        self.ui.setupUi(self)
        self.setWindowTitle("PCEF - Python Editor Example")
        self.acceptDrops()

        # open this file
        try:
            openFileInEditor(self.ui.genericEditor, __file__)
        except:
            pass

        # add styles actions
        allStyles = styles.getAllStyles()
        allStyles.sort()
        self.styleActionGroup = QActionGroup(self)
        for style in allStyles:
            action = QAction(unicode(style), self.ui.menuStyle)
            action.setCheckable(True)
            action.setChecked(style == "Default")
            self.styleActionGroup.addAction(action)
            self.ui.menuStyle.addAction(action)
        self.styleActionGroup.triggered.connect(
            self.on_styleActionGroup_triggered)

        # add panels actions
        allPanels = self.ui.genericEditor.panels()
        allPanels.sort()
        self.panels_actions = []
        for panel in allPanels:
            action = QAction(unicode(panel), self.ui.menuPanels)
            action.setCheckable(True)
            action.setChecked(panel.enabled)
            self.ui.menuPanels.addAction(action)
            self.panels_actions.append(action)
            action.triggered.connect(self.onPanelActionTriggered)

        # add panels actions
        allModes = self.ui.genericEditor.modes()
        allModes.sort()
        self.modes_actions = []
        for mode in allModes:
            action = QAction(unicode(mode), self.ui.menuModes)
            action.setCheckable(True)
            action.setChecked(mode.enabled)
            self.ui.menuModes.addAction(action)
            self.modes_actions.append(action)
            action.triggered.connect(self.onModeActionTriggered)

    def onModeActionTriggered(self):
        """ Enables/Disables a mode """
        modes = self.ui.genericEditor.modes()
        modes.sort()
        for mode, action in zip(modes, self.modes_actions):
            mode.enabled = action.isChecked()

    def onPanelActionTriggered(self):
        """ Enables/Disables a Panel """
        panels = self.ui.genericEditor.panels()
        panels.sort()
        for panel, action in zip(panels, self.panels_actions):
            panel.enabled = action.isChecked()

    def on_styleActionGroup_triggered(self, action):
        """ Change current editor style """
        self.ui.genericEditor.currentStyle = styles.getStyle(action.text())
        print "change style"
        stylesheet = ""
        if action.text() == "Dark":
            try:
                import qdarkstyle
                stylesheet = qdarkstyle.load_stylesheet()
            except ImportError:
                print("Failed to use the qdarkstyle. "
                      "Please execute <pip install qdarkstyle> to fully use "
                      "this theme.")
        QApplication.instance().setStyleSheet(stylesheet)

    @Slot()
    def on_actionSave_triggered(self):
        """ Save the current file """
        saveFileFromEditor(self.ui.genericEditor)

    @Slot()
    def on_actionSave_as_triggered(self):
        """ Save the current file as"""
        filename = QFileDialog.getSaveFileName(self)[0]
        if filename != "":
            saveFileFromEditor(self.ui.genericEditor, filename)

    @Slot()
    def on_actionOpen_triggered(self):
        """ Open a new file in the editor """
        filename = QFileDialog.getOpenFileName(
            self, "Choose a python script", "", "Python script (*.py)")[0]
        if filename != "":
            openFileInEditor(self.ui.genericEditor, filename)