コード例 #1
0
ファイル: time_log_dialog.py プロジェクト: MehmetErer/anima
    def effort_time_changed(self, q_time):
        """runs when the effort has been changed
        """
        if self.updating_timings:
            return

        self.updating_timings = True

        # q_time should be a multiple of the TIMING_RESOLUTION
        q_time = self.round_to_timing_resolution(q_time)
        self.effort_time_edit.setTime(q_time)

        # q_time can not be smaller thane TIMING_RESOLUTION
        from anima import TIMING_RESOLUTION

        start_of_today = QtCore.QTime(0, 0)
        secs_since_start_of_day = start_of_today.secsTo(q_time)

        if secs_since_start_of_day < TIMING_RESOLUTION * 60:
            # clip to TIMING_RESOLUTION
            q_time = QtCore.QTime(0, 0)
            q_time = q_time.addSecs(TIMING_RESOLUTION * 60)
            self.effort_time_edit.setTime(q_time)

        start_time = self.start_time_edit.time()
        end_time = start_time.addSecs(start_of_today.secsTo(q_time))
        self.end_time_edit.setTime(end_time)

        self.updating_timings = False

        self.update_percentage()
        self.update_info_text()
コード例 #2
0
ファイル: time_log_dialog.py プロジェクト: MehmetErer/anima
    def start_time_changed(self, q_time):
        """validates the start time
        """
        if self.updating_timings:
            return

        self.updating_timings = True

        # q_time should be a multiple of the TIMING_RESOLUTION
        q_time = self.round_to_timing_resolution(q_time)
        self.start_time_edit.setTime(q_time)

        end_time = self.end_time_edit.time()
        if q_time >= end_time:
            from anima import TIMING_RESOLUTION
            logger.debug("updating end_time with set_time")
            self.end_time_edit.setTime(q_time.addSecs(TIMING_RESOLUTION * 60))
            logger.debug("updated end_time with set_time")

        start_time = self.start_time_edit.time()
        end_time = self.end_time_edit.time()

        secs = start_time.secsTo(end_time)
        logger.debug("secs: %s" % secs)
        new_time = QtCore.QTime(0, 0)
        new_time = new_time.addSecs(secs)
        logger.debug("new_time: %s" % new_time)
        logger.debug("updating end_time with set_time")
        self.effort_time_edit.setTime(new_time)
        logger.debug("updated end_time with set_time")

        self.updating_timings = False

        self.update_percentage()
        self.update_info_text()
コード例 #3
0
    def stepBy(self, step):
        """Custom stepBy function

        :param step:
        :return:
        """
        if self.currentSectionIndex() == 1:
            if step < 0:
                # auto update the hour section to the next hour
                minute = self.time().minute()
                if minute == 0:
                    # increment the hour section by one
                    self.setTime(
                        QtCore.QTime(self.time().hour() - 1,
                                     60 - self.resolution))
                else:
                    self.setTime(
                        QtCore.QTime(self.time().hour(),
                                     minute - self.resolution))

            else:
                # auto update the hour section to the next hour
                minute = self.time().minute()
                if minute == (60 - self.resolution):
                    # increment the hour section by one
                    self.setTime(QtCore.QTime(self.time().hour() + 1, 0))
                else:
                    self.setTime(
                        QtCore.QTime(self.time().hour(),
                                     minute + self.resolution))
        else:
            if step < 0:
                if self.time().hour() != 0:
                    super(TimeEdit, self).stepBy(step)
            else:
                if self.time().hour() != 23:
                    super(TimeEdit, self).stepBy(step)
