Example #1
0
 def set_start_date(self, fulldate):
     self.start_date = Date(fulldate)
     if not Date(fulldate).is_fuzzy() and \
         not self.due_date.is_fuzzy() and \
             Date(fulldate) > self.due_date:
         self.set_due_date(fulldate)
     self.sync()
Example #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()
Example #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()
Example #4
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())
Example #5
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())
Example #6
0
    def date_changed(self, widget, data):
        try:
            if data == GTGCalendar.DATE_KIND_ENDON:
                if Date.parse(widget.get_text()):
                    if Date.parse(self.startdate_widget.get_text()).__gt__(
                        Date.parse(widget.get_text())):
                        valid = False
                    else:
                        valid = True
            else:
                Date.parse(widget.get_text())
                valid = True
        except ValueError:
            valid = False

        if valid:
            # If the date is valid, we write with default color in the widget
            # "none" will set the default color.
            widget.override_color(Gtk.StateType.NORMAL, None)
            widget.override_background_color(Gtk.StateType.NORMAL, None)
        else:
            #We should write in red in the entry if the date is not valid
            text_color = Gdk.RGBA()
            text_color.parse("#F00")
            widget.override_color(Gtk.StateType.NORMAL, text_color)

            bg_color = Gdk.RGBA()
            bg_color.parse("#F88")
            widget.override_background_color(Gtk.StateType.NORMAL, bg_color)
Example #7
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;
Example #8
0
    def set_due_date(self, new_duedate):
        """Defines the task's due date."""
        def __get_defined_parent_list(task):
            """Recursively fetch a list of parents that have a defined due date
               which is not fuzzy"""
            parent_list = []
            for par_id in task.parents:
                par = self.req.get_task(par_id)
                if par.get_due_date().is_fuzzy():
                    parent_list += __get_defined_parent_list(par)
                else:
                    parent_list.append(par)
            return parent_list

        def __get_defined_child_list(task):
            """Recursively fetch a list of children that have a defined
               due date which is not fuzzy"""
            child_list = []
            for child_id in task.children:
                child = self.req.get_task(child_id)
                if child.get_due_date().is_fuzzy():
                    child_list += __get_defined_child_list(child)
                else:
                    child_list.append(child)
            return child_list

        old_due_date = self.due_date
        new_duedate_obj = Date(new_duedate)  # caching the conversion
        self.due_date = new_duedate_obj
        # If the new date is fuzzy or undefined, we don't update related tasks
        if not new_duedate_obj.is_fuzzy():
            # if the task's start date happens later than the
            # new due date, we update it (except for fuzzy dates)
            if not self.get_start_date().is_fuzzy() and \
                    self.get_start_date() > new_duedate_obj:
                self.set_start_date(new_duedate)
            # if some ancestors' due dates happen before the task's new
            # due date, we update them (except for fuzzy dates)
            for par in __get_defined_parent_list(self):
                if par.get_due_date() < new_duedate_obj:
                    par.set_due_date(new_duedate)
            # we must apply the constraints to the defined & non-fuzzy children
            # as well
            for sub in __get_defined_child_list(self):
                sub_duedate = sub.get_due_date()
                # if the child's due date happens later than the task's: we
                # update it to the task's new due date
                if sub_duedate > new_duedate_obj:
                    sub.set_due_date(new_duedate)
                # if the child's start date happens later than
                # the task's new due date, we update it
                # (except for fuzzy start dates)
                sub_startdate = sub.get_start_date()
                if not sub_startdate.is_fuzzy() and \
                        sub_startdate > new_duedate_obj:
                    sub.set_start_date(new_duedate)
        # If the date changed, we notify the change for the children since the
        # constraints might have changed
        if old_due_date != new_duedate_obj:
            self.recursive_sync()
