def __init__(self, parent, mo): self.log = logging.getLogger('MINICAL') self.parent = parent self.mo = mo self.factory = Factory() self.__stop_auto_highlight = False # Disable automatic highlighting of events. self.__stop_auto_dayjump = False # Disable automatically jumping to the start of the event on selection. self.__stop_auto_treeview_update = False # FIXME GladeSlaveDelegate.__init__(self, gladefile='mo_tab_events', toplevel_name='window_main') # Set up the user interface eventColumns = [ Column('start', title='Start', data_type=datetime.datetime, sorted=True), Column('end', title='End', data_type=datetime.datetime), Column('summaryformat', title='Summary', use_markup=True), Column('duration', title='Duration', justify=gtk.JUSTIFY_RIGHT) ] self.treeview_event = ObjectTree(eventColumns) self.vbox_eventslist.add(self.treeview_event) self.combobox_display_range.set_active(self.show_ranges.index(self.mo.config['events.default_show'].lower())) cal_options = gtk.CALENDAR_WEEK_START_MONDAY if self.mo.config['events.cal_show_weeknr']: cal_options |= gtk.CALENDAR_SHOW_WEEK_NUMBERS self.calendar.set_display_options((self.calendar.get_display_options() | cal_options)) # Connect signals self.treeview_event.connect('selection-changed', self.treeview_event__selection_changed) self.treeview_event.connect('row-activated', self.treeview_event__row_activated) self.treeview_event.connect('key-press-event', self.treeview_event__key_press_event) self.on_toolbutton_today__clicked()
def __init__(self, mo, alarms = None, parent_model = None, event_ui=None): self.mo = mo self.alarms = alarms self.parent_model = parent_model self.event_ui = event_ui self.factory = Factory() columns = [ Column("offsetformat", title='Offset'), Column("type", title='Type') ] self.listcontainer_alarms = ListContainer(columns) self.listcontainer_alarms.add_items(alarms) self.listcontainer_alarms.connect('add-item', self.listcontainer__add_item) self.listcontainer_alarms.connect('remove-item', self.listcontainer__remove_item) self.listcontainer_alarms.connect('edit-item', self.listcontainer__edit_item)
def __init__(self, parent, mo): self.parent = parent self.mo = mo self.factory = Factory() # Set up the user interface GladeSlaveDelegate.__init__(self, gladefile="mo_tab_notes", toplevel_name="window_main") noteColumns = [ Column("summary", title='Title', data_type=str), ] #self.treeview_note = ObjectList(noteColumns) self.treeview_note = ObjectTree(noteColumns) self.vbox_notelist.add(self.treeview_note) # Connect signals self.treeview_note.connect('row-activated', self.treeview_note__row_activated) self.treeview_note.connect('selection-changed', self.treeview_note__selection_changed) self.treeview_note.connect('key-press-event', self.treeview_note__key_press_event) self.refresh()
class AlarmsEditUI(ListContainer): def __init__(self, mo, alarms = None, parent_model = None, event_ui=None): self.mo = mo self.alarms = alarms self.parent_model = parent_model self.event_ui = event_ui self.factory = Factory() columns = [ Column("offsetformat", title='Offset'), Column("type", title='Type') ] self.listcontainer_alarms = ListContainer(columns) self.listcontainer_alarms.add_items(alarms) self.listcontainer_alarms.connect('add-item', self.listcontainer__add_item) self.listcontainer_alarms.connect('remove-item', self.listcontainer__remove_item) self.listcontainer_alarms.connect('edit-item', self.listcontainer__edit_item) def listcontainer__add_item(self, *args): start_time = self.event_ui.dateedit_start.dt delta = datetime.timedelta() alarm = self.factory.alarm(delta, self.parent_model) alarm = miniorganizer.ui.AlarmEditUI(self.mo, alarm, start_time).run() if alarm: self.alarms.append(alarm) self.listcontainer_alarms.add_item(alarm) def listcontainer__remove_item(self, listcontainer, alarm): self.alarms.remove(alarm) self.listcontainer_alarms.remove_item(alarm) def listcontainer__edit_item(self, listcontainer, alarm): start_time = self.event_ui.dateedit_start.dt x = miniorganizer.ui.AlarmEditUI(self.mo, alarm, start_time) alarm = x.run() if alarm: self.listcontainer_alarms.update_item(alarm) def set_sensitive(self, state): self.listcontainer_alarms.set_sensitive(state)
def __init__(self, parent, mo): self.parent = parent self.mo = mo self.factory = Factory() GladeSlaveDelegate.__init__(self, gladefile="mo_tab_todo", toplevel_name="window_main") # Set up the user interface todoColumns = [ Column("done", title='Done', data_type=bool, editable=True), Column("summaryformat", title='Summary', use_markup=True), Column('priority', title='Priority', sorted=True, order=gtk.SORT_DESCENDING), ColoredColumn('due', title='Due', data_type=datetime.datetime, color='red', data_func=self.color_due), Column('created', title='Created', data_type=datetime.datetime) ] self.treeview_todo = ObjectTree(todoColumns) self.vbox_todolist.add(self.treeview_todo) # Connect signals self.treeview_todo.connect('row-activated', self.treeview_todo__row_activated) self.treeview_todo.connect('selection-changed', self.treeview_todo__selection_changed) self.treeview_todo.connect('key-press-event', self.treeview_todo__key_press_event) self.refresh()
class NoteUI(GladeSlaveDelegate): def __init__(self, parent, mo): self.parent = parent self.mo = mo self.factory = Factory() # Set up the user interface GladeSlaveDelegate.__init__(self, gladefile="mo_tab_notes", toplevel_name="window_main") noteColumns = [ Column("summary", title='Title', data_type=str), ] #self.treeview_note = ObjectList(noteColumns) self.treeview_note = ObjectTree(noteColumns) self.vbox_notelist.add(self.treeview_note) # Connect signals self.treeview_note.connect('row-activated', self.treeview_note__row_activated) self.treeview_note.connect('selection-changed', self.treeview_note__selection_changed) self.treeview_note.connect('key-press-event', self.treeview_note__key_press_event) self.refresh() def refresh(self): self.treeview_note.clear() for journal in self.mo.cal_model.get_journals(): parent = self.mo.cal_model.get_model_by_uid(journal.get_related_to()) self.treeview_note.append(parent, journal) def on_toolbutton_add__clicked(self, *args): journal = self.factory.journal() journal = miniorganizer.ui.NoteEditUI(self.mo, journal).run() if journal: self.mo.cal_model.add(journal) self.treeview_note.append(None, journal) self.parent.menuitem_save.set_sensitive(True) def on_toolbutton_addsub__clicked(self, *args): parent_journal = self.treeview_note.get_selected() journal = self.factory.journal(parent_journal) if miniorganizer.ui.NoteEditUI(self.mo, journal).run(): self.mo.cal_model.add(journal) self.treeview_note.append(parent_journal, journal) self.treeview_note.expand(parent_journal) self.parent.menuitem_save.set_sensitive(True) def on_toolbutton_edit__clicked(self, *args): sel_note = self.treeview_note.get_selected() self.treeview_note__row_activated(self.treeview_note, sel_note) def on_toolbutton_remove__clicked(self, *args): sel_note = self.treeview_note.get_selected() if sel_note: children = self.mo.cal_model.get_models_related_by_uid(sel_note.get_uid()) if children: response = dialogs.warning('This note contains sub-notes. Removing it will also remove the sub-notes. Is this what you want?', buttons=gtk.BUTTONS_YES_NO) if response != gtk.RESPONSE_YES: return self.mo.cal_model.delete(sel_note, True) self.treeview_note.remove(sel_note, True) self.parent.menuitem_save.set_sensitive(True) def treeview_note__selection_changed(self, list, selection): has_selection = selection is not None self.toolbutton_addsub.set_sensitive(has_selection) self.toolbutton_remove.set_sensitive(has_selection) self.toolbutton_edit.set_sensitive(has_selection) def treeview_note__row_activated(self, list, object): sel_note = self.treeview_note.get_selected() note = miniorganizer.ui.NoteEditUI(self.mo, sel_note).run() def treeview_note__key_press_event(self, treeview, event): if event.keyval == gtk.keysyms.Delete: self.on_toolbutton_remove__clicked()
class EventUI(GladeSlaveDelegate): show_ranges = ['day', 'week', 'month', 'year'] def __init__(self, parent, mo): self.log = logging.getLogger('MINICAL') self.parent = parent self.mo = mo self.factory = Factory() self.__stop_auto_highlight = False # Disable automatic highlighting of events. self.__stop_auto_dayjump = False # Disable automatically jumping to the start of the event on selection. self.__stop_auto_treeview_update = False # FIXME GladeSlaveDelegate.__init__(self, gladefile='mo_tab_events', toplevel_name='window_main') # Set up the user interface eventColumns = [ Column('start', title='Start', data_type=datetime.datetime, sorted=True), Column('end', title='End', data_type=datetime.datetime), Column('summaryformat', title='Summary', use_markup=True), Column('duration', title='Duration', justify=gtk.JUSTIFY_RIGHT) ] self.treeview_event = ObjectTree(eventColumns) self.vbox_eventslist.add(self.treeview_event) self.combobox_display_range.set_active(self.show_ranges.index(self.mo.config['events.default_show'].lower())) cal_options = gtk.CALENDAR_WEEK_START_MONDAY if self.mo.config['events.cal_show_weeknr']: cal_options |= gtk.CALENDAR_SHOW_WEEK_NUMBERS self.calendar.set_display_options((self.calendar.get_display_options() | cal_options)) # Connect signals self.treeview_event.connect('selection-changed', self.treeview_event__selection_changed) self.treeview_event.connect('row-activated', self.treeview_event__row_activated) self.treeview_event.connect('key-press-event', self.treeview_event__key_press_event) self.on_toolbutton_today__clicked() def refresh(self): """ Refresh the entire events tab. This clears everything and rebuilds it. Call this when events are removed outside of this class. """ self.treeview_event.clear() self.calendar.clear_marks() self.on_calendar__month_changed(self.calendar) self.treeview_event__update() def on_toolbutton_add__clicked(self, *args): now = datetime.datetime.now() sel_day = self.calendar.get_date() start = datetime.datetime(sel_day[0], sel_day[1]+1, sel_day[2], now.hour, now.minute) end = start + datetime.timedelta(hours=+1) event = self.factory.event(start, end) event = miniorganizer.ui.EventEditUI(self.mo, event).run() if event: self.mo.cal_model.add(event) self.treeview_event.append(None, event) self.on_calendar__month_changed(self.calendar) self.on_calendar__day_selected(self.calendar) self.parent.menuitem_save.set_sensitive(True) def on_toolbutton_remove__clicked(self, *args): sel_event = self.treeview_event.get_selected() sel_real_event = getattr(sel_event, 'real_event', sel_event) # Delete real event instead of recurring event if sel_event != sel_real_event: response = dialogs.yesno('This is a recurring event. Deleting it will delete all recurrences. Are you sure you want to delete it?') if response == gtk.RESPONSE_NO: return else: sel_event = sel_real_event if sel_event: self.mo.cal_model.delete(sel_event) self.treeview_event.remove(sel_event) self.on_calendar__month_changed(self.calendar) self.on_calendar__day_selected(self.calendar) self.parent.menuitem_save.set_sensitive(True) def on_toolbutton_edit__clicked(self, *args): sel_event = self.treeview_event.get_selected() self.treeview_event__row_activated(self.treeview_event, sel_event) def on_toolbutton_today__clicked(self, *args): today_dt = datetime.date.today() self.calendar.select_month(today_dt.month - 1, today_dt.year) self.calendar.select_day(today_dt.day) def on_calendar__month_changed(self, calendar, *args): self.calendar.clear_marks() sel_date = self.calendar.get_date() month_start = datetime.datetime(sel_date[0], sel_date[1]+1, 1) month_end = month_start + relativedelta(months=+1, seconds=-1) events = self.mo.cal_model.get_events() + self.mo.cal_model.get_events_recurring(month_start, month_end) for event in events: event_start = event.get_start() event_end = event.get_end() self.log.debug('Event %s, start: %s, end %s' % (event.get_summary(), event_start, event_end)) # If the event falls in the month, mark the days the event spans in # the calendar. if (month_start >= event_start and month_start <= event_end) or \ (month_end >= event_start and month_end <= event_end) or \ (event_start >= month_start and event_end <= month_end): # Walk through the days of the event, marking them. delta_iter = datetime.datetime(*event_start.timetuple()[0:3]) while True: if delta_iter.year == month_start.year and delta_iter.month == month_start.month: self.calendar.mark_day(delta_iter.day) delta_iter = delta_iter + datetime.timedelta(days=+1) if delta_iter >= event_end: break def on_calendar__day_selected(self, calendar, *args): # Make sure the correct display range is shown. self.on_combobox_display_range__changed() # Retrieve the day the user selected. sel_day = self.calendar.get_date() day_start = datetime.datetime(sel_day[0], sel_day[1]+1, sel_day[2]) day_end = day_start + datetime.timedelta(days=+1) display_month = datetime.datetime(day_start.year, day_start.month, 1) # Highlight an event if it starts on the selected day. highlight_events = [] events = [event for event in self.treeview_event] for event in events: event_start = event.get_start() event_end = event.get_end() # If this is the first event that starts on the day the user # selected, highlight the item in the list of events. if event_start >= day_start and event_start < day_end: highlight_events.insert(0, event) # If the selected day occurs during an event, highlight it. We # append it to the list of events to be highlighted, so it'll only # be highlighted if no event actually starts on that day. elif (day_start > event_start and day_start < event_end) or \ (day_end > event_start and day_end < event_end) or \ (event_start > day_start and event_end < day_end): highlight_events.append(event) # Highlight the first event on the day the user selected, unless the # user manually selected an event. if not self.__stop_auto_highlight: if highlight_events and highlight_events[0] in self.treeview_event: self.__stop_auto_dayjump = True self.treeview_event.select(highlight_events[0], True) self.__stop_auto_dayjump = False else: self.treeview_event.unselect_all() def on_calendar__day_selected_double_click(self, *args): self.on_toolbutton_add__clicked() def on_combobox_display_range__changed(self, *args): # Get the currently selected date in the calendar. sel_date = self.calendar.get_date() sel_dt_start = datetime.datetime(sel_date[0], sel_date[1]+1, sel_date[2]) sel_dt_end = sel_dt_start + datetime.timedelta(days=+1) # Determine the start and end of the period that needs to be shown. display_range = self.combobox_display_range.get_active_text() if display_range == 'Day': display_start = sel_dt_start display_end = display_start + datetime.timedelta(days=+1, seconds=-1) text = '%s' % (display_start.strftime('%a %b %d %Y')) elif display_range == 'Week': display_start = sel_dt_start + datetime.timedelta(days=-sel_dt_start.weekday()) display_end = display_start + datetime.timedelta(weeks=+1, seconds=-1) text = '%s - %s' % (display_start.strftime('%a %b %d %Y'), display_end.strftime('%a %b %d %Y')) elif display_range == 'Month': display_start = sel_dt_start + datetime.timedelta(days=-(sel_dt_start.day - 1)) display_end = display_start + relativedelta(months=+1, seconds=-1) text = '%s' % (display_start.strftime('%b %Y')) elif display_range == 'Year': display_start = datetime.datetime(sel_dt_start.year, 1, 1) display_end = display_start + relativedelta(years=+1, seconds=-1) text = '%s' % (display_start.strftime('%Y')) else: raise Exception('No selected display range!') # Update the displayed range self.displayed_range.set_text(text) self.display_start = display_start self.display_end = display_end self.treeview_event__update() def treeview_event__update(self): if self.__stop_auto_treeview_update: return # First, remove all the recurring events, because they're generated on # the fly, so we can't know which ones in the list we need to remove. # Therefor we remove them every time. events_rm = [] for event in self.treeview_event: if hasattr(event, 'real_event'): events_rm.append(event) for event in events_rm: self.treeview_event.remove(event) # Add the events for the displayed range to the list events = self.mo.cal_model.get_events() + self.mo.cal_model.get_events_recurring(self.display_start, self.display_end) for event in events: event_start = event.get_start() event_end = event.get_end() # If the currently displayed range includes an event, add it to the list. if (self.display_start >= event_start and self.display_start < event_end) or \ (self.display_end >= event_start and self.display_end < event_end) or \ (event_start >= self.display_start and event_end < self.display_end): if not event in self.treeview_event: self.treeview_event.append(None, event) # Otherwise, we remove it from the list, if it's present. else: if event in self.treeview_event: self.treeview_event.remove(event) def treeview_event__row_activated(self, list, object): # FIXME: This might be more complicated than it needs to be. See todo.py's row_activated. sel_event = self.treeview_event.get_selected() sel_event = getattr(sel_event, 'real_event', sel_event) # Edit real event instead of recurring event event = miniorganizer.ui.EventEditUI(self.mo, sel_event).run() self.on_calendar__month_changed(self.calendar) self.on_calendar__day_selected(self.calendar) if sel_event in self.treeview_event: self.treeview_event.select(sel_event, True) self.parent.menuitem_save.set_sensitive(True) def treeview_event__selection_changed(self, list, selection): # Stop the treeview from automatically updating itself because that # will remove the recurring events and regenerate them (with different # instance IDs) which means the selection may be invalid. self.__stop_auto_treeview_update = True sel_event = self.treeview_event.get_selected() has_selection = sel_event is not None # Enable / disable toolbuttons self.toolbutton_remove.set_sensitive(has_selection) self.toolbutton_edit.set_sensitive(has_selection) # Do not jump to the day of the event. This is needed because an event # can be automatically selected even if it doesn't start on a # particular day. if self.__stop_auto_dayjump: self.__stop_auto_treeview_update = False return # Stop this selection from being overwritten. self.__stop_auto_highlight = True if has_selection: # Make the calendar jump to the day on which this event begins. sel_event_start = sel_event.get_start() self.calendar.select_month(sel_event_start.month - 1, sel_event_start.year) self.calendar.select_day(sel_event_start.day) # Enable automatic highlighting of items self.__stop_auto_highlight = False self.__stop_auto_treeview_update = False def treeview_event__key_press_event(self, treeview, event): if event.keyval == gtk.keysyms.Delete: self.on_toolbutton_remove__clicked()
class TodoUI(GladeSlaveDelegate): def __init__(self, parent, mo): self.parent = parent self.mo = mo self.factory = Factory() GladeSlaveDelegate.__init__(self, gladefile="mo_tab_todo", toplevel_name="window_main") # Set up the user interface todoColumns = [ Column("done", title='Done', data_type=bool, editable=True), Column("summaryformat", title='Summary', use_markup=True), Column('priority', title='Priority', sorted=True, order=gtk.SORT_DESCENDING), ColoredColumn('due', title='Due', data_type=datetime.datetime, color='red', data_func=self.color_due), Column('created', title='Created', data_type=datetime.datetime) ] self.treeview_todo = ObjectTree(todoColumns) self.vbox_todolist.add(self.treeview_todo) # Connect signals self.treeview_todo.connect('row-activated', self.treeview_todo__row_activated) self.treeview_todo.connect('selection-changed', self.treeview_todo__selection_changed) self.treeview_todo.connect('key-press-event', self.treeview_todo__key_press_event) self.refresh() def refresh(self): """ Refresh the entire todo tab. This clears everything and rebuilds it. Call this when todos are removed outside of this class. """ self.treeview_todo.clear() # Fill the user interface with information for todo in self.mo.cal_model.get_todos(): parent = self.mo.cal_model.get_model_by_uid(todo.get_related_to()) self.treeview_todo.append(parent, todo) def color_due(self, value): if not value: return(False) return(value < datetime.datetime.now()) def on_toolbutton_add__clicked(self, *args): todo = self.factory.todo() todo = miniorganizer.ui.TodoEditUI(self.mo, todo).run() if todo: self.mo.cal_model.add(todo) self.treeview_todo.append(None, todo) self.parent.menuitem_save.set_sensitive(True) def on_toolbutton_edit__clicked(self, *args): sel_todo = self.treeview_todo.get_selected() self.treeview_todo__row_activated(self.treeview_todo, sel_todo) def on_toolbutton_remove__clicked(self, *args): sel_todo = self.treeview_todo.get_selected() if sel_todo: children = self.mo.cal_model.get_models_related_by_uid(sel_todo.get_uid()) if children: response = dialogs.warning('This Todo contains sub-todos. Removing it will also remove the sub-todos. Is this what you want?', buttons=gtk.BUTTONS_YES_NO) if response != gtk.RESPONSE_YES: return self.treeview_todo.remove(sel_todo, True) self.mo.cal_model.delete(sel_todo, True) self.parent.menuitem_save.set_sensitive(True) def on_toolbutton_addsub__clicked(self, *args): parent_todo = self.treeview_todo.get_selected() todo = self.factory.todo(parent_todo) if miniorganizer.ui.TodoEditUI(self.mo, todo).run(): self.mo.cal_model.add(todo) self.treeview_todo.append(parent_todo, todo) self.treeview_todo.expand(parent_todo) self.parent.menuitem_save.set_sensitive(True) def treeview_todo__selection_changed(self, list, selection): has_selection = selection is not None self.toolbutton_addsub.set_sensitive(has_selection) self.toolbutton_remove.set_sensitive(has_selection) self.toolbutton_edit.set_sensitive(has_selection) def treeview_todo__row_activated(self, list, object): todo = miniorganizer.ui.TodoEditUI(self.mo, object).run() self.parent.menuitem_save.set_sensitive(True) def treeview_todo__key_press_event(self, treeview, event): if event.keyval == gtk.keysyms.Delete: self.on_toolbutton_remove__clicked()