コード例 #4
0
ファイル: time_log_dialog.py プロジェクト: MehmetErer/anima
    def round_to_timing_resolution(cls, q_time):
        """rounds to the TIMING_RESOLUTION

        :param q_time:
        :return:
        """
        logger.debug("q_time(RAW)    : %s" % q_time)
        from anima import TIMING_RESOLUTION

        start_of_today = QtCore.QTime(0, 0)
        secs = start_of_today.secsTo(q_time)

        logger.debug('secs       : %s' % secs)
        logger.debug("TIMING_RESOLUTION: %s" % TIMING_RESOLUTION)
        rounded_secs = (secs // (TIMING_RESOLUTION * 60)) * TIMING_RESOLUTION * 60

        logger.debug("rounded_secs: %s" % rounded_secs)
        rounded_q_time = start_of_today.addSecs(rounded_secs)

        logger.debug("q_time(Rounded): %s" % rounded_q_time)

        return rounded_q_time
コード例 #5
0
ファイル: time_log_dialog.py プロジェクト: MehmetErer/anima
    def end_time_changed(self, q_time):
        """validates the end time
        """
        if self.updating_timings:
            return

        self.updating_timings = True
        logger.debug("end_time_changed event is triggered!")

        # q_time should be a multiple of the TIMING_RESOLUTION
        q_time = self.round_to_timing_resolution(q_time)
        self.end_time_edit.setTime(q_time)

        start_time = self.start_time_edit.time()
        if q_time <= start_time:
            from anima import TIMING_RESOLUTION
            if q_time.hour() == 0 and q_time.minute() == 0:
                start_time = q_time
                end_time = q_time.addSecs(TIMING_RESOLUTION * 60)
                self.end_time_edit.setTime(end_time)
            else:
                start_time = q_time.addSecs(-TIMING_RESOLUTION * 60)
            self.start_time_edit.setTime(start_time)

        start_time = self.start_time_edit.time()
        end_time = self.end_time_edit.time()
        secs = start_time.secsTo(end_time)
        logger.debug("secs: %s" % secs)
        new_time = QtCore.QTime(0, 0)
        new_time = new_time.addSecs(secs)
        logger.debug("new_time: %s" % new_time)
        self.effort_time_edit.setTime(new_time)

        self.updating_timings = False

        self.update_percentage()
        self.update_info_text()
コード例 #6
0
    def _set_defaults(self):
        """sets the defaults for the ui
        """
        logger.debug("started setting up interface defaults")

        # Set Default Value for time
        current_time = QtCore.QTime.currentTime()
        # round the minutes to the resolution
        minute = current_time.minute()
        hour = current_time.hour()
        minute = int(minute / float(timing_resolution)) * timing_resolution

        current_time = QtCore.QTime(hour, minute)

        self.start_time_edit.setTime(current_time)
        self.end_time_edit.setTime(current_time.addSecs(timing_resolution * 60))

        self.calendar_widget.resource_id = -1

        # enter revision types
        revision_types = [
            'Yetistiremedim',
            'Ajans',
            'Yonetmen',
            'Ic Revizyon',
        ]

        self.revision_type_combo_box.addItems(revision_types)

        if not self.logged_in_user:
            self.logged_in_user = self.get_logged_in_user()

        # fill the tasks comboBox
        from stalker import Status, Task
        status_wfd = Status.query.filter(Status.code == 'WFD').first()
        status_cmpl = Status.query.filter(Status.code == 'CMPL').first()
        status_prev = Status.query.filter(Status.code == 'PREV').first()

        if not self.timelog:
            # dialog is in create TimeLog mode
            # if a task has been given just feed that task to the comboBox
            if self.task:
                all_tasks = [self.task]
            else:
                # no Task is given nor updating a TimeLog
                # show all the suitable tasks of the logged_in_user
                all_tasks = Task.query \
                    .filter(Task.resources.contains(self.logged_in_user)) \
                    .filter(Task.status != status_wfd) \
                    .filter(Task.status != status_cmpl) \
                    .filter(Task.status != status_prev) \
                    .all()
                # sort the task labels
                all_tasks = sorted(
                    all_tasks,
                    key=lambda task:
                    '%s | %s' % (
                        task.project.name.lower(),
                        ' | '.join(map(lambda x: x.name.lower(), task.parents))
                    )
                )
        else:
            # dialog is working in update TimeLog mode
            all_tasks = [self.timelog.task]

        self.tasks_combo_box.setSizeAdjustPolicy(
            QtWidgets.QComboBox.AdjustToContentsOnFirstShow
        )
        self.tasks_combo_box.setFixedWidth(360)
        self.tasks_combo_box.clear()
        self.tasks_combo_box.addTasks(all_tasks)

        self.tasks_combo_box.setSizePolicy(
            QtWidgets.QSizePolicy.MinimumExpanding,
            QtWidgets.QSizePolicy.Minimum
        )

        # if a time log is given set the fields from the given time log
        if self.timelog:
            # first update Task
            try:
                self.tasks_combo_box.setCurrentTask(self.timelog.task)
            except IndexError as e:
                return

            # set the resource

            # and disable the tasks_combo_box and resource_combo_box
            self.tasks_combo_box.setEnabled(False)
            self.resource_combo_box.setEnabled(False)

            # set the start and end time
            from anima.utils import utc_to_local
            start_date = utc_to_local(self.timelog.start)
            end_date = utc_to_local(self.timelog.end)

            # set the date
            self.calendar_widget.setSelectedDate(
                QtCore.QDate(start_date.year, start_date.month, start_date.day)
            )

            # first reset the start and end time values
            self.start_time_edit.setTime(QtCore.QTime(0, 0))
            self.end_time_edit.setTime(QtCore.QTime(23, 50))

            # now set the timelog time
            self.start_time_edit.setTime(
                QtCore.QTime(
                    start_date.hour,
                    start_date.minute
                )
            )
            self.end_time_edit.setTime(
                QtCore.QTime(
                    end_date.hour,
                    end_date.minute
                )
            )

        self.fill_calendar_with_time_logs()

        # also trigger an update to the side info bar
        self.calendar_widget_selection_changed()
コード例 #7
0
    def __init__(self, parent=None, task=None, timelog=None):
        logger.debug("initializing the interface")
        # store the logged in user
        self.logged_in_user = None
        self.no_time_left = False
        self.extended_hours = None
        self.extended_minutes = None

        self.timelog = timelog
        self.timelog_created = False
        self.task = task

        super(MainDialog, self).__init__(parent)
        self.setupUi(self)

        # customize the ui elements
        from anima.ui.widgets import TaskComboBox
        self.tasks_comboBox = TaskComboBox(self)
        self.tasks_comboBox.setObjectName("tasks_comboBox")
        self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole,
                                  self.tasks_comboBox)

        # self.start_timeEdit.deleteLater()
        from anima.ui.widgets import TimeEdit
        self.start_timeEdit = TimeEdit(self, resolution=timing_resolution)
        self.start_timeEdit.setCurrentSection(
            QtWidgets.QDateTimeEdit.MinuteSection)
        self.start_timeEdit.setCalendarPopup(True)
        self.start_timeEdit.setObjectName("start_timeEdit")
        self.start_timeEdit.setWrapping(True)
        self.formLayout.insertRow(4, self.label, self.start_timeEdit)
        self.start_timeEdit.setDisplayFormat("HH:mm")

        # self.end_timeEdit.deleteLater()
        self.end_timeEdit = TimeEdit(self, resolution=timing_resolution)
        self.end_timeEdit.setCurrentSection(
            QtWidgets.QDateTimeEdit.MinuteSection)
        self.end_timeEdit.setCalendarPopup(True)
        self.end_timeEdit.setObjectName("end_timeEdit")
        self.end_timeEdit.setWrapping(True)
        self.formLayout.insertRow(5, self.label_2, self.end_timeEdit)
        self.end_timeEdit.setDisplayFormat("HH:mm")

        current_time = QtCore.QTime.currentTime()
        # round the minutes to the resolution
        minute = current_time.minute()
        hour = current_time.hour()
        minute = int(minute / float(timing_resolution)) * timing_resolution

        current_time = QtCore.QTime(hour, minute)

        self.start_timeEdit.setTime(current_time)
        self.end_timeEdit.setTime(current_time.addSecs(timing_resolution * 60))

        self.calendarWidget.resource_id = -1

        # setup signals
        self._setup_signals()

        # setup defaults
        self._set_defaults()

        # center window
        self.center_window()