Example #9
0
def task_from_xml(task, xmlnode):
    # print "********************************"
    # print xmlnode.toprettyxml()

    task.set_uuid(xmlnode.getAttribute("uuid"))
    task.set_title(read_node(xmlnode, "title"))

    status = xmlnode.getAttribute("status")
    donedate = Date.parse(read_node(xmlnode, "donedate"))
    task.set_status(status, donedate=donedate)

    duedate = Date(read_node(xmlnode, "duedate"))
    task.set_due_date(duedate)

    startdate = Date(read_node(xmlnode, "startdate"))
    task.set_start_date(startdate)

    modified = read_node(xmlnode, "modified")
    if modified != "":
        modified = datetime.strptime(modified, "%Y-%m-%dT%H:%M:%S")
        task.set_modified(modified)

    tags = xmlnode.getAttribute("tags").replace(' ', '')
    tags = (tag for tag in tags.split(',') if tag.strip() != "")
    for tag in tags:
        # FIXME why unescape????
        task.tag_added(saxutils.unescape(tag))

    # FIXME why we need to convert that through an XML?
    content = read_node(xmlnode, "content")
    if content != "":
        content = "<content>%s</content>" % content
        content = minidom.parseString(content).firstChild.toxml()
        task.set_text(content)

    for subtask in xmlnode.getElementsByTagName("subtask"):
        task.add_child(get_text(subtask))

    for attr in xmlnode.getElementsByTagName("attribute"):
        if len(attr.childNodes) > 0:
            value = get_text(attr)
        else:
            value = ""
        key = attr.getAttribute("key")
        namespace = attr.getAttribute("namespace")
        task.set_attribute(key, value, namespace=namespace)

    # FIXME do we need remote task ids? I don't think so
    # FIXME if so => rework them into a more usable structure!!!
    #                (like attributes)
    # REMOTE TASK IDS
    remote_ids_list = xmlnode.getElementsByTagName("task-remote-ids")
    for remote_id in remote_ids_list:
        if remote_id.childNodes:
            node = remote_id.childNodes[0]
            backend_id = node.firstChild.nodeValue
            remote_task_id = node.childNodes[1].firstChild.nodeValue
            task.add_remote_id(backend_id, remote_task_id)

    return task
Example #10
0
 def test_parse_fuzzy_dates_str(self):
     """ Print fuzzy dates in localized version """
     self.assertEqual(str(Date.parse("now")), _("now"))
     self.assertEqual(str(Date.parse("soon")), _("soon"))
     self.assertEqual(str(Date.parse("later")), _("someday"))
     self.assertEqual(str(Date.parse("someday")), _("someday"))
     self.assertEqual(str(Date.parse("")), "")
Example #11
0
 def test_parse_fuzzy_dates_str(self):
     """ Print fuzzy dates in localized version """
     self.assertEqual(str(Date.parse("now")), _("now"))
     self.assertEqual(str(Date.parse("soon")), _("soon"))
     self.assertEqual(str(Date.parse("later")), _("someday"))
     self.assertEqual(str(Date.parse("someday")), _("someday"))
     self.assertEqual(str(Date.parse("")), "")
Example #12
0
    def set_due_date(self, new_duedate):
        """Defines the task's due date."""
        def __get_defined_parent_list(task):
            """Recursively fetch a list of parents that have a defined due date
               which is not fuzzy"""
            parent_list = []
            for par_id in task.parents:
                par = self.req.get_task(par_id)
                if par.get_due_date().is_fuzzy():
                    parent_list += __get_defined_parent_list(par)
                else:
                    parent_list.append(par)
            return parent_list

        def __get_defined_child_list(task):
            """Recursively fetch a list of children that have a defined
               due date which is not fuzzy"""
            child_list = []
            for child_id in task.children:
                child = self.req.get_task(child_id)
                if child.get_due_date().is_fuzzy():
                    child_list += __get_defined_child_list(child)
                else:
                    child_list.append(child)
            return child_list

        old_due_date = self.due_date
        new_duedate_obj = Date(new_duedate)  # caching the conversion
        self.due_date = new_duedate_obj
        # If the new date is fuzzy or undefined, we don't update related tasks
        if not new_duedate_obj.is_fuzzy():
            # if the task's start date happens later than the
            # new due date, we update it (except for fuzzy dates)
            if not self.get_start_date().is_fuzzy() and \
                    self.get_start_date() > new_duedate_obj:
                self.set_start_date(new_duedate)
            # if some ancestors' due dates happen before the task's new
            # due date, we update them (except for fuzzy dates)
            for par in __get_defined_parent_list(self):
                if par.get_due_date() < new_duedate_obj:
                    par.set_due_date(new_duedate)
            # we must apply the constraints to the defined & non-fuzzy children
            # as well
            for sub in __get_defined_child_list(self):
                sub_duedate = sub.get_due_date()
                # if the child's due date happens later than the task's: we
                # update it to the task's new due date
                if sub_duedate > new_duedate_obj:
                    sub.set_due_date(new_duedate)
                # if the child's start date happens later than
                # the task's new due date, we update it
                # (except for fuzzy start dates)
                sub_startdate = sub.get_start_date()
                if not sub_startdate.is_fuzzy() and \
                        sub_startdate > new_duedate_obj:
                    sub.set_start_date(new_duedate)
        # If the date changed, we notify the change for the children since the
        # constraints might have changed
        if old_due_date != new_duedate_obj:
            self.recursive_sync()
