Exemple #1
0
	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()
Exemple #2
0
	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)
Exemple #3
0
	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()
Exemple #4
0
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)
Exemple #5
0
	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()
Exemple #6
0
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()
Exemple #7
0
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()
Exemple #8
0
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()