#----------------------------------------------------------------------------- # Name: About.py # Purpose: # # Author: Riaan Booysen # # Created: 2000 # RCS-ID: $Id: About.py,v 1.30 2005/05/18 13:19:41 riaan Exp $ # Copyright: (c) 2000 - 2005 # Licence: GPL #----------------------------------------------------------------------------- import sys, time, re, string from thread import start_new_thread import wx import wx.html import wx.lib.wxpTag ##import wxPython ##import wxPython.lib.wxpTag import __version__ import Preferences, Utils # XXX Replace img tags with wxpTags/wxStaticBitmap controls and load from # XXX ImageStore prog_update = re.compile('<<(?P[0-9]+)/(?P[0-9]+)>>') about_html = '''


Constructor
v%s%s
%s ''' # progress_text = '''

''' credits_html = '''

Credits



The Boa Team

Riaan Booysen (riaan@e.co.za)

Shane Hathaway (shane@zope.com)
Kevin Gill (kevin@telcotek.com)
Robert Boulanger (robert@boulanger.de)
Tim Hochberg (tim.hochberg@ieee.org)
Kevin Light (klight@walkertechnical.com)
Marius van Wyk (marius@e.co.za)
Werner F. Bruhin (werner.bruhin@free.fr)

Many thanks to

Guido van Rossum and PythonLabs for Python

wxPython (Robin Dunn) & wxWidgets (Julian Smart, Robert Roebling, Vadim Zeitlin, et al.)
Neil Hodgson for Scintilla

moduleparse.py borrows from pyclbrs.py - standard python library
PythonInterpreter.py by Fredrik Lundh
Mozilla, Delphi, WinCVS for iconic inspirations
Cyclops, ndiff, reindent by Tim Peters
Client.py, WebDAV, DateTime package and the Zope Book from Zope Corporation for Zope integration
PyChecker by Neal Norwitz & Eric C. Newton
py2exe by Thomas Heller
Jeff Sasmor for wxStyledTextCtrl docs
Hernan M. Foffani for ZopeShelf from which the Zope Book was converted
Phil Dawes et al for the Bicycle Repair Man project, a Python refactoring package

Mike Fletcher for reports, ideas and patches (MakePy dialog and much improved UML layout)

Cedric Delfosse for maintaining the Debian package of Boa

Boa interfaces with the following external applications, thanks to their authors
Zope, CVS, SSH, SCP

Last but not least, a very big thank you to Tangible Business Software for partially sponsoring my time on this project.

Boa Constructor is built on:
   

Boa Constructor is packaged for:
     

Back

''' about_text = '''

A Python IDE and wxPython GUI builder

http://boa-constructor.sourceforge.net
©1999-2005 Riaan Booysen. riaan@e.co.za
Credits

Python %s
wx.Platform: %s %s




for Bonnie

