<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--Generated with glade3 3.4.5 on Wed Apr 15 22:22:55 2009 -->
+<!--Generated with glade3 3.4.5 on Thu Apr 16 08:06:09 2009 -->
<glade-interface>
<widget class="GtkWindow" id="mainWindow">
<property name="default_width">800</property>
<widget class="GtkLabel" id="errorDescription">
<property name="visible">True</property>
<property name="use_markup">True</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_END</property>
+ <property name="single_line_mode">True</property>
</widget>
<packing>
<property name="position">1</property>
<widget class="GtkHBox" id="edit-dueDateDisplayControlBox">
<property name="visible">True</property>
<child>
- <widget class="GtkEntry" id="edit-dueDateDisplay">
+ <widget class="GtkCalendar" id="edit-dueDateCalendar">
<property name="visible">True</property>
- <property name="editable">False</property>
+ <property name="can_focus">True</property>
+ <property name="year">2009</property>
+ <property name="month">3</property>
+ <property name="day">16</property>
+ <property name="show_details">False</property>
</widget>
</child>
<child>
<widget class="GtkHButtonBox" id="edit-dueDateActionBox">
<property name="visible">True</property>
<child>
- <widget class="GtkButton" id="edit-dueDateProperties">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="label" translatable="yes">gtk-properties</property>
- <property name="use_stock">True</property>
- <property name="response_id">0</property>
- </widget>
- </child>
- <child>
<widget class="GtkButton" id="edit-clearDueDate">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
</widget>
- <packing>
- <property name="position">1</property>
- </packing>
</child>
</widget>
<packing>
+ <property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
Short/long version with long including tags colored specially
"""
-import warnings
-import contextlib
+import sys
+import traceback
import datetime
+import contextlib
+import warnings
import gobject
import gtk
else:
self.__show_message(message)
- def push_exception(self, exception):
- self.push_message(exception.message)
- warnings.warn(exception, stacklevel=3)
+ def push_exception(self, exception = None):
+ if exception is None:
+ userMessage = sys.exc_info()[1].message
+ warningMessage = traceback.format_exc()
+ else:
+ userMessage = exception.message
+ warningMessage = exception
+ self.push_message(userMessage)
+ warnings.warn(warningMessage, stacklevel=3)
def pop_message(self):
if 0 < len(self.__messages):
self._taskName = widgetTree.get_widget("edit-taskNameEntry")
self._pasteTaskNameButton = widgetTree.get_widget("edit-pasteTaskNameButton")
self._priorityChoiceCombo = widgetTree.get_widget("edit-priorityChoiceCombo")
- self._dueDateDisplay = widgetTree.get_widget("edit-dueDateDisplay")
- self._dueDateProperties = widgetTree.get_widget("edit-dueDateProperties")
+ self._dueDateDisplay = widgetTree.get_widget("edit-dueDateCalendar")
self._clearDueDate = widgetTree.get_widget("edit-clearDueDate")
self._addButton = widgetTree.get_widget("edit-commitEditTaskButton")
self._cancelButton = widgetTree.get_widget("edit-cancelEditTaskButton")
- self._popupCalendar = PopupCalendar(self._dialog, coroutines.func_sink(self._update_duedate))
+ self._onPasteTaskId = None
+ self._onClearDueDateId = None
+ self._onAddId = None
+ self._onCancelId = None
def enable(self, todoManager):
self._populate_projects(todoManager)
- self._pasteTaskNameButton.connect("clicked", self._on_name_paste)
- self._dueDateProperties.connect("clicked", self._on_choose_duedate)
- self._clearDueDate.connect("clicked", self._on_clear_duedate)
- self._addButton.connect("clicked", self._on_add_clicked)
- self._cancelButton.connect("clicked", self._on_cancel_clicked)
+ self._onPasteTaskId = self._pasteTaskNameButton.connect("clicked", self._on_name_paste)
+ self._onClearDueDateId = self._clearDueDate.connect("clicked", self._on_clear_duedate)
+ self._onAddId = self._addButton.connect("clicked", self._on_add_clicked)
+ self._onCancelId = self._cancelButton.connect("clicked", self._on_cancel_clicked)
def disable(self):
- self._pasteTaskNameButton.disconnect("clicked", self._on_name_paste)
- self._dueDateProperties.disconnect("clicked", self._on_choose_duedate)
- self._clearDueDate.disconnect("clicked", self._on_clear_duedate)
+ self._pasteTaskNameButton.disconnect(self._onPasteTaskId)
+ self._clearDueDate.disconnect(self._onClearDueDateId)
+ self._addButton.disconnect(self._onAddId)
+ self._cancelButton.disconnect(self._onAddId)
+
self._projectsList.clear()
self._projectCombo.set_model(None)
originalName = taskDetails["name"]
originalPriority = str(taskDetails["priority"].get_nothrow(0))
if taskDetails["dueDate"].is_good():
- originalDue = taskDetails["dueDate"].get().strftime("%Y-%m-%d %H:%M:%S")
+ originalDue = taskDetails["dueDate"].get()
else:
- originalDue = ""
+ originalDue = None
self._dialog.set_default_response(gtk.RESPONSE_OK)
self._taskName.set_text(originalName)
self._set_active_proj(originalProjectName)
self._priorityChoiceCombo.set_active(int(originalPriority))
- self._dueDateDisplay.set_text(originalDue)
+ if originalDue is not None:
+ # Months are 0 indexed
+ self._dueDateDisplay.select_month(originalDue.month - 1, originalDue.year)
+ self._dueDateDisplay.select_day(originalDue.day)
+ else:
+ now = datetime.datetime.now()
+ self._dueDateDisplay.select_month(now.month, now.year)
+ self._dueDateDisplay.select_day(0)
try:
response = self._dialog.run()
newProjectName = self._get_project(todoManager)
newName = self._taskName.get_text()
newPriority = self._get_priority()
- newDueDate = self._dueDateDisplay.get_text()
+ year, month, day = self._dueDateDisplay.get_date()
+ if day != 0:
+ # Months are 0 indexed
+ date = datetime.date(year, month + 1, day)
+ time = datetime.time()
+ newDueDate = datetime.datetime.combine(date, time)
+ else:
+ newDueDate = None
isProjDifferent = newProjectName != originalProjectName
isNameDifferent = newName != originalName
print "PRIO CHANGE"
if isDueDifferent:
if newDueDate:
- due = datetime.datetime.strptime(newDueDate, "%Y-%m-%d %H:%M:%S")
- due = toolbox.Optional(due)
+ due = toolbox.Optional(newDueDate)
else:
due = toolbox.Optional()
else:
return str(index)
- def _update_duedate(self, eventData):
- widget, date = eventData
- time = datetime.time()
- dueDate = datetime.datetime.combine(date, time)
-
- formttedDate = dueDate.strftime("%Y-%m-%d %H:%M:%S")
- self._dueDateDisplay.set_text(formttedDate)
-
def _on_name_paste(self, *args):
clipboard = gtk.clipboard_get()
contents = clipboard.wait_for_text()
if contents is not None:
self._taskName.set_text(contents)
- def _on_choose_duedate(self, *args):
- self._popupCalendar.run()
-
def _on_clear_duedate(self, *args):
- self._dueDateDisplay.set_text("")
+ self._dueDateDisplay.select_day(0)
def _on_add_clicked(self, *args):
self._dialog.response(gtk.RESPONSE_OK)
LINK_IDX = 6
NOTES_IDX = 7
- def __init__(self, widgetTree):
+ def __init__(self, widgetTree, errorDisplay):
+ self._errorDisplay = errorDisplay
self._manager = None
self._projId = None
self._showCompleted = False
self._todoItemTree.append_column(self._dueColumn)
self._todoItemTree.append_column(self._linkColumn)
self._todoItemTree.append_column(self._notesColumn)
- self.reset_task_list(self._projId)
+ try:
+ self.reset_task_list(self._projId)
+ except StandardError, e:
+ self._errorDisplay.push_exception()
self._todoItemTree.set_headers_visible(False)
self._nameColumn.set_expand(True)
self._todoItemTree.set_model(self._itemList)
def _on_item_select(self, treeView, path, viewColumn):
- # @todo See if there is a way to use the new gtk_toolbox.ContextHandler
- taskId = self._itemList[path[0]][self.ID_IDX]
-
- if viewColumn is self._priorityColumn:
- pass
- elif viewColumn is self._nameColumn:
- self._editDialog.enable(self._manager)
- try:
- self._editDialog.request_task(self._manager, taskId)
- finally:
- self._editDialog.disable()
- self.reset_task_list(self._projId)
- elif viewColumn is self._dueColumn:
- self._editDialog.enable(self._manager)
- try:
- self._editDialog.request_task(self._manager, taskId)
- finally:
- self._editDialog.disable()
- self.reset_task_list(self._projId)
- elif viewColumn is self._linkColumn:
- webbrowser.open(self._manager.get_task_details(taskId)["url"])
- elif viewColumn is self._notesColumn:
- pass
+ try:
+ # @todo See if there is a way to use the new gtk_toolbox.ContextHandler
+ taskId = self._itemList[path[0]][self.ID_IDX]
+
+ if viewColumn is self._priorityColumn:
+ pass
+ elif viewColumn is self._nameColumn:
+ self._editDialog.enable(self._manager)
+ try:
+ self._editDialog.request_task(self._manager, taskId)
+ finally:
+ self._editDialog.disable()
+ self.reset_task_list(self._projId)
+ elif viewColumn is self._dueColumn:
+ self._editDialog.enable(self._manager)
+ try:
+ self._editDialog.request_task(self._manager, taskId)
+ finally:
+ self._editDialog.disable()
+ self.reset_task_list(self._projId)
+ elif viewColumn is self._linkColumn:
+ webbrowser.open(self._manager.get_task_details(taskId)["url"])
+ elif viewColumn is self._notesColumn:
+ pass
+ except StandardError, e:
+ self._errorDisplay.push_exception()
def _on_completion_change(self, cell, path):
- taskId = self._itemList[path[0]][self.ID_IDX]
- self._manager.complete_task(taskId)
- self.reset_task_list(self._projId)
+ try:
+ taskId = self._itemList[path[0]][self.ID_IDX]
+ self._manager.complete_task(taskId)
+ self.reset_task_list(self._projId)
+ except StandardError, e:
+ self._errorDisplay.push_exception()
class QuickAddView(object):
- def __init__(self, widgetTree, addSink):
+ def __init__(self, widgetTree, errorDisplay, addSink):
+ self._errorDisplay = errorDisplay
self._manager = None
self._projId = None
self._addSink = addSink
self._addTaskButton.set_sensitive(not isMeta)
def _on_add(self, *args):
- name = self._taskNameEntry.get_text()
+ try:
+ name = self._taskNameEntry.get_text()
- projId = self._projId
- taskId = self._manager.add_task(projId, name)
+ projId = self._projId
+ taskId = self._manager.add_task(projId, name)
- self._taskNameEntry.set_text("")
- self._addSink.send((projId, taskId))
+ self._taskNameEntry.set_text("")
+ self._addSink.send((projId, taskId))
+ except StandardError, e:
+ self._errorDisplay.push_exception()
def _on_add_edit(self, *args):
- name = self._taskNameEntry.get_text()
+ try:
+ name = self._taskNameEntry.get_text()
- projId = self._projId
- taskId = self._manager.add_task(projId, name)
+ projId = self._projId
+ taskId = self._manager.add_task(projId, name)
- try:
- self._editDialog.enable(self._manager)
try:
- self._editDialog.request_task(self._manager, taskId)
+ self._editDialog.enable(self._manager)
+ try:
+ self._editDialog.request_task(self._manager, taskId)
+ finally:
+ self._editDialog.disable()
finally:
- self._editDialog.disable()
- finally:
- self._taskNameEntry.set_text("")
- self._addSink.send((projId, taskId))
+ self._taskNameEntry.set_text("")
+ self._addSink.send((projId, taskId))
+ except StandardError, e:
+ self._errorDisplay.push_exception()
def _on_add_pressed(self, widget):
- self._addToEditTimerId = gobject.timeout_add(1000, self._on_add_edit)
+ try:
+ self._addToEditTimerId = gobject.timeout_add(1000, self._on_add_edit)
+ except StandardError, e:
+ self._errorDisplay.push_exception()
def _on_add_released(self, widget):
- if self._addToEditTimerId is not None:
- gobject.source_remove(self._addToEditTimerId)
- self._addToEditTimerId = None
+ try:
+ if self._addToEditTimerId is not None:
+ gobject.source_remove(self._addToEditTimerId)
+ self._addToEditTimerId = None
+ except StandardError, e:
+ self._errorDisplay.push_exception()
def _on_paste(self, *args):
- entry = self._taskNameEntry.get_text()
- entry += self._clipboard.wait_for_text()
- self._taskNameEntry.set_text(entry)
+ try:
+ entry = self._taskNameEntry.get_text()
+ entry += self._clipboard.wait_for_text()
+ self._taskNameEntry.set_text(entry)
+ except StandardError, e:
+ self._errorDisplay.push_exception()
def _on_clear(self, *args):
- self._taskNameEntry.set_text("")
+ try:
+ self._taskNameEntry.set_text("")
+ except StandardError, e:
+ self._errorDisplay.push_exception()
class GtkRtMilk(object):
- def __init__(self, widgetTree):
+ def __init__(self, widgetTree, errorDisplay):
"""
@note Thread agnostic
"""
+ self._errorDisplay = errorDisplay
self._manager = None
self._credentials = "", "", ""
self._projectsCombo = widgetTree.get_widget("projectsCombo")
self._onListActivateId = 0
- self._itemView = ItemListView(widgetTree)
+ self._itemView = ItemListView(widgetTree, self._errorDisplay)
addSink = coroutines.func_sink(lambda eventData: self._itemView.reset_task_list(eventData[0]))
- self._addView = QuickAddView(widgetTree, addSink)
+ self._addView = QuickAddView(widgetTree, self._errorDisplay, addSink)
self._credentialsDialog = gtk_toolbox.LoginWindow(widgetTree)
@staticmethod
def _reset_task_list(self):
projectName = self._get_project()
- projId = self._manager.lookup_project(projectName)
+ projId = self._manager.lookup_project(projectName)["id"]
self._addView.reset_task_list(projId)
self._itemView.reset_task_list(projId)
return currentProjectName
def _on_list_activate(self, *args):
- self._reset_task_list()
+ try:
+ self._reset_task_list()
+ except StandardError, e:
+ self._errorDisplay.push_exception()