Пример #1
0
 def __date_comp(self, task1, task2, para, order):
     '''This is a quite complex method to sort tasks by date,
     handling fuzzy date and complex situation.
     Return -1 if nid1 is before nid2, return 1 otherwise
     '''
     if task1 and task2:
         if para == 'start':
             t1 = task1.get_start_date()
             t2 = task2.get_start_date()
         elif para == 'due':
             #BUG: get_urgent_date() compares children, and the constraint one compares parents, and we are blindly blending the two together?!?!
             t1 = task1.get_urgent_date()
             t2 = task2.get_urgent_date()
             if t1 == Date.no_date():
                 t1 = task1.get_due_date_constraint()
             if t2 == Date.no_date():
                 t2 = task2.get_due_date_constraint()
         elif para == 'closed':
             t1 = task1.get_closed_date()
             t2 = task2.get_closed_date()
         else:
             raise ValueError(
                 'invalid date comparison parameter: %s') % para
         #return reverse_if_descending(order, cmp(t2, t1))
         # Tricky! swapped is correct!?
         return cmp(t2, t1);
     else:
         return 0;
Пример #2
0
    def __init__(self, ze_id, requester, newtask=False):
        TreeNode.__init__(self, ze_id)
        # the id of this task in the project should be set
        # tid is a string ! (we have to choose a type and stick to it)
        assert(isinstance(ze_id, str) or isinstance(ze_id, str))
        self.tid = str(ze_id)
        self.set_uuid(uuid.uuid4())
        self.remote_ids = {}
        self.content = ""
        self.title = _("My new task")
        # available status are: Active - Done - Dismiss - Note
        self.status = self.STA_ACTIVE
        self.closed_date = Date.no_date()
        self.due_date = Date.no_date()
        self.start_date = Date.no_date()
        self.can_be_deleted = newtask
        # tags
        self.tags = []
        self.req = requester
        self.__main_treeview = requester.get_main_view()
        # If we don't have a newtask, we will have to load it.
        self.loaded = newtask
        # Should not be necessary with the new backends
#        if self.loaded:
#            self.req._task_loaded(self.tid)
        self.attributes = {}
        self._modified_update()
Пример #3
0
    def __init__(self, ze_id, requester, newtask=False):
        TreeNode.__init__(self, ze_id)
        # the id of this task in the project should be set
        # tid is a string ! (we have to choose a type and stick to it)
        assert(isinstance(ze_id, str) or isinstance(ze_id, unicode))
        self.tid = str(ze_id)
        self.set_uuid(uuid.uuid4())
        self.remote_ids = {}
        self.content = ""
        self.title = _("My new task")
        # available status are: Active - Done - Dismiss - Note
        self.status = self.STA_ACTIVE
        self.closed_date = Date.no_date()
        self.due_date = Date.no_date()
        self.start_date = Date.no_date()
        self.can_be_deleted = newtask
        # tags
        self.tags = []
        self.req = requester
        self.__main_treeview = requester.get_main_view()
        # If we don't have a newtask, we will have to load it.
        self.loaded = newtask
        # Should not be necessary with the new backends
#        if self.loaded:
#            self.req._task_loaded(self.tid)
        self.attributes = {}
        self._modified_update()
Пример #4
0
    def on_date_cleared(self, widget, kind):
        """ Callback when a date is cleared through the popups. """

        if kind == GTGCalendar.DATE_KIND_START:
            self.task.set_start_date(Date.no_date())
            self.start_entry.set_text('')

        elif kind == GTGCalendar.DATE_KIND_DUE:
            self.task.set_due_date(Date.no_date())
            self.due_entry.set_text('')