Example #13
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())
Example #14
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())
Example #15
0
 def get_fuzzy_date(self, current_due_date, due_date):
     #print "Current due_date = " + str(current_due_date)
     #print "New due date = " + str(Date(due_date).date())
     #print "FUzzy date in datetime = " + str(Date(current_due_date).date())
     if Date(current_due_date).date() == Date(due_date).date():
         #print "Both are same"
         return current_due_date
     return due_date
Example #16
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)
Example #17
0
    def test_parse_dates(self):
        """ Parse common numeric date """
        self.assertEqual(str(Date.parse("1985-03-29")), "1985-03-29")
        self.assertEqual(str(Date.parse("19850329")), "1985-03-29")
        self.assertEqual(str(Date.parse("1985/03/29")), "1985-03-29")

        today = date.today()
        parse_string = "%02d%02d" % (today.month, today.day)
        self.assertEqual(Date.parse(parse_string), today)
Example #18
0
File: editor.py Project: huxuan/gtg
    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('')
Example #19
0
 def set_start_date(self, fulldate):
     self.start_date = Date(fulldate)
     if not Date(fulldate).is_fuzzy() and \
         not self.due_date.is_fuzzy() and \
             Date(fulldate) > self.due_date:
         self.set_due_date(fulldate)
     else:
         # BUG: nervous
         self._has_been_modified()
     self.sync()
Example #20
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
Example #21
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
Example #22
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)
Example #23
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)
Example #24
0
 def __day_selected(self, widget, date_type):
     if date_type == "RealDate":
         calendar_date = self.__calendar.get_date()
         date = self.__from_calendar_date_to_datetime(calendar_date)
         self.__date = Date(date)
     else:
         self.__date = Date(date_type)
     # Hackish? Give time for:
     # (1) the user to see the date turn blue, and
     # (2) for *most* button-released events to cancel the calendar's in_drag mode
     # As a side-effect, any dragged dates might drop into the window...
     # but that's better than the aweful alternatives of:
     # (1) "since when & why am I dragging a document into the calendar", and
     # (2) "why did clicking on this date open the link that was under the date"
     gtk.timeout_add(500, self.__maybe_close_calendar)
Example #25
0
    def __day_selected(self, widget, date_type):
        if date_type == "RealDate":
            calendar_date = self.__calendar.get_date()
            date = self.__from_calendar_date_to_datetime(calendar_date)
            self.__date = Date(date)
        else:
            self.__date = Date(date_type)

        if self.__is_user_just_browsing_the_calendar:
            # this day-selected signal was caused by a month/year change
            self.__is_user_just_browsing_the_calendar = False
        else:
            # inform the Editor that the date has changed
            self.close_calendar()
            GObject.idle_add(self.emit, "date-changed")
Example #26
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()
Example #27
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
Example #28
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__()
Example #29
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__()
Example #30
0
def task_from_xml(task, xmlnode):
    # print "********************************"
    # print xmlnode.toprettyxml()

    task.set_uuid(xmlnode.getAttribute("uuid"))
    task.set_title(read_node(xmlnode, "title"))

    status = xmlnode.getAttribute("status")
    donedate = Date.parse(read_node(xmlnode, "donedate"))
    task.set_status(status, donedate=donedate)

    duedate = Date(read_node(xmlnode, "duedate"))
    task.set_due_date(duedate)

    startdate = Date(read_node(xmlnode, "startdate"))
    task.set_start_date(startdate)

    modified = read_node(xmlnode, "modified")
    if modified != "":
        modified = datetime.strptime(modified, "%Y-%m-%dT%H:%M:%S")
        task.set_modified(modified)

    tags = xmlnode.getAttribute("tags").replace(" ", "")
    tags = (tag for tag in tags.split(",") if tag.strip() != "")
    for tag in tags:
        # FIXME why unescape????
        task.tag_added(saxutils.unescape(tag))

    # FIXME why we need to convert that through an XML?
    content = read_node(xmlnode, "content")
    if content != "":
        content = "<content>%s</content>" % content
        content = minidom.parseString(content).firstChild.toxml()
        task.set_text(content)

    for subtask in xmlnode.getElementsByTagName("subtask"):
        task.add_child(get_text(subtask))

    for attr in xmlnode.getElementsByTagName("attribute"):
        if len(attr.childNodes) > 0:
            value = get_text(attr)
        else:
            value = ""
        key = attr.getAttribute("key")
        namespace = attr.getAttribute("namespace")
        task.set_attribute(key, value, namespace=namespace)

    # FIXME do we need remote task ids? I don't think so
    # FIXME if so => rework them into a more usable structure!!!
    #                (like attributes)
    # REMOTE TASK IDS
    remote_ids_list = xmlnode.getElementsByTagName("task-remote-ids")
    for remote_id in remote_ids_list:
        if remote_id.childNodes:
            node = remote_id.childNodes[0]
            backend_id = node.firstChild.nodeValue
            remote_task_id = node.childNodes[1].firstChild.nodeValue
            task.add_remote_id(backend_id, remote_task_id)

    return task
