Home > python, wxpython > wxPython: Rubrica – Controller

wxPython: Rubrica – Controller

22 Maggio 2011

Dopo le Views ed il model, concludo con il mio controller.
Quasi tutti i Bind ai widgets dei frames (views) sono stati codificati qui.
codice:

#!/usr/bin/python
#Controller.py
'''Rubrica by Bancaldo'''

import wx

from sqlalchemy import and_
from sqlalchemy.orm import sessionmaker

from InfoHTMLFrame import FrameInfo
from CoreFrame import FrameCore
from DelContactFrame import FrameDelContact
from ContactFrame import FrameContact

from Find import FrameFindContact
from Data import Model, Contact

class CoreController(object):
    '''Controller Object'''
    def __init__(self):
        '''Constructor'''
        self.metadata = Model.metadata
        self.metadata.create_all(Model.engine)
        session = sessionmaker(bind = Model.engine)
        self.session = session()
        self.model = Model()
        self.core = FrameCore(None, -1, title  = 'Rubrica', size = (200, 280))
        self.core.btn_add.Bind(wx.EVT_BUTTON, self.on_btn_add)
        self.bind_buttons()
    def bind_buttons(self):
        '''Bind the frame buttons'''
        self.core.Bind(wx.EVT_BUTTON, self.on_btn_info, self.core.btn_info)
        self.core.Bind(wx.EVT_BUTTON, self.on_btn_add, self.core.btn_add)
        self.core.Bind(wx.EVT_BUTTON, self.on_btn_del, self.core.btn_del)
        self.core.Bind(wx.EVT_BUTTON, self.on_btn_find, self.core.btn_find)
        self.core.Bind(wx.EVT_BUTTON, self.on_btn_exit, self.core.btn_exit)
    def fill_find_list(self, char):
        '''Fill the find-frame list-control with elements sorted by letter'''
        self.fr_find.list_ctrl.DeleteAllItems()
        contacts = self.session.query(Contact).filter(Contact.surname.like(
                        ('%s%%') % char)).all()
        i = 0
        for contact in contacts:
            pos = self.fr_find.list_ctrl.InsertStringItem(
                               i, contact.surname)
            self.fr_find.list_ctrl.SetStringItem(pos, 1,
                               contact.name)
            self.fr_find.list_ctrl.SetStringItem(pos, 2,
                               contact.address)
            self.fr_find.list_ctrl.SetStringItem(pos, 3, contact.mail)
            self.fr_find.list_ctrl.SetStringItem(pos, 4, contact.phone)
            self.fr_find.list_ctrl.SetStringItem(pos, 5, contact.mobile)
            i += 1
        return True
    def get_contacts(self):
        '''Get the list of contacts as Surname-Name form'''
        contacts = ['%s %s' % (contact.surname,
                               contact.name) \
                    for contact in self.session.query(Contact).all()]
        contacts.sort()
        return contacts
    def on_add_exit(self, evt):
        '''Button-Exit on_click event handler of Add-contact frame'''
        self.fr_add.Destroy()
    def on_add_save(self, evt):
        '''Button-Save on_click event handler of Add-contact frame'''
        name = self.fr_add.t_name.GetValue()
        surname = self.fr_add.t_surname.GetValue()
        address = self.fr_add.t_address.GetValue()
        phone = self.fr_add.t_phone.GetValue()
        mobile = self.fr_add.t_mobile.GetValue()
        mail = self.fr_add.t_mail.GetValue()
        if surname != '' and name != '' and mobile != '':
            contact = Contact(name = name, surname = surname,
                              address = address, mail = mail,
                              phone = phone, mobile = mobile)
            self.session.add(contact)
            self.session.commit()
            for textctrl in self.fr_add.panel.GetChildren():
                if isinstance(textctrl, wx.TextCtrl):
                    textctrl.Clear()
                    textctrl.Disable()
            self.fr_add.t_surname.Enable()
            self.fr_add.btn_ed_save.Disable()
            print "COMMIT... ", surname, name
        else:
            mess = "Need to complete the (*)fields"
            info = wx.MessageDialog(self.fr_add, mess, 'Error',
                                   wx.OK | wx.ICON_STOP)
            info.ShowModal()
            info.Destroy()
    def on_btn_add(self, evt):
        '''Button-Add on_click event handler'''
        self.fr_add = FrameContact(self.core, -1, title  = 'Save Contact',
                                       size = (330, 300))
        self.fr_add.title.SetLabel('Save new Contact')
        self.fr_add.s_sur.SetLabel('Surname*')
        self.fr_add.s_nam.SetLabel('Name*')
        self.fr_add.s_mob.SetLabel('Mobile*')
        self.fr_add.btn_ed_save.Disable()
        for textctrl in self.fr_add.panel.GetChildren():
            if isinstance(textctrl, wx.TextCtrl):
                textctrl.Disable()
        self.fr_add.t_surname.Enable()
        self.fr_add.t_surname.Bind(wx.EVT_TEXT, self.on_text_entry)
        self.fr_add.Bind(wx.EVT_BUTTON, self.on_add_exit,
                          self.fr_add.btn_ed_exit)
        self.fr_add.Bind(wx.EVT_BUTTON, self.on_add_save,
                          self.fr_add.btn_ed_save)
    def on_btn_chr(self, evt):
        '''Chr-Button on_click event handler of Find-Contact frame '''
        btn_chr = evt.GetEventObject()
        char = btn_chr.GetLabel()
        self.fill_find_list(char)
    def on_btn_del(self, evt):
        '''Button-Delete on_click event handler'''
        contacts = self.get_contacts()
        self.fr_del = FrameDelContact(self.core, -1, 'Delete Contact',
                        size = (325, 200), contacts = contacts)
        self.fr_del.btn_exit_del.Bind(wx.EVT_BUTTON, self.on_del_exit)
        self.fr_del.btn_del.Bind(wx.EVT_BUTTON, self.on_del_del)
        self.fr_del.choice.Bind(wx.EVT_CHOICE, self.on_item_to_del)
        self.fr_del.btn_del.Disable()
    def on_btn_entry(self, evt):
        '''Chr-Button on_entry event handler of Find-Contact frame'''
        btn = evt.GetEventObject()
        btn.SetBackgroundColour('yellow')
        evt.Skip()
    def on_btn_exit(self, evt):
        '''Button-Exit on_click event handler'''
        self.core.Destroy()
    def on_btn_find(self, evt):
        '''Button-Find on_click event handler'''
        self.fr_find = FrameFindContact(self.core, -1, 'Find Contact',
                                        size = (700, 400))
        for child in self.fr_find.panel.GetChildren():
            if isinstance(child, wx.Button):
                child.Bind(wx.EVT_BUTTON, self.on_btn_chr)
                child.Bind(wx.EVT_ENTER_WINDOW, self.on_btn_entry)
                child.Bind(wx.EVT_LEAVE_WINDOW, self.on_btn_leave)
        self.fr_find.btn_find_exit.Bind(wx.EVT_BUTTON, self.on_find_exit)
        self.fr_find.btn_trash.Bind(wx.EVT_BUTTON, self.on_find_trash)
        self.fr_find.list_ctrl.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK,
                                    self.on_item_right_click)
        self.fr_find.list_ctrl.Bind(wx.EVT_LIST_ITEM_ACTIVATED,
                                    self.on_item_double_click)
        self.fr_find.btn_trash.Disable()
        self.fill_find_list('A')
        self.fr_find.list_ctrl.Focus(0)
        evt.Skip()
    def on_btn_info(self, evt):
        '''Button-Info on_click event handler'''
        self.fr_info = FrameInfo(self.core, -1, title = 'Info',
                                 size = (400, 350))
        self.fr_info.Bind(wx.EVT_BUTTON, self.on_btn_quit,
                          self.fr_info.btn_quit)
    def on_btn_leave(self, evt):
        '''Chr-Button on_leave event handler of Find-Contact frame '''
        btn = evt.GetEventObject()
        btn.SetBackgroundColour('#c2e6f8')
    def on_btn_quit(self, evt):
        '''Button-quit on_click event handler of frame_info'''
        self.fr_info.Destroy()
    def on_del_del(self, evt):
        '''Button-Delete on_click event handler of Del-Contact'''
        cont_to_del = self.fr_del.choice.GetStringSelection()
        self.model.set_name(cont_to_del.split()[1])
        self.model.set_surname(cont_to_del.split()[0])        
        msg = wx.MessageDialog(self.fr_del, 'Are You sure?', 'Delete',
                               wx.YES_NO | wx.ICON_WARNING)
        if msg.ShowModal() == wx.ID_YES:
            print "DELETING CONTACT...%s" % cont_to_del
            to_del = self.session.query(Contact).filter(
                         Contact.surname == '%s' % self.model.get_surname()
                         ).first()
            self.session.delete(to_del)
            self.session.commit()
        self.fr_del.choice.Clear()
        self.fr_del.choice.AppendItems(self.get_contacts())
        self.fr_del.btn_del.Disable()
        msg.Destroy()
    def on_del_exit(self, evt):
        '''Button-Exit on_click event handler of Del-contact frame'''
        self.fr_del.Destroy()
    def on_edit_exit(self, evt):
        '''Button-Exit on_click event handler of Edit-Contact Frame'''
        self.fr_find.Show()
        self.fr_edit.Destroy()
    def on_edit_save(self, evt):
        '''Save new contact data to DataBase'''
        query = self.session.query(Contact).filter(Contact.surname == 
                    self.model.get_surname()).first()
        surname = self.fr_edit.t_surname.GetValue()
        name = self.fr_edit.t_name.GetValue()
        address = self.fr_edit.t_address.GetValue()
        mail = self.fr_edit.t_mail.GetValue()
        phone = self.fr_edit.t_phone.GetValue()
        mobile = self.fr_edit.t_mobile.GetValue()
        query.surname = surname
        query.name = name
        query.address = address
        query.mail = mail
        query.phone = phone
        query.mobile = mobile
        self.session.commit()
        self.fr_find.Show()
        self.fr_edit.Destroy()
        self.fr_find.btn_trash.Disable()
        self.fill_find_list('A')
    def on_find_exit(self, evt):
        '''Button-Exit on_click event handler of Find-contact frame '''
        self.fr_find.Destroy()
    def on_find_trash(self, evt):
        '''Button-Trash on_click event handler of Find-contact frame '''
        surname = self.model.get_surname()
        name = self.model.get_name()
        where = and_(Contact.surname == surname, Contact.name == name)
        to_del = self.session.query(Contact).filter(where).first()
        print "Contact to del ------> ", to_del
        msg = wx.MessageDialog(self.fr_find, 'Are You sure?', 'Delete',
                       wx.YES_NO | wx.ICON_WARNING)
        if msg.ShowModal() == wx.ID_YES:
            self.session.delete(to_del)
            self.session.commit()
        self.fr_find.btn_trash.Disable()
        msg.Destroy()
        self.fill_find_list('A')
    def on_item_double_click(self, evt):
        '''Enable the delete-button of the find-frame'''
        self.fr_find.btn_trash.Enable()
        row = self.fr_find.list_ctrl.GetFocusedItem()
        self.model.set_surname(self.fr_find.list_ctrl.GetItem(row, 0).GetText())
        self.model.set_name(self.fr_find.list_ctrl.GetItem(row, 1).GetText())
        evt.Skip()
    def on_item_right_click(self, evt):
        '''Edit all the selected contact data'''
        self.fr_find.Hide()
        self.set_list_values()
        self.fr_edit = FrameContact(self.fr_find, wx.ID_ANY,
                                        title  = 'Edit Contact',
                                        size = (330, 300))
        self.fr_edit.title.SetLabel('Edit contact %s %s' \
                                    % (self.model.get_surname(),
                                       self.model.get_name()))
        self.fr_edit.t_surname.SetValue(self.model.get_surname())
        self.fr_edit.t_name.SetValue(self.model.get_name())
        self.fr_edit.t_address.SetValue(self.model.get_address())
        self.fr_edit.t_mail.SetValue(self.model.get_mail())
        self.fr_edit.t_phone.SetValue(self.model.get_phone())
        self.fr_edit.t_mobile.SetValue(self.model.get_mobile())
        self.fr_edit.btn_ed_exit.Bind(wx.EVT_BUTTON, self.on_edit_exit)
        self.fr_edit.btn_ed_save.Bind(wx.EVT_BUTTON, self.on_edit_save)
        evt.Skip()
    def on_item_to_del(self, evt):
        '''Enable the delete-button when an item is selected'''
        self.fr_del.btn_del.Enable()
    def on_text_entry(self, evt):
        '''Enable the Save-button of add-contact-frame'''
        self.fr_add.btn_ed_save.Enable()
        for textctrl in self.fr_add.panel.GetChildren():
            if isinstance(textctrl, wx.TextCtrl):
                textctrl.Enable()
    def set_list_values(self):
        '''Set the list-ctrl values to model variables'''
        row = self.fr_find.list_ctrl.GetFocusedItem()
        self.model.set_surname(self.fr_find.list_ctrl.GetItem(row, 0).GetText())
        self.model.set_name(self.fr_find.list_ctrl.GetItem(row, 1).GetText())
        self.model.set_address(self.fr_find.list_ctrl.GetItem(row, 2).GetText())
        self.model.set_mail(self.fr_find.list_ctrl.GetItem(row, 3).GetText())
        self.model.set_phone(self.fr_find.list_ctrl.GetItem(row, 4).GetText())
        self.model.set_mobile(self.fr_find.list_ctrl.GetItem(row, 5).GetText())
        print self.model.get_surname(), self.model.get_name()
        return True 

