import wx import wx.lib.newevent import settings from database import db_conn from graph import GraphPanel from graphdata import graphdata from pymisc import _ (AnimalSelectedEvent, EVT_ANIMAL_SELECTED) = wx.lib.newevent.NewEvent() class TopPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) self.cursor = db_conn.cursor() self.sectionchoice = wx.Choice(self) self.penchoice = wx.Choice(self) self.animalchoice = wx.Choice(self) self.sectionids = [] self.penids = [] self.animalids = [] self.oldanimalid = None self.update_selections() self.sizer = wx.BoxSizer(wx.HORIZONTAL) self.sizer.Add(self.sectionchoice, flag = wx.LEFT, border = 5) self.sizer.Add(self.penchoice, flag = wx.LEFT, border = 5) self.sizer.Add(self.animalchoice, flag = wx.LEFT | wx.RIGHT, border = 5) self.SetAutoLayout(True) self.SetSizer(self.sizer) self.Layout() self.sectionchoice.Bind(wx.EVT_CHOICE, self.update_selections) self.penchoice.Bind(wx.EVT_CHOICE, self.update_selections) self.animalchoice.Bind(wx.EVT_CHOICE, self.checkanimalid) def update_selections(self, evt = None): def update_control(control, oldchoices, newchoices, newstrings): try: oldchoice = oldchoices[control.GetSelection()] except IndexError: oldchoice = None control.SetItems(newstrings) control.SetSize(control.GetBestSize()) if oldchoice in newchoices: control.SetSelection(newchoices.index(oldchoice)) else: control.SetSelection(0) self.cursor.execute("SELECT section FROM groups GROUP BY section") sectionids = [i[0] for i in self.cursor.fetchall()] sectionstrings = [_("Section %d") % i for i in sectionids] update_control(self.sectionchoice, self.sectionids, sectionids, sectionstrings) self.sectionids = sectionids sectionid = self.sectionids[self.sectionchoice.GetSelection()] self.cursor.execute("SELECT pen FROM groups WHERE section=? GROUP BY pen", (sectionid, )) penids = [i[0] for i in self.cursor.fetchall()] penstrings = [_("Pen %d") % i for i in penids] update_control(self.penchoice, self.penids, penids, penstrings) self.penids = penids penid = self.penids[self.penchoice.GetSelection()] self.cursor.execute("SELECT groupid FROM groups WHERE section=? AND pen=?", (sectionid, penid)) row = self.cursor.fetchone() if row: groupid = row[0] else: groupid = None self.cursor.execute("SELECT animalid FROM animals WHERE groupid=?", (groupid, )) animalids = [i[0] for i in self.cursor.fetchall()] animalstrings = [_("Animal %d") % i for i in animalids] update_control(self.animalchoice, self.animalids, animalids, animalstrings) self.animalids = animalids self.checkanimalid() def checkanimalid(self, evt = None): animalid = self.getanimalid() if animalid != self.oldanimalid: self.oldanimalid = animalid wx.PostEvent(self, AnimalSelectedEvent()) def getanimalid(self): try: return self.animalids[self.animalchoice.GetSelection()] except IndexError: return None class GraphOptPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent) self.graphpanel = GraphPanel(self) #self.graphpanel = wx.Panel(self) self.gtype_days = wx.RadioButton(self, label = _("&Days"), style = wx.RB_GROUP) self.gtype_feeds = wx.RadioButton(self, label = _("&Feed times")) self.avgs_section = wx.CheckBox(self, label = _("Show §ion average")) self.avgs_group = wx.CheckBox(self, label = _("Show &pen average")) self.gtype_sizer = wx.BoxSizer(wx.HORIZONTAL) self.gtype_sizer.Add(wx.StaticText(self, label = _("Graph by:")), flag = wx.LEFT | wx.ALIGN_CENTER, border = 5) self.gtype_sizer.Add(self.gtype_days, flag = wx.LEFT, border = 5) self.gtype_sizer.Add(self.gtype_feeds, flag = wx.LEFT | wx.RIGHT, border = 5) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.graphpanel, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5) self.sizer.Add(self.gtype_sizer, flag = wx.LEFT | wx.RIGHT, border = 5) self.sizer.Add(self.avgs_section, flag = wx.LEFT | wx.RIGHT, border = 5) self.sizer.Add(self.avgs_group, flag = wx.LEFT | wx.RIGHT, border = 5) self.SetAutoLayout(True) self.SetSizer(self.sizer) self.Layout() self.avgs_group.Bind(wx.EVT_CHECKBOX, self.updateavgs) self.avgs_section.Bind(wx.EVT_CHECKBOX, self.updateavgs) self.gtype_feeds.Bind(wx.EVT_RADIOBUTTON, self.updategraphdata) self.gtype_days.Bind(wx.EVT_RADIOBUTTON, self.updategraphdata) def setanimalid(self, animalid): self.animalid = animalid self.updategraphdata() def updategraphdata(self, evt = None): days = self.gtype_days.GetValue() data = graphdata(self.animalid, days) self.graphpanel.setdata(data) self.avgs_section.Enable(days) self.avgs_group.Enable(days) if days: self.updateavgs() # Does redrawing also else: self.graphpanel.show_groupaverage = False self.graphpanel.show_sectionaverage = False self.graphpanel.redraw() def updateavgs(self, evt = None): self.graphpanel.show_groupaverage = self.avgs_group.GetValue() self.graphpanel.show_sectionaverage = self.avgs_section.GetValue() self.graphpanel.redraw() class InfoPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent, style = wx.TAB_TRAVERSAL) self.cursor = db_conn.cursor() self.noticelist = wx.ListBox(self) self.notestext = wx.TextCtrl(self, style = wx.TE_MULTILINE) self.noticelabel = wx.StaticText(self, label = _("Notices:")) self.noteslabel = wx.StaticText(self, label = _("Notes:")) self.savebutton = wx.Button(self, label = _("Save")) self.savebutton.SetDefault() self.cancelbutton = wx.Button(self, label = _("Revert")) self.buttonsizer = wx.BoxSizer(wx.HORIZONTAL) self.buttonsizer.Add(self.savebutton, proportion = 1, flag = wx.EXPAND) self.buttonsizer.Add(self.cancelbutton, proportion = 1, flag = wx.EXPAND) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.noticelabel, flag = wx.LEFT, border = 5) self.sizer.Add(self.noticelist, proportion = 1, flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 5) self.sizer.Add(self.noteslabel, flag = wx.TOP | wx.LEFT, border = 5) self.sizer.Add(self.notes, proportion = 1, flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border = 5) self.sizer.Add(self.buttonsizer, flag = wx.EXPAND | wx.ALL, border = 5) self.SetAutoLayout(True) self.SetSizer(self.sizer) self.Layout() def setanimalid(self, animalid, save = True): if save: if not self.save(ask = True): # Cancel button return False self.cursor.execute("SELECT notes FROM animals WHERE animalid=?", (animalid, )) notes = self.cursor.fetchall()[0][0] self.notestext.SetValue(notes) self.notestext.SetModified(False) self.animalid = animalid return True def save(self, evt = None, ask = False): """Save changes to notes. Ask with dialogbox before saving if ask is True. Returns False if user cancels the dialogbox, True otherwise.""" if ask: if not self.notestext.IsModified(): return True dlg = wx.MessageDialog(self, caption = _("Save changes?"), message = _("Notes for this animal have been modified. " + "Do you want to save changes?"), style = wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION) result = dlg.ShowModal() if result != wx.YES: return False self.cursor.execute("UPDATE animals SET notes=? WHERE animalid=?", (self.notestext.GetValue(), self.animalid)) self.notestext.SetModified(False) return True class AnimalDialog(wx.Frame): def __init__(self, parent, animalid = None, title = None): wx.Frame.__init__(self, parent) if not title: self.title = _("Details for animal %d") self.toppanel = TopPanel(self) self.bottom = wx.SplitterWindow(self) self.graphoptpanel = GraphOptPanel(self.bottom) self.infopanel = InfoPanel(self.bottom) self.bottom.SplitVertically(self.graphoptpanel, self.infopanel) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.toppanel, flag = wx.EXPAND | wx.TOP, border = 5) self.sizer.Add(wx.StaticLine(self), flag = wx.EXPAND | wx.ALL, border = 5) self.sizer.Add(self.bottom, proportion = 1, flag = wx.EXPAND) self.SetAutoLayout(True) self.SetSizer(self.sizer) self.Layout() self.graphoptpanel.SetMinSize(self.graphoptpanel.GetBestSize()) self.SetMinSize(self.GetBestSize()) self.toppanel.Bind(EVT_ANIMAL_SELECTED, self.OnAnimalSelected) def OnAnimalSelected(self, evt = None): animalid = self.toppanel.getanimalid() self.SetTitle(self.title % animalid) self.graphoptpanel.setanimalid(animalid) if __name__ == "__main__": print "Unit testing" class MyApp(wx.App): def OnInit(self): wx.InitAllImageHandlers() dialog = AnimalDialog(None) dialog.Show(True) self.SetTopWindow(dialog) return True app = MyApp(0) app.MainLoop()