Example #31
0
    def date_changed(self, widget, data):
        try:
            Date.parse(widget.get_text())
            valid = True
        except ValueError:
            valid = False

        if valid:
            # If the date is valid, we write with default color in the widget
            # "none" will set the default color.
            widget.modify_text(gtk.STATE_NORMAL, None)
            widget.modify_base(gtk.STATE_NORMAL, None)
        else:
            # We should write in red in the entry if the date is not valid
            widget.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("#F00"))
            widget.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("#F88"))
Example #32
0
 def workview(self, task, parameters=None):
     wv = (self.active(task) and
           self.is_started(task) and
           self.is_workable(task) and
           self.no_disabled_tag(task) and
           task.get_due_date() != Date.someday())
     return wv
Example #33
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
Example #34
0
 def workview(self, task, parameters=None):
     wv = (self.active(task) and
           self.is_started(task) and
           self.is_workable(task) and
           self.no_disabled_tag(task) and
           task.get_due_date() != Date.someday())
     return wv
Example #35
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()
Example #36
0
    def date_changed(self, widget, data):
        try:
            Date.parse(widget.get_text())
            valid = True
        except ValueError:
            valid = False

        if valid:
            # If the date is valid, we write with default color in the widget
            # "none" will set the default color.
            widget.modify_text(gtk.STATE_NORMAL, None)
            widget.modify_base(gtk.STATE_NORMAL, None)
        else:
            # We should write in red in the entry if the date is not valid
            widget.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse("#F00"))
            widget.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("#F88"))
Example #37
0
 def refresh_date_field(self, date, field):
     try:
         prevdate = Date.parse(field.get_text())
         update_date = date != prevdate
     except ValueError:
         update_date = True
     if update_date:
         field.set_text(str(date))
Example #38
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)
Example #39
0
    def local_update_task(self, remote_task, local_task):
        """
        "Local Update" implementation.
        """
        #print "Updating local task started ..."
        local_task.set_title(_(remote_task["name"]))
        local_task.set_text(_(remote_task["description"]))

        #print "Task Status = " + str(remote_task["status"])
        status = self.WEB_STATUS_TO_GTG.get(remote_task["status"], 'Active')
        local_task.set_status(status)

        start_date = self.str_to_datetime(remote_task["start_date"], \
                                        return_date = True, without_time = True)
        due_date = self.str_to_datetime(remote_task["due_date"], \
                                        return_date = True, without_time = True)

        local_task.set_start_date(Date(start_date))

        current_due_date = local_task.get_due_date()
        if current_due_date.is_fuzzy():
            #print "Local task,= " + local_task.get_title() + " due date is FUZZY"
            due_date = self.get_fuzzy_date(current_due_date, due_date)

        local_task.set_due_date(Date(due_date))
        new_tags = set(['@' + tag["name"] for tag in remote_task["tags"]])
        #print "new_tags = " + str(new_tags)
        current_tags = set(local_task.get_tags_name())
        # remove the lost tags
        for tag in current_tags.difference(new_tags):
            local_task.remove_tag(tag)
        # add the new ones
        for tag in new_tags.difference(current_tags):
            local_task.add_tag(tag)

        #if local_task.get_remote_ids().get(self.get_id(), None) == None:
        #local_task.add_remote_id(self.get_id(), remote_task["id"])

        if len(local_task.get_subtasks()) != len(remote_task["subtasks"]):
            local_task = self.add_subtasks_from_remote(local_task, \
                                                        remote_task)

        #print "Before returning, local_task = " + str(local_task)
        return local_task
