def perform_tally(self, questions): ''' Actually calls to openstv to perform the tally ''' from openstv.ballots import Ballots from openstv.plugins import getMethodPlugins # get voting and report methods methods = getMethodPlugins("byName", exclude0=False) # generate ballots dirtyBallots = Ballots() dirtyBallots.loadKnown(self.ballots_path, exclude0=False) dirtyBallots.numSeats = self.num_winners cleanBallots = dirtyBallots.getCleanBallots() # create and configure election e = methods[self.method_name](cleanBallots) question = questions[self.question_num] e.maxChosableOptions = question['max'] # run election and generate the report e.runElection() # generate report from .json_report import JsonReport self.report = JsonReport(e) self.report.generateReport()
def perform_tally(self): ''' Actually calls to openstv to perform the tally ''' from openstv.ballots import Ballots from openstv.plugins import getMethodPlugins # get voting and report methods methods = getMethodPlugins("byName", exclude0=False) # generate ballots dirtyBallots = Ballots() dirtyBallots.loadKnown(self.ballots_path, exclude0=False) dirtyBallots.numSeats = self.num_seats cleanBallots = dirtyBallots.getCleanBallots() # create and configure election e = methods[self.method_name](cleanBallots) if self.strong_tie_break_method is not None: e.strongTieBreakMethod = self.strong_tie_break_method if self.weak_tie_break_method is not None: e.weakTieBreakMethod = self.weak_tie_break_method if self.digits_precision is not None: e.prec = self.digits_precision # run election and generate the report e.runElection() # generate report from .json_report import JsonReport self.report = JsonReport(e) self.report.generateReport()
def load_ballot(self, ballot): try: dirtyBallots = Ballots() dirtyBallots.loadKnown(bltFn, exclude0=False) cleanBallots = dirtyBallots.getCleanBallots() except RuntimeError, msg: print msg
def perform_tally(self): ''' Actually calls to openstv to perform the tally ''' from openstv.ballots import Ballots from openstv.plugins import getMethodPlugins # get voting and report methods methods = getMethodPlugins("byName", exclude0=False) # generate ballots dirtyBallots = Ballots() dirtyBallots.loadKnown(self.ballots_path, exclude0=False) dirtyBallots.numSeats = self.num_seats cleanBallots = dirtyBallots.getCleanBallots() # create and configure election e = methods[self.method_name](cleanBallots) # run election and generate the report # from celery.contrib import rdb; rdb.set_trace() e.runElection() # generate report from .json_report import JsonReport self.report = JsonReport(e) self.report.generateReport()
def perform_tally(self): ''' Actually calls to openstv to perform the tally ''' from openstv.ballots import Ballots from openstv.plugins import getMethodPlugins # get voting and report methods methods = getMethodPlugins("byName", exclude0=False) # generate ballots dirtyBallots = Ballots() dirtyBallots.loadKnown(self.ballots_path, exclude0=False) dirtyBallots.numSeats = self.num_winners cleanBallots = dirtyBallots.getCleanBallots() # create and configure election e = methods[self.method_name](cleanBallots) # run election and generate the report # from celery.contrib import rdb; rdb.set_trace() e.runElection() # generate report from .json_report import JsonReport self.report = JsonReport(e) self.report.generateReport()
def loadBallots(self): self.dirtyBallots = Ballots() self.dirtyBallots.exceptionQueue = Queue(1) loadThread = Thread(target=self.dirtyBallots.loadUnknown, args=(self.filename, )) loadThread.start() # Display a progress dialog dlg = wx.ProgressDialog(\ "Loading ballots", "Loading ballots from %s\nNumber of ballots: %d" % (os.path.basename(self.filename), self.dirtyBallots.numBallots), parent=self.frame, style = wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME ) while loadThread.isAlive(): sleep(0.1) dlg.Pulse("Loading ballots from %s\nNumber of ballots: %d" % (os.path.basename( self.filename), self.dirtyBallots.numBallots)) dlg.Destroy() if not self.dirtyBallots.exceptionQueue.empty(): raise RuntimeError(self.dirtyBallots.exceptionQueue.get())
def iterate_rankings(names, votes, withdrawn_names): "Determine at least one winner" # If there's only one candidate left, return it if len(names) - len(withdrawn_names) == 1: return set(names) - set(withdrawn_names) ballots = Ballots() ballots.setAllNames(names) withdrawn_indices = [names.index(name) for name in withdrawn_names] ballots.setWithdrawn(withdrawn_indices) for ranking in votes: ballots.appendBallot(ranking) election = Condorcet(ballots) election.run() winning_names = [ballots.names[winner] for winner in election.winners] return winning_names
def loadBallots(self): self.dirtyBallots = Ballots() self.dirtyBallots.exceptionQueue = Queue(1) loadThread = Thread(target=self.dirtyBallots.loadUnknown, args=(self.filename,)) loadThread.start() # Display a progress dialog dlg = wx.ProgressDialog(\ "Loading ballots", "Loading ballots from %s\nNumber of ballots: %d" % (os.path.basename(self.filename), self.dirtyBallots.numBallots), parent=self.frame, style = wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME ) while loadThread.isAlive(): sleep(0.1) dlg.Pulse("Loading ballots from %s\nNumber of ballots: %d" % (os.path.basename(self.filename), self.dirtyBallots.numBallots)) dlg.Destroy() if not self.dirtyBallots.exceptionQueue.empty(): raise RuntimeError(self.dirtyBallots.exceptionQueue.get())
def count(cls, vote, **kwargs): from Meeting.models import BallotEntry, Vote seats = kwargs.get("num_seats", 1) assert vote.method == Vote.STV ballots = Ballots() options = vote.option_set.all().order_by('pk') option_translation = {} names = [] for index, option in enumerate(options): option_translation[option.id] = index names.append(option.name) ballots.setNames(names) ballots.numSeats = seats voter = -1 ballot = [] for be in BallotEntry.objects.filter(option__vote=vote).order_by('token_id', 'value').all(): if voter != be.token_id and ballot != []: ballots.appendBallot(ballot) ballot = [] voter = be.token_id ballot.append(option_translation[be.option_id]) if ballots != []: ballots.appendBallot(ballot) electionCounter = ScottishSTV(ballots) electionCounter.strongTieBreakMethod = "manual" electionCounter.breakTieRequestQueue = Queue(1) electionCounter.breakTieResponseQueue = Queue(1) countThread = Thread(target=electionCounter.runElection) countThread.start() while countThread.isAlive(): sleep(0.1) if not electionCounter.breakTieRequestQueue.empty(): [tiedCandidates, names, what] = electionCounter.breakTieRequestQueue.get() c = cls.ask_user_to_break_tie(tiedCandidates, names, what, vote) electionCounter.breakTieResponseQueue.put(c) if "R" in vars(electionCounter): status = "Counting votes using {}\nRound: {}".format(electionCounter.longMethodName, electionCounter.R + 1) else: status = "Counting votes using %s\nInitializing..." % \ electionCounter.longMethodName logger.debug(status) logger.info(electionCounter.winners) vote.refresh_from_db() winners = [] losers = [] for w in electionCounter.winners: winners.append(ballots.names[w]) for l in electionCounter.losers: losers.append(ballots.names[l]) vote.results = "Winners: {} \nLosers:{}".format(winners, losers) r = YamlReport(electionCounter, outputToString=True) r.generateReport() report = "\n" for index, name in enumerate(ballots.names): report += "[{}] -> {}\n".format(index, name) report += r.outputFile vote.results += report vote.save()
class Election(): def __init__(self, frame, filename, methodClass): self.frame = frame self.filename = filename self.methodClass = methodClass self.dispWidth = 100 self.dirtyBallots = None self.cleanBallots = None self.e = None def loadBallots(self): self.dirtyBallots = Ballots() self.dirtyBallots.exceptionQueue = Queue(1) loadThread = Thread(target=self.dirtyBallots.loadUnknown, args=(self.filename,)) loadThread.start() # Display a progress dialog dlg = wx.ProgressDialog(\ "Loading ballots", "Loading ballots from %s\nNumber of ballots: %d" % (os.path.basename(self.filename), self.dirtyBallots.numBallots), parent=self.frame, style = wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME ) while loadThread.isAlive(): sleep(0.1) dlg.Pulse("Loading ballots from %s\nNumber of ballots: %d" % (os.path.basename(self.filename), self.dirtyBallots.numBallots)) dlg.Destroy() if not self.dirtyBallots.exceptionQueue.empty(): raise RuntimeError(self.dirtyBallots.exceptionQueue.get()) def initializeElection(self, cleanType): self.cleanBallots = self.dirtyBallots.getCleanBallots(removeOvervotes=cleanType) self.e = self.methodClass(self.cleanBallots) def runElection(self): if not self.frame.breakTiesRandomly: self.e.strongTieBreakMethod = "manual" self.e.breakTieRequestQueue = Queue(1) self.e.breakTieResponseQueue = Queue(1) countThread = Thread(target=self.e.runElection) countThread.start() # Display a progress dialog dlg = wx.ProgressDialog(\ "Counting votes", "Counting votes using %s\nInitializing..." % self.e.longMethodName, parent=self.frame, style = wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME ) while countThread.isAlive(): sleep(0.1) if not self.e.breakTieRequestQueue.empty(): [tiedCandidates, names, what] = self.e.breakTieRequestQueue.get() c = self.askUserToBreakTie(tiedCandidates, names, what) self.e.breakTieResponseQueue.put(c) if "R" in vars(self.e): status = "Counting votes using %s\nRound: %d" % \ (self.e.longMethodName, self.e.R+1) else: status = "Counting votes using %s\nInitializing..." % \ self.e.longMethodName dlg.Pulse(status) dlg.Destroy() def askUserToBreakTie(self, candidates, names, what): "Provide a window to ask the user to break a tie." instructions = """\ Tie when selecting %s. Break the tie by selecting a candidate or choose Cancel to break the tie randomly.""" % what dlg = wx.SingleChoiceDialog(self.frame, instructions, "Break Tie Manually", names, wx.CHOICEDLG_STYLE) if dlg.ShowModal() == wx.ID_OK: selection = dlg.GetStringSelection() i = names.index(selection) return candidates[i] else: return None def generateReport(self, reportObj): reportObj.generateReport() def generateTextOutput(self, output): self.generateReport(TextReport(self.e, self.dispWidth, outputFile=output)) def generateCsvOutput(self, output): self.generateReport(CsvReport(self.e, outputFile=output)) def generateHtmlOutput(self, output): self.generateReport(HtmlReport(self.e, outputFile=output))
print "Specify method and ballot file" else: print "Too many arguments" print usage sys.exit(1) name = args[0] bltFn = args[1] if name not in methodNames: print "Unrecognized method '%s'" % name print usage sys.exit(1) try: dirtyBallots = Ballots() dirtyBallots.loadKnown(bltFn, exclude0=False) if numSeats: dirtyBallots.numSeats = numSeats cleanBallots = dirtyBallots.getCleanBallots() except RuntimeError, msg: print msg sys.exit(1) def doElection(reps=1): "run election with repeat count for profiling" for i in xrange(reps): e = methods[name](cleanBallots) if strongTieBreakMethod is not None: e.strongTieBreakMethod = strongTieBreakMethod
class Election(): def __init__(self, frame, filename, methodClass): self.frame = frame self.filename = filename self.methodClass = methodClass self.dispWidth = 100 self.dirtyBallots = None self.cleanBallots = None self.e = None def loadBallots(self): self.dirtyBallots = Ballots() self.dirtyBallots.exceptionQueue = Queue(1) loadThread = Thread(target=self.dirtyBallots.loadUnknown, args=(self.filename, )) loadThread.start() # Display a progress dialog dlg = wx.ProgressDialog(\ "Loading ballots", "Loading ballots from %s\nNumber of ballots: %d" % (os.path.basename(self.filename), self.dirtyBallots.numBallots), parent=self.frame, style = wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME ) while loadThread.isAlive(): sleep(0.1) dlg.Pulse("Loading ballots from %s\nNumber of ballots: %d" % (os.path.basename( self.filename), self.dirtyBallots.numBallots)) dlg.Destroy() if not self.dirtyBallots.exceptionQueue.empty(): raise RuntimeError(self.dirtyBallots.exceptionQueue.get()) def initializeElection(self, cleanType): self.cleanBallots = self.dirtyBallots.getCleanBallots( removeOvervotes=cleanType) self.e = self.methodClass(self.cleanBallots) def runElection(self): if not self.frame.breakTiesRandomly: self.e.strongTieBreakMethod = "manual" self.e.breakTieRequestQueue = Queue(1) self.e.breakTieResponseQueue = Queue(1) countThread = Thread(target=self.e.runElection) countThread.start() # Display a progress dialog dlg = wx.ProgressDialog(\ "Counting votes", "Counting votes using %s\nInitializing..." % self.e.longMethodName, parent=self.frame, style = wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME ) while countThread.isAlive(): sleep(0.1) if not self.e.breakTieRequestQueue.empty(): [tiedCandidates, names, what] = self.e.breakTieRequestQueue.get() c = self.askUserToBreakTie(tiedCandidates, names, what) self.e.breakTieResponseQueue.put(c) if "R" in vars(self.e): status = "Counting votes using %s\nRound: %d" % \ (self.e.longMethodName, self.e.R+1) else: status = "Counting votes using %s\nInitializing..." % \ self.e.longMethodName dlg.Pulse(status) dlg.Destroy() def askUserToBreakTie(self, candidates, names, what): "Provide a window to ask the user to break a tie." instructions = """\ Tie when selecting %s. Break the tie by selecting a candidate or choose Cancel to break the tie randomly.""" % what dlg = wx.SingleChoiceDialog(self.frame, instructions, "Break Tie Manually", names, wx.CHOICEDLG_STYLE) if dlg.ShowModal() == wx.ID_OK: selection = dlg.GetStringSelection() i = names.index(selection) return candidates[i] else: return None def generateReport(self, reportObj): reportObj.generateReport() def generateTextOutput(self, output): self.generateReport( TextReport(self.e, self.dispWidth, outputFile=output)) def generateCsvOutput(self, output): self.generateReport(CsvReport(self.e, outputFile=output)) def generateHtmlOutput(self, output): self.generateReport(HtmlReport(self.e, outputFile=output))
print "Specify method and ballot file" else: print "Too many arguments" print usage sys.exit(1) name = args[0] bltFn = args[1] if name not in methodNames: print "Unrecognized method '%s'" % name print usage sys.exit(1) try: dirtyBallots = Ballots() dirtyBallots.loadKnown(bltFn, exclude0=False) if numSeats: dirtyBallots.numSeats = numSeats cleanBallots = dirtyBallots.getCleanBallots() except RuntimeError, msg: print msg sys.exit(1) def doElection(reps=1): "run election with repeat count for profiling" for i in xrange(reps): e = methods[name](cleanBallots) if strongTieBreakMethod is not None: e.strongTieBreakMethod = strongTieBreakMethod if weakTieBreakMethod is not None:
def __init__(self, parent, mode): wx.Frame.__init__(self, parent, -1, "Ballot File Editor") warnings.showwarning = self.catchWarnings self.MakeMenu() self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) self.logfName = "" fn = os.path.join(getHome(), "Icons", "blt.ico") icon = wx.Icon(fn, wx.BITMAP_TYPE_ICO) self.SetIcon(icon) # Edit a new ballot file if mode == "new": # Create an empty ballots class instance self.b = Ballots() # Get the candidate names from the user dlg = CandidatesDialog(parent, self.b) dlg.Center() if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() self.Destroy() return dlg.Destroy() # Edit an existing ballot file elif mode == "old": dlg = wx.FileDialog(self, "Edit Ballot File", style=wx.FD_OPEN|wx.FD_CHANGE_DIR) if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() self.Destroy() return fName = dlg.GetPath() dlg.Destroy() # Open the file try: self.b = Ballots() self.b.loadUnknown(fName) except RuntimeError as msg: wx.MessageBox(str(msg), "Error", wx.OK|wx.ICON_ERROR) self.Destroy() return else: assert(0) # Set the window title to include the filename fn = self.b.getFileName() if fn is not None: title = "%s - Ballot File Editor" % os.path.basename(fn) else: title = "%s - Ballot File Editor" % "New File" self.SetTitle(title) # Create a notebook with an editing page and a log page nb = wx.Notebook(self, -1) self.panel = BallotsPanel(nb, self.b) nb.AddPage(self.panel, "Ballots") self.logN = 1 # counter for display purposes self.log = wx.TextCtrl(nb, -1, style=wx.TE_MULTILINE|wx.TE_READONLY|\ wx.TE_WORDWRAP|wx.FIXED) nb.AddPage(self.log, "Log") # Initialize if mode == "new": self.panel.NeedToSaveBallots = True self.Log("Created a new ballot file.") elif mode == "old": self.panel.NeedToSaveBallots = False self.Log("Loaded %d ballots from file %s." %\ (self.b.numBallots, os.path.basename(self.b.getFileName()))) else: assert(0) # Set up the sizer sizer = wx.BoxSizer() sizer.Add(nb, 1, wx.EXPAND, 0) self.SetSizer(sizer) sizer.Fit(self) sizer.SetSizeHints(self)
def __init__(self, parent, mode): wx.Frame.__init__(self, parent, -1, "Ballot File Editor") warnings.showwarning = self.catchWarnings self.MakeMenu() self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) self.logfName = "" fn = os.path.join(getHome(), "Icons", "blt.ico") icon = wx.Icon(fn, wx.BITMAP_TYPE_ICO) self.SetIcon(icon) # Edit a new ballot file if mode == "new": # Create an empty ballots class instance self.b = Ballots() # Get the candidate names from the user dlg = CandidatesDialog(parent, self.b) dlg.Center() if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() self.Destroy() return dlg.Destroy() # Edit an existing ballot file elif mode == "old": dlg = wx.FileDialog(self, "Edit Ballot File", style=wx.OPEN|wx.CHANGE_DIR) if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() self.Destroy() return fName = dlg.GetPath() dlg.Destroy() # Open the file try: self.b = Ballots() self.b.loadUnknown(fName) except RuntimeError as msg: wx.MessageBox(str(msg), "Error", wx.OK|wx.ICON_ERROR) self.Destroy() return else: assert(0) # Set the window title to include the filename fn = self.b.getFileName() if fn is not None: title = "%s - Ballot File Editor" % os.path.basename(fn) else: title = "%s - Ballot File Editor" % "New File" self.SetTitle(title) # Create a notebook with an editing page and a log page nb = wx.Notebook(self, -1) self.panel = BallotsPanel(nb, self.b) nb.AddPage(self.panel, "Ballots") self.logN = 1 # counter for display purposes self.log = wx.TextCtrl(nb, -1, style=wx.TE_MULTILINE|wx.TE_READONLY|\ wx.TE_WORDWRAP|wx.FIXED) self.log.SetMaxLength(0) nb.AddPage(self.log, "Log") # Initialize if mode == "new": self.panel.NeedToSaveBallots = True self.Log("Created a new ballot file.") elif mode == "old": self.panel.NeedToSaveBallots = False self.Log("Loaded %d ballots from file %s." %\ (self.b.numBallots, os.path.basename(self.b.getFileName()))) else: assert(0) # Set up the sizer sizer = wx.BoxSizer() sizer.Add(nb, 1, wx.EXPAND, 0) self.SetSizer(sizer) sizer.Fit(self) sizer.SetSizeHints(self)
class BFEFrame(wx.Frame): def __init__(self, parent, mode): wx.Frame.__init__(self, parent, -1, "Ballot File Editor") warnings.showwarning = self.catchWarnings self.MakeMenu() self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) self.logfName = "" fn = os.path.join(getHome(), "Icons", "blt.ico") icon = wx.Icon(fn, wx.BITMAP_TYPE_ICO) self.SetIcon(icon) # Edit a new ballot file if mode == "new": # Create an empty ballots class instance self.b = Ballots() # Get the candidate names from the user dlg = CandidatesDialog(parent, self.b) dlg.Center() if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() self.Destroy() return dlg.Destroy() # Edit an existing ballot file elif mode == "old": dlg = wx.FileDialog(self, "Edit Ballot File", style=wx.FD_OPEN|wx.FD_CHANGE_DIR) if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() self.Destroy() return fName = dlg.GetPath() dlg.Destroy() # Open the file try: self.b = Ballots() self.b.loadUnknown(fName) except RuntimeError as msg: wx.MessageBox(str(msg), "Error", wx.OK|wx.ICON_ERROR) self.Destroy() return else: assert(0) # Set the window title to include the filename fn = self.b.getFileName() if fn is not None: title = "%s - Ballot File Editor" % os.path.basename(fn) else: title = "%s - Ballot File Editor" % "New File" self.SetTitle(title) # Create a notebook with an editing page and a log page nb = wx.Notebook(self, -1) self.panel = BallotsPanel(nb, self.b) nb.AddPage(self.panel, "Ballots") self.logN = 1 # counter for display purposes self.log = wx.TextCtrl(nb, -1, style=wx.TE_MULTILINE|wx.TE_READONLY|\ wx.TE_WORDWRAP|wx.FIXED) nb.AddPage(self.log, "Log") # Initialize if mode == "new": self.panel.NeedToSaveBallots = True self.Log("Created a new ballot file.") elif mode == "old": self.panel.NeedToSaveBallots = False self.Log("Loaded %d ballots from file %s." %\ (self.b.numBallots, os.path.basename(self.b.getFileName()))) else: assert(0) # Set up the sizer sizer = wx.BoxSizer() sizer.Add(nb, 1, wx.EXPAND, 0) self.SetSizer(sizer) sizer.Fit(self) sizer.SetSizeHints(self) def catchWarnings(self, message, category, filename, lineno): "Catch any warnings and display them in a dialog box." wx.MessageBox(str(message), "Warning", wx.OK|wx.ICON_INFORMATION) def Log(self, txt): # create a prompt for each new line prompt = "%3d: " % self.logN self.log.AppendText(prompt + txt + "\n") self.logN += 1 def MakeMenu(self): fileMenu = wx.Menu() append = fileMenu.Append(-1, "A&ppend ballots from file...") saveBallots = fileMenu.Append(-1, "&Save ballots") saveBallotsAs = fileMenu.Append(-1, "Save ballots &as...") saveLog = fileMenu.Append(-1, "Save &log") saveLogAs = fileMenu.Append(-1, "Save log as...") exitBFE = fileMenu.Append(wx.ID_EXIT, "E&xit") self.Bind(wx.EVT_MENU, self.OnAppendBF, append) self.Bind(wx.EVT_MENU, self.OnSaveBallots, saveBallots) self.Bind(wx.EVT_MENU, self.OnSaveBallotsAs, saveBallotsAs) self.Bind(wx.EVT_MENU, self.OnSaveLog, saveLog) self.Bind(wx.EVT_MENU, self.OnSaveLogAs, saveLogAs) self.Bind(wx.EVT_MENU, self.OnExit, exitBFE) if wx.Platform == "__WXMAC__": wx.App.SetMacExitMenuItemId(wx.ID_EXIT) menuBar = wx.MenuBar() menuBar.Append(fileMenu, "&File") self.SetMenuBar(menuBar) def OnAppendBF(self, event): # Get the filename of the ballots to be appended dlg = wx.FileDialog(self, "Select Ballot File", style=wx.FD_OPEN|wx.FD_CHANGE_DIR) if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() return fName = dlg.GetPath() dlg.Destroy() # Attempt to append the ballots try: oldNumBallots = self.b.numBallots self.b.appendFile(fName) self.b = self.b.getCleanBallots(removeEmpty=False, removeWithdrawn=False) except RuntimeError as msg: wx.MessageBox(str(msg), "Error", wx.OK|wx.ICON_ERROR) else: self.Log("Appended %d ballots from file %s." %\ (self.b.numBallots - oldNumBallots, os.path.basename(fName))) self.panel.NeedToSaveBallots = True self.panel.NeedToSaveLog = True self.panel.UpdatePanel() def OnSaveBallots(self, event): if self.b.getFileName() is None: self.OnSaveBallotsAs(event) return try: self.b.save() except RuntimeError as msg: wx.MessageBox(str(msg), "Error", wx.OK|wx.ICON_ERROR) return self.panel.NeedToSaveBallots = False def OnSaveBallotsAs(self, event): # Ask the user to choose the filename. dlg = wx.FileDialog(self, "Save Ballot File", style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.FD_CHANGE_DIR) if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() return fName = dlg.GetPath() dlg.Destroy() # Save try: self.b.saveAs(fName) except RuntimeError as msg: wx.MessageBox(str(msg), "Error", wx.OK|wx.ICON_ERROR) return self.panel.NeedToSaveBallots = False # Set the window title to include the filename title = "%s - Ballot File Editor" % os.path.basename(fName) self.SetTitle(title) self.panel.fNameC.SetLabel(os.path.basename(fName)) def OnSaveLog(self, event): if self.logfName == "": self.OnSaveLogAs(event) return try: self.log.SaveFile(self.logfName) except RuntimeError as msg: wx.MessageBox(str(msg), "Error", wx.OK|wx.ICON_ERROR) return self.panel.NeedToSaveLog = False def OnSaveLogAs(self, event): dlg = wx.FileDialog(self, "Save Log to a File", style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT|wx.FD_CHANGE_DIR) if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() return self.logfName = dlg.GetPath() dlg.Destroy() try: self.log.SaveFile(self.logfName) except RuntimeError as msg: wx.MessageBox(str(msg), "Error", wx.OK|wx.ICON_ERROR) return self.panel.NeedToSaveLog = False def OnExit(self, event): self.Close() def OnCloseWindow(self, event): # Check to see if the current ballot is empty and warn user if self.panel.currentBallot == []: txt = "The current ballot is empty. Ok to close editor?" code = wx.MessageBox(txt, "Warning", wx.OK|wx.CANCEL|wx.ICON_QUESTION) if code == wx.CANCEL: # Don't exit event.Veto() return # Ask user if we should save ballots. if self.panel.NeedToSaveBallots == True: if self.b.getFileName() is None: msg = "Do you want to save the ballots?" else: msg = "Do you want to save the ballots to %s?" % self.b.getFileName() saveBallots = wx.MessageBox(msg, "Warning", wx.YES_NO|wx.CANCEL|wx.ICON_INFORMATION) if saveBallots == wx.CANCEL: event.Veto() # Don't exit return elif saveBallots == wx.YES: self.OnSaveBallots(None) # Save ballots elif saveBallots == wx.NO: # If user is discarding ballot changes then don't ask to save the log self.panel.NeedToSaveLog = False # Ask user if we should also save the log. if self.panel.NeedToSaveLog == True: msg = "Do you want to save the log for ballot file %s?"\ % os.path.basename(self.b.getFileName()) saveLog = wx.MessageBox(msg, "Warning", wx.YES_NO|wx.CANCEL|wx.ICON_INFORMATION) if saveLog == wx.CANCEL: event.Veto() # Don't exit return elif saveLog == wx.YES: self.OnSaveLog(None) # Save log self.Destroy()
class BFEFrame(wx.Frame): def __init__(self, parent, mode): wx.Frame.__init__(self, parent, -1, "Ballot File Editor") warnings.showwarning = self.catchWarnings self.MakeMenu() self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) self.logfName = "" fn = os.path.join(getHome(), "Icons", "blt.ico") icon = wx.Icon(fn, wx.BITMAP_TYPE_ICO) self.SetIcon(icon) # Edit a new ballot file if mode == "new": # Create an empty ballots class instance self.b = Ballots() # Get the candidate names from the user dlg = CandidatesDialog(parent, self.b) dlg.Center() if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() self.Destroy() return dlg.Destroy() # Edit an existing ballot file elif mode == "old": dlg = wx.FileDialog(self, "Edit Ballot File", style=wx.OPEN|wx.CHANGE_DIR) if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() self.Destroy() return fName = dlg.GetPath() dlg.Destroy() # Open the file try: self.b = Ballots() self.b.loadUnknown(fName) except RuntimeError as msg: wx.MessageBox(str(msg), "Error", wx.OK|wx.ICON_ERROR) self.Destroy() return else: assert(0) # Set the window title to include the filename fn = self.b.getFileName() if fn is not None: title = "%s - Ballot File Editor" % os.path.basename(fn) else: title = "%s - Ballot File Editor" % "New File" self.SetTitle(title) # Create a notebook with an editing page and a log page nb = wx.Notebook(self, -1) self.panel = BallotsPanel(nb, self.b) nb.AddPage(self.panel, "Ballots") self.logN = 1 # counter for display purposes self.log = wx.TextCtrl(nb, -1, style=wx.TE_MULTILINE|wx.TE_READONLY|\ wx.TE_WORDWRAP|wx.FIXED) self.log.SetMaxLength(0) nb.AddPage(self.log, "Log") # Initialize if mode == "new": self.panel.NeedToSaveBallots = True self.Log("Created a new ballot file.") elif mode == "old": self.panel.NeedToSaveBallots = False self.Log("Loaded %d ballots from file %s." %\ (self.b.numBallots, os.path.basename(self.b.getFileName()))) else: assert(0) # Set up the sizer sizer = wx.BoxSizer() sizer.Add(nb, 1, wx.EXPAND, 0) self.SetSizer(sizer) sizer.Fit(self) sizer.SetSizeHints(self) def catchWarnings(self, message, category, filename, lineno): "Catch any warnings and display them in a dialog box." wx.MessageBox(str(message), "Warning", wx.OK|wx.ICON_INFORMATION) def Log(self, txt): # create a prompt for each new line prompt = "%3d: " % self.logN self.log.AppendText(prompt + txt + "\n") self.logN += 1 def MakeMenu(self): fileMenu = wx.Menu() append = fileMenu.Append(-1, "A&ppend ballots from file...") saveBallots = fileMenu.Append(-1, "&Save ballots") saveBallotsAs = fileMenu.Append(-1, "Save ballots &as...") saveLog = fileMenu.Append(-1, "Save &log") saveLogAs = fileMenu.Append(-1, "Save log as...") exitBFE = fileMenu.Append(wx.ID_EXIT, "E&xit") self.Bind(wx.EVT_MENU, self.OnAppendBF, append) self.Bind(wx.EVT_MENU, self.OnSaveBallots, saveBallots) self.Bind(wx.EVT_MENU, self.OnSaveBallotsAs, saveBallotsAs) self.Bind(wx.EVT_MENU, self.OnSaveLog, saveLog) self.Bind(wx.EVT_MENU, self.OnSaveLogAs, saveLogAs) self.Bind(wx.EVT_MENU, self.OnExit, exitBFE) if wx.Platform == "__WXMAC__": wx.App.SetMacExitMenuItemId(wx.ID_EXIT) menuBar = wx.MenuBar() menuBar.Append(fileMenu, "&File") self.SetMenuBar(menuBar) def OnAppendBF(self, event): # Get the filename of the ballots to be appended dlg = wx.FileDialog(self, "Select Ballot File", style=wx.OPEN|wx.CHANGE_DIR) if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() return fName = dlg.GetPath() dlg.Destroy() # Attempt to append the ballots try: oldNumBallots = self.b.numBallots self.b.appendFile(fName) self.b = self.b.getCleanBallots(removeEmpty=False, removeWithdrawn=False) except RuntimeError as msg: wx.MessageBox(str(msg), "Error", wx.OK|wx.ICON_ERROR) else: self.Log("Appended %d ballots from file %s." %\ (self.b.numBallots - oldNumBallots, os.path.basename(fName))) self.panel.NeedToSaveBallots = True self.panel.NeedToSaveLog = True self.panel.UpdatePanel() def OnSaveBallots(self, event): if self.b.getFileName() is None: self.OnSaveBallotsAs(event) return try: self.b.save() except RuntimeError as msg: wx.MessageBox(str(msg), "Error", wx.OK|wx.ICON_ERROR) return self.panel.NeedToSaveBallots = False def OnSaveBallotsAs(self, event): # Ask the user to choose the filename. dlg = wx.FileDialog(self, "Save Ballot File", style=wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR) if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() return fName = dlg.GetPath() dlg.Destroy() # Save try: self.b.saveAs(fName) except RuntimeError as msg: wx.MessageBox(str(msg), "Error", wx.OK|wx.ICON_ERROR) return self.panel.NeedToSaveBallots = False # Set the window title to include the filename title = "%s - Ballot File Editor" % os.path.basename(fName) self.SetTitle(title) self.panel.fNameC.SetLabel(os.path.basename(fName)) def OnSaveLog(self, event): if self.logfName == "": self.OnSaveLogAs(event) return try: self.log.SaveFile(self.logfName) except RuntimeError as msg: wx.MessageBox(str(msg), "Error", wx.OK|wx.ICON_ERROR) return self.panel.NeedToSaveLog = False def OnSaveLogAs(self, event): dlg = wx.FileDialog(self, "Save Log to a File", style=wx.SAVE|wx.OVERWRITE_PROMPT|wx.CHANGE_DIR) if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() return self.logfName = dlg.GetPath() dlg.Destroy() try: self.log.SaveFile(self.logfName) except RuntimeError as msg: wx.MessageBox(str(msg), "Error", wx.OK|wx.ICON_ERROR) return self.panel.NeedToSaveLog = False def OnExit(self, event): self.Close() def OnCloseWindow(self, event): # Check to see if the current ballot is empty and warn user if self.panel.currentBallot == []: txt = "The current ballot is empty. Ok to close editor?" code = wx.MessageBox(txt, "Warning", wx.OK|wx.CANCEL|wx.ICON_QUESTION) if code == wx.CANCEL: # Don't exit event.Veto() return # Ask user if we should save ballots. if self.panel.NeedToSaveBallots == True: if self.b.getFileName() is None: msg = "Do you want to save the ballots?" else: msg = "Do you want to save the ballots to %s?" % self.b.getFileName() saveBallots = wx.MessageBox(msg, "Warning", wx.YES_NO|wx.CANCEL|wx.ICON_INFORMATION) if saveBallots == wx.CANCEL: event.Veto() # Don't exit return elif saveBallots == wx.YES: self.OnSaveBallots(None) # Save ballots elif saveBallots == wx.NO: # If user is discarding ballot changes then don't ask to save the log self.panel.NeedToSaveLog = False # Ask user if we should also save the log. if self.panel.NeedToSaveLog == True: msg = "Do you want to save the log for ballot file %s?"\ % os.path.basename(self.b.getFileName()) saveLog = wx.MessageBox(msg, "Warning", wx.YES_NO|wx.CANCEL|wx.ICON_INFORMATION) if saveLog == wx.CANCEL: event.Veto() # Don't exit return elif saveLog == wx.YES: self.OnSaveLog(None) # Save log self.Destroy()