Пример #5
0
    def __date_comp(self, task1, task2, para, order):
        '''This is a quite complex method to sort tasks by date,
        handling fuzzy date and complex situation.
        Return -1 if nid1 is before nid2, return 1 otherwise
        '''
        if task1 and task2:
            if para == 'start':
                t1 = task1.get_start_date()
                t2 = task2.get_start_date()
            elif para == 'due':
                t1 = task1.get_urgent_date()
                t2 = task2.get_urgent_date()
                if t1 == Date.no_date():
                    t1 = task1.get_due_date_constraint()
                if t2 == Date.no_date():
                    t2 = task2.get_due_date_constraint()
            elif para == 'closed':
                t1 = task1.get_closed_date()
                t2 = task2.get_closed_date()
            else:
                raise ValueError(
                    'invalid date comparison parameter: %s') % para
            sort = (t2 > t1) - (t2 < t1)
        else:
            sort = 0

        # local function
        def reverse_if_descending(s):
            """Make a cmpare result relative to the top instead of following
               user-specified sort direction"""
            if order == Gtk.SortType.ASCENDING:
                return s
            else:
                return -1 * s

        if sort == 0:
            # Group tasks with the same tag together for visual cleanness
            t1_tags = task1.get_tags_name()
            t1_tags.sort()
            t2_tags = task2.get_tags_name()
            t2_tags.sort()
            cmp_tags = (t1_tags > t2_tags) - (t1_tags < t2_tags)
            sort = reverse_if_descending(cmp_tags)

        if sort == 0:
            # Break ties by sorting by title
            t1_title = task1.get_title()
            t2_title = task2.get_title()
            t1_title = locale.strxfrm(t1_title)
            t2_title = locale.strxfrm(t2_title)
            cmp_title = (t1_title > t2_title) - (t1_title < t2_title)
            sort = reverse_if_descending(cmp_title)

        return sort
Пример #6
0
    def __date_comp(self, task1, task2, para, order):
        '''This is a quite complex method to sort tasks by date,
        handling fuzzy date and complex situation.
        Return -1 if nid1 is before nid2, return 1 otherwise
        '''
        if task1 and task2:
            if para == 'start':
                t1 = task1.get_start_date()
                t2 = task2.get_start_date()
            elif para == 'due':
                t1 = task1.get_urgent_date()
                t2 = task2.get_urgent_date()
                if t1 == Date.no_date():
                    t1 = task1.get_due_date_constraint()
                if t2 == Date.no_date():
                    t2 = task2.get_due_date_constraint()
            elif para == 'closed':
                t1 = task1.get_closed_date()
                t2 = task2.get_closed_date()
            else:
                raise ValueError(
                    'invalid date comparison parameter: %s') % para
            sort = (t2 > t1) - (t2 < t1)
        else:
            sort = 0

        # local function
        def reverse_if_descending(s):
            """Make a cmpare result relative to the top instead of following
               user-specified sort direction"""
            if order == Gtk.SortType.ASCENDING:
                return s
            else:
                return -1 * s

        if sort == 0:
            # Group tasks with the same tag together for visual cleanness
            t1_tags = task1.get_tags_name()
            t1_tags.sort()
            t2_tags = task2.get_tags_name()
            t2_tags.sort()
            cmp_tags = (t1_tags > t2_tags) - (t1_tags < t2_tags)
            sort = reverse_if_descending(cmp_tags)

        if sort == 0:
            # Break ties by sorting by title
            t1_title = task1.get_title()
            t2_title = task2.get_title()
            t1_title = locale.strxfrm(t1_title)
            t2_title = locale.strxfrm(t2_title)
            cmp_title = (t1_title > t2_title) - (t1_title < t2_title)
            sort = reverse_if_descending(cmp_title)

        return sort
