summaryrefslogblamecommitdiffstats
path: root/ui/ui_pygtk.py
blob: f9941ff5049cfe2fbc3f7166524346dc77600739 (plain) (tree)
1
2
3
4
5
6
7
8
9





                       
                
              
           
           

              
                                  




                                 
                                 

                                                                                         
                                                          
                                                                



                                                                            
                                                                  
                                                                           
 




                                                                               




                                                                                    

                                                                               
                                                                            

                                                                                    
                


                                     



                                         

                                                                                                                                       
 
                      







                                                                                                                                                                                                                                                                                                           



                                                        

                                                                                             


                                                                                                                                                        
        
                  
                                   


                  
                                                                                             

                                                          












                                                                                                                  


                                                             

                                                                           
                                                                    
               

                                                  

                                                 
                                    










                                                                       
                                                   




                                                                                                                         

                                                       
        

                                                        








                                                                     



                                                       

                                                                                        
 





                                                                                        
                                                                        
                                                   


                                                               

              



                                                                 




                                                              
                                      
                                                  





                                                      
                                                                           
                                          


                                                                                                                          







                                                                                 






                                                                                         
                              










                                                                          
              






                                                                      








                                                                              




                                                                                                               





                                                           
 
                                         
                                                                
                                                                             

                                                                                                             
                
                                                                                                                           




                               
                          
# -*- 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