Example #40
0
    def set_endon_date(self, new_endondate):
        def __get_defined_parent_list(task):
            """Recursively fetch a list of parents that have a defined due date
               which is not fuzzy"""
            parent_list = []
            for par_id in task.parents:
                par = self.req.get_task(par_id)
                if par.get_due_date().is_fuzzy():
                    parent_list += __get_defined_parent_list(par)
                else:
                    parent_list.append(par)
            return parent_list

        def __get_defined_child_list(task):
            """Recursively fetch a list of children that have a defined
               due date which is not fuzzy"""
            child_list = []
            for child_id in task.children:
                child = self.req.get_task(child_id)
                if child.get_due_date().is_fuzzy():
                    child_list += __get_defined_child_list(child)
                else:
                    child_list.append(child)
            return child_list

        old_endon_date = self.endon_date
        new_endondate_obj = Date(new_endondate)
        self.endon_date = new_endondate_obj
        if not new_endondate_obj.is_fuzzy():
            # if the task's start date happens later than the
            # new endon date, we update it (except for fuzzy dates)
            #We should show it in red. 
            # we must apply the constraints to the defined & non-fuzzy children
            # as well
            for sub in __get_defined_child_list(self):
                sub_duedate = sub.get_due_date()
                # if the child's start date happens later than
                # the task's new endon date, we update it
                # (except for fuzzy start dates)
                #We should show it in red.
        # If the date changed, we notify the change for the children since the
        # constraints might have changed
        if old_endon_date != new_endondate_obj:
            self.recursive_sync()
Example #41
0
    def test_missing_year_next_year(self):
        """ Parsing %m%d have to find correct date:
        we enter a day the next year """
        aday = date.today()
        if aday.day == 1 and aday.month == 1:
            # not possible to add a day next year
            return

        aday = aday.replace(year=aday.year + 1, month=1, day=1)
        self.assertEqual(Date.parse("0101"), aday)
Example #42
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
Example #43
0
 def calculate_new_due_date(self):
     if self.repeats == "Daily":
         if int(self.frequency) == 0:
             return self.get_due_date() + \
                 timedelta(days=1)
         else:
             return self.get_due_date() + \
                 timedelta(days=int(self.frequency))
     elif self.repeats == "Weekly":
         current_date = self.get_current_date()
         rule_tupple = self.create_weekdayrule_tuple()
         if int(self.frequency) == 0 or int(self.frequency) == 1:
             new_date = list(rrule.rrule(rrule.WEEKLY, count=1,
                 wkst=current_date.weekday(),
                 byweekday=rule_tupple,
                 dtstart=datetime(
                 self.due_date.year,self.due_date.month,self.due_date.day+1)))[0]
             return Date.parse(
                 str(new_date.year)+str(new_date.month)+str(new_date.day))
         else:
             new_date = list(rrule.rrule(rrule.WEEKLY,
                 interval=int(self.frequency),count=1,
                 wkst=current_date.weekday(),
                 byweekday=rule_tupple,
                 dtstart=datetime(
                 self.due_date.year,self.due_date.month,self.due_date.day+1)))[0]
             return Date.parse(
                 str(new_date.year)+str(new_date.month)+str(new_date.day))
     elif self.repeats == "Monthly":
         if int(self.frequency) == 0 or int(self.frequency) == 1:
             new_date = self.get_monthly_due_date(1)
             return Date.parse(
                 str(new_date.year)+str(new_date.month)+str(new_date.day))
         else:
             new_date = self.get_monthly_due_date(int(self.frequency))
             return Date.parse(
                 str(new_date.year)+str(new_date.month)+str(new_date.day))
     elif self.repeats == "Yearly":
         if int(self.frequency) == 0:
             return self.add_months(self.due_date(), 12)
         else:
             return self.add_months(
                 self.get_due_date(), 12 * int(self.frequency))
Example #44
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
Example #45
0
    def test_missing_year_next_year(self):
        """ Parsing %m%d have to find correct date:
        we enter a day the next year """
        aday = date.today()
        if aday.day == 1 and aday.month == 1:
            # not possible to add a day next year
            return

        aday = aday.replace(year=aday.year + 1, month=1, day=1)
        self.assertEqual(Date.parse("0101"), aday)