Пример #7
0
    def set_complex_title(self, text, tags=[]):
        if tags:
            assert (isinstance(tags[0], str))
        due_date = Date.no_date()
        defer_date = Date.no_date()
        if text:
            # Get tags in the title
            for match in extract_tags_from_text(text):
                tags.append(match)
            # Get attributes
            regexp = r'([\s]*)([\w-]+):\s*([^\s]+)'
            matches = re.findall(regexp, text, re.UNICODE)
            for spaces, attribute, args in matches:
                valid_attribute = True
                if attribute.lower() in ["tags", _("tags"), "tag", _("tag")]:
                    for tag in args.split(","):
                        if not tag.strip() == "@" and not tag.strip() == "":
                            if not tag.startswith("@"):
                                tag = "@" + tag
                            tags.append(tag)
                elif attribute.lower() in [
                        "defer", _("defer"), "start",
                        _("start")
                ]:
                    try:
                        defer_date = Date.parse(args)
                    except ValueError:
                        valid_attribute = False
                elif attribute.lower() == "due" or \
                        attribute.lower() == _("due"):
                    try:
                        due_date = Date.parse(args)
                    except:
                        valid_attribute = False
                else:
                    # attribute is unknown
                    valid_attribute = False

                if valid_attribute:
                    # remove valid attribute from the task title
                    text = \
                        text.replace("%s%s:%s" % (spaces, attribute, args), "")

            for t in tags:
                self.add_tag(t)

            if text != "":
                self.set_title(text.strip())
                self.set_to_keep()

            self.set_due_date(due_date)
            self.set_start_date(defer_date)
Пример #8
0
    def set_complex_title(self, text, tags=[]):
        if tags:
            assert(isinstance(tags[0], str))
        due_date = Date.no_date()
        defer_date = Date.no_date()
        if text:
            # Get tags in the title
            for match in extract_tags_from_text(text):
                tags.append(match)
            # Get attributes
            regexp = r'([\s]*)([\w-]+):\s*([^\s]+)'
            matches = re.findall(regexp, text, re.UNICODE)
            for spaces, attribute, args in matches:
                valid_attribute = True
                if attribute.lower() in ["tags", _("tags"), "tag", _("tag")]:
                    for tag in args.split(","):
                        if not tag.strip() == "@" and not tag.strip() == "":
                            if not tag.startswith("@"):
                                tag = "@" + tag
                            tags.append(tag)
                elif attribute.lower() in ["defer", _("defer"), "start",
                                           _("start")]:
                    try:
                        defer_date = Date.parse(args)
                    except ValueError:
                        valid_attribute = False
                elif attribute.lower() == "due" or \
                        attribute.lower() == _("due"):
                    try:
                        due_date = Date.parse(args)
                    except:
                        valid_attribute = False
                else:
                    # attribute is unknown
                    valid_attribute = False

                if valid_attribute:
                    # remove valid attribute from the task title
                    text = \
                        text.replace("%s%s:%s" % (spaces, attribute, args), "")

            for t in tags:
                self.add_tag(t)

            if text != "":
                self.set_title(text.strip())
                self.set_to_keep()

            self.set_due_date(due_date)
            self.set_start_date(defer_date)
Пример #9
0
 def __init__(self):
     super().__init__()
     self.__builder = Gtk.Builder()
     self.__builder.add_from_file(GnomeConfig.CALENDAR_UI_FILE)
     self.__date_kind = None
     self.__date = Date.no_date()
     self.__init_gtk__()
Пример #10
0
 def test_parse_local_fuzzy_dates(self):
     """ Parse fuzzy dates in their localized version """
     self.assertEqual(Date.parse(_("now")), Date.now())
     self.assertEqual(Date.parse(_("soon")), Date.soon())
     self.assertEqual(Date.parse(_("later")), Date.someday())
     self.assertEqual(Date.parse(_("someday")), Date.someday())
     self.assertEqual(Date.parse(""), Date.no_date())
Пример #11
0
 def test_parse_fuzzy_dates(self):
     """ Parse fuzzy dates like now, soon, later, someday """
     self.assertEqual(Date.parse("now"), Date.now())
     self.assertEqual(Date.parse("soon"), Date.soon())
     self.assertEqual(Date.parse("later"), Date.someday())
     self.assertEqual(Date.parse("someday"), Date.someday())
     self.assertEqual(Date.parse(""), Date.no_date())
