#!python ############################################################################# ## WinGrabber.py 1.1.0 ### ## GUI and summary generation for Grabber.py ### ## ### ## ### ## Copyright 2005 Leons Petrazickis ### ## Leons.Petrazickis@gmail.com ### ## LPetr.org ### ## ### ## Distributed under the GNU General Public License v2 ### ## http://www.gnu.org/licenses/gpl.txt ### ############################################################################# from Grabber import Grabber, JournalEntry from wxPython.wx import * import wx import os; import sys; import threading; import Queue; # fixes LookupError: unknown encoding: idna import encodings, encodings.idna, encodings.ascii; # embedded images from wx import ImageFromStream, BitmapFromImage import cStringIO, zlib ############################################################################# ## Globals ### ############################################################################# APPLICATION_NAME = "Slashdot Journal Grabber 1.1.0" ID_ABOUT = 101 ID_OPEN = 102 ID_BUTTON_PROCESS = 110 ID_EXIT = 200 ID_BLURBBAR = 400 ID_BB_SAVE_AS = 405 ID_BB_SELECT_ALL = 410 ID_BB_COPY = 420 ID_LABEL_NAME = 900 ID_TEXT_NAME = 910 ############################################################################# ## WinGrabber ### ############################################################################# class WinGrabber(wx.Panel): def __init__(self,parent,id): wx.Panel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL); blurb = wx.TextCtrl(self, 1, style=wx.TE_MULTILINE); blurb.SetMaxLength(4 * 1024 * 512); blurb.SetEditable(false); self.blurb = blurb; blurbBar = wx.ToolBar(self, ID_BLURBBAR); blurbBar.SetToolBitmapSize((24,24)); # sv = getSaveAsBitmap(); #wx.Bitmap('stock_save-as.png', wx.BITMAP_TYPE_PNG); sa = getSelectAllBitmap(); cp = getCopyBitmap(); # blurbBar.AddLabelTool(ID_BB_SAVE_AS, '&Save Summary', sv, wx.NullBitmap, shortHelp='Save Summary'); blurbBar.AddLabelTool(ID_BB_SELECT_ALL, 'Select &All', sa, wx.NullBitmap, shortHelp='Select All'); blurbBar.AddLabelTool(ID_BB_COPY, '&Copy', cp, wx.NullBitmap, shortHelp='Copy Selected'); # blurb.onSaveAs = lambda e: self.onSaveAs(e); blurb.onSelectAll = lambda e: (self.blurb.SelectAll(), self.blurb.SetFocus()); blurb.onCopy = lambda e: self.blurb.Copy(); # EVT_TOOL(self, ID_BB_SAVE_AS, blurb.onSaveAs); EVT_TOOL(self, ID_BB_SELECT_ALL, blurb.onSelectAll); EVT_TOOL(self, ID_BB_COPY, blurb.onCopy); blurbBar.Realize(); self.blurbBar = blurbBar; cmdSizer = wx.BoxSizer(wxHORIZONTAL); self.cmdSizer = cmdSizer; labelName = wx.StaticText(self, ID_LABEL_NAME, '&Username'); cmdSizer.Add(labelName, 0, wx.EXPAND); self.labelName = labelName; grabUser = wx.TextCtrl(self, ID_TEXT_NAME, 'Jorj X. McKie'); cmdSizer.Add(grabUser, 1, wx.EXPAND); self.grabUser = grabUser; grabProcess = wx.Button(self, ID_BUTTON_PROCESS, '&Process'); EVT_BUTTON(grabProcess, ID_BUTTON_PROCESS, self.onProcess); cmdSizer.Add(grabProcess, 0, wx.EXPAND); self.grabProcess = grabProcess; # Use some sizers to see layout options grabSizer = wx.BoxSizer(wx.VERTICAL); grabSizer.Add(cmdSizer, 0, wx.EXPAND); grabSizer.Add(blurbBar, 0, wx.EXPAND); grabSizer.Add(blurb, 1, wx.EXPAND); self.grabSizer = grabSizer; #Layout sizers self.SetSizer(grabSizer); self.SetAutoLayout(1); grabSizer.Fit(self); #Behaviour self.currentDir = '.'; self.currentFile = 'summary.txt'; self.count = 0; self.g = None; EVT_IDLE(self, self.printGrabberQueue); self.Show(1) def onSaveAs(self,e): """save the summary to a file""" dlg = wx.FileDialog(self, 'Save Summary', self.currentDir, self.currentFile, '*.*', wx.SAVE); if dlg.ShowModal() == wx.ID_OK: self.currentFile = dlg.GetFilename(); self.currentDir = dlg.GetDirectory(); f = open(os.path.join(self.currentDir, self.currentFile),'w'); f.write(self.blurb.GetValue()); f.close(); dlg.Destroy(); def onProcess(self, e): """fetch journal entries for a user""" if self.g != None and self.g.done == False: wx.MessageBox("Please wait for this user to finish importing. Exit to cancel.", "Alert"); return; self.blurb.SetValue(''); self.count = 0; self.statusBar.SetStatusText('Saving journals to current directory...'); username = self.grabUser.GetValue(); self.g = Grabber(username); self.g.start(); def printGrabberQueue(self, e): """show summaries of the entries gathered so far""" if self.g != None: if not self.g.queue.empty(): self.blurbBar.EnableTool(ID_BB_SAVE_AS, false); self.blurbBar.EnableTool(ID_BB_SELECT_ALL, false); self.blurbBar.EnableTool(ID_BB_COPY, false); try: je = self.g.queue.get(False); except Queue.Empty: pass; self.count += 1; self.prependStuff(str(je.getID()) + ') ' + je.getIndexItem() + '\n
\n
\n'); else: self.blurbBar.EnableTool(ID_BB_SAVE_AS, true); self.blurbBar.EnableTool(ID_BB_SELECT_ALL, true); self.blurbBar.EnableTool(ID_BB_COPY, true); if self.g.done: sb = self.statusBar; if sb.GetStatusText() != 'Done': sb.SetStatusText('Done'); e.RequestMore(); def writeStuff(self, message): self.blurb.SetValue(message); def appendStuff(self, message): self.blurb.AppendText(message); def prependStuff(self, message): self.blurb.SetInsertionPoint(0); self.blurb.WriteText(message); ############################################################################# ## Embedded Images ### ############################################################################# def getSelectAllData(): return zlib.decompress( 'x\xda\x01\xb2\x02M\xfd\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x18\ \x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0w=\xf8\x00\x00\x00\x04sBIT\x08\x08\ \x08\x08|\x08d\x88\x00\x00\x02iIDATH\x89\xad\x95\xbdO\x14Q\x14\xc5\x7fo]\x85\ U\\\x171F\x13*)H,\xac\xe9dca\xa02\xa1A\x0bK\xe8,,l\x0c\x95\x89\r\x9d\x85\x91\ \xc2\xf8\x1f\xa8\t\t\x89\x15v\x1a\x05-(5\x01d\x94\x10\xf9H\x0clvf\xf7\xbdc1\ \xfb\x96\xd9aga\x8d7y\x99w\xe7\xe6\xdes\xcf\xfd\x98\x81\xff \xc6\x98\\\x96-i\ \xb8\x0b\xa8\x8bS\x01\xfe\x14\x8bE\r\x0f\x0f\xdb\x89\x89\x89o@/`\xb2\xc0\xb4\ \xb2\xb2\xa2J\xa5\xa2\xe3$\x0cC\x85aUaX\xd5\xe6\xe6\xa6\x82 \xd0\xf2\xf2\xb2\ \x06\x07\x07\x03\xe0R*\xf1C\x80\x93\x04?\x04\xa9jooWo\xde\xbc\xd6\xd6\xd6\ \x96$i~~^###\x16(z\x90|\x12\xa1P(\x000^\x9e\xce\xac\xb7\x97\xb7\xef\x9e!\xc1\ \xc1\xc1\x01===\x00\x94\xcbe\xaa\xd5jnrrr\xd6Z\xfb\x10\xa8\xe4\xb3\x02,,\xce\ 5\xc1\xfc\xdd\x8bO \x9f\xcf\x13E5J\xa5R\xda\xfd&P\x02\xa2dC$\xa9+\x06\xb5Z\ \x9d\xb5\xb5U~nl\xf0i\xe93\x06\xf8\x15\xfc\xe0\xf9\xdc\xcb\x00\xb8\x05\xac\ \x1fa\xe0A\xdae\x9dd\x05 g\xe9\xeb\xebch\xe8\x1a\xfd\x03\x17\xd9\xde\xdefw\ \xe77\xc09\xe0\x14`\x8e\x008g3Y$\xdf\xdd\xb9\xfd\xe0\x88\xfd\xf1\x93{\\8\xdf\ \x0b\xd0\xef\x01R\xc9KQ\x14jlt*sz\xd26\xaf\x8f\x8dNi}\xf5\xbbf\x9f\xce\xf8=\ \xb9\x01\x14\xda0p\x99\x0c\xda1I\xebW\xaf\\\xf6W\x03\xa91\x05p6.Q\xba\x07\ \xe9\x80Y\x93\x95\x96\x7fbp\x12{&\x80\x97d\x86\xe9\t:i\xf6m\x01\xea\xb6\xde\ \xd6)\xa9g\x05\x14\xc26\xa60\x13\xc0v\xe8AV\xf6\x0b\x8bs\x8c\x97\xa7c_\x1d\ \xc3\xc079+\xcbN\xfb\xe1\x97\xb4#@\xbd^\xcbd\x90\xc5\xc2\xbf\xb7\xf5zsQ\xdb\ \x02DQ\xd4,Q7{\xe0E\x12i\x12-\x00\xfb\xfb\xfbXky\xf1\xea\x11\x98\xd8!\x97\ \xcb\xe1\x9c\xc3\x18\x83$\x8c1\xb1N\xdc/I\x8d\xa7k\x00\xb8\x16\x80\x96?O\x10\ \x04 \x87\xe4p\xae\xf5(\xf1l\xde\x1b\xe9JB\xc4\xdf1\xe7Z)\xb40\xf8\xf8\xe1=g\ \xcf\x18\x0c\xa6\xe1,\xc0\xe0\x14g\x1ck\xbe\x99\xa6Yo\x1f\xd4\xc9\xb1\xf4\ \xe5k\xb3b\xe9\x12\xde\xa7\xbb\x9f~\xa73\x03\\\x07z\x93\x9f\xd3<0\xd08\xa7\ \xd3\xe8]J\r\xd8\x01v\xfe\x029!\x049\xb3U~(\x00\x00\x00\x00IEND\xaeB`\x82\ \xc0\x083v' ) def getSelectAllBitmap(): return BitmapFromImage(getSelectAllImage()) def getSelectAllImage(): stream = cStringIO.StringIO(getSelectAllData()) return ImageFromStream(stream) def getCopyData(): return zlib.decompress( 'x\xda\x01R\x02\xad\xfd\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x18\ \x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0w=\xf8\x00\x00\x00\x04sBIT\x08\x08\ \x08\x08|\x08d\x88\x00\x00\x02\tIDATH\x89\xbd\x95?\xab\xdaP\x18\x87\x9f\xdc\ \xde\x16\x85RJA\x92t+\x05A\xfag\x08\x8a\xdc\xef\xe0wpLA\x90l.\x05\xadC\xb7\ \xa2[\t\x08uts\xd0\xb9K\x06\x11\xc1Q?AA\xdd\x04M\x82\xb4\x9e\x0e7\xc9\xcd\ \x8dQ\xa3\x85\xbe\xf0BN\xc8y\x9f\xf3;\xbf7\xe7\xc0\x7f\x8a/\x80\xb80?\x03O\ \x01)\t@\x0c\x87C\xe1\xba\xee\xd9\xb4m[X\x96\xe5C^y\x90\xa3\xe1\xd3\x85\xeb\ \xba\xac\xd7\xeb\xc4\x92eY\x06x\x0b\xac\x80\xad\x07<\x88\xdb\xf0\xa0\xdf\xef\ \xb3Z\xad\x00H\xa5R\x94\xcbe&\x93\t\xd3\xe9\x14]\xd71M\x13M\xd3(\x14\n\xfe\ \x94\x94WC:\x06\xb8H\x81\x10\x0f5\x14E\x01\xf8\x08\xfc\x02\xd6\xc0>n\xca#@\ \xa5R\xc1q\x1cZ\xad\x16\xcdf\x13Y\x96\xd14\x8d|>\xef\x17\xbc$t\xe0G@r]W,\x97\ \xcb\xd8\x04\xc4`0\x10Ic6\x9b\x05Mp\xd4\x03\x7f\xcf\xfdm)\x95J\x89\x97\x9e\ \xcb\xe5\xfc\xc7\x97g=\x10B\xa0(\nB\x08z\xbd\x1e\x8b\xc5\x02\x80t:\x8d\xae\ \xeb\x8cF#\xc6\xe31\x86a\xd0n\xb7)\x16\x8b\xdc\xdd\xdd!I\x12\xc0\xbbX\x0f\ \x80\xc0\x87L&C\xa3\xd1xdp\x92\xf0\x00\x1f\xce*\xd8\xef\xf7\xa8\xaa\x8a\x10\ \x82j\xb5\x8am\xdbt:\x1dj\xb5\x1a\xaa\xaa\x06+\x0e+9\n\xe8v\xbb\xb1\x1e\xd4\ \xeb\xf5k\x15\xbc\x0f\x00\xdb\xed\x96\xcdfs\xf0\xe11\x0f\xfc=\x07\x02\x15\ \xa6i\xe28\x0e\x86a\x1c\x02,\xcb"\x9b\xcd\x9e\x04\xfc\x8b\x82O\xc0\xf7S\x13\ \xc2\x1e\x00g}\x88\x02n\x81\xe7\xc0\x0b\xe0\x19\xf7G\x88\x9f\xaf\x81\x9f\xd7\ v\x91\xff\xa3\xfd\x016\xc0\x0e\xb8\xe1\xe1\x8c\x92\x80\xa5?\xe9\x12\x0f|\xe1\ \xd1\xcb"n,\x01\xbf\xaf\xf5\xe0&\xf2>zk\xed\xbdd>\x9f\'.\x1e\xfa6\xee\x84=\\\ \x0c\xf05\x06~.\xbf\x01o\x12\xdd\xa7\x9cn\x82\xb0_\x84\x00;`\x9d\x14 \x01O\ \xbc\xe2\xd1&\x88\xab!\xb8o\x9c]R@\x18tj\x1c\x85\x88\xbf\xb7\xae\x9eC\x12"T\ \x83\x00\x00\x00\x00IEND\xaeB`\x82\xbe\xf3\x00\x92' ) def getCopyBitmap(): return BitmapFromImage(getCopyImage()) def getCopyImage(): stream = cStringIO.StringIO(getCopyData()) return ImageFromStream(stream) def getSaveAsData(): return zlib.decompress( 'x\xda\x01\xcf\x040\xfb\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x18\ \x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0w=\xf8\x00\x00\x00\x04sBIT\x08\x08\ \x08\x08|\x08d\x88\x00\x00\x04\x86IDATH\x89\xa5\x95mh\x95e\x18\xc7\x7f\xcf\ \xdby\xdb9\xc7\xedls\xc7XB\x04QA\xc8l\xf9\x9241\x91R(+2\xa8\xe8[\x1f\xcc\xa8\ \xbe\x94EF\xf9A(\xa4\xec\xcb\xfc\xd2 \r\x84\xa4\xc8\xb7\x0f#\xb6\x0f\x11RdN7\ \ri\xea\xc4\xc4l;\x1e\xb6\x9d\xe9\xf6\x9c\xe7\xed\xbe\xee>\x9c\x17\xb7\xdc \ \xf1\x82\x8b\xe7~\xee\xe7~\xfe\xbf\xfb\xb9\xae\xeb~.\xb8;3\x00]\xf5W\x80\x14\ `\xdd\xa5\xe6\\\xf1pt\x8d\xbe\xd1\xfbL\r\xb2\xb4\n1j\x8b\xcc\xeau\xcb\xac\ \x9d\xfc_\x97\xa8\xf8\x04\xd1\xe9$o~u\xb9\xa6w\x05\x98\x01^\x06l\xc0\xa8\x91\ \xf4\xf1?\xa7\xf9\xc7\x9db\xe0\xe0^>|n\x1d\xa6e\xa1E\x10\xd7\x05\xd3\x82\xea\ }Xv\xc9oz\x91\xa8\xb0\x86p \xc5{\xdfM\xd2\xfd\xcd\x00\xeb\xd7o`\xf3\xeb\xefb\ \xa7\xb2l\xdb\xbc\x1a \x0b\x94\xed\x1a\xda\xd3\xd3\\\xb9\xf4\x17\xc5\xeb\x13\ L\xfdv\x1cfJ \x10\x05\x01\xc4\x93H\xb9\x8c\x9fH\xf1\xc8\xce=\x04\x7f?\x8ew"\ \xc9[_\x17\xd9wd\x88\x0f\xba\x1e\xe3\\2\xc3\xb5B\x81\x8b\x97N\xd4$\x1b\x80\ \xa8\x0e\xd0\xda@\x94\x90\x88\'\x18\x9bVXa\x0cD\x83\xe1`\x84\x1a\xb1S\xac\ \xd8\xb9\x07\xff\xf2j\xfc\x93\t\xde\xde_d\xdf\xd13|\xb9q\x1dN\xba\x99\xabN\ \x16;\x9e\xc60kQ\xc7\x01\xcc: \x12A\xdbBC\xc6b\xe5\xc7\xbb\xe6dSk\x8di\x9a\ \xf8#\xabp\xcf\xb5\xf0\xfe\xf7\xd7\xd8w\xf4\x0c\xfd\xfd\xfd\xe4r9\xda\xda\ \xda\xb8\xb0{7\xb1x\x02\xad\xa2\xd9E@\x1d`\x01\xe2\xcbm\xa5R\x13\xf7\x86WR>\ \x15g\xfb\x91\xab\xf4|;D__\x1fMMM\xe4\xf3yr\xb9\x1c\xb6mc\x9a&\xea\x16\x809\ \x00\xd0h]\x19\r\x0e\x0e\xa2\xb5FkMgg\'\xee\xd9\x15\xcc\x0c\xc4y\xe7\x87)\ \x0e\x1c\x1e\xa2\xbb\xbb\x9bB\xa1\x80R\x8a \x08\x18\x1e\x1e\xc60\x0c\x1c\xdb\ \xc2\xf7\x83\xf9\x01\xa2\rDE\x94J%:::*sR\xf9\xa2+#]\xec>\xd6\xcf\x81\xc3g\ \xe8\xeb\xeb#\x97\xcb\x91\xcf\xe7inn&\x16\x8ba\x9a&\xbd\xbd\xbd\x95w\xa2\x85\ \x00\x9e\xa0L\xa1\xb1\xb1\xb1\x1e\x1a\xcb\xb2\xd8\xbc\xae\x95\x87^\xf8\x1c`A\ \xf1\xd9\xe1\xd4\xa2\xe6\x07\xf8&H\xf5\xe1\xe0\xe0 JU\xc6G\x7f*\xd2\xd3\xd3\ \x83a\x18\x8c\x8f\x8f#"\x04A\xc0\xe8\xe8h]\xdc\xf3\xbc\xba\xe0"{\x81\x1c\x98\ \x8e&f\x80;6FGG\x07"B\xa9T\xa2P(\x10\x04\x01\xd9l\x96t:MCC\x03\xb1X\x0c\xa3~\ F+v\xe8\xd0!"%\xa8(\x9c\x1f\x10(\x8d\x17D\xc4\x1f]\xcb\x8e\x1d;\xf0<\x0f\x11\ !\x8a*;\xb2,\x8bP\x9b\xd8(\x1c\xc7\x99#\xe2\xba.\xb1l+\x96iP\x98\xf1\xe7\x07\ \xe8P\xe3\xfb\x8aLc;fn)i\xd3 \x8c\x14J\tZkl\xdb\xc2\x0b"2\xa98\xbaZn\xa6i\ \x12F\x8a%\x89\x18e?\xc4\xb6L"\x7f\xa1\x10\x85 \x08\x137\\L\xd3d\xe8\xc7\xfd\ \x18X46\xe5hlY\x8cR\n\xa5BD\t\xa2"4\x9a\xd0\xf3)x\n\x99,\xb2v\xcbV\xee[\xd2\ \x0c\xb2@\x15i\x07D)\xd0\x8a\xf3?\x1f\xe3\xa5\x8d]<\xbd\xe9Yl\xdb&\x91LU\xd6\ h\xcd\xcc\xf4MJS\x93\x04^\x99\xb3C\xa7\xe9?y\x81\x99\xdc2FF\xce\xb3|\xd9\xc3\ \x88,\x90\x03\xd0D*\x02\x11\xdc\xe9i\xd6ox\x8aD2\xc1\xceO>\xa2x\xbd\x00\xc0\ \xa7\x9f}\xc1\xc4D\x11\xbf\xec\xe2\x95]:W\xad\xe1`\xef\xaf\xa4\xeem#\x8c<\ \x92\xb6Fys\x01\xf5"\x16\rZC\xac\xda\x8f\x12\xc9\x14\xc9\xea\xcek6}\xf3\x06a\ P\tA\xae\xb9\x95L:K"\x99\xacw\x97\xb8\xc9mv\xebg\x17)D\x14\xa2\x04\xaf\xec"J\ \x11\x86\x11\xd7\x0bc\xf5\x13\x1d\x04\x1e\xa2"\x1a\xd2\x19\x16\xe7\xef!\x91H\ \x11E!\x96\x0e\x10eP(k\xe2\xc6\x029\xf8\xe3\x97~\x1c\x1cf"!\x0c|\xca\xae\x8b\ \xeb\xba\xa8H\xd5\xab\xc6\xf7\xca4\xe5Zhm[B<\x9e\xc0\xf7=D\x14\x81\x1f\xe0\ \x88FD\xa3\xd5\xfc\'y\xc5\xde]\xdb\x7f\x7f\xf2\xf9W\xc94\xe6h\xbf\xff\x01N\r\ \x9c\xa0\xbd\xbd\x9dmol\xa5eq\x1e\x80\x86t\x96Lf\x11\xb6\xedP\x9a\x1c\xe7\ \xe2\x85\xf3\xf8\x9eG\x1a\x0b\x15x\x04\xa6\xa0o\xb5c\xfd_\xd0j\xee\xbc/\xcf\ \xf1\x07\x97w\xd5\xc6\xaf\x01y Y\xc3\x19TZB\xaa\xea\xce\xac\xf9;5\r\x84T\x9a\ \x7f\xf9_:\xdf\\\x8a:\xe0D\n\x00\x00\x00\x00IEND\xaeB`\x82\x03OA\x9a' ) def getSaveAsBitmap(): return BitmapFromImage(getSaveAsImage()) def getSaveAsImage(): stream = cStringIO.StringIO(getSaveAsData()) return ImageFromStream(stream) ############################################################################# ## Main ### ############################################################################# if __name__ == "__main__": app = wx.PySimpleApp() frame = wxFrame(None, -1, APPLICATION_NAME) nb = wxNotebook(frame, -1) panel = WinGrabber(nb, -1); nb.AddPage(panel, "Grab-O-Rama") panel.statusBar = frame.CreateStatusBar(); frame.Show(1) app.MainLoop() """ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """