# -*- coding: utf-8 -*-
# date: 17 Apr 2009
import pygtk
pygtk.require('2.0')
import gtk
import gtk.glade
import gobject
import item
import time
import inspect
import os
from license import version, gpl_3
class ui_pygtk:
def __init__(self, itemList):
self.itemList = itemList
# load ui from glade file
c=inspect.currentframe()
glade = gtk.glade.XML (os.path.dirname(c.f_code.co_filename) + "/todolist.glade")
self.main_window = glade.get_widget('main_window')
self.main_window.todolist = glade.get_widget('todolist')
self.edit_dialog = glade.get_widget('edit_dialog')
self.edit_dialog.title_field = glade.get_widget('title_field')
self.edit_dialog.priority_field = glade.get_widget('priority_field')
self.edit_dialog.due_field = glade.get_widget('due_field')
self.edit_dialog.desc_field = glade.get_widget('description_field')
self.date_select_dialog = glade.get_widget('date_select_dialog')
self.date_select_dialog.calendar = glade.get_widget('calendar')
self.date_select_dialog.hour_field = glade.get_widget('hour_field')
self.date_select_dialog.minute_field = glade.get_widget('minute_field')
# connect the defined signales
dic = {"on_menu_about_clicked" : self.about_clicked_callback,
"on_menu_quit_clicked" : gtk.main_quit,
"on_main_window_destroy" : gtk.main_quit,
"on_treeview_row_activated" : self.item_double_clicked_callback,
"on_edit_clicked" : self.edit_clicked_callback,
"on_remove_clicked" : self.remove_clicked_callback,
"on_add_clicked" : self.add_clicked_callback,
"on_select_date_clicked" : self.select_date_clicked_callback,
"on_show_today_clicked" : self.show_today_clicked_callback
}
glade.signal_autoconnect(dic)
# fill the treeview with data
liststore = gtk.ListStore(object)
for items in self.itemList:
liststore.append([items])
self.main_window.todolist.set_model(liststore)
self.main_window.todolist.append_column(self.create_column(0, 'Finished', 'getCompleted', liststore, gtk.CellRendererToggle()))
# magic column
cellRenderer = gtk.CellRendererText()
column = gtk.TreeViewColumn('Todo', cellRenderer)
column.set_cell_data_func(cellRenderer, (lambda column, cell, model, iter, userdata=None: cell.set_property('markup', ("<b>%s</b>\n%s" % (gobject.markup_escape_text(model.get_value(iter, 0).getTitle()), gobject.markup_escape_text(model.get_value(iter, 0).getDescription()))).strip())), None)
column.set_reorderable(True)
column.set_resizable(True)
#column.set_sort_column_id(id)
self.main_window.todolist.append_column(column)
for column in ([['Id', 'getId'],
['ToDo', 'getTitle'],
['...', 'getDescription'],
['Erstellt am', ['getCreatedAt',
(lambda x: time.strftime('%d.%m.%Y %H:%M:%S', time.localtime(x)))]],
['Bis', ['getDue',
(lambda x: time.strftime('%d.%m.%Y %H:%M:%S', time.localtime(x)))]]
]):
self.main_window.todolist.append_column(self.create_column(len(self.main_window.todolist.get_columns())+1, column[0], column[1], liststore))
# start ui
self.main_window.show_all()
gtk.main()
return
def create_column(self, id, title, data, treemodel, cellRenderer=gtk.CellRendererText()):
# abstract mmethod to create a column for the data
# from the item objects in the treeview
column = gtk.TreeViewColumn(title, cellRenderer)
column.set_cell_data_func(cellRenderer, self.item_data_callback, data)
column.set_reorderable(True)
column.set_resizable(True)
column.set_sort_column_id(id)
treemodel.set_sort_func(id, (lambda model, iter1, iter2, userdata=None:
apply(cmp,
map((lambda x: self.item_data_callback(column, None, model, x, data)),
[iter1, iter2]))))
return column
#########################################################
# callbacks
#########################################################
def item_data_callback(self, column, cell, model, iter, userdata=None):
# method to get the data from the item object for one column
data=''
rowdata = model.get_value(iter, 0)
if (userdata == None):
# try to convert the object to string
data = rowdata.__str__()
else:
if type(userdata) is type([]):
data = getattr(model.get_value(iter, 0), userdata[0])()
# modify data with the given functions
for i in xrange (1, len(userdata)):
data = userdata[i](data)
else:
data = getattr(model.get_value(iter, 0), userdata)()
# set the data as cell content
if isinstance(cell, gtk.CellRendererText) :
cell.set_property('markup', gobject.markup_escape_text(data.__str__()))
# set backround color
if rowdata.getPriority().getColor() is not None:
cell.set_property('foreground-gdk', gtk.gdk.Color(red=rowdata.getPriority().getColor(), blue=0, green=0))
elif isinstance(cell, gtk.CellRendererToggle) :
cell.set_property('active', data)
def about_clicked_callback(self, widget, data=None):
# show the about dialog
about_window = gtk.AboutDialog()
about_window.set_name('Todolist')
about_window.set_version(version)
about_window.set_copyright('2009 Alexander Sulfrian')
about_window.set_license(gpl_3)
about_window.set_website('http://git.animux.de/todolist.git')
about_window.run()
about_window.hide()
return
def edit_clicked_callback(self, widget, data=None):
# edit btn click
treeview = self.main_window.todolist
path = treeview.get_model().get_path(treeview.get_selection().get_selected()[1])
self.item_double_clicked_callback(treeview, path, 0)
def item_double_clicked_callback(self, treeview, path, view_column, user_data=None):
# dbl click on treeview row to edit item
model = treeview.get_model()
item = model.get_value(model.get_iter(path), 0)
if self.edit_item(item):
treeview.get_model().row_changed(path, model.get_iter(path))
sort = list(model.get_sort_column_id())
if sort[0]:
model.set_sort_column_id(0, gtk.SORT_ASCENDING)
apply(model.set_sort_column_id, sort)
return
def remove_clicked_callback(self, widget, data=None):
# remove the selected element
treeview = self.main_window.todolist
if (treeview.get_selection().count_selected_rows() == 1):
iter = treeview.get_selection().get_selected()[1]
path = treeview.get_model().get_path(iter)
item = treeview.get_model().get_value(iter, 0)
self.main_window.todolist.get_model().remove(iter)
self.itemList.remove(item)
treeview.get_model().row_deleted(path)
return
def add_clicked_callback(self, widget, data=None):
# add a new element
new_item = item.item()
if self.edit_item(new_item):
iter = self.main_window.todolist.get_model().append([new_item])
self.itemList.append(new_item)
self.main_window.todolist.get_model().row_inserted(self.main_window.todolist.get_model().get_path(iter), iter)
return
def select_date(self, date):
# select the given date in the calendar control in the date select dialog
self.date_select_dialog.calendar.select_month(date[1] - 1, date[0])
self.date_select_dialog.calendar.select_day(date[2])
self.date_select_dialog.hour_field.set_value(date[3])
self.date_select_dialog.minute_field.set_value(date[4])
return
def select_date_clicked_callback(self, widget, data=None):
# display the dialog to select a date after clicked on the
# button in the edit dialog
try:
date = time.strptime(self.edit_dialog.due_field.get_text(), '%d.%m.%Y %H:%M')
except:
date = time.localtime()
self.select_date(date)
if self.date_select_dialog.run():
date = self.date_select_dialog.calendar.get_date()
date = (date[0], date[1] + 1, date[2],
int(self.date_select_dialog.hour_field.get_value()),
int(self.date_select_dialog.minute_field.get_value()),
0, 0, 0, 0)
self.edit_dialog.due_field.set_text(time.strftime(
'%d.%m.%Y %H:%M', date))
self.date_select_dialog.hide()
return
def show_today_clicked_callback(self, widget, data=None):
# show today in the calendar control in the date select dialog
self.select_date(time.localtime())
return
#########################################################
# helper methods
#########################################################
def edit_item(self, item):
# helper method to edit item
self.edit_dialog.title_field.set_text(item.getTitle())
self.edit_dialog.priority_field.set_text(item.getPriority().__str__())
if item.getDue() != -1:
self.edit_dialog.due_field.set_text(time.strftime('%d.%m.%Y %H:%M', time.localtime(item.getDue())))
else:
self.edit_dialog.due_field.set_text('')
text_buffer = gtk.TextBuffer()
if item.getDescription() != None:
text_buffer.set_text(item.getDescription())
self.edit_dialog.desc_field.set_buffer(text_buffer)
successfull = self.edit_dialog.run()
if (successfull):
item.title = self.edit_dialog.title_field.get_text()
item.setPriority(name=self.edit_dialog.priority_field.get_text())
item.description = text_buffer.get_text(text_buffer.get_start_iter(), text_buffer.get_end_iter())
try:
item.due = int(time.strftime('%s', time.strptime(self.edit_dialog.due_field.get_text(), '%d.%m.%Y %H:%M')))
except:
item.due = -1
self.edit_dialog.hide()
return successfull