Пример #12
0
 def test_parse_fuzzy_dates(self):
     """ Parse fuzzy dates like now, soon, later, someday """
     self.assertEqual(Date.parse("now"), Date.now())
     self.assertEqual(Date.parse("soon"), Date.soon())
     self.assertEqual(Date.parse("later"), Date.someday())
     self.assertEqual(Date.parse("someday"), Date.someday())
     self.assertEqual(Date.parse(""), Date.no_date())
Пример #13
0
    def bgcolor(self, node, standard_color):
        color = self.get_node_bgcolor(node)

        def __get_active_child_list(node):
            """ This function recursively fetches a list
            of all the children of a task which are active
            (i.e - the subtasks which are not marked as 'Done' or 'Dismissed'
            """
            child_list = []
            for child_id in node.children:
                child = node.req.get_task(child_id)
                child_list += __get_active_child_list(child)
                if child.get_status() in [child.STA_ACTIVE]:
                    child_list.append(child_id)
            return child_list

        child_list = __get_active_child_list(node)

        daysleft = None
        for child_id in child_list:
            child = self.req.get_task(child_id)
            if child.get_due_date() == Date.no_date():
                continue

            daysleft_of_child = child.get_due_date().days_left()
            if daysleft is None:
                daysleft = daysleft_of_child
                color = self.get_node_bgcolor(child)
            elif daysleft_of_child < daysleft:
                daysleft = daysleft_of_child
                color = self.get_node_bgcolor(child)

        return color
Пример #14
0
 def __init__(self):
     super(GTGCalendar, self).__init__()
     self.__builder = Gtk.Builder()
     self.__builder.add_from_file(GnomeConfig.CALENDAR_UI_FILE)
     self.__date_kind = None
     self.__date = Date.no_date()
     self.__init_gtk__()
Пример #15
0
 def task_duedate_column(self, node):
     # We show the most constraining due date for task with no due dates.
     if node.get_due_date() == Date.no_date():
         return node.get_due_date_constraint().to_readable_string()
     else:
         # Other tasks show their due date (which *can* be fuzzy)
         return node.get_due_date().to_readable_string()
Пример #16
0
 def task_duedate_column(self, node):
     # We show the most constraining due date for task with no due dates.
     if node.get_due_date() == Date.no_date():
         return node.get_due_date_constraint().to_readable_string()
     else:
         # Other tasks show their due date (which *can* be fuzzy)
         return node.get_due_date().to_readable_string()
Пример #17
0
    def bgcolor(self, node, standard_color):
        color = self.get_node_bgcolor(node)

        def __get_active_child_list(node):
            """ This function recursively fetches a list
            of all the children of a task which are active
            (i.e - the subtasks which are not marked as 'Done' or 'Dismissed'
            """
            child_list = []
            for child_id in node.children:
                child = node.req.get_task(child_id)
                child_list += __get_active_child_list(child)
                if child.get_status() in [child.STA_ACTIVE]:
                    child_list.append(child_id)
            return child_list

        child_list = __get_active_child_list(node)

        daysleft = None
        for child_id in child_list:
            child = self.req.get_task(child_id)
            if child.get_due_date() == Date.no_date():
                continue

            daysleft_of_child = child.get_due_date().days_left()
            if daysleft is None:
                daysleft = daysleft_of_child
                color = self.get_node_bgcolor(child)
            elif daysleft_of_child < daysleft:
                daysleft = daysleft_of_child
                color = self.get_node_bgcolor(child)

        return color
Пример #18
0
 def test_parse_local_fuzzy_dates(self):
     """ Parse fuzzy dates in their localized version """
     self.assertEqual(Date.parse(_("now")), Date.now())
     self.assertEqual(Date.parse(_("soon")), Date.soon())
     self.assertEqual(Date.parse(_("later")), Date.someday())
     self.assertEqual(Date.parse(_("someday")), Date.someday())
     self.assertEqual(Date.parse(""), Date.no_date())