Example #46
0
    def date_changed(self, widget, data):
        try:
            Date.parse(widget.get_text())
            valid = True
        except ValueError:
            valid = False

        if valid:
            # If the date is valid, we write with default color in the widget
            # "none" will set the default color.
            widget.override_color(Gtk.StateType.NORMAL, None)
            widget.override_background_color(Gtk.StateType.NORMAL, None)
        else:
            # We should write in red in the entry if the date is not valid
            text_color = Gdk.RGBA()
            text_color.parse("#F00")
            widget.override_color(Gtk.StateType.NORMAL, text_color)

            bg_color = Gdk.RGBA()
            bg_color.parse("#F88")
            widget.override_background_color(Gtk.StateType.NORMAL, bg_color)
Example #47
0
    def test_on_certain_day(self):
        """ Parse due:3 as 3rd day this month or next month
        if it is already more or already 3rd day """
        for i in range(28):
            i += 1
            aday = date.today()
            if i <= aday.day:
                aday = next_month(aday, i)
            else:
                aday = aday.replace(day=i)

            self.assertEqual(Date.parse(str(i)), aday)
Example #48
0
    def test_on_certain_day(self):
        """ Parse due:3 as 3rd day this month or next month
        if it is already more or already 3rd day """
        for i in range(28):
            i += 1
            aday = date.today()
            if i <= aday.day:
                aday = next_month(aday, i)
            else:
                aday = aday.replace(day=i)

            self.assertEqual(Date.parse(str(i)), aday)
Example #49
0
    def ModifyTask(self, tid, task_data):
        """
        Updates the task with ID tid using the provided information
        in the task_data structure.  Note that any fields left blank
        or undefined in task_data will clear the value in the task,
        so the best way to update a task is to first retrieve it via
        get_task(tid), modify entries as desired, and send it back
        via this function.
        """
        task = self.req.get_task(tid)
        task.set_status(task_data["status"],
                        donedate=Date.parse(task_data["donedate"]))
        task.set_title(task_data["title"])
        task.set_due_date(Date.parse(task_data["duedate"]))
        task.set_start_date(Date.parse(task_data["startdate"]))
        task.set_text(task_data["text"])

        for tag in task_data["tags"]:
            task.add_tag(tag)
        for sub in task_data["subtask"]:
            task.add_child(sub)
        return task_to_dict(task)
Example #50
0
    def ModifyTask(self, tid, task_data):
        """
        Updates the task with ID tid using the provided information
        in the task_data structure.  Note that any fields left blank
        or undefined in task_data will clear the value in the task,
        so the best way to update a task is to first retrieve it via
        get_task(tid), modify entries as desired, and send it back
        via this function.
        """
        task = self.req.get_task(tid)
        task.set_status(task_data["status"],
                        donedate=Date.parse(task_data["donedate"]))
        task.set_title(task_data["title"])
        task.set_due_date(Date.parse(task_data["duedate"]))
        task.set_start_date(Date.parse(task_data["startdate"]))
        task.set_text(task_data["text"])

        for tag in task_data["tags"]:
            task.add_tag(tag)
        for sub in task_data["subtask"]:
            task.add_child(sub)
        return task_to_dict(task)
Example #51
0
    def date_focus_out(self, widget, event, date_kind):
        try:
            datetoset = Date.parse(widget.get_text())
        except ValueError:
            datetoset = None

        if datetoset is not None:
            if date_kind == GTGCalendar.DATE_KIND_START:
                self.task.set_start_date(datetoset)
            elif date_kind == GTGCalendar.DATE_KIND_DUE:
                self.task.set_due_date(datetoset)
            elif date_kind == GTGCalendar.DATE_KIND_CLOSED:
                self.task.set_closed_date(datetoset)
            self.refresh_editor()
Example #52
0
    def __date_from_evo_to_gtg(self, evo_date_timestamp):
        """
        Converts an evolution date object into the format understood by GTG

        @param evo_date: an int, which represent time from epoch in UTC
                        convention
        """
        evo_datetime = datetime.datetime.fromtimestamp(evo_date_timestamp)
        # See self.__date_from_gtg_to_evo for an explanation
        evo_datetime = evo_datetime.replace(tzinfo=tzlocal())
        gtg_datetime = evo_datetime.astimezone(tzutc())
        # we strip timezone infos, as they're not used or expected in GTG
        gtg_datetime.replace(tzinfo=None)
        return Date(gtg_datetime.date())