コード例 #8
0
ファイル: time_log_dialog.py プロジェクト: MehmetErer/anima
    def fill_calendar_with_time_logs(self):
        """fill the calendar with daily time log info
        """
        resource_id = self.get_current_resource_id()
        # do not update if the calendar is showing the same user
        if self.calendar_widget.resource_id == resource_id or resource_id == -1:
            return

        tool_tip_text_format = u'{start:%H:%M} - {end:%H:%M} | {task_name}'

        # import time
        # start = time.time()
        # get all the TimeLogs grouped daily
        sql = """-- TOP DOWN SEARCH --
select
    "TimeLogs".start::date as date,
    array_agg(task_rec_data.full_path) as task_name,
    array_agg("TimeLogs".start) as start,
    array_agg("TimeLogs".end) as end,
    sum(extract(epoch from ("TimeLogs".end - "TimeLogs".start)))

from "TimeLogs"

join (
    with recursive recursive_task(id, parent_id, path_names) as (
        select
        task.id,
        task.project_id,
        -- task.project_id::text as path,
        ("Projects".code || '') as path_names
        from "Tasks" as task
        join "Projects" on task.project_id = "Projects".id
        where task.parent_id is NULL
    union all
        select
        task.id,
        task.parent_id,
        -- (parent.path || '|' || task.parent_id:: text) as path,
        (parent.path_names || ' | ' || "Parent_SimpleEntities".name) as path_names
        from "Tasks" as task
        inner join recursive_task as parent on task.parent_id = parent.id
        inner join "SimpleEntities" as "Parent_SimpleEntities" on parent.id = "Parent_SimpleEntities".id
    ) select
        recursive_task.id,
        "SimpleEntities".name || ' (' || recursive_task.path_names || ')' as full_path
    from recursive_task
    join "SimpleEntities" on recursive_task.id = "SimpleEntities".id
) as task_rec_data on "TimeLogs".task_id = task_rec_data.id

-- getting all the data is as fast as getting one, so get all the TimeLogs of this user
where "TimeLogs".resource_id = :resource_id
group by cast("TimeLogs".start as date)
order by cast("TimeLogs".start as date)
        """
        from sqlalchemy import text
        from stalker.db.session import DBSession
        result = DBSession.connection().execute(
            text(sql),
            resource_id=resource_id
        ).fetchall()
        # end = time.time()
        # print('getting data from sql: %0.3f sec' % (end - start))

        # TODO: Remove this in a later version
        from anima.utils import utc_to_local
        time_shifter = utc_to_local
        from distutils.version import LooseVersion
        import stalker
        if LooseVersion(stalker.__version__) >= LooseVersion('0.2.18'):
            def time_shifter(x):
                return x

        last_end_date = None
        for r in result:
            calendar_day = r[0]
            year = calendar_day.year
            month = calendar_day.month
            day = calendar_day.day
            daily_logged_seconds = r[4]
            daily_logged_hours = daily_logged_seconds // 3600
            daily_logged_minutes = \
                (daily_logged_seconds - daily_logged_hours * 3600) // 60

            tool_tip_text_data = [
                u'Total: %i h %i min logged' %
                (daily_logged_hours, daily_logged_minutes)
                if daily_logged_hours
                else u'Total: %i min logged' % daily_logged_minutes
            ]

            for task_name, start, end in sorted(zip(r[1], r[2], r[3]), key=lambda x: x[1]):
                time_log_tool_tip_text = tool_tip_text_format.format(
                    start=time_shifter(start),
                    end=time_shifter(end),
                    task_name=task_name
                )
                tool_tip_text_data.append(time_log_tool_tip_text)
                # store the last_end_date
                last_end_date = end

            merged_tool_tip = u'\n'.join(tool_tip_text_data)

            date_format = QtGui.QTextCharFormat()
            bg_brush = QtGui.QBrush()
            bg_brush.setColor(
                QtGui.QColor(0, 255.0 / 86400.0 * daily_logged_seconds, 0)
            )

            date_format.setBackground(bg_brush)
            date_format.setToolTip(merged_tool_tip)

            date = QtCore.QDate(year, month, day)

            self.calendar_widget.setDateTextFormat(date, date_format)

        # set the start time in the UI to the last_end_date's time value
        # so the UI will automatically be set to the start of the next
        # available slot
        import pytz
        import datetime
        from anima.utils import local_to_utc
        utc_now = local_to_utc(datetime.datetime.now())
        utc_now = utc_now.replace(tzinfo=pytz.utc)
        start_of_today = datetime.datetime(utc_now.year, utc_now.month, utc_now.day, tzinfo=utc_now.tzinfo)
        if last_end_date and last_end_date > start_of_today:
            from anima import TIMING_RESOLUTION
            last_end_time = QtCore.QTime(last_end_date.hour, last_end_date.minute)
            self.start_time_edit.setTime(last_end_time)
            self.end_time_edit.setTime(last_end_time.addSecs(TIMING_RESOLUTION * 60))