Пример #19
0
 def get_due_date(self):
     '''
     Gets the task due date
     '''
     due = self.rtm_task.due
     if due == "":
         return Date.no_date()
     date = self.__time_rtm_to_datetime(due).date()
     return Date(date)
Пример #20
0
 def get_due_date(self):
     '''
     Gets the task due date
     '''
     due = self.rtm_task.due
     if due == "":
         return Date.no_date()
     date = self.__time_rtm_to_datetime(due).date()
     return Date(date)
Пример #21
0
def _due_within(task, danger_zone):
    """
    Determine if a task is the danger zone.
    Convention: a danger zone of 1 day includes tasks due today.
    """
    ddate = task.get_due_date()
    if (ddate != Date.no_date()):
        if ddate.days_left() < danger_zone:
            return True
    return False
Пример #22
0
def _due_within(task, danger_zone):
    """
    Determine if a task is the danger zone.
    Convention: a danger zone of 1 day includes tasks due today.
    """
    ddate = task.get_due_date()
    if (ddate != Date.no_date()):
        if ddate.days_left() < danger_zone:
            return True
    return False
Пример #23
0
 def _populate_evo_task(self, task, evo_task):
     evo_task.set_summary(task.get_title())
     text = task.get_excerpt(strip_tags=True, strip_subtasks=True)
     if evo_task.get_description() != text:
         evo_task.set_description(text)
     due_date = task.get_due_date()
     if due_date == Date.no_date():
         evo_task.set_due(None)
     else:
         evo_task.set_due(self.__date_from_gtg_to_evo(due_date))
     status = task.get_status()
     if _EVOLUTION_TO_GTG_STATUS[evo_task.get_status()] != status:
         evo_task.set_status(_GTG_TO_EVOLUTION_STATUS[status])
     # this calls are sometime ignored by evolution. Doing it twice
     # is a hackish way to solve the problem. (TODO: send bug report)
     self._evolution_tasks.update_object(evo_task)
     self._evolution_tasks.update_object(evo_task)
Пример #24
0
 def _populate_evo_task(self, task, evo_task):
     evo_task.set_summary(task.get_title())
     text = task.get_excerpt(strip_tags=True, strip_subtasks=True)
     if evo_task.get_description() != text:
         evo_task.set_description(text)
     due_date = task.get_due_date()
     if due_date == Date.no_date():
         evo_task.set_due(None)
     else:
         evo_task.set_due(self.__date_from_gtg_to_evo(due_date))
     status = task.get_status()
     if _EVOLUTION_TO_GTG_STATUS[evo_task.get_status()] != status:
         evo_task.set_status(_GTG_TO_EVOLUTION_STATUS[status])
     # this calls are sometime ignored by evolution. Doing it twice
     # is a hackish way to solve the problem. (TODO: send bug report)
     self._evolution_tasks.update_object(evo_task)
     self._evolution_tasks.update_object(evo_task)
Пример #25
0
    def check_commands(commands_list):
        """ Execute search commands

        This method is recursive for !or and !and """

        def fulltext_search(task, word):
            """ check if task contains the word """
            word = word.lower()
            text = task.get_excerpt(strip_tags=False).lower()
            title = task.get_title().lower()

            return word in text or word in title

        value_checks = {
            'after': lambda t, v: task.get_due_date() > v,
            'before': lambda t, v: task.get_due_date() < v,
            'tag': lambda t, v: v in task.get_tags_name(),
            'word': fulltext_search,
            'today': lambda task, v: task.get_due_date() == Date.today(),
            'tomorrow': lambda task, v: task.get_due_date() == Date.tomorrow(),
            'nodate': lambda task, v: task.get_due_date() == Date.no_date(),
            'now': lambda task, v: task.get_due_date() == Date.now(),
            'soon': lambda task, v: task.get_due_date() == Date.soon(),
            'someday': lambda task, v: task.get_due_date() == Date.someday(),
            'notag': lambda task, v: task.get_tags() == [],
        }

        for command in commands_list:
            cmd, positive, args = command[0], command[1], command[2:]
            result = False

            if cmd == 'or':
                for sub_cmd in args[0]:
                    if check_commands([sub_cmd]):
                        result = True
                        break
            elif value_checks.get(cmd, None):
                if len(args) > 0:
                    args = args[0]
                result = value_checks[cmd](task, args)

            if (positive and not result) or (not positive and result):
                return False

        return True
