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()
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()
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()
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())
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())
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)
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;
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()
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
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("")), "")
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
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)
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)
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('')
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()
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
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)
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)
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)
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")
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()
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
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__()
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__()
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
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"))
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
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))
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
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()
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)
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
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))
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)
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)
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)
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()
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())
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()
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)
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)
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)
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()
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