import wx, re, locale from tiddlywiki import TiddlyWiki import tweeregex import metrics class StatisticsDialog(wx.Dialog): """ A StatisticsDialog displays the number of characters, words, passages, links, and broken links in a StoryPanel. This is not a live count. """ def __init__(self, parent, storyPanel, app, id = wx.ID_ANY): wx.Dialog.__init__(self, parent, id, title = 'Story Statistics') self.storyPanel = storyPanel # layout panel = wx.Panel(parent = self) self.panelSizer = wx.BoxSizer(wx.VERTICAL) panel.SetSizer(self.panelSizer) # count controls countPanel = wx.Panel(parent = panel) countPanelSizer = wx.FlexGridSizer(6, 2, metrics.size('relatedControls'), metrics.size('relatedControls')) countPanel.SetSizer(countPanelSizer) self.characters = wx.StaticText(countPanel) countPanelSizer.Add(self.characters, flag = wx.ALIGN_RIGHT) countPanelSizer.Add(wx.StaticText(countPanel, label = 'Characters')) self.words = wx.StaticText(countPanel) countPanelSizer.Add(self.words, flag = wx.ALIGN_RIGHT) countPanelSizer.Add(wx.StaticText(countPanel, label = 'Words')) self.passages = wx.StaticText(countPanel) countPanelSizer.Add(self.passages, flag = wx.ALIGN_RIGHT) countPanelSizer.Add(wx.StaticText(countPanel, label = 'Passages')) self.links = wx.StaticText(countPanel) countPanelSizer.Add(self.links, flag = wx.ALIGN_RIGHT) countPanelSizer.Add(wx.StaticText(countPanel, label = 'Links')) self.brokenLinks = wx.StaticText(countPanel) countPanelSizer.Add(self.brokenLinks, flag = wx.ALIGN_RIGHT) countPanelSizer.Add(wx.StaticText(countPanel, label = 'Broken Links')) self.variablesCount = wx.StaticText(countPanel) countPanelSizer.Add(self.variablesCount, flag = wx.ALIGN_RIGHT) countPanelSizer.Add(wx.StaticText(countPanel, label = 'Variables Used')) self.panelSizer.Add(countPanel, flag = wx.ALL | wx.ALIGN_CENTER, border = metrics.size('relatedControls')) self.count(panel) okButton = wx.Button(parent = panel, label = 'OK') okButton.Bind(wx.EVT_BUTTON, lambda e: self.Close()) self.panelSizer.Add(okButton, flag = wx.ALL | wx.ALIGN_CENTER, border = metrics.size('relatedControls')) self.panelSizer.Fit(self) size = self.GetSize() if size.width < StatisticsDialog.MIN_WIDTH: size.width = StatisticsDialog.MIN_WIDTH self.SetSize(size) self.panelSizer.Layout() self.SetIcon(app.icon) self.Show() def count(self, panel): """ Sets values for the various counts. """ # have to do some trickery here because Python doesn't do # closures the way JavaScript does counts = { 'words': 0, 'chars': 0, 'passages': 0, 'links': 0, 'brokenLinks': 0 } variables = set() tags = set() def count(widget, counts): if widget.passage.isStoryText(): counts['chars'] += len(widget.passage.text) counts['words'] += len(widget.passage.text.split(None)) counts['passages'] += 1 counts['links'] += len(widget.passage.links) counts['brokenLinks'] += len(widget.getBrokenLinks()) # Find variables iterator = re.finditer(tweeregex.MACRO_REGEX + "|" + tweeregex.LINK_REGEX, widget.passage.text, re.U|re.I) for p in iterator: iterator2 = re.finditer(tweeregex.MACRO_PARAMS_REGEX, p.group(0), re.U|re.I) for p2 in iterator2: if p2.group(4): variables.add(p2.group(4)) # Find tags for a in widget.passage.tags: if a not in TiddlyWiki.INFO_TAGS: tags.add(a) self.storyPanel.eachWidget(lambda w: count(w, counts)) for key in counts: counts[key] = locale.format('%d', counts[key], grouping = True) self.characters.SetLabel(str(counts['chars'])) self.words.SetLabel(str(counts['words'])) self.passages.SetLabel(str(counts['passages'])) self.links.SetLabel(str(counts['links'])) self.brokenLinks.SetLabel(str(counts['brokenLinks'])) self.variablesCount.SetLabel(str(len(variables))) if len(variables): text = ', '.join(sorted(variables)) variablesCtrl = wx.TextCtrl(panel, -1, size=(StatisticsDialog.MIN_WIDTH*.9, 60), style=wx.TE_MULTILINE|wx.TE_READONLY) variablesCtrl.AppendText(text) self.panelSizer.Add(variablesCtrl, flag = wx.ALIGN_CENTER) if len(tags): text = ', '.join(sorted(tags)) tagsCtrl = wx.TextCtrl(panel, -1, size=(StatisticsDialog.MIN_WIDTH*.9, 60), style=wx.TE_MULTILINE|wx.TE_READONLY) tagsCtrl.AppendText(text) self.panelSizer.Add(wx.StaticText(panel, label = str(len(tags)) + " Tags"), flag = wx.ALIGN_CENTER) self.panelSizer.Add(tagsCtrl, flag = wx.ALIGN_CENTER) MIN_WIDTH = 300