Пример #26
0
    def check_commands(commands_list):
        """ Execute search commands

        This method is recursive for !or and !and """

        def fulltext_search(task, word):
            """ check if task contains the word """
            word = word.lower()
            text = task.get_excerpt(strip_tags=False).lower()
            title = task.get_title().lower()

            return word in text or word in title

        value_checks = {
            'after': lambda t, v: task.get_due_date() > v,
            'before': lambda t, v: task.get_due_date() < v,
            'tag': lambda t, v: v in task.get_tags_name(),
            'word': fulltext_search,
            'today': lambda task, v: task.get_due_date() == Date.today(),
            'tomorrow': lambda task, v: task.get_due_date() == Date.tomorrow(),
            'nodate': lambda task, v: task.get_due_date() == Date.no_date(),
            'now': lambda task, v: task.get_due_date() == Date.now(),
            'soon': lambda task, v: task.get_due_date() == Date.soon(),
            'someday': lambda task, v: task.get_due_date() == Date.someday(),
            'notag': lambda task, v: task.get_tags() == [],
        }

        for command in commands_list:
            cmd, positive, args = command[0], command[1], command[2:]
            result = False

            if cmd == 'or':
                for sub_cmd in args[0]:
                    if check_commands([sub_cmd]):
                        result = True
                        break
            elif value_checks.get(cmd, None):
                if len(args) > 0:
                    args = args[0]
                result = value_checks[cmd](task, args)

            if (positive and not result) or (not positive and result):
                return False

        return True
Пример #27
0
 def _populate_task(self, task, evo_task):
     '''
     Updates the attributes of a GTG task copying the ones of an Evolution
     task
     '''
     task.set_title(evo_task.get_summary())
     text = evo_task.get_description()
     if text is None:
         text = ""
     task.set_text(text)
     due_date_timestamp = evo_task.get_due()
     if isinstance(due_date_timestamp, (int, float)):
         due_date = self.__date_from_evo_to_gtg(due_date_timestamp)
     else:
         due_date = Date.no_date()
     task.set_due_date(due_date)
     status = evo_task.get_status()
     if task.get_status() != _EVOLUTION_TO_GTG_STATUS[status]:
         task.set_status(_EVOLUTION_TO_GTG_STATUS[status])
     task.set_only_these_tags(extract_tags_from_text(text))
Пример #28
0
 def _populate_task(self, task, evo_task):
     '''
     Updates the attributes of a GTG task copying the ones of an Evolution
     task
     '''
     task.set_title(evo_task.get_summary())
     text = evo_task.get_description()
     if text is None:
         text = ""
     task.set_text(text)
     due_date_timestamp = evo_task.get_due()
     if isinstance(due_date_timestamp, (int, float)):
         due_date = self.__date_from_evo_to_gtg(due_date_timestamp)
     else:
         due_date = Date.no_date()
     task.set_due_date(due_date)
     status = evo_task.get_status()
     if task.get_status() != _EVOLUTION_TO_GTG_STATUS[status]:
         task.set_status(_EVOLUTION_TO_GTG_STATUS[status])
     task.set_only_these_tags(extract_tags_from_text(text))
