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 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 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 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 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 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 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 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 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 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 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 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 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 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_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 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
def test_parse_week_days(self): """ Parse name of week days and don't care about case-sensitivity """ weekday = date.today().weekday() for i, day in enumerate(["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]): if i <= weekday: expected = date.today() + timedelta(7 + i - weekday) else: expected = date.today() + timedelta(i - weekday) self.assertEqual(Date.parse(day), expected) self.assertEqual(Date.parse(day.lower()), expected) self.assertEqual(Date.parse(day.upper()), expected) # Test localized version day = _(day) self.assertEqual(Date.parse(day), expected) self.assertEqual(Date.parse(day.lower()), expected) self.assertEqual(Date.parse(day.upper()), expected)
def test_parse_week_days(self): """ Parse name of week days and don't care about case-sensitivity """ weekday = date.today().weekday() for i, day in enumerate(['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']): if i <= weekday: expected = date.today() + timedelta(7 + i - weekday) else: expected = date.today() + timedelta(i - weekday) self.assertEqual(Date.parse(day), expected) self.assertEqual(Date.parse(day.lower()), expected) self.assertEqual(Date.parse(day.upper()), expected) # Test localized version day = _(day) self.assertEqual(Date.parse(day), expected) self.assertEqual(Date.parse(day.lower()), expected) self.assertEqual(Date.parse(day.upper()), expected)
def test_missing_year_this_year(self): """ Parsing %m%d have to find correct date: we enter a day this year """ aday = next_month(date.today(), day=1) parse_string = "%02d%02d" % (aday.month, aday.day) self.assertEqual(Date.parse(parse_string), aday)
def refresh_editor(self, title=None, refreshtext=False): if self.window is None: return to_save = False # title of the window if title: self.window.set_title(title) to_save = True else: self.window.set_title(self.task.get_title()) status = self.task.get_status() dismiss_tooltip = GnomeConfig.MARK_DISMISS_TOOLTIP undismiss_tooltip = GnomeConfig.MARK_UNDISMISS_TOOLTIP if status == Task.STA_DISMISSED: self.donebutton.set_label(GnomeConfig.MARK_DONE) self.donebutton.set_tooltip_text(GnomeConfig.MARK_DONE_TOOLTIP) self.donebutton.set_icon_name("gtg-task-done") self.dismissbutton.set_label(GnomeConfig.MARK_UNDISMISS) self.dismissbutton.set_tooltip_text(undismiss_tooltip) self.dismissbutton.set_icon_name("gtg-task-undismiss") elif status == Task.STA_DONE: self.donebutton.set_label(GnomeConfig.MARK_UNDONE) self.donebutton.set_tooltip_text(GnomeConfig.MARK_UNDONE_TOOLTIP) self.donebutton.set_icon_name("gtg-task-undone") self.dismissbutton.set_label(GnomeConfig.MARK_DISMISS) self.dismissbutton.set_tooltip_text(dismiss_tooltip) self.dismissbutton.set_icon_name("gtg-task-dismiss") else: self.donebutton.set_label(GnomeConfig.MARK_DONE) self.donebutton.set_tooltip_text(GnomeConfig.MARK_DONE_TOOLTIP) self.donebutton.set_icon_name("gtg-task-done") self.dismissbutton.set_label(GnomeConfig.MARK_DISMISS) self.dismissbutton.set_tooltip_text(dismiss_tooltip) self.dismissbutton.set_icon_name("gtg-task-dismiss") self.donebutton.show() self.tasksidebar.show() # Refreshing the status bar labels and date boxes if status in [Task.STA_DISMISSED, Task.STA_DONE]: self.builder.get_object("label2").hide() self.builder.get_object("box1").hide() self.builder.get_object("label4").show() self.builder.get_object("box4").show() else: self.builder.get_object("label4").hide() self.builder.get_object("box4").hide() self.builder.get_object("label2").show() self.builder.get_object("box1").show() # refreshing the start date field startdate = self.task.get_start_date() try: prevdate = Date.parse(self.startdate_widget.get_text()) update_date = startdate != prevdate except ValueError: update_date = True if update_date: self.startdate_widget.set_text(str(startdate)) # refreshing the due date field duedate = self.task.get_due_date() try: prevdate = Date.parse(self.duedate_widget.get_text()) update_date = duedate != prevdate except ValueError: update_date = True if update_date: self.duedate_widget.set_text(str(duedate)) # refreshing the closed date field closeddate = self.task.get_closed_date() prevcldate = Date.parse(self.closeddate_widget.get_text()) if closeddate != prevcldate: self.closeddate_widget.set_text(str(closeddate)) # refreshing the day left label # If the task is marked as done, we display the delay between the # due date and the actual closing date. If the task isn't marked # as done, we display the number of days left. if status in [Task.STA_DISMISSED, Task.STA_DONE]: delay = self.task.get_days_late() if delay is None: txt = "" elif delay == 0: txt = "Completed on time" elif delay >= 1: txt = ngettext("Completed %(days)d day late", "Completed %(days)d days late", delay) % \ {'days': delay} elif delay <= -1: abs_delay = abs(delay) txt = ngettext("Completed %(days)d day early", "Completed %(days)d days early", abs_delay) % \ {'days': abs_delay} else: due_date = self.task.get_due_date() result = due_date.days_left() if due_date.is_fuzzy(): txt = "" elif result > 0: txt = ngettext("Due tomorrow!", "%(days)d days left", result) \ % {'days': result} elif result == 0: txt = _("Due today!") elif result < 0: abs_result = abs(result) txt = ngettext("Due yesterday!", "Was %(days)d days ago", abs_result) % {'days': abs_result} style_context = self.window.get_style_context() color = style_context.get_color(Gtk.StateFlags.INSENSITIVE).to_color() self.dayleft_label.set_markup( "<span color='%s'>%s</span>" % (color.to_string(), txt)) # Refreshing the tag list in the insert tag button taglist = self.req.get_used_tags() menu = Gtk.Menu() tag_count = 0 for tagname in taglist: tag_object = self.req.get_tag(tagname) if not tag_object.is_special() and \ not self.task.has_tags(tag_list=[tagname]): tag_count += 1 mi = Gtk.MenuItem(label=tagname, use_underline=False) mi.connect("activate", self.inserttag, tagname) mi.show() menu.append(mi) if tag_count > 0: self.inserttag_button.set_menu(menu) # Refreshing the parent list in open_parent_button menu = Gtk.Menu() parents = self.task.get_parents() if len(parents) > 0: for parent in self.task.get_parents(): task = self.req.get_task(parent) mi = Gtk.MenuItem(label=task.get_title(), use_underline=False) mi.connect("activate", self.open_parent, parent) mi.show() menu.append(mi) self.open_parents_button.set_menu(menu) else: self.open_parents_button.set_sensitive(False) if refreshtext: self.textview.modified(refresheditor=False) if to_save: self.light_save()
def test_parses_common_formats(self): 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")
def add_months(self, sourcedate, months): month = sourcedate.month - 1 + months year = int(sourcedate.year + month / 12) month = month % 12 + 1 day = min(sourcedate.day,calendar.monthrange(year,month)[1]) return Date.parse(str(year)+str(month)+str(day))
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()
def test_parses_todays_month_day_format(self): today = date.today() parse_string = "%02d%02d" % (today.month, today.day) self.assertEqual(Date.parse(parse_string), today)
def refresh_editor(self, title=None, refreshtext=False): if self.window is None: return to_save = False # title of the window if title: self.window.set_title(title) to_save = True else: self.window.set_title(self.task.get_title()) status = self.task.get_status() dismiss_tooltip = GnomeConfig.MARK_UNDISMISS_TOOLTIP if status == Task.STA_DISMISSED: self.donebutton.set_label(GnomeConfig.MARK_DONE) self.donebutton.set_tooltip_text(GnomeConfig.MARK_DONE_TOOLTIP) self.donebutton.set_icon_name("gtg-task-done") self.dismissbutton.set_label(GnomeConfig.MARK_UNDISMISS) self.dismissbutton.set_tooltip_text(dismiss_tooltip) self.dismissbutton.set_icon_name("gtg-task-undismiss") elif status == Task.STA_DONE: self.donebutton.set_label(GnomeConfig.MARK_UNDONE) self.donebutton.set_tooltip_text(GnomeConfig.MARK_UNDONE_TOOLTIP) self.donebutton.set_icon_name("gtg-task-undone") self.dismissbutton.set_label(GnomeConfig.MARK_DISMISS) self.dismissbutton.set_tooltip_text(dismiss_tooltip) self.dismissbutton.set_icon_name("gtg-task-dismiss") else: self.donebutton.set_label(GnomeConfig.MARK_DONE) self.donebutton.set_tooltip_text(GnomeConfig.MARK_DONE_TOOLTIP) self.donebutton.set_icon_name("gtg-task-done") self.dismissbutton.set_label(GnomeConfig.MARK_DISMISS) self.dismissbutton.set_tooltip_text(dismiss_tooltip) self.dismissbutton.set_icon_name("gtg-task-dismiss") self.donebutton.show() self.tasksidebar.show() # Refreshing the status bar labels and date boxes if status in [Task.STA_DISMISSED, Task.STA_DONE]: self.builder.get_object("label2").hide() self.builder.get_object("hbox1").hide() self.builder.get_object("label4").show() self.builder.get_object("hbox4").show() else: self.builder.get_object("label4").hide() self.builder.get_object("hbox4").hide() self.builder.get_object("label2").show() self.builder.get_object("hbox1").show() # refreshing the start date field startdate = self.task.get_start_date() try: prevdate = Date.parse(self.startdate_widget.get_text()) update_date = startdate != prevdate except ValueError: update_date = True if update_date: self.startdate_widget.set_text(str(startdate)) # refreshing the due date field duedate = self.task.get_due_date() try: prevdate = Date.parse(self.duedate_widget.get_text()) update_date = duedate != prevdate except ValueError: update_date = True if update_date: self.duedate_widget.set_text(str(duedate)) # refreshing the closed date field closeddate = self.task.get_closed_date() prevcldate = Date.parse(self.closeddate_widget.get_text()) if closeddate != prevcldate: self.closeddate_widget.set_text(str(closeddate)) # refreshing the day left label # If the task is marked as done, we display the delay between the # due date and the actual closing date. If the task isn't marked # as done, we display the number of days left. if status in [Task.STA_DISMISSED, Task.STA_DONE]: delay = self.task.get_days_late() if delay is None: txt = "" elif delay == 0: txt = "Completed on time" elif delay >= 1: txt = ngettext("Completed %(days)d day late", "Completed %(days)d days late", delay) % \ {'days': delay} elif delay <= -1: abs_delay = abs(delay) txt = ngettext("Completed %(days)d day early", "Completed %(days)d days early", abs_delay) % \ {'days': abs_delay} else: due_date = self.task.get_due_date() result = due_date.days_left() if due_date.is_fuzzy(): txt = "" elif result > 0: txt = ngettext("Due tomorrow!", "%(days)d days left", result) \ % {'days': result} elif result == 0: txt = _("Due today!") elif result < 0: abs_result = abs(result) txt = ngettext("Due yesterday!", "Was %(days)d days ago", abs_result) % { 'days': abs_result } window_style = self.window.get_style() color = str(window_style.text[gtk.STATE_INSENSITIVE]) self.dayleft_label.set_markup("<span color='" + color + "'>" + txt + "</span>") # Refreshing the tag list in the insert tag button taglist = self.req.get_used_tags() menu = gtk.Menu() tag_count = 0 for tagname in taglist: tag_object = self.req.get_tag(tagname) if not tag_object.is_special() and \ not self.task.has_tags(tag_list=[tagname]): tag_count += 1 mi = gtk.MenuItem(label=tagname, use_underline=False) mi.connect("activate", self.inserttag, tagname) mi.show() menu.append(mi) if tag_count > 0: self.inserttag_button.set_menu(menu) if refreshtext: self.textview.modified(refresheditor=False) if to_save: self.light_save()
def parse_search_query(query): """ Parse query into parameters for search filter If query is not correct, exception InvalidQuery is raised. """ if len(query.strip()) == 0: raise InvalidQuery("Query is empty") if query.count('"') % 2 != 0: raise InvalidQuery("Query has odd number of quotes") commands = [] not_count, after_or = 0, False require_date = None for token, value in _tokenize_query(query): cmd = None if require_date: if token not in ['date', 'word', 'literal']: raise InvalidQuery("Unexpected token '%s' after '%s'" % ( token, require_date)) value = value.strip('"') try: date = Date.parse(value) except ValueError: raise InvalidQuery("Date '%s' in wrong format" % (value)) cmd = (require_date, not_count % 2 == 0, date) require_date = None elif token == 'command': value = value.lower()[1:] found = False for keyword in KEYWORDS: if value not in KEYWORDS[keyword]: continue if keyword == 'not': not_count += 1 elif keyword == 'or': if not_count > 0: raise InvalidQuery("!or cann't follow !not") if commands == []: raise InvalidQuery( "Or is not allowed at the beginning of query") if commands[-1][0] != "or": commands.append(("or", True, [commands.pop()])) after_or = True elif keyword in ['after', 'before']: require_date = keyword else: cmd = (keyword, not_count % 2 == 0) found = True break if not found: raise InvalidQuery("Unknown command !%s" % value) elif token == 'tag': cmd = (token, not_count % 2 == 0, value) elif token in ['literal', 'word']: cmd = ('word', not_count % 2 == 0, value.strip('"').lower()) if cmd is not None: if after_or: commands[-1][2].append(cmd) else: commands.append(cmd) not_count, after_or = 0, False if not_count > 0: raise InvalidQuery("Query cannot end with !not (Forgot something?)") if after_or: raise InvalidQuery("Or is not allowed at the end of query") if require_date: raise InvalidQuery("Required date after '%s'" % require_date) return {'q': commands}
def __init__(self, title="", body="", tags=[], due_date=""): self.title = title self.body = body self.tags = tags self.due_date = Date.parse(due_date)
def mark_next_week(self, button): start_date = Date.parse("+7d") for tid in self.plugin_api.get_selected(): task = self.req.get_task(tid) task.set_start_date(start_date)
def task_cb2(self, widget, plugin_api, task): start_date = Date.parse("+7d") task.set_start_date(start_date) plugin_api.get_view_manager().close_task(task.get_id())
def refresh_editor(self, title=None, refreshtext=False): if self.window is None: return to_save = False # title of the window if title: self.window.set_title(title) to_save = True else: self.window.set_title(self.task.get_title()) status = self.task.get_status() if status == Task.STA_DISMISSED: self.donebutton.show() self.undonebutton.hide() self.dismissbutton.hide() self.undismissbutton.show() elif status == Task.STA_DONE: self.donebutton.hide() self.undonebutton.show() self.dismissbutton.show() self.undismissbutton.hide else: self.donebutton.show() self.undonebutton.hide() self.dismissbutton.show() self.undismissbutton.hide() # Refreshing the the parent button has_parents = len(self.task.get_parents()) > 0 self.parent_button.set_sensitive(has_parents) # Refreshing the status bar labels and date boxes if status in [Task.STA_DISMISSED, Task.STA_DONE]: self.builder.get_object("start_box").hide() self.builder.get_object("closed_box").show() else: self.builder.get_object("closed_box").hide() self.builder.get_object("start_box").show() # refreshing the start date field startdate = self.task.get_start_date() try: prevdate = Date.parse(self.startdate_widget.get_text()) update_date = startdate != prevdate except ValueError: update_date = True if update_date: self.startdate_widget.set_text(str(startdate)) # refreshing the due date field duedate = self.task.get_due_date() try: prevdate = Date.parse(self.duedate_widget.get_text()) update_date = duedate != prevdate except ValueError: update_date = True if update_date: self.duedate_widget.set_text(str(duedate)) # refreshing the closed date field closeddate = self.task.get_closed_date() prevcldate = Date.parse(self.closeddate_widget.get_text()) if closeddate != prevcldate: self.closeddate_widget.set_text(str(closeddate)) # refreshing the day left label ''' TODO(jakubbrindza): re-enable refreshing the day left. We need to come up how and where this information is viewed in the editor window. ''' # self.refresh_day_left() if refreshtext: self.textview.modified(refresheditor=False) if to_save: self.light_save()
def parse_search_query(query): """ Parse query into parameters for search filter If query is not correct, exception InvalidQuery is raised. """ if len(query.strip()) == 0: raise InvalidQuery("Query is empty") if query.count('"') % 2 != 0: raise InvalidQuery("Query has odd number of quotes") commands = [] not_count, after_or = 0, False require_date = None for token, value in _tokenize_query(query): cmd = None if require_date: if token not in ['date', 'word', 'literal']: raise InvalidQuery("Unexpected token '%s' after '%s'" % (token, require_date)) value = value.strip('"') try: date = Date.parse(value) except ValueError: raise InvalidQuery("Date '%s' in wrong format" % (value)) cmd = (require_date, not_count % 2 == 0, date) require_date = None elif token == 'command': value = value.lower()[1:] found = False for keyword in KEYWORDS: if value not in KEYWORDS[keyword]: continue if keyword == 'not': not_count += 1 elif keyword == 'or': if not_count > 0: raise InvalidQuery("!or cann't follow !not") if commands == []: raise InvalidQuery( "Or is not allowed at the beginning of query") if commands[-1][0] != "or": commands.append(("or", True, [commands.pop()])) after_or = True elif keyword in ['after', 'before']: require_date = keyword else: cmd = (keyword, not_count % 2 == 0) found = True break if not found: raise InvalidQuery("Unknown command !%s" % value) elif token == 'tag': cmd = (token, not_count % 2 == 0, value) elif token in ['literal', 'word']: cmd = ('word', not_count % 2 == 0, value.strip('"').lower()) if cmd is not None: if after_or: commands[-1][2].append(cmd) else: commands.append(cmd) not_count, after_or = 0, False if not_count > 0: raise InvalidQuery("Query cannot end with !not (Forgot something?)") if after_or: raise InvalidQuery("Or is not allowed at the end of query") if require_date: raise InvalidQuery("Required date after '%s'" % require_date) return {'q': commands}
def mark_not_today(self, button): start_date = Date.parse("tomorrow") for tid in self.plugin_api.get_selected(): task = self.req.get_task(tid) task.set_start_date(start_date)
def get_current_date(self): now = datetime.now() return Date.parse(now.strftime("%Y-%m-%d"))