''' wx.FileSystem.AddHandler(wx.MemoryFSHandler()) def addImagesToFS(): for name, path, type in [ ('Boa.jpg', 'Images/Shared/Boa.jpg', wx.BITMAP_TYPE_JPEG), ('PythonPowered.png', 'Images/Shared/PythonPowered.png', wx.BITMAP_TYPE_PNG), ('wxPyButton.png', 'Images/Shared/wxPyButton.png', wx.BITMAP_TYPE_PNG), ('wxWidgetsButton.png', 'Images/Shared/wxWidgetsButton.png', wx.BITMAP_TYPE_PNG), ('Debian.png', 'Images/Shared/Debian.png', wx.BITMAP_TYPE_PNG), ('Gentoo.png', 'Images/Shared/Gentoo.png', wx.BITMAP_TYPE_PNG), ('FreeBSD.png', 'Images/Shared/FreeBSD.png', wx.BITMAP_TYPE_PNG), ]: if name not in addImagesToFS.addedImages: wx.MemoryFSHandler.AddFile(name, Preferences.IS.load(path), type) addImagesToFS.addedImages.append(name) addImagesToFS.addedImages = [] def createSplash(parent, modTot, fileTot): return AboutBoxSplash(parent, modTot, fileTot) def createNormal(parent): return AboutBox(parent) wxID_ABOUTBOX = wx.NewId() class AboutBoxMixin: border = 7 def __init__(self, parent, modTot=0, fileTot=0): self._init_ctrls(parent) addImagesToFS() self.moduleTotal = modTot self.fileTotal = fileTot self.blackback = wx.Window(self, -1, pos=(0, 0), size=self.GetClientSize(), style=wx.CLIP_CHILDREN) self.blackback.SetBackgroundColour(wx.BLACK) self.html = Utils.wxUrlClickHtmlWindow(self.blackback, -1, style=wx.CLIP_CHILDREN | wx.html.HW_NO_SELECTION) Utils.EVT_HTML_URL_CLICK(self.html, self.OnLinkClick) self.setPage() self.blackback.SetAutoLayout(True) lc = wx.LayoutConstraints() lc.top.SameAs(self.blackback, wx.Top, self.border) lc.left.SameAs(self.blackback, wx.Left, self.border) lc.bottom.SameAs(self.blackback, wx.Bottom, self.border) lc.right.SameAs(self.blackback, wx.Right, self.border) self.html.SetConstraints(lc) self.blackback.Layout() self.Center(wx.BOTH) self.SetAcceleratorTable(wx.AcceleratorTable([(0, wx.WXK_ESCAPE, wx.ID_OK)])) def gotoInternetUrl(self, url): try: import webbrowser except ImportError: wxMessageBox('Please point your browser at: %s' % url) else: webbrowser.open(url) def OnLinkClick(self, event): clicked = event.linkinfo[0] if clicked == 'Credits': self.html.SetPage(credits_html % ('memory:PythonPowered.png', 'memory:wxPyButton.png', 'memory:wxWidgetsButton.png', 'memory:Debian.png', 'memory:Gentoo.png', 'memory:FreeBSD.png', )) elif clicked == 'Back': self.setPage() #self.html.HistoryBack() elif clicked == 'Python': self.gotoInternetUrl('http://www.python.org') elif clicked == 'wxPython': self.gotoInternetUrl('http://wxpython.org') elif clicked == 'wxWidgets': self.gotoInternetUrl('http://www.wxwidgets.org') elif clicked == 'Debian': self.gotoInternetUrl( 'http://packages.debian.org/unstable/devel/boa-constructor.html') elif clicked == 'Gentoo': self.gotoInternetUrl( 'http://www.gentoo.org/dyn/pkgs/dev-util/boa-constructor.xml') elif clicked == 'FreeBSD': self.gotoInternetUrl( 'http://www.freebsd.org/ports/python.html#boaconstructor-0.2.3') elif clicked == 'Boa': self.gotoInternetUrl('http://boa-constructor.sourceforge.net') elif clicked == 'TBS': self.gotoInternetUrl('http://www.tbs.co.za') elif clicked == 'MailMe': self.gotoInternetUrl('mailto:riaan@e.co.za') class AboutBox(AboutBoxMixin, wx.Dialog): def _init_ctrls(self, prnt): wx.Dialog.__init__(self, size=wx.Size(410, 545), pos=(-1, -1), id=wxID_ABOUTBOX, title='About Boa Constructor', parent=prnt, name='AboutBox', style=wx.DEFAULT_DIALOG_STYLE) def setPage(self): self.html.SetPage((about_html % ( 'memory:Boa.jpg', __version__.version, '', about_text % (sys.version, wx.Platform, wx.__version__)))) DefAboutBox = AboutBox class AboutBoxSplash(AboutBoxMixin, wx.Frame): progressBorder = 1 fileOpeningFactor = 10 def _init_ctrls(self, prnt): wx.Frame.__init__(self, size=wx.Size(418, 320), pos=(-1, -1), id=wxID_ABOUTBOX, title='Boa Constructor', parent=prnt, name='AboutBoxSplash', style=wx.SIMPLE_BORDER) self.progressId = wx.NewId() self.gaugePId = wx.NewId() self.SetBackgroundColour(wx.Colour(0x44, 0x88, 0xFF))#wxColour(0x99, 0xcc, 0xff)) def setPage(self): self.html.SetPage(about_html % ('memory:Boa.jpg', __version__.version, progress_text % (self.progressId, self.gaugePId), '')) wx.CallAfter(self.initCtrlNames) def initCtrlNames(self): self.label = self.FindWindowById(self.progressId) self.label.SetBackgroundColour(wx.WHITE) parentWidth = self.label.GetParent().GetClientSize().x self.label.SetSize((parentWidth - 40, self.label.GetSize().y)) gaugePrnt = self.FindWindowById(self.gaugePId) gaugePrnt.SetBackgroundColour(wx.BLACK)#wx.Colour(0x99, 0xcc, 0xff)) gaugeSze = gaugePrnt.GetClientSize() self.gauge = wx.Gauge(gaugePrnt, -1, range=self.moduleTotal+self.fileTotal*self.fileOpeningFactor, style=wx.GA_HORIZONTAL|wx.GA_SMOOTH, pos=(self.progressBorder, self.progressBorder), size=(gaugeSze.x - 2 * self.progressBorder, gaugeSze.y - 2 * self.progressBorder)) self.gauge.SetBackgroundColour(wx.Colour(0xff, 0x33, 0x00)) # secret early quit option self.gauge.Bind(wx.EVT_LEFT_DOWN, self.OnGaugeDClick) self._gaugeClicks = 0 # route all printing thru the text on the splash screen sys.stdout = StaticTextPF(self.label) start_new_thread(self.monitorModuleCount, ()) EVT_MOD_CNT_UPD(self, self.OnUpdateProgress) def monitorModuleCount(self): self._live = True lastCnt = 0 if self and sys and len(sys.modules) >= self.moduleTotal: wx.PostEvent(self, ModCntUpdateEvent(self.moduleTotal, 'importing')) else: while self and self._live and sys and len(sys.modules) < self.moduleTotal: mc = len(sys.modules) if mc > lastCnt: lastCnt = mc wx.PostEvent(self, ModCntUpdateEvent(mc, 'importing')) time.sleep(0.125) def Destroy(self): self._live = False self.gauge = None if sys: sys.stdout = sys.__stdout__ wx.Frame.Destroy(self) def OnUpdateProgress(self, event): self._live = event.tpe == 'importing' and self._live if self.gauge: cnt = event.cnt if event.tpe == 'opening': cnt = cnt * self.fileOpeningFactor + self.moduleTotal self.gauge.SetValue(min(self.gauge.GetRange(), cnt)) self.Update() def OnGaugeDClick(self, event): if event.GetPosition().x <10: self._gaugeClicks += 1 if self._gaugeClicks >= 5: print print 'Received early abort...' sys.exit() class StaticTextPF(Utils.PseudoFile): def write(self, s): if not wx.Thread_IsMain(): locker = wx.MutexGuiLocker() res = prog_update.search(s) if res: cnt = int(res.group('cnt')) wx.PostEvent(self.output.GetGrandParent().GetParent(), ModCntUpdateEvent(cnt, 'opening')) s = s[:res.start()] ss = string.strip(s) if ss: self.output.SetLabel(ss) if sys: ## frame = sys._getframe() ## try: ## d = 0 ## while frame.f_back: ## frame = frame.f_back ## d += 1 ## except AttributeError: ## pass ## s = ' '*d + s ## sys.__stdout__.write(s)#+':'+sys.path[-1]) wx.Yield() wxEVT_MOD_CNT_UPD = wx.NewId() EVT_MOD_CNT_UPD = wx.PyEventBinder(wxEVT_MOD_CNT_UPD) class ModCntUpdateEvent(wx.PyEvent): def __init__(self, cnt, tpe): wx.PyEvent.__init__(self) self.SetEventType(wxEVT_MOD_CNT_UPD) self.cnt = cnt self.tpe = tpe if __name__ == '__main__': app = wx.PySimpleApp() wx.InitAllImageHandlers() #dialog #frame = createNormal(None) #frame.ShowModal() #frame def updlbl(frame): frame.label.SetLabel('Testing') frame.label.SetLabel('Testing 1') frame.label.SetLabel('Testing 2') frame.label.SetLabel('Testing 3') frame = createSplash(None, 0, 0) frame.Show() wx.CallAfter(updlbl, frame) app.MainLoop()