Example #53
0
    def date_focus_out(self, widget, event, data):
        try:
            datetoset = Date.parse(widget.get_text())
        except ValueError:
            datetoset = None

        if datetoset is not None:
            if data == "start":
                self.task.set_start_date(datetoset)
            elif data == "due":
                self.task.set_due_date(datetoset)
            elif data == "closed":
                self.task.set_closed_date(datetoset)
            self.refresh_editor()
Example #54
0
    def date_focus_out(self, widget, event, data):
        try:
            datetoset = Date.parse(widget.get_text())
        except ValueError:
            datetoset = None

        if datetoset is not None:
            if data == "start":
                self.task.set_start_date(datetoset)
            elif data == "due":
                self.task.set_due_date(datetoset)
            elif data == "closed":
                self.task.set_closed_date(datetoset)
            self.refresh_editor()
Example #55
0
 def NewTask(self, status, title, duedate, startdate, donedate, tags,
             text, subtasks):
     """
     Generate a new task object and return the task data as a dict
     @param status:     One of 'Active', 'Dismiss', or 'Done'
     @param title:      String name of the task
     @param duedate:    Date the task is due, such as "2010-05-01".
      also supports 'now', 'soon', 'someday'
     @param startdate:  Date the task will be started
     @param donedate:   Date the task was finished
     @param tags:       List of strings for tags to apply for this task
     @param text:       String description
     @param subtasks:   A list of task ids of tasks to add as children
     @return: A dictionary with the data of the newly created task
     """
     nt = self.req.new_task(tags=tags)
     for sub in subtasks:
         nt.add_child(sub)
     nt.set_status(status, donedate=Date.parse(donedate))
     nt.set_title(title)
     nt.set_due_date(Date.parse(duedate))
     nt.set_start_date(Date.parse(startdate))
     nt.set_text(text)
     return task_to_dict(nt)
Example #56
0
 def set_date(self, date, date_kind):
     self.__date_kind = date_kind
     if date_kind == GTGCalendar.DATE_KIND_DUE:
         self.__fuzzydate_btns.show()
     else:
         self.__fuzzydate_btns.hide()
     if not date:
         # we set the widget to today's date if there is not a date defined
         date = Date.today()
     self.__date = date
     if not date.is_fuzzy():
         self.__calendar.select_day(date.day)
         # Calendar use 0..11 for a month so we need -1
         # We can't use conversion through python's datetime
         # because it is often an invalid date
         self.__calendar.select_month(date.month - 1, date.year)
Example #57
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)
Example #58
0
    def delete_old_closed_tasks(self, widget=None):
        self.__log("Starting deletion of old tasks")
        today = Date.today()
        max_days = self.preferences["max_days"]
        requester = self.plugin_api.get_requester()
        closed_tree = requester.get_tasks_tree(name='inactive')
        closed_tasks = [requester.get_task(tid) for tid in
                        closed_tree.get_all_nodes()]
        to_remove = [t for t in closed_tasks
                     if (today - t.get_closed_date()).days > max_days]

        for task in to_remove:
            if requester.has_task(task.get_id()):
                requester.delete_task(task.get_id())

        # If automatic purging is on, schedule another run
        if self.is_automatic:
            self.schedule_autopurge()
Example #59
0
 def get_monthly_due_date(self, interval):
     onthe = self.get_onthe_index()
     ondayD = {"Monday":rrule.MO, "Tuesday":rrule.TU, "Wednesday":rrule.WE,
         "Thursday":rrule.TH, "Friday":rrule.FR, "Saturday":rrule.SA,
         "Sunday":rrule.SU}
     new_date = list(rrule.rrule(
     rrule.MONTHLY, interval=interval,
     count=1, byweekday=ondayD[self.onday](onthe), dtstart=datetime(
     self.due_date.year,self.due_date.month,self.due_date.day)))[0]
     date = Date.parse(
         str(new_date.year)+str(new_date.month)+str(new_date.day))
     if date.__eq__(self.due_date):
         return list(rrule.rrule(
         rrule.MONTHLY, interval=interval,
         count=1, byweekday=ondayD[self.onday](onthe), dtstart=datetime(
         self.due_date.year,self.due_date.month,self.due_date.day+1)))[0]
     else:
         return new_date