# -*- 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', ("%s\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