def main_frame():
    '''Application starter'''
    app = wx.PySimpleApp()
    CoreController()
    app.MainLoop()

if __name__ == '__main__':
    main_frame()

Ora eseguendo il file Controller.py, avremo a disposizione la nostra rubrica.
Il codice e le immagini sono disponibili, impacchettate, qui.

Refactoring:

è possibile ridurre il codice unificando le chiamate alla callback di uscita dal frame. Infatti, invece di codificare una callback da legare ad ogni pulsante “exit” di ogni frame, si crea un’unica callback generica dove, tramite il parametro “evt” passatogli come argomento, si risale al parent del widget bottone cliccato e, una volta raggiunto il livello window, lo si chiude.
es:

    def on_btn_find(self, evt):
        ...
        self.fr_find.btn_find_exit.Bind(wx.EVT_BUTTON, self.on_generic_exit)
        ...
    def on_btn_del(self, evt):
        ...
        self.fr_del.btn_exit_del.Bind(wx.EVT_BUTTON, self.on_generic_exit)
        ...
    def on_generic_exit(self, evt):
        '''Exit from current frame'''
        btn = evt.GetEventObject()
        panel = btn.GetParent()
        frame = panel.GetParent()
        frame.Destroy()
Categorie:python, wxpython Tag:
I commenti sono chiusi.