Пример #29
0
    def get_node_bgcolor(self, node):
        """ This method checks the urgency of a node (task) and returns its
         urgency background color"""
        sdate = node.get_start_date()
        ddate = node.get_due_date()
        daysleft = ddate.days_left()

        # Dates undefined (Fix to bug #1039655)
        if (ddate == Date.today()):
            return self._get_color(2)  # High urgency
        elif (daysleft < 0 and ddate != Date.no_date()):
            return self._get_color(3)  # Overdue
        elif (sdate == Date.no_date()  # Has no start date
                and ddate != Date.no_date()  # and a due date
                and not ddate.is_fuzzy()):  # which is not fuzzy, is fixed
            return self._get_color(1)  # Normal

        # Fuzzy dates (now, soon, someday)
        # These can ignore the start date
        if (ddate == Date.now()):
            return self._get_color(2)
        elif (ddate == Date.soon()):
            return self._get_color(1)
        elif (ddate == Date.someday()):
            return self._get_color(0)

        # Dates fully defined. Calculate gradient color
        elif (sdate != Date.no_date() != ddate):
            dayspan = (ddate - sdate).days
            redf = self._pref_data['reddays']
            reddays = int(ceil(redf / 100.0 * dayspan))

            # Gradient variables
            grad_dayspan = dayspan - reddays
            grad_half_dayspan = grad_dayspan / 2.0

            # Default to low urgency color
            color = self._get_color(0)

            # CL : low urgency color
            # CN : normal urgency color
            # CH : high urgency color
            # CO : overdue color
            # To understand this section, it is easier to draw out a
            # timeline divided into 3 sections: CL to CN, CN to CH and
            # the reddays section. Then point out the spans of the
            # different variables (dayspan, daysleft, reddays,
            # grad_dayspan, grad_half_dayspan)
            if daysleft < 0:  # CO
                color = self._get_color(3)
            elif daysleft <= reddays:  # CH
                color = self._get_color(2)
            elif daysleft <= (dayspan - grad_half_dayspan):
                # Gradient CN to CH
                # Has to be float so division by it is non-zero
                steps = float(grad_half_dayspan)
                step = grad_half_dayspan - (daysleft - reddays)
                color = self._get_gradient_color(self._get_color(1),
                                                 self._get_color(2),
                                                 step / steps)
            elif daysleft <= dayspan:
                # Gradient CL to CN
                steps = float(grad_half_dayspan)
                step = grad_half_dayspan - (daysleft -
                                            reddays - grad_half_dayspan)
                color = self._get_gradient_color(self._get_color(0),
                                                 self._get_color(1),
                                                 step / steps)

            return color

        # Insufficient data to determine urgency
        else:
            return None
Пример #30
0
 def __init__(self, gtk_builder):
     super(GTGCalendar, self).__init__()
     self.__builder = gtk_builder
     self.__date_kind = None
     self.__date = Date.no_date()
     self.__init_gtk__()
Пример #31
0
 def __init__(self, Gtk_builder):
     super(GTGCalendar, self).__init__()
     self.__builder = Gtk_builder
     self.__date_kind = None
     self.__date = Date.no_date()
     self.__init_gtk__()
Пример #32
0
    def populate_from_single_line_of_text(self, text, tags=[]):
        if tags:
            assert (isinstance(tags[0], str))

        # TODO: We expect one line, without tabs, so... a bit of paranoia for pasted text?

        # Reduce multiple spaces
        text = string.replace(text, '  ', ' ').strip()
        text = string.replace(text, '  ', ' ')

        if not text:
            print("populate_from_single_line_of_text: empty/whitespace")
            return

        due_date = Date.no_date()
        defer_date = Date.no_date()

        # Extract/remove tags from the title, but only if doing so would not make it empty.
        for match in extract_tags_from_text(text):
            tags.append(match)
            without_tag = string.replace(text, match, '')
            without_tag = string.replace(without_tag, '  ', ' ').strip()
            if without_tag:
                text = without_tag

        # Get key-value attributes of the form "key:value"
        regexp = r'([\s]*)([\w-]+):\s*([^\s]+)'
        matches = re.findall(regexp, text, re.UNICODE)
        for spaces, attribute, args in matches:
            valid_attribute = True
            if attribute.lower() in ["tags", _("tags"), "tag", _("tag")]:
                for tag in args.split(","):
                    if not tag.strip() == "@" and not tag.strip() == "":
                        if not tag.startswith("@"):
                            tag = "@" + tag
                        tags.append(tag)
            elif attribute.lower() in [
                    "defer", _("defer"), "start",
                    _("start")
            ]:
                try:
                    defer_date = Date.parse(args)
                except ValueError:
                    valid_attribute = False
            elif attribute.lower() == "due" or \
                    attribute.lower() == _("due"):
                try:
                    due_date = Date.parse(args)
                except:
                    valid_attribute = False
            else:
                # attribute is unknown
                valid_attribute = False

            if valid_attribute:
                # remove valid attribute from the task title
                text = \
                    text.replace("%s%s:%s" % (spaces, attribute, args), "")

        for t in tags:
            self.add_tag(t)

        if text != "":
            self.set_title(text.strip())
            self.set_to_keep()

        self.set_due_date(due_date)
        self.set_start_date(defer_date)
        self._has_been_modified()
Пример #33
0
 def get_days_late(self):
     due_date = self.get_due_date()
     if due_date == Date.no_date():
         return None
     closed_date = self.get_closed_date()
     return (closed_date - due_date).days
Пример #34
0
    def get_node_bgcolor(self, node):
        """ This method checks the urgency of a node (task) and returns its
         urgency background color"""
        sdate = node.get_start_date()
        ddate = node.get_due_date()
        daysleft = ddate.days_left()

        # Dates undefined (Fix to bug #1039655)
        if ddate == Date.today():
            return self._get_color(2)  # High urgency
        elif daysleft < 0 and ddate != Date.no_date():
            return self._get_color(3)  # Overdue
        elif (
            sdate == Date.no_date()  # Has no start date
            and ddate != Date.no_date()  # and a due date
            and not ddate.is_fuzzy()
        ):  # which is not fuzzy, is fixed
            return self._get_color(1)  # Normal

        # Fuzzy dates (now, soon, someday)
        # These can ignore the start date
        if ddate == Date.now():
            return self._get_color(2)
        elif ddate == Date.soon():
            return self._get_color(1)
        elif ddate == Date.someday():
            return self._get_color(0)

        # Dates fully defined. Calculate gradient color
        elif sdate != Date.no_date() != ddate:
            dayspan = (ddate - sdate).days
            redf = self._pref_data["reddays"]
            reddays = int(ceil(redf / 100.0 * dayspan))

            # Gradient variables
            grad_dayspan = dayspan - reddays
            grad_half_dayspan = grad_dayspan / 2.0

            # Default to low urgency color
            color = self._get_color(0)

            # CL : low urgency color
            # CN : normal urgency color
            # CH : high urgency color
            # CO : overdue color
            # To understand this section, it is easier to draw out a
            # timeline divided into 3 sections: CL to CN, CN to CH and
            # the reddays section. Then point out the spans of the
            # different variables (dayspan, daysleft, reddays,
            # grad_dayspan, grad_half_dayspan)
            if daysleft < 0:  # CO
                color = self._get_color(3)
            elif daysleft <= reddays:  # CH
                color = self._get_color(2)
            elif daysleft <= (dayspan - grad_half_dayspan):
                # Gradient CN to CH
                # Has to be float so division by it is non-zero
                steps = float(grad_half_dayspan)
                step = grad_half_dayspan - (daysleft - reddays)
                color = self._get_gradient_color(self._get_color(1), self._get_color(2), step / steps)
            elif daysleft <= dayspan:
                # Gradient CL to CN
                steps = float(grad_half_dayspan)
                step = grad_half_dayspan - (daysleft - reddays - grad_half_dayspan)
                color = self._get_gradient_color(self._get_color(0), self._get_color(1), step / steps)

            return color

        # Insufficient data to determine urgency
        else:
            return None
Пример #35
0
 def get_days_late(self):
     due_date = self.get_due_date()
     if due_date == Date.no_date():
         return None
     closed_date = self.get_closed_date()
     return (closed_date - due_date).days