drpython-3.11.1/0000755000175000017500000000000011246265352014260 5ustar dktrkranzdktrkranzdrpython-3.11.1/drSTC.py0000644000175000017500000002411611150445514015607 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #The StyledTextControl Base Class import re, string import wx import wx.stc import drPopUp import drShortcuts, drShortcutsFile from drDragAndDrop import drDropTarget from drFindReplaceDialog import drFinder #******************************************************************************************************* class DrStyledTextControl(wx.stc.StyledTextCtrl): def __init__(self, parent, id, grandparent): wx.stc.StyledTextCtrl.__init__(self, parent, id) #Constants: self.PYTHON_FILE = 0 self.CPP_FILE = 1 self.HTML_FILE = 2 self.TEXT_FILE = 3 self.IsAPrompt = False self.IndicatorSetStyle(0, wx.stc.STC_INDIC_HIDDEN) self.grandparent = grandparent self.Finder = drFinder(grandparent, self) #Python!!!! self.filetype = 0 self.stclabelarray = drShortcutsFile.GetSTCShortcutList() self.stcactionarray = drShortcuts.GetSTCCommandList() self.ID_POPUP_BASE = 33000 #Speed Optimization Submitted by Franz self.SetModEventMask(wx.stc.STC_PERFORMED_UNDO | wx.stc.STC_PERFORMED_REDO |\ wx.stc.STC_MOD_DELETETEXT | wx.stc.STC_MOD_INSERTTEXT) self.droptarget = drDropTarget(self) self.SetDropTarget(self.droptarget) #WIERD! self.SetProperty("tab.timmy.whinge.level", "1") #Right Click Menu self.UsePopUp(0) self.SetMarginType(0, wx.stc.STC_MARGIN_SYMBOL) self.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER) self.SetMarginWidth(0, 0) self.SetMarginWidth(1, 0) self.SetMarginWidth(2, 0) self.SetMarginType(2, wx.stc.STC_MARGIN_SYMBOL) self.SetMarginMask(2, wx.stc.STC_MASK_FOLDERS) self.SetScrollWidth(1) self.retab = re.compile('^\t+', re.MULTILINE) self.respaces = re.compile('^ +', re.MULTILINE) self.remixedoutright = re.compile('(^\t+ )|(^ +\t)', re.MULTILINE) self.indentationtype = 2 self.renonwhitespace = re.compile('\S') if self.grandparent.prefs.doceolmode[self.filetype] == 1: self.SetEOLMode(wx.stc.STC_EOL_CRLF) elif self.grandparent.prefs.doceolmode[self.filetype] == 2: self.SetEOLMode(wx.stc.STC_EOL_CR) else: self.SetEOLMode(wx.stc.STC_EOL_LF) self.Bind(wx.EVT_RIGHT_DOWN, self.OnPopUp) self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) def CheckIndentation(self, text=None): if text is None: text = self.GetText() if not text: return 2 tabs = (self.retab.search(text) is not None) spaces = (self.respaces.search(text) is not None) mixed = (self.remixedoutright.search(text) is not None) if mixed or (tabs and spaces): return 0 elif tabs: return 1 elif spaces: return -1 return 2 def EnsurePositionIsVisible(self, position): self.GotoPos(self.PositionFromLine(self.LineFromPosition(position))) self.EnsureCaretVisible() self.GotoPos(position) self.EnsureCaretVisible() def GetEndOfLineCharacter(self): emode = self.GetEOLMode() if emode == wx.stc.STC_EOL_CR: return '\r' elif emode == wx.stc.STC_EOL_CRLF: return '\r\n' return '\n' def GetIndentationCharacter(self): #What is this document using? result = self.CheckIndentation() if result == 0: if self.grandparent.prefs.docusetabs[self.filetype]: result = 1 else: result = -1 if result == 1: compchar = '\t' else: compchar = ' ' return compchar def OnLeftDown(self, event): self.droptarget.SetModifierDown(event.ControlDown()) if self.grandparent.prefs.draganddropmode != 1: pos = self.PositionFromPoint(wx.Point(event.GetX(), event.GetY())) s, e = self.GetSelection() if (pos > s) and (pos < e): self.SetSelection(pos, pos) return event.Skip() def OnPopUp(self, event): #fast context #ugly hack franz if event.ControlDown(): import drAboutDialog dlg = drAboutDialog.drAboutDialog(self.grandparent) dlg.notebook.SetSelection(2) dlg.ShowModal() else: #end ugly hack franz drPopUp.OnPopUp(self, event) def OnPopUpMenu(self, event): drPopUp.OnPopUpMenu(self, event) def Paste(self): if wx.TheClipboard.IsOpened(): wx.TheClipboard.Close() wx.TheClipboard.Open() tdo = wx.TextDataObject() data = wx.TheClipboard.GetData(tdo) if data: text = tdo.GetText() #Clean Up the Text: #Line Endings First: emode = self.GetEOLMode() if emode == wx.stc.STC_EOL_CR: text = self.grandparent.FormatMacReTarget.sub('\r', text) elif emode == wx.stc.STC_EOL_CRLF: text = self.grandparent.FormatWinReTarget.sub('\r\n', text) else: text = self.grandparent.FormatUnixReTarget.sub('\n', text) line, pos = self.GetCurLine() skipfirstline = self.renonwhitespace.search(line[:pos]) is not None #Now Indentation: if self.indentationtype == -1: text = self.SetToSpaces(-1, text) elif self.indentationtype == 1: text = self.SetToTabs(-1, text, skipfirstline) else: if self.grandparent.prefs.docusetabs[self.filetype]: text = self.SetToTabs(-1, text, skipfirstline) else: text = self.SetToSpaces(-1, text) if self.grandparent.prefs.docusetabs[self.filetype]: self.indentationtype = 1 else: self.indentationtype = -1 s, e = self.GetSelection() if (e - s) > 0: self.SetTargetStart(s) self.SetTargetEnd(e) self.ReplaceTarget(text) pos = self.GetCurrentPos() else: pos = self.GetCurrentPos() self.InsertText(pos, text) self.GotoPos(pos + len(text)) self.OnModified(None) wx.TheClipboard.Close() def SetSelectedText(self, text): self.SetTargetStart(self.GetSelectionStart()) self.SetTargetEnd(self.GetSelectionEnd()) self.ReplaceTarget(text) def SetToSpaces(self, tabwidth=-1, text=''): if tabwidth < 0: tabwidth = self.grandparent.prefs.doctabwidth[self.filetype] eol = self.GetEndOfLineCharacter() regex = re.compile('(\S)|' + eol) if not text: text = self.GetText() SetTheText = True else: SetTheText = False lines = text.split(eol) new_lines = [] for line in lines: result = regex.search(line + eol) if result is not None: end = result.start() new_lines.append(line[0:end].expandtabs(tabwidth) + line[end:]) else: new_lines.append(line) newtext = string.join(new_lines, eol) self.indentationtype = -1 self.SetupTabs(False) if SetTheText: self.SetText(newtext) else: return newtext def SetToTabs(self, tabwidth=-1, text='', skipfirstline=False): if tabwidth < 0: tabwidth = self.grandparent.prefs.doctabwidth[self.filetype] - 1 else: tabwidth -= 1 eol = self.GetEndOfLineCharacter() regex = re.compile('(\S)|' + eol) #Create Target String y = 0 oof = " " while y < tabwidth: oof = oof + " " y = y + 1 #Continue if not text: text = self.GetText() SetTheText = True else: SetTheText = False lines = text.split(eol) new_lines = [] x = 0 for line in lines: result = regex.search(line + eol) if result is not None: end = result.start() newline = line[0:end].replace(oof, "\t") if x == 0 and skipfirstline: newline = newline + line[end:] else: newline = newline.replace(' ', '') + line[end:] new_lines.append(newline) else: new_lines.append(line) x += 1 newtext = string.join(new_lines, eol) self.indentationtype = 1 self.SetupTabs(True) if SetTheText: self.SetText(newtext) else: return newtext def SetupTabs(self, UseTabs=-1): if UseTabs == -1: UseTabs = self.grandparent.prefs.docusetabs[self.filetype] self.SetUseTabs(UseTabs) self.tabwidth = self.grandparent.prefs.doctabwidth[self.filetype] self.addchar = '\t' if not UseTabs: #franz: x not referenced self.addchar = "\t".expandtabs(self.tabwidth) drpython-3.11.1/drFindReplaceDialog.py0000644000175000017500000013020211232254421020440 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #FindReplace Dialog import wx import wx.stc import drScrolledMessageDialog import re class drFinder: #copy old finder limodou 2004/04/19 def __init__(self, parent, stc, oldfinder=None): #end limodou self.parent = parent self.stc = stc self.reset() #copy old finder limodou 2004/04/19 self.Copy(oldfinder) #end limodou #copy old finder limodou 2004/04/19 def Copy(self, finder): if finder: self.findtext = finder.findtext self.findflags = finder.findflags self.backwards = finder.backwards #Franz: Bug Report with Fix self.RE = finder.RE #Moved here by Dan. #Edited by Dan #(Bug Report, Franz.) #copy old finder limodou 2004/04/19 self.docEnd = self.stc.GetTextLength() self.SetTargetRange(0, self.docEnd) #end limodou #end limodou def DoFind(self, findtext, findflags, backwards=False): self.parent.SetStatusText(findtext, 2) self.RE = 0 self.rectanglefind = 0 doclength = self.stc.GetLength() self.findtext = findtext self.findflags = findflags prev = self.findpos if self.backwards != backwards: self.backwards = backwards if backwards: endpos = self.targetStart else: endpos = self.targetEnd self.findpos = self.stc.FindText(self.findpos, endpos, findtext, findflags) if self.findpos == -1: if self.stc.FindText(self.targetStart, self.targetEnd, findtext, findflags) == -1: if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self.parent, ('Search string "' + findtext + '" not found.'), "DrPython Find") else: #wx.MessageBox ('Search string "' + findtext + '" not found.', "DrPython Find", wx.ICON_INFORMATION) self.parent.SetStatusText('NOT FOUND: ' + findtext, 2) return if ((self.findpos >= doclength) or (self.findpos < 0)) and (doclength > 0): self.lastposition = -1 if self.backwards: msg = 'Start of document reached: "' + findtext + '".\nStart again from the end?' fpos = self.targetEnd else: msg = 'End of document reached: "' + findtext + '".\nStart again from the beginning?' fpos = self.targetStart #ugly hack: on windows you can escape with ESC, on gtk it is the other side if self.parent.PLATFORM_IS_WIN: ok = wx.OK stylemsgbox = wx.OK | wx.CANCEL else: ok = wx.YES stylemsgbox = wx.YES_NO if self.parent.prefs.findreplaceautowrap: answer = ok else: answer = wx.MessageBox(msg, "DrPython Find", stylemsgbox | wx.ICON_QUESTION) if answer == ok: self.findpos = fpos self.stc.GotoPos(self.findpos) if self.backwards: self.DoFindPrevious() else: self.DoFindNext() else: self.stc.GotoPos(prev) return if self.parent.prefs.docfolding: self.stc.EnsureVisible(self.stc.LineFromPosition(self.findpos)) endpos = self.findpos + len(findtext) self.stc.EnsurePositionIsVisible(endpos) self.stc.GotoPos(self.findpos) self.stc.SetSelectionStart(self.findpos) self.stc.SetSelectionEnd(endpos) self.lastposition = self.findpos + len(findtext) if backwards: self.findpos = self.findpos - 1 else: self.findpos = self.findpos + 1 def DoREFind(self, findtext, matchcase): self.RE = 1 self.rectanglefind = 0 self.findtext = findtext self.findflags = matchcase prev = self.findpos case = 0 if not matchcase: case = re.IGNORECASE try: regularexpression = re.compile(findtext, case | re.MULTILINE) except: drScrolledMessageDialog.ShowMessage(self.parent, 'Regular Expression Error', "DrPython Find") return endpos = self.targetEnd matchedtext = regularexpression.search(self.stc.GetText()[self.findpos:endpos]) if matchedtext is None: testforexist = regularexpression.search(self.stc.GetText()) if testforexist is None: drScrolledMessageDialog.ShowMessage(self.parent, ('Regular expression "' + findtext + '" not found.'), "DrPython Find") return self.lastposition = -1 if prev > self.targetStart: self.findpos = self.targetStart if self.parent.PLATFORM_IS_WIN: ok = wx.OK stylemsgbox = wx.OK | wx.CANCEL else: ok = wx.YES stylemsgbox = wx.YES_NO if self.parent.prefs.findreplaceautowrap: answer = ok else: answer = wx.MessageBox('End of document reached: "' + findtext + '".\nStart again from the beginning?', "DrPython Find", stylemsgbox | wx.ICON_QUESTION) if answer == ok: self.stc.GotoPos(self.findpos) self.DoFindNext() else: self.stc.GotoPos(prev) return oldpos = self.findpos self.findpos = oldpos + matchedtext.start() endpos = oldpos + matchedtext.end() if self.parent.prefs.docfolding: self.stc.EnsureVisible(self.stc.LineFromPosition(self.findpos)) self.stc.EnsurePositionIsVisible(endpos) self.stc.GotoPos(self.findpos) self.stc.SetSelectionStart(self.findpos) self.stc.SetSelectionEnd(endpos) self.lastposition = endpos self.findpos = endpos def DoFindNext(self): if not self.findtext: return if not self.inselection: textlength = self.stc.GetTextLength() if textlength != self.docEnd: self.docEnd = textlength self.SetTargetRange(0, self.docEnd) self.findpos = self.stc.GetCurrentPos() if not self.RE: if self.rectanglefind: self.DoRectangleFind(self.findtext, self.findflags) else: self.DoFind(self.findtext, self.findflags) else: if self.rectanglefind: self.DoRERectangleFind(self.findtext, self.findflags) else: self.DoREFind(self.findtext, self.findflags) self.ScrollFewLinesAbove() def ScrollFewLinesAbove(self): top = self.parent.txtDocument.GetCurrentLine() - (self.parent.txtDocument.LinesOnScreen() - 5) lastline = self.parent.txtDocument.GetFirstVisibleLine() + self.parent.txtDocument.LinesOnScreen() if self.parent.txtDocument.GetCurrentLine() > (lastline - 5): self.parent.txtDocument.ScrollToLine(top) def ScrollFewLinesBelow(self): top = self.parent.txtDocument.GetCurrentLine() - 5 firstline = self.parent.txtDocument.GetFirstVisibleLine() if self.parent.txtDocument.GetCurrentLine() < (firstline + 5): self.parent.txtDocument.ScrollToLine(top) def DoFindPrevious(self): if not self.findtext: return if not self.inselection: textlength = self.stc.GetTextLength() if textlength != self.docEnd: self.docEnd = textlength self.SetTargetRange(0, self.docEnd) self.findpos = self.stc.GetCurrentPos() if not self.RE: if (self.findpos == self.lastposition) and not self.rectanglefind: self.findpos = self.findpos - len(self.findtext) - 1 self.stc.GotoPos(self.findpos) elif self.rectanglefind and (self.lastposition == -1) and (not self.backwards): self.stc.GotoPos(self.findpos) if self.rectanglefind: self.DoRectangleFind(self.findtext, self.findflags, True) else: self.DoFind(self.findtext, self.findflags, True) self.ScrollFewLinesBelow() else: drScrolledMessageDialog.ShowMessage(self.parent, 'Find Previous Not Possible:\nRegular Expressions Are On.', 'DrPython Find') def DoRectangleFind(self, findtext, matchcase, backwards=False): self.RE = 0 self.rectanglefind = 1 doclength = self.stc.GetLength() lenlines = len(self.Lines) if matchcase: self.findtext = findtext else: self.findtext = findtext.lower() prev = self.findpos if self.backwards != backwards: self.backwards = backwards self.findpos = self.stc.GetCurrentPos() endpos = self.targetEnd lineArrayPosition = self.getArrayPosition(self.findpos) if lineArrayPosition == -1: self.findpos = self.findpos - 1 lineArrayPosition = self.getArrayPosition(self.findpos - 1) if lineArrayPosition == -1: self.findpos = -1 else: relative_findpos = self.positions[lineArrayPosition].index(self.findpos) + 1 else: relative_findpos = self.positions[lineArrayPosition].index(self.findpos) if self.findpos > -1: self.findpos = self.findInArray(lineArrayPosition, relative_findpos) if self.findpos == -1: if self.backwards: notFound = self.findInArray(0, self.positions[lenlines-1][len(self.positions[lenlines-1])-1]) == -1 else: notFound = self.findInArray(0, 0) == -1 if notFound: drScrolledMessageDialog.ShowMessage(self.parent, ('Search string "' + findtext + '" not found.'), "DrPython Find") return if ((self.findpos >= doclength) or (self.findpos < 0)) and (doclength > 0): self.lastposition = -1 if self.backwards: msg = 'Start of document reached: "' + findtext + '".\nStart again from the end?' self.findpos = self.targetEnd else: msg = 'End of document reached: "' + findtext + '".\nStart again from the beginning?' self.findpos = self.targetStart if self.parent.prefs.findreplaceautowrap: answer = wx.OK else: answer = wx.MessageBox(msg, "DrPython Find", wx.OK | wx.CANCEL | wx.ICON_QUESTION) if answer == wx.OK: self.stc.GotoPos(self.findpos) if self.backwards: self.DoFindPrevious() else: self.DoFindNext() else: self.stc.GotoPos(prev) return if self.parent.prefs.docfolding: self.stc.EnsureVisible(self.stc.LineFromPosition(self.findpos)) endpos = self.findpos + len(findtext) self.stc.EnsurePositionIsVisible(endpos) self.stc.GotoPos(self.findpos) self.stc.SetSelectionStart(self.findpos) self.stc.SetSelectionEnd(endpos) self.lastposition = self.findpos + len(findtext) def DoRERectangleFind(self, findtext, matchcase): self.RE = 1 self.rectanglefind = 1 doclength = self.stc.GetLength() self.findtext = findtext self.findflags = matchcase prev = self.findpos case = 0 if not matchcase: case = re.IGNORECASE try: regularexpression = re.compile(findtext, case | re.MULTILINE) except: drScrolledMessageDialog.ShowMessage(self.parent, 'Regular Expression Error', "DrPython Find") return endpos = self.targetEnd if (self.findpos >= doclength) or (self.findpos < 0): self.findpos = 0 lineArrayPosition = self.getArrayPosition(self.findpos) if lineArrayPosition == -1: self.findpos = self.findpos - 1 lineArrayPosition = self.getArrayPosition(self.findpos - 1) if lineArrayPosition == -1: self.findpos = -1 else: relative_findpos = self.positions[lineArrayPosition].index(self.findpos) + 1 else: relative_findpos = self.positions[lineArrayPosition].index(self.findpos) if self.findpos > -1: matchedtext, newArrayPosition = self.searchInArray(regularexpression, lineArrayPosition, relative_findpos) else: matchedtext = None if matchedtext is None: testforexist, nap = self.searchInArray(regularexpression, 0, 0) if testforexist is None: drScrolledMessageDialog.ShowMessage(self.parent, ('Regular expression "' + findtext + '" not found.'), "DrPython Find") return self.lastposition = -1 if prev > self.targetStart: self.findpos = self.targetStart if self.parent.prefs.findreplaceautowrap: answer = wx.OK else: answer = wx.MessageBox('End of document reached: "' + findtext + '".\nStart again from the beginning?', "DrPython Find", wx.OK | wx.CANCEL | wx.ICON_QUESTION) if answer == wx.OK: self.stc.GotoPos(self.findpos) self.DoFindNext() else: self.stc.GotoPos(prev) return relative_findpos = matchedtext.start() self.findpos = self.positions[newArrayPosition][relative_findpos] endpos = self.findpos + (matchedtext.end() - matchedtext.start()) if self.parent.prefs.docfolding: self.stc.EnsureVisible(self.stc.LineFromPosition(self.findpos)) self.stc.EnsurePositionIsVisible(endpos) self.stc.GotoPos(self.findpos) self.stc.SetSelectionStart(self.findpos) self.stc.SetSelectionEnd(endpos) self.lastposition = endpos self.findpos = endpos def findInArray(self, arrayposition, position): if self.backwards: r = self.Lines[arrayposition][:position].rfind(self.findtext) if r == -1: arrayposition -= 1 while arrayposition > -1: r = self.Lines[arrayposition].rfind(self.findtext) if r == -1: arrayposition -= 1 else: return self.positions[arrayposition][r] else: return self.positions[arrayposition][r] else: l = len(self.Lines) r = self.Lines[arrayposition][position:].find(self.findtext) if r == -1: arrayposition += 1 while arrayposition < l: r = self.Lines[arrayposition].find(self.findtext) if r == -1: arrayposition += 1 else: return self.positions[arrayposition][r] else: return self.positions[arrayposition][r] return -1 def getArrayPosition(self, position): x = 0 for posArray in self.positions: if position in posArray: return x x += 1 return -1 def GetFindPos(self): return self.findpos def GetFindText(self): return self.findtext def RectangleReplaceAll(self, findtext, replacetext, matchcase): targetText = self.stc.GetSelectedText() if not matchcase: targetText = targetText.lower() eolchar = self.stc.GetEndOfLineCharacter() lines = targetText.strip().split(eolchar) c = self.stc.GetColumn(self.targetStart) linenumber = self.stc.LineFromPosition(self.targetStart) lenline = len(lines[0]) x = 0 for line in lines: position_of_first_character = c + self.stc.PositionFromLine(linenumber) p = line.find(findtext) if p > -1: line = line.replace(findtext, replacetext) self.stc.SetTargetStart(position_of_first_character) self.stc.SetTargetEnd(position_of_first_character+lenline) self.stc.ReplaceTarget(line) x = x + 1 linenumber = linenumber + 1 return x def RectangleREReplaceAll(self, findtext, replacetext, matchcase): case = 0 if not matchcase: case = re.IGNORECASE try: regularexpression = re.compile(findtext, case | re.MULTILINE) except: drScrolledMessageDialog.ShowMessage(self.parent, 'Regular Expression Error', "DrPython Replace") return targetText = self.stc.GetSelectedText() if not matchcase: targetText = targetText.lower() eolchar = self.stc.GetEndOfLineCharacter() lines = targetText.strip().split(eolchar) c = self.stc.GetColumn(self.targetStart) linenumber = self.stc.LineFromPosition(self.targetStart) lenline = len(lines[0]) y = 0 for line in lines: #You need to update the position(do the replace) during the loop. position_of_first_character = c + self.stc.PositionFromLine(linenumber) line, x = regularexpression.subn(replacetext, line) y = y + x self.stc.SetTargetStart(position_of_first_character) self.stc.SetTargetEnd(position_of_first_character+lenline) self.stc.ReplaceTarget(line) linenumber = linenumber + 1 return y def ReplaceAll(self, findtext, replacetext, flags, prompt = 0): p = self.stc.FindText(self.findpos, self.targetEnd, findtext, flags) diff = len(replacetext) - len(findtext) x = 0 notfirst = 0 favpos = wx.Point(5, 5) while p != -1: if self.parent.prefs.docfolding: self.stc.EnsureVisible(self.stc.LineFromPosition(p)) self.stc.GotoPos(p) self.stc.EnsureCaretVisible() self.stc.SetTargetStart(p) self.stc.SetTargetEnd(p + len(findtext)) if prompt: self.stc.SetSelection(p, (p + len(findtext))) d = wx.SingleChoiceDialog(self.parent, ("Found \"" + findtext + "\" at Line: " \ + str(self.stc.LineFromPosition(p)+1) + \ " Col: " + str(self.stc.GetColumn(p)) + "\n(Hit Cancel to Stop)"), "Replace", ["Replace", "Skip"], wx.CHOICEDLG_STYLE) if notfirst: d.Move(favpos) else: notfirst = 1 answer = d.ShowModal() favpos = d.GetPosition() d.Destroy() if answer == wx.ID_OK: if d.GetStringSelection() == "Replace": self.stc.ReplaceTarget(replacetext) self.targetEnd = self.targetEnd + diff else: x = x - 1 p = p + 1 p = self.stc.FindText((p + len(replacetext)), self.targetEnd, findtext, flags) else: p = -1 x = x - 1 else: self.stc.ReplaceTarget(replacetext) self.targetEnd = self.targetEnd + diff p = self.stc.FindText((p + len(replacetext)), self.targetEnd, findtext, flags) x = x + 1 return x def REReplaceAll(self, findtext, replacetext, matchcase, prompt = 0): case = 0 if not matchcase: case = re.IGNORECASE try: regularexpression = re.compile(findtext, case | re.MULTILINE) except: drScrolledMessageDialog.ShowMessage(self.parent, 'Regular Expression Error', "DrPython Replace") return oldtext = self.stc.GetText() if not prompt: newtext, x = regularexpression.subn(replacetext, oldtext[self.targetStart:self.targetEnd]) self.stc.SetText(oldtext[0:self.targetStart] + newtext + oldtext[self.targetEnd:]) else: matchedtext = regularexpression.search(self.stc.GetText()[self.findpos:self.targetEnd]) diff = len(replacetext) - len(findtext) x = 0 notfirst = 0 favpos = wx.Point(5, 5) while matchedtext is not None: oldpos = self.findpos self.findpos = oldpos + matchedtext.start() endpos = oldpos + matchedtext.end() if self.parent.prefs.docfolding: self.stc.EnsureVisible(self.stc.LineFromPosition(self.findpos)) self.stc.GotoPos(self.findpos) self.stc.EnsureCaretVisible() self.stc.SetSelectionStart(self.findpos) self.stc.SetSelectionEnd(endpos) self.stc.SetTargetStart(self.findpos) self.stc.SetTargetEnd(endpos) d = wx.SingleChoiceDialog(self.parent, ("Found \"" + findtext + "\" at Line: " \ + str(self.stc.LineFromPosition(self.findpos)+1) + \ " Col: " + str(self.stc.GetColumn(self.findpos)) + \ "\n(Hit Cancel to Stop)"), "Replace", ["Replace", "Skip"], wx.CHOICEDLG_STYLE) if notfirst: d.Move(favpos) else: notfirst = 1 answer = d.ShowModal() favpos = d.GetPosition() d.Destroy() if answer == wx.ID_OK: if d.GetStringSelection() == "Replace": self.stc.ReplaceTarget(replacetext) self.findpos = self.findpos + len(replacetext) self.targetEnd = self.targetEnd + diff else: self.findpos = endpos x = x - 1 x = x + 1 matchedtext = regularexpression.search(self.stc.GetText()[self.findpos:self.targetEnd]) else: matchedtext = None return x def reset(self): self.inselection = 0 self.findflags = 0 self.findpos = 0 self.lastposition = 0 self.backwards = 0 self.findtext = "" self.targetStart = 0 self.targetEnd = 0 self.docEnd = 0 self.RE = 0 self.rectanglefind = 0 def searchInArray(self, regularexpression, arrayposition, position): l = len(self.Lines) match = regularexpression.search(self.Lines[arrayposition][position:]) if match is None: arrayposition += 1 while arrayposition < l: match = regularexpression.search(self.Lines[arrayposition]) if match is None: arrayposition += 1 else: return match, arrayposition return match, arrayposition def SetFindPos(self, findpos): self.findpos = findpos def SetFindText(self, findtext): self.findtext = findtext def SetTargetPositions(self, matchcase): self.targetText = self.stc.GetSelectedText() self.findflags = matchcase if not matchcase: self.targetText = self.targetText.lower() eolchar = self.stc.GetEndOfLineCharacter() self.Lines = self.targetText.strip().split(eolchar) self.targetText = self.targetText.replace(eolchar, '') c = self.stc.GetColumn(self.targetStart) linenumber = self.stc.LineFromPosition(self.targetStart) lenline = len(self.Lines[0]) self.positions = [] for line in self.Lines: position_of_first_character = c + self.stc.PositionFromLine(linenumber) self.positions.append(range(position_of_first_character, position_of_first_character+lenline)) linenumber = linenumber + 1 def SetTargetRange(self, start, end, backwards = 0): self.docEnd = self.stc.GetTextLength() self.inselection = (start > 0) | (end < self.docEnd) self.findpos = start if backwards: self.findpos = end self.targetStart = start self.targetEnd = end class drFindTextCtrl(wx.ComboBox): def __init__(self, parent, id, value, pos, size, returnfunction = None, InFiles = False): wx.ComboBox.__init__(self, parent, id, value, pos, size) #This is a workaround for a bug in how wx.TextCtrl handles #carriage returns on windows. self.parent = parent if InFiles: self.ancestor = parent.parent.parent else: self.ancestor = parent.parent if self.ancestor.PLATFORM_IS_WIN: self.doReplace = True self.cr = chr(5) else: self.doReplace = False self.cr = '\r' self.ID_CHAR_BASE = 20 self.ID_MENU_BASE = 50 self.ID_HISTORY_BASE = 420 self.returnfunc = returnfunction if self.returnfunc is None: self.returnfunc = self.parent.OnbtnFind self.Bind(wx.EVT_CHAR, self.OnChar) self.Bind(wx.EVT_RIGHT_DOWN, self.OnPopUp) #wxPython Bug Work-Around if self.ancestor.PLATFORM_IS_WIN: self.insertionpoint = -1 self.Bind(wx.EVT_SET_FOCUS, self.OnFocus) #franz07/19: catch kill focus self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) #endfranz07/19 def AppendToHistory(self, targetList): text = self.GetText() try: i = targetList.index(text) targetList.pop(i) except: pass targetList.append(text) def GetText(self): text = self.GetValue() if self.doReplace: return text.replace(chr(5), '\r') else: return text def OnChar(self, event): if event.GetKeyCode() == wx.WXK_ESCAPE: self.parent.OnbtnCancel(event) elif event.GetKeyCode() == wx.WXK_RETURN: self.returnfunc(event) else: event.Skip() def OnFocus(self, event): self.insertionpoint = -1 event.Skip() #franz07/19: do not steal focus #drpython: removed "pass", replaced with function code below. def OnKillFocus(self, event): self.insertionpoint = self.GetInsertionPoint() event.Skip() #franz07/19 def OnPopUp(self, event): self.PopUp(event.GetPosition()) def OnPopUpMenu(self, event): eid = event.GetId() pos = self.GetInsertionPoint() #wxPython Bug Work-Around if self.ancestor.PLATFORM_IS_WIN: if self.insertionpoint > -1: pos = self.insertionpoint text = self.GetValue() if eid == self.ID_CHAR_BASE: self.SetValue(text[:pos] + '\t' + text[pos:]) self.SetInsertionPoint(pos+1) elif eid == self.ID_CHAR_BASE+1: self.SetValue(text[:pos] + '\n' + text[pos:]) self.SetInsertionPoint(pos+1) elif eid == self.ID_CHAR_BASE+2: self.SetValue(text[:pos] + self.cr + text[pos:]) self.SetInsertionPoint(pos+1) elif eid == self.ID_MENU_BASE+1: self.Cut() elif eid == self.ID_MENU_BASE+2: self.Copy() elif eid == self.ID_MENU_BASE+3: self.Paste() elif eid == self.ID_MENU_BASE+4: f, to = self.GetSelection() self.Remove(f, to) elif eid == self.ID_MENU_BASE+5: self.SetValue("") self.SetFocus() def PopUp(self, pos): self.PopUpMenu = wx.Menu() self.CharMenu = wx.Menu() self.CharMenu.Append(self.ID_CHAR_BASE, "Tab (\\t)") self.CharMenu.Append(self.ID_CHAR_BASE+1, "Newline (\\n)") self.CharMenu.Append(self.ID_CHAR_BASE+2, "Carraige Return (\\r)") self.PopUpMenu.Append(self.ID_MENU_BASE+5, "Clear Text") self.PopUpMenu.AppendSeparator() self.PopUpMenu.AppendMenu(self.ID_MENU_BASE, "Insert Special Character", self.CharMenu) self.PopUpMenu.AppendSeparator() self.PopUpMenu.Append(self.ID_MENU_BASE+1, "Cut") self.PopUpMenu.Append(self.ID_MENU_BASE+2, "Copy") self.PopUpMenu.Append(self.ID_MENU_BASE+3, "Paste") self.PopUpMenu.Append(self.ID_MENU_BASE+4, "Delete") x = 0 y = 0 while x < 6: if y < 3: self.Bind(wx.EVT_MENU, self.OnPopUpMenu, id=self.ID_CHAR_BASE+y) y = y + 1 self.Bind(wx.EVT_MENU, self.OnPopUpMenu, id=self.ID_MENU_BASE+x) x = x + 1 self.PopupMenu(self.PopUpMenu, pos) self.PopUpMenu.Destroy() def SetHistory(self, history): if self.GetCount() > 0: self.Clear() l = len(history) #self.Append('') x = l - 1 while x > -1: self.Append(history[x]) x = x - 1 if l > 0: self.SetMark(0, len(history[l-1])) class drFindReplaceDialog(wx.Dialog): def __init__(self, parent, id, title, stc, IsReplace = 0): wx.Dialog.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(-1, -1), wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.THICK_FRAME | wx.RESIZE_BORDER) self.ID_FIND = 1001 self.ID_CANCEL = 1002 self.ID_CHK_REGEX = 1010 self.ID_CREATERE = 1011 self.ID_SEARCH_TXT = 1012 self.ID_BTNSF = 98 self.ID_BTNRW = 99 self.parent = parent self.stc = stc self.theSizer = wx.FlexGridSizer(8, 3, 5, 10) self.IsReplace = IsReplace #Size Buffer self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Search For: "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.txtSearchFor = drFindTextCtrl(self, self.ID_SEARCH_TXT, "", wx.DefaultPosition, wx.Size(250, -1)) self.btnPopUpSearchFor = wx.Button(self, self.ID_BTNSF, " Menu ") self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(self.txtSearchFor, 1, wx.SHAPED) self.theSizer.Add(self.btnPopUpSearchFor, 1, wx.SHAPED) self.txtSearchFor.SetHistory(parent.FindHistory) if IsReplace: #self.SetSize(wx.Size(400, 345)) self.txtReplaceWith = drFindTextCtrl(self, -1, "", wx.DefaultPosition, wx.Size(250, -1)) self.btnPopUpReplaceWith = wx.Button(self, self.ID_BTNRW, " Menu ") self.txtReplaceWith.SetHistory(parent.ReplaceHistory) self.chkRegularExpression = wx.CheckBox(self, self.ID_CHK_REGEX, "RegularExpression") self.btnCreateRE = wx.Button(self, self.ID_CREATERE, " &Create ") self.chkMatchCase = wx.CheckBox(self, -1, "Match Case") self.chkFindBackwards = wx.CheckBox(self, -1, "Find Backwards") self.chkWholeWord = wx.CheckBox(self, -1, "Whole Word") self.chkInSelection = wx.CheckBox(self, -1, "In Selection") self.chkFromCursor = wx.CheckBox(self, -1, "From Cursor") #Prefs self.chkRegularExpression.SetValue(parent.prefs.findreplaceregularexpression) self.btnCreateRE.Enable(parent.prefs.findreplaceregularexpression) self.chkMatchCase.SetValue(parent.prefs.findreplacematchcase) self.chkFindBackwards.SetValue(parent.prefs.findreplacefindbackwards) self.chkWholeWord.SetValue(parent.prefs.findreplacewholeword) self.chkInSelection.SetValue(parent.prefs.findreplaceinselection) self.chkFromCursor.SetValue(parent.prefs.findreplacefromcursor) self.chkInSelection.Enable(len(parent.txtDocument.GetSelectedText()) > 0) if IsReplace: self.chkPromptOnReplace = wx.CheckBox(self, -1, "Prompt on Replace") self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Replace With: "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(self.txtReplaceWith, 1 ,wx.SHAPED) self.theSizer.Add(self.btnPopUpReplaceWith, 1, wx.SHAPED) self.chkFromCursor.Disable() self.chkFindBackwards.Disable() #Prefs self.chkPromptOnReplace.SetValue(parent.prefs.findreplacepromptonreplace) self.Bind(wx.EVT_BUTTON, self.OnbtnPopUp, id=self.ID_BTNRW) #Size Buffer self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(self.chkRegularExpression, 1, wx.SHAPED) self.theSizer.Add(self.btnCreateRE, 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(self.chkMatchCase, 1, wx.SHAPED) self.theSizer.Add(self.chkFindBackwards, 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(self.chkWholeWord, 1, wx.SHAPED) self.theSizer.Add(self.chkInSelection, 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(self.chkFromCursor, 1, wx.SHAPED) if IsReplace: self.theSizer.Add(self.chkPromptOnReplace, 1, wx.SHAPED) else: self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.btnCancel = wx.Button(self, self.ID_CANCEL, "&Cancel") self.btnFind = wx.Button(self, self.ID_FIND, "&Ok") self.btnFind.Enable(False) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(self.btnCancel, 1, wx.SHAPED) self.theSizer.Add(self.btnFind, 1, wx.SHAPED) self.SetAutoLayout(True) self.SetSizerAndFit(self.theSizer) self.btnFind.SetDefault() self.txtSearchFor.SetFocus() self.Bind(wx.EVT_BUTTON, self.OnbtnCancel, id=self.ID_CANCEL) self.Bind(wx.EVT_BUTTON, self.OnbtnFind, id=self.ID_FIND) self.Bind(wx.EVT_BUTTON, self.OnbtnCreateRE, id=self.ID_CREATERE) self.Bind(wx.EVT_BUTTON, self.OnbtnPopUp, id=self.ID_BTNSF) self.Bind(wx.EVT_CHECKBOX, self.OnCheckRegularExpression, id=self.ID_CHK_REGEX) self.Bind(wx.EVT_TEXT, self.OnTextChanged, id=self.ID_SEARCH_TXT) self.parent.LoadDialogSizeAndPosition(self, 'findreplacedialog.sizeandposition.dat') def OnCloseW(self, event): self.parent.SaveDialogSizeAndPosition(self, 'findreplacedialog.sizeandposition.dat') if event is not None: event.Skip() def GetOptions(self): rarray = [self.chkRegularExpression.GetValue(), self.chkMatchCase.GetValue(), \ self.chkFindBackwards.GetValue(), self.chkWholeWord.GetValue(), \ self.chkInSelection.GetValue(), self.chkFromCursor.GetValue()] if self.IsReplace: rarray.append(self.chkPromptOnReplace.GetValue()) return rarray def OnbtnCancel(self, event): self.Close(1) def OnbtnCreateRE(self, event): from drRegularExpressionDialog import drRegularExpressionDialog d = drRegularExpressionDialog(self, -1, "Create Regular Expression") d.Show() def OnbtnFind(self, event): if not self.btnFind.IsEnabled(): return self.Show(0) findflags = 0 findbackwards = self.chkFindBackwards.GetValue() isRegularExpression = self.chkRegularExpression.GetValue() isMatchCase = self.chkMatchCase.GetValue() self.txtSearchFor.AppendToHistory(self.parent.FindHistory) if self.IsReplace: self.txtReplaceWith.AppendToHistory(self.parent.ReplaceHistory) #Set Target Range if self.chkInSelection.GetValue(): selstart = self.stc.GetSelectionStart() selend = self.stc.GetSelectionEnd() if (selend - selstart) < 1: selstart = 0 selend = self.stc.GetTextLength() self.stc.Finder.SetTargetRange(selstart, selend, findbackwards) #Do the Search if it's a rectangle: if self.stc.SelectionIsRectangle(): if self.IsReplace: if isRegularExpression: x = self.stc.Finder.RectangleREReplaceAll(self.txtSearchFor.GetText(), self.txtReplaceWith.GetText(), isMatchCase) if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, (str(x) + " occurances of \"" + self.txtSearchFor.GetText() + "\" replaced with \"" + self.txtReplaceWith.GetText() + "\""), "Replace") else: x = self.stc.Finder.RectangleReplaceAll(self.txtSearchFor.GetText(), self.txtReplaceWith.GetText(), isMatchCase) if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, (str(x) + " occurances of \"" + self.txtSearchFor.GetText() + "\" replaced with \"" + self.txtReplaceWith.GetText() + "\""), "Replace") else: self.stc.Finder.SetTargetPositions(isMatchCase) if isRegularExpression: self.stc.Finder.DoRERectangleFind(self.txtSearchFor.GetText(), isMatchCase) else: self.stc.Finder.DoRectangleFind(self.txtSearchFor.GetText(), isMatchCase, findbackwards) self.Close(1) return else: self.stc.Finder.SetTargetRange(0, self.stc.GetTextLength(), findbackwards) if self.chkFromCursor.GetValue(): #) and (not self.IsReplace): self.stc.Finder.SetFindPos(self.stc.GetCurrentPos()) #Do Search if isRegularExpression: if self.IsReplace: x = self.stc.Finder.REReplaceAll(self.txtSearchFor.GetText(), self.txtReplaceWith.GetText(), isMatchCase, self.chkPromptOnReplace.GetValue()) if x == 0: if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, 'Search string: "' + self.txtSearchFor.GetText() + '" not found.', 'DrPython Replace') else: self.parent.SetStatusText( '"'+self.txtSearchFor.GetText() + '" NOT FOUND', 2) else: if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, (str(x) + " occurances of \"" + self.txtSearchFor.GetText() + "\" replaced with \"" + self.txtReplaceWith.GetText() + "\""), "Replace") else: self.parent.SetStatusText(str(x) + ' occurances of "' + self.txtSearchFor.GetText() + '" replaced with "' + self.txtReplaceWith.GetText() + '"', 2) else: self.stc.Finder.DoREFind(self.txtSearchFor.GetText(), isMatchCase) else: #Set Flags if self.chkWholeWord.GetValue(): findflags = findflags | wx.stc.STC_FIND_WHOLEWORD if isMatchCase: findflags = findflags | wx.stc.STC_FIND_MATCHCASE if self.IsReplace: x = self.stc.Finder.ReplaceAll(self.txtSearchFor.GetText(), self.txtReplaceWith.GetText(), findflags, self.chkPromptOnReplace.GetValue()) if x == 0: if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, 'Search string: "' + self.txtSearchFor.GetText() + '" not found.', 'DrPython Replace') else: self.parent.SetStatusText( '"'+self.txtSearchFor.GetText() + '" NOT FOUND', 2) else: if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, (str(x) + " occurances of \"" + self.txtSearchFor.GetText() + "\" replaced with \"" + self.txtReplaceWith.GetText() + "\""), "Replace") else: self.parent.SetStatusText(str(x) + ' occurances of "' + self.txtSearchFor.GetText() + '" replaced with "' + self.txtReplaceWith.GetText() + '"', 2) else: self.stc.Finder.DoFind(self.txtSearchFor.GetText(), findflags, findbackwards) self.Close(1) if self.IsReplace: self.parent.ReplaceOptions = self.GetOptions() else: self.parent.FindOptions = self.GetOptions() if findbackwards: self.stc.Finder.ScrollFewLinesBelow() else: self.stc.Finder.ScrollFewLinesAbove() # top = self.parent.txtDocument.GetCurrentLine() - self.parent.txtDocument.LinesOnScreen()/2 # if top < 0: # top = 0 # self.parent.txtDocument.ScrollToLine(top) def OnbtnPopUp(self, event): eid = event.GetId() if eid == self.ID_BTNSF: s = self.txtSearchFor.GetPosition()[0] x = self.btnPopUpSearchFor.GetPosition()[0] self.txtSearchFor.PopUp((x-s, 0)) elif eid == self.ID_BTNRW: s = self.txtReplaceWith.GetPosition()[0] x = self.btnPopUpReplaceWith.GetPosition()[0] self.txtReplaceWith.PopUp((x-s, 0)) def OnCheckRegularExpression(self, event): usingRegularExpressions = self.chkRegularExpression.GetValue() self.btnCreateRE.Enable(usingRegularExpressions) self.chkWholeWord.Enable(not usingRegularExpressions) if not self.IsReplace: self.chkFindBackwards.Enable(not usingRegularExpressions) def OnTextChanged(self, event): self.btnFind.Enable(len(self.txtSearchFor.GetText()) > 0) def SetFindString(self, findstring): self.txtSearchFor.SetValue(findstring) self.txtSearchFor.SetMark(0, len(findstring)) self.OnTextChanged(None) def SetOptions(self, OptionsArray): if OptionsArray: self.chkRegularExpression.SetValue(OptionsArray[0]) self.btnCreateRE.Enable(OptionsArray[0]) self.chkMatchCase.SetValue(OptionsArray[1]) self.chkFindBackwards.SetValue(OptionsArray[2]) self.chkWholeWord.SetValue(OptionsArray[3]) self.chkInSelection.SetValue(OptionsArray[4]) self.chkFromCursor.SetValue(OptionsArray[5]) if self.IsReplace: self.chkPromptOnReplace.SetValue(OptionsArray[6]) drpython-3.11.1/setup.cfg0000644000175000017500000000005211150445515016071 0ustar dktrkranzdktrkranz[bdist_wininst] install-script=postinst.pydrpython-3.11.1/drPrefsFile.py0000644000175000017500000000775611150445514017050 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Preferences #LongLineCol from Chris McDonough #Changed "doc.longlinecol" to "doc.long.line.col" import drPreferences import re def GetPrefValue(preflabel, text): restart = re.compile('^<' + preflabel + '>', re.M) reend = re.compile('$', re.M) start = restart.search(text) end = reend.search(text) if start is None or end is None: return None return text[start.end():end.start()] def ConvertRawPreference(preference, type, default): if type == 0: if preference: return preference else: return default elif type == 1: try: return int(preference) except: return 0 elif type == 2: return preference def ExtractPreferenceFromText(text, pref): try: start = text.index("<" + pref + ">") + len(pref) + 2 end = text.index("") return text[start:end] except: return "" def ReadPreferences(prefs, prefsfile): #Handle exceptions in parent function. #sets prefs for parent frame. #Use GetPrefFromText(oldpref, text, prefstring) for string prefs #Use GetPrefFromText(oldpref, text, prefstring, True) for int prefs #Use ExtractPreferenceFromText(text, prefstring) for prefs where and empty #string is a valid value. fin = open(prefsfile, 'r') text = fin.read() fin.close() PreferencesDictionary = drPreferences.GetPreferencesDictionary() for Entry in PreferencesDictionary: for Preference in PreferencesDictionary[Entry]: value = GetPrefValue(Preference[1], text) if value is not None: prefs[Preference[0]] = ConvertRawPreference(value, Preference[2], prefs[Preference[0]]) def WritePreferences(prefs, prefsfile): fin = open(prefsfile, 'w') PreferencesDictionary = drPreferences.GetPreferencesDictionary() for Entry in PreferencesDictionary: for Preference in PreferencesDictionary[Entry]: if Preference[2] == 1: fin.write('<' + Preference[1] + '>' + str(prefs[Preference[0]]) + '\n') else: fin.write('<' + Preference[1] + '>' + prefs[Preference[0]] + '\n') fin.close() #***************************** #Old Functions (Still Used In Plugins) def GetPreference(pref, prefsfile): #Handle exceptions in parent function. fin = open(prefsfile, 'r') text = fin.read() fin.close() #Test File: if text.find("drpython") < 0: return -1 return ExtractPreferenceFromText(text, pref) def GetPrefFromText(oldvalue, text, targetpref, integer = False): if integer: pref = ExtractPreferenceFromText(text, targetpref) if pref: return SafeInt(pref) else: pref = ExtractPreferenceFromText(text, targetpref) if pref: return pref return oldvalue def SafeInt(string): if string: try: return int(string) except: return 0 return 0drpython-3.11.1/drpython.lin0000644000175000017500000000005011150445514016620 0ustar dktrkranzdktrkranz#!/bin/bash python ${0%/*}/drpython.pyw drpython-3.11.1/drToolBarDialog.py0000644000175000017500000005220311150445515017637 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #ToolBar Menu Dialog import os.path, re import wx import wx.stc import drScrolledMessageDialog import drShortcutsFile import drToolBarFile import drFileDialog def GetToolBarLabels(filename, frame): try: f = file(filename, 'r') text = f.read() f.close() except: drScrolledMessageDialog.ShowMessage(frame, 'File error with: "' + filename + '".', "ERROR") return [] # modified 22/10/2006 Jean-Pierre MANDON # line: rePopUpMenu = re.compile(r'^\s*?DrFrame\.AddToolBarFunction\(.*\)', re.MULTILINE) # replaced with rePopUpMenu = re.compile(r'^\s*?DrFrame\.AddPluginToolBarFunction\(.*\)', re.MULTILINE) allPopUps = rePopUpMenu.findall(text) PopUpArray = [] for s in allPopUps: #From the Left most '(' start = s.find('(') #To the Right most ')' end = s.rfind(')') if (start > -1) and (end > -1): s = s[start+1:end] i = s.find(',') # modified 22/10/2006 Jean-Pierre MANDON """ e = i + 1 + s[i+1:].find(',') arglabel = s[i+1:e].strip().strip('"') """ # replaced with arglabel=s[1:i-1] arglabel=arglabel.strip().strip('"') # end of modification PopUpArray.append(":"+arglabel) return PopUpArray class drToolBarDialog(wx.Dialog): def __init__(self, parent): wx.Dialog.__init__(self, parent, -1, "Customize ToolBar", wx.DefaultPosition, wx.Size(-1, -1), wx.DEFAULT_DIALOG_STYLE | wx.THICK_FRAME) wx.Yield() self.parent = parent self.ID_PROGRAM = 1001 self.ID_POPUP = 1002 self.ID_ADD = 1003 self.ID_REMOVE = 1004 self.ID_UPDATE = 1005 self.ID_SAVE = 1006 self.ID_LIST = 1300 self.ID_UP = 1111 self.ID_DOWN = 2222 self.ID_16 = 3016 self.ID_24 = 3024 self.theSizer = wx.FlexGridSizer(5, 4, 5, 10) self.menubuttonSizer = wx.BoxSizer(wx.VERTICAL) self.listSizer = wx.BoxSizer(wx.HORIZONTAL) self.preferencesdirectory = parent.preferencesdirectory ToolBarList = [] map(ToolBarList.append, parent.ToolBarList) #Icons: self.customNames, self.customFiles16, self.customFiles24 = drToolBarFile.getCustomBitmaps(self.parent.datdirectory) #End Icons ToolBarList.insert(0, "") programmenulist = drShortcutsFile.GetShortcutList() try: i = programmenulist.index("Toggle Maximize") programmenulist.pop(i) except: pass programmenulist.sort() programmenulist.insert(0, "") self.ListArray = [] self.ListArray.append(programmenulist) #STC stclist = [] map(stclist.append, drShortcutsFile.GetSTCShortcutList()) stclist.insert(0, "") self.ListArray.append(stclist) #DrScript drscriptlist = [] map(drscriptlist.append, parent.drscriptmenu.titles) x = 0 l = len(drscriptlist) while x < l: drscriptlist[x] = ":" + drscriptlist[x] x = x + 1 drscriptlist.insert(0, "") self.ListArray.append(drscriptlist) #Plugins plist = os.listdir(parent.pluginsdirectory) self.PluginList = [] plugins = [] for p in plist: i = p.find(".py") l = len(p) if i > -1 and (i + 3 == l): self.PluginList.append(":" + p[:i]) plugins.append(p[:i]) poplist = [] for plugin in plugins: pluginfile = os.path.join(self.parent.pluginsdirectory, plugin + ".py") pluginlist = GetToolBarLabels(pluginfile, self) plist = self.parent.GetPluginLabels(pluginfile) for p in plist: if not (p in pluginlist): pluginlist.append(p) if pluginlist: pluginlist.insert(0, "") self.ListArray.append(pluginlist) else: poplist.append(":" + plugin) for popl in poplist: i = self.PluginList.index(popl) self.PluginList.pop(i) list = ["Standard", "Text Control", "DrScript"] list.extend(self.PluginList) self.cboList = wx.ComboBox(self, self.ID_LIST, "Standard", wx.DefaultPosition, (200, -1), list, wx.CB_DROPDOWN|wx.CB_READONLY) self.programmenu = wx.ListBox(self, self.ID_PROGRAM, wx.DefaultPosition, wx.Size(250, 250), programmenulist) self.toolbaritems = wx.ListBox(self, self.ID_POPUP, wx.DefaultPosition, wx.Size(250, 250), ToolBarList) self.btnUp = wx.Button(self, self.ID_UP, " Up ") self.btnAdd = wx.Button(self, self.ID_ADD, " ---> ") self.btnRemove = wx.Button(self, self.ID_REMOVE, " Remove ") self.btnDown = wx.Button(self, self.ID_DOWN, " Down ") self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(self.btnAdd, 0, wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(self.btnUp, 0, wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(self.btnDown, 0, wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(self.btnRemove, 0, wx.SHAPED) self.listSizer.Add(wx.StaticText(self, -1, "List: "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.listSizer.Add(self.cboList, 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.listSizer, 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Current List:"), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "ToolBar:"), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.programmenu, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.menubuttonSizer, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.toolbaritems, 0, wx.SHAPED | wx.ALIGN_CENTER) self.txt16 = wx.TextCtrl(self, -1, "", wx.DefaultPosition, wx.Size(200, -1), wx.TE_READONLY) self.btn16 = wx.Button(self, self.ID_16, "Change") self.txt24 = wx.TextCtrl(self, -1, "", wx.DefaultPosition, wx.Size(200, -1), wx.TE_READONLY) self.btn24 = wx.Button(self, self.ID_24, "Change") self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Icon 16x16:"), 0, wx.ALIGN_LEFT) #AB:with wx.SHAPED only shows 1st word self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Icon 24x24:"), 0, wx.ALIGN_LEFT) #AB:with wx.SHAPED only shows 1st word self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.txt16, 0, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.txt24, 0, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.btn16, 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.btn24, 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.btnUpdate = wx.Button(self, self.ID_UPDATE, "&Update") self.btnSave = wx.Button(self, self.ID_SAVE, "&Save") self.btnClose = wx.Button(self, 101, "&Close") self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.btnClose, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.btnUpdate, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.btnSave, 0, wx.SHAPED | wx.ALIGN_CENTER) self.btnClose.SetDefault() self.SetAutoLayout(True) self.SetSizerAndFit(self.theSizer) self.Bind(wx.EVT_BUTTON, self.OnbtnUp, id=self.ID_UP) self.Bind(wx.EVT_BUTTON, self.OnbtnAdd, id=self.ID_ADD) self.Bind(wx.EVT_BUTTON, self.OnbtnRemove, id=self.ID_REMOVE) self.Bind(wx.EVT_BUTTON, self.OnbtnDown, id=self.ID_DOWN) self.Bind(wx.EVT_BUTTON, self.OnbtnUpdate, id=self.ID_UPDATE) self.Bind(wx.EVT_BUTTON, self.OnbtnSave, id=self.ID_SAVE) self.Bind(wx.EVT_BUTTON, self.OnbtnChange16, id=self.ID_16) self.Bind(wx.EVT_BUTTON, self.OnbtnChange24, id=self.ID_24) self.Bind(wx.EVT_BUTTON, self.OnbtnClose, id=101) self.Bind(wx.EVT_COMBOBOX, self.OnList, id=self.ID_LIST) self.Bind(wx.EVT_LISTBOX, self.OnSelect, id=self.ID_PROGRAM) self.parent.LoadDialogSizeAndPosition(self, 'toolbardialog.sizeandposition.dat') def OnCloseW(self, event): self.parent.SaveDialogSizeAndPosition(self, 'toolbardialog.sizeandposition.dat') if event is not None: event.Skip() def OnbtnAdd(self, event): tselection = self.programmenu.GetStringSelection() tsel = self.programmenu.GetSelection() if tsel == -1: drScrolledMessageDialog.ShowMessage(self, "Nothing Selected to Add", "Mistake") return separator = (tselection == "") if separator: tselection = "" sel = self.toolbaritems.GetSelection() if sel == -1: sel = 0 self.toolbaritems.InsertItems([tselection], sel+1) self.toolbaritems.SetSelection(sel+1) def OnbtnChange16(self, event): d = wx.SingleChoiceDialog(self.parent, 'Change Icon For 16x16:', "Change Icon", ["Default", "Select File"], wx.CHOICEDLG_STYLE) d.SetSize(wx.Size(250, 250)) answer = d.ShowModal() d.Destroy() if answer == wx.ID_OK: sname = self.programmenu.GetStringSelection() i = d.GetSelection() newname = "" if i == 1: dlg = drFileDialog.FileDialog(self.parent, "Open", "PNG (*.png)|*.png") if dlg.ShowModal() == wx.ID_OK: newname = dlg.GetPath() self.txt16.SetValue(newname) if newname == "": newname = "" if sname in self.customNames: ci = self.customNames.index(sname) self.customFiles16.pop(ci) self.customFiles16.insert(ci, newname) else: self.customNames.append(sname) self.customFiles16.append(newname) self.customFiles24.append("") def OnbtnChange24(self, event): d = wx.SingleChoiceDialog(self.parent, 'Change Icon For 24x24:', "Change Icon", ["Default", "Select File"], wx.CHOICEDLG_STYLE) d.SetSize(wx.Size(250, 250)) answer = d.ShowModal() d.Destroy() if answer == wx.ID_OK: sname = self.programmenu.GetStringSelection() i = d.GetSelection() newname = "" if i == 1: dlg = drFileDialog.FileDialog(self.parent, "Open", "PNG (*.png)|*.png") if dlg.ShowModal() == wx.ID_OK: newname = dlg.GetPath() self.txt24.SetValue(newname) if newname == "": newname = "" if sname in self.customNames: ci = self.customNames.index(sname) self.customFiles24.pop(ci) self.customFiles24.insert(ci, newname) else: self.customNames.append(sname) self.customFiles16.append("") self.customFiles24.append(newname) def OnbtnClose(self, event): self.Close(1) def OnbtnDown(self, event): sel = self.toolbaritems.GetSelection() if sel < self.toolbaritems.GetCount()-1 and sel > 0: txt = self.toolbaritems.GetString(sel) self.toolbaritems.Delete(sel) self.toolbaritems.InsertItems([txt], sel+1) self.toolbaritems.SetSelection(sel+1) def OnbtnRemove(self, event): sel = self.toolbaritems.GetSelection() if not sel: drScrolledMessageDialog.ShowMessage(self, "You cannot remove the root item.", "Mistake") return if sel == -1: drScrolledMessageDialog.ShowMessage(self, "Nothing Selected to Remove", "Mistake") return self.toolbaritems.Delete(sel) self.toolbaritems.SetSelection(sel-1) def OnbtnUp(self, event): sel = self.toolbaritems.GetSelection() if sel > 1: txt = self.toolbaritems.GetString(sel) self.toolbaritems.Delete(sel) self.toolbaritems.InsertItems([txt], sel-1) self.toolbaritems.SetSelection(sel-1) def OnbtnUpdate(self, event): y = 0 c = self.toolbaritems.GetCount() ToolBarList = [] while y < c: pop = self.toolbaritems.GetString(y) if not pop == "": ToolBarList.append(pop) y = y + 1 self.parent.ToolBarList = ToolBarList if self.parent.hasToolBar: self.parent.DestroyToolBar() self.parent.SetToolBar(None) self.parent.toolbar = wx.ToolBar(self.parent, -1, wx.DefaultPosition, wx.DefaultSize, wx.TB_HORIZONTAL) self.parent.ToolBarIdList = self.parent.SetupToolBar() if self.parent.prefs.iconsize > 0: self.parent.SetToolBar(self.parent.toolbar) thereisafile = (len(self.parent.txtDocument.filename) > 0) self.parent.toolbar.EnableTool(self.parent.ID_RELOAD, thereisafile) if self.parent.txtPrompt.pid == -1: self.parent.toolbar.EnableTool(self.parent.ID_PYTHON, True) self.parent.toolbar.EnableTool(self.parent.ID_END, False) self.parent.toolbar.EnableTool(self.parent.ID_RUN, thereisafile) self.parent.toolbar.EnableTool(self.parent.ID_SET_ARGS, thereisafile) else: self.parent.toolbar.EnableTool(self.parent.ID_PYTHON, False) self.parent.toolbar.EnableTool(self.parent.ID_END, True) if thereisafile: self.parent.toolbar.EnableTool(self.parent.ID_RUN, False) self.parent.toolbar.EnableTool(self.parent.ID_SET_ARGS, False) if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, ("Succesfully updated the current instance of DrPython.\nClick Save to make it permanent."), "Updated ToolBar") def OnbtnSave(self, event): toolbarfile = self.parent.datdirectory + "/toolbar.dat" msg = "Succesfully wrote to:\n" + toolbarfile + "\nand updated the current instance of DrPython." #Custom Bitmaps. if self.customNames: toolbarcustomfile = self.parent.datdirectory + "/toolbar.custom.icons.dat" f = file(toolbarcustomfile, 'w') x = 0 l = len(self.customNames) while x < l: if (len(self.customFiles16[x]) > 0) or (len(self.customFiles24[x]) > 0): f.write(""+self.customNames[x]+"<16>"+self.customFiles16[x]+"<24>"+self.customFiles24[x]+"\n") x = x + 1 f.close() msg = msg + "\n\nSuccesfully Saved Custom ToolBar Icons." y = 0 c = self.toolbaritems.GetCount() toolbaritemsstring = "" ToolBarList = [] while y < c: pop = self.toolbaritems.GetString(y) if not pop == "": toolbaritemsstring = toolbaritemsstring + pop + "\n" ToolBarList.append(pop) y = y + 1 self.parent.ToolBarList = ToolBarList if self.parent.hasToolBar: if self.parent.toolbar is not None: self.parent.SetToolBar(None) self.parent.DestroyToolBar() self.parent.toolbar = wx.ToolBar(self.parent, -1, wx.DefaultPosition, wx.DefaultSize, wx.TB_HORIZONTAL) self.parent.ToolBarIdList = self.parent.SetupToolBar() if self.parent.prefs.iconsize > 0: self.parent.SetToolBar(self.parent.toolbar) thereisafile = (len(self.parent.txtDocument.filename) > 0) self.parent.toolbar.EnableTool(self.parent.ID_RELOAD, thereisafile) if self.parent.txtPrompt.pid == -1: self.parent.toolbar.EnableTool(self.parent.ID_PYTHON, True) self.parent.toolbar.EnableTool(self.parent.ID_END, False) self.parent.toolbar.EnableTool(self.parent.ID_RUN, thereisafile) self.parent.toolbar.EnableTool(self.parent.ID_SET_ARGS, thereisafile) else: self.parent.toolbar.EnableTool(self.parent.ID_PYTHON, False) self.parent.toolbar.EnableTool(self.parent.ID_END, True) if thereisafile: self.parent.toolbar.EnableTool(self.parent.ID_RUN, False) self.parent.toolbar.EnableTool(self.parent.ID_SET_ARGS, False) try: f = file(toolbarfile, 'w') f.write(toolbaritemsstring) f.close() except IOError: drScrolledMessageDialog.ShowMessage(self, ("There were some problems writing to:\n" + toolbarfile + "\nEither the file is having metaphysical issues, or you do not have permission to write.\nFor metaphysical issues, consult the documentation.\nFor permission issues, change the permissions on the directory to allow yourself write access.\nDrPython will now politely ignore your request to save.\nTry again when you have fixed the problem."), "Write Error") return if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, msg, "Saved ToolBar") def OnList(self, event): sel = self.cboList.GetSelection() self.programmenu.Set(self.ListArray[sel]) def OnSelect(self, event): #Take one away for "Insert Separator" seltext = self.programmenu.GetStringSelection() if seltext in self.customNames: i = self.customNames.index(seltext) if self.customFiles16[i]: self.txt16.SetValue(self.customFiles16[i]) else: self.txt16.SetValue("") if self.customFiles24[i]: self.txt24.SetValue(self.customFiles24[i]) else: self.txt24.SetValue("") else: self.txt16.SetValue("") self.txt24.SetValue("")drpython-3.11.1/drSetupPreferences.py0000644000175000017500000002227511150445515020445 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Requirements(Dependencies): Install Python, and wxPython. # # Tested On Windows, Linux, Mac OS X # # Icons taken from "Klassic New Crisp Icons" by Asif Ali Rizwaan (therizwaan) from the KDE-LOOK site (some edited a bit). # A humble and excellent artist. # Oh, the python icon is taken from wxPython. # The basic design of the program is meant to roughly (ROUGHLY) mimick DrScheme. # The purpose is the same, to provide a simple IDE(integrated development environment) ideal for teaching. # The DrPython icon itself was based on the DrScheme icon, with a slightly edited wxpython icon inserted(note yellow tongue, googly eyes). # # This program could not have been written without the wonderful work of the people behind # python and wxPython, in particular the Styled Text Control. Thank you. Hopefully this tool will be of use. #This is a module for a gui for importing / exporting preferences. import wx import drZip import drFileDialog class drSetupPreferencesDialog(wx.Dialog): def __init__(self, parent): wx.Dialog.__init__(self, parent, -1, 'Setup Preferences', style=wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.THICK_FRAME | wx.RESIZE_BORDER) self.parent = parent self.drframe = parent.drframe self.ID_EXPORT_ALL = 501 self.ID_IMPORT_ALL = 502 self.ID_EXPORT_PREFS = 503 self.ID_IMPORT_PREFS = 504 self.ID_EXPORT_PLUGINS = 505 self.ID_IMPORT_PLUGINS = 506 self.ID_EXPORT_DRSCRIPTS = 507 self.ID_IMPORT_DRSCRIPTS = 518 self.btnExportAll = wx.Button(self, self.ID_EXPORT_ALL, 'Export Preferences, Plugins, DrScripts To Zip') self.btnImportAll = wx.Button(self, self.ID_IMPORT_ALL, 'Import Preferences, Plugins, DrScripts From Zip') self.btnExportPrefs = wx.Button(self, self.ID_EXPORT_PREFS, 'Export Preferences To Zip') self.btnImportPrefs = wx.Button(self, self.ID_IMPORT_PREFS, 'Import Preferences From Zip') self.btnExportPlugins = wx.Button(self, self.ID_EXPORT_PLUGINS, 'Export Plugins To Zip') self.btnImportPlugins = wx.Button(self, self.ID_IMPORT_PLUGINS, 'Import Plugins From Zip') self.btnExportDrScripts = wx.Button(self, self.ID_EXPORT_DRSCRIPTS, 'Export DrScripts To Zip') self.btnImportDrScripts = wx.Button(self, self.ID_IMPORT_DRSCRIPTS, 'Import DrScripts From Zip') self.btnExit = wx.Button(self, wx.ID_CANCEL, 'Exit') self.theSizer = wx.BoxSizer(wx.VERTICAL) self.theSizer.Add(wx.StaticText(self, -1, ' '), 1, wx.EXPAND) self.theSizer.Add(self.btnExportAll, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.btnImportAll, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(wx.StaticText(self, -1, ' '), 1, wx.EXPAND) self.theSizer.Add(self.btnExportPrefs, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.btnImportPrefs, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(wx.StaticText(self, -1, ' '), 1, wx.EXPAND) self.theSizer.Add(self.btnExportPlugins, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.btnImportPlugins, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(wx.StaticText(self, -1, ' '), 1, wx.EXPAND) self.theSizer.Add(self.btnExportDrScripts, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.btnImportDrScripts, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(wx.StaticText(self, -1, ' '), 1, wx.EXPAND) self.theSizer.Add(self.btnExit, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(wx.StaticText(self, -1, ' '), 1, wx.EXPAND) self.SetAutoLayout(True) self.SetSizerAndFit(self.theSizer) self.Bind(wx.EVT_BUTTON, self.OnExportAll, id=self.ID_EXPORT_ALL) self.Bind(wx.EVT_BUTTON, self.OnImportAll, id=self.ID_IMPORT_ALL) self.Bind(wx.EVT_BUTTON, self.OnExportPrefs, id=self.ID_EXPORT_PREFS) self.Bind(wx.EVT_BUTTON, self.OnImportPrefs, id=self.ID_IMPORT_PREFS) self.Bind(wx.EVT_BUTTON, self.OnExportPlugins, id=self.ID_EXPORT_PLUGINS) self.Bind(wx.EVT_BUTTON, self.OnImportPlugins, id=self.ID_IMPORT_PLUGINS) self.Bind(wx.EVT_BUTTON, self.OnExportDrScripts, id=self.ID_EXPORT_DRSCRIPTS) self.Bind(wx.EVT_BUTTON, self.OnImportDrScripts, id=self.ID_IMPORT_DRSCRIPTS) def OnExportAll(self, event): dlg = drFileDialog.FileDialog(self.drframe, "Export Preferences, Plugins, and DrScripts To", 'Zip File (*.zip)|*.zip', IsASaveDialog=True) if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath().replace("\\", "/") drZip.ExportPreferencesTo(self.drframe.pluginsdirectory, self.drframe.preferencesdirectory, self.drframe.datdirectory, filename) dlg.Destroy() def OnExportDrScripts(self, event): dlg = drFileDialog.FileDialog(self.drframe, "Export DrScripts To", 'Zip File (*.zip)|*.zip', IsASaveDialog=True) if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath().replace("\\", "/") drZip.ExportDrScriptsTo(self.drframe.preferencesdirectory, filename) dlg.Destroy() def OnExportPlugins(self, event): dlg = drFileDialog.FileDialog(self.drframe, "Export Plugins To", 'Zip File (*.zip)|*.zip', IsASaveDialog=True) if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath().replace("\\", "/") drZip.ExportDirectoryTo(self.drframe.pluginsdirectory, filename, 'plugins') dlg.Destroy() def OnExportPrefs(self, event): dlg = drFileDialog.FileDialog(self.drframe, "Export Preferences To", 'Zip File (*.zip)|*.zip', IsASaveDialog=True) if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath().replace("\\", "/") drZip.ExportPreferencesTo(self.drframe.pluginsdirectory, self.drframe.preferencesdirectory, self.drframe.datdirectory, filename, plugins=False, drscripts=False) dlg.Destroy() def OnImportAll(self, event): if self.drframe.Ask('This will permanently overwrite all of your preferences, plugins, and drscript file.\n\nProceed?', 'Warning'): dlg = drFileDialog.FileDialog(self.drframe, "Import Preferences, Plugins, and DrScripts From", 'Zip File (*.zip)|*.zip') if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath().replace("\\", "/") drZip.ImportPreferencesFrom(self.drframe.preferencesdirectory, filename) self.drframe.ShowMessage('Successfully imported preferences, plugins, and drscripts.', 'Import Success') dlg.Destroy() def OnImportDrScripts(self, event): if self.drframe.Ask('This will permanently overwrite all of your drscript file.\n\nProceed?', 'Warning'): dlg = drFileDialog.FileDialog(self.drframe, "Import DrScripts From", 'Zip File (*.zip)|*.zip') if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath().replace("\\", "/") drZip.ImportDrScriptsFrom(self.drframe.preferencesdirectory, filename) self.drframe.ShowMessage('Successfully imported drscripts.', 'Import Success') dlg.Destroy() def OnImportPlugins(self, event): if self.drframe.Ask('This will permanently overwrite all of your plugins.\n\nProceed?', 'Warning'): dlg = drFileDialog.FileDialog(self.drframe, "Import Plugins From", 'Zip File (*.zip)|*.zip') if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath().replace("\\", "/") drZip.ImportPluginsFrom(self.drframe.preferencesdirectory, filename) self.drframe.ShowMessage('Successfully imported plugins.', 'Import Success') dlg.Destroy() def OnImportPrefs(self, event): if self.drframe.Ask('This will permanently overwrite all of your preferences.\n\nProceed?', 'Warning'): dlg = drFileDialog.FileDialog(self.drframe, "Import Preferences From", 'Zip File (*.zip)|*.zip') if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath().replace("\\", "/") drZip.ImportJustPreferencesFrom(self.drframe.preferencesdirectory, filename) self.drframe.ShowMessage('Successfully imported preferences.', 'Import Success') dlg.Destroy()drpython-3.11.1/drBookmarksMenu.py0000644000175000017500000001075011150445514017732 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Bookmarks Menu import os.path import wx from drProperty import * import drScrolledMessageDialog class drBookmarksMenu(wx.Menu): def __init__(self, parent): wx.Menu.__init__(self) self.ID_BOOKMARK_BASE = 5500 self.ID_BOOKMARK_MENU = 5199 self.bookmarks = [] self.parent = parent self.datdirectory = parent.datdirectory self.loadBookmarks() def loadBookmarks(self): bookfile = self.datdirectory + "/bookmarks.dat" if os.path.exists(bookfile): try: #Read from the file f = open(bookfile, 'r') folders = [self] folderindex = 0 menuTitles = [] menuTitleindex = -1 lastCount = 1 bookmarkcount = 0 #Skip the First Line line = f.readline() #Initialize line = f.readline() while line: c = line.count('\t') line = line[c:].rstrip() while lastCount > c: folders[(folderindex - 1)].AppendMenu(self.ID_BOOKMARK_MENU, menuTitles.pop(), folders.pop()) folderindex = folderindex - 1 menuTitleindex = menuTitleindex - 1 lastCount = lastCount - 1 if line[0] == '>': folders.append(wx.Menu()) menuTitles.append(line[1:]) folderindex = folderindex + 1 menuTitleindex = menuTitleindex + 1 c = c + 1 else: self.bookmarks.append(line) self.parent.Bind(wx.EVT_MENU, self.OnBookmark, id=(self.ID_BOOKMARK_BASE + bookmarkcount)) folders[folderindex].Append((self.ID_BOOKMARK_BASE + bookmarkcount), line, line) bookmarkcount = bookmarkcount + 1 lastCount = c line = f.readline() f.close() #Add any menus not yet added: c = 1 while lastCount > c: folders[(folderindex - 1)].AppendMenu(self.ID_BOOKMARK_MENU, menuTitles.pop(), folders.pop()) folderindex = folderindex - 1 menuTitleindex = menuTitleindex - 1 lastCount = lastCount - 1 except: drScrolledMessageDialog.ShowMessage(self.parent, ("Your bookmarks file is a tad messed up.\n"), "Error") def OnBookmark(self, event): bookmarkindex = event.GetId() - self.ID_BOOKMARK_BASE if not os.path.exists(self.bookmarks[bookmarkindex]): drScrolledMessageDialog.ShowMessage(self.parent, ("Error with: " + self.bookmarks[bookmarkindex] + "\nBookmark does not actually exist.\n"), "Error") elif os.path.isdir(self.bookmarks[bookmarkindex]): self.parent.ddirectory = self.bookmarks[bookmarkindex].replace("\\", "/") self.parent.OnOpen(event) else: filename = self.bookmarks[bookmarkindex].replace("\\", "/") self.parent.OpenOrSwitchToFile(filename) def reloadBookmarks(self): mnuitems = self.GetMenuItems() num = len(mnuitems) x = 0 while x < num: self.Remove(mnuitems[x].GetId()) #mnuitems[x].Destroy() x = x + 1 self.bookmarks = [] self.loadBookmarks() drpython-3.11.1/drProperty.py0000644000175000017500000000772311150445514017007 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA def convertStyleToColorArray(StyleString): ''' Returns a two arrays, one for the foreground, and one for the background ''' #Returns the Red, Green Blue Values for a string formatted: #00FF33 return (convertColorPropertyToColorArray(getStyleProperty("fore", StyleString)), convertColorPropertyToColorArray(getStyleProperty("back", StyleString))) def convertColorPropertyToColorArray(ColorString): #Returns the Red, Green Blue Values for a string formatted: #00FF33 return int(ColorString[1:3], 16), int(ColorString[3:5], 16), int(ColorString[5:7], 16) def convertStyleStringToWXFontArray(StyleString): #This returns an array to be used as arguments in the wx.Font constructor, #Face, Size, Underline, Bold, Italic t = getStyleProperty("size", StyleString) size = int(t) t = getStyleProperty("italic", StyleString) italic = (len(t) > 0) t = getStyleProperty("bold", StyleString) bold = (len(t) > 0) t = getStyleProperty("underline", StyleString) underline = (len(t) > 0) t = getStyleProperty("face", StyleString) face = t return face, size, underline, bold, italic def getStyleProperty(Property, StyleString): if (Property == "bold") or (Property == "italic") or (Property == "underline"): if StyleString.find(Property) != -1: return Property else: return "" i = StyleString.find(Property) if i != -1: lindex = i + len(Property) + 1 rindex = StyleString[lindex:].find(",") if rindex == -1: return StyleString[lindex:] rindex = rindex + lindex return StyleString[lindex:rindex] return "" def setStyleProperty(Property, StyleString, newValue): i = StyleString.find(Property) if Property == "bold": if i != -1: return StyleString[0:i] + "," + newValue + StyleString[(i + len(Property)):] else: prop = getStyleProperty("face", StyleString) i = StyleString.find(prop) + len(prop) return StyleString[0:i] + "," + newValue + StyleString[i:] if Property == "italic": if i != -1: return StyleString[0:i] + "," + newValue + StyleString[(i + len(Property)):] else: prop = getStyleProperty("face", StyleString) i = StyleString.find(prop) + len(prop) return StyleString[0:i] + "," + newValue + StyleString[i:] if Property == "underline": if i != -1: return StyleString[0:i] + "," + newValue + StyleString[(i + len(Property)):] else: prop = getStyleProperty("face", StyleString) i = StyleString.find(prop) + len(prop) return StyleString[0:i] + "," + newValue + StyleString[i:] if i != -1: lindex = i + len(Property) + 1 rindex = StyleString[lindex:].find(",") if rindex == -1: return StyleString[0:lindex] + newValue rindex = rindex + lindex return StyleString[0:lindex] + newValue + StyleString[rindex:] return "" drpython-3.11.1/drZip.py0000644000175000017500000002213011150445515015713 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Requirements(Dependencies): Install Python, and wxPython. # # Tested On Windows, Linux, Mac OS X # # Icons taken from "Klassic New Crisp Icons" by Asif Ali Rizwaan (therizwaan) from the KDE-LOOK site (some edited a bit). # A humble and excellent artist. # Oh, the python icon is taken from wxPython. # The basic design of the program is meant to roughly (ROUGHLY) mimick DrScheme. # The purpose is the same, to provide a simple IDE(integrated development environment) ideal for teaching. # The DrPython icon itself was based on the DrScheme icon, with a slightly edited wxpython icon inserted(note yellow tongue, googly eyes). # # This program could not have been written without the wonderful work of the people behind # python and wxPython, in particular the Styled Text Control. Thank you. Hopefully this tool will be of use. #This is a module to make adding #to / from zip files really easy. #Targets are prefs directory, #creating a directory structure from the drscript menu #an all plugins. import os, zipfile, string, tempfile from drPrefsFile import ExtractPreferenceFromText def AddDirectoryToZipFile(directory, dirname, zip): dlist = os.listdir(directory) for item in dlist: absitem = os.path.join(directory, item) zipitem = os.path.join(dirname, item) if os.path.isdir(absitem): AddDirectoryToZipFile(absitem, zipitem, zip) else: zip.write(absitem, zipitem) def AddDrScriptsToZipFile(prefdir, zip): scriptfile = prefdir + "/drscript.dat" if os.path.exists(scriptfile): newlines = [] dirstrings = ['drscripts'] lastCount = 0 #Read from the file f = open(scriptfile, 'rb') #Initialize line = f.readline() while line: c = line.count('\t') indentationstring = line[:c] line = line[c:].rstrip() while lastCount > c: dirstrings.pop() lastCount = lastCount - 1 if line[0] == '>': dirstrings.append(line[1:]) newlines.append(indentationstring + line) c = c + 1 else: line_path = ExtractPreferenceFromText(line, "path") line_title = ExtractPreferenceFromText(line, "title") line_filename = os.path.basename(line_path) if os.path.exists(line_path): zippath = string.join(dirstrings, '/') zipname = os.path.join(zippath, line_filename) zip.write(line_path, zipname) newlines.append(indentationstring + '' + zipname + '' + line_title + '') lastCount = c line = f.readline() f.close() #Add the edited Script File: newtext = string.join(newlines, '\n') tdrscript = tempfile.mktemp() f = file(tdrscript, 'wb') f.write(newtext) f.close() zip.write(tdrscript, 'drscript.dat') #Remove the temporary file: os.remove(tdrscript) #Add Shortcuts zip.write(prefdir + "/drscript.shortcuts.dat", 'drscript.shortcuts.dat') def CreateDirectories(targetdir, zippedfilename): zippedfilename = zippedfilename.replace('\\', '/') d = zippedfilename.find('/') while d > -1: dir = zippedfilename[:d] targetdir = targetdir + '/' + dir if not os.path.exists(targetdir): os.mkdir(targetdir) zippedfilename = zippedfilename[d+1:] d = zippedfilename.find('/') def ExportDirectoryTo(targetdirectory, filename, ziproot = ''): zf = zipfile.ZipFile(filename, 'w') AddDirectoryToZipFile(targetdirectory, ziproot, zf) zf.close() def ExportDrScriptsTo(prefdir, filename): zf = zipfile.ZipFile(filename, 'w') AddDrScriptsToZipFile(prefdir, zf) zf.close() def ExportPreferencesTo(pluginsdirectory, prefdir, shortcutsdir, datdirectory, filename, shortcuts = True, popupmenu = True, toolbar = True, plugins = True, drscripts = True): zf = zipfile.ZipFile(filename, 'w') #Add Plugins if plugins: AddDirectoryToZipFile(pluginsdirectory, '', zf) if drscripts: AddDrScriptsToZipFile(prefdir, zf) #Add Preferences zf.write(prefdir + "/preferences.dat", 'preferences.dat') #Add Shortcuts if shortcuts: zf.write(shortcutsdir + "/shortcuts.dat", 'shortcuts.dat') zf.write(shortcutsdir + "/stcshortcuts.dat", 'stcshortcuts.dat') #Add Pop Up Menu if popupmenu: zf.write(datdirectory + "/popupmenu.dat", 'popupmenu.dat') #Add ToolBar if toolbar: zf.write(datdirectory + "/toolbar.dat", 'toolbar.dat') zf.close() def ImportDrScriptsFrom(prefdir, filename): UnPackIf(prefdir, filename, 'drscript') SetupImportedDrScripts(prefdir) def ImportPluginsFrom(prefdir, filename): UnPackIf(prefdir, filename, 'plugins') def ImportPreferencesFrom(prefdir, filename): UnPack(prefdir, filename) SetupImportedDrScripts(prefdir) def ImportJustPreferencesFrom(prefdir, filename): UnPackJustPreferences(prefdir, filename) SetupImportedDrScripts(prefdir) def SetupImportedDrScripts(prefdir): scriptfile = prefdir + "/drscript.dat" if os.path.exists(scriptfile): #Read from the file f = open(scriptfile, 'rb') lines = f.readlines() f.close() newlines = [] for line in lines: c = line.count('\t') identationstring = line[:c] if line[0] != '>': line_path = ExtractPreferenceFromText(line, "path") line_title = ExtractPreferenceFromText(line, "title") new_path = os.path.join(prefdir, line_path) if os.path.exists(new_path): newlines.append(identationstring + '' + new_path + '' + line_title + '\n') else: newlines.append(identationstring + line) f = open(scriptfile, 'wb') f.writelines(newlines) f.close() def UnPack(targetdirectory, filename, label=''): zf = zipfile.ZipFile(filename, 'r') dir = targetdirectory + label if not os.path.exists(dir): os.mkdir(dir) zippedfiles = zf.namelist() for zippedfile in zippedfiles: l = len(zippedfile) if (zippedfile[l-1] == '/') or (zippedfile[l-1] == '\\'): CreateDirectories(dir, zippedfile) else: CreateDirectories(dir, zippedfile) data = zf.read(zippedfile) f = file(dir + '/' + zippedfile, 'wb') f.write(data) f.close() zf.close() def UnPackIf(targetdirectory, filename, prefix, label=''): zf = zipfile.ZipFile(filename, 'r') dir = targetdirectory + label if not os.path.exists(dir): os.mkdir(dir) zippedfiles = zf.namelist() for zippedfile in zippedfiles: if zippedfile.find(prefix) == 0: l = len(zippedfile) if (zippedfile[l-1] == '/') or (zippedfile[l-1] == '\\'): CreateDirectories(dir, zippedfile) else: CreateDirectories(dir, zippedfile) data = zf.read(zippedfile) f = file(dir + '/' + zippedfile, 'wb') f.write(data) f.close() zf.close() def UnPackJustPreferences(targetdirectory, filename, label=''): zf = zipfile.ZipFile(filename, 'r') dir = targetdirectory + label if not os.path.exists(dir): os.mkdir(dir) rawzippedfiles = zf.namelist() zippedfiles = [] targets = ['preferences.dat', 'popupmenu.dat', 'shortcuts.dat', 'stcshortcuts.dat', 'toolbar.dat'] for rz in rawzippedfiles: if rz in targets: zippedfiles.append(rz) for zippedfile in zippedfiles: l = len(zippedfile) if (zippedfile[l-1] == '/') or (zippedfile[l-1] == '\\'): CreateDirectories(dir, zippedfile) else: CreateDirectories(dir, zippedfile) data = zf.read(zippedfile) f = file(dir + '/' + zippedfile, 'wb') f.write(data) f.close() zf.close() drpython-3.11.1/documentation/0000755000175000017500000000000011246265352017131 5ustar dktrkranzdktrkranzdrpython-3.11.1/documentation/montypythonMOLDoctorAndSupport.jpg0000644000175000017500000005120111150445515026000 0ustar dktrkranzdktrkranzÿØÿàJFIFÿþCreated with The GIMPÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀPT"ÿÄÿÄF!1AQa"2q‘¡#B±ÁRbrÑ$Sáð%34CD‚’sƒ¢²cdñÿÄÿÄ&!1A"Q2a#q‘ÿÚ ?â/¾±z5Ùn‡dh½>§ŽM^?d:4l.u‰™UŒQn9 ˜ý{U?@Є_PR #4°ÁîGëZo‚e‡Hðm½ÝìA¶k‰ON®sSŠÙFñ^½…¥³Šâ`R$ëž>oµb:ä——rË)ÞÌÄîíŠâO\kš¤·rd);c<$}‡ÔòOÔŠÎIë÷=èÎu¡U‹Ï”ääÙŠúô¦Cq’jm¨C§Ë‘ñoǦ* tØö¹½D`ÛweñÔûQ[›‚o<”Ct[æ¡óÉiûØþea¸¤{Q´–+èÄëÊäóÕ—ëéRm Ô™?N¼6î§{àtÃVƒáÝen"Kw'mÇš iú%ÍÅÄð81GÞfW?Ÿuð¾%µ²I(„1råPÆCÐЄ¾Úÿ; ßÝÅuiuĬ§aΗaRg‚i|± ¿J¯Ý^Cy‘Ù±k[fXÒB1¼Ÿ˜ÿJ/%‚1¢³ªD±¼3…ü»…E8ÎJ)«)6¨u|­ aŒ{úÕ¢„ž;q\øGÍŸµwp“´žõ&T•’Dç°§´€¢Ø„·vÃ;ˆSÔÍÿƤ¬V1”’ï¿ï‰ ùŠ——ž~#€;š?£éd÷I …¹žÔ¼Ðj†4 NÔ +¡éŠ€€JÀK~{Ö©øcMÕ^9¦²…Î>lml}A©Z‡ôË-¯ ²–Ç Fh¹Î0:qÐS,|•ØŽtÌoZѼ=mu5¼ŸÚV’/I`a2ƒî½Qõ W½†»³º¶Ôí—–{s¶TöhÈÏë[]ýÞ“i#Þ!!<árÕ™x¤Ãø¶¹²bàîŒcqSriñeIYOPŽ A}ªM½Ñ_Ýz]šH§9ÈY}TcwÖ ùÈI9!Ç£m=ÖfÓÄëy8|#cÛ‘üéŸÚ͸}'O¸RD°JåO¢•9ýBþUQð^¿âKy.$Ûo10ÈsБÁ>€¸þÑ.£˜Áj¬­»¾:çq\~ŠÕÓZ&ÿ  …нӭî9Ë ¼Šªeu W9åHýk¾ ¸èoÁh.9ô©>%U[{I‚Œ¬¥síPØÛ(#<çÌȲ¥w bœ!Œ îp¤ŠªZ2¥¨éïjÅÓ>Y9!÷âŽéšf`,ZÙˆÉnõöcI,Ó%ìss¦ÝHÚ†ž'sÃFòH,ЫŸè2E3^Íæ;£hÔãŽ9úQ­ONð¤žeضI3ÜÊû¿$$þthZ`+ hÑÅÃÅ‚}òFOÜÔÞ /aæºD¿‰obµ$5–dˆÙ¶™ # ì0zÕb·m«„‰GQ×ëš©kWZ”æk¹ŽïLàÊ¡þ5Œ{Pà{Sûfº%ßÜ‹‹‚äQ´}}jgÇ H¦än85t„ìU¸OñtÆM¶…®na·„n–VÚ£Þ„Ææ68êEðî¥ý¯ÙݼbUI(}×þ¥ §CEÑ`Õtó¥È°FÊåP sÏzkNÕ#³—!~/zoψ^{ËH–)RR²Û#e¿Ì9àT3¤Çq{wݸá°r3õíRŒ©l 6Ëâ}B÷VDFê¾¹ÉÅh³Ü$;w6Ú£xG×–n’Ü$kàÀ£ƒœÖŠx¶+‡…êѾT¯~*œ¥ÃB´œ>*»Þ¼"Ö6ßГU›µC o%UXa†ìñ]¿¼¹Ô]K¸vÇlj%¸‘$o3w”Xcïô¤ëKð ¬iÏe¶xÆ"ñÏCA§r®¬z5wÖž+í"âæ;e¶X|³…êÛŽÜâ©7òˆ§4èFô%ÎðïÂGëFôk—Þœ¶ÁŽI$¯Ûõ Šp™©d¦=bÙ³ð;oÎ1K?¢*5hÊãeØ=²(îµlfÑæãâ@$~u–ëo¯3°U}A¾'8(©wšîœˆé¤ÀeZ\ü*î€örù¶àÒ¤€Æhf›4lìˆÀ¡9È¢`€NT‘O\cÜöN+¡€<>”“‚Ù‹®ƒ4¥œýk‡Ž‡íQoï ¥žrGmªÃµNM$þõ=KË?„¶«ñ¸8çÒ†ÁnÌê»YÚFTdîo§\ÑÓa3gq%Ðu±Lǰæµ øVÛGµŽæX•ï˜d¾>Lö¹%'+¢p+z'€ItºÕØAÿÈV÷ù˜tû~•y°Òt8ÁÙÁwp¹sõc’~æ§Gj3¹ÉcïRj8~TqcÊ÷¢2û7 ¨¦&Ó-gB9ö©›Ep=k¥ãM}ŠMtÊ…Ïí¥6…=±ÿ:õ[L˜8"½\ßÒ¿6B¡¨Ü,瘘B¬FW,ä’yÍlÙÿ±/º’b<Ö8x=«ÓÊ$žÎnÍz’:Òñßµs‚Î(¥¨Ûžk¡@Õ^§ëŠV€,ž;u¨n¥ã9ÿ6*Vœ?2Ádv8 £'òJ÷Ãz¬3|]܃øb?éK쪋{þôrN}N3±§#»ò¾hÃ1=sÿ*•«º4MA¶õÄE±ùsB®œÛÌb¹‚h$é¶x™ëJÕŠíf½  5¦vn¯ÐR6g‘ 5ïá¦Q [’ß3iQà“ù×eŸ\TÓe-½µ¥ÃÄnÃù-냎ßzu@ØÙVUä÷ã¥Gs¸ã¥½Œ&’OÉɘ9/ôôÅWƒ!$.py(´k£ ã:“"DáÁÈúÒP¹ûUÖyífÛLÑʽœU÷Kñƒ®B- ó½G›ösoâ6—ž{·ô­Š}9ubiƒ+ 63ß)ZU„(•‡k~@⊓Ҍ"¥ÛSièÏ|Cá­FiìW9;&uo¶8ªuÞ«¯YC%½ô¯snç]ê ó##ó­¢öúÞÑ} PGJ¦kº®›vÞ^ÖaÓ” RM(iËú2Dz·¸í×ðÏÔÆ9FúzT, õA«&£e ¦gƒ{@Ý}¹h¤ˆ•$H¤î+r¶ ذ'g·µÑmîõ!90ÀÅן”zP°û‰äóÇJ½xÁgŠk‡ÉÂ=?ÎŒŸf„[‘'PÒ„úL±ª`„ãò5žü·e ä+v¸³‰­íçb—¬‰<ìÄ*‰É>ô!>C䇱„øH©R¢ùˆëÞ£Û‰n¦Xà…ˆêÇhsV / jª@¼Ò‘‡U{[ï€jI¾ŠØR:dß4ê—SÀëéÔÑ©¼1ªÃ)H›Nº¯•t8üÀ¨·:N­mnfŸI»/Y#O11I Ó]Zê/iŸ/11à•î>¸ÈûbîàLÅäbz?èj.í˸túc†ä ÖQg2ªAÛ¸Š•$¦WÜcö^”ÖzR‡Ž”ÏB‰*AõÜàqÅx¶}i#­ÎNMqÀØéŠï9©væîöÖÝo6UO‡œäŠ+³$kúdM—iÞV_qÆh|%q®Cöœ¯Tm• óW¶=*ÔRvämô§ò>žüU¸ª)F}¤~˃"O®]ƒÿõ`þE½*gˆt´fŠóN„Çl@FPsƒÒ®êxQ×’I¦îíá½·{i†b~ ô÷¤ãFâQ!e‘9ȧqƒíPî-åе&´—q;¢r>aSƒ®AÕ­‰gdlGúU~ÚE[¶ ?ŒÕ…¾CœgµTï·A¨ÉÎ3ñRËâµw ôâ ê– ªØËfãæB{é–ÇlÊ7¾ç¥.É|aGëH¹·’Öym¤R¯`Ó¶… ‚á‚+žQ2Ð{Be’óÌdÌp ç=Ïý <·S^^;‰PN «iw6ð»þ êã·¿ÚGÈCä.Ö•Föçó®iJ˜ÊÞÂ6ÚÜÉrˆ\¤c†ääV“¤ßÅd’Är sëY0µ¹†5W#sq“z¿ø%gMC½*«k¥\« yÜ7˜wä³ÿËÞŠm7fíhæ“΂RÄàœÕ6úo}, ÅsíÖ®ZåÊèÈÚ|soÔføeœˆ#àûâ©—× %Ó¶0¹àÒãvÌÕ"$\¹µ«ø%O A&9’i?þ••@0å±î+a𢂪^-ð¿ïWRie=]¡•ê¼P-wö„×% °£‹‘–3ûò:UÕ¯´¿ðNèÐf×,à•£gË/\W«—V-#3d“×#þUêß'•úŠ|PöÍ9Tð§‘^8 ÓÓÞ‘¼|Êxu7¨® œó‘šö,Œ»+¾,Ðþ}j›§A‰ŒT_É”¹R®;ŠÙ9?j¦øŸÃ «ßØÅ–êñÿåŠI&+²¬²ˆäÜß`Žnr?*³ÙÞϧ%ÇödrjúIR#8–õǽSÃ4gk„õõ©6—²ØÎ³[LÉ"úöï\Ó…”Œ«³BÒüKáëÉãS©ÞBÙÚÐ\Æw.;o^ƒëWÝ&úÆu)i©ÇtOÅ…œHØüɬ¾ËÆZUäk‰4HîYOÃsjÍÓŽ ÑuÙíèšÏJ’Öel’[3~X&’¸ý¬Òv\5èÚ[É þ¤‘²üñ¢oÈf©¯âOZ‘áð®‘-¬Ÿ;Rº\mŽ $~¹ã¥JÕº¾QXIÃà±ÁäfŒéÚ‘}º]åÀçu¤Žä*‚9éœö®xÜ{+7tH½Õ®``©tìqñav“Ï ¢žÖç3—œ±]ÝØš©xVúGVÄL‡< öÀïNèºmõ¥ðZJ€ 4Eüª—{LÖ™©~*&EŸ6¡¬ËR=vâëåå€tãô«}Ey7k$²ÄÞZ”Á8œã<µ—êWW7ãÆFÇÊ7çú þtÒrulHRZ ZËšUpF7tª¿ˆ ò'GÇ‘œzQËKiî."P\Éÿ AcSP¼[sµ³†)–RŽå±Ð{f–R¹)û)óç£cæ×ri]í],AÀÕP¬îk¤ óòŽ´•9É'ëš°x[î܉fV‹O²ïŽdöé[ øææqªÞËh¿î#c힦´pÜwéšnc…PG |Š=1KGLÕâ¨t¨ñú¾µÂ6w5ÆÁ9éIcï€G>ÔØNà’0 'Ú jZÅŽ’Œnd&AòÃ%åÒ«~%ñl±9Ó´R ~òá¹ÛYåÕË£°7Ò\Hç.UŽséXçÉ›Žƒºÿ‹5 ^w"coôŽ3Œz­^}¹?üiX±éHnaR[+ŸÞN?*äO#Þ­»4¯³™É˲Lþ'º¸¶LË'}ì€ãéDôÍxåUŸµkKiÉèv­6útŠ›¡uvÏ4®/²‘È¢h 4W±lúЫß—ËÛ°Ï\P[ûˆ8'E²×ãp˜ S§ì²È¤žÖê‰"eõ\œÓ"L7ÄpPGúÕþ+«{„#wÅ,ZZ>’œóòƒ[Šc&ÊN™Â‘Ÿ@j\^_Z³{ºñùš¼Ei|¬1þØÍ:C•p>€QXwc[+1xZgŒo‚?u œWªÐ‘œŠõ?Ç[ ø_þÑÓÍŒìêßäÈêµm‘ÂöϹ¬iÿáO«á•¡rx•'?z×,oâÔ,îÝŽ\½ûŠu¦-’ó»5ïˆñíÿ\WÆ3×¶k¹\ñœŽ´á+:ç„འud«ÈhØü/ÿ: Om-´æ ã)(8ØÜVÀOÅÆA'®*&¡¤Ùêñ컄:HŸ04£(.ËÁ|{bœŽæT<*ý@éGu_ êV¥·‰®í¿¿˨÷^mÊÄlÚ{†\›‡è6H’îIîÀÇqÛíLç#âcö¤dž+§A*2=‚^GJçQß5ìצ ÜñÏZæA\^=kÙã Ì.9àŽ‡“Ò‹X_@Ñ‹E˜[3$^LgÔwü¨)^ø¯ N?èÒJ6‚]ö 4ÿØÈ¶¼®ÓqhÅT.73žØ¨o‹t}Ðë—Vh¸V¶»ˆá~ø8üꃠx“QЧXÌ¥OÏ ƒ(@SW»OÚ&ý_DD•F¨‹(?ü€"¡ñ±¬5w¯ÙÞÛƒÄZbDrFJ¶~ ý=ZþÒh–.­ø©›–Ê×.sè@¡·úÿ€‹™G…³v&Ñ¿5¿hBÜÑô 9q·x_‹ÿÄÖ•â¿fRH‘©^^Çfå`]Mb~-¤]\Lž€ÿZ£\Ü,óoUŠ0¨:ãÔûÓú–¥u©Ìg¾¹’i;yœ}(h;—ã¿<Õ!‹ˆ%4ú82ÌÇø®¶:1éÍMÓ´»ýf*ÆÑ¤ìd#¾å_´Øi¬³^8¼½…#!úw>õÑ ¶W¼3àÙµR—Z’˜,ÈCÃKÿ/zÓa…-£XaŒG UÀ¯xî>•ÃÙáÖ¬¾¥TGºû׉ÛƒL–Àè1ï^Vç$šÌû€<ãíCuíHiz-Íß]«€RO0ÙÅVüo“ Å 7Ç,»}±JNN“³<ó$ŸÌvrsóœb£7â[0ÀÂE';!_‹æ‰Ùi3ë—bÊß)e3JVôÍ^ì´›}&ÐÅkÝüRø×5 ™”t…ÁἿfdï¦LgÙ&œç#øäÜ;ý™snm›®8Áþµ¢ÜÙÈ­»á-œôý)û²Ë€zÔÖvöu? =ĸXÏ›Æ Á,˜56Ž)7Ã#+ï.A­A¡W\Kn= ç5UÖ6ÙP‡ÄQÆû'ßwYçDâÖíd0üêáp–÷`%ͼ§¤±©þ” xzà’táïä1ô)¢ö þÓ„ÿlשÃàm? —È;(“§é^­lÖ?âÏ .»hßá¼AðãøÅQ4j>Ž÷K–Ö-Ò„Lh˜“Åk¸øGƒÁŠfòÎÏQB—Ö6÷@² ?¾`›ÚÌ9I?Ê—ÇW*§þѱCމ ÿaVà¿ 6ì(OÅÑ]‡õ¥¯ƒü0€Ðm6ÿ-üÍ'™J¸ñíÒ®?¶vÏîíÐåC®|u}6Jk7ßhÊ´á håèšjãû…©ÙXÄ@‹M³ŒvÙé[ˆhÆÅÚ´ðj—äzbåQ¿ªO/˜-o'fïå1'ô­Ûz§bAþAþµãs Æ$8úY«5½¬:¬¼cjúù åOÏkwkƒqi<@÷’"¿ÌV©$嘂í×±é^B힪E2qüë˜íš»jÞKÙ<í>émg',Ž CùsCm¼ªOã5+(ãõ‰Y‰üéi‹²µ³&¸Ã [eð<£?‡Õ"n?ó#+ÿ_•Foê¨Ë‹'ÿî‘ý(Óf+y$+ dp*ÁþÅk9àZÿ×ÿ•u|­0ÿÑs1þ‚·m•å¬G¦–&•DÌp‹üêÈžÔœâ[Ë4=È.ßÐTȼ¼õsŽ›a‡?©480Ó*>l’)b3þ") &æÚ™sÓ¹Íh–Þ Ñ!Çš—/ë$„~‚ŽZ[YÙ¨¶°BÃ9?\ÐPv2‰›ØøWYÔhí üÙØ ûõiÓ¼ ¦[8“P™¯PæjÊd%rÝ3^ÜJáˆ8è=)ÔPGc1ÁŠH¢Q…D8¯=4§Œ~ÕÒH “Å7CØø~psŸ¥'sM+ük¬pܽk¿áÁæ¹–ãÀ¤1È知x…ÀÇÞ‹fB·‚àòì*§ãÛ€šu´iŸ6GmžÜU©rÝ7UwÆ»í¬¥ÆæV`3ïS”´i+¤'Bò´_ Û#¨i¦IXžœÐëï]—Ú°ãqEµï †(l£Ì‚ 2ݳëôÔ Ü†âPÌ}k†[gj¸E$X޹;(.¤ nM}“©ÏµMдã&†&½ÁgmÉÇ%j·­ÀöדO@ioe%É+ Zø’'m¯{äæ‹­Äs'™Ú¨·wPH?Ý÷þGì.ÔÌ esÃFÉFMö‡µû[ËxâT¸^UÐ`“ïT¥ÊŒ²²¯™«îª?Ýã¨ëTK˜Ê\«¨ø3ƒUÃ'g/• Vˆw’T¸Œ„`ƒ[„˜Iám=×§•‚=óYò¬vÆMØ ÀcÔÖ·àëk‹_ Ù­Òís’¼ãƒí]iœX‘a# ûšF8 zW<äâ•GÕ€¤ÉunŸ5Äxÿ05¤ö^ÅÀæ½QMõ–ñQרÚ5“Ç=kÙô=ñúTÈôñÉwüºæ£kI ®‹;D¥]ˆ]ÄóŸZ§E)û"É<1rÒF8äçõkh·móÓgJ¯ˆÔg‚Iïšî[§Qž¹¤r[ÿ‡樯©\Id ŸîŒb¡}é%ˆ<ö¥¶ÃC#¹ËJǦ‹i÷>rÎ ”ŸΗ ïo2ȤñØVLÕ Ë`¹çÑðžOjH“ÌÛ*ÿæºy#éöO¡aŽ@äq]Üuì)Ä{c5ìîéŠ5ú,}ÿ:è;yŸjâ¡?ÃKç$ô´: 6p’IÇàÚk© ñ1jX)ázP°¨‰ØXdÅ-"f# éFPHpFMC¾¾òmObxƒ˜ÜPÕ’–Ì ©Á,+‹¯>’otâ„–;ŽNsÖ½9À4œ˜ kvð•xÉ뻞jR]@àyr¡ã³UXc×’0Iäç¾h¦bâ¹<ã#cšSg#‚ª1Ï48Û,©é‡8¢úmôÓ3Å<†F*Ýè§lÜB»ÎáÆ)D‡ïÈëMÈü«½sŠz¼€xçŠé'Sgåâ‡kšÈÒl÷…-+p¾Ô²i)»Ë‚¨þóPÝVÜ]ÙÛ\ÆàÄ—(Ï$Vu}â{Û’Ây‰^ØãkðF¨š®‘«é“IºX W1ýçõÅNÔƒÑrÔmRkc’ÉPƒ@ÓæÔ6™s“œg'ëEüI«˜¬¼¨;·$wªî•k}’þIDlGüv®9-èôÕU‡/&G,±'À  ´7 µÀÝž½ètúµìwGlÊwA#ŠràÞIh'”¯˜?¸)æž„ÛèÄJ6ÊÄz-˜ˆáöe‡ëPtËüœ?$zõ£"çp˜ÛÐÑ*ë ÇbIÈÅSÅ´·’ ‰¤fuÍ_ob[Äh+Œò3IÓ,¡ÓôÖa"Å{z–@9Tý³UÃò9ó._R§aá‹Ù.!72EÉ ŽMZE¼Ëó0`Øý)*ÎIì$73HãÌøXÈry©CKƒqÈr}Ø×D_%g$±ün†Í·9iý^‘ä[ƒ––?¡Á©CO¶ÿƒÇ©$ÒÖÊÙFKôÁ¦àÑ™e—i—êŸø;oø ^¥ûз¿Þ„ø¢o/MHòù1ù Ñ nímk‹˜b<ŠAœU_ÄZŭþqVf;T‘ϽUÊË· C×Ö’[Œô§ ±yyyá…OrÙ52="Ôe½Fç 4(‚˨!š›¥ÊVùvž`Ð8µ¤\œÿwšŸ`ò5Ü,°ÍÜ’„w•Ù¹ìã 5ÑŽã½0Õ'Ͻ-OõªÑ†oïÊÑç`pœx‹WšòEF$ž h÷Q%ÄNŽ £‡Ö©ºvŠ·úÔÆtsmÉ#£ÿ¥så´< äè¥Å¦_Ü0FþY<u«—ìê7ÓuÛ¸î@ sjbÜ}wdU¦î;y#X"AF1´ P‡³²¸Vi2k™d}‚¶M×eü-„.ªÌæfŸN”Ä×:½æ“§N‹h\e¦QšŸû»§‹åe^p8æš¼ó§·hƒmQÓš±‘O/:\`iãv…ªy¼»‚ÞY̪GpH4ÓYL²Ïpjd3˜nYÎ *Y\y·k*.Ñœ2Ñ{iˆi?sÍ GXo @<àT˜$b㙜ð(¨Ù'*ö¸U;Š(Ý&;/¾*[ÛGu¨Ãz³’ÀD^ˆ£Æhe²JoYãðê£$œÞÜQ»ym^2‰2»÷;YqWøeJ„YØâÄ#MˆÐx¯`çâ\­=±@äÓm$q ÈØ_STJ•“äì@EÁ<ýë¾_|f›kËm¬ÞzlI5_¿ñL¬rŒtô£ÊŒ²loLWªŒ|Ov§ tTv+Ô9 ¶¶>a’gy]»±£01 „PBí8éíS!9 dcÚˆI¶ƒñwèk äÿ\Ó`õæ¸dÛØ½tbFò¿®kÆE òŸzŒf O9¦šMÙ¶•™‰f~HíŽ)§—=OéQ|ÁŒç?zm¦ÇÒ‹f’r$ãØÔ¦sŸ‰¿:ãÎ 4Ë>G–ÌšÕK1ä·9'5E1|n8ñSÛ–9¥.RøP[1a¿ZŽÅK`;ÑÃò2>Ô&æ!ø’ dÿt “FFŠLA2ÿ*zM*áFP#cÍMÓ¼5ª_x¡1&~iNßÐÕ¶ÃÃÁ·&âLä íF1°Q7Ÿ˜¸±—bôbx©¶«$ë˜ìær~_€µiñi¶0ò°&Æ¡ªJ6ÄÚ(ÿùSp‰žÛè:Í×1Øy0¿ÊˆÅàÛöø§»‚Üc2æ®- D˹ªî¥¯cLG=©dè<Ù]*&ÿz¿žn9ÿ*›m¤øv,h$=Œì[šüŽùÎx§Žµl@FoŒušš•‡gŠ+H€0AýÄy]¤ç¸9¡ZuÂN¬ÁשÌ@À' բњ¡Ì“ØW7O8¦ûƒŠîì Q±G7+»Ÿ\URæëPµüBéѤQ,¥Þg=}ªÊ¤;ÕVÑîuxã¸òàÉ%G5 ÝÁ|„.¥,º›=Ègc‚Gs@-l ½×'-+3duÇJàZY„·üHø@õ4_Âö1\ܼª v!#ÚÙç¿JO”ÑÓšMD)gd#¥Fѳ³ü>¸ ú¾¢Š]a#'ÑO?J²êÜØ]oŽd‹ †ö5]Öt›mAÍŲ~ÜüQñŒ×~oÉ\N8fk²±é2þñ¸ÍOÃÈŸ ãš {¥]Ùî&2ÊU¤éñ\\J#ÜU;ç­pün†–d{XÙ°ŒYϧj3c¥›h™ÕKÎË€{-=¥éb$ n(O.Ã<ûQôÓonád… iŒo“ šô|Cr9å‘Ë $0Dñ”|œðY\ç5Û{8ô×–axë߈HÀ€*uƘú9"Y£.ìäŠÎ¼UâGºoÂ@ÀBÄAç4¹þ¯B¦ÕüoäJÉd(8ߎµZ»ñV¡~vM(ÁèUziWÌÃ;y55na·ƒ|A‡SÚ¹Za±RÞ]±¤uC隇5Ä€ñ.G½5qzìÝPG~¦²˜™øùã$ûת>•ê< } þÎXÿ Ì>Kµ>eçÔ¥OÖ»ç rÒ©Cχ­AɸŸ¦@¤·†­ÿU8ÿÚ(mÇ# õ®‰=†+QÂÖÙâò\{¨®7†aòPqŽTboñìp¶íŸZÕF FßúÆû(¤·„¢ y&qÐ(ÍNÖuÛm&5óX<ò¥RµêS+y ¶àž6Ži\‘ƒÍáH³‡½•~ R„íûj¢Š¡Ë«ê2¸2ÜJìzóЦë7p62åsÈ'4ªH¹¼ãþИ}#½þÌGlw-ãÉþ@)í'\Kçòc¥Ÿå♪¼ Œè#¥X4»+8`YÖ3?%ØPycÄÍž›ªÁcµlâ¶Ñ¤b^öÉÉŽÀê¸àçô¦ÉÏ Ž=«„œätëGþŒ=¿ƒ]/•¦yæ£ÝÞ KWöéïK+A½µíLG•G\ϯ/™¦nIçÖ§jšƒO1Ë·5_Üdœ-r¶äÊ.‚2BD"V•ÀnÁ©IåÄÅTž§­9øÈЧ_Ý×ÐÐóu´ŸºmÈzƒMb†`Õn­™^'b;€y£ö~*‘ãY·ÌªOãíÏ>g–ÝóJþ׎ðLý(;ôÿ³U·Õb¹ ¹$c57üßjÍt­~1 A,qÈÍ›Çú^šÛO6>pŸûf«ý‚\QrÉÇÔS-¸“ÐŇaTãûL¶'áÑæ:†‘ÈÏÚ ÏûDŽIÁke=ä}¨N`ÇäG jú}œ3a底ÆH4[¾&±ÒJG%º2©;\7z­VÊm¯°óŸ©` &)Qe>]¼yS–!óÅWÆÁ4ôÆËåÂZFªºý…À*Îц;Žáþ´Íä¶1)h9HéU­t¿†eØ»ã䆥5tÐ ÁäÉŽäí®¹y /‹E¸ZDÛ“cs0FšEByÇJŒ§H¶“AqpëÆp1Qr¿‘¤ uÇ5%/§—÷v(„SYOvB]l7§êÿ…Ùˆ †0rC¯&‰'‹"’esu9$/óª²ÙF?{©_Æ$<ùjÄgò¦n¦¶XöÙØÛÉ“œš3¨+cB—òHñ‰ç¸Ò¤X¢qÀe\ñõ5‹ÜÜœ¨9ç,:Ö¶ÐÛÃe'âó™WàAÉÍTg¶Ó…É0éË&Çç <ûW;ŸË°äÿl¢²ÈÌÜóÔb–û„mž=ªÛªxj9ãü]„j¤üñ.>‚ª—1˜œÆrpF1IM ŠdRs^g­)£ f‘Ó­2 ÈëԜ޽Xc>!ÒÐá.iCĺNÓºìýã5‘HY]¤ÿ7ÌsƒM‚ʼn19ÎFqœRó`5óâ}¯þ%›‘“κ¾*щø¯þƒÿ¥f1»Ë5…¢aRQ‚UFz‘éíG_FŒ&EÌÙô*¤~¢¶Ì\Ú?ø©N;X: ©xÛ É§"”çd&«76¢Ð2;†ç”QÊ ¶”ªóëÚ—a$Ëq<»æžGgn~.ßJ q<¯'ÓµJºúàP§‘òNsÍ 5Ù8J噂{Sö2m8Ç\ж”²zDRÇ'ßʂAŠ.6—Ÿ„½Šu“i Îzb®_Ó^%Ý{±‚جÐ]´Ðàà7½z1@pÃ¥5ÐZ/Þ|—x¤WRx äQÛ.-Óš èÛ#†@J&LàUêÄæÊ=§¯|uª'hàFÒkÊ}E7ž žµ SžK{`èp¡†óŽ@¬ÝöMYWÌ 6Op;P^ÿ»íA)0jéo<óç[¶Aèj·¬kÎòT¢“œy©NV†@«‘+ÈX㙨Pnk ªy'5ââ!LF8,z#q¥ÙZYÇ*130ÉÁéQE`MB7¶¶O¾(S)cÞ¬PÚÜ]þéNÿ@}(mý‹Û±@Çše@iƒ³È\\•~¦r=«¥àžØëV]7Ã1˜çVRÉÕ-àŸó´adg>déòÞË4Â`°B¿Ïκ*Ú“ÚZÚ§™¦[K*ò ¶ýOzC\•8"ŽÞá%éõõ¦·eŠÇךºÄ‘Å?%· v§$ºÜâ[ØøP‰°(¨ãK¶lf(ý7fˆ°R~Pê¦ü˜É#¦{ÑâMäc‚ÊڌǦdWˆ´ß¶sš÷•Œ3 tÍGœ\¢~êLû*â*¶ÓµitÉ §YpÃ֊ͪÛ_Æ]#ûñTæ–鸓íLÉ$м§~Ù®|˜ù»³»“(.,°½ü±Hv¾G¦k¿Ú÷;€P÷r*§ø¤î öÍ)nâõqö4ª^Æ–x·ÑvMV=¹¹¸LŽÊ þµ×ñE¸;ŸŒf©«wnÆe?D4úNŽß¹´•ϸ£ð¹n@ÿ%Çù ]ë—z”ÂAº5Ûµ@9Àõ¡“iKxæk›™`õ§nÎEŽ!éÞ¤)Êî0; ¬aG$òÊNÙÓFK[Ÿ>ÎöhÜtÃd®h•Þ™oª"›¨ÊÜŽ<ø8ÏÔRSf:ŠudØ%ǵQFÉr•ØãÃÞ@8/´tfèhÝŒ°±,¹_P*ýæÕÃíu<ËšT–Zf¡ÇýÉï‘€MFXæ¶uâòSU#3ÙŽ1^«eß„oVå„ ¾>ªG5ê[eùÃôŠgr^ dÙœà+±ÝËf$! --§Û2yÄß!^ÞœPaÀar0R³CG¡¹nZÕ¬gˆá•r2}ÏúÓßíF ØÓ¡¨¦òCWHܨà”õ¤yè\GäCŸð¯4´ÌO:•ÅÚd`p1ÅsñQÈ ³`Ðû›•EUQ׊ô@4JÝ ©»[*Ç%MÊ~,ý*/áÎjצiÑ<_¼@I§-…²gúPù ¬%ki¢_i¨Ýâl•®·:zKœ§¨5Άä¨H¦S°¹z²$[GÓ…ªG¡I}Eq—r~Uº‚:ײ1š¨ ^ÉüŽ\zÖm¯AEÄ6ö–·mV\žX+qš¬1mùlãÓ4OQ¹t% 20ù³×4 ÈŒOœ޵'°Ý Û.¥qk¹5‡Ó¯5rÖ´¸#c¼$ºž0*£û9.5‰£,ÀªnÀàÖƒ«››_ÞF±ÊçÇ#Œt¨JîŽì0Œ¡`|9qbEÌò/œFDhrGÖ«—ðÉæ9‘rK‚9«Ýïˆ]lÞOÀ-¹ /ÃÉl{‘U9ïÐ,×#’2GnT'£YKÓ–73€X|ªz Ÿu9XVMÅŽpsP`¹‘¬š]ÌX¿Å]¹™&´b¤åO&½8¤–žË9JG¼òNp1IyW㚌ŒI¥·Œfˆ´+ztçò¯|æš#Ž•Ø÷gâÕÏ ã§7cÒ’Ì{P2aoSš‡$jÇ©n ˟­ C) ~CúW¿2ô§7Xa¸fµ#6Ĭa{)ÿØ ;“Ð`@1^¯sÚµÎÉùE8Ð r%ßœÒX•=x­T#bJ¨çº®GEý)9=H® SY»30öÔŸÄ9ùIÅ4¹'ž•Ù ZìÔH²ƒ+þuêe|°£=kÕ¨4D jÄ… ä± ×šTŠ=‚Ú_rM[ï¼' –+©gÑü¨Eí‹Ú²¢Kädåk–M&z°‹h­hë“n™Ïl×fŠ(âÜ‘…=±R–Y‘ˆ Iôþ”ÅÔ›ÇÇŒçÒ‘È*-vff¹Áoph…¾ÙrÁ@5X‚ÈX°¨nYÜÃï'W«Wö.™£+¬VªÃ`Š&®é.ФŽçîœ/"°Ay‰ÇñqŠL±C&Kqô5©m6´I†è͘GÚ†\ê23•XetÏ^€Q˜`ðÀ("¢­¬Jù#ާ4obñ~ȸþÏ/"mÀÏZ­Io™x9î ñÐ * ¡vŒ<ÐÄ/½:dfÑÂÇ278# Z%¡Å²0¾õAÓ—Ì‘‡â®–Ñ\#¦Â;õ«BÉ0’œšã:Ã9÷ô¤ªíŒÜ÷&¼ @8ª4dgþ+&K¦l.Õà2Žj•*?\mç¦y«‡ˆ¦/¬ÍÂù,G0ªíÒÆ„lŽ9¨¾ÂX¿fÚŒpx•a硌}{V“¨Ér\2Us—'ׇZË%­ôsDû$Gʰ­¿NÕ-um0Hø d Åså‹[;||𢳩j:×â63ÛJáBž@Öå)b Àgå±Eõ(íaf‘F(sÝMVüAv“Ȱ®rª ÷âº|h}làó³;â7c2~”·$çššÅ?0F7qŽôÞb‘ºg‚:Q]=üý1³ËÆMuÅèó&ŽdgŒ×]—Ö’í·×5Ç$ޏ¢ â6@Ç4æïQùThŽOJwê1÷¬aÌÒšö)9È;V Ò2¥#nI¥? zûSFFÅc dæT†öë0=À4– f¯êiÅp:Ó'ŒW)mšÉ[ý t¸õ>1Ö–H#9¬lçÔRI,zÓe¸àÒƒasÞ™ gXíäã“Þ’7Zöþ@¬‡ô¯S €9aù׫Í.ýU¬d¤§uéTMKHžI·‰ðŒräÖ„pWžÜÔ]3O[­cËuÄ0âFluôÉ(Û=¼T@Ó¿g#Q‚;ÍZò[H°CÛß&‚ø«Âúv˜Ëýžò…~•…iwWæs4JÄmÊ…¸íU¹4ßíÛ%INݘ±5GŽ¢i-™ì-v½qVoE¥œ—²ÚÆó;Ga€£õ¨:½Œ‘^,.¿1xù‡j=i¥…±†b‘Æ Éžk’rkCâNî‰77P\‘+«²‘ÈÇÌ}¨V¡hË&TìØ¢Ð¶ÂÄ.~ôÀïCÚ{­YÈuG’XñŸqSGC±6²»BÌ(Û¸ŒrO-&s‡ºlz-"öátØMìN07Vö,¥H­k’yº‡àA½"Ýñ·ƒÞšX¦¼¹Äq¼’9È :ÑëÞ™6ÜÁå/bq“]1ŽŽFí–o hwWVߊU‡#Ç5cŠ mÔG¾Õe°Õ–i¡ιêz½tB:3@ö#$“Ö¼p;QKÝ1¡ñvùšÙ»õ)P#¶šâ@ÆÌOz P¥GÅl²y+$H:‚Àrj‹uBB#(íWß•³’8™×s ü§ÔÕ\F¥ÜuéžõÁ’) ¸Vƒá™X[.IÁµAb]°zcš¼hÀÅl„Ž‹S’½Ç*l!ª:„;AäÕJýÊÝ$„Œ0ÅY/æO ¸è¹ªÜÈ×cdfEmãé]xâÔO?4ùd#FB¼™ô¢:UÊ%›ÂÜ;7™ƒ#ç¨äTËUÍ”ŽÜ~ 2dd‚¥y“Iœ` ð}Ñ+ŽIÌät5DHâž´êÉ–ÆÜûšŽÇœ³ƒX$òäúÒpû×™òÆ'#k …¶8úÔi†_4öÅL¹Áþ´ò|]zÒºu4ÌG’ZqŽ8¥1ã‚3ŠG–q¶›èh˜ñçÚ›2cŒÓ çµx qèkh=:­‘ÉÅ2ѕ溒pEd…°Â–ÒUŽzR䆼ì‹ìubÔG%>tEÆF8¡z…ÚéÊ- ø[høG§½¶‹$2žG|UcQ¶žJ<19çŠTƒ9hñÔ$@ÅWw¡egÖo£„±$ö¹ÎÔe$úäU§ÃXŠÐÝÈ¥qì*¸ánÎyIô/IÓ"Ñ“ÌØd‘~.y¢_YÈsh‘ž¹Ôµ‰wËÔc5HÖÁO>õÓNÅÿh£\Æâ-¬8>âœóvÈ áA9À¨F »‰¢¶ÂêõPƒµFN*©ØoI–äÆû‹ygø[h“BRÙ‡"3ÎÑÓýiÛx#6Ã`À^*bFñ¨à3ç 7COKÙZ@‹¿ éºÅ’G}oæ2®QÔa”úPÉ?ezD¥&‘rŒ*nàÕšæë^\Ãmbô;Ëö¢zi»“OG½(fcü 1lÚ0ýÂI£ë,+.QzÓ‚Ñ ²óO xî1 ÖeÌgZ¦ë2dTp3\³d¤$ Ù]—2 Sòœæ£[(ó^, ¬03]ŠèDêŒ2 5Ò :ºñ]Zèñ[]Àa™ã=Aâ· –-o‰›‘EuˆxY@ÎF3AÚ=ç4²)š'i—KlISŒÑ@¡Z\f9äP2¤gH1Ž]yÒØà-5 <Óƒ’~*ÔÃ8éIa•æºXŽ+ qA£”ª·4ã|¦£È»dÎjBÉA£ƒ:׈¯ i;ˆÎk0Î8®‚Hâ¹G½s$ (Ǹ&¸iL ¦ùÅEðx=êú´‘$@üÍRwÁ4ÔŒ¬Ê[ ¥aCñ®ÈÕ@à WªžáŽP½±^¬FýœY´óßÞÅ"P€gÇŸåVù¢øŠ)ÔT Ø +ÁöâQ²Yóq6<ð£ò¯O ¶d:’ëëï[£Ò„ZHãÆÊA<ô¥ÛÁ4·2쌜“ŽØ¤ÛÏ5ì¢8¢»“V[EŽÊ2½cyõ¥kE¡Eþq0Î0Xnâ… R\9^½¨¦£lÖz¬Ñ2“vd#‘´ò;kH…Ùr ðkÅó£±#낳À 4²{kØ®xÛ,{3èE\žÒñ7`FÇÃÕ›Ò›Ôãе˵»–åÑõ®…G<Ù“[XM©ê6ÐFØ27#ü9æ´èí1¤Ið¢£éIÓ´? i7 qm=ì’@óà~TQçÓ\*«Ê£b¨˜1›dgŸZ+oc×"¬t§\<— :c2öÒP ßå㌚¢D5Â)ÈÃë…iŽ2N>Õ]‘I `äñŠ'c­ÛX]¥…÷û¼Œ¹R~SUŒmX"ça(Ì‘ž€æ§®Ýzž¦‚i×› é‚¬;w£ªwž7zóOÙT.bÏÆ8늗c"ËkT`Š‹!Š“Áõ¥Å¶&PÌAêíM(´þ0±7Ú¯Ï$_µdÚ£´Öˆà÷­É•.¡db$¦1Xvµᮤ· üEÃvCÈBŠÖ ‰ º0Ϙ[ŠT7T\ʛԾ)•?º»±ïše FÁ‡éLû<ÊÑ'S–9mB¢œŠ¸†9 ïFdá4ù Ÿ„àIv>2N™|§°ÿ¯Î‰ÉðÈNßj«ZÉäÞE!ì⭓΢²hmŽFFk‡§&º§pÁê)¢Jœ”I¤? PM:@1 øºRî_áO5[-ÀQ•èoV+Œ€­’A5à¹ø”G¥+nÆ¢eÆ3Åw~¼u¦ÁÚ;Òå?»v£f¡Ö'– 9miqr µ‰¤’L(÷¦£!Ðg“éE¼3qømqNÓ¹¢B{þ´­Ò³A'.Æu-ÿH™c¿„#7ÊC(y\¿¥].`}jÑâߺæ‰7 –•L‘9Yv•8#ÐІNE³àøú8ÙÅ4ìE:HÝŒóM6ERÎdt1•wÀÚÅ!ÇÒ¹•cAÁ5Ízƒ9Uæ€ÜBÑÆ‹ŒtêæêõahÝ'» jŒ`(6ãŠLqËå;…= ô›¶¶Òí&¸"I¤Œyk׎™5/ñWÆcUî{þµGHõ`Õ!ñGiË“–aü…¹ÕæmˆÌ¨#R¼7•~éz‘Þ Û`Ì8#×¥NLté„îíÒòÄ'jQ³Óýhv“4É8²uñ#TÓ2ƒ‚ß—½{V¾L°óQÞJ„Gþx& Ò»)Ë@msS‡Ï{HømÎçç÷ûP¹çl¦šÜ¡UGÅùõ>´Ÿ4gåçÚƒd¶I[“œäÓ«tÁþµMb~”ôj¬7)È ¥aàÂ0Ü;œTÇ“áºÓVöƒ žEvwzUR5…L·Q¡Ï'LéÊ¥°W¥,JO¡ÐQI”w¯+úŸÎºrx4í‘=nrÜ×e9vúR"ø\}k“¾ÒHïA°ÅºŠv Â@CM)ÁÉïR#_›žÆ‚…Ê€04©íÆI¯­·,Hö§¿ <ˆ¤[ÌÊsüšÍª ‹n‘&ÛÀúæ¤C9¶™&Cñ!ߓ߫GÒ¯ìm4{[Yô¨ dI7®œ(¨ãœÔ Ï iú¨’} ùS –·cÁ>Æ£òG£©x“IH‹ovH®¡U ý×=j/ˆ´©ÜjvÈZ'?¿Uä©õ¢ÚN‡¨Ã —»…,›@ëÏçSP˦Ú\yÁJ¼L¥XpF?Edã*£ªps†ÌÈü?SÍ!ŸÚ¸Èåz$cÒ \Ê"Œœö®ËÑäJ5*"ßJðÝ+OZ–<±èjï>p£G&‰ÆíKe$©<üq^¨fNkÕ¹’£k°’W±3Î꼊…1Ú£Ox\~íÎÏj`ɾݓyÂŽ¨†L)Pp=(¶ÏJ.‘*9ƒrNzv)D%Øò1BÆÚw¨²ÄÁO"–Ãa8µxÅêÉ3-9ǽ3ªÌnäù— uÀö ³JK7z-³ü”0@8ÇjG°Ø&{¡Y¹Æ)³$®™M¯íéF¯’Þèa­UXÿ òÙy˜÷9â£$ÑH´1ýݳ’",½¢úf¡™^HÙ}ˆ¨0yã˜äFîTõ©©xTæX2;*|š*ƒÓj2|8Á¨/pIàŒPÉn”r®Az±\F$ãsƒV†_BM2Ç¥¹ 휕,œ“Ï4Õ´I/}jP ÜcœWBèh“¦þ9‘¬K³ø˜œPëíBÿñn’Y‰£íѳRf‚ÜÚº6¤öŽr>SíUIKÕ¤ö(µÁ’7#²ãÝ¥Ô®„6ð=¹a™¾{’ikPÒ­'–Kõ‰0ÒÍ;m'ØQ.uß7JN´i9-,­Ã9ôúUzâ9$„,NWª°‹Š9²O—°¬z–é imkÛ‚b„nüÎhmæ^'Rr„sÍG°·–Ùä–l…õ&¢_jØo&³1ì+¯­nes9þîêÊA_sÚ µ½³9ÅÈ 9ÍJ;ɸ½˜í=1õ®%¢¼˜DøGLôôKH…qmŒÃ>÷î¨2#©­Y¿&éŽ}6Ô›=6ßa‘âø{n5¸™M"ž¶ÓÝN‰LÄžHíVX"ñ‹}€³žjL÷‰hàˆ(Àæ¹ò!ÜçLîÝéÿF²Tg+"›Ie]ÐÆ[<à Ó't?ãÊÿ“áþupð ëÙëM¸‰ÒHÉ ã$}+G1i—û^òÚÖé£ãþQqÐñÄ¥ìÃmí.. xmæ‘‚Ê„÷¨ÓBâvãpÀdƒƒÅjÞ3ÔQµ -ÚE†8ñ,ë „äôsÓš~-¡ˆ(Fw‘¸±úšäËŸ†¨ìÃásöfÚG†õ=jáa²¶%€'sª>¹{Ó¿eN±Â×÷ÿë êH«¶Š`µ²y°¡™ÝŽíSmoLä<ŽÞd£pLcËÿZlsRVYxÊØ2ÃÂÚf•òíz|L2i›ûë—¹Xab pª§Uº[[%’CYÌú³<ûÁÏ_JžY¯EñÆ5tº¶{«V›\œ©åsÏéš­Ïú5À–',ƒâ ¼ŒS2_]Ú¼’¬Œñ,@çg9éô©öºÄ7Ò@Ä•FA\“þ•ïa”ƒZ7ˆ£š4Že¥²sÛíQüQ4Og)Ž< §µVØÃg6è¹çŽjLòɨ[4xåШöªE[²RžíÄ…OL P‹ùsl@“Eo­'†îH¤BŒ¬rqê>Ô"ùwd¼ŽµÕèòiòØ‹8ö®â9©2‘äÔ(À‚;dT‰\ʃ€‡¸&ˆdy™ï^¤ˆ˜{ýëÕ¨ÔÍefÛ!^بï/Äj:ͼ)<äu‰¤ê@5¬ì=<ûAɨñÅÆì¤‘ž)›˜e‘€ÉcDÓ'–Ø,V³Hrr"Ç4†˜Åµ¿—óŒ}hÅ´Ḻª³áUFI>ÜÑ­3Àš¼Ì%+ªžò‹AýjÛa¢Ùx}A Ï9ø‹mΰ¡i*ݘ|ªÝDO•¿ÿUñÿë“ùÓ7¾Õ¢rGÇ!&ô­"@Hv²0ü$Tññ&}zV« ¥(½£çôÉ­eužÙàt'(˱±ëJŽ×e>lŽŸæ·Ohjš[ºE›¨”´l£âÞØõr}³P48& gšW’g¾•AµÖ}Úà옖 ‘Vž&Ö#ua"DZu,{{õªÖ§à$f¸´»”Žv‡é]‹SYÔ-­aÜ-mÉ9g ý*Õw+.dPìw-uChçË Ú2›­¥d“~t9¢¶Žªß÷ÍsÍ?tó[Þ;yå–çqéOÛβ–RûØôȦHå•¢2Á:(Q9 w Wªq…óÂq^¦¡y³ÿÙdrpython-3.11.1/documentation/help.txt0000644000175000017500000005165311150445515020627 0ustar dktrkranzdktrkranz================ DrPython: Help ================ .. _Credits: credits.html .. _Thanks: thanks.html .. _DrScript: drscript.html .. _Plugins: plugins.html .. _Preferences: preferences.html .. _GPL: gpl.html :Author: Daniel Pozmanter :Contact: drpython@bluebottle.com :Web site: http://drpython.sourceforge.net/ :Copyright: 2003-2007 Daniel Pozmanter :License: GPL_ .. _Top: Credits_ Thanks_ .. contents:: **Customize and Extend:** - Preferences_ - DrScript_ - Plugins_ Introduction ============= *Just what is DrPython?* To start with, DrPython is a Development Environment. It is essentially a text editor with built in programming tools, like an integrated prompt, text manipulation, and syntax highlighting to name a few. The integrated prompt means when you run a python program, DrPython catches the output, takes input, and in general behaves like a console window (cmd.exe or rxvt for example). DrPython was designed to be a cross-platform Python IDE. The primary purpose was for use in Education, to make teaching Python programming easier. It was originally designed based roughly on DrScheme. DrPython is meant to play the same role for Python that DrScheme plays for Scheme. The development platform is Linux (Mandrake 10.1 is the current flavor) It has been tested on various flavors of Linux (E.g. Mandrake, Debian, Gentoo, Fedora), Windows 9x, Windows NT, Windows XP, and Mac OS X. Any platform which supports python 2.3+ and wxPython 2.5.2+ should work. *Is DrPython Free or What?* DrPython is both free and open source software. This means you can download DrPython for free, share it as much as you want, look through the source, whatever. You can even take chunks of code and plop them into your own program (so long as you give proper credit!). You could even start your own branch of DrPython, or rewrite the code to work with another language. The point of Free/Open Source Software is that the user has the power to use their software as they wish. The bummer side of this is that DrPython has no warranty. So if after using DrPython your computer becomes telekinetic and blows up your refrigerator... You can send me a bug report. DrPython is released under the GNU Public License. Built Using ------------ For the Program: - Python (Guido van Rossum et al.) - wxWidgets (Julian Smart et al.) - wxPython (Robin Dunn et al.) - Scintilla (Neil Hodgson) For the Documentation: - docutils (David Goodger) - Syntax-highlighted code blocks for docutils (On ASPN) (Kevin Schluff) - Silver City (Brian Quinlan) Icons from: - Klassic New Crisp Icons (Asif Ali Rizwaan) - Sparkling (Flow) - Noia (Carles Carbonell Bernado) - Nuvola (David Vignoni) - (Some Icons Were Either Created or Edited by Daniel Pozmanter.) Donate! -------- If you want to show support for DrPython, send a donation our way. A single dollar would be delicious and nutritious: `Donate to Daniel Pozmanter `_ `Donate to North Star `_ Back to the Top_. Installation ============= If you are reading this, DrPython should already be installed. That being said, you need the following programs to run DrPython: Python 2.0 or newer (tested with 2.2) and the corresponding wxPython. It is really best to get the lastest version of Python and wxPython. If you are having trouble running DrPython on Linux/Unix, run the file ``drpython.lin``, or edit the first line of ``drpython.pyw`` or ``drpython.py`` to read: .. code-block:: Python #![PATH/TO/PYTHON]/python (eg: ``#!/usr/bin/python``). (In other words, make the path absolute.) If you are still having trouble, go to the DrPython website (http://www.sourceforge.net/projects/drpython/) and post to the help forum. You can manually set the path used for storing preferences: ``drpython.pyw --preferencesbasepath="the path"`` DrPython will then use preferences in the directory: - "the path/.drpython" - "the path/drpython" on Windows Support -------- Found a bug? Want to see something change? Have a feature request? Stop by the `DrPython Sourceforge Project Page `_. Post in the forum, or formally submit a bug/feature request. I highly recommend starting a discussion on possible features/changes. Part of the power of open source is the power of the users and developers to engage in discourse about a project, its design and its uses. Features ========= Bookmarks ---------- Bookmarks are pretty straighforward: there are Bookmarks, and there are Bookmark Folders. A Bookmark is either a file or directory. When it is selected from the menu, if it is a file, it is opened. If it is a directory, an Open Dialog in that directory pops up. A Bookmark Folder may contain Bookmarks and/or Bookmark Folders. You can only add a Bookmark Folder or Bookmark to a Bookmark Folder. To move a Bookmark or a Bookmark Folder (and all it's contents): 1. Single click on the item you want to move. 2. Drag it to the item you want it to go immediately after. 3. Dragging it to the any item in a folder will cause it to be added directly after that item. 4. Dragging it to a folder will cause it to be the first item in that folder. Back to the Top_ Check Syntax ------------- Runs the python built in 'compile', then tabnanny, on the current file. Reports syntax and indentation errors. Note that this only checks the syntax for the current file. Encoding Support ----------------- **The following only applies if your version of wxPython was built with unicode support:** If you want to use a non ascii encoding (like latin-1 or unicode (utf8)), you need to set some preferences first. (In the event of a bad encoding, drpython will warn you via standard output (if the problem is in the file dialog or prompt), or via a dialog (if the problem occurs while saving or opening a file). DrPython, by default, checks for unicode when opening/saving files, and in the Prompt. If you want to use a specific encoding, you have two options. 1. You can set the default encoding via Preferences. This is the encoding used by default when opening/saving files, and the encoding used in the prompt and file dialog. 2. For Opening and Saving files, if you use the special python comment: .. code-block:: Python # -*- coding: xyz -*- (As detailed in the Python Tutorial). DrPython will try the encoding 'xyz' for the file first. DrPython, when getting text to open/save will go through the following steps: 1. Check for a special comment (coding) (if Auto Detect is enabled). 2. Check for Unicode (if Auto Detect is enabled) 3. Check for default encoding (if Default Encoding is enabled) 4. If no check passes, ensure the text is ascii. To disable default encoding, leave it blank. Back to the Top_ Find/Replace -------------- This is a rather standard/straightforward dialog. However there are some things that stick out. Right clicking on the text field will yield a pop up menu. You can insert tab/newline/carriage returns, perform clipboard operations, or clear the text. You can also access Find/Replace History via the combobox. Back to the Top_ Find and Complete ------------------ This is a user initiated version of auto complete. DrPython will search the current file for possible completions to the word you are currently typing. It will display these results in a small window. Navigate by using the up and down arrows, or to go faster, page up and page down to go faster, or home and end to skip to the start and end of the list. Hitting Enter or Tab will complete the current word with the selection. Context Sensitive: Find And Complete stops at the following characters (in addition to whitespace):: ( ) < > [ ] { } This means: .. code-block:: Python tree dog(threat) dogs dog(tre searching at ``dog(tre`` will yield ``tree, treat``. However: .. code-block:: Python tree dog(treat dogs dog( searching at ``dog(`` will yield ``dog(threat, dogs``. Note: Find And Complete is case sensitive. Back to the Top_ Go To Block / Class / Def -------------------------- A few notes. In the code: .. code-block:: Python if True: print "Hallo" # Comment print "Hello again" '``if True:``' is the start of the block; '``print "Hello again"``' is the end. Comments '``#``' are ignored. For explicitly (joined with a backslash) and implicitly joined lines, every line after the first is ignored. Goto Traceback --------------- Double clicking a traceback entry in the prompt (the *File* line in the example below):: Traceback (most recent call last): File "/home/user/Desktop/test.py", line 6, in ? wd NameError: name 'wd' is not defined will tell DrPython to open '/home/user/Desktop/test.py' and go to line 6. Back to the Top_ Indentation and Tabs --------------------- The "Use Tabs" option under "Document" in preferences tells DrPython whether to use tabs (default) or spaces for autoindentation. "Tab Width" under "General" is how many spaces DrPython should consider a "Tab" to be. To see what characters the current document uses for indentation, check the statusbar. The "Whitespace" menu has entries that allow you to set indentation to tabs or spaces. Setting the indentation for the document to tabs, for example, will replace a set number of spaces with tabs. This operation takes place at the beginning of each line. Some programmers prefer (and/or were taught) to use tabs ('\t') to indent blocks of code. Some use spaces instead. The whitespace menu lets you easily switch the type of indentation used in the current file to the type you prefer to work with. Note: The ClassBrowser only works properly if the current file is using the same type of indentation (tab character or spaces) as is set as the default for DrPython in prefs. DrPython will automatically check for this when you open the Class Browser. To fix a mixed file, use the "Whitespace" menu under "Edit". NOTE: If the line endings are mixed, DrPython will not be able to properly fix the indentation. Always set the line endings before setting the indentation type. Back to the Top_ Shortcuts ---------- You can set shortcuts by selecting "Customize Shortcuts" from the Options menu. Ignore Keys ignores the modifier keys listed. Only modifier keys are valid. This is primarily for operating systems such as Linux, where the "Meta" key is set to "Num Lock" by default, and hence may always be on. Note: You can set shortcuts for DrScript menu items. If you have not, or the shortcuts file is somehow out of sync with the actual number of DrScripts, DrPython will simply load the correct DrScripts, with no default shortcuts. DrScript Shortcuts are stored separately from DrPython Shortcuts. If your shortcuts are not working, use "get key" on a shortcut to see if a modifier key is constantly present. On Linux, "Meta" may be present. If this is the case, use "Ignore Keys" to set "Meta" as a key to ignore. For a given shortcut, simply click the "Get Key" Button, and press the keys you wish. It will print the modifiers detected, and the keycode. When you are done, hit "Close", and the keystring will be next to the shortcut. Select "Update" to start using the key now. Select "Save" to have DrPython remember the changes. Note: The Tab and Enter keys are used for code related to indentation in the document, and Enter + the arrow keys are used behaviour specific to the prompt. Setting these keys in the shortcuts may cause DrPython to behave incorrectly. Note: On some platforms some keys may not register, and thus cannot be used as shortcuts. Note: There seems to be a bug where shift + backspace inserts the backspace character. To work around this, "Delete Back Not Line" is assigned to ``shift + backspace``. If you want to insert the backspace character, just set "Delete Back Not Line" to None. If you want to use ``shift + backspace`` for something else, just set it to None, and you should be set. The defaults are: =================== ================== Key Default shortcut =================== ================== Ctrl + N New File Ctrl + O Open File Ctrl + S Save File Ctrl + W Close File .. .. .. .. .. .. Ctrl + M Open Imported Module .. .. .. .. .. .. F9 Select Previous Document F10 Select Next Document .. .. .. .. .. .. F7 Open a Python interpreter Ctrl + E Run current program Ctrl + D End current program / Python interpreter .. .. .. .. .. .. Ctrl + R Replace Ctrl + F Find F3 Find Next Shift + F3 Find previous .. .. .. .. .. .. Ctrl + G Go to line Ctrl + B Go to block start Ctrl + Shift + B Go to block end Ctrl + F8 Source Browser Go To .. .. .. .. .. .. Ctrl + Enter Find and complete .. .. .. .. .. .. F6 Toggle view prompt F5 Toggle maximise F8 Toggle source browser Ctrl + Shift + W Toggle view whitespace .. .. .. .. .. .. Ctrl + P Print file Ctrl + Shift + P Print prompt .. .. .. .. .. .. Ctrl + [ Comment Ctrl + ] Uncomment Ctrl + I Indent Ctrl + Shift + I Dedent .. .. .. .. .. .. Ctrl + A Select all Ctrl + Z Undo Ctrl + Y Redo Ctrl + X Cut Ctrl + C Copy Ctrl + V Paste Ctrl + + Zoom in Ctrl + - Zoom out Ctrl + Shift + U Uppercase Ctrl + U Lowercase =================== ================== Back to the Top_ Line Endings ------------- ================ ======== === Unix Mode \\n New line Windows Mode \\r\\n Carriage return, New line Macintosh Mode \\r Carriage return ================ ======== === Windows mode can make linux hiccup. So Unix Mode is the default (Windows seems to be fine with it.) Note: Setting the Line Endings in Preferences does not affect the current open file! Back to the Top_ Menu And Focus (Toggling) -------------------------- Some menu items act on the Text Control currently with focus. Toggle Whitespace Visible is one such item. If the focus is on the File text control, then selecting this menu item will cause the whitespace to either become visible or invisible in that control. If the focus is on the prompt, then the whitespace will be toggled in the prompt. Back to the Top_ Open Imported Module ---------------------- DrPython only shows modules which exist. These are either in the current module search path for Python, or in the same directory as the current document. Some modules do not exist as files. The integral modules sys and time are two examples. These will not show up in the list of imported modules, even if they are imported in the current document. If you type, the typed text is used as a filter for the matching modules. (Use backspace to backtrack). Only matches that contain the typed text will be shown. (Case insensitive.) Back to the Top_ Pop Up Menu ------------- The Pop Up Menu is the menu that pops up when you right click on the Document, or the Prompt. You can customize this menu to handle DrPython functions, DrScripts, or plugins. Note that each item on the Pop Up Menu must have a distinct name for everything to work properly. Back to the Top_ Rectangular Selection ----------------------- To activate this feature, use ``Alt`` on Windows, ``Shift + Alt`` on Linux. (If neither works, try ``Ctrl``). **In Find**: rectangular selection ignores line endings, and does not support the 'Whole Word' flag. It searches line by line. **In Replace**: the above applies. Also, 'Prompt On Replace' is not supported. Back to the Top_ Regular Expressions -------------------- It is best to consult the python documentation (Under Modules, "re"). In short, Regular Expressions provide a fast and powerful method for matching patterns of text. These can be quite useful in programs you write, or simply to find and/or replace text in a given file. Back to the Top_ Running a Python Program ------------------------- Open a file, click run, and you are set to go. If your program takes arguments, select "Set Arguments" from the menu or toolbar. Note the right field in the status bar tells you if the program is running. Also note that the "End" button is enabled, and "Run", "Set Arguments", and "Python Debugger" are disabled. When the program has ended, the right status bar field goes blank, "End" is disabled, and "Run", "Set Arguments", and "Python Debugger" are enabled. Back to the Top_ Shell Commands --------------- To add a shell command, go to the DrScript menu, under Add Script, and select "Shell Command". Back to the Top_ Source Browser --------------- The source browser displays classes, defs, imports, and labels. Double Clicking (Or, Optionally, Right Clicking) an item will set the Document to the line number of that item. Separators (Labels) can be added manually #---YourLabelHere or via the Insert Seperators Dialog. Back to the Top_ Source Browser Go To --------------------- A very quick and simple way to move around in a large document. If you type, the typed text is used as a filter for the matching classes, defs, and imports. (Use backspace to backtrack). Only matches that contain the typed text will be shown. (Case insensitive.) The typed text is echoed in the top text control. The next two text controls shows the line number of the selected item, as well as the class or function the item is defined in. (The filename is used if no class or function is found). Back to the Top_ Status Bar ----------- | The Status Bar displays some useful information. The left bar displays: | [*current line*] [*current column*] [*line ending type*] [*insert/overtype*] [*indentation type*] | The right bar displays program/Python status, for example ``Running Python Interpreter``. Back to the Top_ Tool Bar --------- A few notes on customizing the toolbar. 1. When selecting a particular icon for a toolbar item, select the toolbar item from the left list ("Current List"), then click the "Change" button for the icon size you want. 2. If you specify an icon, this will be loaded instead of the default, and instead of any icon file loaded. 3. If you select an icon that is a different size than the selected size (16x16, 24x24), the toolbar will not display correctly. Back to the Top_ Tracebacks ----------- Tracebacks are the output the python interpreter produces for an unhandled exception. This output:: Traceback (most recent call last): File "/mnt/win_e/docs/prog/drpython/drpython-3.1.2/drpython.py", line 1840, in OnGoTo v = int(v) - 1 ValueError: invalid literal for int(): line number is produced if you type "line number" into the Goto dialog. Now, DrPython handles this exception. However DrPython displays tracebacks in its error dialogs (if there are any) for the purposes of transparency. This way, if there is a bug it is easier to report it, and if you are working on a DrScript or a Plugin, this makes it easier to figure out what is going on. Back to the Top_ View In Panel -------------- View In Panel lets you view any open document (including the current one) in any side panel. There are two notes. 1. Only STC shortcuts work in these panels. (The exception is if the split view is of the current document). 2. If you view document 1 in document 2, then close document 1, you need to close the panel in document 2 manually. Back to the Top_ Notes ====== DrPython cannot handle everything. If you create more than 100 Panels in any one direction (Left, Right, Top, Bottom), the events will be all messed up. If you do not have permission to write to your user's home directory, or the replacement directories DrPython will try if your home directory does not exist (eg. ``C:\`` or ``os.environ["APPDATA"]``), then DrPython will not save preferences, and will not keep a recent files list. If you run a program with an infinite loop, things will get rather slow. Hit the "End" button on the toolbar, or hit Ctrl+D to end the program being run. Please note that if you type the color in for the font style dialog, any bad characters (not 0-9 or A-F) will create a warning the moment you enter them. If the string is not properly formated ('#' followed by 6 characters), the sliders will be disabled. Upon hitting OK, any invalid color string will be ignored, and DrPython will revert to the last value for that color string. Back to the Top_drpython-3.11.1/documentation/gpl.html0000644000175000017500000004275111150445515020605 0ustar dktrkranzdktrkranz GPL

GPL



GNU GENERAL PUBLIC LICENSE

Version 2, June 1991

Copyright (C) 1989, 1991 Free Software Foundation, Inc.  
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

Back to the Top


Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.

We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.

Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.

Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and modification follow.

Back to the Top


TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  1. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".

    Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.

  2. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.

    You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.

  3. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:

    1. You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
    2. You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
    3. If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)

    These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.

    Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.

    In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.

  4. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:

    1. Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
    2. Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
    3. Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)

    The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.

    If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.

  5. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

  6. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.

  7. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.

  8. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.

    If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.

    It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.

    This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.

  9. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.

  10. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.

    Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.

  11. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

NO WARRANTY

  1. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  2. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

END OF TERMS AND CONDITIONS

Back to Top

drpython-3.11.1/documentation/gpl.txt0000644000175000017500000003732511150445515020461 0ustar dktrkranzdktrkranz================ GPL ================ .. _Top: .. contents:: GNU GENERAL PUBLIC LICENSE =========================== Version 2, June 1991 :: Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Back to the Top_ Preamble --------- The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. Back to the Top_ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ---------------------------------------------------------------- 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. **NO WARRANTY** 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. **END OF TERMS AND CONDITIONS** Back to Top_drpython-3.11.1/documentation/credits.html0000644000175000017500000002240611150445515021453 0ustar dktrkranzdktrkranz Credits

Credits

Back to Help

montypythonMOLDoctorAndSupport.jpg

This section is for people who have contributed to DrPython.

Thank you!

(Note, this list is only for the DrPython Core.)

Contributors

(Thanks For Helping Develop DrPython!)

(Note: If you built an os specific package, and want to be on this list, send me an email at DrPython AT bluebottle.com, or post in the forums.)

Austin Acton Mandrake Packager.
Bjorn Breid 1 bug-report with fix.
Bo Jangeborg 3 bug-reports.
bugmenot 1 bug-report.
Carsten Eckelmann Linux/UNIX documentation note.
Cédric Delfosse Debian Packager, 1 bug report with fix.
Chris McDonough
Initialized CVS Repository,
Submitted Long Line Indicator
Code for Preferences.
Chris Wilson
1 bug-report/feature request,
3 bug-reports, 4 bug-reports with fix.
Donation to North Star(DrPython), Daniel Pozmanter(drpython).
Christian Daven 1 bug-report with fix, 3 submitted patches.
Christof Ecker 1 bug-report, 1 bug-report with fix.
Christoph Zwerschke
2 bug-reports with fix, 1 bug-report with co-fix,
1 bug-report/feature request with co-fix, 8 bug-reports, 10 bug-report/feature requests,
Windows Installer, 3 setup.py patches.
Dan Kruger 4 bug-reports, 1 bug-report with fix.
Dan Uznanski 1 bug-report.
Dariusz Mikuiski 1 bug-report with fix.
dataangel 4 bug-reports.
Davy Mitchell Windows Installer.
Dmitry Ovsjannikov 1 bug-report.
Dominique Buenzli
4 bug-reports,
1 bug-report/feature request.
Testing side of the Mac wxPython
1 Bug Work Around.
fyngyrz (Ben)
Donation to Daniel Pozmanter(drpython).
Franz Steinhausler
29 bug-report/feature requests,
7 bug-report/feature requests with co-fix,
83 bug-reports, 6 bug-reports with co-fix,
46 bug-reports with fix, 4 bug-fixes.
19 code-fixes.
Submitted Code:
Highlight Current Line Code for Preferences.
Added Configure Plugins, Customize Shortcuts, Pop Up, Toolbar to pop up menu and shortcuts.
Speed Optimizations in Find, Indent/Dedent Region.
Indentation format in Paste from CopyCutPasteExtend Plugin.
Write Access Patch. 2 Patches for File Dialog.
Plugin Display Patches in Edit Index Dialog, Load From Index Menu.
Submitted pychecker report, Patch: Display Shortcuts in Pop Up Menu.
fstephens2 1 bug-report.
gero 1 bug-report with co-fix.
Greg Wilson 1 bug-report.
Gregory Smith 4 bug-reports, 1 bug-report with fix.
Guillermo Fernandez 1 bug-report with fix.
indefual 1 bug-report.
Ivar Marohombsar 1 bug-report.
James Paige Donation to North Star(DrPython), Daniel Pozmanter(drpython).
Jean Luc Damnet 2 bug-reports, bug-report with fix.
John Bell 2 bug-reports, patch.
Jon Schull 1 bug-report/feature request.
Keith Nash 1 bug-report/feature request.
limodou
Unicode Co-Developer,
UTF-8 Autodetect,
Interface Tweak, Persistent Find Across Documents,
4 bug-reports, 8 bug-fixes.
Marek Kubica
1 co-fix, 6 bug-reports, 3 bug-report/feature requests.
Converted Documentation to docutils format.
Mark Rees 1 bug-report with fix.
Martinho DOS SANTOS Submitted Find and Complete patch.
Matthew (ECOP) Submitted patch for right click activation.
Michael Stather 1 bug-report, 1 bug-report/feature request.
Mike Foord 1 bug-report/feature request with fix.
Nathan Jones 1 bug-report with fix.
Pawel Dzierzanowski
1 bug-report with fix,
1 bug-report with diagnostic test.
Peter Mayne
4 bug-reports, 2 bug-report/feature requests.
1 bug-report/feature request with co-fix.
Submitted updated documentation files with style sheets.
Peter Schott 1 bug-report.
Radoslaw Stachowiak
Gentoo Packager, 1 submitted patch.
Submitted distutils support (setup.py, manifest.in).
Rene Aguirre Submitted pylint report.
Richard Townsend 5 bug-reports, 1 bug-report/feature request.
Robin Dunn Code for Text Drag and Drop.
Ronald Hollwarth 1 bug-report.
Ruben Baumann 1 bug-report with fix.
RunLevelZero 3 bug-report/feature requests.
Sascha Ernst Mac Launcher, 1 bug report.
Schmolch 1 bug-report/feature-request.
Sean McKay 1 bug-report.
Slim Amamou submitted file drag and drop code.
Stephen Anderson 5 bug-reports, bug-report with fix.
Stewart Midwinter Submitted Code for Save A Copy.
Steve Holden 1 bug-report.
theomurpse 1 bug-report.
Thomas Klinger 1 bug-report.
Tom De Muer 1 bug-report/feature request.
Toronto DrPython Project
Release 160.
1 bug-report with co-fix,
2 bug-reports,
4 bug-report/feature requests
Ulf Wostner bug-report, bug-report with fix.
Vincent Foley-Bourgon 1 bug-report/feature request.
widhaya3 1 bug-report/feature request with co-fix.

Toronto DrPython Project

3 Students at the University of Toronto worked on a project to extend and improve DrPython. The class was run by Professor Greg Wilson.

  • Laurie MacDougal
  • Pat Smith
  • Tim Smith
drpython-3.11.1/documentation/northstar.txt0000644000175000017500000000267211150445515021720 0ustar dktrkranzdktrkranz================ North Star ================ .. _Help: help.html Back to Help_ .. _Top: .. image:: NorthStarLogoSmall_top.gif `North Star `_ is a center for self-directed learners. Kids who choose not to go to school and pursue their own studies come here to learn about an impressive variety of topics. Classes are offered in diverse subjects such as: - philosophy - rhetoric - number theory - physics - programming - history - tidal pool biology - crochet - Shakespeare - war and peace - music ensemble - theater - botany - disability and the media - supreme court cases - business - photography - writing - art - and more! The school is small, with one full time teacher/staff member, a private army of college volunteers, and a host of passionate students. If you, dear user, would take a moment to think of the children, those plucky little folks, and donate some tax-deductable moolah to a truly wonderful cause, you can help a cutting edge "un-school" survive, and make what was hell for most of us (high school and middle school) heaven for these kids (and eventually more by serving as a model). `Please Donate to North Star `_ If you are interested or just want to know more, please contact me via e-mail: drpython@bluebottle.com or contact North Star directly via email: info@northstarteens.org or via phone (Massachusetts, USA): *(413) 582-0193*.drpython-3.11.1/documentation/help.html0000644000175000017500000011031711150445515020745 0ustar dktrkranzdktrkranz DrPython: Help

DrPython: Help

Author: Daniel Pozmanter
Contact: drpython@bluebottle.com
Web site:http://drpython.sourceforge.net/
Copyright: 2003-2005 Daniel Pozmanter
License:GPL

Credits

Thanks

Customize and Extend:

Introduction

Just what is DrPython?

To start with, DrPython is a Development Environment. It is essentially a text editor with built in programming tools, like an integrated prompt, text manipulation, and syntax highlighting to name a few. The integrated prompt means when you run a python program, DrPython catches the output, takes input, and in general behaves like a console window (cmd.exe or rxvt for example).

DrPython was designed to be a cross-platform Python IDE. The primary purpose was for use in Education, to make teaching Python programming easier. It was originally designed based roughly on DrScheme. DrPython is meant to play the same role for Python that DrScheme plays for Scheme.

The development platform is Linux (Mandrake 10.1 is the current flavor) It has been tested on various flavors of Linux (E.g. Mandrake, Debian, Gentoo, Fedora), Windows 9x, Windows NT, Windows XP, and Mac OS X.

Any platform which supports python 2.3+ and wxPython 2.5.2+ should work.

Is DrPython Free or What?

DrPython is both free and open source software. This means you can download DrPython for free, share it as much as you want, look through the source, whatever. You can even take chunks of code and plop them into your own program (so long as you give proper credit!). You could even start your own branch of DrPython, or rewrite the code to work with another language.

The point of Free/Open Source Software is that the user has the power to use their software as they wish.

The bummer side of this is that DrPython has no warranty. So if after using DrPython your computer becomes telekinetic and blows up your refrigerator... You can send me a bug report.

DrPython is released under the GNU Public License.

Built Using

For the Program:

  • Python (Guido van Rossum et al.)
  • wxWidgets (Julian Smart et al.)
  • wxPython (Robin Dunn et al.)
  • Scintilla (Neil Hodgson)

For the Documentation:

  • docutils (David Goodger)
  • Syntax-highlighted code blocks for docutils (On ASPN) (Kevin Schluff)
  • Silver City (Brian Quinlan)

Icons from:

  • Klassic New Crisp Icons (Asif Ali Rizwaan)
  • Sparkling (Flow)
  • Noia (Carles Carbonell Bernado)
  • Nuvola (David Vignoni)
  • (Some Icons Were Either Created or Edited by Daniel Pozmanter.)

Installation

If you are reading this, DrPython should already be installed. That being said, you need the following programs to run DrPython: Python 2.0 or newer (tested with 2.2) and the corresponding wxPython. It is really best to get the lastest version of Python and wxPython.

If you are having trouble running DrPython on Linux/Unix, run the file drpython.lin, or edit the first line of drpython.pyw or drpython.py to read:

#![PATH/TO/PYTHON]/python

(eg: #!/usr/bin/python). (In other words, make the path absolute.)

If you are still having trouble, go to the DrPython website (http://www.sourceforge.net/projects/drpython/) and post to the help forum.

You can manually set the path used for storing preferences:

drpython.pyw --preferencesbasepath="the path"

DrPython will then use preferences in the directory: - "the path/.drpython" - "the path/drpython" on Windows

Support

Found a bug? Want to see something change? Have a feature request? Stop by the DrPython Sourceforge Project Page. Post in the forum, or formally submit a bug/feature request. I highly recommend starting a discussion on possible features/changes. Part of the power of open source is the power of the users and developers to engage in discourse about a project, its design and its uses.

Features

Bookmarks

Bookmarks are pretty straighforward: there are Bookmarks, and there are Bookmark Folders.

A Bookmark is either a file or directory. When it is selected from the menu, if it is a file, it is opened. If it is a directory, an Open Dialog in that directory pops up.

A Bookmark Folder may contain Bookmarks and/or Bookmark Folders.

You can only add a Bookmark Folder or Bookmark to a Bookmark Folder.

To move a Bookmark or a Bookmark Folder (and all it's contents):

  1. Single click on the item you want to move.
  2. Drag it to the item you want it to go immediately after.
  3. Dragging it to the any item in a folder will cause it to be added directly after that item.
  4. Dragging it to a folder will cause it to be the first item in that folder.

Back to the Top

Check Syntax

Runs the python built in 'compile', then tabnanny, on the current file. Reports syntax and indentation errors.

Note that this only checks the syntax for the current file.

Encoding Support

The following only applies if your version of wxPython was built with unicode support:

If you want to use a non ascii encoding (like latin-1 or unicode (utf8)), you need to set some preferences first. (In the event of a bad encoding, drpython will warn you via standard output (if the problem is in the file dialog or prompt), or via a dialog (if the problem occurs while saving or opening a file).

DrPython, by default, checks for unicode when opening/saving files, and in the Prompt.

If you want to use a specific encoding, you have two options.

  1. You can set the default encoding via Preferences. This is the encoding used by default when opening/saving files, and the encoding used in the prompt and file dialog.
  2. For Opening and Saving files, if you use the special python comment:
# -*- coding: xyz -*-

(As detailed in the Python Tutorial).

DrPython will try the encoding 'xyz' for the file first.

DrPython, when getting text to open/save will go through the following steps:

  1. Check for a special comment (coding) (if Auto Detect is enabled).
  2. Check for Unicode (if Auto Detect is enabled)
  3. Check for default encoding (if Default Encoding is enabled)
  4. If no check passes, ensure the text is ascii.

To disable default encoding, leave it blank.

Back to the Top

Find/Replace

This is a rather standard/straightforward dialog. However there are some things that stick out.

Right clicking on the text field will yield a pop up menu. You can insert tab/newline/carriage returns, perform clipboard operations, or clear the text.

You can also access Find/Replace History via the combobox.

Back to the Top

Find and Complete

This is a user initiated version of auto complete. DrPython will search the current file for possible completions to the word you are currently typing. It will display these results in a small window. Navigate by using the up and down arrows, or to go faster, page up and page down to go faster, or home and end to skip to the start and end of the list.

Hitting Enter or Tab will complete the current word with the selection.

Context Sensitive: Find And Complete stops at the following characters (in addition to whitespace):

( ) < > [ ] { }

This means:

tree
dog(threat)
  
dogs
dog(tre

searching at dog(tre will yield tree, treat. However:

tree
dog(treat

dogs

dog(

searching at dog( will yield dog(threat, dogs.

Note: Find And Complete is case sensitive.

Back to the Top

Go To Block / Class / Def

A few notes. In the code:

if True:
    
print "Hallo"
# Comment
    
print "Hello again"

'if True:' is the start of the block; 'print "Hello again"' is the end.

Comments '#' are ignored. For explicitly (joined with a backslash) and implicitly joined lines, every line after the first is ignored.

Goto Traceback

Double clicking a traceback entry in the prompt (the File line in the example below):

Traceback (most recent call last):
File "/home/user/Desktop/test.py", line 6, in ?
  wd
NameError: name 'wd' is not defined

will tell DrPython to open '/home/user/Desktop/test.py' and go to line 6.

Back to the Top

Indentation and Tabs

The "Use Tabs" option under "Document" in preferences tells DrPython whether to use tabs (default) or spaces for autoindentation. "Tab Width" under "General" is how many spaces DrPython should consider a "Tab" to be.

To see what characters the current document uses for indentation, check the statusbar.

The "Whitespace" menu has entries that allow you to set indentation to tabs or spaces. Setting the indentation for the document to tabs, for example, will replace a set number of spaces with tabs. This operation takes place at the beginning of each line.

Some programmers prefer (and/or were taught) to use tabs ('t') to indent blocks of code. Some use spaces instead.

The whitespace menu lets you easily switch the type of indentation used in the current file to the type you prefer to work with.

Note: The ClassBrowser only works properly if the current file is using the same type of indentation (tab character or spaces) as is set as the default for DrPython in prefs. DrPython will automatically check for this when you open the Class Browser. To fix a mixed file, use the "Whitespace" menu under "Edit".

NOTE: If the line endings are mixed, DrPython will not be able to properly fix the indentation. Always set the line endings before setting the indentation type.

Back to the Top

Shortcuts

You can set shortcuts by selecting "Customize Shortcuts" from the Options menu.

Ignore Keys ignores the modifier keys listed. Only modifier keys are valid. This is primarily for operating systems such as Linux, where the "Meta" key is set to "Num Lock" by default, and hence may always be on.

Note: You can set shortcuts for DrScript menu items. If you have not, or the shortcuts file is somehow out of sync with the actual number of DrScripts, DrPython will simply load the correct DrScripts, with no default shortcuts. DrScript Shortcuts are stored separately from DrPython Shortcuts.

If your shortcuts are not working, use "get key" on a shortcut to see if a modifier key is constantly present. On Linux, "Meta" may be present. If this is the case, use "Ignore Keys" to set "Meta" as a key to ignore.

For a given shortcut, simply click the "Get Key" Button, and press the keys you wish. It will print the modifiers detected, and the keycode. When you are done, hit "Close", and the keystring will be next to the shortcut.

Select "Update" to start using the key now. Select "Save" to have DrPython remember the changes.

Note: The Tab and Enter keys are used for code related to indentation in the document, and Enter + the arrow keys are used behaviour specific to the prompt. Setting these keys in the shortcuts may cause DrPython to behave incorrectly.

Note: On some platforms some keys may not register, and thus cannot be used as shortcuts.

Note: There seems to be a bug where shift + backspace inserts the backspace character. To work around this, "Delete Back Not Line" is assigned to shift + backspace. If you want to insert the backspace character, just set "Delete Back Not Line" to None. If you want to use shift + backspace for something else, just set it to None, and you should be set.

The defaults are:

Key Default shortcut
Ctrl + N New File
Ctrl + O Open File
Ctrl + S Save File
Ctrl + W Close File
Ctrl + M Open Imported Module
F9 Select Previous Document
F10 Select Next Document
F7 Open a Python interpreter
Ctrl + E Run current program
Ctrl + D End current program / Python interpreter
Ctrl + R Replace
Ctrl + F Find
F3 Find Next
Shift + F3 Find previous
Ctrl + G Go to line
Ctrl + B Go to block start
Ctrl + Shift + B Go to block end
Ctrl + F8 Source Browser Go To
Ctrl + Enter Find and complete
F6 Toggle view prompt
F5 Toggle maximise
F8 Toggle source browser
Ctrl + Shift + W Toggle view whitespace
Ctrl + P Print file
Ctrl + Shift + P Print prompt
Ctrl + [ Comment
Ctrl + ] Uncomment
Ctrl + I Indent
Ctrl + Shift + I Dedent
Ctrl + A Select all
Ctrl + Z Undo
Ctrl + Y Redo
Ctrl + X Cut
Ctrl + C Copy
Ctrl + V Paste
Ctrl + + Zoom in
Ctrl + - Zoom out
Ctrl + Shift + U Uppercase
Ctrl + U Lowercase

Back to the Top

Line Endings

Unix Mode \n New line
Windows Mode \r\n Carriage return, New line
Macintosh Mode \r Carriage return

Windows mode can make linux hiccup. So Unix Mode is the default (Windows seems to be fine with it.)

Note: Setting the Line Endings in Preferences does not affect the current open file!

Back to the Top

Open Imported Module

DrPython only shows modules which exist. These are either in the current module search path for Python, or in the same directory as the current document.

Some modules do not exist as files. The integral modules sys and time are two examples. These will not show up in the list of imported modules, even if they are imported in the current document.

If you type, the typed text is used as a filter for the matching modules. (Use backspace to backtrack). Only matches that contain the typed text will be shown. (Case insensitive.)

Back to the Top

Pop Up Menu

The Pop Up Menu is the menu that pops up when you right click on the Document, or the Prompt. You can customize this menu to handle DrPython functions, DrScripts, or plugins.

Note that each item on the Pop Up Menu must have a distinct name for everything to work properly.

Back to the Top

Rectangular Selection

To activate this feature, use Alt on Windows, Shift + Alt on Linux. (If neither works, try Ctrl).

In Find: rectangular selection ignores line endings, and does not support the 'Whole Word' flag. It searches line by line.

In Replace: the above applies. Also, 'Prompt On Replace' is not supported.

Back to the Top

Regular Expressions

It is best to consult the python documentation (Under Modules, "re").

In short, Regular Expressions provide a fast and powerful method for matching patterns of text. These can be quite useful in programs you write, or simply to find and/or replace text in a given file.

Back to the Top

Running a Python Program

Open a file, click run, and you are set to go. If your program takes arguments, select "Set Arguments" from the menu or toolbar.

Note the right field in the status bar tells you if the program is running. Also note that the "End" button is enabled, and "Run", "Set Arguments", and "Python Debugger" are disabled.

When the program has ended, the right status bar field goes blank, "End" is disabled, and "Run", "Set Arguments", and "Python Debugger" are enabled.

Back to the Top

Shell Commands

To add a shell command, go to the DrScript menu, under Add Script, and select "Shell Command".

Back to the Top

Source Browser

The source browser displays classes, defs, imports, and labels. Double Clicking (Or, Optionally, Right Clicking) an item will set the Document to the line number of that item.

Separators (Labels) can be added manually #---YourLabelHere or via the Insert Seperators Dialog.

Back to the Top

Source Browser Go To

A very quick and simple way to move around in a large document. If you type, the typed text is used as a filter for the matching classes, defs, and imports. (Use backspace to backtrack). Only matches that contain the typed text will be shown. (Case insensitive.)

The typed text is echoed in the top text control. The next two text controls shows the line number of the selected item, as well as the class or function the item is defined in. (The filename is used if no class or function is found).

Back to the Top

Status Bar

The Status Bar displays some useful information. The left bar displays:
[current line] [current column] [line ending type] [insert/overtype] [indentation type]
The right bar displays program/Python status, for example Running Python Interpreter.

Back to the Top

Tool Bar

A few notes on customizing the toolbar.

  1. When selecting a particular icon for a toolbar item, select the toolbar item from the left list ("Current List"), then click the "Change" button for the icon size you want.
  2. If you specify an icon, this will be loaded instead of the default, and instead of any icon file loaded.
  3. If you select an icon that is a different size than the selected size (16x16, 24x24), the toolbar will not display correctly.

Back to the Top

Tracebacks

Tracebacks are the output the python interpreter produces for an unhandled exception. This output:

Traceback (most recent call last):
  File "/mnt/win_e/docs/prog/drpython/drpython-3.1.2/drpython.py", line 1840, in OnGoTo
    v = int(v) - 1
ValueError: invalid literal for int(): line number

is produced if you type "line number" into the Goto dialog.

Now, DrPython handles this exception. However DrPython displays tracebacks in its error dialogs (if there are any) for the purposes of transparency. This way, if there is a bug it is easier to report it, and if you are working on a DrScript or a Plugin, this makes it easier to figure out what is going on.

Back to the Top

View In Panel

View In Panel lets you view any open document (including the current one) in any side panel.

There are two notes.

  1. Only STC shortcuts work in these panels. (The exception is if the split view is of the current document).
  2. If you view document 1 in document 2, then close document 1, you need to close the panel in document 2 manually.

Back to the Top

Notes

DrPython cannot handle everything.

If you create more than 100 Panels in any one direction (Left, Right, Top, Bottom), the events will be all messed up.

If you do not have permission to write to your user's home directory, or the replacement directories DrPython will try if your home directory does not exist (eg. C:\ or os.environ["APPDATA"]), then DrPython will not save preferences, and will not keep a recent files list.

If you run a program with an infinite loop, things will get rather slow. Hit the "End" button on the toolbar, or hit Ctrl+D to end the program being run.

Please note that if you type the color in for the font style dialog, any bad characters (not 0-9 or A-F) will create a warning the moment you enter them. If the string is not properly formated ('#' followed by 6 characters), the sliders will be disabled. Upon hitting OK, any invalid color string will be ignored, and DrPython will revert to the last value for that color string.

Back to the Top

drpython-3.11.1/documentation/default.css0000644000175000017500000001454511150445515021273 0ustar dktrkranzdktrkranz/* :Author: David Goodger, Ian Bicking :Contact: ianb@colorstudy.com :date: $Date: 2003/11/01 20:35:45 $ :version: $Revision: 1.3 $ :copyright: This stylesheet has been placed in the public domain. A modification of the default cascading style sheet (v.1.3) for the HTML output of Docutils. Modified by Marek Kubica to look nicer Modified further by Daniel Pozmanter for 3.10.4 */ body { font-family: Arial, sans-serif; } em, i { /* Typically serif fonts have much nicer italics */ /*font-family: Times New Roman, Times, serif;*/ /* mk: I don't thinks so */ font-family: sans-serif; } /*li { list-style-type: circle; }*/ ul { list-style-type: circle; } a.target { color: blue; } a.toc-backref { text-decoration: none; color: black; } a.toc-backref:hover { background-color: inherit; } a:hover { background-color: #cccccc; } cite { font-style: normal; font-family: monospace; font-weight: bold; } dd { margin-bottom: 0.5em; } div.abstract { margin: 2em 5em; } div.abstract p.topic-title { font-weight: bold; text-align: center; } div.attention, div.caution, div.danger, div.error, div.hint, div.important, div.note, div.tip, div.warning { background-color: #cccccc; width: 40%; border: medium outset; padding: 3px; float: right } div.attention p.admonition-title, div.caution p.admonition-title, div.danger p.admonition-title, div.error p.admonition-title, div.warning p.admonition-title { color: #cc0000; font-weight: bold; font-family: sans-serif; text-align: center; background-color: #999999; display: block; margin: 0; } div.hint p.admonition-title, div.important p.admonition-title, div.note p.admonition-title, div.tip p.admonition-title { font-weight: bold; font-family: sans-serif; text-align: center; background-color: #999999; display: block; margin: 0; } div.dedication { margin: 2em 5em; text-align: center; font-style: italic; } div.dedication p.topic-title { font-weight: bold; font-style: normal; } div.figure { margin-left: 2em; } div.footer, div.header { font-size: smaller; } div.system-messages { margin: 5em; } div.system-messages h1 { color: red; } div.system-message { border: medium outset; padding: 1em; } div.system-message p.system-message-title { color: red; font-weight: bold; } div.topic { margin: 2em; } h1, h2, h3, h4, h5, h6 { font-family: Helvetica, Arial, sans-serif; border: thin solid black; font-size: medium; /* This makes the borders rounded on Mozilla, which pleases me */ -moz-border-radius: 3px; padding: 1px; } h1 { background-color: #444499; color: #ffffff; border: medium solid black; } h1 a.toc-backref { color: #ffffff; } h2 a.toc-backref, h3 a.toc-backref, h4 a.toc-backref, h5 a.toc-backref, h6 a.toc-backref { color: #000000; } h2, h3, h4, h5, h6 { background-color: #77b5ea; color: #000000; border: medium solid black; } h1.title { text-align: center; background-color: #444499; color: #eeeeee; border: thick solid black; -moz-border-radius: 20px; } h2.subtitle { text-align: center; } hr { width: 75%; } ol.simple, ul.simple { margin-bottom: 1em; } ol.arabic { list-style: decimal; } ol.loweralpha { list-style: lower-alpha; } ol.upperalpha { list-style: upper-alpha; } ol.lowerroman { list-style: lower-roman; } ol.upperroman { list-style: upper-roman; } p.caption { font-style: italic; } p.credits { font-style: italic; font-size: smaller; } p.first { margin-top: 0; } p.label { white-space: nowrap; } p.topic-title { font-weight: bold; } pre.address { margin-bottom: 0; margin-top: 0; font-family: serif; font-size: 100%; } pre.line-block { font-family: serif; font-size: 100%; } pre.literal-block, pre.doctest-block { margin-left: 2em; margin-right: 2em; background-color: #f5f5f5; border: thin black solid; padding: 5px; } span.classifier { font-family: sans-serif; font-style: oblique; } span.classifier-delimiter { font-family: sans-serif; font-weight: bold; } span.interpreted { font-family: sans-serif; } span.option-argument { font-style: italic; } span.pre { white-space: pre; } span.problematic { color: red; } table { margin-top: 0.5em; margin-bottom: 0.5em; } /* mk borderless table */ table.docutils { border-width: 0px; } /* /mk borderless table */ table.citation { border-left: solid thin gray; padding-left: 0.5ex } table.docinfo { margin: 2em 4em; } table.footnote { border-left: solid thin black; padding-left: 0.5ex; } td, th { padding-left: 0.5em; padding-right: 0.5em; vertical-align: top; /* mk */ border-width: 0px; /* /mk */ } td > p:first-child, th > p:first-child { margin-top: 0em; } th.docinfo-name, th.field-name { font-weight: bold; text-align: left; white-space: nowrap; } h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { font-size: 100%; } code, tt { color: #000066; } ul.auto-toc { list-style-type: none; } /*SilverCity CSS Thanks to Kevin Schluff's recipe on ASPN. */ div.code-block{ margin-left: 2em ; margin-right: 2em ; background-color: #eeeeee; font-family: "Courier New", Courier, monospace; font-size: 10pt; } /* SilverCity */ .code_default { FONT-FAMILY: "Courier New", Courier, monospace; FONT-SIZE: 10pt; } .css_class { color: #900000; } .css_comment { color: green; font-style: italic; } .css_default { } .css_directive { color: #009000; font-weight: bold; } .css_doublestring { color: navy; } .css_id { color: #900000; } .css_identifier { color: black; } .css_important { color: blue; } .css_operator { color: #000090; font-weight: bold; } .css_pseudoclass { color: #900000; } .css_singlestring { color: navy; } .css_tag { color: #900000; font-weight: bold; } .css_unknown_identifier { color: red; } .css_unknown_pseudoclass { color: #ff0000; } .css_value { color: navy; } .p_character { color: olive; } .p_classname { color: blue; font-weight: bold; } .p_commentblock { color: gray; font-style: italic; } .p_commentline { color: green; font-style: italic; } .p_default { } .p_defname { color: #009999; font-weight: bold; } .p_identifier { color: black; } .p_number { color: #009999; } .p_operator { color: black; } .p_string { color: olive; } .p_stringeol { color: olive; } .p_triple { color: olive; } .p_tripledouble { color: olive; } .p_word { color: navy; font-weight: bold; }drpython-3.11.1/documentation/NorthStarLogoSmall_top.gif0000644000175000017500000000462111150445515024236 0ustar dktrkranzdktrkranzGIF89aBeÄÿ///???OOO___oooŸŸŸ¯¯¯¿¿¿ÏÏÏßßßïïïÀÀÀ!ù,Be@ÿ $Ždižhª®lë¾p,Ïtmßx®ÛìÀ pH,HRoÉL’§tJ­Zs>ÅUDèm¿à°xL.›Ïè´zÍno¹ÔÂ^÷¡[2Txnƒz|% t€y'=#x='tt•tž‘#{]žŒ.ž+“¥¦‰&t|¶Š„»&=‡,šK?“½= ,M%~ɮƆ)K;°Ò$¬0ŽÕÏ¿¼Ý$ —Là2Ú'Lv¹' ¹Käå(¥ "ït Q Ô{ö© £®µa'féÁ¤À¥vtÜCÅDßžiS´ÛÔBQe4#pÙò5õ Ȥ]¤o"Ì%‚&¡¯‹ÔÒ4žœÌò´§äi—n%RoÓ˜}Þ¡ô\.ŽP‡qV`‹AÉÇg[ÉL:%Gü‚(ËÔxƒ»Q¤ïR› ‘À¿ zP û yšðaB;¡ ͱ®º0f=Há g(®r†2‘˜‡ÃF…¤˜ B.†×C>™h²ËÁÒb¼"–‰‰Ü·œX(’ª„TÌ¢·ÈÅ.zñ‹` £ÇHÆÿ2š1<£eC €tt¢ãÔè‚a‘LDÓ ê–†$Š-pÜH’&~ÐnË!ˆ J4¦Ñ24#לxÇúüP†2$™H²ŒÏ±• 0v…í‹~Šä *Ê‹¤¼¢)çC+¢€"tßè`µXš§âK‚Á`<íZ žñÀÀqˆ¬™‰˜NŠ@‡¥vJT³?±”Ï„¦–ùÁOKà8Îù4l)S4ã‘Mù®u§¦àC{íι܅Ç[(ê&Q릸R"’TéÆÛxu0ôT“дÛÉv‰°• cžèO‚%µXÿ³*K bÇŠŸ5E“ètf&5©^}ÒR%Áƒ‚±‘ Ì£ÚÛNC=¦ƒ-”' Ù6DÓ’¥ ¨8Fy•Ô4FÓšAÝ#v&š‚êtb/­TQMLqmG¤9=ØNIºŠ ž`¢Tý%?4ÔCÒ’©öA$)¼cÓgX ªM¬~TDªðƒ˜BÍÙ[³Õ›¢@!0àÊrA„½p¾¨êÑ a*1 X ¢pÌ*1¬˜ö´XI$×̹„¥âµ¨]ü[ÓÚáµÅJ  …ˆ2!ƒ  ´èÀR%&·¦Í¥r—Ë\1ز¹ciªS‹à°À*ÿŠÛBñz3ÚÔÈ3PâáqðHÄd°%kd€cÙ®UTrw#ÐÝÎÆ`Ç÷®×½5AR ÖJ„;ª·y˜á¯ä+Ù/üÓ†1 Fú0ºØkI…Ì .V¢v<€‘ZŠE0ì¡8X8¶ƒ…D ÉGøC¯ôB€Ç›‚Ìêpñ%àr᫈Ó&*I ((²=/ÀC8ƒ-püÃ4€ÖB„K»¸*íè‚p°€D £)aÀ¡Fð¤d7™t(ï €£¥"à̶€ #XYÈHsËt#šßäˆÏ]ÓgžÎæœÄbt ÏxÈFô#ûxs‘åÂþF‡$fÆÿƒ£ã»¥8äÙªÀKž±çý(UZãhP1 ÊùM?L¨æÖJ£ßÙÙÐHîþ[htT m QÝu”кÕYipUp[°Ôz×ôøÝ/(’˜\,;Ò=‘]Íô¢|® _å`¤ ±šuÈŽ/t2«é%åÂ9äÝçÃÔz ¡üîV?Å×-!­Ÿ7Z¹¥•^ a7‚ÄtÚ…©3\ t+­¡x P#çÓ!™öƸ|YDŸ¦8H Hñƒ.”W‡¿¬|*!ž”fG%èüaÆþjÔ÷ÉÒÐí—Sn!Õ4•9ùÁÄŒ©Äxx.t§ –c/ýSgr,Ã/;drpython-3.11.1/documentation/plugins.txt0000644000175000017500000005277611235247404021370 0ustar dktrkranzdktrkranz================ Plugins ================ .. _Help: help.html Back to Help_ .. _Top: .. contents:: Plugins provide a method of adding functionality to DrPython. Installing a Plugin ==================== Note: - Plugins are not loaded on install. - Some plugins cannot be indexed. They can only be loaded at program startup. You have two options for installing a plugin. Use the Wizard --------------- Select Install Plugin from the Configure Plugins Menu (Under Options). You can either download from a mirror, or select a downloaded plugin to install from local media. When installing, you will be asked to select which plugins are: - **Loaded By Default** (These plugins will be loaded at startup. They are placed in the default index [default.idx].) - **Loaded From Index** (If supported (only supported plugins will be listed here), these plugins are indexed. You can then select them from the options submenu "Load Plugin(s) From Index".) Install From Py ---------------- If you are making your own plugin, or have the plugin files availible in unzipped format, simply locate the main plugin file (``PluginName.py``), and DrPython will do the rest. Configuring a Plugin ===================== You can (via Options:Configure Plugins) edit the Plugin Source, or Create/Edit/Delete Index Files, which are simply lists of plugins to load when activated. You can edit Plugin Preferences via the Plugin Preferences menu. You can edit shortcuts or add items to the pop up menu or toolbar via the standard dialogs, for all plugins which support each feature. All changes to a plugin's source take effect the next time DrPython loads. Shortcuts, Preferences, etc are either immediate, or effective upon reload depending on the plugin. If a plugin is not loaded, you can still edit shortcuts and the pop up menu, but you will be unable to access the plugin functions unless the plugin is loaded. Uninstalling a Plugin ====================== Simply fire up the Uninstall Wizard. Creating a Plugin ================== NOTE: If you write your own plugin, please note that you can access the entire DrPython application (via the DrFrame instance). This means a plugin can make stuff not work right, or can access an internal function that may be changed in a future release. If you are adding a new component (such as a new menu item, and a new dialog), you should be fine. Naming Convention ------------------ If you want to distribute your plugin named *PluginName*, make sure that: 1. All needed files are in a zip file: *PluginName*-*Version*.zip 2. The main plugin file is named: *PluginName*.py 3. The install script, if any, is named *PluginName*.py.install 4. The index file, if any, is named: *PluginName*.idx The first thing you need to do is import the relevant wxWidgets modules (usually just "wx"). .. code-block:: Python import wx Next, you need to define the "Plugin" function. .. code-block:: Python def Plugin(DrFrame): DrFrame is the variable for the DrFrame in the DrPython program. It is the same variable as in DrScript. Now you can add something to the interface simply by using the underlying code in DrPython. To bind a function to an event, there are two ways. Let's take a look at the following code. .. code-block:: Python #Example Plugin import wx def Plugin(DrFrame): idum = DrFrame.GetNewId() DrFrame.viewmenu.Append(idum, "Lookit!"," I said Lookit!") def exampleFunction(event): DrFrame.ShowPrompt() DrFrame.txtPrompt.SetText("I'm looking.... Now what?") DrFrame.Bind(wx.EVT_MENU, exampleFunction, id=idum) DrFrame.AddToPopUpMenu("Lookit!", exampleFunction, 0) DrFrame.AddSeparatorToPopUpMenu(1) What this code does is the following. It adds an item to the viewmenu (you can grab the menu names by looking in the DrPython source: ``drpython.py``). DrFrame.GetNewId() makes sure a unique id number is returned. (You only need an id number if the wx Component you are adding requires one. You need one for menus). The second step to adding a menu is to use the DrFrame function. There are two necessary steps. The first is to define a function. If this function is going to access DrFrame, it must be defined within the Plugin function (which is only called once, when the plugin is loaded). The function you add must take one argument, ``event``. You can name them whatever you want. For example, ``MenuEvent`` the second will hold the wx Menu Event. Next, you must use the wxPython method Bind() to bind that function to the component you want. Consult the wxPython documentation for usage. Here is a brief summary of Bind(). | ``wxPythonWidget.Bind(wx.EVT_EVENTTYPE, Function, id=IdNumber)`` | The idNumber argument is optional (recommended if the eventtype in question allows it, check the wxWidgets documentation for that info). ``wx.EVT_EVENTTYPE`` is the event type (wxWidgets documentation for a list). Function is the function you are binding to the widget. Keyboard Shortcuts ------------------- To Tell DrPython to let a user access a function from keyboard shortcuts, the pop up menu, or the toolbar, you have several options. You can specify each separately (or choose only one or two methods), or you can specify all at once. .. code-block:: Python DrFrame.AddPluginFunction(NameOfTheCurrentPlugin, FunctionLabel, FunctionYouWantToAdd) Here is a brief code example. .. code-block:: Python DrFrame.AddPluginShortcutFunction("SearchInFiles", "Find In Files", OnFindInFiles) This will let the user add the function OnFindInFiles to keyboard shortcuts, the pop up menu, or the toolbar. For more info on what this means for each method, see below. To add a keyboard shortcut, you have two options. You can simply use "AddKeyEvent". It takes the following arguments. .. code-block:: Python DrFrame.AddKeyEvent(FunctionYouWantToAdd, Keycode, Control, Shift, Alt, Meta) The default for all modifier keys (Control, Shift, Alt, Meta) is 0 (do not use). Keycodes can be tricky. For both lowercase and uppercase, use the Python function ``ord()`` plus the uppercase letter. Add Shift=1 if you want to use uppercase. **Target**: Uppercase 'A' .. code-block:: Python DrFrame.AddKeyEvent(FunctionYouWantToAdd, ord('A'), 0, 1) **Target**: Lowercase 'a' .. code-block:: Python DrFrame.AddKeyEvent(FunctionYouWantToAdd, ord('A')) This will make the shortcut set in stone. If you want to let the user configure the shortcut: .. code-block:: Python DrFrame.AddPluginShortcutFunction(NameOfTheCurrentPlugin, FunctionLabel, FunctionYouWantToAdd) For example: .. code-block:: Python #Example Plugin #This file is called "examplenumber2.py" import wx def Plugin(DrFrame): idum = DrFrame.GetNewId() DrFrame.viewmenu.Append(idum, "Lookit!", " I said Lookit!") def exampleFunction(event): DrFrame.ShowMessage("I'm Looking Already!", "Result:") DrFrame.Bind(wx.EVT_MENU, exampleFunction, id=idum) DrFrame.AddPluginShortcutFunction("examplenumber2", "Example Function", exampleFunction) Now, you can open the customize shortcuts dialog, and select the "examplenumber2" plugin, to set the shortcut for the function "exampleFunction" you just added. Note the use of the ShowMessage function. Show message calls the drScrolledMessageDialog. DrFrame.ShowMessage(message, title) The drScrolledMessageDialog automatically displays a traceback if one exists. Pop up menu ------------ To allow the user to add to the pop up menu, use ``AddPluginPopUpMenuFunction``. .. code-block:: Python AddPluginPopUpMenuFunction(NameOfTheCurrentPlugin, FunctionLabel, FunctionYouWantToAdd) The NameOfTheCurrentPlugin is straightforward. This will allow the user to, via the PopUpMenu Dialog, add a Plugin Function to the PopUpMenu (with the label *FunctionLabel*). Notes: If you uninstall the plugin, you have to manually remove the item from the PopUpMenu list via the PopUpMenu Dialog. Each Plugin Item on the PopUpMenu is only loaded if that plugin is loaded. So if the plugin is loaded via index, when you load the plugin, the relevant item will show up on the PopUpMenu. Even if the plugin is not loaded, the item is on the PopUpMenu List. Toolbar -------- To allow the user to add to the ToolBar, use ``AddPluginToolBarFunction``. .. code-block:: Python AddPluginToolBarFunction(FunctionLabel, FunctionYouWantToAdd) This will allow the user to, via the Customize ToolBar Dialog, add a Plugin Function to the ToolBar (with the label *FunctionLabel*). Notes: If you uninstall the plugin, you have to manually remove the item from the ToolBar list via the ToolBar Dialog. Each Plugin Item on the ToolBar will be loaded no matter what, so be sure to remove the entry if you remove the plugin (if not, nothing will happen when you click the button.) To set icons, you have two options. One is to write an install script that installs the icons onto the user's harddrive, and then adds entries for each icon into the custom icon data file in the user's DrPython preferences directory. The other is to let the user set the icons manually. To add entries, you can either do so manually, or use the following built in functions. .. code-block:: Python AddPluginIcon(Label, LocationOf16x16File, LocationOf24x24File) .. code-block:: Python RemovePluginIcon(Label) Here is an example. .. code-block:: Python plugindir = DrFrame.GetPluginsDirectory() DrFrame.AddPluginIcon("Find In Files", "", plugindir + "/bitmaps/24/Find In Files.png") Assuming you have copied the icon file to the proper location (in this case, in the plugin directory ``plugindir/bitmaps/24/``), this will add an entry into the user's custom icon data file, so that if they have their toolbar set to 24x24, and they add the Find In Files item, it will display the "Find In Files.png" icon. This function is best called in a ``.install`` script. ``RemovePluginIcon`` is best called in the ``Uninstall`` function, and removes the entry in question from the custom icon data file. .. code-block:: Python DrFrame.RemovePluginIcon("Find In Files") Note: ``AddPluginIcon`` will overwrite any entries in the custom icon data file with the same label. Preferences ------------ If the you want to set and load preferences in your plugin, all you have to do to edit those preferences is define a function. .. code-block:: Python def OnPreferences(DrFrame): This function will be called (with DrFrame as the argument) from the Options menu. You can make your own Preferences Dialog, and have it launched from this function. About Dialog ------------- If you want to have an About dialog, or a Help dialog, use: .. code-block:: Python def OnAbout(DrFrame): .. code-block:: Python def OnHelp(DrFrame): This function will be called (with DrFrame as the argument) from the Help menu. You can make your own Dialog, and have it launched from this function. DrFrame Events --------------- DrPython defines a few wxPython events you can use in your plugins. They are: EVT_DRPY_DOCUMENT_CHANGED (Posted whenever the active document is changed). EVT_DRPY_FILE_OPENING (Posted at the start of DrFrame.OpenFile). EVT_DRPY_FILE_OPENED (Posted at the end of DrFrame.OpenFile). EVT_DRPY_FILE_SAVING (Posted at the start of DrFrame.SaveFile). EVT_DRPY_FILE_SAVED (Posted at the end of DrFrame.SaveFile). EVT_DRPY_FILE_CLOSING (Posted at the start of DrFrame.OnClose). EVT_DRPY_FILE_CLOSED (Posted at the end of DrFrame.OnClose). EVT_DRPY_NEW (Posted at the end of DrFrame.OnNew). EVT_DRPY_NEW_PROMPT (Posted at the end of DrFrame.OnNewPrompt). EVT_DRPY_PROMPT_GOTO (Posted when a line in the prompt output is double clicked (can be evaluated for goto). Usage is as below: .. code-block:: Python DrFrame.PBind(DrFrame.EVT_DRPY_FILE_OPENED, CustomFunction) That's it. Just bind the event to DrFrame. By default, no argument is passed to the function. (There is no need to call event.Skip()). You can change this as follows: .. code-block:: Python DrFrame.PBind(DrFrame.EVT_DRPY_FILE_OPENED, CustomFunction, None) This will result in CustomFunction(None). (The last argument is a tuple of arguments to pass to the function.) **IMPORTANT: You MUST Unbind the event if the function is a member of a deleted object.** For example: If you have: .. code-block:: Python DrFrame.PBind(DrFrame.EVT_DRPY_NEW, MyPanel.OnButtonPress, None) and you want to call .. code-block:: Python DrFrame.ClosePanel(MyPanel.Position, MyPanel.Index) You MUST call ``DrFrame.PUnbind((DrFrame.EVT_DRPY_NEW, MyPanel.OnButtonPress)`` first. DrFrame.PUnbind takes the same arguments as PBind, except you do not need the optional arguments bit. **Note: If a plugin runs code in OnNew, it is highly recommended that the plugin is loaded by default, rather than via an index. Otherwise things can be a bit complicated if multuiple documents are open when the plugin is loaded (you can always handle this in your plugin code, however).** Adding to Panels ----------------- Want to write a panel to access from the main window? Here is what the code looks like for the creation of a Panel. .. code-block:: Python if self.SourceBrowser is None: target, i = self.mainpanel.GetTargetNotebookPage(self.prefs.sourcebrowserpanel, "Source Browser") self.SourceBrowser = drSourceBrowserPanel(target, -1, self.prefs.sourcebrowserpanel, i) target.SetPanel(self.SourceBrowser) self.mainpanel.ShowPanel(self.prefs.sourcebrowserpanel, i) else: if not self.mainpanel.IsVisible(self.SourceBrowser.Position, self.SourceBrowser.Index): self.SourceBrowser.Browse() self.mainpanel.TogglePanel(self.SourceBrowser.Position, self.SourceBrowser.Index) So there are four steps to creating a side panel: Get the Target Notebook Page itself, and its index, - Create the Panel. - Set the Notebook page's Panel - Tell DrPython to Show the Panel. There are several important things to note: 1. ``GetTargetNotebookPage`` takes two arguments, the position (0 = Left, 1 = Right), and (optionally) the tab text for the target notebook. 2. ``GetTargetNotebookPage`` returns the page itself (the parent of the Panel you create), and the index. The Index and the Position (Left, Right) are how you access that specific panel. In this case, the last two arguments to ``drSourceBrowserPanel`` are the position and the index. 3. You need to call the target sash window's .SetPanel method to ensure the Panel you create is sized properly. 4. You need to call ``ShowPanel`` after newly creating a panel. 5. You have two options for toggling a panel. A. Simply call TogglePanel(Position, Index). B. Call ``ShowPanel(Position, Index, ShowThePanel=True)``. (ShowThePanel is a boolean, enabled by default.). If you choose B, you can use ``IsVisible(Position, Index)`` to determine if the Panel is showing. In this case, if the panel is going to be shown, DrPython refreshes the Source Browser. Here is the code for destroying the Panel. .. code-block:: Python def OnbtnClose(self, event): self.parent.PUnbind(self.parent.EVT_DRPY_DOCUMENT_CHANGED, self.OnbtnRefresh) self.parent.txtDocument.SourceBrowser = None self.panelparent.ClosePanel(self.Position, self.Index) ``ClosePanel(Position, Index)`` will destroy the panel completely, so any code after it will cause issues. This makes calling ``ClosePanel`` from code that gets called more than one (like ``wx.EVT_SIZE``) a bad idea. Also note that the SourceBrowser variable is set to None here. Closing a Panel does not automatically do this, so if you are using the value of variable holding the Panel in your code, be sure to set it to None before destroying the Panel itself. The full code can be found in the SourceBrowser code in the DrPython Core. Install/Uninstall Scripts ========================== DrPython provides a method for automatic install script execution. If you have a plugin named ``example.py``, a file named ``example.py.install`` in the same directory will be automatically run on install. Install Script --------------- An install script is especially useful if you have files you want to install to a specific location on the user's hard drive (eg, bitmaps for the toolbar). Here is an example. .. code-block:: Python #Example Plugin Install Script #This file is called "example.py.install" import wx, shutil, os, os.path def Install(DrFrame): d = wx.MessageDialog(DrFrame, "This will install some bitmaps for the Example plugin.\nAre you sure you want to proceed?", "Install Search In Files", wx.YES_NO | wx.ICON_QUESTION) answer = d.ShowModal() d.Destroy() if (answer == wx.ID_YES): cwd = os.getcwd() plugindir = DrFrame.GetPluginsDirectory() if not os.path.exists(plugindir + "/bitmaps"): os.mkdir(plugindir + "/bitmaps") if not os.path.exists(plugindir + "/bitmaps/16"): os.mkdir(plugindir + "/bitmaps/16") if not os.path.exists(plugindir + "/bitmaps/24"): os.mkdir(plugindir + "/bitmaps/24") shutil.copyfile(cwd + "/bitmaps/16/Example.png", plugindir + "/bitmaps/16/Example.png") shutil.copyfile(cwd + "/bitmaps/24/Example.png", plugindir + "/bitmaps/24/Example.png") DrFrame.AddPluginIcon("Example", plugindir + "/bitmaps/16/Example.png", plugindir + "/bitmaps/24/Example.png") return True Note the return statement. This determines the behaviour after your plugin install script exits. If you return ``True``, DrPython will continue to install the plugin. This is good if you just want to install some bitmaps, but otherwise want DrPython to handle the rest. Returning ``False`` will tell DrPython to halt the installation. This is good if you want to let the user cancel, or if you want to manually install the plugin yourself. Also note ``GetPluginsDirectory()``. This returns the user directory where plugins are stored once they are installed. Uninstall Script ----------------- If you want specific behaviour on uninstall, write a method in your plugin file called ``UnInstall``. .. code-block:: Python #Example Plugin import wx, os, os.path def UnInstall(DrFrame): plugindir = DrFrame.GetPluginsDirectory() if os.path.exists(plugindir + "/bitmaps/16/Example.png"): os.remove(plugindir + "/bitmaps/16/Example.png") if os.path.exists(plugindir + "/bitmaps/24/Example.png"): os.remove(plugindir + "/bitmaps/24/Example.png") DrFrame.RemovePluginIcon("Example") return True def Plugin(DrFrame): yadda yadda yadda... Again, note the return. ``UnInstall`` must take a DrFrame as the only argument. If this function returns ``True``, DrPython will continue with the rest of the uninstall process. If the function returns ``False``, DrPython will halt the uninstall. Useful Methods =============== Here are a few useful methods, and what they do: (They are all members of DrFrame) .. code-block:: Python Ask(question, title='DrPython') Asks a yes or no question, with an optional title. Returns True if the user selects 'Yes', False otherwise. .. code-block:: Python Execute(command, statustext='') Executes a raw command in the prompt, displaying optional statustext. .. code-block:: Python ExecutePython() Runs the python interpreter in the prompt. .. code-block:: Python ExecuteWithPython(command, statustext='', pythonargs='') Executes a command as an argument to python in the prompt, displaying optional statustext, and using optional additional arguments to the python interpreter (in addition to those set in preferences). .. code-block:: Python GetActiveSTC() Returns the active Styled Text Control (Document or Prompt). .. code-block:: Python GetAlreadyOpen() Returns a tuple of the filenames of each open Document. .. code-block:: Python GetNewId() Returns a new wx Id, making sure the value is not anywhere near constants used by drpython. .. code-block:: Python GetPluginsDirectory() Returns the directory where the user's plugins are stored. .. code-block:: Python GetPluginMenuLabel(plugin, functionlabel, menulabel='') You must first add the shortcuts with (DrFrame.AddPluginFunction or DrFrame.AddPluginShortcutFunction). Then use DrFrame.LoadShortcuts(plugin). When this function is called, it will return a properly formatted menu label that includes the corresponding shortcut. 'plugin' is the name of the plugin. 'functionlabel' is the label given in 'AddPluginFunction'. 'menulabel' (optional) lets you specify a specific label to append the shortcut to (like adding '...' or and Ampersand). .. code-block:: Python GetPreference(pref, key=None) Returns the value of preference 'pref', using the optional key 'key'. pref should be a string. key should be either a string or an integer as appropriate. .. code-block:: Python GetPreferencesDirectory() Returns the directory where the user's preferences, shortcuts, pop up menu, toolbar settings, etc, are stored. .. code-block:: Python LoadPluginShortcuts(plugin) If this is called within a plugin, it will load the shortcuts (useful if you need to get the shortcuts to display in the menu). Otherwise, it is automatically called during plugin initialization. It can only be called once for each plugin. .. code-block:: Python ShowMessage(msg, title='DrPython') Shows a message, with an optional title. If there are any tracebacks to be had, shows them too. .. code-block:: Python ShowPrompt(Visible=True) Either shows or hides the prompt. .. code-block:: Python ViewURLInBrowser(url) Shows the url in the default browser specified in preferences.drpython-3.11.1/documentation/thanks.txt0000644000175000017500000000236011150445515021156 0ustar dktrkranzdktrkranz================ Thank You ================ .. _Help: help.html .. _NorthStar: northstar.html Back to Help_ .. _Top: .. image:: montypythonMOLDoctor.jpg - To NorthStar_, the inspiration for this entire project. - To all the programmers/artists whose works have made this project possible. - To my Dad and my high school programming teacher for helping inspire a skill which has served me well in my current activities. - Thank you to my students at North Star. If not for you, I never would have thought of teaching programming, and never would have written this program. - Thanks to Robert Tate, for helping debug throughout the creation of 1.0.0. - Thank you to the users of this program. - Thanks to the supporters of this programmer, and of North Star. Your donations are greatly appreciated. - And thanks to Monty Python for inspiration (and being chill about me using their images.) As additional thanks, I exhort you to spend some quality time watching Monty Python's Flying Circus and their many quality films. - One more: Thanks to the Open Source Community, and the advocates of Free Software and Open Source. If not for you, I would not even have been able to afford a computer, let alone create this program. drpython-3.11.1/documentation/montypythonMOLDoctor.jpg0000644000175000017500000003732311150445515023771 0ustar dktrkranzdktrkranzÿØÿàJFIFÿþCreated with The GIMPÿÛC    $.' ",#(7),01444'9=82<.342ÿÛC  2!!22222222222222222222222222222222222222222222222222ÿÀQ"ÿÄÿÄG!1A"Q2aq‘¡#BR±Á3b$%4r’Ñáð5S‚ñCsDT£²ÂÿÄÿÄ&!1AQaq"2RÿÚ ?ô=€ŒqŸ¥q¢=ó×°£²÷jJ29PhU`Œ`ã“H®4MйŒž…k$5°eNÓŒ~4ݪF6øQ”piÅALQhÖÈÁ2NH¤@ 1ÏB €1ø×BwÈ÷¥â`}9hÅp®w0±ÓŠ6Â28ç·½s`(0pGZÔh €WœäòqN8v;ôÍs`U'5lXR:ÓV4Î öÅ ¬Ø$Æxì£;Z lmƒ’Þ#À@GjÜ£=ñò©aO«¦}4b§±ûMìƒ÷q_æoŸoŸ©A¡Y-åÎ$¹pM­»§»Ãæ“O}¯êÃ×ç]ÎÙäð>cØ tos«ê°¨‘ÚââP7ã'qïÖ¾ŽÐô«mE·°µP#y Q=Xþ9¯#ðþ‹—‰t{$Är]K!ë¸.÷­ç¬®>á­<^]FÒÊçýÕœŸ1ºóÏJ±Ôõ[-J}Fû?ûP޳0è1õ¯Õõ}KÄúÏšêÓ\ÎÛ"…H`=†>Y©ÎK¤¶2þóPñ.µµÜÝÜ6„|¾€JômÀãE±o.ñ^îE 4›;ûì:U§ƒ|!…íY±.§0dƒƒùE_”ã‚Hà¿:1ÆêØR2ÚFœñxÊu”ªm±Áe*oËÇ‘øÖ ÄZ·í}bæí#f+ÿ àÃó¯AñLë¦øQº±w|‰gøÿBkÊäqÐ}³ÛéýÅNÔgŽîI,Ò¦óJ¡BÑï…±ÎÐAg5Ì’¸ úS"¿µ½w{eaÆI#$Ñ@Vl)<üë¯b0~Y$uéÐS¶ÓÔ«298ÇÖ“:äsÎ?…f@ÈcÛ<×1´’VŠcôëŽÆ“sœóŒÐMØ@”,¹Â?ìÓ¼™€­’æƒ5JåqÓwå¿hWM'‰D[ÀH­À îk×>í0>¨_oOjñE;x¾úVðùuÛ´Ö‚ds&DµÓü»8ï.çŽñ¹Õ›–úTYuiµ¼« ÑÛñ¨çõ]xð$®óFgq€¡ŸÓŸ¥[iºEÞ¨[¬ÛÚã)~œÒO%Å‚Sdd–Ãï Zß_8<ºœÔæmVDP4e*8Û$»H¢·µµ´ˆEiÊ5!6žß¥Aç~FÇA+“1Ò¤‘°7:DÑxåóü+ˆèùòfG9ÿ Îò­Ð|¼`œûqQî4-:ù?} ç³*í#ñ§–×`Ÿñ©«‹2¡£bûäŒC¹‚D;¶‚t=jÖï÷¶ª^Ù¾÷þœ¼¸ùïU‘LÊYe ñDàåk¢£3ÍÍãOäŠîH*{T)<ʼn¶¨Ü>*µ™UðÀ …:(F#Ьº"´Hðµì6ÚõœÓn‰}ÿöxJÈÁç8Áb¼ ÑÕ% žEzF™ãk¤Ò­aÓ4=6òXãÚï!;¿ø©èìÃ3v Y#rî=9Ÿwg¥é¯¨ß¸KH¤Á™‡aXÏümâ¼ hÚ¿ÿ“ÿ ¬Ï‰®õýXÅ5ì¶Œ¡‰XmÝB¯à3ýhK-i#¥½µÿj>)Ö•Änò»ì¶µNª§ ßõ¯LðWƒ¢ðõ¨º¼ ú´Ãpqö_ïõ¯9ðÄiPß¶£ios‚Q g¦GJö«yVKhÛ9Ü¡²s’O^{ÒÁnÙ¡²C+`·L tê}è ÿ<‘KÌÎî>tØããž•ÒúÁ}¡\³KgoÕUYñó'þ•…-øgšÕøôç]Lr sY&ùb¸òvJöw4«”ªf³Ô´/èV–s-æ±/æãc#{x« |oáHY2rq1þ¢¼NsšMÎO«<a’Ü÷cçTrÞ‰&{%ÏÚG†àšss.ÒUZ=«»çÍfGÛ«*‡Ò,6—#q#õ¯>ûÕ²29Œ¸R9«‰/­&i z$È:ùgž=ëscYèr}ªhà+M»”í~ôªóíÁ¢é¾>›[˜Á¦ø|3ÞÍ%פsŽ›k˵[Û¿gµÒÂ?-t„ü@ry?÷ŠPê“Úé©=±h%Yãn£ÿZW'ö7«=ªÛ^i\-Í­µ£ƒêYA#Ü{W5jâÇD¹½°›Ožx8‹îõw¯ý¥>¡(žîv–R c׊ì»Ab¤‚A#ç\²Ë%#ÑŽ8O®ÍÛý x­ÕžÞÑ|µ's%¨*¿.µ['Ú7Š]†n¶ûm·E8þµ…w‰ R1Ü)8ÿ¼æ»÷ÀO ÷äWL^¬ó¦éѱoø¢SΣr>·úQ¤ñGˆå½Jôçù®ún¬±¼ÛñL:ß'S7û«Y “RÕ¤fw¼v=74ÜÌš«:'më-ôë´¸lí•@³|øˆ± }G¡Ii#ÜÝI7£ØëEÉ 8¶Ãh–s__«ÊKÔ|ëÓ-íÞ4A|'µe<l<¹îä8Œ`/gªê²‰?Ñ¥#=p+Ÿ#mø”aÚXrx1óÅ€¯!˜üóXÿÛ×p¸ÈÞ3WZwˆDíµ×ö©ñgT'h¼@ÛO¨ÓјWçL[…|àƒÅtò/¶)Yf•hŸŽAÏÊ jÚ]–©YD7?ÅAÎ~ue#fs“\h†7 ƒÜÑÉÄYbŒÕ4y­ÒËerÖׄ«öoFî ïŒzÛø–Â+Í&V+™¢õ)…yð ŒúƒÈ÷¯CW%³ÂòüeŠVˆ³Â!šDQß4kI&´ŽVvÛ/]ØÅrá³vP†oVßìóE†òöêæâÚ)¡Ÿ|ü±VjÎh[t`R‰”ƒ*:eû{ÑVô¼`¦v gô4V6"¬Z]„ayô[ þÕŽûCðÔw¶ƒU²· Å­ãv¾äòNØ}ÿ÷j—ØöÖMbå×åêMzì®,•l“Æ)þûC©4´Ì\d\fÔdos.?µJ_³C‚ÚlÒ|ä¹üˆ­h OÃÖ›¸7ŠÇÒMögãð/„¢åt̳œýy©‹áßZF͇aŒg-œ~`Õ“ ž­qIãëEÆ(óOjì%Žem#1@oÄ óÛÙRWhõ<`f½oZÐ-3Qºa™6„ŒûÖ¼óCÒŽ§®CA夙|û âÊ’z)Û-­íŽŸáØ DõœøóY»»[«†!™’<ü`VæâFIÙbrã±ÅUO , óÕq\ܶu¼M£Ÿ×pÅ»ÜÓáÁ'–ìC+c85£h|©7·Ž¸ Éo²†ÆX÷÷§ä˜#‰¦M´’a äc­maíØ€NEZÚ©ŠÕÔ/;yúÖZþÆàÊYX{ ’Û¢ó”’,í|[5¼™‘7©?ÃW±x–Þèkgâ"°YI$û"+wëSíiZ†É“Ûš2Æ–ÉG$¬Ü\¿nÜçrí$W™K*Áy-»’íϽzU†×ÓÀ9,¢¼óV†6Ôç9Ëž;Søò©h—˜¹FÙÇ1ÎÈÊw?Ç¿jö/ iEÐá‚LyÎL’¾ýåŠÇýšèP\E.­p†@²…·±ÀÜ¥zPmŘŸWÈW£láÇ ØðÃíŠ~cxÚ7Uhä`{Š ??Ò’äç{{Óò+èñ¿xu´ažöy[t'/~+{à¿HX'oôËeÚ}Ý}Í[ëÚ4Zî‘%³cÌPZì}«Æ¬/nü-¯¬ a£}²ЯqR’ر{=»b“Û#½3’<Ƹ4;{è/­`º·;¢˜nž~”L`“Î3ŠdÊ5[!©éÚ;î,¥—#ø…y;öÈ?x=-ǵ{í‡wqò¯<ñ†’l¯…ô`ù3óô59«Ø­™ã×¥*á°=©T¨³xYhêÞ\Y Fí¼žz¾<{Õ†˜&Œ™àŸz¼$·NžõÓÄô=Hnª œ‚ ÆF+VúÜòj×6ZiV¹Ì8çÚµÒ4»¹Ç%mßóÇ•ýÃêQº<€GËŸëFF·M6ÃM·ûªÂ#ØÁR£wn1RßÒ= sŽŸ­BÓPÁ¥ÚÄܱ àûóSrJWéâÂp8bœ’£““CãqÀêinp01ގƒ0Ú~#×ÅuÜW*Gr{Sò88®BúqŽõ¬6qÝ@ÆåÇn)Û‡| Fp=\ñHg€Ã§,P‘‘[âQ éï1þfUoP¬–c‡šªÀË rqšºñ\ö¨úš»4Ž« ŒàvªY¦X´ØM„eÜ9Ípù ­˜+‰)î㳉–%C#p_½T<‹ÔŸQêqÖ KvK»¥®w¡ à×6θM$IžâluíBˆG$™8éUÒI±•ˆÝ·œQmµ˜É*ö¦3Øã­¤8¶h¼½¶¹ã&«îí O2>Ýhöú³Á¶FÚÇüØ¡I|¶×Š<ÀÊi-5*+ µ„Üï!AБÍHmYî…ÄM—oˆcþ•¡¶ŽÚì¹Í`!ÎhùS<ŒO…U­âûµ£¬§ ƒšómE³¨H=E `‘í^w+‹Ivã%OQT'Ãñ®÷Òê^BÀ£‰Ò#“7HÜx0À<1i¼Rƨ%‡V÷«üœc‚1Æ*.‡I³„î8ˆ|^õ$Žzý+ÓÆíRBÉ÷Í,ƒÔ`SU°O5Ó+GnÞôß¡­‡àž:b°¿h~[ˆŽ«l«¸ KŸÆ· w.A÷=¾TÉV9ch¥]ñÈ6¸¡-£4yŸÙÿˆ<›Ù7 Çt%ŽB°öúô¯J+·*C)ãµxω´Y¼=«år¾øXvEzO†õÅÖôd•ïãeÇSó©Å´Æ‰v7Np;Ô{ëu+)-&Yå?*)cŒ¨Èé]'¥POg—]h:”RD-ÝÂQÁ«Õ<ÆöæÝiRS5°^oõ2™f«…a°¨½Rxt/ìX²qÉ«…ˆçÑlR£,Á&ŒØ"ª~öÖ®DÇ ŸŒÕŒ •É®‹q’_{•ÂÒ.›dEž×)"?û­C•%$`>µ7ö]£œùf2yÊF]*\»Ì¯ž¡èZA²ztwZ`[?*tÖñ qÇæp/ôõß=Ÿîz‹‘P[W‚l”ÝŸb1ZÏ”M.•rêÁIè1Z4‘'‰ÕÏ VOºc Æ@aÞ´ÓJ’*23£]¢¶I'd`ÛÍ?EӘɰ¡hÕ·sõ®Ú&öÝÎ;‘Z%DˆÌF7úWŽ*˜±ób¹ñ‹d’ß¼èM;·1#ÓN Écž˜Í0íÉÏJõiF4y’w+§=²«Åp0,: ûŒ×Q€#¿Ê¹¹IaÉÁþÈùPé-Á†7=ø¦3g ðâºÄ·,ȨÇç\ŒÔ)üM¢oItP<ôѽë̼5¬Káít, ¬R7—(cŠö@vÈ9ŠóŸ´ G(ÔíynxE8¤qa7êñž¨ÊîW¨ëO9åX¿ëâûOmÄ™žß˜É<•­¡$±Èý+D×gNsJ»øf•0@øxìÑ ìÆ¬ÃaB“Œ¶.?½ctÿ.g¯ÝCísSŽ,£Œù–²O'\2Üœtä€ ªÝ7÷Þ$s€Dq¹Èé“íùQuK¡s¯ä « „‘í»/ËFÔìì¯î^î_,¹Ú¿J.–Àhœt<Šè#î*µ5Í%ˆÛ| r9!u ~ØÕ±AI}ŒI,pI\æº <ô†—ä·7ÑÅÛéelôƒŠmqì5CXEsqà`šyIrA„ŒpiÃâSÓÚ€N.FpE4ƒÆ ¤ÌGËë\bÀ‚HÇÖ™‚( µ–ñR«H£>¢¼Öœ0+ŸoeüI(i¥™ª˜ÄB„ªŽ3Öº æžÍå³) š8À®)#ª-õŸÂ‹2Ö Ñ*tl¬>GÊ‘Šüœó%1Œö¨qÇ·!× ÍY8;NÜý3QæAåÀü¹¦ Í¦ˆ(±@£o ~•&)‹Þ¢2„Áaô©ú5©Ôuâç` ±ùPPäè’=3H»x¡¸ûà†'_R…É5¡ãTÈ!zÆ~uÅÂÆ…_Hϵ#מ8ì+¿5d%•ÉÑ eÀž´>Üš{íLÈãFì“3c<‚:RÞ RFAýk¼œ®iœŒsK@#’3Ó5ÖØ_¨¦ ±9çå]RXxÇZcŒ½ò(W6°ÞÚÉo0Ìr.ŽôG W4”ú¸ÏNqFÃZ<{VÓ/¼#­%ÊbVÝŸ ‘ìOéZ¿þ£ÛÏs›}4E  ,NŽpÞÕ´š(.-ÞÞæžRE ? ÎÜ}Ÿøfy7¥½Õ©Èâ ðáHã[о9Am¾>wB•&û7ðàb<ýP|¼ñÿ*T*F¦+û x#I´ë–p]ƒD‚ïF¼š(ÆpÓ:džC‘¹€öùÕ¾žîŒœîjãITý±nÓcb•ò…RGê)é“*/çYõvw\få¡È÷ªh?bÜ7×Ëìw"‰ Ä’èÂîF-%Éi¤9êXäË:ÆÆ ,#ymbwa’Jf‰’dÙšLƒ÷z¤ {‚E5¼?npcÔ!o” µ:E“~å8ì1ýè/ éÍÿéBŸpÄz^2úCQxràçËvÃçûÒýƒª¦<¶“å-ý¨ÍáË2r úJÜ~µÏØ 8Žú鯩Á©­Æ½ -n÷û³5;ï~!ˆ°ógã¹Ó×H¸Œº­Þ~déÓõD^lãëÅ*[0Å×|E`ÈÌó­|U¬Æ2ÞVGº ^^¹ ûVÝÔ< Óí´ó,$U똀4hÔêè†Ö$õÙƒPu[†•¤,=Dîǵu5Gûìº[«’bŒ΢j3‰áÁéQÈÚ{:±GE[1x8#­B`Áùâ‹#êÆsÍ7ÌI1ꆬŒ½ K†õ”à±úTb£RD@pM+TLºŽô1Í8ɸýGAUñ²(O=¨à³äœäx ³™úsí[]N}žæžQÏÈ{U‡j³êq· ±‚ç5³bwcŒ|…_ Wdò:¼/ã¯ÒžOÌ îà:S7/ P<êýéìë×ß®k˜±ŽÔÃ08Ëw®gä:÷ ØDN@óÞ‘Áë\Î_µq‡&€IÉ‘'¶ïó®qÓõ¤wu=èîx#ÕÒqÓŠbì •H[iå?ß©¢2íÏ$ãó®¸?!×èjréëÀ’VÀ_zËkÒ7íIaŠGHP€O~õ®†¦û.|ÏóøéVL€NK±úšT¼…¢÷NŒþζÇòT‰æº>¯2æGc$kõr…eéÒ­pqˆ€?Ö¨#»’òÃVl‡Ž[¨->çö§otKЮ€ƒNŽ!ŠŠèXõçŽ!–„*œâ£ë2=±ÅQ E¼¾3PÍ).ƒf¥|Mo¼‰àüA©é­éÜbd¢Œšòë›°gm²8"‡g¨Ï£,2vœpxæ’É{Mt_jŸkBퟣ©`~;† ÇÐVzOµ i‰Ü!D'-ÿcUž"Ò%´¹yÕÇ!ÈÛYÆIX¬¹=œöï³lŸhš¬’î:«ì=ãLÉj}·Žµ¿3FÚPzf5ýEyÚÚJØÜNôQbøè¿•…—ìõÛ^‘›‘i0Ç,$PGášÕGwoqbŒmòdÈÈýkÀ4ý)¦¿†Ü®ß:E‹ójú'G°Q#GÃ$Hª2aŠìñ¡\˜ñeMÔQ41‹Xciõ2XÕ&¡Ø$A…=ÁþÍzAҭ؆h#Šè6ŒwDΧ¸`ö£“ÄÃ7ìé†IÇ£ÈnLcâqQŒŠ–årqƒ^¹?‡p2É"ŽßúTðj.¶ª9ø•ۊ矃þ²æÿ¤yˆ•ѰÊH§:u÷¾¹ðfcô¸ ØÈ þ¤Õ%Ï„ïíg€ºõ&/ù\òñ²D¤em žØ« xžF @U=i¬ !Ô°þØ#ðgHê6&sס%Dzê ôh<;¦I»Î°³);rjµùiSŸˆŸÊ³uã%ù„ÎW’µh˜‡ î݆ö<×v(Ã…œ™^èàž'r»˜ã¸^ãNä’8À=M"ù!wqÏt®qŽ(´—DDÄnâ—#âÍ4F ®‚ æ”"ÏNÕÌînãA»a÷i}[8¡@bæBNÑA…à°¢(ˆíÜ:u FH-Š’àc¨÷Å#vV1D”r¸ª?­sqž ޏQßð5!A €­ÏSŠÊT=PeË‘úVS•fÔ®\ËŸÓŠÛÏs  Ý4ñGƒŸ[Çõ¯;Þ×39…Kå‰ÊMìY1n4ªXÒ¯˜¶!žÅ©P¡,™{1·ðäDcq‰üª§M³–ÛÃzb® —7“]0Ç@hýsVÚ˜Q¡D ,‘ý~ÿ5›káŽ1™£Œ¢î=3×õÍY&öräÊ¢©“åx$¾U¸ŠIaœF;væ©ïí-fŸ÷V² Ï˜tüêÕn`Ô<¢ãÊnŸQS&ºIã"©=Ȫ|j]œ3Ï“ï@~ᵉRTÀgûЦ±ó€cp¯]È(êÈÞ¦¸\`y¤H“7§<MÆ+ÑçÛ`­`,‡Mºž)a¸áX§ømÚª@¸Ve76îÊJò=»Õ¬ÑK D‹)Í-Nßýgp7® ïKJôR3mhWãˆÒÝñìøþÕm3R­ˆ?5UóB@ÎNOSQ$VRpß­ge‘t2Û[±’êÒTEž=Þ‚F3ò¯£4ý="šm úÜ·ÂG^E|ðí0ÃïÍzî•ö‹§¥¹ž)Œ¾Z‰#°3ýS¥HëÅ+ìÜýßk9k¾C‚0W8Î:dT'ÄZV¶ ³ºAÖ2pGüêÔ+`zOÏ€hò~ÎÈ€xXv!~|ÐÄ›Hù⦯,ÙV·ÉñØ¢§zËs·ÒÜS…¼ÈB3ß8ÿ¥GRRSíSr6)gø¢Þ‰ez˜Èí Ïô"©æð•ºneóðÄì@ü2?½iQ[±ÈúQ‹í_íRu-=†äºgš_ø{TŽpñùrEóX~µ*ÍåŠÍžë"8Î ›Òz !ê{b±>8+‡5ƒnV2! ÷ÈÇ隦5ª'’N¶+«YFc»·s×"AÒžIá•¿ÝÁ¯“S»µ™ocÈã·÷«m'ÅïêÎ̸öcPÖÑ%’eÝÎHÇÖ¸Kf©4mz×V"Uó±ÈcÉúU¾áŽ7q×päP±Ô¬ëP –< @ŽYÄk‘ñšmÜ1_C峺óÃÆp߬ž©á Oc=¦ ×JOør¶ÿ4’¾ÐÊTi®|A£X©óõwgáFÜj¶çí'G·$[[ÜÜœíò¯:»³¹µ˜ÇsÂÀze¥—ŸtªN3ÔÿÙ©·!¹³s7Ú.«0Ûgomn=Ê—#òª{{ÄZƒŸR”)þOOåŠäVk+· t9®ù{Xö#Þµ?a¶ÙyÝ#¼îäœÕ‚ÊøIO¥@‹ çÔ°NÀsÖŠ0c+dò:T<û©ö`ºî²…`†6Pß\Y+›¢—j ï×4Ë©†G9õTEÎD‹ÔpjëG‘)svyÿÖ0ú‡5pÓm…Žåã¦k+4»¯­\ã†3ZA2(ÚU[-ÓÉšQ²É<ƒ-P:ÑLmɑ êXÒ“Q;AoîäÔVF™ó82úSi“ô딥¸Œ4ˆ “Á5âyžöwvóœôãåR4È‘æiÝvàÞíÚ¢ì2ÜHç g“×=i}ÒÙ#–Üh.„é£K,Ã,àŸ­WͬG» €Vm˜¤Œ¦«É §#Ú£>¥æ‘ùS­”ß]Eo ýìŒ2{Ò9$[oEŸ…´ýGQ×]2Soä°yîÉôªûW»Z\ÝÞ¡$ì…x ÆùŽüõ¬n™-Œp }×9wïœSî|Du2íÝ…PFʹ2e•žæuß0d…l}+QŠü:ßþñ?à4ªÜÇÂ:U¸€ñû”nǸ¨²ìh$ô¨ñ^:.×>“Í)X4lGz«<¨ÄƒÝ4<àFô{‹Õc•sœž•z.0xÍDxØL7Ö(•šKö $þ5=u7;F½R@»"_ëO’Vž(© ã³R÷ÀiaØz~ ½Q\êÒD`ð8ÇÏ­ù¥‹I³·/‚yqUˆ ˜ùÐÛf¤…™¦9mÀrÚŽ»‰æŒçšîH n «bÚ{Ö—ÁÚq¹¿–ç“ œã‚k8Hüë[áýj+mØÄ…di2ì:ŸûÅG"£§ÇIHÜÛ[[ßEºúöh ODIÃûŸÃš-®á˜.¼ÓûBg<<Àúu¬ƒjoÑŒÓÆ9­È¬3†çâŒ×¥^aT½ž‰wa ^Æà•ÆBdU\>'’ †‚WÀÆÖ<Ô ]oÌ[ÔHéž•lÚ¾¯jn\lp2¿ZK²ëH—u|×vâUSè_³YŸø§Äžžºùog"a È9>õfl/¬"%Ô@HÛ>úzÿZÅx—ÄÒj6I§€­äHÙqÆOçò5o’–Ž_.qQÙžÔ|Uâ=P¿Þ5ŒÙ*¤ ðÆýÖÄBOVíï’OãH®T‚3\EPv„è=ëÐ.ìñžWeÍέ5ä c^êŒgŽ ÷¡FÇ Z6Þ˜Œœ™'+œ çð©{PbNrhÃ!Ž(¢lš²(\bšÓ` PUŽÑ]9b8¬(hÔݜ緵c³¬‘²'VhqFÀðH ÐÊ@#­7@Mú.´ÝjRËizÙ$ú?B{Õ½Ëf"?ˆuÁ¬{:]!ó0Sç¨úTë EÞÒE“-,$)8çolÔ¾=¸³ê™ß0yŒóš¿‚î­bÝqãùºVZïr"°en~•’½žELy®{Ô§q:á5#Ö†©b§~·äç—®ON þßmÿ5âÍw ]¾cõìjE„áå,Xʪ„á˜õÔù69ìWÓA?ëãjUäÐ\Í4*à¢ü8<~´«lÅs¨eëê¡Ç)ÎÒhìªz‘+ ¡Ã é£ÍUtê?@aØæ¡•&íO½Nf-£@‚<Üò.iXè”ÞžÎ)°#MwãÒfµ¤9©6P7Þ”ç5ª¶*vþVžñ•¾á~”½)¤Ýu'áøSíäõ¢€<0Ï4že­ÖÇå\xl*#ŒëƒŒç¹­_ƒÊ?Þå | þ±â>1^¢Ø;E²&,»ƒ#Ÿ|ôþ•3«¦ 9êGZ›s§n· ¨'`T8QnoÿzÛIè+EsË 9ÂŽ1\³G¥£¡Ý¬³Büí8äÖþÇUª=8^Õ„±·C{q) sÐÕç˜Ð z’*j%T¨³ÖÎâT,­åvŠòÆ`îIžI'¹¯L´a9dÀoCC^e)Ù+!lm$qõ5×Qçy¶ö// È∪«Ðm oöÉ¢v×R<ÆHP)ãnECóJÓÅÁ‘DRpwQDQùT(ïPd*lG*€¯œQLV˜E\SÆÕå#µtqÒšÌs€yïL/àêÈß¼ƒÜbŠgVPKpÜ®žà†À'ËyFÖIÏ5‘¨°·leG*.ÒQ ê2²©SP"#ËÏóO‚uIä î_¥kKcÁ>aL£ Ç’ d¯d90c‚zcÚµspë·Ø`{sYÝ@ùw€/•×ø×"¥šš:°Å©æà„ä©ïÓòïRb¸7¶¢Ÿ)¸Aî¡ýà%Ñc ÀÏ+øS¤½ *»Bƒ»oÊÑÜú£,0¬j€žß:TÓ5ªq÷5ÿˆÒ¡³#&—N”òA)Ž+­lûp¹Æ3Òi(05.Aéùb«lº8ƒ -Kª§è¶rÎH ±•÷j„Äï ”y[£Qþ,Ùoý½?\ÐTÆÆ6ŽrN=«»CŸUup{äSȵ:9·µ ñƒò¢tíùw©Ú]ýøÖÝäV`€…ã'Þ–CB.NƒxsB¾×µˆmímÙÑ<­· (æ½]‘­ÐÆƹÂéÇNÔ-A“¶²ÁqBõýYó]Hàtâu=õÌJ—2ùÊINò?÷ÍsÍÑéâ±iVÉæ,‡–<Õ¶£)ŽÉÉãŽ9¨6(#PàlSu©ÀÓäõPnθ­ÚOÁ»ù‰5>å܉èj»J @ƒ8ÈÍhl4ÖÔÛ(€<ÈÃô ²Ò¥BC€ìØà¾õ–ñÆ•m¥kî‘DbI0íÓûW«ÙXÚØ‚‘ÎHÝ!^[ßô©Z‹ÚM¦Ï Í¢\©‰‚¡MÍžØ=«¯¤rf$|ñ±àGΈ¬GQR5[ý*àG¨ióÛ#äÄ$R=>ÔÃó«£Ì”Z{tÆÁ¤±¡ç"hýFÕÇΙt#{>!D\žÈ8ÍK¶Ò庌²€ –cÅll¾Í¤k«i?jA-³Æ&ˆ3Ÿå ÃæÌö‹á-[Z½Š8í&Hœƒç:»~µìFÌxsÃÂÛIH³kû¬™2‡ôgm|m¬R̰ m¥V½æd*HÆ6à€ÒÉž†b©I›“º ’¨+Ž;b˜ñ•$îÎ{Q®@ƒÆÏ̤Ñî^ôI݈òAÈùT[¨0Ùõ©$yg½2^Fîk ˆ^aÀWv‘Û:…±DÚ9®\·—oq’ÜÒ5CXRßzmŠÌ¨:ã½IŒ,~ˆÀ{Pa);Ux÷¢ÛÏ’h 6J&‰ ðI¸Ç½<ž(ÑÄ® çðª"m–6nÕ” ²61ò­Í‡û¾ÁÚ°šr»]’qêzÝiçPôŽ•‡~ ¢‹^·•æZ±óYAa™ª3CÔu —µHVi_„²ûŸjÚê1 ŒÌTúFâ¯4SHÓ Ñ &¸#Ÿå…rð¹ŒâdÓìšõP Þy!%Hüýêo–AÇqOX`/®š˜¯Ga½F%鎣µ4âÞ]ÈÞdMЯj´*NÑߥu#•IÀÍ…°ÎD©½@ü(2Rˆ"xŸÌTô7ľÕÝ ¡ÆqÛéDÄ%ီÊcy1åk¸Ì˜éQÑ‹ÎÄ{õ ÇŠ&D»Ïoz–Šà CwCEÜyuÅ,®Â(ä`gа >õÎh¼¼ØÍâ]«Œ²•#VL‹餞 ÉÓÞ¶Ús²‡`cmaœ™m­0ppx'õ­‰ªBZ+)X,Ê=<õ4’Ú:ðÊ´j-m£¸£®P)f*—ª8’h]¡JoûËgHabN$fÆ·z ìªe8åHý(.ŽþT€AsºozUS'˜²0^™â•ò£É®ÇS’AùQR&g>ž(Ñ)4ƒÆCÚÂȹdlý*6¤ÏûA6®B`Þ¦¬aÃm©z˜5oØBêZ(Ç›#Ð'#õ­%¢¸®STzZIŸj³3;¤Cs7¹ãaœÍXjb[™KÇ&%ŠcÈþõV/„cdŠr?O•%ž’UØ6cÅ*¦Yåµb§¡¥B†Ñâ6ß5"yw2¢÷¨1I°æŠÇ“€Fy¢™Å™‘Ù\ù#¦ YK¶âÄžç=i¥Á gµ ÎF{ ÍHÓÏ4X°°)Hæ¢ç|Ø;Ô¢{cÓJ½$ŽiÜ9¡’r)éËb˜gϤTYæ( Ýê4Y ÜzUp>|å¹ö ÍDÛ|ç'š’0O4Ô)%jF7bç9æ†Ñ‚Ùb@ÏÕ=)¨@$‹ÒqUÓ¡F8«¼Qn-÷ÆHëAĤfBŽRÊM9Ù ðj6Ò¤ QTƒ×?*Cé–+'c<Óã•£“*qP’FÆ£n$ (›‰{‹tžž\u¥å°É#Š¥ŠW‚MÊØ«›mM$]y§S%(±ÎÐ1iÑLð°V%£?¥HóáÈ;E/2(Ï8§BšgŒ£ ©}ªŽæÚâÕÖ0„¯ðœõ¢ˆÀ:Pö¨zŽž5)IIÌ[~´4eL¢qrOÓÚ„Æám¬éÅJ›IÖìå>\þbÝh)-䲿÷nö¦Ó,šh™k«(õtæ®íõäȨ1X[ßDœL½ø¨o5”ø ©ó£'(¦hÅÊ Þ™­—‚Ù!¼ºŢly?ËÞ¼ì1‘ #µl<ÒßÏ}€â˜¯©7‘¤ºüDöÙ,¾ñ8/(^N=ýªZµ¤ Ë$eà¾i³L±@nN~/gHôôK*€®¨£¢ûR¬ÛÜM#—ó1“œR¥° ‚ºîO©©Ÿzë´–sdV†Aëɦ9À&œ[?J ³ ¯%«YÎrÜ’å»T†?*ChãŽ~´éΰ=œ&Ÿî'ÚƒœQî&#е¬q÷s™[jü4KxV0(ð`Ç5<¼XW­éDWäq@Þ[§Z@L{V–ÅOZJàšŽ©!±áÿ0üh‹Ä9Îy®2‚1Šj™†­X0á¹ö¦@ª+ç„ÈÍDVõU»&àj Ðì'çA•ƒ9´€4HÝßkl'ŽÔ_—jP½’ƒH ƒŽÔÄp)Ùæ²—ÐË“KcìAª‰ÈüjD&1±¹AßÚ:VXFØ$ž>U:&`ûÕb0f,#" ú اL”‘b¯´…È_ªXAsFT•·L{PneÄyçÒh½‚e%̶_,¹ÇãZ†h/ AÙ‡ZÎ_Û‰#.§‚(º-áx¼ŒK¥Ii”’µeÀ°`0„2|«Aá¹n-n$HSJn=”üUœêFÖ!«K¢<±Æf‘Ô»qŸ•4ž‡ñ×ö4ÓÊ-ŽÜª=+ŸÖ«e½’Gýã’OéQîœýãs6ãÚ£I/«qÅIÉž–a<““ïšU[÷)RÙ¬ó8®Hx§ ®H>TQÏ?/jiQž•Ó×ÖqøÑ9ëcÃíé\'çÍ3pš%Ó1*ƒŸz Œm†’A´…ëB†=ÌYºâ›f ±¥ÆªU»Ðè=´D©lQ‚ã4Üb1ƒÞœc†Á¢‰±ëÓ·åDAùW w#ëNPƒš"&9·c fº­œ‹øÒ k¸Æüd€ÙÖØÃáPi„¯þ˜§çã_ÄWv¹õ  £@°`†àŒÑR1FÛž ÓpÃŽM+2®X¶+‘Ë»ÒÕ>xï"ªfS’JVQ2z:~”î½F‚`ëȩڲ§µ,î*i5ÖÏ9¦2$[¹lðx©‰œc ¨ ìDÚO5.''éž)“D¤‘†y¥.Z“E~SçŠq1ºª€ûž¡¹z1æ­æ!ÇñTK…äsƒHÇL»·ýñÊò>¼V–"TPù?µgü?ÔÇ3lf{Ž•ak¨}êçnübESцýsRlêà Ùe4û£Sßåâ˜e>#ŽÕW,!è(6tk¸óJªÊNNGJT¶jfqi“v¥J˜”ºCn´©V À\‡QbëJ•àO £ÅýéR¬$»&w®'ZT¨¢R:S’•*"4ôëJ•<@ÎŽô—­*TÌQý郧ãJ•MŽÍÐÕ=ÇV¥J•”‡`­:šœ:R¥X2:Ò?ÅJ•? }*D)R¦BH”hÍðR¥N!~Æ£Ëþ×øR¥HƇfûì—ÿ4o÷$þ•D?ó«ïÿ3ÿZTª/³¿DÑÒ˜>)?Ý¥J„ŠŠ/ðÅ*T©G?ÿÙdrpython-3.11.1/documentation/preferences.html0000644000175000017500000013317711150445515022327 0ustar dktrkranzdktrkranz Preferences

Preferences

Back to Help

There are several things you need to know about how preferences behave.

First is the file format. Preferences are stored in a markup text format. This means if new preferences are added in future versions, you will not need to change the format, or run some utility on your preferences file.

Contents

Import/Export

At the bottom of the General Panel, there is an innocuous little button titled "Setup Preferences". This launches a dialog that allows you to import/export:

  • preferences, shortcuts, the pop up menu, the toolbar;
  • plugins;
  • drscripts;
  • all of the above.

This is to facilitate setting up a specific environment. (Eg you can distribute SillyDefaults.zip, which includes the preferences, plugins, and drscripts you want all recipients to have installed.)

WARNING: Importing Will Overwrite!

DrPython will overwrite any duplicates on import. This means:

  • Preferences will be overwritten.
  • Ditto shortcuts, the pop up menu, and the toolbar.
  • Which Plugins are loaded at startup, and any duplicates, will be overwritten.
  • The drscript menu will be overwritten.
  • Also, any duplicates will overwritten.

After importing, you must restart DrPython to see the changes.

When Exporting, DrPython will store drscripts in the preferences directory (in the zip file). The directory structure will mirror the menu. This means that when you then import drscripts, they will be physically located in your preferences directory, under 'drscripts'.

Back to the Top

Bookmarks

This tells DrPython how the Edit Bookmarks Dialog should look. Also applies to Documentation Bookmarks.

Style

This sets how the Edit Bookmarks Dialog appears (foreground and background color, font, size, underline/bold/italics).

Back to the Top

Document

This is "DrFrame.txtDocument". It is the text control that has the text of the currently open file.

Show Line Numbers

Sets whether or not DrPython shows line numbers.

Remove Trailing Whitespace

Automatically removes trailing spaces and tabs from each line on save.

Autoindent

Chooses the auto indentation method:

None: Leave Well Enough Alone!
Normal: Adds the number of tabs up to the first n on-whitespace character in the previous line on every new line.
Context Sensitive: Same as Normal, but adds an extra indent after ':', and dedents after the following statements: return, break, pass, continue, raise.

AutoReload

Automatically check (OnActivation of DrPython) if any open files have been modified by an outside source. It then prompts the user to reload the file. If not, the modification time for the document (in program) is reset.

Update Indentation

Updates indentation type whenever the document is modified. Displays the type in the status bar. (->Type)

Use File's Indentation

If on, use the indentation type of the loaded file. (Only runs on Open). In other words: if the default indentation type is tabs but you load a file that uses spaces, DrPython will use spaces for indentation for that document, while still using tabs as the default for other documents.

Use Tabs

If checked, uses tabs 't' when you hit the tab key, and for autoindent. If not, uses the number of spaces specified in tabwidth.

Word Wrap

Does not show the horizontal scroolbar, and "wraps" lines that are rather long around so they appear as more than one line.

Whitespace is Visible on Startup

When DrPython starts up, automatically toggles whitespace is visible.

Use Indentation Guides

This optionally draws vertical lines, visually connecting levels of indentation.

Long Line Indicator Column

Set a column to indicate you have gone past a particular position (79, for example). Using a negative number tells DrPython to highlight the text past the specified position, instead of drawing a column. 0 tells DrPython not to draw anything.

Scroll Extra Page

This tells DrPython to set the vertical scroll range to one page more than the length of the current document.

Highlight Current Line

Highlights the current line using the Background from the Caret Style.

Comment Mode

Sets where DrPython places the comment string. If Start of Line, then at the start of every line in the selected region. If Start of Word, then at the start of the first word of every line in the selected region.

Default Syntax Highlighting

Highlight text not recognized via extension THIS WAY.

Only Use Default Syntax Highlighting

Only use the syntax highlighting specified above, no matter what extension a file has.

Style

This sets how different kinds of text appear (foreground and background color, font, size, underline/bold/italics). You can choose to Not use styles at all, use them, or use only "Normal" and "Caret Foreground"

Back to the Top

Documentation

This sets the behavior of the built in help, and external documentation.

Browser

The preferred browser for viewing the documentation. (On Windows, the default is "<os.startfile>", which uses the default Windows browser).

Python Docs

The Official Python Documentation. Sets the location.

wxWidgets Docs

The wxWidgets Documentation. Sets the location.

Regular Expression Howto

A guide to regular expressions for Python programmers.

Back to the Top

Drag and Drop

This sets the behaviour of drag and drop in DrPython.

Drag and Drop Mode

This can be set to one of three values:
Drag: Files Only, Drop: Files and Text
Turns off Text Drag, but allows you to drag text from outside of the program.
Drag: Files and Text, Drop: Files and Text
Turns on Text Drag and Drop
Drag and Drop Files Only
Completely Turns off Text Drag and Drop.

Drag and Drop Text Mode

Sets the whether Dragging and Dropping Text within DrPython is by default a cut or a copy operation. The secondary behaviour can be executed when the control key is down.

Back to the Top

DrScript

This sets the behavior of Adding/Creating a Script.

Default Directory

This tells DrPython what directory to set the Add/New Script Dialog to.

Style

This sets how the Move/Rename Scripts Dialog appears (foreground and background color, font, size, underline/bold/italics).

Load Examples

Loads all example scripts from the DrPython program directory, and places them in a submenu of DrScript. Note that disabling this option will remove any Shortcuts for these Scripts. (If you subsequently update DrScript Shortcuts)

Back to the Top

File Dialog

This sets the behaviour of file dialogs in DrPython.

Default Extension (".py")

If no extension is given, append '.py' onto the end. (Enabled by default).

Use wx.FileDialog

If you want to use the default wxPython File Dialog, check this option. Only the wildcard preference will be used in this case.

Wildcard

This is the string used by wxPython to determine what file types to show. The format is DescriptionA|ExtensionPatternA1;ExtensionPatternA2|DescriptionB|ExtensionPatternB1;ExtensionPatternB2

'|' separates File Types. Here is an example: Python Files (*.py *.pyw)|*.py;*.pyw|All Files (*)|*

You can use the editor to add entries to the wildcard string.

If all entries are removed, All Files (*)|* is automatically set as the wildcard.

Constant Wildcard

You can set this in the wildcard editor. It is simply a pattern (eg *.py) that is always visible, no matter what file type is selected in the file dialog.

Windows Shortcut Replace Table

This is only needed/used on non-Windows systems.

This contains info for replacing strings found in Windows shortcuts (*.lnk) with the correct paths. So for example, if your C: drive is mounted on /mnt/win_c, you could enter "C" for Windows Pattern, and "/mnt/win_c" for Replace String.

The Replace Table uses regular expressions for the Windows Pattern, and two special characters for the Replace String. So the entry:

Windows Pattern: "[A-D]"
Replace String: "/mnt/win/@"

would replace any drive A-D (eg C: with /mnt/win/c) with the lowercase matching string. If the Replace String was /mnt/win_&, it would yield /mnt/win_C.

Any valid regular expression will work for the Windows Pattern.

Back to the Top

File Types

These preferences apply to the document depending on which file type is active.

Extensions

These are the file extensions that are recognized for each file type. Separate with commas (eg 'py,pyw,c,h').

Comment String

This is the string used to comment out selected regions of code.

Use Tabs

If checked, uses tabs \t when you hit the tab key, and for autoindent. If not, uses the number of spaces specified in tabwidth.

Word Wrap

Does not show the horizontal scroolbar, and "wraps" lines that are rather long around so they appear as more than one line.

Folding

Allows the document to "Fold". This lets you hide or show lines of a "block" (eg a class, function or an "if" statement).

Tab Width

This tells DrPython how big to make tabs look (\t). For example, 8 will make a single tab look like 8 spaces.

Line Ending Format

The default is UNIX (\n). You can also select Windows (\r\n) or Mac (\r).

Back to the Top

Find/Replace

Most of these are the defaults for the Find/Replace/Switcheroo Dialogs. The last governs the find/replace dialog behaviour.

Regular Expression

Evaluates the search text as a regular expression. Only searches forward.

Match Case

Case-Sensitive Search.

Find Backwards

Search from the end of the target text.

Whole Word

Only match whole words (whitespace on either side).

In Selection

If there is selected text, then only search within the selected text.

From Cursor

Search from the current position in the document, rather than from the start.

Prompt on Replace

Prompt the user on each replace operation, and let the user decide whether or not to replace the target text, or skip it.

Auto Wrap

If on, when the start/end of the document is reached during find, automatically wrap around.

Under Cursor

The Find/Replace Dialog sets the word under the cursor as the findtext if no text is selected.

Back to the Top

General

These apply to the program as a whole.

Remember Window Size And Position

Remembers the size and position of the DrPython window.

Remember Dialog Sizes and Positions

Remembers the sizes and positions of all main dialogs.

Remember Panel Sizes

Remembers the sizes of the prompt, and the left and right side panels.

Auto Detect Encoding

Automatically detects an encoding (for open/save documents) specified with a special comment. Also automatically detects Unicode, and encodes the Opening and Saving of documents, saving the Prompt text, and sending prompt text to the currently running program. (Only if wxPython was built with Unicode Support).

Default Encoding

This is the encoding used by default. (If Auto Detect is enabled, DrPython will try unicode first). You can manually enter an encoding, leave it blank to disable, or select from the list of encodings: the default locale (if available), ascii, latin-1, utf-8, and utf-16. (Only if wxPython was built with Unicode Support).

Save On Run

Automatically saves the current document before running.

Check Syntax On Save

Runs Check Syntax on a file after it has been saved. Unlike running this from the menu, it does not provide any feedback if no errors are found.

Check Syntax: Only On Extensions

Restricts checking syntax on save to the exact extensions listed. The format is extensions only (no period), separated by spaces (eg): py pyw python will only run check syntax on save (if it is enabled) on files with the extensions py, pyw, or python.

Prompt On Save All

Prompt before saving all modified documents.

Double Click To Close Tab

Clicking a tab in the notebook will close that tab.

Max Number of Recent Files

This tells DrPython how many recent files to keep track of. 0 is the least you can enter, and will cause DrPython to ignore recent files.

View Line Endings With Whitespace

View end of line characters when whitespace is visible.

Check Line Ending Format on Open

This tells DrPython to check to see if your default line ending is used as the line ending when you open a file.

Check Indentation Type on Open

This tells DrPython to check to see if your default indentation type is being used in the opened file.

Python Arguments

This sends the given arguments directly to Python when you run a file, debug a file, or run the Python interpreter on its own. A common argument is -i. This will tell Python to switch to interactive mode after the current file has finished running. More arguments can be found in the Python documentation, or by typing python -h at the command prompt.

Icon Size

This tells DrPython how big the toolbar needs to be. Selecting 0 will (on restart) tell DrPython to not load the ToolBar at all.

Default Directory

This tells DrPython where to look for files initially. Once a file has been opened, DrPython sets the current directory to the file's directory.

Enable Feedback

This allows pop up windows to tell you if operations were successful. (For example, successfully updated preferences).

Always Prompt On Exit

This tells DrPython to always ask if the user wants to exit, even if there is no current file, or the current file has been saved.

Backup File On Save

Whenever you save a file, before DrPython writes to the file, it will make a renamed copy (the filename with .bak attached) in the same folder.

Back to the Top

Plugins

These are the preferences for configuring plugins.

Default Directory

The default directory for installing plugins and plugin indexes.

Back to the Top

Print

These are the preferences for printing.

Document Line Numbers

This tells DrPython whether or not to print line numbers when printing the current file.

Prompt Line Numbers

This tells DrPython whether or not to print line numbers when printing the text of the prompt.

Tab Width

This tells DrPython how big to make tabs look (\t) when printing. For example, 5 will make a single tab look like 5 spaces.

Back to the Top

Prompt

This is DrFrame.txtPrompt. It is the text control that has the input and output of the currently running program.

Line Number Margin Width

Sets the margin width in pixels for linenumbers.

Visible By Default

If True, tells DrPython to show the prompt by default for each document.

Use Tabs

If checked, uses tabs \t when you hit the tab key. If not, uses the number of spaces specified in tabwidth.

Tab Width

This tells DrPython how big to make tabs look (\t). For example, 8 will make a single tab look like 8 spaces.

Line Ending Format

The default is UNIX (\n). You can also select Windows (\r\n) or Mac (\r).

Word Wrap

Does not show the horizontal scrollbar, and "wraps" lines that are rather long around so they appear as more than one line.

Whitespace is Visible on Startup

When DrPython starts up, automatically toggles whitespace is visible.

Scroll Extra Page

This tells DrPython to set the vertical scroll range to one page more than the length of the prompt.

Vertical Size

Sets the percentage size of the prompt vs the document when the prompt is visible. 25% for the prompt means 75% for the document.

Style

This sets how different kinds of text appear (foreground and background color, font, size, underline/bold/italics).

You can choose to not use styles at all, use them, or use only "Normal" and "Caret Foreground".

Back to the Top

Startup Script

This is a set of commands run in the prompt after launching the python interpreter.

Simply leave it blank to disable.

Back to the Top

Side Panels

This sets the defaults for the side panels.

Left Panel Size

The default size (percentage of the total window) for the left panel.

Right Panel Size

The default size (percentage of the total window) for the right panel.

Top Panel Size

The default size (percentage of the total window) for the top panel.

Back to the Top

Source Browser

This tells DrPython how the source browser looks and acts.

Position

Have the Source Browser appear in a panel to the left, right or top of the current document.

Visible By Default

If True, tells DrPython to show the source browser by default for each document.

Close On Activate

When you activate an item (select it with a double click, or with the keyboard), this tells DrPython whether or not to close the Source Browser window.

Sorted (Alphabetical)

This tells DrPython whether or not to sort classes/functions/import statements alphabetically, or leave them in the order they appear in the program.

Style

This sets how the source browser appears (foreground and background color, font, size, underline/bold/italics).

Auto Refresh on Save

Automatically refreshes the source browser on save.

Auto Refresh

Automatically refreshes the source browser whenever the document is modified. (This can severely impact performance for large files.)

Back to the Top

drpython-3.11.1/documentation/thanks.html0000644000175000017500000000373511150445515021312 0ustar dktrkranzdktrkranz Thank You

Thank You

Back to Help

montypythonMOLDoctor.jpg
  • To NorthStar, the inspiration for this entire project.
  • To all the programmers/artists whose works have made this project possible.
  • To my Dad and my high school programming teacher for helping inspire a skill which has served me well in my current activities.
  • Thank you to my students at North Star. If not for you, I never would have thought of teaching programming, and never would have written this program.
  • Thanks to Robert Tate, for helping debug throughout the creation of 1.0.0.
  • Thank you to the users of this program.
  • Thanks to the supporters of this programmer, and of North Star. Your donations are greatly appreciated.
  • And thanks to Monty Python for inspiration (and being chill about me using their images.) As additional thanks, I exhort you to spend some quality time watching Monty Python's Flying Circus and their many quality films.
  • One more: Thanks to the Open Source Community, and the advocates of Free Software and Open Source.

If not for you, I would not even have been able to afford a computer, let alone create this program.

drpython-3.11.1/documentation/drscript.html0000644000175000017500000002336311150445515021653 0ustar dktrkranzdktrkranz DrScript

DrScript

Back to Help

DrScript is vaguely modeled after Script-Fu in The Gimp (a VERY powerful open source image manipulation program, used on the images in DrPython).

You can add any Python file you want to the DrPython menu under the heading DrScript. Simply select "Add Existing Script".

To start from scratch, select "Add New Script" to add a new script to the menu, then open it for editing. (You will have to select the filename).

To add a Shell Command, select "Add Shell Command". Note that:

  • Current Directory is replaced with the directory of the currently open file.
  • Current File is replaced with the current open file.
  • Current File can only be used as an argument.
  • You can either run the command in the prompt (default), or run it using wx.Shell().

You can select "Dynamic DrScript" from the menu to type in a DrScript right away (without saving it to a file). Dynamic DrScripts are parsed in the same way as a saved DrScript.

Whether you select "Add New Script" or "Add Existing Script", you must select a title for your script. This is what you will see on the DrScript submenu.

You can also move scripts Around on the menu once you have added them. (Moving scripts around updates and saves all of your shortcuts.)

When shortcuts have been added to the menu, they can then be seen in the customize shortcuts dialog, and you can bind keys to your custom scripts.

Now you are ready to script! It is advisable to make the first line or so read.. code-block:: Python

#drscript

just as a reminder.

Now let's look at an example DrScript. Let's say you want to write a script which adds "with ducks" to the selected text.

#drscript
DrDocument.SetSelectedText(DrDocument.GetSelectedText() + " with ducks!")

First let's look at what this does. Let's say I select the text "The Philosopher shares his epipheny". I then select "Add With Ducks" from the DrScript submenu. Viola! The text now reads "The Philosopher shares his epipheny with ducks!"

Back to the program. DrPython will run the code in the DrScript exactly as if it were written into the source of DrPython itself! The difference is that there are special keywords DrPython recognizes.

You can choose from:

DrFrame which gives access to DrPython internals (DrFrame)
DrScript a wxObject attached to DrFrame to hold persistant variables.
DrFilename the current filename (of the active tab if in mdi mode)
DrDocument gives access to the Document wxStyledTextControl
DrPrompt gives access to the Prompt wxStyledTextControl

You could choose DrFrame for several reasons. If you want a dialog, all you have to do is.. code-block:: Python

wx.TextEntryDialog(DrFrame, "Replace What?:", "Replace All In Selection", "")

In other words, it is perfect for functions that require a wxFrame as an argument.

You can also access DrPython internals.. code-block:: Python

Frame.txtDocument.GetTextLength()

Of course, you could also write.. code-block:: Python

DrDocument.GetTextLength()

Now if you wanted to set a variable in one script, then use it in another, you would write in the first:

#drscript
#SetWhoRoars

import wx

d = wx.TextEntryDialog(DrFrame, "Who Roars?", "Determine Who Roars", "")
if (d.ShowModal() == wx.ID_OK):
  
DrScript.WhoRoars = d.GetValue()

and in the second:

#drscript
#AddRoar

if DrScript.VariableExists("WhoRoars"):
    
DrDocument.SetSelectedText(DrDocument.GetSelectedText() + " roared the " + DrScript.WhoRoars)
else:
    
DrDocument.SetSelectedText(DrDocument.GetSelectedText() + " roared the Mouse")

You can also set the text for either the Prompt or Document. For example:

#drscript
#AddWithDucks

DrPrompt.SetText(DrDocument.GetSelectedText()+ " with ducks!")

This code will set the prompt text to the document selection plus the string "with ducks!".

drpython-3.11.1/documentation/pyrst2html.py0000644000175000017500000000351011150445515021625 0ustar dktrkranzdktrkranz#!/usr/bin/env python ''' By Kevin Schluff Code from From ASPN. Placed here by Dan. ''' import SilverCity import docutils.parsers.rst import StringIO def code_block( name, arguments, options, content, lineno, content_offset, block_text, state, state_machine ): """ The code-block directive provides syntax highlighting for blocks of code. It is used with the the following syntax:: .. code-block:: CPP #include int main( int argc, char* argv[] ) { std::cout << "Hello world" << std::endl; } The directive requires the name of a language supported by SilverCity as its only argument. All code in the indented block following the directive will be colourized. Note that this directive is only supported for HTML writers. """ language = arguments[0] try: module = getattr(SilverCity, language) generator = getattr(module, language+"HTMLGenerator") except AttributeError: error = state_machine.reporter.error( "No SilverCity lexer found " "for language '%s'." % language, docutils.nodes.literal_block(block_text, block_text), line=lineno ) return [error] io = StringIO.StringIO() generator().generate_html( io, '\n'.join(content) ) html = '
\n%s\n
\n' % io.getvalue() raw = docutils.nodes.raw('',html, format = 'html') return [raw] code_block.arguments = (1,0,0) code_block.options = {'language' : docutils.parsers.rst.directives.unchanged } code_block.content = 1 # Simply importing this module will make the directive available. docutils.parsers.rst.directives.register_directive('code-block', code_block) if __name__ == "__main__": import docutils.core docutils.core.publish_cmdline(writer_name='html')drpython-3.11.1/documentation/plugins.html0000644000175000017500000020176711150445515021510 0ustar dktrkranzdktrkranz Plugins

Plugins

Back to Help

Plugins provide a method of adding functionality to DrPython.

Installing a Plugin

Note:

  • Plugins are not loaded on install.
  • Some plugins cannot be indexed. They can only be loaded at program startup.

You have two options for installing a plugin.

Use the Wizard

Select Install Plugin from the Configure Plugins Menu (Under Options). You can either download from a mirror, or select a downloaded plugin to install from local media.

When installing, you will be asked to select which plugins are:

  • Loaded By Default (These plugins will be loaded at startup. They are placed in the default index [default.idx].)
  • Loaded From Index (If supported (only supported plugins will be listed here), these plugins are indexed. You can then select them from the options submenu "Load Plugin(s) From Index".)

Install From Py

If you are making your own plugin, or have the plugin files availible in unzipped format, simply locate the main plugin file (PluginName.py), and DrPython will do the rest.

Configuring a Plugin

You can (via Options:Configure Plugins) edit the Plugin Source, or Create/Edit/Delete Index Files, which are simply lists of plugins to load when activated.

You can edit Plugin Preferences via the Plugin Preferences menu.

You can edit shortcuts or add items to the pop up menu or toolbar via the standard dialogs, for all plugins which support each feature.

All changes to a plugin's source take effect the next time DrPython loads. Shortcuts, Preferences, etc are either immediate, or effective upon reload depending on the plugin.

If a plugin is not loaded, you can still edit shortcuts and the pop up menu, but you will be unable to access the plugin functions unless the plugin is loaded.

Uninstalling a Plugin

Simply fire up the Uninstall Wizard.

Creating a Plugin

NOTE: If you write your own plugin, please note that you can access the entire DrPython application (via the DrFrame instance). This means a plugin can make stuff not work right, or can access an internal function that may be changed in a future release. If you are adding a new component (such as a new menu item, and a new dialog), you should be fine.

Naming Convention

If you want to distribute your plugin named PluginName, make sure that:

  1. All needed files are in a zip file: PluginName-Version.zip
  2. The main plugin file is named: PluginName.py
  3. The install script, if any, is named PluginName.py.install
  4. The index file, if any, is named: PluginName.idx

The first thing you need to do is import the relevant wxWidgets modules (usually just "wx").

import wx

Next, you need to define the "Plugin" function.

def Plugin(DrFrame):

DrFrame is the variable for the DrFrame in the DrPython program. It is the same variable as in DrScript.

Now you can add something to the interface simply by using the underlying code in DrPython. To bind a function to an event, there are two ways. Let's take a look at the following code.

#Example Plugin

import wx

def Plugin(DrFrame):

    
idum = DrFrame.GetNewId()

    
DrFrame.viewmenu.Append(idum, "Lookit!"," I said Lookit!")

    
def exampleFunction(event):
        
DrFrame.ShowPrompt()
        
DrFrame.txtPrompt.SetText("I'm looking.... Now what?")

    
DrFrame.Bind(wx.EVT_MENU, exampleFunction, id=idum)

    
DrFrame.AddToPopUpMenu("Lookit!", exampleFunction, 0)

    
DrFrame.AddSeparatorToPopUpMenu(1)

What this code does is the following. It adds an item to the viewmenu (you can grab the menu names by looking in the DrPython source: drpython.py). DrFrame.GetNewId() makes sure a unique id number is returned. (You only need an id number if the wx Component you are adding requires one. You need one for menus).

The second step to adding a menu is to use the DrFrame function. There are two necessary steps. The first is to define a function. If this function is going to access DrFrame, it must be defined within the Plugin function (which is only called once, when the plugin is loaded).

The function you add must take one argument, event. You can name them whatever you want. For example, MenuEvent the second will hold the wx Menu Event.

Next, you must use the wxPython method Bind() to bind that function to the component you want. Consult the wxPython documentation for usage. Here is a brief summary of Bind().

wxPythonWidget.Bind(wx.EVT_EVENTTYPE, Function, id=IdNumber)
The idNumber argument is optional (recommended if the eventtype in question allows it, check the wxWidgets documentation for that info). wx.EVT_EVENTTYPE is the event type (wxWidgets documentation for a list). Function is the function you are binding to the widget.

Keyboard Shortcuts

To Tell DrPython to let a user access a function from keyboard shortcuts, the pop up menu, or the toolbar, you have several options. You can specify each separately (or choose only one or two methods), or you can specify all at once.

DrFrame.AddPluginFunction(NameOfTheCurrentPlugin, FunctionLabel, FunctionYouWantToAdd)

Here is a brief code example.

DrFrame.AddPluginShortcutFunction("SearchInFiles", "Find In Files", OnFindInFiles)

This will let the user add the function OnFindInFiles to keyboard shortcuts, the pop up menu, or the toolbar.

For more info on what this means for each method, see below.

To add a keyboard shortcut, you have two options. You can simply use "AddKeyEvent". It takes the following arguments.

DrFrame.AddKeyEvent(FunctionYouWantToAdd, Keycode, Control, Shift, Alt, Meta)

The default for all modifier keys (Control, Shift, Alt, Meta) is 0 (do not use).

Keycodes can be tricky. For both lowercase and uppercase, use the Python function ord() plus the uppercase letter. Add Shift=1 if you want to use uppercase.

Target: Uppercase 'A'

DrFrame.AddKeyEvent(FunctionYouWantToAdd, ord('A'), 0, 1)

Target: Lowercase 'a'

DrFrame.AddKeyEvent(FunctionYouWantToAdd, ord('A'))

This will make the shortcut set in stone.

If you want to let the user configure the shortcut:

DrFrame.AddPluginShortcutFunction(NameOfTheCurrentPlugin, FunctionLabel, FunctionYouWantToAdd)

For example:

#Example Plugin
#This file is called "examplenumber2.py"

import wx

def Plugin(DrFrame):

    
idum = DrFrame.GetNewId()

    
DrFrame.viewmenu.Append(idum, "Lookit!", " I said Lookit!")

    
def exampleFunction(event):
        
DrFrame.ShowMessage("I'm Looking Already!", "Result:")

    
DrFrame.Bind(wx.EVT_MENU, exampleFunction, id=idum)

    
DrFrame.AddPluginShortcutFunction("examplenumber2", "Example Function", exampleFunction)

Now, you can open the customize shortcuts dialog, and select the "examplenumber2" plugin, to set the shortcut for the function "exampleFunction" you just added.

Note the use of the ShowMessage function.

Show message calls the drScrolledMessageDialog. DrFrame.ShowMessage(message, title) The drScrolledMessageDialog automatically displays a traceback if one exists.

Pop up menu

To allow the user to add to the pop up menu, use AddPluginPopUpMenuFunction.

AddPluginPopUpMenuFunction(NameOfTheCurrentPlugin, FunctionLabel, FunctionYouWantToAdd)

The NameOfTheCurrentPlugin is straightforward.

This will allow the user to, via the PopUpMenu Dialog, add a Plugin Function to the PopUpMenu (with the label FunctionLabel).

Notes: If you uninstall the plugin, you have to manually remove the item from the PopUpMenu list via the PopUpMenu Dialog.

Each Plugin Item on the PopUpMenu is only loaded if that plugin is loaded. So if the plugin is loaded via index, when you load the plugin, the relevant item will show up on the PopUpMenu. Even if the plugin is not loaded, the item is on the PopUpMenu List.

Toolbar

To allow the user to add to the ToolBar, use AddPluginToolBarFunction.

AddPluginToolBarFunction(FunctionLabel, FunctionYouWantToAdd)

This will allow the user to, via the Customize ToolBar Dialog, add a Plugin Function to the ToolBar (with the label FunctionLabel).

Notes: If you uninstall the plugin, you have to manually remove the item from the ToolBar list via the ToolBar Dialog.

Each Plugin Item on the ToolBar will be loaded no matter what, so be sure to remove the entry if you remove the plugin (if not, nothing will happen when you click the button.)

To set icons, you have two options. One is to write an install script that installs the icons onto the user's harddrive, and then adds entries for each icon into the custom icon data file in the user's DrPython preferences directory.

The other is to let the user set the icons manually.

To add entries, you can either do so manually, or use the following built in functions.

AddPluginIcon(Label, LocationOf16x16File, LocationOf24x24File)
RemovePluginIcon(Label)

Here is an example.

plugindir = DrFrame.GetPluginsDirectory()
DrFrame.AddPluginIcon("Find In Files", "", plugindir + "/bitmaps/24/Find In Files.png")

Assuming you have copied the icon file to the proper location (in this case, in the plugin directory plugindir/bitmaps/24/), this will add an entry into the user's custom icon data file, so that if they have their toolbar set to 24x24, and they add the Find In Files item, it will display the "Find In Files.png" icon. This function is best called in a .install script.

RemovePluginIcon is best called in the Uninstall function, and removes the entry in question from the custom icon data file.

DrFrame.RemovePluginIcon("Find In Files")

Note: AddPluginIcon will overwrite any entries in the custom icon data file with the same label.

Preferences

If the you want to set and load preferences in your plugin, all you have to do to edit those preferences is define a function.

def OnPreferences(DrFrame):

This function will be called (with DrFrame as the argument) from the Options menu. You can make your own Preferences Dialog, and have it launched from this function.

About Dialog

If you want to have an About dialog, or a Help dialog, use:

def OnAbout(DrFrame):
def OnHelp(DrFrame):

This function will be called (with DrFrame as the argument) from the Help menu. You can make your own Dialog, and have it launched from this function.

DrFrame Events

DrPython defines a few wxPython events you can use in your plugins. They are:

EVT_DRPY_DOCUMENT_CHANGED
(Posted whenever the active document is changed).
EVT_DRPY_FILE_OPENING
(Posted at the start of DrFrame.OpenFile).
EVT_DRPY_FILE_OPENED
(Posted at the end of DrFrame.OpenFile).
EVT_DRPY_FILE_SAVING
(Posted at the start of DrFrame.SaveFile).
EVT_DRPY_FILE_SAVED
(Posted at the end of DrFrame.SaveFile).
EVT_DRPY_FILE_CLOSING
(Posted at the start of DrFrame.OnClose).
EVT_DRPY_FILE_CLOSED
(Posted at the end of DrFrame.OnClose).
EVT_DRPY_NEW
(Posted at the end of DrFrame.OnNew).
EVT_DRPY_NEW_PROMPT
(Posted at the end of DrFrame.OnNewPrompt).

Usage is as below:

DrFrame.PBind(DrFrame.EVT_DRPY_FILE_OPENED, CustomFunction)

That's it. Just bind the event to DrFrame. By default, no argument is passed to the function. (There is no need to call event.Skip()).

You can change this as follows:

DrFrame.PBind(DrFrame.EVT_DRPY_FILE_OPENED, CustomFunction, None)

This will result in CustomFunction(None).

(The last argument is a tuple of arguments to pass to the function.)

IMPORTANT: You MUST Unbind the event if the function is a member of a deleted object.

For example: If you have:

DrFrame.PBind(DrFrame.EVT_DRPY_NEW, MyPanel.OnButtonPress, None)

and you want to call

DrFrame.ClosePanel(MyPanel.Position, MyPanel.Index)

You MUST call DrFrame.PUnbind((DrFrame.EVT_DRPY_NEW, MyPanel.OnButtonPress) first.

DrFrame.PUnbind takes the same arguments as PBind, except you do not need the optional arguments bit.

Note: If a plugin runs code in OnNew, it is highly recommended that the plugin is loaded by default, rather than via an index. Otherwise things can be a bit complicated if multuiple documents are open when the plugin is loaded (you can always handle this in your plugin code, however).

Adding to Panels

Want to write a panel to access from the main window? Here is what the code looks like for the creation of a Panel.

if self.SourceBrowser is None:
    
target, i = self.mainpanel.GetTargetNotebookPage(self.prefs.sourcebrowserpanel, "Source Browser")
    
self.SourceBrowser = drSourceBrowserPanel(target, -1, self.prefs.sourcebrowserpanel, i)
    
target.SetPanel(self.SourceBrowser)
    
self.mainpanel.ShowPanel(self.prefs.sourcebrowserpanel, i)
else:
    
if not self.mainpanel.IsVisible(self.SourceBrowser.Position, self.SourceBrowser.Index):
        
self.SourceBrowser.Browse()
    
self.mainpanel.TogglePanel(self.SourceBrowser.Position, self.SourceBrowser.Index)

So there are four steps to creating a side panel:

Get the Target Notebook Page itself, and its index,

  • Create the Panel.
  • Set the Notebook page's Panel
  • Tell DrPython to Show the Panel.

There are several important things to note:

  1. GetTargetNotebookPage takes two arguments, the position (0 = Left, 1 = Right), and (optionally) the tab text for the target notebook.

  2. GetTargetNotebookPage returns the page itself (the parent of the Panel you create), and the index. The Index and the Position (Left, Right) are how you access that specific panel. In this case, the last two arguments to drSourceBrowserPanel are the position and the index.

  3. You need to call the target sash window's .SetPanel method to ensure the Panel you create is sized properly.

  4. You need to call ShowPanel after newly creating a panel.

  5. You have two options for toggling a panel.

    1. Simply call TogglePanel(Position, Index).
    2. Call ShowPanel(Position, Index, ShowThePanel=True). (ShowThePanel is a boolean, enabled by default.).

    If you choose B, you can use IsVisible(Position, Index) to determine if the Panel is showing. In this case, if the panel is going to be shown, DrPython refreshes the Source Browser.

Here is the code for destroying the Panel.

def OnbtnClose(self, event):
    
self.parent.PUnbind(self.parent.EVT_DRPY_DOCUMENT_CHANGED, self.OnbtnRefresh)
    
self.parent.txtDocument.SourceBrowser = None
    
self.panelparent.ClosePanel(self.Position, self.Index)

ClosePanel(Position, Index) will destroy the panel completely, so any code after it will cause issues. This makes calling ClosePanel from code that gets called more than one (like wx.EVT_SIZE) a bad idea.

Also note that the SourceBrowser variable is set to None here. Closing a Panel does not automatically do this, so if you are using the value of variable holding the Panel in your code, be sure to set it to None before destroying the Panel itself.

The full code can be found in the SourceBrowser code in the DrPython Core.

Install/Uninstall Scripts

DrPython provides a method for automatic install script execution.

If you have a plugin named example.py, a file named example.py.install in the same directory will be automatically run on install.

Install Script

An install script is especially useful if you have files you want to install to a specific location on the user's hard drive (eg, bitmaps for the toolbar).

Here is an example.

#Example Plugin Install Script
#This file is called "example.py.install"

import wx, shutil, os, os.path

def Install(DrFrame):
    
d = wx.MessageDialog(DrFrame, "This will install some bitmaps for the Example plugin.\nAre you sure you want to proceed?",
        
"Install Search In Files",
        
wx.YES_NO | wx.ICON_QUESTION)
    
answer = d.ShowModal()
    
d.Destroy()
    
if (answer == wx.ID_YES):
        
cwd = os.getcwd()
        
plugindir = DrFrame.GetPluginsDirectory()
        
if not os.path.exists(plugindir + "/bitmaps"):
            
os.mkdir(plugindir + "/bitmaps")
        
if not os.path.exists(plugindir + "/bitmaps/16"):
            
os.mkdir(plugindir + "/bitmaps/16")
        
if not os.path.exists(plugindir + "/bitmaps/24"):
            
os.mkdir(plugindir + "/bitmaps/24")

        
shutil.copyfile(cwd + "/bitmaps/16/Example.png", plugindir + "/bitmaps/16/Example.png")
        
shutil.copyfile(cwd + "/bitmaps/24/Example.png", plugindir + "/bitmaps/24/Example.png")

        
DrFrame.AddPluginIcon("Example", plugindir + "/bitmaps/16/Example.png", plugindir + "/bitmaps/24/Example.png")

    
return True

Note the return statement. This determines the behaviour after your plugin install script exits. If you return True, DrPython will continue to install the plugin. This is good if you just want to install some bitmaps, but otherwise want DrPython to handle the rest.

Returning False will tell DrPython to halt the installation. This is good if you want to let the user cancel, or if you want to manually install the plugin yourself. Also note GetPluginsDirectory(). This returns the user directory where plugins are stored once they are installed.

Uninstall Script

If you want specific behaviour on uninstall, write a method in your plugin file called UnInstall.

#Example Plugin

import wx, os, os.path

def UnInstall(DrFrame):
    
plugindir = DrFrame.GetPluginsDirectory()
    
if os.path.exists(plugindir + "/bitmaps/16/Example.png"):
        
os.remove(plugindir + "/bitmaps/16/Example.png")
    
if os.path.exists(plugindir + "/bitmaps/24/Example.png"):
        
os.remove(plugindir + "/bitmaps/24/Example.png")

    
DrFrame.RemovePluginIcon("Example")

    
return True

def Plugin(DrFrame):
    
yadda yadda yadda...

Again, note the return. UnInstall must take a DrFrame as the only argument. If this function returns True, DrPython will continue with the rest of the uninstall process. If the function returns False, DrPython will halt the uninstall.

Useful Methods

Here are a few useful methods, and what they do: (They are all members of DrFrame)

Ask(question, title='DrPython')

Asks a yes or no question, with an optional title. Returns True if the user selects 'Yes', False otherwise.

Execute(command, statustext='')

Executes a raw command in the prompt, displaying optional statustext.

ExecutePython()

Runs the python interpreter in the prompt.

ExecuteWithPython(command, statustext='', pythonargs='')

Executes a command as an argument to python in the prompt, displaying optional statustext, and using optional additional arguments to the python interpreter (in addition to those set in preferences).

GetActiveSTC()

Returns the active Styled Text Control (Document or Prompt).

GetAlreadyOpen()

Returns a tuple of the filenames of each open Document.

GetNewId()

Returns a new wx Id, making sure the value is not anywhere near constants used by drpython.

GetPluginsDirectory()

Returns the directory where the user's plugins are stored.

GetPluginMenuLabel(plugin, functionlabel, menulabel='')

You must first add the shortcuts with (DrFrame.AddPluginFunction or DrFrame.AddPluginShortcutFunction). Then use DrFrame.LoadShortcuts(plugin). When this function is called, it will return a properly formatted menu label that includes the corresponding shortcut.

'plugin' is the name of the plugin. 'functionlabel' is the label given in 'AddPluginFunction'. 'menulabel' (optional) lets you specify a specific label to append the shortcut to (like adding '...' or and Ampersand).

GetPreference(pref, key=None)

Returns the value of preference 'pref', using the optional key 'key'. pref should be a string. key should be either a string or an integer as appropriate.

GetPreferencesDirectory()

Returns the directory where the user's preferences, shortcuts, pop up menu, toolbar settings, etc, are stored.

LoadPluginShortcuts(plugin)

If this is called within a plugin, it will load the shortcuts (useful if you need to get the shortcuts to display in the menu).

Otherwise, it is automatically called during plugin initialization.

It can only be called once for each plugin.

ShowMessage(msg, title='DrPython')

Shows a message, with an optional title. If there are any tracebacks to be had, shows them too.

ShowPrompt(Visible=True)

Either shows or hides the prompt.

ViewURLInBrowser(url)

Shows the url in the default browser specified in preferences.

drpython-3.11.1/documentation/northstar.html0000644000175000017500000000500211150445515022033 0ustar dktrkranzdktrkranz North Star

North Star

Back to Help

NorthStarLogoSmall_top.gif

North Star is a center for self-directed learners. Kids who choose not to go to school and pursue their own studies come here to learn about an impressive variety of topics. Classes are offered in diverse subjects such as:

  • philosophy
  • rhetoric
  • number theory
  • physics
  • programming
  • history
  • tidal pool biology
  • crochet
  • Shakespeare
  • war and peace
  • music ensemble
  • theater
  • botany
  • disability and the media
  • supreme court cases
  • business
  • photography
  • writing
  • art
  • and more!

The school is small, with one full time teacher/staff member, a private army of college volunteers, and a host of passionate students.

If you, dear user, would take a moment to think of the children, those plucky little folks, and donate some tax-deductable moolah to a truly wonderful cause, you can help a cutting edge "un-school" survive, and make what was hell for most of us (high school and middle school) heaven for these kids (and eventually more by serving as a model).

Please Donate to North Star

If you are interested or just want to know more, please contact me via e-mail: drpython@bluebottle.com or contact North Star directly via email: info@northstarteens.org or via phone (Massachusetts, USA): (413) 582-0193.

drpython-3.11.1/documentation/drpython.png0000644000175000017500000001023611150445515021503 0ustar dktrkranzdktrkranz‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs÷NåtIMEÓ#Þ‹pÝ+IDATxÚ ßïÿÿ.ÑþÿþÍ4ÿÿÿ ôíñûÍ4ÿÿàÿ ÿ ÿÿîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ óÿ)Õÿ8ÆÿÿÿÎÿP88ÿÿÿÿÿÿÿÿÿ···ÿÿ¾ÿ¾ÿ¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿéÿ6ÈÿÿÿÿÿÂÿ(ÿßßßÿŸŸŸÿ···ÿÿÿÿÿ€€€ÿÿÿÿ«ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ óÿ2ÌÿÿÿËÿÿÿÿßßßÿÿÿÏÏÏÿ€€€ÿÏÏÏÿÿÿÿÿÿÿÿÿÿŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ óÿ2ÌÿÔ5¡o!!!ÿÿÿÿÿÿÐÐÐ111ìììßßß¡õ Ù'<Âÿÿÿë»5’‰‰‰××׿¿¿ õ Ù'M±ÿÿÿã6(è„é\ÿÿÿ1äKì…l‹,ÓÔ.»š¤úŒ‹ ß!L²ÿ´Nÿÿ¦ØTf¤¤àèõ éºææE5G ¸ê_Ÿÿ)Î2‹Œìíÿÿ(ÿÿ¾áÆœtž:ÍÕ8(a ÿõ ûÿÿùÿûçØr"Ð Œ‹º¿™Œ¨Ë©èÿ>Áÿÿÿÿÿÿÿÿÿÿÿéÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿæÿßÿ,ÿ»ÿ»ÿ»ÿFÿ¿ÿãÿÿ@ÿ²ÿQÿÿÿÿÿÿ9Åÿü ñ=ãÌu@AàéÿÀ¿”ðøÿ ÿZÄÄä§-{=î(;È öÏŸÀ <>¬0ÌwºrAôü߀2b#¿¿( cfu0Ð@& áíëj˜#0Ò@ÝìòNÈ{#æ˜j=È–#ÈñuÚäYäçà÷– ºðèüüüÿàøìûü’¨i€FØZäÃo¯ß‘Yää¬êYÓ×)¤Rã$žžÿÿÑ#ŸÝè4¬óuÜ…÷Tº¬·$ïÜÜÿÿAÀ¤ÑÑGº–põúâ7ûªªÿÿ·J»Ôqxï{ ô5Ê;Å„~ÿÿÇ:/Ñ»tîHãw0ç>Â4ÌvŒÿÿÿÿÿÿÞÿ¦ÿÿÿÿÿÿßÿßÿëÿÿÿÿÿ óÿ:Äÿqÿÿÿÿ ôç!ß&ÚávŒÿÿEº õ õïêƒðY!Öw\OIEND®B`‚drpython-3.11.1/documentation/drdoc.py0000644000175000017500000000237011150445515020573 0ustar dktrkranzdktrkranz#!/usr/bin/python #By Dan, GPL, etc. #***************************************************************************** #*You need to have docutils and SilverCity installed for this script to work.* #***************************************************************************** import os, sys def DoDoc(title): print 'Processing:', title, '...' cwd = os.getcwd() fname = os.path.join(cwd, title + '.html') if title == 'gpl': os.system('pyrst2html.py --output-encoding=ascii %s.txt %s.html' % (title, title)) f = file(fname, 'rb') text = f.read() f.close() text = text.replace('charset=ascii', '').replace('encoding="ascii"', '') text = text.replace('', '').replace('', '') text = text.replace(' 1: DoDoc(sys.argv[1]) else: DoDoc('credits') DoDoc('gpl') DoDoc('drscript') DoDoc('help') DoDoc('northstar') DoDoc('plugins') DoDoc('preferences') DoDoc('thanks') drpython-3.11.1/documentation/preferences.txt0000644000175000017500000004527611150445515022204 0ustar dktrkranzdktrkranz================ Preferences ================ .. _Help: help.html Back to Help_ .. _Top: There are several things you need to know about how preferences behave. First is the file format. Preferences are stored in a markup text format. This means if new preferences are added in future versions, you will not need to change the format, or run some utility on your preferences file. .. contents:: Import/Export ============== At the bottom of the General Panel, there is an innocuous little button titled "Setup Preferences". This launches a dialog that allows you to import/export: - preferences, shortcuts, the pop up menu, the toolbar; - plugins; - drscripts; - all of the above. This is to facilitate setting up a specific environment. (Eg you can distribute SillyDefaults.zip, which includes the preferences, plugins, and drscripts you want all recipients to have installed.) **WARNING: Importing Will Overwrite!** DrPython will overwrite any duplicates on import. This means: - Preferences will be overwritten. - Ditto shortcuts, the pop up menu, and the toolbar. - Which Plugins are loaded at startup, and any duplicates, will be overwritten. - The drscript menu will be overwritten. - Also, any duplicates will overwritten. After importing, you must restart DrPython to see the changes. When Exporting, DrPython will store drscripts in the preferences directory (in the zip file). The directory structure will mirror the menu. This means that when you then import drscripts, they will be physically located in your preferences directory, under 'drscripts'. Back to the Top_ Bookmarks ========== This tells DrPython how the Edit Bookmarks Dialog should look. Also applies to Documentation Bookmarks. Style ------ This sets how the Edit Bookmarks Dialog appears (foreground and background color, font, size, underline/bold/italics). Back to the Top_ Document ========= This is "DrFrame.txtDocument". It is the text control that has the text of the currently open file. Show Line Numbers ------------------ Sets whether or not DrPython shows line numbers. Remove Trailing Whitespace ---------------------------- Automatically removes trailing spaces and tabs from each line on save. Autoindent ----------- Chooses the auto indentation method: | **None**: Leave Well Enough Alone! | **Normal**: Adds the number of tabs up to the first n on-whitespace character in the previous line on every new line. | **Context Sensitive**: Same as Normal, but adds an extra indent after ':', and dedents after the following statements: ``return``, ``break``, ``pass``, ``continue``, ``raise``. AutoReload ----------- Automatically check (OnActivation of DrPython) if any open files have been modified by an outside source. It then prompts the user to reload the file. If not, the modification time for the document (in program) is reset. Update Indentation ------------------- Updates indentation type whenever the document is modified. Displays the type in the status bar. (->Type) Use File's Indentation ----------------------- If on, use the indentation type of the loaded file. (Only runs on Open). In other words: if the default indentation type is tabs but you load a file that uses spaces, DrPython will use spaces for indentation for that document, while still using tabs as the default for other documents. Use Tabs --------- If checked, uses tabs '\t' when you hit the tab key, and for autoindent. If not, uses the number of spaces specified in tabwidth. Word Wrap ---------- Does not show the horizontal scroolbar, and "wraps" lines that are rather long around so they appear as more than one line. Whitespace is Visible on Startup --------------------------------- When DrPython starts up, automatically toggles whitespace is visible. Use Indentation Guides ----------------------- This optionally draws vertical lines, visually connecting levels of indentation. Long Line Indicator Column --------------------------- Set a column to indicate you have gone past a particular position (79, for example). Using a negative number tells DrPython to highlight the text past the specified position, instead of drawing a column. 0 tells DrPython not to draw anything. Scroll Extra Page ------------------ This tells DrPython to set the vertical scroll range to one page more than the length of the current document. Highlight Current Line ----------------------- Highlights the current line using the Background from the Caret Style. Comment Mode ------------- Sets where DrPython places the comment string. If Start of Line, then at the start of every line in the selected region. If Start of Word, then at the start of the first word of every line in the selected region. Default Syntax Highlighting ---------------------------- Highlight text not recognized via extension THIS WAY. Only Use Default Syntax Highlighting ------------------------------------- Only use the syntax highlighting specified above, no matter what extension a file has. Style ------ This sets how different kinds of text appear (foreground and background color, font, size, underline/bold/italics). You can choose to Not use styles at all, use them, or use only "Normal" and "Caret Foreground" Back to the Top_ Documentation ============== This sets the behavior of the built in help, and external documentation. Browser -------- The preferred browser for viewing the documentation. (On Windows, the default is "", which uses the default Windows browser). Python Docs ------------- The Official Python Documentation. Sets the location. wxWidgets Docs --------------- The wxWidgets Documentation. Sets the location. Regular Expression Howto ------------------------- A guide to regular expressions for Python programmers. Back to the Top_ Drag and Drop ============== This sets the behaviour of drag and drop in DrPython. Drag and Drop Mode ------------------- This can be set to one of three values: **Drag: Files Only, Drop: Files and Text** Turns off Text Drag, but allows you to drag text from outside of the program. **Drag: Files and Text, Drop: Files and Text** Turns on Text Drag and Drop **Drag and Drop Files Only** Completely Turns off Text Drag and Drop. Drag and Drop Text Mode ------------------------ Sets the whether Dragging and Dropping Text within DrPython is by default a cut or a copy operation. The secondary behaviour can be executed when the control key is down. Back to the Top_ DrScript ========= This sets the behavior of Adding/Creating a Script. Default Directory ------------------ This tells DrPython what directory to set the Add/New Script Dialog to. Style ------ This sets how the Move/Rename Scripts Dialog appears (foreground and background color, font, size, underline/bold/italics). Load Examples -------------- Loads all example scripts from the DrPython program directory, and places them in a submenu of DrScript. Note that disabling this option will remove any Shortcuts for these Scripts. (If you subsequently update DrScript Shortcuts) Back to the Top_ File Dialog ============ This sets the behaviour of file dialogs in DrPython. Default Extension (".py") -------------------------- If no extension is given, append '.py' onto the end. (Enabled by default). Use wx.FileDialog ------------------- If you want to use the default wxPython File Dialog, check this option. Only the wildcard preference will be used in this case. Wildcard --------- This is the string used by wxPython to determine what file types to show. The format is ``DescriptionA|ExtensionPatternA1;ExtensionPatternA2|DescriptionB|ExtensionPatternB1;ExtensionPatternB2`` '|' separates File Types. Here is an example: ``Python Files (*.py *.pyw)|*.py;*.pyw|All Files (*)|*`` You can use the editor to add entries to the wildcard string. If all entries are removed, ``All Files (*)|*`` is automatically set as the wildcard. Constant Wildcard ------------------ You can set this in the wildcard editor. It is simply a pattern (eg ``*.py``) that is always visible, no matter what file type is selected in the file dialog. Windows Shortcut Replace Table ------------------------------- This is only needed/used on non-Windows systems. This contains info for replacing strings found in Windows shortcuts (\*.lnk) with the correct paths. So for example, if your ``C:`` drive is mounted on ``/mnt/win_c``, you could enter "C" for Windows Pattern, and "/mnt/win_c" for Replace String. The Replace Table uses regular expressions for the Windows Pattern, and two special characters for the Replace String. So the entry: | ``Windows Pattern: "[A-D]"`` | ``Replace String: "/mnt/win/@"`` would replace any drive A-D (eg ``C:`` with ``/mnt/win/c``) with the lowercase matching string. If the Replace String was ``/mnt/win_&``, it would yield ``/mnt/win_C``. Any valid regular expression will work for the Windows Pattern. Back to the Top_ File Types =========== These preferences apply to the document depending on which file type is active. Extensions ----------- These are the file extensions that are recognized for each file type. Separate with commas (eg 'py,pyw,c,h'). Comment String --------------- This is the string used to comment out selected regions of code. Use Tabs --------- If checked, uses tabs ``\t`` when you hit the tab key, and for autoindent. If not, uses the number of spaces specified in tabwidth. Word Wrap ---------- Does not show the horizontal scroolbar, and "wraps" lines that are rather long around so they appear as more than one line. Folding -------- Allows the document to "Fold". This lets you hide or show lines of a "block" (eg a class, function or an "if" statement). Tab Width ---------- This tells DrPython how big to make tabs look (``\t``). For example, 8 will make a single tab look like 8 spaces. Line Ending Format ------------------- The default is UNIX (``\n``). You can also select Windows (``\r\n``) or Mac (``\r``). Back to the Top_ Find/Replace ============= Most of these are the defaults for the Find/Replace/Switcheroo Dialogs. The last governs the find/replace dialog behaviour. Regular Expression ------------------- Evaluates the search text as a regular expression. Only searches forward. Match Case ----------- Case-Sensitive Search. Find Backwards --------------- Search from the end of the target text. Whole Word ----------- Only match whole words (whitespace on either side). In Selection ------------- If there is selected text, then only search within the selected text. From Cursor ------------ Search from the current position in the document, rather than from the start. Prompt on Replace ------------------ Prompt the user on each replace operation, and let the user decide whether or not to replace the target text, or skip it. Auto Wrap ---------- If on, when the start/end of the document is reached during find, automatically wrap around. Under Cursor ------------- The Find/Replace Dialog sets the word under the cursor as the findtext if no text is selected. Back to the Top_ General ======== These apply to the program as a whole. Remember Window Size And Position ---------------------------------- Remembers the size and position of the DrPython window. Remember Dialog Sizes and Positions ------------------------------------ Remembers the sizes and positions of all main dialogs. Remember Panel Sizes --------------------- Remembers the sizes of the prompt, and the left and right side panels. Auto Detect Encoding ------------------------------- Automatically detects an encoding (for open/save documents) specified with a special comment. Also automatically detects Unicode, and encodes the Opening and Saving of documents, saving the Prompt text, and sending prompt text to the currently running program. (Only if wxPython was built with Unicode Support). Default Encoding ------------------ This is the encoding used by default. (If Auto Detect is enabled, DrPython will try unicode first). You can manually enter an encoding, leave it blank to disable, or select from the list of encodings: the default locale (if available), ascii, latin-1, utf-8, and utf-16. (Only if wxPython was built with Unicode Support). Save On Run ------------ Automatically saves the current document before running. Check Syntax On Save --------------------- Runs Check Syntax on a file after it has been saved. Unlike running this from the menu, it does not provide any feedback if no errors are found. Check Syntax: Only On Extensions --------------------------------- Restricts checking syntax on save to the exact extensions listed. The format is extensions only (no period), separated by spaces (eg): ``py`` ``pyw`` ``python`` will only run check syntax on save (if it is enabled) on files with the extensions ``py``, ``pyw``, or ``python``. Prompt On Save All ------------------- Prompt before saving all modified documents. Double Click To Close Tab -------------------------- Clicking a tab in the notebook will close that tab. Max Number of Recent Files --------------------------- This tells DrPython how many recent files to keep track of. 0 is the least you can enter, and will cause DrPython to ignore recent files. View Line Endings With Whitespace ----------------------------------- View end of line characters when whitespace is visible. Check Line Ending Format on Open --------------------------------- This tells DrPython to check to see if your default line ending is used as the line ending when you open a file. Check Indentation Type on Open ------------------------------- This tells DrPython to check to see if your default indentation type is being used in the opened file. Python Arguments ----------------- This sends the given arguments directly to Python when you run a file, debug a file, or run the Python interpreter on its own. A common argument is ``-i``. This will tell Python to switch to interactive mode after the current file has finished running. More arguments can be found in the Python documentation, or by typing ``python -h`` at the command prompt. Icon Size ----------- This tells DrPython how big the toolbar needs to be. Selecting 0 will (on restart) tell DrPython to not load the ToolBar at all. Default Directory ------------------ This tells DrPython where to look for files initially. Once a file has been opened, DrPython sets the current directory to the file's directory. Enable Feedback ---------------- This allows pop up windows to tell you if operations were successful. (For example, successfully updated preferences). Always Prompt On Exit ---------------------- This tells DrPython to always ask if the user wants to exit, even if there is no current file, or the current file has been saved. Backup File On Save -------------------- Whenever you save a file, before DrPython writes to the file, it will make a renamed copy (the filename with .bak attached) in the same folder. Back to the Top_ Plugins ======== These are the preferences for configuring plugins. Default Directory ------------------ The default directory for installing plugins and plugin indexes. Back to the Top_ Print ====== These are the preferences for printing. Document Line Numbers ---------------------- This tells DrPython whether or not to print line numbers when printing the current file. Prompt Line Numbers -------------------- This tells DrPython whether or not to print line numbers when printing the text of the prompt. Tab Width ---------- This tells DrPython how big to make tabs look (``\t``) when printing. For example, 5 will make a single tab look like 5 spaces. Back to the Top_ Prompt ======= This is ``DrFrame.txtPrompt``. It is the text control that has the input and output of the currently running program. Line Number Margin Width ------------------------- Sets the margin width in pixels for linenumbers. Visible By Default -------------------- If True, tells DrPython to show the prompt by default for each document. Use Tabs --------- If checked, uses tabs ``\t`` when you hit the tab key. If not, uses the number of spaces specified in tabwidth. Tab Width ---------- This tells DrPython how big to make tabs look (``\t``). For example, 8 will make a single tab look like 8 spaces. Line Ending Format ------------------- The default is UNIX (``\n``). You can also select Windows (``\r\n``) or Mac (``\r``). Word Wrap ---------- Does not show the horizontal scrollbar, and "wraps" lines that are rather long around so they appear as more than one line. Whitespace is Visible on Startup --------------------------------- When DrPython starts up, automatically toggles whitespace is visible. Scroll Extra Page ------------------ This tells DrPython to set the vertical scroll range to one page more than the length of the prompt. Vertical Size -------------- Sets the percentage size of the prompt vs the document when the prompt is visible. 25% for the prompt means 75% for the document. Style ------- This sets how different kinds of text appear (foreground and background color, font, size, underline/bold/italics). You can choose to not use styles at all, use them, or use only "Normal" and "Caret Foreground". Back to the Top_ Startup Script --------------- This is a set of commands run in the prompt after launching the python interpreter. Simply leave it blank to disable. Back to the Top_ Side Panels ============ This sets the defaults for the side panels. Left Panel Size ---------------- The default size (percentage of the total window) for the left panel. Right Panel Size ------------------ The default size (percentage of the total window) for the right panel. Top Panel Size ------------------ The default size (percentage of the total window) for the top panel. Back to the Top_ Source Browser =============== This tells DrPython how the source browser looks and acts. Position --------- Have the Source Browser appear in a panel to the left, right or top of the current document. Visible By Default ------------------- If True, tells DrPython to show the source browser by default for each document. Close On Activate ------------------- When you activate an item (select it with a double click, or with the keyboard), this tells DrPython whether or not to close the Source Browser window. Sorted (Alphabetical) ---------------------- This tells DrPython whether or not to sort classes/functions/import statements alphabetically, or leave them in the order they appear in the program. Style ------ This sets how the source browser appears (foreground and background color, font, size, underline/bold/italics). Auto Refresh on Save --------------------- Automatically refreshes the source browser on save. Auto Refresh -------------- Automatically refreshes the source browser whenever the document is modified. (This can severely impact performance for large files.) Back to the Top_drpython-3.11.1/documentation/credits.txt0000644000175000017500000001624411150445515021331 0ustar dktrkranzdktrkranz================ Credits ================ .. _Help: help.html Back to Help_ .. _Top: .. image:: montypythonMOLDoctorAndSupport.jpg This section is for people who have contributed to DrPython. Thank you! (Note, this list is only for the DrPython Core.) Contributors ============= (Thanks For Helping Develop DrPython!) (Note: If you built an os specific package, and want to be on this list, send me an email at DrPython AT bluebottle.com, or post in the forums.) =============================== ======================================================================= Austin Acton Mandrake Packager. Bjorn Breid 1 bug-report with fix. Bo Jangeborg 3 bug-reports. bugmenot 1 bug-report. Carsten Eckelmann Linux/UNIX documentation note. Cédric Delfosse Debian Packager, 1 bug report with fix. Chris McDonough | Initialized CVS Repository, | Submitted Long Line Indicator | Code for Preferences. Chris Wilson | 1 bug-report/feature request, | 3 bug-reports, 4 bug-reports with fix. | Donation to North Star(DrPython), Daniel Pozmanter(drpython). Christian Daven 1 bug-report with fix, 3 submitted patches. Christof Ecker 1 bug-report, 1 bug-report with fix. Christoph Zwerschke | 2 bug-reports with fix, 1 bug-report with co-fix, | 1 bug-report/feature request with co-fix, 8 bug-reports, 10 bug-report/feature requests, | Windows Installer, 3 setup.py patches. Dan Kruger 4 bug-reports, 1 bug-report with fix. Dan Uznanski 1 bug-report. Dariusz Mikuiski 1 bug-report with fix. dataangel 4 bug-reports. Davy Mitchell Windows Installer. Dmitry Ovsjannikov 1 bug-report. Dominique Buenzli | 4 bug-reports, | 1 bug-report/feature request. | Testing side of the Mac wxPython | 1 Bug Work Around. fyngyrz (Ben) | Donation to Daniel Pozmanter(drpython). Franz Steinhausler | 29 bug-report/feature requests, | 7 bug-report/feature requests with co-fix, | 83 bug-reports, 6 bug-reports with co-fix, | 46 bug-reports with fix, 4 bug-fixes. | 19 code-fixes. | Submitted Code: | Highlight Current Line Code for Preferences. | Added Configure Plugins, Customize Shortcuts, Pop Up, Toolbar to pop up menu and shortcuts. | Speed Optimizations in Find, Indent/Dedent Region. | Indentation format in Paste from CopyCutPasteExtend Plugin. | Write Access Patch. 2 Patches for File Dialog. | Plugin Display Patches in Edit Index Dialog, Load From Index Menu. | Submitted pychecker report, Patch: Display Shortcuts in Pop Up Menu. fstephens2 1 bug-report. gero 1 bug-report with co-fix. Greg Wilson 1 bug-report. Gregory Smith 4 bug-reports, 1 bug-report with fix. Guillermo Fernandez 1 bug-report with fix. indefual 1 bug-report. Ivar Marohombsar 1 bug-report. James Paige Donation to North Star(DrPython), Daniel Pozmanter(drpython). Jean Luc Damnet 2 bug-reports, bug-report with fix. John Bell 2 bug-reports, patch. Jon Schull 1 bug-report/feature request. Keith Nash 1 bug-report/feature request. limodou | Unicode Co-Developer, | UTF-8 Autodetect, | Interface Tweak, Persistent Find Across Documents, | 4 bug-reports, 8 bug-fixes. Marek Kubica | 1 co-fix, 6 bug-reports, 3 bug-report/feature requests. | Converted Documentation to docutils format. Mark Rees 1 bug-report with fix. Martinho DOS SANTOS Submitted Find and Complete patch. Matthew (ECOP) Submitted patch for right click activation. Michael Stather 1 bug-report, 1 bug-report/feature request. Mike Foord 1 bug-report/feature request with fix. Nathan Jones 1 bug-report with fix. Pawel Dzierzanowski | 1 bug-report with fix, | 1 bug-report with diagnostic test. Peter Mayne | 4 bug-reports, 2 bug-report/feature requests. | 1 bug-report/feature request with co-fix. | Submitted updated documentation files with style sheets. Peter Schott 1 bug-report. Radoslaw Stachowiak | Gentoo Packager, 1 submitted patch. | Submitted distutils support (setup.py, manifest.in). Rene Aguirre Submitted pylint report. Richard Townsend 5 bug-reports, 1 bug-report/feature request. Robin Dunn Code for Text Drag and Drop. Ronald Hollwarth 1 bug-report. Ruben Baumann 1 bug-report with fix. RunLevelZero 3 bug-report/feature requests. Sascha Ernst Mac Launcher, 1 bug report. Schmolch 1 bug-report/feature-request. Sean McKay 1 bug-report. Slim Amamou submitted file drag and drop code. Stephen Anderson 5 bug-reports, bug-report with fix. Stewart Midwinter Submitted Code for Save A Copy. Steve Holden 1 bug-report. theomurpse 1 bug-report. Thomas Klinger 1 bug-report. Tom De Muer 1 bug-report/feature request. Toronto DrPython Project | Release 160. | 1 bug-report with co-fix, | 2 bug-reports, | 4 bug-report/feature requests Ulf Wostner bug-report, bug-report with fix. Vincent Foley-Bourgon 1 bug-report/feature request. widhaya3 1 bug-report/feature request with co-fix. =============================== ======================================================================= Toronto DrPython Project ------------------------- 3 Students at the University of Toronto worked on a project to extend and improve DrPython. The class was run by Professor Greg Wilson. - Laurie MacDougal - Pat Smith - Tim Smith drpython-3.11.1/documentation/drscript.txt0000644000175000017500000001010011150445515021507 0ustar dktrkranzdktrkranz================ DrScript ================ .. _Help: help.html Back to Help_ .. _Top: DrScript is vaguely modeled after Script-Fu in The Gimp (a *VERY* powerful open source image manipulation program, used on the images in DrPython). You can add any Python file you want to the DrPython menu under the heading DrScript. Simply select "Add Existing Script". To start from scratch, select "Add New Script" to add a new script to the menu, then open it for editing. (You will have to select the filename). To add a Shell Command, select "Add Shell Command". Note that: - *Current Directory* is replaced with the directory of the currently open file. - *Current File* is replaced with the current open file. - *Current File* can only be used as an argument. - You can either run the command in the prompt (default), or run it using wx.Shell(). You can select "Dynamic DrScript" from the menu to type in a DrScript right away (without saving it to a file). Dynamic DrScripts are parsed in the same way as a saved DrScript. Whether you select "Add New Script" or "Add Existing Script", you must select a title for your script. This is what you will see on the DrScript submenu. You can also move scripts Around on the menu once you have added them. (Moving scripts around updates and saves all of your shortcuts.) When shortcuts have been added to the menu, they can then be seen in the customize shortcuts dialog, and you can bind keys to your custom scripts. Now you are ready to script! It is advisable to make the first line or so read.. code-block:: Python #drscript just as a reminder. Now let's look at an example DrScript. Let's say you want to write a script which adds "with ducks" to the selected text. .. code-block:: Python #drscript DrDocument.SetSelectedText(DrDocument.GetSelectedText() + " with ducks!") First let's look at what this does. Let's say I select the text "The Philosopher shares his epipheny". I then select "Add With Ducks" from the DrScript submenu. Viola! The text now reads "The Philosopher shares his epipheny with ducks!" Back to the program. DrPython will run the code in the DrScript exactly as if it were written into the source of DrPython itself! The difference is that there are special keywords DrPython recognizes. You can choose from: ================ ============================== DrFrame which gives access to DrPython internals (DrFrame) DrScript a wxObject attached to DrFrame to hold persistant variables. DrFilename the current filename (of the active tab if in mdi mode) DrDocument gives access to the Document wxStyledTextControl DrPrompt gives access to the Prompt wxStyledTextControl ================ ============================== You could choose DrFrame for several reasons. If you want a dialog, all you have to do is.. code-block:: Python wx.TextEntryDialog(DrFrame, "Replace What?:", "Replace All In Selection", "") In other words, it is perfect for functions that require a wxFrame as an argument. You can also access DrPython internals.. code-block:: Python Frame.txtDocument.GetTextLength() Of course, you could also write.. code-block:: Python DrDocument.GetTextLength() Now if you wanted to set a variable in one script, then use it in another, you would write in the first: .. code-block:: Python #drscript #SetWhoRoars import wx d = wx.TextEntryDialog(DrFrame, "Who Roars?", "Determine Who Roars", "") if (d.ShowModal() == wx.ID_OK): DrScript.WhoRoars = d.GetValue() and in the second: .. code-block:: Python #drscript #AddRoar if DrScript.VariableExists("WhoRoars"): DrDocument.SetSelectedText(DrDocument.GetSelectedText() + " roared the " + DrScript.WhoRoars) else: DrDocument.SetSelectedText(DrDocument.GetSelectedText() + " roared the Mouse") You can also set the text for either the Prompt or Document. For example: .. code-block:: Python #drscript #AddWithDucks DrPrompt.SetText(DrDocument.GetSelectedText()+ " with ducks!") This code will set the prompt text to the document selection plus the string "with ducks!".drpython-3.11.1/lnkDecoderRing.py0000644000175000017500000000551411150445514017523 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Requirements(Dependencies): Install Python, and wxPython. # # Tested On Windows, Linux, Mac OS X # # Icons taken from "Klassic New Crisp Icons" by Asif Ali Rizwaan (therizwaan) from the KDE-LOOK site (some edited a bit). # A humble and excellent artist. # Oh, the python icon is taken from wxPython. # The basic design of the program is meant to roughly (ROUGHLY) mimick DrScheme. # The purpose is the same, to provide a simple IDE(integrated development environment) ideal for teaching. # The DrPython icon itself was based on the DrScheme icon, with a slightly edited wxpython icon inserted(note yellow tongue, googly eyes). # # This program could not have been written without the wonderful work of the people behind # python and wxPython, in particular the Styled Text Control. Thank you. Hopefully this tool will be of use. #This loverly little file #let's people grab file attributes from the #.lnk file format (windows shortcut). # #It does not require any libraries external to python. # Adapted from the excellent perl code found in smb2web. # (smb2web by Rolf Howarth) import string, re refile = re.compile('(\\\\|[A-Z]\:)(.+)', re.M) reinvalid = re.compile('(\")|(\t)|(\n)|(\r)', re.M) def IsFolder(text): return ord(text[0x18]) & 0x10 def IsNetwork(text): return (ord(text[0x18]) == 0x00) and (ord(text[0x14]) == 1) def GetPrintableStrings(text): strings = [] cs = '' for character in text: if character in string.printable: cs += character else: if cs: if (refile.search(cs) is not None) and (reinvalid.search(cs) is None): if cs[0] != '/': strings.append(cs) cs = '' return strings def ReadLink(filename): f = file(filename, 'rb') text = f.read() f.close() return GetPrintableStrings(text)[0].replace('\\', '/')drpython-3.11.1/postinst.py0000644000175000017500000000474711150445515016524 0ustar dktrkranzdktrkranz# DrPython post installation script # # added by Christoph Zwerschke 2005-06-26 # """DrPython postinstallation script""" import sys, os if sys.platform.startswith('win'): platform = 'win' else: platform = 'other' from distutils.sysconfig import get_python_lib python_lib = get_python_lib() drpython_base = os.path.join(python_lib, 'drpython') drpython_prg = os.path.join(drpython_base, 'drpython.pyw') drpython_docs = os.path.join(drpython_base, 'documentation') drpython_help = os.path.join(drpython_docs, 'help.html') def install(): """Routine to be run with the -install switch.""" try: import wx wx = True except ImportError: print 'DrPython needs wxPython (http://www.wxpython.org)' wx = False if platform == 'win': # Windows specific part of installation if wx: # here, you could add a wx dialog asking the user: # - shall desktop shortcuts be created? # - shall start menu shortcuts be created? # - user or system wide installation? # (i.e use personal desktop or common desktop, etc.) # - take over old user profile? (in case of update, default yes) # - associate .py/.pyw extension with DrPython automatically? # - start DrPython automatically after installation? # - show release information after installation? # - some fundamental preferences to be preconfigured? # (default language, like tabs or no tabs etc.) pass # not yet implemented # for the time being, we only add desktop shortcuts (if they do not already exist) def create_shortcut_safe(target, description, filename, *args, **kw): """Create and register a shortcut only if it doesn't already exist.""" if not os.path.isfile(filename): create_shortcut(target, description, filename, *args, **kw) file_created(filename) desktop = get_special_folder_path('CSIDL_DESKTOPDIRECTORY') create_shortcut_safe(drpython_prg, 'DrPython Editor/Environment', desktop + '\\DrPython.lnk') create_shortcut_safe(drpython_help, 'DrPython Online Help', desktop + '\\DrPython Help.lnk') def remove(): """Routine to be run with the -remove switch.""" pass if __name__ == '__main__': if len(sys.argv) > 1: if sys.argv[1] == '-install': install() elif sys.argv[1] == '-remove': remove() drpython-3.11.1/drToolBarFile.py0000644000175000017500000004352611150445515017327 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #ToolBar File import os.path import drPrefsFile import wx import drScrolledMessageDialog def getToolBarList(datdirectory): toolbarfile = datdirectory + "/toolbar.dat" if not os.path.exists(toolbarfile): return ["New", "Open", "Reload File", "Close", "Save", \ "", "Print File", "Print Prompt", \ "", "Find", "Replace", \ "", "", "Preferences", "Toggle Prompt", "Toggle View Whitespace", \ "", "", "", "Check Syntax", "Run", "Set Arguments", "Python", \ "End", "Import All"] ToolBarList = [] f = file(toolbarfile, 'r') line = f.readline().rstrip() while line: ToolBarList.append(line) line = f.readline().rstrip() f.close() return ToolBarList def getCustomBitmaps(datdirectory): filename = datdirectory + "/toolbar.custom.icons.dat" if not os.path.exists(filename): return [], [], [] nameArray = [] fileArray16 = [] fileArray24 = [] f = file(filename, 'r') line = f.readline() while line: nameArray.append(drPrefsFile.ExtractPreferenceFromText(line, "Name")) fileArray16.append(drPrefsFile.ExtractPreferenceFromText(line, '16')) fileArray24.append(drPrefsFile.ExtractPreferenceFromText(line, '24')) line = f.readline() f.close() return nameArray, fileArray16, fileArray24 def getBitmapFileArray(bitmapNames, defaultbitmapdirectory, iconsize, customNames, customFiles): iconsizestr = str(iconsize) fileArray = [] l = len(bitmapNames) x = 0 while x < l: if not bitmapNames[x] == "": if bitmapNames[x] in customNames: i = customNames.index(bitmapNames[x]) t = customFiles[i] if not os.path.exists(t): t = defaultbitmapdirectory + "/" + iconsizestr + "/" + bitmapNames[x] + ".png" else: t = defaultbitmapdirectory + "/" + iconsizestr + "/" + bitmapNames[x] + ".png" if not os.path.exists(t): t = defaultbitmapdirectory + "/" + iconsizestr + "/Default.png" fileArray.append(t) else: fileArray.append("") x = x + 1 return fileArray def AddandReturn(frame, bitmapFileArray, IDNUM, count, title = ""): if title: frame.toolbar.AddSimpleTool(IDNUM, wx.BitmapFromImage(wx.Image(bitmapFileArray[count], wx.BITMAP_TYPE_PNG)), title) return IDNUM frame.toolbar.AddSimpleTool(IDNUM, wx.BitmapFromImage(wx.Image(bitmapFileArray[count], wx.BITMAP_TYPE_PNG)), frame.ToolBarList[count]) return IDNUM def SetupToolBar(frame): try: #AB names, f16, f24 = getCustomBitmaps(frame.datdirectory) if frame.prefs.iconsize == 16: bitmapFileArray = getBitmapFileArray(frame.ToolBarList, frame.bitmapdirectory, frame.prefs.iconsize, names, f16) else: bitmapFileArray = getBitmapFileArray(frame.ToolBarList, frame.bitmapdirectory, frame.prefs.iconsize, names, f24) frame.toolbar.SetToolBitmapSize(wx.Size(frame.prefs.iconsize, frame.prefs.iconsize)) ToolBarIdList = [] x = 0 l = len(frame.ToolBarList) while x < l: if frame.ToolBarList[x] == "": frame.toolbar.AddSeparator() ToolBarIdList.append(-300) elif frame.ToolBarList[x] == "New": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_NEW, x)) elif frame.ToolBarList[x] == "Open": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_OPEN, x)) elif frame.ToolBarList[x] == "Open Imported Module": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_OPEN_IMPORTED_MODULE, x)) elif frame.ToolBarList[x] == "Reload File": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_RELOAD, x)) elif frame.ToolBarList[x] == "Close": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_CLOSE, x)) elif frame.ToolBarList[x] == "Save": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_SAVE, x)) elif frame.ToolBarList[x] == "Save As": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_SAVE_AS, x)) elif frame.ToolBarList[x] == "Save All Documents": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_SAVE_ALL, x)) elif frame.ToolBarList[x] == "Save Prompt Output To File": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_SAVE_PROMPT, x)) elif frame.ToolBarList[x] == "Restore From Backup": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_RESTORE_FROM_BACKUP, x)) elif frame.ToolBarList[x] == "Close All Documents": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_CLOSE_ALL, x)) elif frame.ToolBarList[x] == "Close All Other Documents": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_CLOSE_ALL_OTHER_TABS, x)) elif frame.ToolBarList[x] == "Print Setup": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_PRINT_SETUP, x)) elif frame.ToolBarList[x] == "Print File": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_PRINT, x)) elif frame.ToolBarList[x] == "Print Prompt": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_PRINTPROMPT, x)) elif frame.ToolBarList[x] == "Exit": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_EXIT, x)) elif frame.ToolBarList[x] == "Next Document": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_NEXT_TAB, x)) elif frame.ToolBarList[x] == "Previous Document": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_PREVIOUS_TAB, x)) elif frame.ToolBarList[x] == "First Document": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_FIRST_TAB, x)) elif frame.ToolBarList[x] == "Last Document": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_LAST_TAB, x)) elif frame.ToolBarList[x] == "Find": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_FIND, x)) elif frame.ToolBarList[x] == "Replace": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_REPLACE, x)) elif frame.ToolBarList[x] == "Find Next": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_FIND_NEXT, x)) elif frame.ToolBarList[x] == "Find Previous": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_FIND_PREVIOUS, x)) elif frame.ToolBarList[x] == "Insert Regular Expression": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_INSERT_REGEX, x)) elif frame.ToolBarList[x] == "Insert Separator": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_INSERT_SEPARATOR, x)) elif frame.ToolBarList[x] == "Go To": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_GOTO, x)) elif frame.ToolBarList[x] == "Go To Block Start": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_GOTO_BLOCK_START, x)) elif frame.ToolBarList[x] == "Go To Block End": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_GOTO_BLOCK_END, x)) elif frame.ToolBarList[x] == "Go To Class Start": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_GOTO_CLASS_START, x)) elif frame.ToolBarList[x] == "Go To Class End": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_GOTO_CLASS_END, x)) elif frame.ToolBarList[x] == "Go To Def Start": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_GOTO_DEF_START, x)) elif frame.ToolBarList[x] == "Go To Def End": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_GOTO_DEF_END, x)) elif frame.ToolBarList[x] == "Source Browser Go To": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_SOURCEBROWSER_GOTO, x)) elif frame.ToolBarList[x] == "Find And Complete": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_FIND_AND_COMPLETE, x)) elif frame.ToolBarList[x] == "Comment": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_COMMENT_REGION, x)) elif frame.ToolBarList[x] == "UnComment": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_UNCOMMENT_REGION, x)) elif frame.ToolBarList[x] == "Indent": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_INDENT_REGION, x)) elif frame.ToolBarList[x] == "Dedent": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_DEDENT_REGION, x)) elif frame.ToolBarList[x] == "Undo": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_UNDO, x)) elif frame.ToolBarList[x] == "Redo": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_REDO, x)) elif frame.ToolBarList[x] == "Uppercase": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_UPPERCASE, x)) elif frame.ToolBarList[x] == "Lowercase": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_LOWERCASE, x)) elif frame.ToolBarList[x] == "Find And Complete": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_FIND_AND_COMPLETE, x)) elif frame.ToolBarList[x] == "Dynamic DrScript": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.drscriptmenu.ID_DYNAMIC_SCRIPT, x)) elif frame.ToolBarList[x] == "Copy": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_COPY, x)) elif frame.ToolBarList[x] == "Cut": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_CUT, x)) elif frame.ToolBarList[x] == "Paste": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_PASTE, x)) elif frame.ToolBarList[x] == "Delete": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_DELETE, x)) elif frame.ToolBarList[x] == "Select All": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_SELECT_ALL, x)) elif frame.ToolBarList[x] == "Select None": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_SELECT_NONE, x)) elif frame.ToolBarList[x] == "Zoom In": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_ZOOM_IN, x)) elif frame.ToolBarList[x] == "Zoom Out": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_ZOOM_OUT, x)) elif frame.ToolBarList[x] == "Toggle Fold": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_TOGGLE_FOLD, x)) elif frame.ToolBarList[x] == "Fold All": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_FOLD_ALL, x)) elif frame.ToolBarList[x] == "Expand All": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_EXPAND_ALL, x)) elif frame.ToolBarList[x] == "Select All": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_SELECT_ALL, x)) elif frame.ToolBarList[x] == "View In Left Panel": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_VIEW_IN_LEFT_PANEL, x)) elif frame.ToolBarList[x] == "View In Right Panel": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_VIEW_IN_RIGHT_PANEL, x)) elif frame.ToolBarList[x] == "View In Top Panel": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_VIEW_IN_TOP_PANEL, x)) elif frame.ToolBarList[x] == "Toggle Source Browser": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_TOGGLE_SOURCEBROWSER, x)) elif frame.ToolBarList[x] == "Preferences": #Fixed by limodou: ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_PREFS, x)) #End limodou elif frame.ToolBarList[x] == "Customize Shortcuts": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_SHORTCUTS, x)) elif frame.ToolBarList[x] == "Customize Pop Up Menu": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_POPUP, x)) elif frame.ToolBarList[x] == "Customize ToolBar": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_CUSTOMIZE_TOOLBAR, x)) elif frame.ToolBarList[x] == "Toggle Prompt": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_TOGGLE_PROMPT, x)) elif frame.ToolBarList[x] == "Toggle View Whitespace": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_TOGGLE_VIEWWHITESPACE, x)) elif frame.ToolBarList[x] == "Run": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_RUN, x, "Run Python script or Display HTML file")) elif frame.ToolBarList[x] == "Set Arguments": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_SET_ARGS, x)) elif frame.ToolBarList[x] == "Python": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_PYTHON, x)) elif frame.ToolBarList[x] == "End": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_END, x)) elif frame.ToolBarList[x] == "Check Syntax": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_CHECK_SYNTAX, x)) elif frame.ToolBarList[x] == "Close Prompt": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_CLOSE_PROMPT, x)) elif frame.ToolBarList[x] == "Help": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_HELP, x)) elif frame.ToolBarList[x] == "View Python Docs": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_PYTHON_DOCS, x)) elif frame.ToolBarList[x] == "View WxWidgets Docs": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_WXWIDGETS_DOCS, x)) elif frame.ToolBarList[x] == "View Regular Expression Howto": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_REHOWTO_DOCS, x)) elif frame.ToolBarList[x] == "Import All": ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_IMPORT_ALL, x)) #elif frame.ToolBarList[x] == "Inspect Tool": # ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_INSPECT_TOOL, x)) #todo elif frame.ToolBarList[x].find(":") > -1: try: title = frame.ToolBarList[x][frame.ToolBarList[x].find(":")+11:] i = frame.drscriptmenu.titles.index(title) ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.drscriptmenu.ID_SCRIPT_BASE+i, x, title)) except: pass elif frame.ToolBarList[x].find(":") > -1: try: title = frame.ToolBarList[x][frame.ToolBarList[x].find(":")+9:] ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_OTHER+x, x, title)) frame.Bind(wx.EVT_MENU, frame.OnToolBar, id=frame.ID_OTHER+x) except: pass else: ToolBarIdList.append(AddandReturn(frame, bitmapFileArray, frame.ID_OTHER+x, x)) frame.Bind(wx.EVT_MENU, frame.OnToolBar, id=frame.ID_OTHER+x) x = x + 1 frame.toolbar.AddSeparator() frame.toolbar.Realize() except: drScrolledMessageDialog.ShowMessage(frame, "Error Loading the ToolBar.", "DrPython Error") return [] return ToolBarIdList drpython-3.11.1/drSourceBrowserGoTo.py0000644000175000017500000001107511150445515020554 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Go To Source Browser import re import wx from drSingleChoiceDialog import drSingleChoiceDialog respacecount = re.compile(r'\S') def GetMatches(text, resourcebrowser): matches = [] positions = [] matcher = resourcebrowser.finditer(text) try: match = matcher.next() except: match = None while match is not None: matches.append(match.group().replace('\t', ' ')) positions.append(match.start()) try: match = matcher.next() except: match = None return matches, positions class drSourceBrowserGoToDialog(drSingleChoiceDialog): def __init__(self, parent, Document, matches, positions): drSingleChoiceDialog.__init__(self, parent, 'Source Browser Go To', matches, False, SetSizer=False) self.Document = Document self.positions = positions self.txtLine = wx.TextCtrl(self, -1, '', (0, 0), (350, -1), style=wx.TE_READONLY) self.txtDefinedIn = wx.TextCtrl(self, -1, '', (0, 0), (350, -1), style=wx.TE_READONLY) self.lineSizer = wx.BoxSizer(wx.HORIZONTAL) self.lineSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.lineSizer.Add(self.txtLine, 1, wx.EXPAND) self.lineSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.defSizer = wx.BoxSizer(wx.HORIZONTAL) self.defSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.defSizer.Add(self.txtDefinedIn, 1, wx.EXPAND) self.defSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.theSizer.Insert(2, wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.theSizer.Insert(3, self.lineSizer, 0, wx.EXPAND) self.theSizer.Insert(4, self.defSizer, 0, wx.EXPAND) self.SetSizerAndFit(self.theSizer) self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelected, id=self.ID_CHOICES) self.OnSelected(None) if parent.PLATFORM_IS_GTK: #does not get initially the focus (bug tracker #1903778, "Open Imported Module: focus problem", 29.02.2008: from Jon White, thanks. self.SetFocus() def OnSelected(self, event): sel = self.listChoices.GetFirstSelected() if sel > -1: pos = self.listChoices.GetItemData(sel) spaces = respacecount.search(self.choices[pos]).start() - 1 definedin = self.Document.GetFilenameTitle() if spaces > 0: x = pos while x > -1: if (respacecount.search(self.choices[x]).start() - 1) < spaces: definedin = self.choices[x].rstrip() break x -= 1 linenumber = str(self.Document.LineFromPosition(self.positions[pos]) + 1) self.txtLine.SetValue('Line Number: ' + linenumber) self.txtDefinedIn.SetValue('Defined In: ' + definedin) def SourceBrowserGoTo(frame, Document): compchar = Document.GetIndentationCharacter() resourcebrowser = re.compile(r'(^'+compchar+'*?class\s.*[(:])|(^'+compchar+'*?def\s.*[(:])|(^'+compchar+'*?import\s.*$)|(^'+compchar+'*?from\s.*$)', re.MULTILINE) text = Document.GetText() matches, positions = GetMatches(text, resourcebrowser) d = drSourceBrowserGoToDialog(frame, Document, matches, positions) answer = d.ShowModal() d.Destroy() if answer == wx.ID_OK: i = d.GetSelection() line = Document.LineFromPosition(positions[i]) Document.EnsureVisible(line) Document.ScrollToLine(line) Document.GotoLine(line) Document.GotoPos(positions[i]) Document.SetFocus() Document.SetSTCFocus(True) drpython-3.11.1/drPopUp.py0000644000175000017500000001531011231604453016214 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #PopUp import wx.stc def OnPopUp(stc, event): stc.actiondict = SetUpPopUpActions(stc.grandparent) if not stc.grandparent.popupmenulist: stc.grandparent.popupmenulist = ["Undo", "Redo", "", "Cut", "Copy", "Paste", "Delete", "", "Select All"] stc.PopUpMenu = wx.Menu() #Franz: added getlabel functions. x = 0 l = len(stc.grandparent.popupmenulist) while x < l: try: if stc.grandparent.popupmenulist[x] == "": stc.PopUpMenu.AppendSeparator() elif stc.grandparent.popupmenulist[x].find("") > -1: label = stc.grandparent.popupmenulist[x][stc.grandparent.popupmenulist[x].find(":")+1:] try: i = stc.grandparent.drscriptmenu.titles.index(label) stc.PopUpMenu.Append(stc.grandparent.ID_SCRIPT_BASE+i, stc.grandparent.drscriptmenu.getdrscriptmenulabel(label)) stc.Bind(wx.EVT_MENU, stc.OnPopUpMenu, id=stc.grandparent.ID_SCRIPT_BASE+i) except: pass elif stc.grandparent.popupmenulist[x].find("") > -1: label = stc.grandparent.popupmenulist[x][stc.grandparent.popupmenulist[x].find(":")+1:] try: i = stc.grandparent.PluginPopUpMenuLabels.index (label) stc.grandparent.PluginPopUpMenuLabels.index(label) stc.PopUpMenu.Append(stc.ID_POPUP_BASE+x, stc.grandparent.GetPluginMenuLabel(stc.grandparent.PluginPopUpMenuNames [i], label, label)) stc.Bind(wx.EVT_MENU, stc.OnPopUpMenu, id=stc.ID_POPUP_BASE+x) except: pass else: stc.grandparent.Append_Menu(stc.PopUpMenu, stc.ID_POPUP_BASE+x, stc.grandparent.popupmenulist[x]) stc.Bind(wx.EVT_MENU, stc.OnPopUpMenu, id=stc.ID_POPUP_BASE+x) except: #Error with PopUpMenu Item pass x = x + 1 stc.PopupMenu(stc.PopUpMenu, event.GetPosition()) stc.PopUpMenu.Destroy() def OnPopUpMenu(stc, event): eid = event.GetId() label = stc.PopUpMenu.GetLabel(eid) #Franz: Remove Shortcut f = label.find ("\t") if f != -1: label = label [:f] #/Remove Shortcut if label in stc.actiondict: stc.actiondict[label](event) elif label in stc.stclabelarray: if label == 'Paste': stc.Paste() else: i = stc.stclabelarray.index(label) stc.CmdKeyExecute(stc.stcactionarray[i]) else: #DrScript try: i = stc.grandparent.drscriptmenu.titles.index(label) stc.grandparent.drscriptmenu.OnScript(event) except: pass #Plugins try: i = stc.grandparent.PluginPopUpMenuLabels.index(label) stc.grandparent.PluginPopUpMenuFunctions[i](event) except: pass def SetUpPopUpActions(frame): actiondictionary = {"New":frame.OnNew, "Open":frame.OnOpen, "Open Imported Module":frame.OnOpenImportedModule, "Save":frame.OnSave, "Save As":frame.OnSaveAs, "Save All Documents":frame.OnSaveAll, "Save Prompt Output To File":frame.OnSavePrompt, "Reload File":frame.OnReload, "Restore From Backup":frame.OnRestoreFromBackup, "Close":frame.OnClose, "Close All Documents":frame.OnCloseAllDocuments, "Close All Other Documents":frame.OnCloseAllOtherDocuments, "Print Setup":frame.OnPrintSetup, "Print File":frame.OnPrint, "Print Prompt":frame.OnPrintPrompt, "Next Document":frame.OnSelectDocumentNext, "Previous Document":frame.OnSelectDocumentPrevious, "First Document":frame.OnSelectDocumentFirst, "Last Document":frame.OnSelectDocumentLast, "Exit":frame.OnExit, "Find":frame.OnMenuFind, "Find Next":frame.OnMenuFindNext, "Find Previous":frame.OnMenuFindPrevious, "Replace":frame.OnMenuReplace, "View In Left Panel":frame.OnViewInLeftPanel, "View In Right Panel":frame.OnViewInRightPanel, "View In Top Panel":frame.OnViewInTopPanel, "Insert Separator":frame.OnInsertSeparator, "Insert Regular Expression":frame.OnInsertRegEx, "Go To":frame.OnGoTo, "Go To Block Start":frame.OnGoToBlockStart, "Go To Block End":frame.OnGoToBlockEnd, "Go To Class Start":frame.OnGoToClassStart, "Go To Class End":frame.OnGoToClassEnd, "Go To Def Start":frame.OnGoToDefStart, "Go To Def End":frame.OnGoToDefEnd, "Source Browser Go To":frame.OnSourceBrowserGoTo, "Comment":frame.OnCommentRegion, "UnComment":frame.OnUnCommentRegion, "Find And Complete":frame.OnFindAndComplete, "Indent":frame.OnIndentRegion, "Dedent":frame.OnDedentRegion, "Toggle Fold":frame.OnToggleFold, "Fold All":frame.OnFoldAll, "Expand All":frame.OnExpandAll, "Toggle Source Browser":frame.OnToggleSourceBrowser, "Toggle View Whitespace":frame.OnToggleViewWhiteSpace, "Toggle Prompt":frame.OnTogglePrompt, "Run":frame.OnRun, "Set Arguments":frame.OnSetArgs, "Python":frame.OnPython, "End":frame.OnEnd, "Check Syntax":frame.OnCheckSyntax, "Close Prompt":frame.OnClosePrompt, "Preferences":frame.OnPrefs, "Customize Shortcuts":frame.OnCustomizeShortcuts, "Customize Pop Up Menu":frame.OnCustomizePopUpMenu, "Customize ToolBar":frame.OnCustomizeToolBar, "Help":frame.OnViewHelp, "View Python Docs":frame.OnViewPythonDocs, "View WxWidgets Docs":frame.OnViewWxWidgetsDocs, "View Regular Expression Howto":frame.OnViewREHowtoDocs, "Inspect Tool":frame.OnOpenWidgetInspector} return actiondictionary drpython-3.11.1/drText.py0000644000175000017500000006067611150445515016116 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # #Some Folding Code From demo.py by Robin Dunn #Some more from pype by Josiah Carlson #The Document import os.path, re import wx import wx.stc from drProperty import * import drKeywords import drSTC import drEncoding #******************************************************************************************************* class DrText(drSTC.DrStyledTextControl): def __init__(self, parent, id, grandparent, DynamicScript = 0, SplitView=0): drSTC.DrStyledTextControl.__init__(self, parent, id, grandparent) self.notebookparent = grandparent.documentnotebook self.indentationtype = 1 if not self.grandparent.prefs.docusetabs[0]: self.indentationtype = -1 self.filename = "" self.mtime = -1 self.untitlednumber = 0 self.lineendingsaremixed = 0 self.IsActive = True self.filetype = 0 self.encoding = '' self.SetupTabs() self.usestyles = (self.grandparent.prefs.docusestyles == 1) self.indentationstring = "" #Keyword Search/Context Sensitive Autoindent. self.rekeyword = re.compile(r"(\sreturn\b)|(\sbreak\b)|(\spass\b)|(\scontinue\b)|(\sraise\b)", re.MULTILINE) self.reslash = re.compile(r"\\\Z") self.renonwhitespace = re.compile('\S', re.M) self.DisableShortcuts = (SplitView == 1) if SplitView == -1: SplitView = 1 self.IsSplitView = SplitView #Check this against Self.GetModify(), to ensure events are called too many times. self.modified = False self.DynamicScript = DynamicScript if not DynamicScript: self.targetPosition = 0 self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModified, id=id) self.Bind(wx.EVT_KEY_UP, self.OnPositionChanged) self.Bind(wx.EVT_LEFT_UP, self.OnPositionChanged) self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateUI, id=id) self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) self.Bind(wx.stc.EVT_STC_MARGINCLICK, self.OnMarginClick, id=id) def _autoindent(self): pos = self.GetCurrentPos() #Strip trailing whitespace first. currentline = self.LineFromPosition(pos) lineendpos = self.GetLineEndPosition(currentline) if lineendpos > pos: self.SetTargetStart(pos) self.SetTargetEnd(lineendpos) t = self.GetTextRange(pos, lineendpos) self.ReplaceTarget(t.rstrip()) #Look at last line pos = pos - 1 clinenumber = self.LineFromPosition(pos) linenumber = clinenumber self.GotoPos(pos) self.GotoLine(clinenumber) numtabs = self.GetLineIndentation(clinenumber+1) / self.tabwidth if self.renonwhitespace.search(self.GetLine(clinenumber+1)) is not None: if self.renonwhitespace.search(self.GetLine(clinenumber)) is None: numtabs += self.GetLineIndentation(clinenumber) / self.tabwidth if numtabs == 0: numtabs = self.GetLineIndentation(linenumber) / self.tabwidth if (self.grandparent.prefs.docautoindent == 2) and (self.filetype == 0): checkat = self.GetLineEndPosition(linenumber) - 1 if self.GetCharAt(checkat) == ord(':'): numtabs = numtabs + 1 else: lastline = self.GetLine(linenumber) #Remove Comment: comment = lastline.find('#') if comment > -1: lastline = lastline[:comment] if self.reslash.search(lastline.rstrip()) is None: if self.rekeyword.search(lastline) is not None: numtabs = numtabs - 1 #Go to current line to add tabs self.SetTargetStart(pos+1) end = self.GetLineEndPosition(clinenumber+1) self.SetTargetEnd(end) self.ReplaceTarget(self.GetTextRange(pos+1, end).lstrip()) pos = pos + 1 self.GotoPos(pos) x = 0 while x < numtabs: self.AddText(self.addchar) x = x + 1 #/Auto Indent Code #Ensure proper keyboard navigation: self.CmdKeyExecute(wx.stc.STC_CMD_CHARLEFT) self.CmdKeyExecute(wx.stc.STC_CMD_CHARRIGHT) def CheckIndentationFor(self, type): text = self.GetText() if not text: return False if type == -1: return (self.respaces.search(text) is not None) else: return (self.retab.search(text) is not None) def EnsureVisible(self, linenumber): if self.grandparent.prefs.docfolding[self.filetype]: wx.stc.StyledTextCtrl.EnsureVisible(self, linenumber) def GetEncoding(self): return self.encoding def GetIndentationString(self): return self.addchar def GetIndentationEventText(self): cline, cpos = self.GetCurLine() nextline = self.GetLine(self.LineFromPosition(cpos)+1) return cline + nextline def GetFilename(self): if self.filename: return self.filename return "Untitled " + str(self.untitlednumber) def GetFilenameTitle(self): if self.filename: return os.path.split(self.filename)[1] return "Untitled " + str(self.untitlednumber) def OnModified(self, event): if self.grandparent.disableeventhandling: return if self.DynamicScript: return if not self.IsSplitView: if self.grandparent.prefs.sourcebrowserautorefresh: if self.grandparent.SourceBrowser is not None: self.grandparent.SourceBrowser.Browse() modify = self.GetModify() if (modify != self.modified) or (event is None): self.modified = modify if self.modified: if self.IsActive: pimageidx = 3 else: pimageidx = 1 else: if self.IsActive: pimageidx = 2 else: pimageidx = 0 self.SetSavePoint() self.notebookparent.SetPageImage(self.targetPosition, pimageidx) if not self.filename: title = "DrPython - Untitled " + str(self.untitlednumber) pagetext = "Untitled " + str(self.untitlednumber) else: title = "DrPython - " + self.filename pagetext = os.path.basename(self.filename) if self.modified: title += '[Modified]' #wx.CallAfter(self.grandparent.SetTitle, title) #workaround one for gtk, 15.03.2008, else segmentation fault self.grandparent.SetTitle(title) self.notebookparent.SetPageText(self.targetPosition, pagetext) if self.grandparent.prefs.docupdateindentation: #If deleting text, or undo/redo: if event is not None: modtype = event.GetModificationType() if (modtype & wx.stc.STC_MOD_DELETETEXT) or (modtype & wx.stc.STC_PERFORMED_UNDO) or \ (modtype & wx.stc.STC_PERFORMED_REDO): if (self.indentationtype == 0) or (self.indentationtype == 2): result = self.CheckIndentation(self.GetText()) else: hasit = self.CheckIndentationFor(self.indentationtype) result = self.CheckIndentation(self.GetIndentationEventText()) if (result != self.indentationtype) and (result != 2): result = 0 elif hasit: result = self.indentationtype else: result = 2 self.indentationtype = result self.setIndentationString() return else: result = self.CheckIndentation(self.GetIndentationEventText()) else: result = self.CheckIndentation(self.GetText()) if (result != self.indentationtype) and (result != 2): if (self.indentationtype == 0) or (result == 0) or \ ((self.indentationtype + result) == 0): self.indentationstring = "->MIXED" result = 0 else: if result == -1: self.indentationstring = "->SPACES" elif result == 1: self.indentationstring = "->TABS" self.indentationtype = result else: self.setIndentationString() else: self.indentationstring = "" if event is None: try: self.OnPositionChanged(None) except: pass def OnPositionChanged(self, event): if self.lineendingsaremixed: eolmodestr = "MIXED: " else: eolmodestr = '' emode = self.GetEOLMode() if emode == wx.stc.STC_EOL_CR: eolmodestr += "MAC" elif emode == wx.stc.STC_EOL_CRLF: eolmodestr += "WIN" else: eolmodestr += "UNIX" if self.GetOvertype(): ovrstring = "OVR" else: ovrstring = "INS" statustext = "Line: %(line)s, Col: %(col)s %(mode)s %(ovrstring)s %(ind)s" \ % {"line": self.GetCurrentLine()+1, "col": self.GetColumn(self.GetCurrentPos()), \ "mode": eolmodestr, "ovrstring": ovrstring, "ind": self.indentationstring} #reason gtk ; workaround tow for gtk, 15.03.2008, else segmentation fault #wx.CallAfter (self.grandparent.SetStatusText,statustext, 1) self.grandparent.SetStatusText(statustext, 1) if event is not None: event.Skip() def OnUpdateUI(self, event): if (self.usestyles) and (self.grandparent.prefs.docparenthesismatching): #Code for parenthesis matching from wxPython Demo. # check for matching braces braceAtCaret = -1 braceOpposite = -1 charBefore = None caretPos = self.GetCurrentPos() if caretPos > 0: charBefore = self.GetCharAt(caretPos - 1) styleBefore = self.GetStyleAt(caretPos - 1) # check before if charBefore and chr(charBefore) in "[]{}()" and styleBefore == wx.stc.STC_P_OPERATOR: braceAtCaret = caretPos - 1 # check after if braceAtCaret < 0: charAfter = self.GetCharAt(caretPos) styleAfter = self.GetStyleAt(caretPos) if charAfter and chr(charAfter) in "[]{}()" and styleAfter == wx.stc.STC_P_OPERATOR: braceAtCaret = caretPos if braceAtCaret >= 0: braceOpposite = self.BraceMatch(braceAtCaret) if braceAtCaret != -1 and braceOpposite == -1: self.BraceBadLight(braceAtCaret) else: self.BraceHighlight(braceAtCaret, braceOpposite) event.Skip() def OnKeyDown(self, event): result = self.grandparent.RunShortcuts(event, self, self.DisableShortcuts) if result > -1: if (result == wx.stc.STC_CMD_NEWLINE) and (self.grandparent.prefs.docautoindent): self._autoindent() if result == wx.stc.STC_CMD_TAB: #Check Indentation for trailing spaces pos = self.GetCurrentPos() linenumber = self.LineFromPosition(pos) lpos = pos - self.PositionFromLine(linenumber) - 1 #Only at the end of a line. end = self.GetLineEndPosition(linenumber) if pos != end: return ltext = self.GetLine(linenumber).rstrip(self.GetEndOfLineCharacter()) #only proceed if the text up to this point is whitespace. if self.renonwhitespace.search(ltext[:lpos]) is not None: return #Get the position of where the full indentation ends: lnws = len(ltext.rstrip()) fiendsat = lnws + (ltext[lnws:].count(self.addchar) * len(self.addchar)) #Get the diff betwixt this and the current pos: difftwixt = len(ltext) - fiendsat if difftwixt > 0: #Check to make sure you are just looking at spaces: target = ltext[fiendsat:] for a in target: if a != ' ': return #Remove the extra spaces self.SetTargetStart(pos - difftwixt) self.SetTargetEnd(pos) self.ReplaceTarget('') #/Check Indentation for trailing spaces elif result == wx.stc.STC_CMD_DELETEBACK: #if self.indentationtype == -1: if self.indentationtype == -1 and self.grandparent.prefs.docuseintellibackspace[self.filetype]: pos = self.GetCurrentPos() - 1 if chr(self.GetCharAt(pos)) == ' ': x = 0 l = self.grandparent.prefs.doctabwidth[self.filetype] while x < l: c = chr(self.GetCharAt(pos)) if c == ' ': self.CmdKeyExecute(wx.stc.STC_CMD_DELETEBACK) else: x = l x += 1 pos = pos - 1 else: event.Skip() else: event.Skip() def OnMarginClick(self, event): # fold and unfold as needed if event.GetMargin() == 2: lineClicked = self.LineFromPosition(event.GetPosition()) if self.GetFoldLevel(lineClicked) & wx.stc.STC_FOLDLEVELHEADERFLAG: self.ToggleFold(lineClicked) def SetEncoding(self, encoding): self.encoding = encoding def setIndentationString(self): if self.indentationtype == 2: self.indentationstring = "->NONE" elif self.indentationtype == 1: self.indentationstring = "->TABS" elif self.indentationtype == 0: self.indentationstring = "->MIXED" elif self.indentationtype == -1: self.indentationstring = "->SPACES" def SetupLineNumbersMargin(self): if self.grandparent.prefs.docshowlinenumbers: linecount = self.GetLineCount() if linecount < 1000: linecount = 1000 lstring = str(linecount * 100) textwidth = self.TextWidth(wx.stc.STC_STYLE_LINENUMBER, drEncoding.EncodeText(self.grandparent, lstring, self.encoding)) self.SetMarginWidth(1, textwidth) else: self.SetMarginWidth(1, 0) def SetupPrefsDocument(self, notmdiupdate = 1): if self.grandparent.prefs.doconlyusedefaultsyntaxhighlighting: self.filetype = self.grandparent.prefs.docdefaultsyntaxhighlighting self.SetEndAtLastLine(not self.grandparent.prefs.docscrollextrapage) self.SetIndentationGuides(self.grandparent.prefs.docuseindentationguides) if (len(self.filename) == 0) and not self.GetModify(): self.SetupTabs(self.indentationtype == 1) if self.grandparent.prefs.docfolding[self.filetype]: self.grandparent.viewmenu.Enable(self.grandparent.ID_FOLDING, True) self.SetMarginWidth(2, 12) self.SetMarginSensitive(2, True) self.SetProperty("fold", "1") else: self.grandparent.viewmenu.Enable(self.grandparent.ID_FOLDING, False) self.SetMarginWidth(2, 0) self.SetMarginSensitive(2, False) self.SetProperty("fold", "0") #LongLineCol from Chris McDonough #Adding if statement, else section myself, also added code to use line and/or background method: #I put the set edge color section in under styles. if self.grandparent.prefs.doclonglinecol > 0: self.SetEdgeColumn(self.grandparent.prefs.doclonglinecol) self.SetEdgeMode(wx.stc.STC_EDGE_LINE) elif self.grandparent.prefs.doclonglinecol < 0: self.SetEdgeColumn(abs(self.grandparent.prefs.doclonglinecol)) self.SetEdgeMode(wx.stc.STC_EDGE_BACKGROUND) else: self.SetEdgeMode(wx.stc.STC_EDGE_NONE) #/LongLineCol from Chris McDonough self.SetupLineNumbersMargin() if notmdiupdate: self.SetViewWhiteSpace(self.grandparent.prefs.docwhitespaceisvisible) self.SetViewEOL(self.grandparent.prefs.docwhitespaceisvisible and self.grandparent.prefs.vieweol) self.SetTabWidth(self.grandparent.prefs.doctabwidth[self.filetype]) if self.grandparent.prefs.docwordwrap[self.filetype]: self.SetWrapMode(wx.stc.STC_WRAP_WORD) else: self.SetWrapMode(wx.stc.STC_WRAP_NONE) self.SetKeyWords(0, drKeywords.GetKeyWords(self.filetype)) self.SetLexer(drKeywords.GetLexer(self.filetype)) indentguide = wx.LIGHT_GREY if (self.filetype == 0) or (self.filetype == 3): self.grandparent.prefs.txtDocumentStyleDictionary = self.grandparent.prefs.PythonStyleDictionary cursorstyle = self.grandparent.prefs.txtDocumentStyleDictionary[15] foldingstyle = self.grandparent.prefs.txtDocumentStyleDictionary[17] self.SetEdgeColour(self.grandparent.prefs.txtDocumentStyleDictionary[18]) highlightlinestyle = self.grandparent.prefs.txtDocumentStyleDictionary[19] indentguide = self.grandparent.prefs.txtDocumentStyleDictionary[20] elif self.filetype == 1: self.grandparent.prefs.txtDocumentStyleDictionary = self.grandparent.prefs.CPPStyleDictionary cursorstyle = self.grandparent.prefs.txtDocumentStyleDictionary[17] foldingstyle = self.grandparent.prefs.txtDocumentStyleDictionary[19] self.SetEdgeColour(self.grandparent.prefs.txtDocumentStyleDictionary[20]) highlightlinestyle = self.grandparent.prefs.txtDocumentStyleDictionary[21] elif self.filetype == 2: self.grandparent.prefs.txtDocumentStyleDictionary = self.grandparent.prefs.HTMLStyleDictionary cursorstyle = self.grandparent.prefs.txtDocumentStyleDictionary[18] foldingstyle = self.grandparent.prefs.txtDocumentStyleDictionary[20] self.SetEdgeColour(self.grandparent.prefs.txtDocumentStyleDictionary[21]) highlightlinestyle = self.grandparent.prefs.txtDocumentStyleDictionary[22] #Folding: foldback = getStyleProperty("back", foldingstyle) foldfore = getStyleProperty("fore", foldingstyle) self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEREND, wx.stc.STC_MARK_BOXPLUSCONNECTED, foldback, foldfore) self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEROPENMID, wx.stc.STC_MARK_BOXMINUSCONNECTED, foldback, foldfore) self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERMIDTAIL, wx.stc.STC_MARK_TCORNER, foldback, foldfore) self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERTAIL,wx.stc.STC_MARK_LCORNER, foldback, foldfore) self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDERSUB, wx.stc.STC_MARK_VLINE, foldback, foldfore) self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDER,wx.stc.STC_MARK_BOXPLUS, foldback, foldfore) self.MarkerDefine(wx.stc.STC_MARKNUM_FOLDEROPEN,wx.stc.STC_MARK_BOXMINUS, foldback, foldfore) #Margin: self.marginbackground = foldback self.marginforeground = foldfore if self.grandparent.prefs.docusestyles: self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, self.grandparent.prefs.txtDocumentStyleDictionary[0]) self.StyleClearAll() self.StartStyling(0, 0xff) self.SetCaretForeground(cursorstyle) if self.grandparent.prefs.dochighlightcurrentline: self.SetCaretLineBack(highlightlinestyle) self.SetCaretLineVisible(True) else: self.SetCaretLineVisible(False) self.SetCaretWidth(self.grandparent.prefs.doccaretwidth) self.StyleSetForeground(wx.stc.STC_STYLE_INDENTGUIDE, indentguide) if (self.grandparent.prefs.docusestyles < 2) or (not self.filetype == 4): self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER, self.grandparent.prefs.txtDocumentStyleDictionary[1]) self.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT, self.grandparent.prefs.txtDocumentStyleDictionary[2]) self.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD, self.grandparent.prefs.txtDocumentStyleDictionary[3]) drKeywords.SetSTCStyles(self.grandparent, self, self.filetype) def SetTargetPosition(self, pos): self.targetPosition = pos def FoldAll(self, expanding): lineCount = self.GetLineCount() #Yup, this is different from the demo.py stuff. #This is a really messed up hack of the pype.py and demo.py stuff to act #the way I want it to... #Folding is just ugly. #Set stuff up first... lines = [] #franz: lineNum not referenced for line in xrange(lineCount): lines.append(line) lines.reverse() if not expanding: #Code Inspired by pype.py...Wake wx.stc.STC Up Before we fold! self.HideLines(0, lineCount-1) wx.Yield() self.ShowLines(0, lineCount-1) for line in xrange(lineCount): if self.GetFoldLevel(line) & wx.stc.STC_FOLDLEVELHEADERFLAG: self.SetFoldExpanded(line, 1) #Back to demo.py...mmmm, open source...Modified ever so slightly if expanding: #Modify the demo.py stuff to act like pype.py: for line in lines: a = self.GetLastChild(line, -1) self.ShowLines(line+1,a) self.SetFoldExpanded(line, True) else: #Get pype.py funky(Ever so slightly modified old bean)! for line in lines: a = self.GetLastChild(line, -1) self.HideLines(line+1,a) self.SetFoldExpanded(line, False) def Expand(self, line, doExpand, force=False, visLevels=0, level=-1): #From demo.py (pype.py 1.1.8 uses it too!) lastChild = self.GetLastChild(line, level) line = line + 1 while line <= lastChild: if force: if visLevels > 0: self.ShowLines(line, line) else: self.HideLines(line, line) else: if doExpand: self.ShowLines(line, line) if level == -1: level = self.GetFoldLevel(line) if level & wx.stc.STC_FOLDLEVELHEADERFLAG: if force: if visLevels > 1: self.SetFoldExpanded(line, True) else: self.SetFoldExpanded(line, False) line = self.Expand(line, doExpand, force, visLevels-1) else: if doExpand and self.GetFoldExpanded(line): line = self.Expand(line, True, force, visLevels-1) else: line = self.Expand(line, False, force, visLevels-1) else: line = line + 1 return line drpython-3.11.1/drShortcutsDialog.py0000644000175000017500000006511211150445515020276 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Shortcuts Dialog import os.path, re import wx, wx.lib.dialogs import drScrolledMessageDialog from drGetKeyDialog import drGetKeyDialog import drShortcutsFile import drShortcuts from drShortcuts import MatchControl, MatchShift, MatchAlt, MatchMeta def ShortcutIsAlreadyTaken(TargetShortcut, ShortcutArrays, CurrentShortcut = None): if drShortcuts.GetKeycodeStringFromShortcut(TargetShortcut) == "": return -1 i = 0 for ShortcutArray in ShortcutArrays: for Shortcut in ShortcutArray: if Shortcut == TargetShortcut: if CurrentShortcut is not None: if not CurrentShortcut == TargetShortcut: return i else: return i i += 1 return -1 def GetShortcuts(filename, frame): try: f = file(filename, 'r') text = f.read() f.close() except: drScrolledMessageDialog.ShowMessage(frame, 'File error with: "' + filename + '".', "ERROR") return "" reShortcuts = re.compile(r'^\s*?DrFrame\.AddPluginShortcutFunction\(.*\)', re.MULTILINE) allShortcuts = reShortcuts.findall(text) ShortcutsArray = [] for s in allShortcuts: #From the Left most '(' start = s.find('(') #To the Right most ')' end = s.rfind(')') if (start > -1) and (end > -1): s = s[start+1:end] i = s.find(',') e = i + 1 + s[i+1:].find(',') argfunctionname = s[i+1:e].strip().strip('"') ShortcutsArray.append(argfunctionname) return ShortcutsArray class drShortcutPanel(wx.Panel): def __init__(self, parent, id, wxSize): wx.Panel.__init__(self, parent, id, size=wxSize) self.ID_GET_KEY = 403 self.shortcutIndex = -1 self.listIndex = 0 self.theSizer = wx.FlexGridSizer(7, 3, 5, 10) self.txtKeyChar = wx.TextCtrl(self, id, size=wx.Size(100, -1), style=wx.TE_READONLY) self.txtKeyCode = wx.TextCtrl(self, id, size=wx.Size(100, -1), style=wx.TE_READONLY) self.chkAlt = wx.CheckBox(self, id, "") self.chkControl = wx.CheckBox(self, id, "") self.chkMeta = wx.CheckBox(self, id, "") self.chkShift = wx.CheckBox(self, id, "") self.chkAlt.Enable(False) self.chkControl.Enable(False) self.chkMeta.Enable(False) self.chkShift.Enable(False) self.btnGetKey = wx.Button(self, self.ID_GET_KEY, "Get Key") self.parent = parent self.theSizer.Add(wx.StaticText(self, -1, ""), 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Key Char:"), 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(self.txtKeyChar, 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Key Code:"), 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(self.txtKeyCode, 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Alt:"), 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(self.chkAlt, 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Control"), 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(self.chkControl, 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Meta:"), 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(self.chkMeta, 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Shift:"), 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(self.chkShift, 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 1, wx.ALIGN_LEFT | wx.SHAPED) self.theSizer.Add(self.btnGetKey, 1, wx.ALIGN_LEFT | wx.SHAPED) self.SetAutoLayout(True) self.SetSizer(self.theSizer) self.Bind(wx.EVT_BUTTON, self.OnbtnGetKey, id=self.ID_GET_KEY) def OnbtnGetKey(self, event): oldv = self.parent.ShortcutsArray[self.listIndex][self.shortcutIndex] d = drGetKeyDialog(self, self.parent.txtIgnore.GetValue(), self.parent) d.SetKeyString(oldv) d.ShowModal() newv = d.GetKeyString() d.Destroy() alreadytaken = ShortcutIsAlreadyTaken(newv, self.parent.ShortcutsArray, oldv) if alreadytaken > -1: if alreadytaken == 0: takenby = self.parent.parent.ShortcutNames[self.parent.ShortcutsArray[alreadytaken].index(newv)] elif alreadytaken == 1: takenby = self.parent.parent.STCShortcutNames[self.parent.ShortcutsArray[alreadytaken].index(newv)] elif alreadytaken == 2: takenby = self.parent.parent.DrScriptShortcutNames[self.parent.ShortcutsArray[alreadytaken].index(newv)] else: takenby = self.parent.PluginShortcutNameList[alreadytaken-3][self.parent.ShortcutsArray[alreadytaken].index(newv)] drScrolledMessageDialog.ShowMessage(self, ('The Shortcut "' + newv + \ '"\nis already being used by "' + takenby + '".\nDrPython will politely ignore your request.'),\ "Shortcut Already Taken") return self.parent.ShortcutsArray[self.listIndex][self.shortcutIndex] = newv self.SetShortcut(self.parent.ShortcutsArray[self.listIndex][self.shortcutIndex], self.shortcutIndex, self.listIndex) def Reset(self): self.txtKeyChar.SetValue("") self.txtKeyCode.SetValue("") self.chkAlt.SetValue(False) self.chkControl.SetValue(False) self.chkMeta.SetValue(False) self.chkShift.SetValue(False) def SetShortcut(self, shortcut, shortcutIndex, listIndex): try: self.shortcutIndex = shortcutIndex self.listIndex = listIndex keycode = drShortcuts.GetKeycodeFromShortcut(shortcut) if keycode: found, text = drShortcuts.GetKeycodeText(keycode) if found: self.txtKeyChar.SetValue(text) elif (keycode < 0) or (keycode > 256): self.txtKeyChar.SetValue("UnKnown") else: self.txtKeyChar.SetValue(chr(keycode)) else: self.txtKeyChar.SetValue("None") self.txtKeyCode.SetValue(str(keycode)) self.chkAlt.SetValue(drShortcuts.MatchAlt(shortcut)) self.chkControl.SetValue(drShortcuts.MatchControl(shortcut)) self.chkMeta.SetValue(drShortcuts.MatchMeta(shortcut)) self.chkShift.SetValue(drShortcuts.MatchShift(shortcut)) except: drScrolledMessageDialog.ShowMessage(self.parent, "Error Selecting Shortcut", "DrPython Error") return class drShortcutsDialog(wx.Dialog): def __init__(self, parent): wx.Dialog.__init__(self, parent, -1, ("Customize Shortcuts"), wx.DefaultPosition, wx.Size(-1, -1), wx.DEFAULT_DIALOG_STYLE | wx.THICK_FRAME) wx.Yield() self.ID_SHORTCUTS = 1001 self.ID_LIST = 1300 self.ID_RESET = 1004 self.ID_UPDATE = 1005 self.ID_SAVE = 1006 self.ID_IGNORE = 1300 self.parent = parent self.theSizer = wx.FlexGridSizer(5, 4, 5, 10) self.listSizer = wx.BoxSizer(wx.HORIZONTAL) self.ignoreSizer = wx.BoxSizer(wx.HORIZONTAL) self.shortcutsdirectory = parent.shortcutsdirectory self.ShortcutsArray = [[], [], []] #Shortcuts self.ShortcutsIgnoreString = parent.ShortcutsIgnoreString self.ShortcutsArray[0] = list(self.parent.Shortcuts) #Text Control self.ShortcutsArray[1] = list(self.parent.STCShortcuts) #DrScript self.ShortcutsArray[2] = list(self.parent.DrScriptShortcuts) self.ShortcutsArrayPos = 0 #Plugins self.LoadPluginShortcutList() self.ShortcutList = ["Standard", "Text Control", "DrScript"] self.ShortcutList.extend(self.PluginList) self.cboList = wx.ComboBox(self, self.ID_LIST, "Standard", wx.DefaultPosition, (200, -1), self.ShortcutList, wx.CB_DROPDOWN|wx.CB_READONLY) self.boxShortcuts = wx.ListBox(self, self.ID_SHORTCUTS, wx.DefaultPosition, wx.Size(200, 200), self.parent.ShortcutNames) self.pnlShortcut = drShortcutPanel(self, -1, wx.Size(250, -1)) self.btnGetIgnoreKeys = wx.Button(self, self.ID_IGNORE, "Ignore Key(s)...") self.txtIgnore = wx.TextCtrl(self, -1, self.ShortcutsIgnoreString, size=wx.Size(100, -1), style=wx.TE_READONLY) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.listSizer.Add(wx.StaticText(self, -1, "List: "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.listSizer.Add(self.cboList, 0, wx.ALIGN_CENTER | wx.SHAPED) self.ignoreSizer.Add(wx.StaticText(self, -1, "Ignore: "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.ignoreSizer.Add(self.txtIgnore, 0, wx.ALIGN_CENTER | wx.SHAPED) self.ignoreSizer.Add(self.btnGetIgnoreKeys, 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.listSizer, 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.ignoreSizer, 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Shortcuts List:"), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Shortcut:"), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.boxShortcuts, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.pnlShortcut, 1, wx.EXPAND | wx.ALIGN_CENTER) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.btnReset = wx.Button(self, self.ID_RESET, "&Reset") self.btnUpdate = wx.Button(self, self.ID_UPDATE, "&Update") self.btnSave = wx.Button(self, self.ID_SAVE, "&Save") self.btnClose = wx.Button(self, 101, "&Close") self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.btnReset, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.btnUpdate, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.btnSave, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.btnClose, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.btnClose.SetDefault() self.SetAutoLayout(True) self.SetSizerAndFit(self.theSizer) self.Bind(wx.EVT_BUTTON, self.OnbtnReset, id=self.ID_RESET) self.Bind(wx.EVT_BUTTON, self.OnbtnUpdate, id=self.ID_UPDATE) self.Bind(wx.EVT_BUTTON, self.OnbtnSave, id=self.ID_SAVE) self.Bind(wx.EVT_BUTTON, self.OnbtnClose, id=101) self.Bind(wx.EVT_BUTTON, self.OnbtnGetIgnoreKeys, id=self.ID_IGNORE) self.Bind(wx.EVT_COMBOBOX, self.OnList, id=self.ID_LIST) self.Bind(wx.EVT_LISTBOX, self.OnSelect, id=self.ID_SHORTCUTS) self.parent.LoadDialogSizeAndPosition(self, 'shortcutsdialog.sizeandposition.dat') if parent.PLATFORM_IS_GTK: #does not get initially the focus (bug tracker #1903778, "Open Imported Module: focus problem", 29.02.2008: from Jon White, thanks. self.SetFocus() def LoadPluginShortcutList(self): plist = os.listdir(self.parent.pluginsdirectory) self.PluginShortcutNameList = [] self.PluginList = [] for p in plist: i = p.find(".py") l = len(p) if i > -1 and (i + 3 == l): self.PluginList.append(":" + p[:i]) poplist = [] #Load shortcuts from plugins. for plugin in self.PluginList: list = [] if plugin.find("") > -1: pluginfile = os.path.join(self.parent.pluginsdirectory, plugin[plugin.find(':')+1:] + ".py") shortcutfile = os.path.join(self.parent.pluginsshortcutsdirectory, plugin[plugin.find(':')+1:] + ".shortcuts.dat") list = GetShortcuts(pluginfile, self) plist = self.parent.GetPluginLabels(pluginfile, True) for p in plist: if not (p in list): list.append(p) shortcuts = [] if list: needtomakefile = 0 #If the file does not exist, or is out of date, create it. if not os.path.exists(shortcutfile): needtomakefile = 1 else: shortcuts, names, ignorestring = drShortcutsFile.ReadShortcuts(shortcutfile, 0) if len(shortcuts) != len(list): needtomakefile = 2 if needtomakefile: try: if list: f = file(shortcutfile, 'w') if needtomakefile == 2: for s in list: if s in names: ix = names.index(s) f.write("<" + s + ">") if MatchControl(shortcuts[ix]): f.write("Control,") if MatchShift(shortcuts[ix]): f.write("Shift,") if MatchAlt(shortcuts[ix]): f.write("Alt,") if MatchMeta(shortcuts[ix]): f.write("Meta") f.write("" + drShortcuts.GetKeycodeStringFromShortcut(shortcuts[ix]) + "\n") else: f.write("<" + s + ">\n") else: for s in list: f.write("<" + s + ">\n") f.close() shortcuts, names, ignorestring = drShortcutsFile.ReadShortcuts(shortcutfile, 0) else: shortcuts, names, ignorestring = [], [], "" if plugin.find(':') > -1: plugin = plugin[plugin.find(':')+1:] x = 0 for shortcut in shortcuts: try: i = self.parent.PluginShortcutFunctionNames.index(plugin + ":" + names[x]) self.parent.PluginAction.append(self.parent.PluginShortcutFunctions[i]) self.parent.PluginShortcuts.append(shortcut) except: pass x += 1 if os.path.exists(shortcutfile): shortcuts, names, ignorestring = drShortcutsFile.ReadShortcuts(shortcutfile, 0) except: drScrolledMessageDialog.ShowMessage(self, ("Error Creating Shortcuts For Plugin"), "Plugin Shortcuts Error") return if shortcuts: self.ShortcutsArray.append(shortcuts) self.PluginShortcutNameList.append(names) else: poplist.append(plugin) for popl in poplist: try: i = self.PluginList.index(popl) self.PluginList.pop(i) except: pass def OnCloseW(self, event): self.parent.SaveDialogSizeAndPosition(self, 'shortcutsdialog.sizeandposition.dat') if event is not None: event.Skip() def OnbtnClose(self, event): self.Close(1) def OnbtnGetIgnoreKeys(self, event): addstring = '\n\n' if self.parent.PLATFORM_IS_WIN: addstring = '\n\n\n\n\n\n' d = wx.lib.dialogs.MultipleChoiceDialog(self, "Select the Modifier Keys you wish to ignore:" + addstring, "Ignore Modifier Keys", ["Control", "Meta", "Shift", "Alt"]) answer = d.ShowModal() if answer == wx.ID_OK: tuply = d.GetValueString() leString = "" for selection in tuply: leString = leString + selection + "," self.txtIgnore.SetValue(leString) d.Destroy() def OnbtnReset(self, event): answer = wx.MessageBox("This will reset all standard shortcuts to the program default.\n(You still need to click update and/or save)\nAre you sure you want to do this?", "Reset Shortcuts", wx.YES_NO | wx.ICON_QUESTION) if answer == wx.YES: self.ShortcutsArray[0], self.ShortcutsIgnoreString = drShortcutsFile.GetDefaultShortcuts() self.ShortcutsArray[0], saa, sarg = drShortcuts.SetShortcuts(self.parent, self.ShortcutsArray[0], self.parent.ShortcutNames, 1) sel = self.boxShortcuts.GetSelection() self.ShortcutsArray[1] = drShortcuts.SetSTCShortcuts(self.parent.txtDocument, self.ShortcutsArray[1], True) drShortcuts.SetSTCShortcuts(self.parent.txtPrompt, self.ShortcutsArray[1], True) self.pnlShortcut.SetShortcut(self.ShortcutsArray[self.ShortcutsArrayPos][sel], sel, self.ShortcutsArrayPos) def OnbtnSave(self, event): #STC shortcutsfile = self.shortcutsdirectory + "/stcshortcuts.dat" try: drShortcutsFile.WriteShortcuts(shortcutsfile, self.ShortcutsArray[1], self.parent.STCShortcutNames, "", False) except: drScrolledMessageDialog.ShowMessage(self, ("There were some problems writing to:\n" + shortcutsfile + "\nEither the file is having metaphysical issues, or you do not have permission to write.\nFor metaphysical issues, consult the documentation.\nFor permission issues, change the permissions on the directory to allow yourself write access.\nDrPython will now politely ignore your request to save.\nTry again when you have fixed the problem."), "Write Error") return #STCDefault if self.parent.STCUseDefault: self.parent.STCUseDefault = 0 #Main shortcutsfile = self.shortcutsdirectory + "/shortcuts.dat" try: drShortcutsFile.WriteShortcuts(shortcutsfile, self.ShortcutsArray[0], self.parent.ShortcutNames, self.txtIgnore.GetValue()) except: drScrolledMessageDialog.ShowMessage(self, ("There were some problems writing to:\n" + shortcutsfile + "\nEither the file is having metaphysical issues, or you do not have permission to write.\nFor metaphysical issues, consult the documentation.\nFor permission issues, change the permissions on the directory to allow yourself write access.\nDrPython will now politely ignore your request to save.\nTry again when you have fixed the problem."), "Write Error") return #DrScripts shortcutsfile = self.shortcutsdirectory + "/drscript.shortcuts.dat" try: drShortcutsFile.WriteShortcuts(shortcutsfile, self.ShortcutsArray[2], self.parent.DrScriptShortcutNames, "", False) except: drScrolledMessageDialog.ShowMessage(self, ("There were some problems writing to:\n" + shortcutsfile + "\nEither the file is having metaphysical issues, or you do not have permission to write.\nFor metaphysical issues, consult the documentation.\nFor permission issues, change the permissions on the directory to allow yourself write access.\nDrPython will now politely ignore your request to save.\nTry again when you have fixed the problem."), "Write Error") return #Plugins x = 3 l = len(self.ShortcutsArray) while x < l: plugin = self.ShortcutList[x] if plugin.find("") > -1: shortcutsfile = os.path.join(self.parent.pluginsshortcutsdirectory, plugin[plugin.find(':')+1:] + ".shortcuts.dat") try: drShortcutsFile.WriteShortcuts(shortcutsfile, self.ShortcutsArray[x], self.PluginShortcutNameList[x-3], "", False) except: drScrolledMessageDialog.ShowMessage(self, ("There were some problems writing to:\n" + shortcutsfile + "\nEither the file is having metaphysical issues, or you do not have permission to write.\nFor metaphysical issues, consult the documentation.\nFor permission issues, change the permissions on the directory to allow yourself write access.\nDrPython will now politely ignore your request to save.\nTry again when you have fixed the problem."), "Write Error") return x = x + 1 self.update() if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, ("Succesfully saved shortcuts\nand updated the current instance of DrPython."), "Saved Shortcuts") def OnbtnUpdate(self, event): self.update() if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, ("Succesfully updated the current instance of DrPython.\nClick Save to make it permanent."), "Updated Shortcuts") def OnList(self, event): sel = self.cboList.GetSelection() self.ShortcutsArrayPos = sel self.pnlShortcut.Reset() if sel == 0: names = self.parent.ShortcutNames elif sel == 1: names = self.parent.STCShortcutNames elif sel == 2: names = self.parent.DrScriptShortcutNames else: names = self.PluginShortcutNameList[sel-3] self.boxShortcuts.Set(names) def OnSelect(self, event): sel = self.boxShortcuts.GetSelection() self.pnlShortcut.SetShortcut(self.ShortcutsArray[self.ShortcutsArrayPos][sel], sel, self.ShortcutsArrayPos) def update(self): self.parent.ShortcutsIgnoreString = self.txtIgnore.GetValue() self.parent.Shortcuts = self.ShortcutsArray[0] self.parent.STCShortcuts = self.ShortcutsArray[1] self.parent.DrScriptShortcuts = self.ShortcutsArray[2] self.parent.ShortcutsActionArray = [] self.parent.ShortcutsArgumentsArray = [] drShortcuts.SetSTCShortcuts(self.parent.txtPrompt, self.parent.STCShortcuts) self.parent.STCShortcuts = drShortcuts.SetSTCShortcuts(self.parent.txtDocument, self.parent.STCShortcuts) self.parent.Shortcuts, self.parent.ShortcutsActionArray, self.parent.ShortcutsArgumentsArray = drShortcuts.SetShortcuts(self.parent, self.ShortcutsArray[0], self.parent.ShortcutNames) #Plugins: l = len(self.ShortcutsArray) if l > 3: x = 3 while x < l: sArray = self.ShortcutsArray[x] a = x - 3 ly = len(sArray) y = 0 while y < ly: yName = self.ShortcutList[x] + ":" + self.PluginShortcutNameList[a][y] yName = yName[yName.find(':')+1:] if yName in self.parent.PluginShortcutFunctionNames: i = self.parent.PluginShortcutFunctionNames.index(yName) try: self.parent.PluginShortcuts[i] = sArray[y] except: pass y = y + 1 x = x + 1drpython-3.11.1/drEncoding.py0000644000175000017500000001561011232251305016675 0ustar dktrkranzdktrkranz#Edited by Dan: #Now takes raw encoding as arguments for Set/Get EncodedText. #Also removed some uneeded code. #*************************************************************************** #drDetectUTF_8 # Programmer: limodou # E-mail: limodou@users.sourceforge.net # # Copyright 2004 limodou # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import wx, re def utf8Detect(text): """Detect if a string is utf-8 encoding""" lastch=0 begin=0 BOM=True BOMchs=(0xEF, 0xBB, 0xBF) good=0 bad=0 for char in text: ch=ord(char) if begin < 3: BOM = (BOMchs[begin]==ch) and BOM begin += 1 continue if (begin == 4) and BOM: break if (ch & 0xC0) == 0x80: if (lastch & 0xC0) == 0xC0: good += 1 elif (lastch &0x80) == 0: bad += 1 elif (lastch & 0xC0) == 0xC0: bad += 1 lastch = ch #modi limodou 2004/04/16 #if all characters are ascii, its encoding also can be ascii encoding or default encoding #in most cases, I think it's better that not recognizing it as utf-8 encoding if ((begin == 4) and BOM) or (good >= bad and good > 0): return True else: return False #/drDetectUTF_8 #*************************************************************************** #Autodetect: If the user has enabled autodetection, #and the file has the proper special comment for encoding, #return the encoding used (or None if nothing is found): reencoding = re.compile(r'\#\s*-\*-.+-\*-') def CheckForEncodingComment(text): encodingmatch = reencoding.search(text) if encodingmatch is not None: t = encodingmatch.group() i = t.find(':') + 1 encoding = t[i:].rstrip('-*-').strip() return encoding return None #What if python is not built with unicode support, but wxPython is? #So, here is a safe way to test for ascii. def CheckAscii(text): #Optimize this a little. _ord = ord for a in text: n = _ord(a) if (n < 0) or (n > 127): return False return True def DecodeTextWith(text, encoding): #Try the encoding try: text = text.encode(encoding) return text except: pass return None def DecodeText(frame, text, encoding=''): if wx.USE_UNICODE: etext = None if encoding != '': etext = DecodeTextWith(text, encoding) if etext is not None: return etext defaultencoding = len(frame.prefs.defaultencoding) > 0 if frame.prefs.autodetectencoding: enco = CheckForEncodingComment(text) if enco is not None: etext = DecodeTextWith(text, enco) if etext is not None: return etext if utf8Detect(text): etext = DecodeTextWith(text, 'utf-8') if etext is not None: return etext if defaultencoding: etext = DecodeTextWith(text, frame.prefs.defaultencoding) if etext is None: frame.ShowMessage('There was an error using the encoding "%s".' % (frame.prefs.defaultencoding), 'Decoding Error') else: return etext if CheckAscii(text): return text if etext is None: etext = DecodeTextWith(text, wx.GetDefaultPyEncoding()) if etext is None: raise Exception, 'Encoding Error!' else: return etext else: return text def EncodeTextWith(text, encoding): #Try the encoding try: #AB, 25.02.2007: import types if type(text)==types.UnicodeType: return text text = unicode(text, encoding) return text except: print "ERROR EncodeTextWith ",text,type(text) return None def EncodeText(frame, text, encoding='', returnEncoding=False): if wx.USE_UNICODE: etext = None if encoding != '': etext = EncodeTextWith(text, encoding) if etext is not None: if returnEncoding: return etext, encoding else: return etext defaultencoding = len(frame.prefs.defaultencoding) > 0 if frame.prefs.autodetectencoding: enco = CheckForEncodingComment(text) if enco is not None: etext = EncodeTextWith(text, enco) if etext is not None: if returnEncoding: return etext, enco else: return etext if utf8Detect(text): etext = EncodeTextWith(text, 'utf-8') if etext is not None: if returnEncoding: return etext, 'utf-8' else: return etext if defaultencoding: etext = EncodeTextWith(text, frame.prefs.defaultencoding) if etext is None: frame.ShowMessage('There was an error using the encoding "%s".' % (frame.prefs.defaultencoding), 'Encoding Error') else: if returnEncoding: return etext, frame.prefs.defaultencoding else: return etext if CheckAscii(text): if returnEncoding: return text, 'ascii' else: return text if etext is None: etext = EncodeTextWith(text, wx.GetDefaultPyEncoding()) if etext is None: # Patch by knuger, Jan 2007: added "Please try..." to error message raise Exception, \ 'Encoding Error! Please try another Default Encoding (See Options -> Preferences -> General)' else: if returnEncoding: return text, wx.GetDefaultPyEncoding() else: return text else: if returnEncoding: return text, '' else: return textdrpython-3.11.1/drFileDialogPrefs.py0000644000175000017500000002575711150445514020171 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Prefs Dialog for File Dialog import wx, wx.lib.dialogs import drScrolledMessageDialog #******************************************************************************************************* class drEditTwoStringsDialog(wx.Dialog): def __init__(self, parent, label1, label2, title): wx.Dialog.__init__(self, parent, -1, title, wx.Point(50, 50), wx.Size(-1, -1), wx.DEFAULT_DIALOG_STYLE | wx.THICK_FRAME) self.txt1 = wx.TextCtrl(self, -1, '', size=(300, -1)) self.txt2 = wx.TextCtrl(self, -1, '', size=(300, -1)) self.btnCancel = wx.Button(self, 1, '&Cancel') self.btnOk = wx.Button(self, 2, '&Ok') self.theSizer = wx.FlexGridSizer(3, 2, 5, 10) self.theSizer.Add(wx.StaticText(self, -1, label1), 1, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, label2), 1, wx.EXPAND) self.theSizer.Add(self.txt1, 1, wx.SHAPED) self.theSizer.Add(self.txt2, 1, wx.SHAPED) self.theSizer.Add(self.btnCancel, 1, wx.SHAPED) self.theSizer.Add(self.btnOk, 1, wx.SHAPED) self.SetAutoLayout(True) self.SetSizerAndFit(self.theSizer) self.Bind(wx.EVT_BUTTON, self.OnCancel, id=1) self.Bind(wx.EVT_BUTTON, self.OnOk, id=2) def GetValues(self): return self.txt1.GetValue(), self.txt2.GetValue() def OnCancel(self, event): self.EndModal(wx.ID_CANCEL) def OnOk(self, event): self.EndModal(wx.ID_OK) def SetValues(self, value1, value2): self.txt1.SetValue(value1) self.txt2.SetValue(value2) #******************************************************************************************************* class drFilePrefsDialogBase(wx.Dialog): def __init__(self, parent, title): wx.Dialog.__init__(self, parent, -1, title, wx.Point(50, 50), wx.Size(-1, -1), wx.DEFAULT_DIALOG_STYLE | wx.THICK_FRAME) wx.Yield() self.parent = parent self.ID_ADD = 1003 self.ID_REMOVE = 1004 self.ID_CANCEL = 1005 self.ID_OK = 1006 self.ID_LIST = 1300 self.ID_UP = 1111 self.ID_DOWN = 2222 self.btnUp = wx.Button(self, self.ID_UP, " Up ") self.btnAdd = wx.Button(self, self.ID_ADD, " Add ") self.btnRemove = wx.Button(self, self.ID_REMOVE, " Remove ") self.btnDown = wx.Button(self, self.ID_DOWN, " Down ") self.btnCancel = wx.Button(self, self.ID_CANCEL, "&Cancel") self.btnOk = wx.Button(self, self.ID_OK, "&Ok") self.lstItems = wx.ListView(self, self.ID_LIST, size=(500, 350), style=wx.LC_REPORT | wx.LC_SINGLE_SEL) self.items = [] self.theSizer = wx.FlexGridSizer(4, 2, 5, 10) #self.theSizer = wx.BoxSizer(wx.VERTICAL) #self.mainSizer = wx.BoxSizer(wx.HORIZONTAL) self.menubuttonSizer = wx.BoxSizer(wx.VERTICAL) #self.okcancelSizer = wx.BoxSizer(wx.HORIZONTAL) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(self.btnAdd, 0, wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(self.btnUp, 0, wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(self.btnDown, 0, wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(self.btnRemove, 0, wx.SHAPED) self.theSizer.Add(self.menubuttonSizer, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.lstItems, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.btnCancel, 0, wx.SHAPED | wx.ALIGN_LEFT) self.theSizer.Add(self.btnOk, 0, wx.SHAPED | wx.ALIGN_RIGHT) self.SetAutoLayout(True) self.SetSizerAndFit(self.theSizer) self.Bind(wx.EVT_BUTTON, self.OnbtnUp, id=self.ID_UP) self.Bind(wx.EVT_BUTTON, self.OnAdd, id=self.ID_ADD) self.Bind(wx.EVT_BUTTON, self.OnRemove, id=self.ID_REMOVE) self.Bind(wx.EVT_BUTTON, self.OnbtnDown, id=self.ID_DOWN) self.Bind(wx.EVT_BUTTON, self.OnbtnCancel, id=self.ID_CANCEL) self.Bind(wx.EVT_BUTTON, self.OnbtnOk, id=self.ID_OK) self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnActivate, id=self.ID_LIST) def OnActivate(self, event): sel = self.lstItems.GetFirstSelected() if sel == -1: return d = drEditTwoStringsDialog(self, self.dlabel1, self.dlabel2, 'Edit ' + self.dtitle) d.SetValues(self.lstItems.GetItemText(sel), self.lstItems.GetItem(sel, 1).GetText()) answer = d.ShowModal() v = d.GetValues() d.Destroy() if answer == wx.ID_OK: y = self.lstItems.GetItemCount() self.lstItems.InsertStringItem(y, v[0]) self.lstItems.SetStringItem(y, 1, v[1]) def OnAdd(self, event): d = drEditTwoStringsDialog(self, self.dlabel1, self.dlabel2, 'Add ' + self.dtitle) answer = d.ShowModal() v = d.GetValues() d.Destroy() if answer == wx.ID_OK: y = self.lstItems.GetItemCount() self.lstItems.InsertStringItem(y, v[0]) self.lstItems.SetStringItem(y, 1, v[1]) def OnbtnCancel(self, event): self.EndModal(wx.ID_CANCEL) def OnbtnDown(self, event): sel = self.lstItems.GetFirstSelected() if sel < self.lstItems.GetItemCount()-1 and sel > -1: txt = self.lstItems.GetItemText(sel) value = self.lstItems.GetItem(sel, 1).GetText() self.lstItems.DeleteItem(sel) self.lstItems.Select(sel, False) self.lstItems.InsertStringItem(sel+1, txt) self.lstItems.SetStringItem(sel+1, 1, value) self.lstItems.Select(sel+1, True) def OnbtnOk(self, event): self.EndModal(wx.ID_OK) def OnbtnUp(self, event): sel = self.lstItems.GetFirstSelected() if sel > 0: txt = self.lstItems.GetItemText(sel) value = self.lstItems.GetItem(sel, 1).GetText() self.lstItems.DeleteItem(sel) self.lstItems.InsertStringItem(sel-1, txt) self.lstItems.SetStringItem(sel-1, 1, value) self.lstItems.Select(sel, False) self.lstItems.Select(sel-1, True) def OnRemove(self, event): sel = self.lstItems.GetFirstSelected() if sel == -1: drScrolledMessageDialog.ShowMessage(self, "Nothing Selected to Remove", "Mistake") return self.lstItems.DeleteItem(sel) if sel > 0: self.lstItems.Select(sel-1, True) def SetColumns(self, label1, label2): self.lstItems.InsertColumn(0, label1) self.lstItems.InsertColumn(1, label2) self.lstItems.SetColumnWidth(0, 250) self.lstItems.SetColumnWidth(1, 250) def SetDialog(self, label1, label2, title): self.dlabel1 = label1 self.dlabel2 = label2 self.dtitle= title #******************************************************************************************************* class drFilePrefsDialog(drFilePrefsDialogBase): def __init__(self, parent): drFilePrefsDialogBase.__init__(self, parent, 'Edit Wildcard') self.ancestor = parent.grandparent self.SetColumns('Label', 'File Pattern') self.SetDialog('Label:', 'File Pattern:', 'Wildcard Entry') self.txtConstant = wx.TextCtrl(self, -1, self.ancestor.prefs.constantwildcard, size=(500, -1)) self.theSizer.Insert(2, wx.StaticText(self, -1, ' '), 1, wx.EXPAND) self.theSizer.Insert(3, wx.StaticText(self, -1, ' '), 1, wx.EXPAND) self.theSizer.Insert(4, wx.StaticText(self, -1, 'Constant Wildcard:'), 1, wx.EXPAND) self.theSizer.Insert(5, self.txtConstant, 0, wx.SHAPED) self.Fit() wcarray = self.ancestor.prefs.wildcard.split('|') l = len(wcarray) - 1 x = 0 while x < l: y = self.lstItems.GetItemCount() self.lstItems.InsertStringItem(y, wcarray[x]) self.lstItems.SetStringItem(y, 1, wcarray[x+1]) x += 2 def GetConstantWildcard(self): return self.txtConstant.GetValue() def GetWildcard(self): l = self.lstItems.GetItemCount() if l < 1: return 'All Files (*)|*' wcstring = self.lstItems.GetItemText(0) + '|' + self.lstItems.GetItem(0, 1).GetText() x = 1 while x < l: wcstring += '|' + self.lstItems.GetItemText(x) + '|' + self.lstItems.GetItem(x, 1).GetText() x += 1 return wcstring #******************************************************************************************************* class drReplaceTableDialog(drFilePrefsDialogBase): def __init__(self, parent): drFilePrefsDialogBase.__init__(self, parent, 'Windows Shortcut Replace Table') self.btnUp.Show(False) self.btnDown.Show(False) self.SetColumns('Windows Pattern', 'Replace String') self.SetDialog('Windows Pattern:', 'Replace String:', 'Replace Table Entry') self.ancestor = parent.grandparent wcarray = self.ancestor.prefs.windowsshortcutreplacetable.split('#') l = len(wcarray) x = 0 while x < l: y = self.lstItems.GetItemCount() if wcarray[x]: items = wcarray[x].split(',') self.lstItems.InsertStringItem(y, items[0]) self.lstItems.SetStringItem(y, 1, items[1]) x += 1 def GetReplaceTable(self): l = self.lstItems.GetItemCount() if l < 1: return '' wcstring = self.lstItems.GetItemText(0) + ',' + self.lstItems.GetItem(0, 1).GetText() x = 1 while x < l: wcstring += '#' + self.lstItems.GetItemText(x) + ',' + self.lstItems.GetItem(x, 1).GetText() x += 1 return wcstring drpython-3.11.1/bitmaps/0000755000175000017500000000000011246265352015717 5ustar dktrkranzdktrkranzdrpython-3.11.1/bitmaps/install.wizard.png0000644000175000017500000005557311150445515021404 0ustar dktrkranzdktrkranz‰PNG  IHDRª,Sè(óbKGDÿÿÿ ½§“ pHYs  šœtIMEÔ 7ÿæHÖtEXtCommentCreated with The GIMPïd%n IDATxÚì½w|÷}çýž™ÙÞ°»¨@ì¤DR”(‘j´ŠUܤؖ}rì䟜ø9_ûâKîâ¯×¼˜]Ì.fÞûý}Ûï7ÂÃÏ–LlÙºÌ%Ú§À– ª-[6¨¶lPmÙ²AµeËÕ– ª-[6¨¶lÙ Ú²AµeËÕ–-T[6¨¶l-·ïÔûOô dSx§N ç³(™¾Ûwx]øƒàiôà K4ìh°¯” ê¥Qpð(áã‡h:°‡ðÀaÜÓã(¹ŽRaÁë®c®ëPBÇ+æ©sϔٴ¥ÌªmN:vGí+÷“p±ûQ;öüU{~@øøÛ¸g'Ïü8ýÇQ•–`Š­ÛU¶ßí¢m»ß¾Š6¨ç¯ ?þ+:Ÿ|˜àP¢aœýâì?N@ÎsÍæ$7ÝïbíM>ûjÎSºP`|rœxbšt.‹Z.#NE&èõщÒPÁë ¾7A]ÿÓ¿aíÏ¿Mp¸› ðs wÞó+áeµ*§¨²sK‚÷}ÊCÇ5î÷,œñÄ4†F9"µ1Z’Ðä €iº®£j*f¹@°0ÁgMž2[V¯&®¿òAy…mßþõ‡ö!`PùšßÏ‹ŠR{ÝŽr™ÿžÉ°N×ñ,¨5?Ø™çƒ÷å¹ëó÷ ý£'øåŒ‹#4#›&~³„Kv ˆ’h%vL,V ÓDÕtŠZ™œ¦“UK´2Ñâ(7( voXC}Cë• ê¦Gþ‚M|gz¦¶ï)àÑPˆõ=Dã5×ÔöO9‘¿ÿ{îŠÇù ,#¨"›VgøäWœ´®s\Ñ€¦3IþuÔà%½ˆ¡ÓàºEœŠ€è&€i€aZ°ê†µ_-ËeR…3¥"ùR™Ha„»ƒ³ì¼j+àå´^ð•¼þ_ ó©ï!•U²Àaà`[Ån`×Ç>Æu×]W{ý[o½Å¡áaíÝ‹ÒߨpXÈçõy ê “ø¯>óe7:¯HHÇùþdˆ²àcGؤ³ÁßcYμ 9Je(똦Yµ¨x pÉ"͉Wq(8):ghjl$ílá‰c4^âÖ[?üî·¨·õ4¾ñl-X*ÝÀ×€Î_ÿu¾ðû¿O4Ãáp N§Ã0ˆOLðwñüà[ß©(ˆ’T;æ`ù!J¥/cšõü= ¸ |ò!›î»²`ý·ã'x¤¸Š§À-kas80›…©$Ìd!W²@Õ«–”9XMÓ²°ººªR1Å–X†‡náü·_Ä™˜œdÅì1n}ßý§ý<¹Ì,“c½ÌN@0TôrÐM _ FcÛ" í‚pé-ê_¹›¦7Ÿ«ý®Ïÿ¼´û|¸=~üãsôèQÜn7ùÈG¸á†ˆÕ×cø|˜ÍÍ|øX±bEí8û÷gxôÑo’Ïÿ °í†Ƣ›‡¿©¥+Öç{†øgu5×GL>±S`ëJ( 0”€BÅ’ªº5ì#‚(Vʦ‰€€aš†ªÃ„²N=͆Æ4_ºµ‘˜Oæé“X$€ªÌ*/<÷Sn}ßG|ŽR!GßáINAÏÇñ8EÆ4MÓ¤\.£•JŒåè; #¹hßx+¶Ý¬8/ ¨·õ4½ù:p4à§Qø~´ ëuår™žžöïßßïg×®]¤R)Ž;†Ãáà¶ÛnãsŸûëÖ­«ûñÇgbâxë­f Ð (ç}a‹e…‡¿ ²[ãú»ÞÝ>ëëC£üX]Í- &ÿÏ"×ÕÁ,0Q„ø,L§![ÕSAQA¡TÄ™Åôã–JªI¡¬ãtŠlípp߯F|.™G{a4kš¼ø]ƒãyÇ&^|þ§Ü²û£”Õ"]G9BCÄMc›IZiZ³a†išèºN©T"“É099É¡çÿŽ‘¾×¹ñžÏã FQ<»*þ9ý×ã ¬~ü»†AøÿDø‘¦Ó÷ÀÔ60_¸ó üá×þB¾@.—C’$èííåÏþìÏØ±c<ð¸\.A@’$R©]]=üÉŸüž|Rþ¸ðj,çó$°v«ô®„ttj’¯OµpuÈàw½f€·Tè…‘)Hæ¡¤Í õ–E$0&G‰”g¹eË*®ZáÄ œ§ƒ™2¼:ã9PD0MMavbߨÜê([7µ‡I§Ó”ËeŠÅ"©TŠd2I>ŸGE¼^/>Ÿǃ(Š FFFèïïG vpûG¿J Ã!+g圓‰ÙôÈ_ÐùÔ÷ ƒ^à_ð‹­pdƒ5ÌpÐ|¨øÎÃßácù›6mšógr9úûû¹á†ðz½<òÈ#Œ‡ùЇ>DGG«Ww f€TÅV_¸¦Ò~ø,ôð»TM+ó½!“Æ À¯ÝbAZºu86Q4EÝò?ÁºBuè¬GêÉŽ¤y}`–’ÔȺf™¬ ÉHªVàrWýXÓ4YÕà=€VŠQN»¹yõZ——T*…¦i ÓÝ}ŒÙŒŠnÊHŠ»â£ˆ*ím+X±b~¿ŸU«VÐÓÓÃÞÇÿŽÛ>òE<¾YY>P£G^aÓ#_¯E÷ýÀ·dÞµ<“Xy|?xá#?!ÒAÓæ`FU­c$“Iž}öYºººhiiáú믧££ãâåG|üßäø?”ßU îíîcʳ…Oo„;Z­ õ¨ ]q8¯@ªYi(Q˜TAæ`œfS+¹‰A'ýh¢¯SÀ4­çÉJ¸š€‰•â’“17³éc™5ì…uMER™¯ì?ÀTR'X¿U«Zñ‡¢8еT`&>ÌðñýÌÌbóæMD":;;Éçót{‘cooeóµw"ˆ"’äXP·}ûk ò¤–#nHKd’$0¶L‡§ùëŸý5ÿÝõ§R©SSS´¶¶ò{¿÷{d³Y\.«W¯¾èý•} /³óÞw‡¿šË¦x²ØÊ†FؽѺ`=&™„áq˜­@ªÏƒT’À1Vqž¯*†|¨Å(‰øN—Œs#Vr®Õö\vÀ ¾$I"öŸÑ7 ùê+ôH¨_ÏÆ› „bxýaœ.’CAELÓ¤¥}ë·ÞÊ¡ýÑ}ì Û¶º ƒ´··3>>N÷›¿¤µój‘f$÷2€ºþ§Cý¡}€5ä¼ü¢r;€U§ø£:P*GGBy¾iyÌ+‰Wèx¼ƒÛo»X,V{º««‹§ž{ŠÞ`/ÜP„ƒ?„âû-ËráKšÌã?*³óÞw‡5}y` Ó½…­­P†aàØ C"…²å“ ˜ˆRTaÞ&‚Ø#ߟfzz—S¦ÎïÀXTÃÃ0 ø\„‚~füí¼ñúólÞ|;±¦•øƒ1á˜5„;ú›¦ibè;ïø ¯>#2<ÜÏÕW_M,£¾¾žîÞ^&Fúð"8ÝÞ uíÏ¿]Ë•æ€G€^Å_Oó‡àΓÝ̲Væ©§ž"þq¢õQ6­ŸóaŸ{é9¾þƒ¯ZM˜üŒP\—£FÁ‰Q'O|¯Ä=Ÿ¾¼­ªaš¼,o¤Y(Ó“É0•1+ÂÏ«–%¬ù¢Uk*YRå÷* ‚`yf²"a67‘8>€ìò ;‚¸jïPRƒ XÂe–Á#’‰º˜˜n@ ¯$i¢qżþ0Ù‰$9N ŠA@QdÇmòÜOþ”B¡€Ïç#"öö1B[» Ã0N›8ã•Úðã¿"8Ü=÷-ò@Þ¸ÏP@ge[X>¢´³DW¬‹?þÖÌÍuðŒÄFˆ N¹³l}º? ? /O¿]‰Ö.$^x\âžO_ÞÖtxì‰r'«ê +hš˜É”•Ð× *M'ó|RqR‡<Ï’JÖë„Êïþ˜Ÿì¸“©ÉID‡ƒ¦ˆ‡(XÖˆyd5ÃØd‚ãSifò&¢+ˆ¢¸PZÖ ºe ]ž3þ’äÀëÓ¸jåò$.— ǃCÉegÐÔ†¡_¨O>¼àw'p0–€×_‡Âf å¯€´BZN³¯odæ=·ª’=¨6AmÑà£@øì²A0w°ç‘w~òòµªGFãx=«ð:%òEÈ—a* é¢UM2…¹!¿ ¤£bA% ´B‰ìä ¦®U¢$_4„C–o}Œ©ÞaüÅ< AcIˆšir3ãüòÐ ½³"Ù¼I¡Ç-O±ªµoËZ£oŸs¥Ééò‡q:hš†nˆ¢Œ®—1ÏÐ zګԱ燇ºìóUpi‚¯| ž¨µä&ðÉJY«*p-þÅ4…Ê „ ¶ª/?#pç'/c‹êéÄ¥³YÐLH­Ò¨aÎ}ç«C»4Òb&OXeצYm@1Iie’¹é¬N6¯‡ùkƒx½"?œ‚:I¥Ið“CŒ¬Þ´ ­¬˜Í086ÌälœX$ÄP*C©˜Gqº1 ƒ™x?2y-^JcêEêÂtÃ`zzAöãÖG [H¥RÄãqÊeo ®æ&œ7¨«öüदg±â)†43X¹’󕜩A_v Áž¿„ħ€VþøÂ48 sx¿ÎæÂe©f˜L•À©XCülÎòG‹Z%BŸïwÎ –„Ê0_*D‘»6)¨ä`ŵ%äl˜dt“5N˜Kä_ëÔ Ü’Á“%Æò7ܲ›\re+uåV\LçøËñ¢Irj¡0H½_eÃ’( ŠaD1€ªªVŪ³UUÉåÜd2TUµ|Rg/„$Ɉ¢t~ ZsœÞ>åÖ;txmFÞªìl¨l§»îY`«súlútÀ€IxùQHlîYP5ÃÁÁ}e6ï¸üŠ%]'c8ð–Í,+¡UÊ£UwNúžUWCgx¦È“ã:#“ÅRÅêŠ,àu x˜4!Y2³3$f¦8‘Öš˜ÂérY¾¯PÍ$ˆH‚Hºn3Ë»:¸aµJcC´fGígAjeT]×QUI’$ EQ¸ãŽ;p£©%«)é|-jøø¡ÓÎqº øSþòyøþ‹íÐ>p†WÝ»/x¿`õ½<+U…lÝa5€«U« J%WZ ¢ª óâW‡ì`¶XfbFC¥ZÇ””KVO€aZ^—×aà*•xôõ!ÊHÈŠƒk®¿Œ9øUC$¤¨Ü¹IçÞµ Muk]^\.n·I’Ðu}A­¿ ª¦i(Š‚,Ë8TUE–eÞwÓ5¼üzÙô ¾`YvžÒ8%¨MöœöDz€Õ&<†¶4߯fáŸ~ºx†á~#Öœ”Ë@ñ1êh_}yÝsCÕÊY”u«†/U£{áääÊü]†X˜øØ É\™°Ï‰ªÍYá“FS eH¤óe®Ùyíí+Èå T¨´ ê:ÛƒìêœeUÌÛÀ áóùP”¹Ü©¦iµa}þ¦i‡Qd2ɱcÇ0M“u î~_ ‚?=eíÿÔuàðO¦ ìnúU¿.ü„Iï §¯ÎgÖ‰¡$cÕaB_âtÖÕ‰•WMOÀl7VW•·âu éE!_Ûy±%*?E…ñãÚW_^–UE0 LSD3Lʺe6¡’—_ü½2î€\IÃ-›½pbÊD^â_ÔIEÌRÍÐQ'š†n¹aRÜbC¸H0&P#Ô†ù0UúŽç[VÃ0$©–zÒup8LCC¯½ö©Tа/ÈØÐQV®ÝŽ Š8òÙê?у{züŒ'ÓŒ?å·hÿÉÇmÏ'¸j‰s8_†áϾ #òÜ5ï>0/'»°MÀ§uøÙÏáÉiÐÿ¸Hÿ ø·y/Þü°â¬|‹Ánƒ@uË2bqCŽ`&º! UñR¥r„y2 f5hRuPîZåæíI“¢f`,¶¼xÄ>5ÁcGú Fëhn‰‘Í©élFØ'tжQWW‡¢(gÈ™JµjØ*¤†aÔ†¯×K4åðáÃl߾ɱ.bM«ò’Ń%AU²)”\ê´¨ hŸù³ÔcÈOÓj¥GO«PRƒ˜·o¿ öåAsÀVNnAuí&DÆAèªDeo‚ë1¸î—ÐÒ=/Iš„QÈ~°â ŸÖé©Ë¯IÅåtâ)cøê0 C1$ËX éü®}³’ O³½ÅKƒ,Ò7e æICDÜEÎÒ;[äC¼‰‚ Þr†«ÅVùŠ„"õÔ74áv»”FOªíÌ«LUª*¨š¦Õ|YMÓ…BhšF6›%—)“ËÌâñ…0]æÙê:qÒ &KêüS(ÿ®ŠkÏÐYÇD+/Î3&ð#?fuªìŒBlšŒ“ó©'©œÂ¶˸ •t×ðLÿor­•„í©Ý€ÄÔåLÉŠ‹°W!SVÑ¥6ÏiÁt’E–µ2#]3ì>JÊíà3£EÂÁ:n7šfT‚k³Ö•7tÞËâ<^7±ô8›ÅBnð‡c‚! …ÙlQk[5‚¯ZPI’–,¡V·ªeu8ÌÌÌÔÜ€B¡€¡ ótMΪœÏžùDþG‚ ¬ÖÎ)p—æªú°›uë~Ç[Ÿ…â7ᣙ³èC¹r.øÅŸÃ¾W-°?l0à×ÓðØ?ÁóÓ`~X{Ê£èªùΧ–°P-êo»1t Ã1 Ѳš‹·Ê„=QC k¯ÙHWÏñÉi\n7+ëtfU(DQÂ!¸ƒŒf’PE<¬ËöNö.—I‰ÎéY\.Š¢àr¹j¾,Ë(Šr’°¬óu8är9‰n·›B¡€¦iˆ¢ˆ¦ëhzÃÐÏ>ê¯.Xv*¿´ü~~J@~@E/"}ëü3›í•Xê% 3<ÃÕë Þ Y™¬“ÂÛN`g =Év3ôYÉVg ü@è…Õ4¯”^3§°‹Æ²äe—[kë|¼”V )¢5übm¾Ó|HMÃÔA4A/C f×Î0O<û&éÉ1ޤu ¢AV×¹Yã/ ‹œHiÔ+e¶ƒ <õ*ûSY …Šì ±©‰¦ÆF"‘^¯·ÛM©TªA[«~g5p’¤“Ï¥,Ë z{{Q…R©Tk÷t8¢\±¤ç˜ž:uéÔ:ÿ¤¯¦)½$âøŒã[¹ó¾Ôy`@„‡ýpûí?â¡ÿœçoò0; }®\ˆX‰“¢q(ü NCéwÀüŒõªIxáÿ…L/üF¥ÒêÓ ? z®’T»üªP§Òš•x_¥¤¬@‘5º„.ŠèÕN)cnê³(€©[Å(« (Ðvsøà›H’¤àkè`³×Íþƒ#œÈá3òÜ(ôÐvAÄÔ5t­L"“&sT– ‡Ã´´´ÐØØH4Åï÷ãñxðx<¸ÝîšÕ•e¹mÕE¨ZXAèêê¢X,â÷ûezzš@ÀÊ;œ>DQ:ecÊ9ƒ*ŽŸ€ùMàQã©Ây7ß™ÀÓÀQØùìøP޵­ðù4yáïGa¦¼(MµB·¸uOÂó9Pÿ#°ÍºJEÅ"_¬”^#ð‹ÿ ¿|ô¬RV—‹¼ÞW‰¯sPkÆ]VÑ% CR0tkŽšaXi$]˜ö }î«XVáªÍëÙ¸¾‡2é,{_>Ê/ßIbëšVÖN<Çî-[Ù²ý::ÌÑ£G)‹˜¦‰¦i Òé4===twwã÷ûijjbÅŠÄb1^¯·fqNçIÐ:tˆ©©)"‘©TЉ‰ 2™ mmmJÅCv"ž¢Óɽª¿îÔ¾àš=: g\Ðéözác»aÇkßN$5øÞø)ª Û€á^Ø—µ:µZ¶jfépô0\•‡í³ðÂ˜Ø Ü·äû+®Ëw=ã›:[yåXœ¢Ô€,I8D]ѵy )HõùÉÿJ»ž`‚C’€h4L,ìÁí ²më&ÄýÿÄZ¹óž¢ë:n·›ºº:J¥Ò‚ HUU …™L†T*Åàà 5h[[[kÐúý~¼Þ¹Š•(Štuu122BCCªª266ÆÄÄ¢(‰Dèž&ÔÂåñãp(K–S—µì¹¸+㙀ZÙLÀTÀã…Å9dà•@@5Oñ5s™P,TºªÜÀ¯Á‰xøwáãC°¹bDeʹÊ/ I¹|Ý­«¹îØ/yK­Ãé‘DIÑiT榫ÌkT|5³â4XÕÞJ}sõØ:õ8·ßõyLÓ䨱c$‰“†íjŠÉ0 êëë)—Ë …Ú”¢£GÒÕÕE4¥££ƒööv¢Ñ(áp]×9vìSSSµÙƽ½½LLLÇinnFŠš/ˆËí=åÜ)éþ_ûÚtýóY:žù¢®]”“¯a­MõàYÀ±îø,\»‚óVA”ˆÈÖa¨x P&Lg ¥k€ “P~ 6ÌZM ¬äÄ ­@d¡/¸^gÇm—¯ ÐìsñRÿ0†@-xDA°æÅ/òºÔüçåM@,ð‚¨¹î#ÿ—÷ßr=­í+¤··—b±ˆ$I8ŽÚÐ=?¯Q¿ßO$!‰àr¹H&“?~œÁÁAŠÅbmUœ#GŽ ……¬4WOO}}}¤ÓiÖ­[ÇÔô E!B´©ƒºØ œnËW=«<ªê ¢zƒgÌ¥ž+œCÀ$Pà'1ø¾Ì8|õZøä¯‚gQ³øJ7|ºzòðÂì]spøg0¬TÊ[~‹Ls LafvSà`´[OJUEceÎw­«K¡h} ÷×÷óýÙYd jeBSÓšI*˜sÔ4*þ˜èF‰°’CJÇ™˜â)Åiqët®Ý@"‘```€r¹Œ,˵S5Týy~²ß0 Ün7^¯—`0H$¡¡¡D"ÁÈÈ{÷îett”üã„B!&&&ðù|5+<>>N[[›µŽCN'XߌÛ@qºO‘âZÔLëZ Ñ&<3Ër¢J%þ»"<*€)Ãä-`¬áûãÒ®í`ßÿ‚Ôwà3§÷¡W®¿üï¹±ãš~æ öå6!šB•FÃÄ4µ1_’¬¦ ·¥ŒÏU`}½ÄÍ+½¼>ÜÌt×ÊÐ>Ú¯^‰®ë 2;;Ëðð0™LY–éèè ®®‡Ã±dn´ kµáD–eœN'^¯—P(ÄÈÈGå­·Þâ†nàÀ‹E’É$£££†ASSétÕôЮÇã "9dk-×s‰úg;6éysYNò1à§ >Îðð0+W®´*Ý“I<Á5ø¼þ0’$Ã" ~FPǯ½“ÕO}ûqài7üí ˜¼¸‘¹Å*Þyš¹ìZüN%§Û˃»wóÈóÏòFy#õ>AW ɯñïw7Ñ– Š"’’CÄ%Âñ4<>}3 ‰Îâ$nƒÉ©i{ü ¦§§Ù¹s'Ñh”ÞÞ^J¥/¾ø"GŽ!VY‰QQ”“ò›UX«`Váªöš’É$år—Ë…ªªtuu!Ë2ÌÌÌVÝ´´6á ÔárûN9ìŸÞ¢v^E!\V7ˆ8•RX}M¿X ‰O€±úòs;וÞU¹U_ Žo»“оgx:…XŒ¦úz®kp³/n2’2Éd¡T6Ñ€tÉZ½OvˆÈ÷1ÞßÏ¡£ÇX»v-wß}7¹\Žááa\.‰D¢Ö?Z*•jÉúù¥Ð*¨ÖthqÁïUßVQr¹º®#IÃÃà °eËJ¥Ãi‚±«ð#µ)ׂ ž;¨©•™í¼÷§Ï넾 üÒOnî±ÒD縼þPž˜†·²góê>àÀ]XÙg–CÔØv«Â»M_Üöš_{ާr3Ô(¿ÿ³šB8àÂ¥(h:蚈(Hˆ‰b¡Lº{/Ù7Ÿ¡­)Ê=¼úúzúûûI§Ó8†††Ø¿-@ªåUHç[ÕjúªjY«U‹ƒ¯jöàÁƒ477ãóù8>pœM„£ÍÔÕW"ýÓ@zÆÊTÿŸZ°Pï¹èà/Ý0ù~àúE¾¨‰µäJŠ…3P©'5 ųxCåx¾”Â@Ü9+5uŠÚîÊŽËs¾ÔÙHVœìºñnÜo¼À³O>ƨ#J¸¾‘úH€ú°B׉׭àU$ô‰~&_~ gz„{︅-×\ËìÌ ]]]µÞÐ7ß|“×^{ºº:Ö¯_O$Áçó-¨ÛWat8¤R)^}õUt]gÛ¶m(ŠR¶ê¿V³ƒƒƒd³YV¯^Íøø³EM+WS[Ò]‹d IDAT?³¦ ˆêÀ²é‘¿ ýýý …Znó¥—^âàÁƒ466²jÕ*ˆF£8Κլn‡ƒt:Í /¼€aìÛ·žž>ðàp8Ð4­6%Åív“ËåˆÇã´µµ‘N§91¥mÝH]ý B‘Fœ.Ïg žT€ãw†k¿ù_ÎúÄe€ÀÁ&(_…ÕµÈq•ŽÂ†}°î•û“»á™_Âõ» ¾JÌÀ¿%¡p¶Æ<l/ƒñ6øÞ¶þ³­ŠêRjlÐ.ëÅ'ÎEÁº¶Ô5°áª]LO 2>6ÀÑ£/cN°¡)ÈîûïgÃÆMÄãqq¹\46ZQÿž={èë룥¥…¶¶6ZZZhhh  Š"ƼÑTE4McÏž=lß¾@ ÀØØ‡¢µµ•uëÖÕï- µÊÓªU«8~ü8ÇO$ 7m¢.ÖB]´Åš*í8u¤N v}üK¬yì» –õ9&€o/lâ§N*ÁÈ?€Á+õèïì?ÿñ—ŒÂX ¾5NYU©SªŒÕ€¢1·tÐíÀ͕̂«’Ä-%˜ÀˆÎ­÷꼃·‚½(Ráh3}¥ÑfÛÍ×ró­ïC>Œªªµ!½¯¯={ö0>>Nss3­­­4VZúª5úùþ§YYÕïÅ_$ qíµ×ò裋Åp»ÝÌÌÌL&‘e™b±H6›¥¡¡ºº:¦§§é?‘À^C¤¾•XãJ|ÁȨs çCŸcû7¿zV¾ª†µrÆY)É'¿@È€¯hMë1³3 ªp ËI«)å´:<ƒ5·oCå`žÊVÕ$ðK^}hkhm¹üH; Yöýëÿ$ì.òï>û9êëë`bb¯×Kcc#¢(ràÀžþy’É$Äb1êêêðûýµ¾RMÓjpV;ó9ÂÄÄ¿ýÛ¿Í+¯¼‚ªªLMM!I@€R©„ad2LÓdåÊ•ôôôp¨kÑ×I´±hC;pŠâ®PËj÷G¿Hë¾ŸÑøÖ‹Ë_c-ôkðܤÅV=äÖÀA`j ~‡ÌÙ´ /*_îÿ¢ìþˆžÞ£÷Çé¹÷ß•¹õÆsÿH}@ç·~ë?°gÏÊå2±XŒX,F&“aÿþý¼úÚë¤Óê£~Á`§Ó‰išµÕMªÁP5Õ4>>Î+¯¼ÂC=ÄÌÌ èºÎððpm=)I’(•J$“ÉZÕÿå1_'±†vb + E›pVšOÎ@3¨o~î¿sÛ»Áb¾ç¥ þ:üË£ðÜ“V ¹2÷Ã7LÐÆ!§ŸáfÅtk¬¥Y¾½%øÖŸ‚´èó©k õ5¬æT…nʳó^ùŠƒt¨÷uJ3GøÂ—¾Äìì,O=õ‡ÆÆF+%tü8¯½ö=ÇG·l£eCééJjŽr¹L>Ÿ¯µõ9Nt]¯5¤ ž}öYvïÞÍÊ•+ùùÏŽÛíæøñ㨪J}}}-ðÊçó¤R)V¯^;—0£†inï¤.ÖJ8Ú\ƒ”³´¤ç êô¦8òɯ°å»\[ýüÊ+`6ÂÌM0­@·h„±jºàl* û€ý×UzQo±e*ªX+¸.¨=×V­Èò¨\‘ÖtðÈ3\wíµœ8q‚—_~¿ßO8FUU^{í5Þzë-fsí›ßO´q%þ`÷¶÷1q¢›'^'!µ¦œT;÷N'år™×_úúz>üá³wï^ÌÊíyŽ?N0Äï÷£( š¦‘J¥PU•T¦ÄLÂK¬©“p´…HC+N§§bEÅs^ ðœµ#ŸüÏøÆúYýøwO鯺°z“†S0> zÖ:óU­õ_=oß©>·QqzçÏÞsÁcmpüÃ`~Þò'¬Õ)" äyðËÒ i1ŸA*O£iAžþyü~?š¦ÑÛÛËØØƒCÈ•¬Ý¶“hc;áh3Áp’ä .¶‚ôª«9~ä%Ž "ä™"©«M7'—Ëñ¥/}‰ÑÑQâñ8‡žž’É$µl@©T"NS*•™•h[³–P]#u±¸Ý~„yƒ‹ *À«_þßø&†h>EŪ ø= áMøÛ4dµR•Z £p†¡}~Bö9à¹y 6Cü¿€y' çA-}P—¬òÀoñ®½uÏ™”LŒ¡H:CCCäóy‰ÓÓÓ$“I ÉO}û.Z;·Š4Š4áó×!;­ÈÞÐuBuMl¾în2©k<Ìñ‘·QÌIÜN‘\.Çg?ûYB¡/½ô§ÖW*Š"årÙš—ŸË‘ËåH¥RM „ê‰5­Äí ,¸;ãùè¼Bßgþü±“îÜ7ߢ®>’‚r7üë“püh¥2µk‰ÓV°¢ªª PV൛¡wû¼Õ·qæå.,H?ó[%®¿ëʼ'ª•Gm"‘÷è%ŸÏSÖÁl$Ö¹…XS'P _0J]¬·ÒNW±h¢$¡¸<ÈŠ §ÛG \O~ÍvN?ÈèáŸs÷]·që­·²wï^Êå2~¿Ÿ®®.ÆÇÇ­uQgf¬yù¦ˆª Èþf:6m¡®¡•P´iY =oPžþú“'Ý u¾®ZòxκsŠá 2gª÷¿áƒŽ@¾2L˜^Ð~u‘9>³¯y¥Þ u±ÜÞ·Ü÷º_#“šFVÜ8]^\?nO_ ŒÛÀ¡8—ìžA’PD7’CÆë Óµÿÿ²º³û￟¡¡!FGG d³YŽ;F¦`â 5c¸"àà÷…ñc•/E„`¸¯/¼,^¨U˺øîÒóÜüN>]†lþîIxâÀ™¢¶!õ› ûçiÕ¢äè™ÕÎð™/sÅÞ]z§dš(Š›¶Õ[)s`šˆ’Yv";ÝÈŠkÉõœËê|’9vði¤Òþä¯áóùØ»womfi?ƒÃ£´tî mõ¢í¸=«gU‘nO§Ë{V7:»$ V}Öló*6=òõ“RWNæ;)è Ãõç?Þñ›XPîóú<"›VgøäWœ´®sð^ ÈŠÉaµÌYcŽPKKà25Þω·ÿ•›v]Ë®]»Ø»w/Ùl–ºº:fggéîîÆá®§sÚÛ×ml¯T˜„ïy>ÓEµš ˆ_uÛ¾ý5êí[Òp®l§õ¾ó÷Õœy>x_ž»>à½(« ïü§Õ†Á‘û±ˆŸûî»ááaúûûñT&³õõõ1|b”Ƶ·Š6áF­ “tñƒÔe›,4½éöüå^ÿ­?'Õ¶þ’^ §¨²{Û8_þ³ò{ÒåÐÛ/ý-;Â]wÝE0äå—_F×uEajjŠîîn )H´a%þ@—gaÊébjÙÇÆî~‘î~‘ ?þ+:Ÿ|˜àP×yõ³žržk6'¹é~koŠØ¤]ˆ¡™$Þû,Û·må}ï{/¾ø"SSSƒATU­XÓb7ã „ñêײï—Ôªº>þ%º>þ%:öüU{~@øøÛ4­¥*EPi ¦Øº]eûÝ.Ú¶GmÊ–A=ošÚ7àõ×YS›ÅK7{÷¢Gw>ÈÀVî²rˆ¦{Æ==Ž’Kví ¯˜§Î')³iK™UÛœtì¶á\N©¥<™©^Ö®jdrr’—_~UUñûý‹E%¼â:¡z¡ùÒfS.YXœZ¹‘ÔÊ Þþ ÀZ~]ɦðN@ÎgkK]~¡ï ðºðÀÛäÁ–hØÑ`Ót•MÏ`%2™ Ï=÷¥R‰@ P['ª§§C ÒÔ¾ /„×:ãmËßµ .V¦ÕZ­$±áºûo°¹¹är¹ýhšYë#õù|äóy`j&Ëê­÷RmÁãPœ—Ì7}ÇAµuùÈã â®cjt?ét§ÓI6›ezzšBY¢}Óí4¬XK8fM9›9N6¨¶.Š®Ùý)öüóÇ0tSñÇ:Ù¸úZ¢ í„£-V?©Ë{É­)€ðð³%Ó¾L¶ ]g61Fß‘—HÍLàò„„ëñ£Ãõxu8žK’Ü·-ª­Ó˜,0ʆm·‘Ï&Ñʪu§_Èjh9ÅõlPm]R‰•†‡CÁã Öà­v[½“Ú ÚZdT­v¿wjx?íɾ<¶Þß>¶lPmÙ²AµeƒjË– ª-[6¨¶lPmÙ²AµeËÕ– ª-[6¨¶lÙ Ú²AµeËÕ– ª-[6¨¶lÙ Ú²AµeËÕ–-T[6¨¶lÙ Ú²eƒjËÕ–-T[6¨¶lÙ Ú²eƒjËÕ–-T[¶lPmÙ Ú²eƒjË– ª-T[¶lPmÙ²AµeƒjË– ª-T[¶lPmÙ²AµeƒjË– ª-[6¨¶®Ù·A_Îo}æMP§Œ¦ibÊQLg x:ì“cƒzyHJ<Ž`j’ÙÃÐUÔÜ4By3sSô€³ WÛ'Ëõ:‰Ó?CdBm×â­¬í×J9ŠéIò‰Q ³£˜ù>È÷aâW3BèZûäÙ ^¢8û4±õ·¢xC8%ˆx ¤ARðâpvà‹YC>1B~f”\âFa#?€)GÜ-ˆ¾5ö µA½8Œîh;Š7DÄ ë>?‡Ty ²OdÑ5×SÊÎ’™ì§˜ŠSÊNaªShÉ7Aò ¸[BÛì“kƒºLÁSî0¦iâ7Ð:ù5QµuÖAVµ g_§o;åb–\b„Br‚\b#Óƒ‘éAFp·àˆ\oƒjãv ª8ý1œø”Ó¿Þ§X[K4ò²‰<$ðjYO¨e=º¦RHÆÉN“›>ž@Í `š&¢»ÁU#°ÞÕÖ¹ û®p3¢C!è:Ç/BƒÏÚª.B"©¢‚mÅm ˜!=~œÌôZa3?‚6óÈ!DW=JäZT[§´8‚iš(þ`P¢ª‹–‹Pµ¶øêp­©£~Íu” Y2ÓÃd§†ÉÍŽ£«³äSÝ ÊHžVœõ»lPm-öKøÃÍHÂdË¡ª‹Ð‚¢6Œ%ðQ׺‘ºÖèå™ °™©a´Ìq´ÌqLÓDò¶âð¶"VÛ ¾çAÕ8’©^ëâ{Ûýí8C—¡AxøÙ’i£wŽßî™'d™¦-÷â•ášæËëói$‹s™>ï §âdc¤âƒ”òi˯uÖ¡„ÖâŽl¶A½R$'~Ž;ÒFݪëX¶ò¢—³ª.B"%}n>5MvfŒÄ‰n éiLÓBApxQ+ñ5í²A}×Q¹Ãˆ…~"kvâ·°­é̉þËEfÕEÈÁLR¥yV¸\"9ÑOrb€äxÍÒ ¢‚ìkFñ¯Ä]·Îõ]3ìÏ> zž;>†S‚+Þ€bž¼¯ZK—NvfÇûIŽ÷“ž©¹˜ ¹êpÕ­Ç»Úõrö¡&¢kvÑì·jøïFH—zMª3yËÚ.t¦˜ïgvì8¹ÔÔœ_«øQ+ ®¸Ùõ²rè‹#HÙ7wX}§bË›è¿Ô€ÎÝâ犚ìTòå¹ý¥\šôô3cÇ™?^óke\ÁU¸#ëqù—˜±ÓSç ©xg ¶ìÕ¨ËÐêsN4ù­MÓ-hg 8½‰µo`f¬™±ã$Fû(Ìt“Ot¡øZˆ­ûÛ¢¾“þäaóKöž^ €.Þa.ñ·³˯-‚:ÏEÈ%'é?øé©® ›\¾ ÖÆïÜTí=x.@Ms!eæ)üPÓ¬lK=·Ðy¯[üa·Õ{»¥6Å 5n¼¡z®Úý êÛ7Q.L“{Õõ’ûé×0MWèòõt©¿ñ(V¦lŒ$@ÇÖÝH²“LüMÔKHiÓHNŠ7DÐiõ“¾—]ê=ܲõv(.‚±VL]µA½ä šÎeê=½€r /E²}áú¹Œ€õ_-žu©A½’ižÿñ9¼0—MMž°ÓS—TuQ’q‡[pJVè•É/×{¤ŠÖc69‰¤øí¡ÿ’ûF%pé†ýËÙ=Ý{”4+]•íES‹¸Ã¶E½dVæF¹/A´ÿn´ óß#Y±¦‰Ñ>\6ÔK––ªT£ªs£.Æ´“w; ‹‡ýÔä IÁê°A½dUOãð„ʲ[Ó+PÐ «ï5;;I1—ÂZeS—Zžh;°|Öt9£ìó´\V‘eeÙ¾Uk:3ÖW:mP—R×D€°[¦1¸B4äÁ©X`*²DK} â£[.Š_·Ãjñ) KÐ7錳v¸‘©,‘Xýg ª“gÆú–µuY€ú›?>D¾lXÖʯ°eeˆ­+­!z]KÀ‚Ï ~§uÒ}ŠõsÄmuŸŸJÍ~Ø\~%B$púÃ`š|ç¥þë½g?$ F%ÔpV+õ™Àáá,Ù¢¾Â* g3JT ¹Q-õ~œòŒÑ°gBÙÑçY„:÷Ò€™@¦dM-)–ÁïsÖÞ/™7.8U(C¹R²ú!:¯PÿÇÓ}5Hw®‹ðÀ®6¶6;X²¬có9|)§óVÙnÜ ú‰x`e>¸2ª^߯/^¢{"ÃD²pVVUÌ[Pª®û´Â´J¼P±’¹¥/ëiÀlŽù,Cü^…€G±½N\KPÀ!Y:D닺TºªšÃÔ k~“ª[Í!ù²5Ó´ú1 Zõ‹àaz6ÇèTfAIõ||éÅÃ~¸íÖ+Ô½ý3tOæj>tÇ*>¸öôóÆ2•re…D2êÜIZ¬ˆÛumnßÖÌ/^à™c“|êúöÓg’ŒÔ$Si™œªpìÅ!6E4†*Ÿùä né_Y"tÕŒÝ0Ý8þEœsCõRp¨:äTË‚éK¦-Ï«Û3W“ŸÿX=†(T>[¥o6g\p°7»¨u±tÉA}ª{ª6Ü?°«Ý+-HKŒWVó¨ZÉDa᜜Óù‚æ<#ÏÁ£Ýps;žt°"æed*ÇÀ¤5?½k< ˜t§É—t†Y¦3%¦³%ÉdS´L?cýI"^ Ÿ^Zò3øÝ2~bÁ'K´Ä,ÓÛóÕ, \y¬Bè¯ø‹K©¨YV0_/¯‚fZCvµä$ ÏÒù[4ìat"Mωä’çðlÓeºa}æj5ÊÙpå€Z ž¶¬ Sï·†ûé<üòøÉòt0žê"•NŸÑ ô&*6àbd2KÏdŽÏüÃ+§MuùdË%Éc™øÎz…怃–¨§, ºQd‰XÈ]¢CXwï¢P¶FUŸ»ÐeÃòóæCÅbè.RÓz?ËÚ[—]ÕETUEV”“N‡ažÔj59xW`Å•jW<[ûyk‡u‘’¿86×p{Œgx4Ì“6*Ï&­cµF½¼Õ7}êT׊•Q¨÷Ñæ/Ñà‡¬Ò€®¹µýÂIþbÀ¹ôá s>M¯<Öÿ§Ïë‹«µÍ-n½›éüý©‰õY0¡¥!ÀkÀdÎÅlr–p¤£§y 8—*çŠ[£WrüÄE©F½óQåÌùðÚäʧ†Ñ˜ÿóü}Ký^Ý*ûLA{Zc^Ö® ¸ˆœ´Æ|¸ÖµZ·1iªK^ƒRj§ÃdPõàTàžÕ'ÕZÕêÖû©KúÉð,ðt²Rsù 5Më‹S³¨•ýÓɾð©­çR€V÷%  Rh™Iœþ–‹ŠÌ;šGMä­H´¨Æ:΃ÕX ÊEÏÍßôŠuÛ±.Ê=[£µ¼ë©R]…B‰„ñ¼„ä 8¡¨ V$]‰žUý䧹ȃ8_HÍ% 5– Rݘ;V´Î[{ÏÑÙ2íç(X«j¨Ó•&”PçjålTÝJ£TˆSgšKC¸x«s[©©Ö€å/¶Á〠§)HUƒU·Núìl‘lúÒ.24û¬ìÂRÖíÝ©ÉBØ*8Éd‹¤ÒùSΟ2O³/^I‚”gO\´jÔ;ê†jB81'QÓ?{f0õÊckÀª­Z'l}Ô dÚCK¿ŸnXÁKµ_R­XU[èRT3ù"eÝ$«+¨÷^šU·d~ÆÂg:6£ž ó‡}£\¤<}ñªQï¨EõÈù²N"SªYµ¢6庈cuõ¶€5\ǼK¯\IlW‘«XÀêc5=t¦ ­ie Ó$¥Š˜7^œ²pE@Zý²ÏWÀ«0 ŒOgãl MW*]ZòÄE­F½£ ¶…ÝtÇ3$ÒVšêSWY>c[¼Ê™ó‹z5‚6 ¨ŸœaZ2+p† m¥¢5f5Ó´¬éå)g)XîÕbù|V]8™7ú¦gmµö¡þÿí[l$יߧî}oÞÉކ£Ñh8ÒŒlÉ’½v,iV¶³^K6‚ Y N‚ìC€‹’— 0¼Ù »/1ò ØIœA ¯åãØÞ•´ë8’%[²ì¹É!‡÷[³ïÕUuòPÕÍnö•3$›3ªhÍf7‹Õ¿þnÿïœZ;\5ª¯ Ç X¡æQŸkÖîm×ï­æìfOжùßæTEwH%P±ýãɸ(þvç å@*{€Ôó÷:­¾Öð€ß'Þ.l¬-38<ÞÔô—-äZ)ë@]¿y¨jTƒ¬}Ô ŽÄ|p#ëçFÅÆÇ·KpkËo&÷ ©lÿF½íŽº®ƒã8äl‰#, â†è©< H¹?H«¹i+mÃÔ5’ЧP©ØM^´•g•t›µÁÉ®âUJ‡^í÷ Ôáºø>¿ž'[§Nf˾ŒÚs¡ ¤†êç¨ •ìrÉßqÙÖ‘(µ°ßwHåýAêíµþƒwrɬöIæÔÇ1Rc“ƒ •¶Ê}BÚrõA+xÛäš-•¦²©'}ýÝõšGõZ­À®þHÓ´ÚÛS:TÛÅ£W£úê…ñDíÌ-¬å)»~ó¹>/mz“z€Ô¼óÖ¼S+0£(û}”éˈ‘G‘Ù rí&̼ÍĵŸ2Á|¸¢=Ï/w¾Ì¼öÛ©éa©tO¶Ëg÷§'{²—TfO®¹S V›BG´ D ã£)–W3Ü^ØäSÏ´.¨JNÐ>ܚǫ”ˆ]àÊ­e E›;‹›J6sw7Yßʱ¾å»ÞGN òïþÅW‚öTp e— šTÀmÑï©’›%òÛobÝy -ï¯6>ƒzᔳÏi¸‚ÜX»Œòè§àÑO#?ûGÈ™ÿ‡¼ú.,¾Åî[T®ÅYN\f%~™ùôçH¦Ò$’i©t£w’í%NÚå íÀëT\u‘O=¶Ë>¤í¼fךj«°ä´†¹¡Ú÷7@ûÖ÷渲¸Øñí]ßÌ=øü)ª;[E®ß͵Où ŠÝåu€T”·1î¼Fä7ßDÛ|!@ ŸBýô?A9û „o®7— ¾{…]aÆÓŸ‡é¿ÜYC^û1úµq*ó:§v^§¸:ÁRâ2óÉWXL\"‘L“²¢M««×k^‡T€.y­ãó^—Éü6ùiõõÆFS¬¬ls{©ØvrªºS_µ:³ÖŒMdhÕ0È--ù-ȳã¨Qc÷OWeT!:CªÏ¾†yãUŒ¹ï!‘Dyú%´§?HŽpŠÖpci½øL$ÇÏý!<÷Uäúmäÿ“Èì_óèÖw9»õ] úw’_f.ñ •è©Á!ÒƒCèºÙ[o³UHï©ìà CÊí‡GšdÓù¶®«ÁÂ?…b~+–l€Ýñv×F¹Å ³¥1žz#ÇL$ˆ ¡™þJÇíÙÙ¨Ÿ¸øÈÃê…ñWW²\_Èø¡¢àHï…TYÿúõW1o¼ŠbgÀŒ >ñIÔ³G}ìãµÐÞÕ6—f÷]RÄðcˆ—þµŸ.\û!̼Etö-¦7¿Åôæ·È˜3·ö ±Ë¸ñ³¤‡H$Óh] me·%ÑÞžŸ9ž_4UçK[!¶-¤ÚxÚtÚŸHÏØ ù,f4ÙðZÛ{¼ézúcLŒ< BA±Û@­ÚóÏ>öðH¨»yªƒíjµ‰ì,ÚÌkè×^EÝðC»2yíâ—PÏ>…°bûo/ÏîûðÄù/ÁùWÙe˜y ®ÿ€ÔÆuž*ÿ ÛøîF_daõ2·£—±&‰'ÓÄ“iEëš´ûY»n@¶\·¶¬C%ß*-Ùûóú¶U4º;ØÉH4>¿ªVÕ¨oÏ)#T ݇5°l·ŽZÌ\3?óàƒ:=^·~j-Ïb6ÅÈܫĮ½†¸] íiôß}õ±K(©á ¬ï_£K³÷u¬"qžúðÔ?D®ß„ë߇ëßçdá NÞàS|…õ¹ÿ2×"—‰'S$†‰'ÓíU¦½yH •ÝÖS«ü±mK©C!UÿX4húK`y³ÂéG_s£°«Fm1@Þ‹ „ƒÂ?„ka};çPO?>pà¼ô Ԉߋûlô—¼<ÿgœ¹õCÊÎ6²О|ýÙ¿…:zòžáÜöÊÄðyž†Ïü+˜ý+¸ö=˜û)“…7˜,¼-âÌG/3¹Ìµøçj^6–L·.Zx׊ç¯ùÊ•ëR¡6á½ÓÐIË%Ð-‹FMòù2Ë뙆O>XaQU£î2‰ô!‚z@(HEe{n®öw¦Nı"ñ‡Ô³_ç×ýGNËíÜãhç^D¿ôLïygÏaƧþŸ˜z ¦>å<Ìþ>ü6ÆÆÎæ_çlþuì87c_æfìîZO"™ :õÀV·…,“=D­@ÜOZPýY4j‘Ï—Ù©[?%i^µàM qA(Anꃪ¨Z-?MÇuƇ"LœzüÁõÔÚw8µö†wÞôóΓ£—>‡~éc+z pJ» ›ë»€ÍUÔX ¹4xhR©}/Nœ¿¿?j&àüß…ó²‹ðëWaöÿ`äx"÷]žÈ}—¬:ÁOŠ_gfí<ªf0P¹22gû®$“ @¢ñëêZã™Û†­ïž2×0Á°`iÆ¿¿4Óà~ä/þWëç'‡!1²:¨R-$Æ`gµùXÍL¾ “¯Àì 0 ?!á.Q.æXµ¡âÚØ 3Ö:tïkUh·‚©)µ¶~J¥R.£fmc{í^¥Äª;‰ô|HýÐ/ÀE%»Xö'⨊ö`ƒ*kâ<æùgý t ¡iu¡^c÷«9ê“ëòÕN·æß‘¿ylñôKm~WÝÇk÷ö»Ò)ƒR†åw!¿úÞ“:IUv÷ší¦óï)-¨‡¼~.uØ÷‚¥8Ù­5Òc“lÕ~u'”yg)¨ÕÐ/T½ö-Caz*‰M<Ø È‘qH>Kkp{9hÁx‘ŽÞ‡å;Góÿ-¿ëWü›¢@<êß6ü¨:TRÿý½x̓L Ôúᔊ¯$lû§ó•A„„}áPÝïKg‚Bj*ØmnôÄ™ÔêÙ²¢pòT°Nnn!5ŽÃäÂ2yLæ–aámX¿ N âq˜œ€x ¤;FS¥îÉfP;¶˜ä>ÚO]Æûö>/‘ŠßKf—Š Nì.‰v‹îØC~ØGi¨ø…f44ù/L%íyè÷ó¼ t )H$Áu ³¿\@êÀä0 §ƒÔàøyTYÊÀò‡°ü”2þÿ0:‰X0æ5Åí¦ÁgÙ~Hd¿ž¶)ÅîTý·H'4]¥b;ìdó»a?Xi:_@m ûŠf6€:=•B×ÍTXvõøV ¨ Ãà ”Š°’[+È¡  †ï½÷iZÈ`mÔ}¾S†õÛ> Ûó`E =ÉþNÒ m½œ¶~'çà7›Ö3µ+ˆZæ™]¼æ~Ò‚D*ÎæÚ6Ë[¦‚j¿ºvÙŽtj J!PôBÕÔ(ËP™<óäCjÕ£ ¥îͬƒµzߊÀ˜c£ÍÂüòêŒÃø("~ÍäìÖ½òú-Ðõ[þglpÎ_C÷ÿY?wßùsZ¦º_©ìÐÄï±aß ˆÝÒ‚HÄ÷„+k™ÚÚ(7·Æf%B¶¢!T¼ÝŠ_1¢‡®Fõ¹á¿Û(îkõ~"á‡S×…\~} ©k0>ãã­Çió¡ýÉR>€õ¨`` ö?D5¯éíï5÷ŒþIÙ¡)€iA/žÖ 4ÿõ¢hP£näSàÕK¦þMµ’¬Ýøín[êDüáu77 B¯°¢ø]¡T’ ¨Ø°µ³óÈt †Gã÷¿5·tlX¿ BnÃÏm'A¤ƒË8¶ë½BêíÙr§§BªÇ<³§bªM!‘Š#¥ä7«/oÍ×Ô¨¥¢…ô\DОóþ…bDšÔ¨ƒ–MûÛžªzÔ³û€ÏªnÀð §¡P‚ÅäíÛ08“SˆxªuAÕ6´ÏÁò-Òø €G/"Tå¾àl+-V•öÞÛxÚ}¥´dQu ÁÊŽÿ¿:Ûód+¥ ìSöã-Õ¨ƒ–MAèWÃfGXë·E©ƒµz?jù7׃\®¾t$LžñS-¨BȞОƒ…ë> ŠÓpéE„au-Šîµ-·wßV¯Í>§ÛûX«´ ÕkvI ÒCiÿJŽÇ;?ÿ%ær ðܦ°¯Åؾ»»¥Ú?}xrÔêYU­½X[ÀÙ꾪@*îß*d–aá6rü4ŒŸ†x0½´½êϦ®Ý… 8û"9¸¯¢è^ÿwO67üÛ*Ij­˜¢ÖO{°VM×`0éßJYøíÏ W@zQ˜|>~Ñþ½‡¢è^?ŸÈæm!ÛÁ×µ(jåM{I h=ùïz[10Õ<Û9IÙÌf‚°_ª–šÕ¨ÃMûúë‹©=°6Á{°VÍ2`bg .}!xGЖí)ÚlÙÞÁSvò¨‘8ŽËû·VÙvÕ2¹¢`1§‚×(™"zb´¥u²iŸCÿžµ%¬¢ênpŠú×n³Mµi€>JßLîiòËæ>j/U«Ç÷- ìyÞ•¹U®,láX"E›¼­0›QjÓR»CÒ-6ÈöïÔþÞô!õbjoŽÚëž|µOÚðm`Õtúió›Ô …¡ºVUËñ¾n€Ý§­û»kÛldòlætábj8p}UCjÎnØG ÆPÌX“uX²iŸsTZç¨{=é¾`m•JHŽ4gKîÚ.‹—­Èð Áp\!ii¨B´ßB¨§íòx·¬T®0·¼IÙñ(”]Rª ªJÉ¥ÄR¼Ý!i!ÐS'ZªQ‡%›ö=ô d“Ü ç~`mç¬Àˆ¶Ã ›¥èjl‡;[w¶ÀPmR–ÂhR#a*XÁZû{N z(À®Ì,ẛ9OBD±ASÉÁZ=¯…Öߪª÷Шˆ8Õ÷bUO«SÂÔ ÍcÀ*á8yò…íŠE±¢³”ÑYÊ8hJ‘TDe{kMºhªà?7FÅ•|ãÍ"Ëy8cVˆß›Xììàºè` fõí_ÕŽ¯ªF¶lzYë±î Îúûõ¯'Ž ¬{A•Âþ½A¬âŠ77Y؈a*&_ÿ Ó'#¼;osuÓßÄ¥(¢ä•¶ð¦h4J&“©SvÅBO³=û7ÀÑ«QÇ#ô÷8gZë±îVqìþžl,¦zõ^!ÞÞɲ°äWù¿óXšþÅs,fá›?†\›wÝ0êVôš&”JG²Sß1ý¢çѽZ¾ú€æ¨M-ªµÝcŽëð›k·HET^ûggøÚ_í^Ø£•™f]ÞxÕ¥÷ÞÛ ûAÿÔ0#*Øïœiï°¶ùô»*Ûç¨ êõ[³¸®¿þéÕ4E:ªñ_~ ï.u>Æ‹A>_ÛIº^:yúÂCjS›is¦½Áz|û¨Þ€º´²Âæ–¥™¯~zˆ¿óñ4×Öá[ïv?¾&*%®m7xÓDèo¨ø{ÊQ;´­ö k=ªlì¥v ýZSÝÚV¥r™…»¾Û<=dðÍ?ð¯ýµ7:‡üz‹D"‹ÅZå_DU5ê(eÓþå¨{CÇ=½Áºw>µ›wîcnZ]3Uý^ȃiMU¿¿~ãÖnÈÿªò¿ñ3¸¾Ñøš…B×uÉf}Ý?›Í⺮ènÐðœªu”²iŸÛSõÐt*~¼Þ`íuÀ1°ú}UzP­©ÅÅÅhÿö• .ŸOðÖÍßøÑ6®ëR(°mÛîѵڻ—S¬W£ŽR6=¡¿žœƒ€u Ð2Gí?­žl,ªºÚë¸w6›eii·RzíWÛ|íõ¥Þ¬Xô7¡+•v7£«ó®‡½Sßñu¯†ß°¶ÈWSŽZÍOéîQïÅVVVî¿¿Plþ¥|¾ÆRÉ÷š{=l‹ÅXÓSþ.3G-›ö¿êo «ØçÂ=jKXü§uƒõ˜ôP÷\üì~¬œËaçóÉìX©ø7Ûö¿VÞ.,]0>Á2ÆLº¯B?«ÚQ˦Ç'ôß÷*ÓÝ×è+ý-¦î‡ÈÂÖ®m“]]ŵíÚýâÖV‡äµÙ+¦c鏯Ā…©+L ZX†ÂÔx”Áú»¥Ï}ÁÚümaÞñ˜òo—cV!ÜÞÆÎç)çóØUoÙ¾½6>``i Sã¾rtf4‚e¨Œ>Xï8 Ú3ïR™œF;u ¡ê»½ºnÅP˪Û{Öþêå·ñ¶Vk@®mÝ¢”ÍBd™b¶Œ[©ôì¦F-?T§M"A¨ö½åáîsT«M¨×ÿ:'¿ý_ÿ Zz”È/½ôy”ÉŠ¡û…õè@•v wþ î­_á­îŽÈmÞ¹ÃúZpÊ#¨Vë|1møðE5âþ×ñ³!_< 3ÌŠ¢ÙÊÒ}Åàoÿ´|ä¥F<û'¿ÍÈê÷‰”æ0'Ïcû"ÿ"ˆ²g§ûÀ£Ôß÷hدÍ}Y}Ž”°: Fqò vó«ÿÚ°ýyãWÙá±êóœ¹qï\Á½õËÚç"S±xýî“ü§Ùgxkí1Т¤ÓiÒ‰8iÓP˜HXºÂÔ¨uèçÞŠÄQU½oýÐ ÔzYý>#«Ή¥ï 4ëôEbÏ}íä“Mßû„ueŒøƒê®ßŹñîß sÛ c[ü¢ü)~¼öÊÏÑ5ƇâXV”ñãPϧªhè¦u,½â j½M,~‡‰Åï0¸õ&j$FìéßÃ<÷I´ñsÍ^u¿°®Ì€;Pe9OåúÛ8×ßÁÛ 6e’›Ú ÜÒ_à–þ"eqx9®›¨šþÐÁøÀ€Zo§æþŒGæÿ”hi}ø$‘‹¿‹5ý”ÄȽÁºrû¾Aµ¯ý_œ™pç~];Î5í¿4ÿàÀá<Îùbj›|öô?edíÏ1Dë‘'‰\¼Œ~öYkó®°úú F÷ ª»v‡òû?¡2û>ؾ⳦žã·æ—¸m¼ÀŽ2ñ‘ËCP»ØÀâÿ`xæ?0Uz ÕŠaž{–èÅËh'§»Â*—oõ ª›YžòרW~†Ìnøy§2ÎŒñWÌ—YÓÎ}¤óÅÔmñê›<žûd~À¤¸‰–!zñEÌ'žGI 5xÒ*¬rå&è‘¶ zÅ•[¿Àþí[8w¯PVb\1_æªÕÎb¾‚º›¹î¯åI8K\Ìý7Îß$é.c~óÂó=\3ªT« TûÆÛØ7ß¡ró]¤] ,bÜ6_dÆ|Ûæ a¾‚zp°VíDé=Îþ‚Ó¥7ˆ¨6ÖcÏb=ùY´çýkš º™Š¿xÊwðvÖ@ÀŒù<·Í¸y™X| ÌCPVÓËqºøgJor¦ôZzëä9¤fb¯Ìà®ÎpÛzžYëfÌÑ’§B8CPÖVù¢–½ÎÉÌ8¹üm’¹؉?ŵèË\ãYʱGû²¢2´(¨¡=ü¦„§ ´ÔÐB A -5´ÐBPC -5´ÔÐB A -´ÔÐBPC -5´ÐBPC A -´ÔÐBPC -5´ÐBPC A -´ÔÐB A -5´ÐBPC -5´ÔÐB A -5´ÐBPC -5´ÔÐB A -´ÔÐBPC -5´ÐBPC A -´ÔÐB A -5´ÐBPC A -´ÔÐB A -5´ÐBPC -5´ÔÐB A -´FûÿaocD/ÚFÖIEND®B`‚drpython-3.11.1/bitmaps/drAdvanced.png0000644000175000017500000001317411150445515020461 0ustar dktrkranzdktrkranz‰PNG  IHDR–21îµMgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€èu0ê`:—o—©™ÔIDATxœbÿÿñãûûw Ÿ?‹ðòiÈÈ(JHHŠ‹K°°°þÿ´öÂ`ÄBk €‘ÇÄŒ?fVV`ü±rp°>zôèСÃae}RYñÇÔì#ã/†?üÿ áú>µ20üc`FÛÿÿì@¡Ó§~OöéÕkvFFvvvaaQ`ÒÚýƒm£ÀÌÇÄÊ Ì|Àó÷Ö­›>r丘ث–f&]`<ý#äœÄ1À‘ÇÌÀðûû·ß›7óýù#¯¦¦©ªª&"" L4uüPD«(— àøc†ÄßÏŸß/\¸¸wïþÛ·¯èè|8‡OßÁY­$f>æÿÿ1ÄŽÎÿ½=ÿV®QW7¶µµÒÐÐàããÿ÷á÷ï¿@ðD¢ @4‰BxåDÀ¼ÂÎÎòõë—3gÎnݺãÙ³«~¾¿ëê9åç`öÂÔ Î|lÀòÈ™>íßú ÀŒ¨áímacc-//ÿãÇï_¿~ÿùóTŽF @Q? áñ©ü€ä—/Ÿ=¶mÛöoßnæd3&$r02þ"lñÇÎ@W1ÎûgÉ^66933#33UUU`–þöíço`ôýf?p3æ?Ãh,•£­ñ¬ß¼y}üøñíÛwÿøñ ºšÉÇX±ãï;¬¶Cq 8ó1?yü¯¹…ñúuIS33Seee~~`‘ùã(þ ‘Î#=ò €¨…˜—+W®8pèØ±êê¯ÚÛX•XÁ•ßOŒøæ@Ô‰BÌÆ 0þ®^½¼sçžóçOÛÙ}˜4‰ ¬ð8þþ!;’ó~ÿblkcº~C”—WÝÅÅDSSØæfæ_¿þ@j¾¿Ðºo4ó¡€¢B"õÜùÔóûöíëÉ“'…çÇ—²³¥¦r€)ßÀõŠíàfç¿ukÿÍ_ *  ëêjkh¨/!!þû÷?`³åçÏ_À(W}£%'N@”F!Fã…åÇ÷ÇŸØ´i ;û¶ö?ÖÖ|`…_ÁùÖàd78Ù>`š0ýÊUq 3''{==`Uúöíû/_~£ ¨HkÁÑøÃˆ¢(„5^€ùTx22þôèÁÑ£Ç:,.~§·‡IF–Xí12~Cj|‚: ÿÿóÞ»ÇÑßÏzå2·¼¼œ››–ŽŽ&ÛéÓ'ž?úáÃG~))Y11 &&fŒ^ã(@D~"7>ñ÷÷ïï;wîìÙ³ïøñ#ª*_¦Nåf7^¾aÆÁÂ…¿&NF-ª*˜8óŸßwîß?+Àÿœ•õ͇ß®]åb`ÐýóÇØåää¦ÌƒÃ9QˆÚxÆ{íÚõë7ߺyÑÑ‘¹­•—“ë;¬ðD‹?`ÌýÒÐø̨ ðÙÀ൶Î?FFxe¼}›áöm¶÷ïAM Ü÷Ž.eÞÎ €I©@žvÖ|ÀÆ °ñyîܹ;vߺu94ä{I)0F™ï+¸ð$¦ d„ d3®\ñwÍZvv-CC ==}AA¡””Ä;wîOž< Ø;$˃Ãi¹¹òccÆÛ»woñ·wïÁ'O®%'ýNKgfdünyþ"Æ<Ø@㣇¿›šXŸ<•ÑÐ0µ°0WPPdgç8yòÄ“'O-š5kÖ”——“çÃaˆ„(DŒŒÿîÞ½sðàáÇòó½hoûãäÌ«ü0G^0d ¨å÷„þ¿k× JIéØéêê › ?þÙ¾}ûÏŸ¿Q´c4 q€"6 ™ÀÆ xΖõ÷ïŸW¯^ݽ{ïÅ‹gu´ß¶·³JË{x?Á#gÿéW;‹LÏžþ*(d¸uKÚÁÁÖÉÉAMMØwöåÝÁçÏŸïßÈFá—/_Ž9bccC’߀Z€-¬„„’t 6ñ;.ïQQ®þ Ói£ogÏžß²eÛýû§ÃÃþUUsUAF®ñÇ|ߌӧý[²„_L\+6ÖÒÊÊBDD Ö—ÿ DÛ¶mûñãxD T¡s$‘QøâÅ‹ 3îׯ_srrˆÑ280ýk;vÙ&LÀ¥ €G!¬ýÂl¿011|üøáÜÙ³;wmÿõóBmퟰª#gXLƸÙÂv÷cCãß›7ÄÌÌMœœ444€9üÛ·H³ÿ—/_ÁÁÁ LƒÍG²‰‘ ƒQTŒ? [EE… úA €þýüù3„m``€K@› ¥(0h=zxØý>qXQñV{Û_1q^`´+¿„ŸøãV~m­¿6oáP7ÍÊvÕÖÖâãÆÜ?!™2³cÇöÏŸ¿xxxœ?þåË—#€å P„ k À¨ñîÝ»ÄønЈGð+ &bÌvû€¹ãÅ‹ç×®]¿ÿš‰É«Þf1qîÿÿ±Âñÿ?÷Ñ£ì{öpýøÎdƒçüÐ3Xû… ¿ÃÂ~lß!f`àdjjÊÍÍ ,-XÿÁ'’€Q¸mÛv 6`5æéé 7eõêÕÄûŸ˜ü:<@SBÿþ,üü<ç/p‰‹<}&xéÒÏóçßܸñÉÄø§-#FYЍùfÏú»j5?/¯zp°µ‘‘¡˜¨ø¿ÿ À'¤ðDž…–„/^Ô××—f;`Å1 ˜«€R@A\NV.\F0ñÂK` B@)HÑ ¬f!Qi;m¹}û¶­­-°ö…'ˆ°Jž8q"ÜX`ª*Ã,€*²@CTUU†#›ÑÀrÂÐШÍG@‹€º(ާü„€„š= ƒ@…ÖÄFrÅÁSdÑSx ØXY‹ÞÂKYJ=A„&_v`!ÐjØŸçÌ{îÌ(îK(Ÿ—I¤ApÑZûþaÛn}ÿ­jËò†Ç4½£H•¥:WÛѸŒêÙÊçÏó‘–uu’˜8¾‡áU)o]_öè‰~??Šfrþƒ—z—‰ío‡IÀUUÁ&|a7M#µÐJ_€aŒ©ëZÖþÀ2˜ç9k„ë,Ëà·m[º¡4MÅ%¦&t]‡Ò$yŠtd/'ž"þ#9»xðÀ.³Ë”ÛîA<îRÅ®@DTA ŒE`mÈÏϧ¦¦feåàîjlìÆÎ.òøñÓ/ÙÙ}X±ü«šúwØpöÈ.¸Pe_¶”9#Càí[Com`Ïäóç¯?þÏB ¯€°1)..OÚ¡¡¡pY`ˆ`:¨%??¨ âsçΚWG‹x áhƒD*0¡Ã À]¹r%Pb)Ð%õÀlŒWx(Ož<¹²²ôÜÜ !\`Av 0þ€fµíݺu+D ãØYZtP;F0Ð4¸É@í@“nzdΜ9c €ˆŠBpqÊÆÆ&$$$##-**úúõë'Nݽ{Ö×çeW×O`¦¨AzôšûïÖÂB¦¶v`ÿOZ[[MT”÷Áƒ[»wmÝ»w7°œ|õê50 ‚Õ£L$ƒè+ä*¹/Lõ@¢¹ ’ê!Ù€Q‚Ö…Ès 0ë@D )$"Ñ”Áeáh\ ÊXääÅÎÇÀœ ŒdA¸_€¹ XŠ Ï 0)B¡q<ÿ!Û ÌÁ x@(H!= p¿4)$?~üxîܹ 6út>+ówL,°¨ü´–‚’ÿ¦Laœ3X8²«¨ëé±ÉÉÝâá>ùáëë7þÀb­%ï›Bzx Hu3¸É—&PÌÊÍ#˜ €ðE!êBzV`§þýû·§NÞ³gÿ¿×jk~;8Û)¿ê?Иç“Ǽäȱ#GŽ33ßéêüe`ÈÎÈÓÿÿÈÈþ a ùçàY&ú—‘¨àï;l½½ü¯_+[ZéèèIII²°°þùƒÒ‚…4:0x@`΀´&€$æ`Zé LæðÞ$µ«%`ˆ (äÂh&°,W!¶Ãs &À5\I4˜I mÇj$·¡i‡×²x@aBÌÜß³gßG””^ÖTÿÕÖa„ÅZ/(øÉÙùóÿÿÌE¡@¡ÿÿþT×0Þ¾-#'g`¦¨¨ÄÉÉ Y޼š ’3`mn4'Á\ C‹B`™ l.bõ0#B†¬€I¹0þ»XÛM@€§f‚D 0éV[1À’RÀ¢U àH…ûÈ@NÁ¸<‚ Ks6#Á ™NbeeºuëÖºu÷ìÙ­¯ÿbÆ `ü1e0ãœ#ÿ€ëEfP½ø¡³“ÁÏ_ìÉ''§Ø€€` ßøøøþÿg„/džÇ!<á/ÀsP%¼†€”<À¼T2€ k´Š:¼Žœ€Ó¤ ƒp‘³5$+@òfc «[p«® ¨ È…°Ib8Äp»€ €ÁìA2€‹S¸,0âm¸9¸,@·Ü ÃPô†„TÄ92ê d\a‡n‰îÁŽY„BEô‘¯Z¥Ÿ¢È®­ØŽófyå«ü›®sWÃðÌ9“·ë¥mïÇÓºxèñ½ÎIo!>Vúó»ë¶Õf×4‡ºÞ;çÈËÒ…y©ºø#Ô{ŸRJÿʉ4&-Zm Q¢˜±.sØ9IÃdPà³ÃGÍ#âÃ:ÂÜ’jƒêh¡¾¢‚¤TSíŠ!lÀNÔ‰¯(RáË8† .dŒm’Å æÑ‹.5Øà'~víGØ6ca( k4ÁQGB$q`5p :è®wà(„…C˜À€!aâ $Òcüä%M24}mùÛ¾ÿõµ¯…½»Zûß’T뱪n¬¿¦¹ªø~¾|ø›¾¥—Yæ¿hÓ-èJÏã镦[×݇áÁ÷wëõæ´~Xü}Å(1Ë2¬8Š¢¿üÍ&U×µä‡a0‡u¦Úuµ(B)EGü#š Ñ>"bA%ç~Ú˜B´‰Ê! ‚€Z§¢(é%ŽcVvÛ¶HÀ“ã8â6ó<§ü²,iÉ[žçÉ`Īp×hØô%K¨¾ï§q’$b²€ Ò),’aØæVF™¢=fó¼J.„¡ÀúØ |ûö50XOœ8üæÍ•ì쟑‘`_‘¦s‘£²¨†uÖÌßK–þcg×ôöö°µµáççÿù4ÿ‡¼–ž}96$9£e4L§p.žüŠhΞÁ@„ÞœF0Œß¿wöìÙ½{÷ ð_;纸lü ÎdÀŒø\œÂ3d iû6–)Sÿ>Îghhêåå¡®®ÆÂÂöõ+d ßZz`˜Bú ø‡q ¶ËƘ3 }»¿ÿúþ´óOB‚ãëWOŸú¹båŸ÷ï™}|~$&~6;a»9 [8;:~ïÚÅ/%¥éäd¨­­©ù¾ÿ )9ñ¯¥‡dÌÀÂjÊ”)6°Ñ‰B:ì5Ì €P¢2)ÁÌÌÂl„¨(sp‹ÕÏÇŽ3mßñåôé½ÓÑùmiñ¼´ ²"ÿwíú5>Û·¯®®¶ )1166v`¶ÏAü’ÀzÏ\"°j·E Nêëx+`Üõu”€BkÎ0›£LÜÜœ²²Rêêê¼¼"|¼páÑÇÏ}}¿NšôMDô3° 7;ÙNúßÔøwÝ:1II???KK QQ1p³ó|þXv¾zñ‚›{Ä@šp h`u¿,F0ò$0¤FF8œ@!š3Èciœœl\\ß¾}>tèØÎ{ž>½™ÿ-=ã/8ÿý7^ÛÛY¶oQ233ödee½uHŸ E'°_ÿïçŸìœX­÷ööFžb·ž¥%æã ØðAÓŸB™ € )|3(ƒýÏÍ›7?yðàa&¦;55?½½!ÛÞAêÏžaèèäúòEÑÙÙÌÐÐ@II‰……9ç¡ì¿edÄ ¨ID2´ o@ \‰?P—‚‘‹‡óׯïׯßvçÏ;¥©ùrÒ$fQQÈÙÌ¿±ÔÕÿÞ±OWÏÈÕÕÑÀÀ²fy˜¾Q@k@,ÐøcŒe3}þüñÌ™³ûöí¿sç¼›ÛמvرLú¯[Œ*W7kWW'%%e`‡²ù¥ä?ú€ba—ž¹ˆ7o^;w~ûöŸ?ߨ(ÿÍ l¶»ÏŸý(.f¼sWLOÏÈÞÞVGG‡óÛ·ðÌ7zrÁ€b¶?ÁslOŸ>Þ¿ÿà¡C……î´·1󣄑ñëÜ9?–¯5NN¶o~VšÀüÙü>zrÁ€€펢î Ï£G*(<©¯cQS–ŸßŸ>ýÑÓÃzù²šžž¹££°äo~ÿýóçÏÑÌ7x@±üøñãöí›'Ožº}ûœ§ÇÇÈH.%å ÿΞýgó1>>ý°0mQ`ä ÏÑfË`ÄrçÎísçÎ}þ|ÇÝý§—'§„Äýû~®^Íýô™’‰ h’HIIØ3•ýAšdÍ|ƒËÍ›×ÿþ}iañÓĘáñãÿK—²?!*/¯e¥¡¡ÉÉÉ >6ä×è±!ƒ°7ø^^þ×ÏŸ ë7°?x ÀÄ$éì¬m` '%% ÌvÀ>Ãh³e€báâÿñCð×OfAA~Q11 `5òF›-ƒÃÀ›TIEND®B`‚drpython-3.11.1/bitmaps/drpython.ico0000644000175000017500000003227611150445515020267 0ustar dktrkranzdktrkranz ¨4( @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ%^€ÿÿÿÿÿÿÿÿÿÿÿI +”=' &'Ÿ(5›+N”/:?.c ÿÿÿÿÿÿÿÿÿÿÿÿJ¤$«­«ª¬%«4¥1 "ÿÿÿÿÿÿÿÿé÷ÿD"wJ©¶¬ˆ c%­µ¶ ± ¤!E–/S]VÿR <ÿÿÿÿÿÿÿ39¬ ¯}"µ¸ ³ «9Ÿ"3+L]*g f; ÿÿÿÿýÿÿCyG© ®lÿ>1áÉí–· º·® ‹ 3N9B™+B—/=x44ÿÿÿÿÿÿþÿÿ)¡. ´ ¢\%¡¬.úîÿØò‰¸ º·ª/Ti2 IRY‡Eÿÿÿÿÿÿþðÿ~J¦"ª¡,)½±!üøÿíø¯¶»»"ª6iI<[ÿÿÿÿÿÿÿÿÿÿÿqD œ2ž0$Á­ý÷ÿôÿá ë“»»4¦/ÿÿr LU#ÿÿÿÿÿÿÿÿþÿÿÿÿ tA+½±"ýùÿ÷ÿèè›»¹@¢O ÿÿt NT# ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ=³¾(ùý ÿôÿá ꔹ´K]ÿÿb&Vm6 ÿÿÿÿÿ ò îÿøÿÿÿÿÿÿÿÿ0&àòÿíü¿´ ¶ª'Vÿ[UDJS!#ÿÿÿÿÿÿÿÿÿÿ ðþÿÿÿÿÿÿÿÿ:ÿá,ú›· ° C›&."ÿÿE3bv5+p ÿÿÿÿÿÿÿÿÿ åþÿÿÿþÿÿÿÿ>]÷À´µ +§+AYÿp&C7WJÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!«´ ­TXÿ3"@K‰55Geÿÿÿÿÿ÷ ðÿÿÿÿÿÿÿÿÿÿÿÿBœ$± ² )£)Fÿÿ{_)Ti$=K 5 ÿÿÿÿÿÿôøÿÿÿÿÿÿƒ0¥!± ¸¯2„G1ÿÌÿup©ÿÿÿÿÿÿðöÿÿ   xq)! '®·»º$«0W\ÿìÿÿÿÿÿÿÿÿÿÿ ëÿÿ7`/‘     , ¯·ºº¸2¥RL~ÿùðìðóûÿÿÿÿÿÿÿ Ÿ.¶ ¹»º µ «¦©¬­®­,}["ÿÿþþþþüûÿÿÿÿÿ 4 ‰:¬¹ºº¸ ³ ª)ž)U,19–58š(Fd‚ ÿðþÿÿþûÿÿÿÿÿ#-"ˆ:ª µ µ ° š “Œ "ïÿðêÿé<IaFÿÿùþÿþþòÿÿÿÿÿ$™6¨§„7p‹qÎÝϺùðüðñãÑNÿÿùüþÿþüå ÿÿÿÿÿ€8r!ñÿòŸŸŸ€€€òêêÿÙÙÿìþþÿÿ÷ìÿÿÿÿÿ$ÍèÔÏÏÏ€€€ÏÏÏÿþþÿüüCÿÿõþüÿüìÿÿÿÿÿ7Ó×ô›œ¦µ¶ºûûÿyx’ 9„ÿòûüûÿåÿÿÿÿÿö÷ÿûûÿ­®Ð5ÿÿÿÿÿûüûÿÿÿÿÿÿÿ@:1ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀÿÿÿüøðàÀÀ€€€€ÀÀàðøü?þÿ€ÿÿàÿdrpython-3.11.1/bitmaps/24/0000755000175000017500000000000011246265352016144 5ustar dktrkranzdktrkranzdrpython-3.11.1/bitmaps/24/Save All Documents.png0000644000175000017500000000134611150445515022162 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ >ŒÉ8sIDATxÚµ”ÁKQÆgfÞËžš½½DiQ‘.ú#´òµpßÎMæ¢Z!ˆÐ&‘ EÐN¨eº‚ A\é""\‘ sžùÞ½÷´˜7úfœ7hä—{νÌ÷ÍwνW†îLi¡³Œ³ÙúEÿå³(‚S@HÌPOPEPæÏËkëˆñúé‰ã ÐY¦x¦»ý›àë'îÞ®` Š‚!Ê4âæ\˜¼ÿ„—c08úXiB@ 5IÓ R ’ˆ£½ÈE+Håás¸¹÷ø…2ªÑ ®ô¢J4HÎ.ŽãõF¾º¼†16Û_(Ó~â Ön!f‘±ñ ÆQ°.ÆÕdlÜÞþä½)^½€ÊÍGƒšKÇ„º=SMr´PÀØqêï³ön O(" ¹êY$©?N»Q £| ßï Ü\ÊwP·Óäº_4žÓhí@#ͤ™"Í}Ð)Ë,QIfã{-›ìEÜšœÕ“XÔå9¨ÙýõªÛÔY×nš.ZK°®tÅn¤~óovo­Ó½ìHæÍÄ~Ð}Ÿ×dñŠxršs«mí}ˆùõš²¾ÐÇ¿ »[)¥µ@*ïþ00pPœ‹žµèQÓŒ±·¾²C7Ú9™'ÐÕå1;{Šï?v¨× Ö:J%‡ï;¬µc0&š£Üb­axXxјžÙ £|}°ÞsÞ¡ÊåqÄÌv¾,Ôôhf'Gw‹622óßU\¢¶’OP8|EMv¶J¸¹V¹pÞ2ýì?·1vªÂü[¥¦£ê§.qd/]l@¸)8[å/Õº ª/nIEND®B`‚drpython-3.11.1/bitmaps/24/Copy.png0000644000175000017500000000151511150445515017561 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDùC» pHYs  šœtIMEÕ13¦7|ÚIDAT(ϵV=oÓP=Ï~uÚ$¤­J •*RXø¨@…Π2"ºWH ˜øLüFÔØ *ªÄ¢ ©@4MCç½{üì\;®”KO¶_ìsϽçÜëÿùP©»«÷•§TmfîÌ­‰riŠ™y$N)¥v»áAãçkz0 §¯,_{xoue­vzjœGóXŽv³Ý³Ož½ÚJðuåÜÙÚåÛ×* ÕâHàp  €°.P‡€­÷ K:û1ƒG·ÆÀñ53е€µÌúxjÇÄi`f€ Dç8и¸æÃRÌŒ-õ{¡ØîâwóøÁ˜FP`Y `8zföÔj½6¿21ø¦oÆ[­óO_l£xCµ†ˆÅ‚»71?[QN4Ⱥhô…úüãGëwêÕɉ+à¬!Ë"ÖËÍOxþæ#ÖW«è™ãX g? =Y.Uës¨V ¹RÄ4.ýÝ_øúm?¥‡NÐŒ|ÏÄ.1®®Ö €±‘Ù éšÇB³p“nçèëKpëêÝ3 K”°fJ;*í¢Œ+ ˆ%—`Ã!4iâ²JõÃá8€ôwÂ4n ‰cX€$.â´‹¬‹ eYH‚ÇÀbÏ 19s?$2g20N¼”‡6b4„ðÂi,ÈB <ÆÙ½l3ó‡p’A·oÑ· 4{©‰‘,…sb{Úœ``@7Ûí>¡Â9Ž{†2õ†?ÇE6Î@að€¡K›·D#eK”4¬„JAùJÁ÷ßs]G€¯Ç<Àý¢<À’w”󬊯hPžRºÑl}ÞØüréädYY˹³%»Þí|‡¯Ûûèô8團D£Ò½½J/?¸Q<1³4¼x‚rîüˆö˜[*Uåi0‹/~’¢BØ92ÆîÛÿý¯ÿ¯°f*ÈgIEND®B`‚drpython-3.11.1/bitmaps/24/Help.png0000644000175000017500000000274011150445515017540 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  šœtIMEÕ\qêÐmIDAT(ÏÅ•KlœWÇßkæ›±çáÇ8‰±» !/¿‚“F&*"Ú Ê¢Qĉe…„P…ØA±Ê¦‚¶°k…¡‚„@4!%´¢*¨©›—k¬dl'Ûóžùæûî“E¬˜G„ÚâHWgq®ÎïŽî=þÇæü×èì³ u ìŸJ©Ôc­#⤡¢x©ñ¼un|SpÀ‘gòxþcÅá/Î?xxw)ŸÏ„AVjK§£âv{éÒµµõʯlœ¼ÈíoWÞ`æ‡)pç÷{~áôá©SÇ÷Qìó‰cK”hâÄ ”C¬¶Z†å¥u®¼qéVeùæ“*Š~ÏæwºÿœÎû÷ä~*ýÈ‘c÷ýê—OMœ%›r)¯ÕÙ¬T‰;-Z›m„T8F‘Íç)ŽíËEQr:ét»ÊùØzĽ{>7tzÿÙ'›?º´èX W—+„¢ÊƒsŽä™ž)¤o]Ý gŒL0ÆîšÈÇÝh.ªÕ–Mûå+ÿ 8öƒìäþýü‰ÇOÿðØ€#”o7Ȩ:ßúÒAêmÁOÎÝ¢ÖQ|úÄŸ91ȯÿT¦+d’ •%UÚ—‹jµzí©Ÿ!^i¸Ì=–‡æOÚÀOÿ¸E¢\Œ1T[-¢¸K:°a_ÊM§ûï0ÖÑÚ`Ð(£¸¶®¹µÕevÌc´à¢¤fv¦ÏÏÑŠ »óìo*¼y] µ¤Öî E Fc\­Œƒ½ó‰}%e3é%IØoÁhp4­Hñ祘B¥ŒáSÓ­žüQ™·Þí²^h)‰E‚Ñ ¬£ðÜ4:‘Bw{Ý»‹ÛZ{`x_ÉÇ ´†m_íhâŽDÙ"ÊÀ/^«¡¥4uG1Û^ãidµ™n´¹óŠçrùêò;YWPÌ8Û—åv…Ôšs—Z<ó»*.¬¾Û9Ïõðü¸¼¶j•|{àz¨Úøeõæ*»Røöެ¥Ø;ð…Sþh–‡ïÆÝV»SÆÑ†T؇iGÈÍÍó8îÊ`ùÖjóÒÚâµË9WP* ÕÒ¥äÔ‘Îg™µ|å“#ô¥‡}:ù×YÔ:'÷ôU“È…±‰Ýƒ±RŽè%X£°ÖáÐd?ðÂjüe±‚5¬Æ1?H‘íA¬”·ÄÚêS¨ï^¸ç4µá'Þ‹›íšìöf÷LŒøA€”‚ÊF›WßnñÛ7êœ}%c°ÏuH÷3ˆ•›U±ºzÖFÝàµäÞãº{^™àãKQ½ùNÒlìÏe‡Š¥A|ß§ÝlT#p,©tH˜ÍöâF’xieK¬®>e£î‹ðýÖû[™¹ï•/øZ¶4ôhnbï¤fúñü”Ö )»Q—××d¥rÎJñc8³üÁ—~ãŽëÍz™p·fr‹Žz‘éö6­‹à®ÀÓ1ÿ/û$ÒÊî€ØIEND®B`‚drpython-3.11.1/bitmaps/24/Customize ToolBar.png0000644000175000017500000000175311150445515022160 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  šœtIMEÕ$4~¼FüxIDAT(Ïí•»EÆÕÓ³³{½;û|XhïŒE`Ä ñ‘ þB$‡HHüÄdDdˆ˜ˆB„8@X$Øòãtgì{°{;Ó=ÝU³æd‰‰Ä%•ê©êûªºZ=ðÐþo“;¯¿ôÖøüÖPÛÖÄ uèõ+ÊÒcΑT)¼'æDÕï£@QzL„¬J6c°0@EçȪ¨ b|öÝßúÉ¥ÍwvŸyz57áðhÂòÒ€ª*1ƒ&´”½‚ñ¸fuu‘Øfz½U¥ ‰#k«CÌ¡n"YaI#»¦ûÕ•¢wñ¶Ÿ% #Þ{ú}Á ¼‡ƒÃÌùGc°P0mŒ6@`ÔÓÌÙ³=~¿›Y\(ˆ±ea©@!¶·Öý’î±&÷ÐEÅ9c©oܹklŽ ÁpšifÑ`ãŒâ$åæ>\¼d˜‡˜Œ2ÀcëFáíU Ä™·á«°u—ZК% T ©ÁXà™±€w´fe-2œk@[°È…'#¢‘B"qmƒè!žj†/€&Ð .îQ…=¨–AÒ³)h Ö€N)¬f0ÃX6¥—k îòd ሬx¤›€e8ÞáÞ—ïÇ›W¯·_~v­|þ5GáAO@;¢Ž4€Õ§Ú€Ìp' ¹!§ŒC2ЙæúWúéGß\}ûÃïýöÅ÷?qüóŒ¬é-€Å9Òùx?¯ËµЬx$uêZP,rq«ªßùõü¨2Jëºù눰ºkJëÙ$õéDtškr›ð",An(G—åò·ŸË·n|0Ø~bÁ&äÖv®Ý»)©:b ÝDR£9SÆ“÷áäsH¡[ÖÖJÑæ9h þrÝiînŒ¶³ ‘þc-µØa"·ŠG÷¨÷?argLáe Ó€PSøÈpEq (g>ï§YTÀÀ;}o×w&ìþ2F$R–J#±N,¯O½Ãþ\ñÉß"ÀF·dq‘õhVŽ÷#Ãs-ñ$Sx#µ@uZð@g.豈ÿ‘'k#×c¹LytíA;öÇ]g–À’bÉ:oïcÅZƒd˜¤#89!É»/n\9öºmX"†!ˆ&€ †@ÕH1‘“‘’’Ú„¶:Ùœ3CKÈG\ 0cùo-?üåþ«ý [ñeœR~ÈpIEND®B`‚drpython-3.11.1/bitmaps/24/Save.png0000644000175000017500000000113511150445515017543 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øgAMA± üabKGDÿÿÿ ½§“ pHYs  ÒÝ~üíIDATxœí”=oA†Ÿ½³-cG÷ T$ hrÁ‚ÃA ÑQÑ èQDEG\PBŠˆ‚HHˆ"E(Q ’‹ˆ3ÄÞÙ¡Xßù>Ö&#­vgWó¾3;ð¯‹I·{5®wPµpµ»†*~QÜ]zNï'úþ§ÏX+ø«þSK•¸Þ¡}ú "?0öwînbXq~Y¢Å³uÓ÷'÷ŸòòÅ=ÐÛx¨AYF®œ– sdªUœ VJÀ%ïCo›·)Æ jgŒC %ËÑ(°Ô¹F/‘~œÁX&†ep­’¦{H¨ $Éç!ðÿü¢H0ñ“·¿Nr(')©[8¡Xë:#š\£‹ 2 ˆWÙ~½“u­Ói;Šz8®­zûy&j™s¼»?+¸™Òl¯cL²B0)ë ¬¬(õF6âªI¢¼ÛùE·{ PœócÍ5 ¬éýÞÜØhsfÀòrD¿–¯ßŽ,"ŽVËÇÁZ‹µ~÷º béõLkfl=$¾Eo^o²v>:Þ?ådq‹ÿ!i¶bjõ“ù’%ÙÉÐÏpQ.^¶ž}aðý'ÖÂÑаý&b·•+U§8u…’½| É¡ÁÉðD-,¿´"¾Šéëõ®IEND®B`‚drpython-3.11.1/bitmaps/24/Run.png0000644000175000017500000000075111150445515017414 0ustar dktrkranzdktrkranz‰PNG  IHDRoª¯bKGDÿÿÿ ½§“ pHYsò ltIMEÕ!€d vIDATxœ­Õ¿/AÀñïÛÛ³ö"¡QP\¯?šë”jÀE)¹‚ˆ ‰N±êJ¢×I´J …(Ü­s n÷ÎÝÜŽ‚„‹·ÄË43“|òÞ˼Œh­ùpŒ§’/I¾ôÐÄTá ¼ò+Ë u•&ÇãÛ ½e†Ú]]’z‹ÊMZË ©„çW.8¹âø4•e†ÍSLå…0â¢ÂîaËÒ#ÍS‹ûaD-¦³VîcY „z“jƒ0¢QxŒY ~²\3µˆûŽ|žÏï’/é» -”hê1a“f/Ìn˜-si@[¡º$Ú°¦× 5Z!• Al×ßÂ2k 4¶q>ß2”fî‘nßC Ò›ÕÙæoší@ÎC ÊíŽVÍŠ=#ßC\:_ ý%«b…€Á¼A:Ùí^ñ'Åž‘À÷i;d³l/ôQ¬ãó"3Âò\Å eDÆFÜÅ™T ¶w”q¹»®§W1þ"ï^±Bˆ7ÿΰX{í>lIEND®B`‚drpython-3.11.1/bitmaps/24/Print Prompt.png0000644000175000017500000000242511150445515021206 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  šœtIMEÕ08ÄXÁ¢IDAT(Ï–Ë‹W‡¿[UÝí<ìÖqÍÌ c@'ŠˆFtð…¢F2ÉÂBÜHù²Õ€‹„$AY„l‚‹d²È.K1‚%¨ ˆ Dãø˜±ŸÕõ¾çdÑÝ3­±5ª¸Uuïùî½çwÎ)Cvüø—ïnÜ8yzxxYTŸ?ʘz½!×®]ÿüäÉO¾Þ¯`xxhhûö×W¯]»Æyú‹v]033§<îe§'@U}vå gÏþ *ø~dâxæíS_[vöÚZ@­^+÷8ŽÁ˜ÿ˶­;QTUe÷Î=»Ue7ªH×û?ÿºrÿ0Ï@i4ü–Ú7ÆÀ mˆ˜ž×uÛVÞê[¾þíg¬ ™Z¬X2¬Z2µÄI–e|0u´àС&M“‚ã¸]Æe¾?¹i’ ²˜fÒÌ"Â,&NB*Ÿ[åûˆ "ú´“÷íÛ»LDWãNAíCcgÁð¨e<"HcšY4ÿì§!å¨ÁJ[@¥¥ozzš$IÖ .~oíÚuW­ZóÊÈÈÈPFc¥tË”fE4Ó ‹ ÒˆjìSOšwUEUŒ788¸qûögöïcÛèè8žçá:†~ú…Êø¨ZÁ´A$hbü$$È"êIÀlXŪà8.*–,ÍrÞèèØôÔÔŽÍ«WOe "Q20²’Á+È<8¦¥”L˜_}ÆøI@%nPOšH{Ç:JêóJ¥âÔØØXÎÅu]\סو±KÆ©¸8¢(ÐH¡+ÕI@9ªSKªQƒDR¤+&Ui‘z^±XzmÉ’"žçeJ–¤Ô‚˜[ºŒ¿g }¸^†J¢ˆ:…ø:/nŠª` ž—φ\×ÅqÒ4±ÔBËz7gàvÕÐÌÀé ëuKyikíãU*¾wãÆ]–//18ØGž‡Ç¹+}TB°h‹u¾ý/€`Eð¬•øñã³³Ur¹KJ},Í÷óñæ ›§–xTCSC&-±Þy©qZ¹JOUæúûóãŽã¢*ܽwŸ¦_çUW1®‹ã¹˜¢Áª™„/âŒ1'‹ö~.çl^´h"–óçÿàÒ¥ äóù®\DWf5ðÎÀ ^¾ÐΨ"ž1Üp]}«Xì7qS(¸ŒrôèQ …tAŠ*|zþ Šve^w¾è‰äÙ<±ë%I|9Šüz©4QʲEìÝ{€M›¶²eËÒÔ¢ªX+])XùqÕ1D¤U• ¸ŽÛ9’–smFÔl hâ•Ës—oß¾y®X,N—JCyÏëgýúQ“e"‚µŠÈÀ/Ï¢*ˆ * *íBÓh»jbŽyq±XšÌåú7LMíúèðá7÷äry§3ÉZéß~óÙ¼\Z¬8ŽC­V }¿ö‘PT£¦ßxZp'Nœž¼xñÊïišI§E‰†a¬Ak³©ï‡Z¯Z­6µRih¹\×¹¹š>zTÕJÅ׫W¯ß:uê»]=‹¾j¶úÞ½FTí£^?*O×èŽo[{òäÉ€ï76:£þ¬u!´¾ÂBøIEND®B`‚drpython-3.11.1/bitmaps/24/detailed.png0000644000175000017500000000040111150445515020413 0ustar dktrkranzdktrkranz‰PNG  IHDRÄ´l;gAMA± üabKGD10bâÕÏ­ pHYs  d_‘tIMEÑ  %©V&%~IDATxœc`´Œ(<ƒ9ÿ‘¹† ÇÎ_˜‡ª†HÀ‚.ðéT2Ã—ß Ÿ30D8#ÇLìà ýòU|{Ãÿ_?~þ``ëe`44Hú®—îC ƒa†~F3س5ØŠÁ† Ç(òþ( /Í £dàÕP»Z“þVIEND®B`‚drpython-3.11.1/bitmaps/24/Close Prompt.png0000644000175000017500000000213511150445515021155 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  šœtIMEÕ.Óµ„êIDAT(ÏÕ–Oh\UÆwf’10i’‰±c‹ed(ŠI¥ìÈ º°&Ð`VnŠh¢$…ÉÆ¤ 7®$AºLº(b!q¡° VDQ!b! c†É$3óòÞüy÷¸xïÍŸFƒ›.¼ðxg¾wßýÞ9÷Üï%"<ÈáãÀÕ«Wæ{Ã}§7q#ÁýÔï¬Ø™ã=a¿°ŸÿƒO^ \¸ðêP<þB·ˆF´FDÑh­7qŸ5ÅNS,"üüËv=ÔìærÆJRÎ*@)ª)vñæáªNªµn”H´€¾¸½Ìzöwúº{¨i-6¶ÖÔpïâb¢©‰­í:V›r¥Â3½QÆâçA´(¥þs}øÑÇôœ?ÅAÕâ Vƨ˜5 ³V¦\1ÉçKü¶ûZ4ZK#ƒÑÑQÆÇÇ)•JGÌ/,0pð/G8¨–1j–KfQªšìZE"vÑ‚¸àÈçóˆ###$ ¶··ëW"‘`dd„ŽŽÎ ðÓí[俼‡Q31ªNFÕb¯\¢P1P~Ÿ×$ªNËåØÚÚ" ‰Dfmmááa"‘¡P¨NøP°ïo-#K»+&ÅÊùr‰¬¹‡-ŸÏhqkäÞ †ÁÞÞñxœ®®."‘ýýý´µµ177Çââ"›››”J%Š…}î®ßáLû“Ü}8Ç^¹ˆ-]µ‰ú{y1ÚÏö_òÄSgß x%ZYYa}}\.Çôô4ñx€™™Òé4;;;-ûQ©TøüÓk\ô¿ÉÒé;M·DÎ,˲,:;; ‡Ã- …ÃaLÓ$—ËÚôcݽtv…ïCÅ=xºU‹b±©TЉ‰ LÓdvvÓ4™˜˜ •J‹ÅZ–91öFŠë¬"´ˆj!djjŠB¡@:frr’t:M¡P`jjŠÁÁÁ–Å/^žäÆÉþ±=¹¨— ›Í’ÉdØØØ ™LL&ñûýD£Q²Ù,'‹òZòÊ‹ãhU³Td22™Ì¡.]ºTûŽ?ÊåÉ·¸~|õ_£RÊÛäV‚Æ ¾@ˆž® žøz#õö{|vìë£õ¿=è•Èé"QK7òçâÏwõëw\[¹‰/àkh|Sw|Sü–Åv¤ õùüž u;g£{r®šäZ@4CýÏ24p®î8š‚–†Gxº¢Àïó×K"¢±í–Ql=¢õó|A‹€kÍx‹‰vd¾nFÒ:G;(áõ±WVƒÁާEëín¶K¯C¸ßV[JÙˆKÅâþüåêÿ¯âoï1¸yQucIEND®B`‚drpython-3.11.1/bitmaps/24/forward.png0000644000175000017500000000061711150445515020315 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDùC» pHYs  ­#½utIMEÔsfǦIDATxÚí•ËJ1†¿s’ŠàFÝx)ô•ú,]è8¢2ÚA|—>J^6JA·.‹A‰‹t°–¤N†vׇdòsΟI`«Œ~ÿÆ¥®ÑuC’§yDÛ”\\5‡$P°ûpÙbS{l«@Yæn4:“Æ€A‘#àSÁˆ€Š/Ù¨‡tŽ .‡Lw SÈŒ· ØÙÜΠVa¯ ·Uõ ¨Óèßçùw‡=(‹°'A€JXt:ŸI»H$.‚¾ÜÃùõP‹l¬‚í©§‹x£¾¾:Ç¿€ÉC\¼ö3i›ÞU9»]oþëãrñV‡ÝäÙ¹OçžÆÎ5ùÑ´ èý­ù—· NVؖŵ¹Özálâßø˜[[óÏHIEND®B`‚drpython-3.11.1/bitmaps/24/New.png0000644000175000017500000000102011150445515017367 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øgAMA± üabKGDÿÿÿ ½§“ pHYs  ÒÝ~ü IDATxœÕU=KAœˆÄào°±“à´V hQ±KA!"(þA°M‘ÂR¤µ±µ·l¢„Dó¹;¹‹{ïÞÝ­…… {·÷¸y3ïíðÇ#§—wîYZ_ Á¤~¿­?c«`P=.ªXêØ®4I’cK Ù“_#òsDv†d{@~ ÈVŸ\;|àËû€g—ujX3Z,c'÷pšpŸäçòØ=ØÄÉy-F¢@ ׆QRèt{èvzØ(®¡\¹‹Ì&)ˆa$ÉH`iq7×µé>X])³Ñ¼Ê¥X‘i„Ä!8*`Yˆ¼wºwá§À Ò*W„6è®ţÏy˜Lf 2Ž2ÝÆlˆgM [×ߢ«Ü:¸ä™¹EÖìqÉäáó·H¦´N’±LP6«D –y+Þª'Z ¬L‹bíQ £O‘]RŒˆùÕ Üd ¢@Úðwm ÄUc„"¯"[N~6Zk¤†¢Yí§ªûS5®²p¡Å\Z¯oì?ß—F5îcJÏIEND®B`‚drpython-3.11.1/bitmaps/24/Next Document.png0000644000175000017500000000214111150445515021320 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ -…I#-îIDATxœí”KoUÇçÞy8cׯÔV’ÖI7T)éŠD+$ºãtØtÁžÏ5_‰EUU°àM‹ %¤ (¤´4Oœ&öxfây\±]»­ŠÊ† GºæÌùýÏãøßþk“á—ééiU¯×½³gÏêõºz¦@"ÄqÌÚÚÚáÆÆF{ee%ŽãØX}‡F£¡fffÆkµÚ«µZíµJ¥’–àišš©©©ß´ÖW•RkKKKÑÀ©ÑhT/_¾üƵk×Z‡‡‡æßÚÖÖ–YXXøðÒ¥K/Êê—éܹs‰‰‰‹³³³…4Mi·ÛOÓ "‘Þï1xžÇÜÜÜ…0 ç‹Åâj`J¥’ëºnYk-A¦éCÑ 4$]$lAÚÅX.x%D;H㺮+"Ç\×uûQJ)­µÊ²Œ(ŠžP=ÀÞü ÷þ v§‰ƒ!«rxêEâó ´1ˆÕor€1†n·K–e£Êµµ·Ž·~ƒ¼ÿ'Nu 5ù¢5&MpÛ{8·®â7o£YQÚQJSdY¶m£”"Ë2Œ1ƒ+ ÕÙcìöG;¸…;5‹šœ†\DÉÐå"ZuÐw>¡˜oâù-A; ¶m Ì FÙäv–)ì~‰[Ì£ÊclCkcP=”ª'·u@mç3*;]´Ix,ÇqFJCâ5oâf¿¢ì¬¦gÈ´…€Js]•¢(ÊwÐZcÛ6®ëŽ´‹„›8锳 ’@‚¸ †‡Ë@ K@î‘«øÊ-¤“ÏSüg€•CŒåp,gè€äŽê? 7BÆXE©NTÉ´ÖÒŸ¤áˆ­O!Ž@. €°Œéz%@“Y<ÜEI’¤aûûûí‘; TdQ´rNÞÑŽäAõT›!¿Á­ãcbÅîÝøh@5Z¹\ž«T*SY–飮iRÞº¸úúùWZj'Ó*2²„GÍÀÁ:þõ%Þ~sÁ¼gõb°½½½ïûþÒÎÎŽ“$‰Ý—cŒAk•¾¯[Í3gÒñÚIΓ7,ú¡6DðõŸÞü™ïš|Ýÿ–¦)Q™N§“…a˜†a˜„a‡a˜A`:毊ÇaµÊäxIÉ`Vïمů¸¹øï\¹Î[ˆô4d@Ú;Iï˜V@’Älf÷ƒ€ÄÊ(æÏÄH×'ÞøÍ/®óÁ7˼ûñ"ËË¿ÐÒáD‡ú±èžNçô ¥‹/sjþ4Ï•Ê4Dã™”Nû€»7¾eõóïùãÞ6þQ>ÄOéÖˆ©Ä,;?†w¼D¾àa·âÍ]ÚqJhŽ2Ž{'ýÚý×<Ó‘×-IEND®B`‚drpython-3.11.1/bitmaps/24/Fold All.png0000644000175000017500000000030511150445515020220 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~üeIDATxœc`ê€ÆhZ÷ø?5 ® ’ed````¢¦¡ØÀ¨£  X)¸rl êžL¬ra%Ót¬|ðêxð K1h[y㔣ØYu#†põ †~*µ`X0ô‚Ž âÿ»¼ËIEND®B`‚drpython-3.11.1/bitmaps/24/Toggle Fold.png0000644000175000017500000000061111150445515020731 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ (:²uûÙIDAT(Ïcüÿÿ?- ŒÑ¼þ U½R(ÃH œuA²´µ€™…mˆ¥"X°°sñ2üÿ÷áïŸ_ ­1Z ?¿}fhZ÷˜áÓÛç ³*üJfŸ&ݘ! aÊ ÕK®ah¸qz7ƒº± í‚èÆéÝ êfn”[ð÷Ï/ ±Ÿß¿2<½}AI׊r ƒ î\8È  mÁÀÂÊN› ºqzƒ ÁC’ÿþþe¸sþ ƒš±3ùÉxtó ƒ°¤"7ŸJ²–Q5dxñð:###ƒ°¤"CVßNÒ-¸yz7ƒ†™+Áx";ˆnœÚÅ aêFYNÆò§bÅõ±€qÈ·*SûÎIEND®B`‚drpython-3.11.1/bitmaps/24/View Regular Expression Howto.png0000644000175000017500000000213711150445515024345 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs¸¸jAõ[tIMEÔ5È}ÑìIDATxÚ¥–[LeÇÃì––Ë–pA XQ,ÐØÔ¤¦¥PÓµ›£ªA›˜&mbÛ}ðÁ¸‰ÄV›hܤ¨¾ÔRZY.’41 È¥Ú-¥¥R´´„ŲewÙËÌçò0Ã]ý’ù2™œß9ÿsæÿ­$„`ázóãU«ÕÒ˜”´í+Ñmô™¢¨¸®Ž¸|^ßá` ØÙÔôžªe`™UQ^Ķ'óQgƒ  ®jï|þ §ë΂§oŒT}Ú81ËTjô>»W¢{5< ÉÈJáÚý…ÖÌÌz›Í¾Ãf³Ë«´´ûE0’³×Q}ðÅâ¼Üœ/€§Vh³×ÿ­ ºÏi$Š‚Ï 9ÃDå ÏYRS?·Ùì[V쮂Y˜« êö@Õg‘  I1¨ªàÇbL––Z<áv·Ùìo­˜“ø½ Nœ¢dŸÁ<Ø`4ðJMÞ{à¸È¶ò F<\u]OrKäp$Ôdq*Ú`E@_‡àÈû_‹Ã”­«eå)Lú”×-X­¯'}Û°)>>UÀ•V8~f‚á‰ËÔ¿ßÃ-šþhÆU‘¡dûËxóßÊâ&÷÷'rìXUÖP®nnö*¼ã#/¿ƒïNcÿp337ÃüìlÇã™ÖM•€®‹õ˜d}¾zÀ¥Ko%ú¼N¥ákÂÆ ϼÆ&õ!6?fÁ{ÝÂÖÚ)¦Ó%BaƒnºÂF°fg"/ÐÄ Éþaj((ôóti}zWG™_šäãOKQ8gü|•ÕÊ–¼X>zf·n| ©‘SŽÛ¯—hÐÕù,mNŽÂØh¶Äb>\K ¹»@UÓYІ†9å÷“€ª]»u¶!…¡£¥Ž½OàKI4zûƒñA7ýä(H{·–œ’|„if†…%ü24^/ScP娹jPaàrùG˜\‹]kËßg¢®òFƒ‘ê?G©’ã7è¤ ÅCؚٞè§ÄbNFØš_0gŠÆ³ ^¸qgŠOd¬ð¡-å¦ Î±„•G“výˆ9n­hÏ;«@o†¡ØW}” º./ P¼ú{¾šè,f/’æ]YD¤¸ã‹ …º ÀsßãmþÁy¯µ¥Kæ?,EQ¦¤¥þUØlö\ }²ÿv/ ˜…ÄÿOÿ¯ÒC^¡¡ŠIEND®B`‚drpython-3.11.1/bitmaps/24/Redo.png0000644000175000017500000000122111150445515017532 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDeÍRŠ ¹ pHYs  ’ù¥tIMEÒ#•<-IDATxœÝ•1‹A†ß•+FÙ“\!d…-<®p-läš‹&iÔ4Á!ø¬NñBÎÂÊÂÂêáXîŠ VQ‰).Ü?8ÆBX!Ŧ3à.;ÀXLv“™\‚_˜bgfßg¾™o¾þ[‘¼ÛØÞmóB­Å¿9ç$ï6þÄÇÐØc¶˜ k}_ ö<ØÇçJ}¦c©ÉU€žTŒ 1wÑ‘µÒ}ÎÀK Tóç{gï?¢sP6.)S&æðNZ¬¬z3”š\@ DÃä;lï¶9³'+&”ÇE#nη³} ´©‡„Ñ¡ðáÔ{=¬[•¶€žTê8.¤óU†ø GŠD`Eg’ÍPÝÀ4.g€H„Í™^ýL@À.°¿L¬þŠ ClKÍõOCÆ 8‚àþ] G?â ×Öð´Ñâ¯ëe9×5Yà ÿ×÷^xM½*(59Ì `fðö‹/‘¼Ë¯Þ¾57*õ ¤‹6=̶P¨µ”.ÜbéjOnsÏÃË{7_<¹³“ŒÙšò¡QÁŒÐ9()@¡Öâàrré¥x÷,wXÝZßYÈYQº`©Qü%D X&d&`Yµ\KbݪAè¤h0Û§SïÑ¢æÀœbÅÙãŒ~êšeˆä]íóÏõè%ƒ] ’IEND®B`‚drpython-3.11.1/bitmaps/24/UnComment.png0000644000175000017500000000170111150445515020551 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ.RÕ–éNIDATxÚµ–_LSgƧ,2q¤éjYüPpËFf;X™ sX&F »ðf»X²d‰»Ýõv³dwf»ØÅØ(Ãé6‡ŠÖ QÁ „Œ‚Ô:Ñ9¶¥¶}wA;s´+d¼É—¼_ÎùžsÞ÷y¾çûa-Ãô¿ (Š(vŒ!ò@É¥‚º##í€/==ðWª=ó´\{äîðE>¸ùÉÀp‘_VRÁ^]Þ§%õ‡¯¹lÑ»4Üþ‘æà·Q 6jïrøû2À‘žÎüÕýZ[v>=è õðÆÌ)ì‘Ðzà0L®„Ÿ.×À`³;|éøkwÎãPƒ$Óc“$Î_S9W¸tyGšÐRà˜'Ô³Õ9?‰j.À$‰Nà$0„H|‰=ÉuGF|@{F±H [4LýìÏšþ ü²½ž®òV&¬$ f€Ž€¿ºue2aSì¯ÏžÅô³E"jÊgÀææ”ó(ãÖ ’‹à«Ø"/Ìá õÐ4ÝC ¢š ,qÑí<ʸµrYðôZÉ8j[†Ûkßï›ç¥÷¹†Ï†’sgÍò^ݲ¯y@²ad%Y‘”¯8vOèîðÅW€Ý€Üàí*oe´°Š¸ÑÒ·*«hxkÀm[x€'toÐÿÄ,‰J œýrÇ;©‰¿{žÛÒ ZÔ®$§:ÓPóǯ¡æ„bŒÝ]o¿ÕSÖtëÂæýºžë×üÕ™*h×}vá!{îÑ4ÝÍVõwTsWKöæu;ÕŒ¿P7æé1N<ÝÙÌ-Áÿ“Úp/Þ çü$Ó3ôÛ^¥«¼±Â]Ä–ÕÙµA’ߨ#!˙ӥûfÚ¹e~jC̘ÇM/E/•6^+¬¼7ZRiãsèŒïöH\0” ¼/p-ÉǦ|¹PÚ(½üq¯@Þ?¤Û2,éáË&QYª ðï»ã†u©Á—¡³¼ kÅiDbË™ßÓ„fkÑv ØÌÚ\æÎçÛL¿í!n´tjYö\ÈÚF‹³ÀõGæß½íxþÍ¢‰-,ùÿ¿µo%$§­ÖþYÕ‡ÛG «Þ~b\·hÏ™­»?§ãz­oÖ8þìÆ•Àž¤áTIEND®B`‚drpython-3.11.1/bitmaps/24/list.png0000644000175000017500000000044311150445515017621 0ustar dktrkranzdktrkranz‰PNG  IHDRÄ´l;gAMA± üabKGD´âÿ›`þè pHYs  d_‘tIMEÑ  Úóì IDATxœc`PÀˆÂ3˜ó™kÈpŒ…õ2ãéÓ§©;aªYè>ýúÿÿÙ×ÿÿo~øÿßÐ é?¹ê˜Ð¾üf`øüBã„Ôa Sü™€Á„Ô± s Ž1D8Ão" êP€UÔÀcòì †ÿ?20üüÉÀðãïŸ ?@ø±SHW7ôÀhÁmðÐË Ô£„öôÇAJÊÊ IEND®B`‚drpython-3.11.1/bitmaps/24/Find Next.png0000644000175000017500000000203511150445515020424 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿBß ¯. pHYs  šœtIMEÕ/$=ådªIDAT(ϵ–ML\UÇwf€ù‚a†R!B‚‚m¢¤¶¢MkL!UFS—FIue«1&š˜¸ri`Ù•®Ô°ÐhcªÆÔÁ‚ƒ¥`£SDÀÎ Ã0o†y_÷º˜0!ñ$7÷Ü÷òþÿû?çžsŸP¯¡Ä@¯à0Q"pZ_ðË÷ö ¸0Óæf¦/ðóMmG‚’MOT|®(ç\ôm WÿÐŒ7Þ|ëE~üÕ«<»í¦»¿±à lì¡ ¬@VðÝÁH5¶y'ಮÿ¤ûœ(  ªàËâÅkO>'p(6À6ù‚íÚO"É$éôÒ.Ãiž½>3Æüí5â—~  ÐÚ¢ùŽV¢šQ¸°$$sû øóõCãÓhK‚H¤ƒhL[1vk ßÜÜwønî:Ô-!±Ù¯X\\dð‹ï¸÷ø£<}(J­×]~O·ðí/K\"PßDCôà¶UÎÁ€Bö+”‚‘‘¢]'9ÞÕXW ry‹\N§# Ô~?“cÃ…|ì”d1r¶ÿ×wT¼˜¸ôZá©& ö{ÊàÙ¼ÉÊZݰ V |¾: Ã$™LnW zE¹9β4-ËrÞK[¤¦®ÈåM2šm‘jÜÄM?º®o;ª›B¤¶´!Ü„k$š.QJ¡6ëºU CI ÖME°Ê—{÷”úJIEm(„ÇÌðW\ô$¦åüZ”Ú%Ëéuúlóç/LMŒ¨jðÞýŽ;Á@,0ÓgÎ1ܸy‹áóç/ êêª êj 7með÷óËïjÉñòò0ÅxyyÁê÷í?v#›qüÄ)fff€b–’’l––bxöì9Üy‹ôõtš[»nܸ4–‘añÒ`±ÒŠZ°!GŽg¸té*ƒ´´$CBrƒµX;;;ÃÍ›·áf0121ð@,ÈÞŠ‹‰`ÈÊHaCvf*Ъ –¶®`9)I °È’Ü‚2^> Oü½b£#€ŽdX¼dƒ™©1ÜŒi3æ€õÞH |zBfŸ?AÄ@¾Çˆ§ øòå ƒ›gØ¢Š²B°O@®‹e¸yë6ÃÄþNpÁÈW]ý ÄHLQм©Ógƒ ¹Ùg H%l$@Dù”r44Ô°„Ëp˜@åJ@åP؃‚eíªÅ`>,…ÀR¾L @‹ PøƒÀg`ê±IDÐ6n¦w8›Ô" €ðúäê›·2<}úŒÁlØ,‹LŒ Á9ž>{.ŸH„× Œ Xab/Š‘ˆæÉ €h^áÍ- š[`ý ͳd•ÉIEND®B`‚drpython-3.11.1/bitmaps/24/Open.png0000644000175000017500000000066611150445515017556 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÕ!9ùÄCHCIDAT(ϵ–=NÄ0…ßD{ ¸A***îAAGJBÞ-¡÷!h¨V‹Œ¨¨¨|¤ 2Ù(ÇÙ(–,Y±ý¾73Žbf,ÙV¹ ‰hä„™)¹/OØ""öW9â!§Ý|ÌDgfŠ¥!'EÅœÍ9é50[¹¡¼NC²OÑæ–¸zT£íM œ !fnÅâƒnž×I‘˜‰þ …›~\^*ïsa"ip6›—õ¤T¸õë"“ v§»GçÞl)ýÐ(¯ð³þs Æãÿ´ §Èî5êet»ïjR¸EþÞiœÝ¨<ÅÝK@ØwÇ=2Ç÷£¾Þ4Îï&¸§¸{°F£þuÜM„¸îàóUãâ^ Þñ‰{âGDás½®³ LNªôe7÷Z®ž_½¥ÿ* ,Üþ1Ûµ2u˜ë1IEND®B`‚drpython-3.11.1/bitmaps/24/new directory.png0000644000175000017500000000163311150445515021426 0ustar dktrkranzdktrkranz‰PNG  IHDRÄ´l;bKGDÿÿÿ ½§“ pHYs  šœtIMEÔ ã«”(IDATxÚµ•[LTW@—;Ȉ°±õ-2D¥fMßòPÓ Vûmj~Û˜öƒØ¤1­FªÄè_Ä7ô‡Ä*DÀmšXJ …™LæqŸ§÷28ƒ±Æ“ìœsöÞYgŸ½ïÙ7MÁûïi¤±öðæ%kÌu&”ÞÁÏ.~»õÈß×ÿÙ;"D§/!¾q!Víÿåž‚ÿ+òüœ¬<¯Æ”Äaƒ!Ø[±±üëSMoUÅÏ•ë§Ä³KßÉNÊ\0CLöcØkÃäõµ=OÖ+àñ\ÊBªå l€°ºiíu’l× ‹%¢—8eÛ)ÍšµÉp]$ÖšauX`]E3RDfR @7 ³8qðT5fM‹nz¤(Äô©…”MûÚŠñ†œN;Pøû)õ×ð§s1ÿ’$OvÄŠž€…T ?jÙ„°*¾d¼âÑ3´ä!C ’Uµ¹§q_”"+c¸–9<)¦•Ѝ]C00–ü;]?r÷W[XÒzšæ' ¿žªR/ŽÅ.~¾sv€4qH…æ? w"ZriÈëÅ¥¹‘~¤X›mn>Wï3{[9˜:Ž•… `ð\= á/)ùàìGiU?5ŠšƒŸR×9ósõÌÝEVÙv°_'’& ¦) ©q›ïÜåv9‰Ð燨63xp8e½}`‚äÌÀ±¢0a4 Û†€àð¿ÿ¤H+òÄÒ’¢á@³Ó’LÍÏð¼ÜÆß¿ûÙì’ž3L tfÍ&ÐÝÏÎ|s²íB]cûIypâPço÷‚© 6!QCfS¤‰Úý^y.^¯CEéyAøA–s{÷]Ês†´x¯zz¿:2:Pû¦¶xlÝ­…Že•‹zê.»›¸ò«¶ÖŽuµm)X°nMvõåü6Í»¡ŒÂçû8~°€Õ+Ù)”“"ÖuX :öðI{%Gk>&_ïò—xõkÑãî–7&³ýy«@ ÿg«IEND®B`‚drpython-3.11.1/bitmaps/24/Close.png0000644000175000017500000000205711150445515017716 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øgAMA± üabKGDÿÿÿ ½§“ pHYs  ÒÝ~ü¿IDATxœ•_h[eÆiÚ¥ÅÔš”bÔ:‚"tÂ@¤ÂP, «É”QȪvâÖ‹1&t´ÈÀ57ÖÞ¤w‚¸‹z£ëÖêâ6¶9×Z7ÿÔºÕÓ&!Mš&閜Nj4i’žv{áãûÎ{ÎyÞï{Ÿ÷{^V¶7,Kÿ½ìúäVmå®Z«ïvz_nC€Di†ªõÆ»Ìzž/¾¹Áþ7zù釯õÏßÙ¬pKÖÒù¹LSÊ™ÒzNÊÜ•ÖîH«ëR2+­d¤xZŠ­I‘5iöߌØÖµ…ŒPÛ“í¥ XžÀ˜Å¹l¨|.û®x¢†GÈ›éæÜ¬­fǦ5¸)ÈSé§ìyp8Äs~v{Ÿå Ì»«,-G ¿±C pâp4”v®RPAn•X4BþN=¦à­£'H&V6y»ŸqjäS-§L)iqUº”n%¤+,oûO-@ww7}}}¤R©¨‡/Ïœ!•NóΑc\4¹š¹xcy3…'>}òxäx<Ž$ºººˆÇãLLL”@{zzp¹\LMMñÔž=\þù<¡Së¼wl°”sl5¸š[*82]õ ÔÄb1q:x<ü~?³³³øý~<N§Ã00 ƒzÇ..œÿžÓ´m9°ÖÖÖ²¶¶ÆÊÊ 455áñxhoo§®®Ž±±1&''YXX •J±šLðçÍ9–Œ%žÙ÷BÙ•¥}îÛ³…¹\Ã0˜™™!ÓÙÙIkk+v»¡¡!ÆÇÇ™››#FI&“Ä¢Q~ÿm†L&ÍÓÏ>_y/6žûîlƒl6K6›¥±±·Û]A¬Ûí&“ɋŶþàCÍ46¹ €lMWñ: ÏçS(’$¥ÓiŽŽ*NK’B¡|>_Eùíöútb(¤Ùeéú²tmIúÅ®þ']^”.Ý–ûU $I‰DBápX€Âá°‰„$)T€?9R_*€_5¤+eànI¯ì߼ɑH„ééiæçç ƒƒAìv;^¯—H$Àc{9|—7­¬"¶V“66SuOkyøÞäõÞþ-„–ËGÑÿÉàa 5µÕPSëÄÕä(T´#ïóÊþ^òT©jU‰Ë r]ÙdâÚ÷™.}u  vUŠjn^õ¾8,Õ´¼äª.O‹U•á §º©X6+¹¸ŸV¹Ý t;.vn™Ûí°Ê·Óf,»¿ãÑõêKm%.Ðæ.­Ë¥Àb-Á¯äy`C—f0®?IEND®B`‚drpython-3.11.1/bitmaps/24/Replace.png0000644000175000017500000000177511150445515020232 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  šœtIMEÕ'‰!¿„ŠIDAT(ϵ–ÏO\UÇ?oÞÌ0? Ãt*¤ƒA[-X[© 5†4UZ£[„˜XãÆ¸ào0.Œ1.\tc£1ÄñçÆ@ "TbK5f #Œ†aà1Ìûu¯ fà Èš¾äæž“Ü÷ý¾ï9çžóù!’{øxÝNê—ÚŽµkÿ0;›ÑgμýþåÓËý¿wéÊÙû5¿êÙDJî½j;®ýÙe*é—僟mWðhïɤ¿«y𰱋­j1?Žu¬vÞsØÔå.¶¨ú€rW¸«-÷IòA²¼²‚eY¨ª­¡a+D®uhár9²Ù,³wVÈub‘0m‰-÷µonAâÁP(’@H˜›cx|Ý— ë Ë‘ŒÝ^ xë'ºN<ÈÇ»q,” –ùùy¿âä¹§yéxœú€ºy&_jå‡_&ܘ )~tGˆ<ûUËÈÈñÔyÎ¥Žl‚K åŠM¹lÐiŒÉ±ôF²9A­*J+%¯ŸX,J4äÝ_«X,­T0Lͯ 6`š…Ba®Z€®¯‘«HÆêªà’rÅbU7qœ*’á:•¼Â0Œ¥êÙµ«»¢¨Dëº!Rb˜ë†] CI*¬[Íç€GÝ[A­¯ÔTÔG"x­Uæò:–-°l÷ÛÕ˪Hr¥ Êz‘P}do† Ž!À xÔiQ ³¿1Çr$Óóe<Åhñ6T_±W’s:ؘLgƒä‰Þ§°—ÿbêú8#7óÜÈd‹3wL&2E¦&Gûî R1 »¬ï}“-±¥ víUŸŸ Ÿáçki&†¾"ÒgU† £SÈÿM(PÇim‘εOXøãNàÅÿ&Õž.䑬î±}Ï^b¹¸Ìï·nb˜¼¾£œíí#Üa)¸€¦LÑQd:["LewwÓª×|Åã%Òt„S=çl)u$¨=¯1žþ€S­ž‹~MéÉBçÕIõ÷1ãÙ® ¶6Á]Š„`¸nNbŸ¾Ìd6‰…W.†^x¤»ûùí ÒßNÜ~s± ·O+·/ÜÆ=Ñd « ýÌ\¿j¾þx&òP·÷Ýôpç;›òÕ+_Ö¶|ߘH‚TîfàK) d–ÖN(«=ím¡3Å5%¨Ü‹ß–·>O<œlmJ-.é£ÿ¨Üháþþ^IEND®B`‚drpython-3.11.1/bitmaps/24/Toggle View Whitespace.png0000644000175000017500000000123411150445515023036 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øgAMA± üabKGDÿÿÿ ½§“ pHYs  ÒÝ~ü,IDATxœÕSÍOAÿUIü_J84xðÊÙ pññ°t»,- (!´€m H(AÚ,‰Éöߨ7FìÅzð !Ćô@Ø™yfw`éîêr1¾d2/óú~¯oÿ=qÚ(è½ ¸5ã7AÛ%5ÿGÃWûú~—Ú`01¨pûbÙhL%06oËÇNSÕ“) özú|š^ ´ÿâQÉ!ÍqŒéšº•úÖ!àKE€U˪œq·w÷üàõCu§^÷µ>4ïwàã‚Úˆ¾Ûd› ³.#ÛÑgÍw{gt¸¨ò?p.¨{ÉUÃy—Óé£ãŽŸäËɵޝèè#Ñèp1¸gDDFÀ³é}UlŸÙ¿ñ‹*Pϡɪh®Ö0•×#W±‡€ € `g×ã„ÒÖ$'0!ëÏ`@ÈãÑ«ØSãà‚03-U—·&±òòm(@zYI@.€7Û¦RXØ0àÜpA®;™GE°f¥ƒBÅÀ«¥ƒP€§ é;ÂZÅAª\,Rõmpx$~l\[”ª—Ê*+ážÌMÄ#ð¶(¿a(ųëßÜ•K1ñtQtç>·žÁöj-`äyL\8ùçžÍër‹n)÷ò˜òxsÏtì롳Zh-‚@ÎÝq7&½¬|îÅý.~úŸî»çA4ÎßtÎ~¡üºtG¨¿Š‘{n9‡äIEND®B`‚drpython-3.11.1/bitmaps/24/Select All.png0000644000175000017500000000061211150445515020554 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~ü*IDATxœíU»‚@}:¦Ò€˜k:S†6`$™ }x‰ Ã`˜ÃY€ÁÊœËá‡Ì7ÃÜqËìÛ·{»hÐɶÈÚ$è¶ézœADÀòXmóWÀlÐŒà#nØü[¶I ø’öÁµì4^¦¡'`˜°Ó§tf=¥E\ôÎk r$©ræÚ€3¥½×0MZïL«5 Ân&ô߀@þ€@D´æŽMC©pN_x!E:ìS-räd¾¤Öí@å>¾ÄØÛ¼VA Õ5­ "ª·óüˆÞz*lË#©óB`3}ƒ IUc¹6?œGŠ OPJ‘ˆÔÕö©ÉŠiH g¾$U×¶4*¸bfÛ× ªábæ¿Fë?œ?´¸¯ëd~ÿ¬»éIEND®B`‚drpython-3.11.1/bitmaps/24/First Document.png0000644000175000017500000000214011150445515021470 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ 0}H‹(íIDATxœí•ÍoTUÆçã~ÌδÒRLE,¡4%‘hLü\³wÇßÀÊ-ÿ‰k7.Hd£&Ĩ˜ Ú ­-íð1Lg:ÓvfîÌ{ÏqÑa@†qãÆ'ys“÷œû>ç=ÏsÎÿñ_C8Ž#Ξ=ëLNNfggg=Çq°Ö¾V¡jµjîܹӪV«ÍÍMó4¯æç罩©©Ù‰‰‰ÏJ¥Òq¥”^‹ÄZÛ>vìØ©Tꆵ¶^.—‡$òÒ¥K\½zõÛJ¥bÿ-z½ž½víÚîåË—?Ÿžž.;Èåré¹¹¹3gNŸù(ŸÉSoÖØé6B1æHé€Ä&›¼²­5'NœÈ,..~záÂ……r¹ÜÐ)?å T6´ïú½¯YÙ¹‹ÅbW8œÌŸcîÐyÒnö•$J)”RÂó¼üØØ˜7H -Qb¹uK´››6—ñxûÓn‹e7Üæ÷­ÔÃÇÌ—.Rð“@¢”ƒRJJ)% tX¨÷ÌBQ¥fÔÑÂÇŠèÊ&ÖZdÚàu·jߣ…æ|ñ´t±˜‚$I°Ö¢”b@ «ƒóÑT·´uª•÷ä“xÊ2ÆX¬µ¸®Æ¨ˆûv‰l+Ï›é“L3Äf´ c RJÇAk=ÌËìŒV¥hv×ÔÄúÖ*IW’³ã¤M‘½½õíT©°ÆŽ©¢•ƒVúéžãùâŽã<ß È(MVu&ƒwx÷ÐûŒùEó¤õÛµ‡ñ"7Ä:®ã -ŒâÅtÔ¢„^XÒ“œœ8M*åÐ6u„” EŽ›S¬—WðI“ñsx¾4â@79ŽƒRê9‚=º&„lÄ‹$;ÉPD)¡jƒî’SErn ßó£L:DAÂâ¶Zg9êàà†ö7¡“ìÒö·‰uDB!Aî;pB”Râo~žÀË›ŒñÛ4Ä:!$XKBL"DÚÒIšqmg+j°“D¦ûR¥avâ8ÚL‹˜¶†–Ÿ¡k{Ï~`ÿ6T.üùÇÒÒ_^¹.VÇW-Æ•”2i4šÍf™§ç µÆZp„»nŠiqvÛÄa§usù—od½öØZ#Åèd«µîGQµÛíþ0·õ+coñ]ø€sùYÆ_\—‰¡¾ÊBsÉü¸³>2½°/9Êû%@<øÀª¨‰Õ m©9êå((gÿ!ê7éÕnñkí7¾ªÜàçv™] ?ˆø%‘Â9å3Ž¡ßïp¿¹ÌíêM–j Ô¬%:Ȩ–gÚXB¸€ƒÀu2Ù§’Iz${ë4à Ûq‡ð…Uÿã§î/éüX!«‰pIEND®B`‚drpython-3.11.1/bitmaps/24/Delete.png0000644000175000017500000000211311150445515020044 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDùC» pHYs  šœtIMEÕ" &3ÓØIDAT(Ͻ–KhUÇgfr››&¹iólhÚC0 F X­˜5 ›BiJq¥QèBеZbMli)è®Õv FBÑRºp!èÂЦ%´y”ôšTbÞÏÛ<îcÎw\ÌÜ$·Iš(è3s˜søþßÿÿ=ÎÀ<Ôòªª1TTZ~$”›—‹1æß³”¥"s3‘¿Â}ít}= à$73ròÞøà݆æÊ’ì Þ‚yc¼) Þ´”âÁT4vêô¥Ðx§Svî:pø`y¨4´ãþÃø@ÐJÁxŒÀ…Ò}Oûg—ŒÑbRTÛÈsíO¬ˆ%@D–5°þ‰Æ«@9 ÊK~DÞ D„©Þ^zÎc²»³Ê¸!2&üåWÌÞ¹hwÙ¸$²ÀtO£çÏêïg¸©‰±ÎˆÃLO7#gÏ’;=Ábk+s]·0–g<ƒ©¥- _¼È®H„âcÇØSVÆÈçÍLõöòpp€‘3g(), ¨îevïÜÁBÛhË‹ÅbÂÙ ÷Ð!&‡†ˆ^¾LNNåy¹üyü8áwÞæ Ûbgv6ñë×™¸s»¦Ñ+AßR jjH?q‚{÷ˆ^»F¦ÖTlR¡ ¤ñŽÜífñð²^­GÇ×pÖ °ì4 _©‡¬lú)$;cˆÝºMØ|ÖLöKu¶!â¹+&5ÑõŒ'ÓN” I»˶!ÀdeËË'=˜F-f‰’&D4¿ýÊÌûïQîLjI$˜Ó×¶)õEó¿üŒ&–RtJ”ì/FÁä¢}HÑÍ›Äýý‡%{mé#³`;,Î3wéó*@ ¶ü@¯ËÀˆkŸ…‚Ù–ï(èì$Mk´ã0ó‹äµ]¡èÊODªŸÃu],Ç!?º„ºú#.+Ò® 0³äˆp]ÈyëMFkëXp¦Ÿ?HfS3•Uö–‘qòfž¬$:7Ëpf·¡ãn’EZ<Æ€Ö°ý©jts3#­mdm XU$,´Àþg‘O1Ôò-Îk¯c?sízÌÍãÒT’­×€›ôýÕ7U£cà&<µÑÎÞ 2N~ŠÄA»žƒøï±"Þa¯:WµfVš„Îg.*¥Ï¥(˲[áXfyLÄUÚöÞX^.+Ÿ­2 ,ï°¥À¶@Y–ZƒÈXWûï, î \mnçÿGjµAsΫIEND®B`‚drpython-3.11.1/bitmaps/24/Default.png0000644000175000017500000000255711150445515020242 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÕ83€W½üIDAT(ϵ–MOW†Ÿ{Œ‡l>ŒÍ§q!œ…AM(d“U#µ‹,P¥*‹æ'äÏ$ûHT"R³©”¥]4E*ù àb®ÁÄcŒñøkìñL¤NJTõ.¯ÎÑsϹç}ï…O\‚ ÂùãÏØ××ǽ{÷èèè ›ÍòàÁÂáð¿æÙÏ ðz½º»»I&“x½Þs刢ÈüüÇÇÇ(ŠBoo/¦iR.—™™™áÙ³gØ>B¡wïÞebbY–Éçóô÷÷3;;‡×çÅÄDQzºzP…|!ÏØØ·oßæòåˬ®®’ËåX__?[ÁÎÎÇÇÇlmmÑÞÞÎôô4W§®bñƒËÑ_É•óØm6ºÜ]„ÆC\Ÿ¹^ÏßÝÝ%N³±±Qß;U®ë¸\.‰¡±MMMhyW®*¦•FÜ-­H éBŠ­·Q$´6·¡i÷ïß'³¼¼LµZ= 0MUUñx<tttðóæSR†ŠÙ`¢£“74Jf C4ÈVˆ¼}ƒ×Ù…©[,ü°@4%|L].XàóøX¿âÉÞÈngY> °€wb+êÔ£·H;ß~þ=ÁÑ ‡‡‡È²L¥R¡V«AàÖ­[tww …èééÅÓæå—ÈO¼)ýŽSrâ¬8ÏÌx¥¦“­јrðMiž›7o2uuŠùùyVWWyüøñ{ÀÔÔ~¿Ÿ+W®Ð(+ØD;jyÍyHÁ^Á!JßÂÂÀ *×È”ö9ÊÑÛÛKgg'n·›t:Ûí~ß"Ó4EI’ÐË:&Î&‹šRBËïœE,,lXØÊC@×uŠöÅb\.G¡P Z­ž,ËbssÃ0p68¹8ÄcëÂåp 7[Ø$ ,¡~~0M@èÌõ švÖ×ÖÈd2$ölll ªê{À‡¯×ËÄÄ$w¾»C_ãEºªý¨öcĦ ¢hÕ›dµ’ˆ|Ôΰm‚J¥ÊÒÒÏ{N8Æ4ͳcZ«ÕÈår(Š‚§Óð?Hµ` ÙRÔ5ìr »d!Ú@¬IÈÙN†Ò_0Õðe½Ä“§OI$öÈd2ÿ,4ŸÏÇÀÀ—.]Âëë¤ÍìCÈ:ÐËE Ó@4Øò MjŸ%ç˜0¿¦µ©ì’J¥êZú[hgÜt||œ@ À… (ëe.Šst¦FH«q â’å¤ÝêÃãèÃ);É—4ìv;ÓÓÓ¤R)ü~Ý.Np¹\  ª*+++8N†‡Fl@’°,“|)Gtk“µõ5ü~?“““´´´ÐÖÖÆÈÈHpæAààà€Z­ÆÒÒkkkD"ö Ú:ܸښ)–ó¬GÖx´øˆímö÷÷Éf³$“I677yýú5š¦­À²,¶··ÉçóõÑM&“†A:fvöKt]§T.‘L&‰ü¡Z­"Ë'6ÒÜÜL,CUÕ{Q±X$‹‹ÅNíg2¶··1 ƒJ¥B,«_d©TâåË—ÿíM6M“h4J¡PÀ0 vwwù_Ö§~[þô,K àÅb§IEND®B`‚drpython-3.11.1/bitmaps/24/up.png0000644000175000017500000000066011150445515017273 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDùC» pHYs  ­#½utIMEÔ4¢ª§g=IDATxÚí•ËJAEïL†,]ŠßÕÿ"ÄÁÉÊoɧd‘1ÅGóœ¼_s\ô@"Ì€˜qHAw4}OÝêEKÇ8¨0ÆÇŸ¯•¡V&}ˆ1>:L—°\§ 1Ƨ~Ý) ç0YÂ|•ÄŸZ Þ†ÐÁ×ú3-`¶/ÄŸJ]xîÃë>h¡7… ró'ˆ1>å*Tšp׆z{ð2€÷ZcèL`0ƒñž’!NœøÅU^®$¹RÆ&eÏ$ϵ+ãJóOÉu~*œçŠ*• N" ©‹Ëë¼¼ÓHܱyÝ’r…bìv!^ÒÁ.4DZm¤+ŽmñwvÃûÍ›‘-²ˆ"Ë̘qK´ÌL·dÁ ‰#\LKBÍÁȸ ´ÐÓËë‡^Â`«Ù"_|’'9ï{rþÿóÿ?Ïó¾’‚õ ™uŽ8TÜ–'·Uþ×ÊŠç2«Ôó58¤ØFWWWÉdÚ‰p}ÇÄ€gà—ãýØ4r­­EŠaó£[¬Uùæ¢=ï>­9”QüÚpmË¥¦{R !¸æe]§×þÔ<˜Ó—8÷“ Bï’Í÷$I:,„˜¿+Ê*‚ÑöïØ­I¶˜%ZÛI›žähc-<˜‹ÃáØy× l·:ÀEFžûí"‡ÇÏ‚±çkd¾iåYÓ+†ï¶[4î9q3 âùäÂþÇ›«°³¿Ò¶Ò¢Š µ‚¦ðX鬿óüÔsÒ“-IÔ}ó)%}U$™2¹p¾ ­²…Š’_³€¬C§j²€xƒŒ^+]]ƒˆ‚™¾‡¢[žƒoÜ^no¡á’’~h›“— €H8§ 6Î-,‡vLõN ~büçÖk±b®—õ·|î–äDÆÜ¼J«e›­¢ÄòLME𣌲º‘ûÚ߉ÑmÀ«šÁUÏ©èŒÉw´ÈZóeξLÑ>AW¿¼ìTv.kß²gÒc·ùóI`X;hÅŽ‡€Zn¿Û-ɹs×™ÏIÁ«)'ßâ¡ô~‰Í9§¯Ã‹qÏc kH``…E!äÜf ·~lèõ ] ¡©ÕT&þö¢a¼¾eÒ 'ø™^ܾª¤»áV‚î°9±Çô÷;»rÍ»<‘¶IwiæªÀ;>Er†üÓÌ̆p{Θa›“²H·\\¶9‘]ÐSÕ¯|R¢+³éÈg¡Ñ°I¾‘³ƒò@/E™‹¨ ÕÕ¯¨ª:¤E'w)ZTƒ«ž›;àn( OBuòØ6Ýœ~“ç2Ù[ ¸ÝK¨@’V«]TUÕ ¨@DÕûmNÌ@r”tNúÿ\úëÿ¾æ|½ºBЉIEND®B`‚drpython-3.11.1/bitmaps/24/Zoom In.png0000644000175000017500000000275511150445515020131 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ 81?Y¿ézIDATxœ”ÏoÇÇ¿3³;»Ë].)вDQ¶hÙ *[n+.;0j#(z)ú/è¥@=÷ÚkoE¯í¥@ô8B$)bYHSÚ•dÈõƒ)R)rÉå¯ÝÙ$«†#Èmð€‡Á›ùÌ|ß{¼ÙÈ‘ó¿mÎd2LUÕËóóóSét:F)¥ÕjÕ- ÕrµZmÿ_]×é‚=77÷½éé鎎Ι¦9Na®ë6ëõúz©TúûÚÚÚÒâââ¾”2x@9 …Ü¿?žÉdîf³Ù_ݾ}ûÖÔÔ8ç „Àó<”Ëå÷óùüBÈŸ…zôèÑ6y€½ æçç#¹\n!—ËýöÁƒ7‰†Ã!ƒƒ„°m›¤R©¤¦i׆¬ÕjyÇqoÆYXX¸1;;û‹»wïÞ‡¨×ëpNçÌÇ–eÅ,ËŠæóù½J¥òâ" )¥ÚÍ›7³7nÜøšÍ&\×E¯×C·ÛE¯×;sÇq ¥ÄØØØô­[·îào¬A*•Šiš63111&¥c Š¢€o7™””RX–eg³ÙYÎù%Ïóö/˜¦©° Ã`ªªB×uB¾RBJ MÓ€™¦iiš–8œSp|ß!>¥T†A¤”çÞþ%„s!„ ‚@!<\0Œ Öl6û¾ïº®ë¦R©¨”v8çh¶ZÝâÞÞžïû œ4˹3APÇqú¥RikwwwíT_èº~®›–B)ZÇ ÑÜÝé!ÂSiÎ} „a(5Mñx\K&“s©TÊTUœspΡª*Eç¡”¨–ËhwpÙ²‚«†Þ\^±þyvºHJ¥’—H$Ji4‹¥#¦enï;88ì@U‡ö·¶°ùŧð ëêõ«™ÑKétz‚áhùEa @øº¸/'™„aˆíím·Ói¥” DÑÿø×Õ‘Ï¿*0!†}…öå­õöög“Ö—Ÿð ° •53—»¤Æô´©MÎ+{µ#œ¨B‹Åæò“åg_ó´öÉ ouÓ‰T6×7×–>}þÙßòÊê’ƒã1%òníRxÊìÞMÉ0xKg²09b>ß;ák€ˆá}{b8öÎXµ _&³"6jÔJŸ¯lU?Η{ßâøx2ÊbãñȸBµW+C {ìûwî]î9­ ¹>½(UDð¸rgvæ—H¿ûÄf>„5–‚a0G'a_ù¬ô7üøódí«D”§.'­IJÁõ \¹÷Þ¿Òn6¦Å ·~û°Øê‹W³?™ÀHæç¸öÁ;ˆŽ€s ÝìIÉkq˜É8T}uõÉ_>i{ÑŸ¹>nOQF0¬—ázÈærW›ÕÒ8ºí'¥æÁY‘ðˆ ÏQ0<>Bks—f3°*:ÅUÔž~qâÏË£µÝª;¬ÆMm?b¨3ßIÙ“DUºÇúmD½Ö””â_ÿ(·6^Pˆ¾a„þTþ¹ŠÜÏ~ {ÂDíÙG¨äÿ·úõçEt=×¢3 ê†ÆŠ†®^{+m§XÐGú¢Ñ÷n­(¯H$Ñ©t*.JKChQzdÃ`ÄE§tŒ‡ÍÓŽ“R‚­×\‡1²Lýו_¿=iW†! •öâz½»âzb¨œ~b )Cž‹/öQyú5œ½6€ð4'„R†k•ŽãzÁc¦Rÿ¨çÍK)ý•R{éñv£ÐóùúhŸH¨ TÃèõ˜ÂЭ÷Ðouxÿü= € @¡„èÙI{dàÁQgØrú~€ÿoZR± $peIEND®B`‚drpython-3.11.1/bitmaps/24/Zoom Out.png0000644000175000017500000000263011150445515020322 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ 8:¨‹fa%IDATxœ•ÝOUÆŸsæ»;»K¨ Ô@ýiuƒÕB+ÚØ^˜ÿ½4ñ¢7&j¼3ñ_ðN/ô´©©!¬5µãj Ê .°…ÝîÎîìî|œ™× Y²Vê›<™“É™ó;ïyŸ÷ pt°1ç¿}<00 )Šòh:>Ù××—äœóB¡àd³ÙÂÚÚÚf¡P¨þ/€®ë|||<122òlÿë#±XìƘä8N¹X,.æóù› ?MMMýADáQy ËìâÅ‹“ÃÃÃïž;wîìÉ“'¡ª*cð}›››/g2™Wc_!>Ÿžž^@‡¤Ö NýèÒ¥Kc©T žçÁu]¸® !‰³,«KÓ´ÇK¥íììdlÛv0I’ØøøøÐààà;“““<ÏC±X„mÛ¨Õjû²mB˜¦™4M3žÉd6¶··—pÄ9×ÆÆÆ†‡††^€r¹ ÇqÐh4P¯×Ñh4öeÛ6ˆÝÝÝýgÏž½@=²–e%5M{¬§§§›ˆ IdYcÿ4sÓ4ÃÃꪞð}ÿC±XL0 CRº®ƒ1öˆ iH±XÌÔ4-µ`8 à2A2ÆÎ9†ÁˆèÀÝ· ªªBAa !„CšQ •Ëåf÷Çq,ËŠê<¨ªŠr¥R_ߨØ‚ „¿Ìr`Opܶíf>Ÿ_Éår {ç ]×TÌ4Á8GåAI”sku&D´w4f!£("MÓDGG‡ÖÕÕ5bYVL–åýb·¤ª*""67QZ_㦞2ôòìâÒrA¤½—,ŸÏû©TÊæœÇ“Éd_<iš¶¿¸$Ið<ùÕ,ßøAvQyâÔ@牾¾¾ »³KÙÑÇÛêdEVWWjµºND’®kªïû¢Q¯‹jµêK¥òÊÝùÚÚÌ·¬ò÷j˜‡Â™202zB7Œþþ˜¾SÕí] \Aë¹\yvööo¿f2¹ÍÍüN.—»??geæûïçæ®_™Wæo¡Ë}Ð-‡žZßÙ _|á%‹¢ð)]¢lïñÄý»["jí¼íÉaôƒÞeÁèM!@èj= ®z,òÄ]Å‘×,å­SqýL(„BB÷蘷 M jµýѪ[!ª[u,O»m=ÒŠ@´'F¾¸ãØ’Äf¹Ä?Quù½Ó½‰g(ŠÝ®N-ëw_xíEn-ÒŠ¨ @ûFøK€GDÑÂvÍvüð–¤ð`·á§‰(¸“¯þtkµ”mø!=ÜÚì!µµ©5W 9cúpo⸄ánÍ«ØÍ  ø:–s$îV¢IEND®B`‚drpython-3.11.1/bitmaps/24/Select None.png0000644000175000017500000000052211150445515020743 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~üòIDATxœí•ÑÄ D'§+#B!¤Pˆébú0}ø¾v•S`AÙÍߎÄ2ódà«3³;?wš¿03–ei®RÊû€W"¢éÚnµVˆ ”r2UU¬ë:&Ø„BÀ¼÷À͵!@UŸ¦"b1F`ιφÞû&ðm€sÎXι ½ ¢æ8Ž]¨êuÀ1ÔÞŠ1^ˆÈÐ|&ìßÞõef€÷û¾7k¶mƒª"¥Ô­iv0{SfÂ>=ÌŒ”À9U}vóP­õßžˆ ¥Ô~£N¡tf}TιYBwðiÝþá|5Ô\çgÞ›ÅÆIEND®B`‚drpython-3.11.1/bitmaps/24/Python.png0000644000175000017500000000110111150445515020117 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øgAMA± üabKGDÿÿÿ ½§“ pHYs  ÒÝ~üÑIDATxœ¥•±NÃ0†?We`@¢êSU©êÄо™û LÀ€„Ýy€n °ñ0Ó…u`BU«n BLHÇ`Çv\§Ià—œØgû¿ûíÜò!¦ý *\Ds+¥ŠÖnD-<%NñGE¾M0ÔQ‡ D$µUrR·ä# ç&Râv»Íl6³N:¡ä‘Õm¯ãY`OwçÌ£Šª*X‡§†[P}C<6¶K„I± ç`úè£À–“"zwÉŠ;à&gÕaÄ–%.<#qÒŠ­ûØ{±8^7“œ‚t6$ží=븴öô€¡9ROuô‡c¾ ]>Ôõ54ÐØŠìx4ï}¤ïn*¿š¦8NÀC$òÔÁÅaæÓTöU#ò1¾€gà!?‡6]×Ú_p•Uל"ŽtmÂø­~±ó4æøgtIEND®B`‚drpython-3.11.1/bitmaps/24/Previous Document.png0000644000175000017500000000216111150445515022220 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ 0,% Ç9þIDATxœí•ÏoTUÇ?çÞûÞ›™NgZ(PZФ©b%1 âB]áÊ„½;Vþ$þ ,5q!&ŠòC C#ÖÆ„ÔN Í”v¦å½ùýîq1?ZIpãÆ“œ¼—›“û9ç|Ͻþ·ÿÚ YXX:4:77A€ª¾ÖF•JÅ?xð ®T*õÕÕU?Xw'OžŒ&''ç&&&ΕJ¥cÖZ^ ¢ªÉôôôwÙlöºªn”Ëå!Äœ?þÔÅ‹¯¬­­é¿µV«¥—/_Þ¾páÂ'SSS{† …‘ùùù·?~&—ËÇ1 ¨˜~QUàŸ+rÎ1;;›_\\|ïôéÓwËårÀEQ‰ÈhEQ³ÕFM€¦m¨o!ÝØÍÀ…àSDÓ—¬µXk%Š¢±b±õ—ʼnˆQÄb¬6“˜àñ"ÑÊ]‚Æ&¢ŠŠÐ)Ñš\ sðš)€ï¾Pµï=ÖZcŒ1€pbŒˆmlI¸ø%ùõ_ ÷¿™FGsqÎÓ-’¤A]{YwûÙ2}¥ýÔa–à?ÃeIEND®B`‚drpython-3.11.1/bitmaps/24/Find.png0000644000175000017500000000201011150445515017516 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  šœtIMEÕ-$,š•IDAT(ϵ–ML\UÇwÞÌ0†a:ÒÁ  k‘ÚPcš¦êÂÔ¨[¿¢‰¸4Æ ·]º¯]©aã¢ñsc `A„JB¤´ÆP™±Ã0 óf˜™÷Þ½.˜×‚Ôx““snòÞÿÿþçœ{ÏJ)þÏå®b`Xïî}|¸ãD§þ_ËKÆ­…ù«ê׫Æ=À«ï¿yùÊÙ‡u¯æª¢(§¯Æ¶„ëöU>øp<)„øR)¥œO Š{ûZ¯+ûÄšñb›'€Pp55@µO,«{@T#HྱªSäæecsÓ4Ñ4zSÓnŠvdiK’©‰D‚å»›¤³‘PŽXˆ¶‡:ˆ¶¶¡paIÈH ,¯¬06=቉t ƒi+¦î$ñßú™¾“òHo?¶„µÃÔÒ²ººÊÈ·£œ:÷¯ôFiôi;Ϥsíüø[’ÑÉ1‚Í1Z¢Ç÷¤ÈuP·LLLí9Ϲžc;àJA±dQ,–éŠ u>ÉìÔøv±9A­+r›9„ÛK$&pï€J&ë›%ÊÝ+ðû›¨TL2™Ì ½,Ã(*ùˆGªàŠbÉ$oT°í*’€`ƒFÚ P.—÷´ªkßv¬z!4 £,QJQ®Øl•­jªHJ°e*t .­¾‚Ú½RSÑ á6ó¬¤ LKbZηEÕ)R¹b+K 1T_AÙ[”`In z˜ÌòïŒ-æ0myÏ瘶b~µˆ+»€í@óøõŠœ2À²¡"¡bo“<=ô,ÖÆ_Ìݘfâfš…T™DÖdñn…™¥,s³“L}ÿ=«hÔ?ɦÜUP;öšÇËÅKÏóËõqfF¯j‰’WA‚dÒð5pF_£»ðÉ?.bû^þwY½Ó¥Ú&RU߉qá…Ëld7¸}ë&åJ ·ç8g‡.l ±îO¢‹9ºJ#Ì'r)QØÀyiÕÀk{árj9ÆéÁóHv•Ú ´Á7˜ÿ„ÓíK¼þ†Ü3™îŸòÃu¿‚ší€;IÉp© ØÇ:ó.³‰8¯] ¼ôÑ;ý¯: üNãßÍÜ^Ëèþû§•s/Æ9ÑTù¦·X¼ñyåí§–Bõ»¯”rÝ–“àÚ×#_|üCs,J<ÈÀWJá[Z/œùÁÎŽÀ@¶ üÂùÛ"„Ðïî)z°õÞ`¬3ÞÞÒ³¶nLþß#Œ‡~¶IEND®B`‚drpython-3.11.1/bitmaps/24/Undo.png0000644000175000017500000000120511150445515017550 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDeÍRŠ ¹ pHYs  ’ù¥tIMEÒlÇIDATxœå”¿kaÇ?g‹¼’Eš!BÀÁû\B‚K@q3´A1S+‰èæàà N…£]N»$Í`è&Nòv:\†b{%)¼w¹»Üå䢂ƒ_x¹÷yyÞï÷ùõü—5£sïùgUo÷ÔúF_‰šÑIóÕ¦½i*y¼»­¥9Ó0;À&åŠg¯–`dc#-€®;l=JÔÛ=U½{€'Ý×sEô¦©d¡â‘Æ1²¼Ì¤Lˆœ›nœñg\]ØŒ^ NÇNç 4LÅ•ê ±~°ßeçš6]~äžH¹ÄúF_MíåPà,I¾ÖW\ÒS öp‡-MÆÜÜaK#o*ÊÈxó!ôˆÄ¢o˜!ùÈBHé¥@_)­›Áy¤DgaѲd X-ˆ¹çAŽëg­wFr€‘íBáa–fÆ. 9€q ,B¾°À¢äK‹ˆ‹7w?©8/2‘Ão”HošJ.g¦é¯CÔŒäëþWø {…a•<IEND®B`‚drpython-3.11.1/bitmaps/24/Exit.png0000644000175000017500000000250611150445515017561 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDùC» pHYs  šœtIMEÕ 6Õ6Ò ÓIDAT(ÏÝ•KlTe†ŸsÎÌ93K‡ít:µ[ÂEP‹@¢+ F#KÑ…—°Ð˜‰1&ˆ‘è c"‚ÅÄ[BÀH„ h“j¹CoÃŒÐv.93çþ»LµŒ;ýÖÞçûóæ{_ø¯t·!fÁrfyrAv!+à¬Ç_„‘8íþhxC 1ùdÃÜYí“:欯GúÐý½ üzöj1—?¬ë•ýz6ƒ¸+àH6,ˆ¦ßn]¿nQsg§›¿˲ɜ=‡W(’¬¢–Šä{z¸|ò„ÛûãOÝ™£›øîUpÆë)ÇjBÁwæíؾtÊ ›”PÛ p=úN¦ï—ÆŠŒtšh$‚êWI6$äÉ¡PÓÀ`ÿœ’i]\ýßÞ Ð í‘æä{óßܾ´ùÙ瑵^¥‚—Ï3|þ­K–œ1ƒÑÓ§©ó«¸…Ž^¡Î ±FkÌ tM뇽¥éðGÃZׯ[œXÿA)&}ò$“¢QÓD8’ª¢X…¡!F²YêÇóHÃÌN5uä«Õg¶šV÷Ž›~ÈãL­ $O5¯[ç÷ÕÆ¨s±« )`àÌŒLY’'Ÿg(›%¼v-Cå2Æð0F©L[(,G5íqR·tÿذ¢aJÓýQ¯Œ(1ÐÕE¼½ikÖà—eŒtI$ÀA©©áÞ•+iÝ´‰kccØÅ®°iŽÇUxtÀÙu-M8Ÿ`ìý]Xeú… ¹vô(Á|žx"!±p˜ð… |öñŽ‚Ë–s­ÿ ÙÑëÄT?.´MxÒ‚ÎP7ÞÝM¤¥¯R¡tâÍmm(¦‰$lšÔ‡B”ÆÈf‰?¼”t>®ë¨ürò“]=ÛÁ±],£B¤© #“AÍçðò£H¥¢TÂÓud]Ç­VPŠcé45©B àØ>ÛÁw_ãY½¤Ñ‚H0Mähã\×=‰…Lî|/BVð/R0 ì@œ¤¦i"¹ P±llÈMxÐ;œ¾NbJ2~Ü«W-X@pú Š]#B¶u×W³ «£M›Fõûïql 5$c˜8py‚2¼Ô×_–‚¨©8ÕO?Á-äixíu‚÷ÍÅ5U<ÇO]K­ÛÞYâÆxŠ‚.•õœ¾žpÉ_@uµçÝ£…#‹Z’òØ™ŸÑÔ|+WRóàJÕ&œœJýªGIlÙŠoæL*û÷sþ£½DU…Œã‰‹Uó+ľö—°{ æÄêã<´lÑí·~ªƒ£4=ýþ—_Â’$(ÑZT¿{ÏzvïÆ(æðÍÏÚöÆ}pê¶iº$VÔF»V<¼pn@/P:{•º{¦}d5òÔ© K¸ƒäŽãj÷O¨¡„ÏÏ—¹Â…뎻E…#{Á½c\ï_–Ç'ÅvNoMu$CšL.‡W(ƒmá¹K€£È8>YË¿è• ƒ–½Uƒ¯ö‚y×ÂÙ’!Ióüšº1Ð:[êbµªÕóðl‡Šå0j\*Wr9Ç=¢»î~¿ù?®ÌW eÂc.´KwA² çÂ%¾ú>¼M“ýæw£V7^äx ·IEND®B`‚drpython-3.11.1/bitmaps/24/Close All Other Documents.png0000644000175000017500000000232711150445515023373 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ­#½uwIDATxœí”Kl”UÇ÷Þï1Óv¦3-mÇÖi,$•!!‚€‘‘/—Ëå‚ ŒUQÈf³²­­­¾¡¡aOCCÃþt:]ý4Æ¢(2ÍÍÍ·•Rg¥”#}}}¥GJÙl¶îèÑ£GÎ;7ïyžù·211aNœ8ñíáÇ_¤U¡©££#›Éd´··×DQD>Ÿÿ'¡#„Àh‚ªª*6lØðR±XÜœL&‡*Lmm­ëºnJ)% …Q=Ù¨ehßÇ„!²Pñ8„!„!®ëºBˆ„ëºnÅRJ¥”ÔZS*•Vt , îÞe~pâø8ºXDÅãIJYÒÛ·SÕÚŠÒJ!+E®8Àƒïûh­7nÛ““ÌvwS"žHP×Ô„r"Ï£06ÆøÀµ»v¡3¡G)Å£.², Û¶‘R¢µ&2!À¢W îYLwuQ¼vÚL†ôš5¸©¶ÑA@M:ÍÔÏ?3sö,~GzzZ(ÇA¾}òõÛ¶Ñ®g¿{óUŽ bÜ»…R eY$’)ò,\º„=5E²®åyø¹Þè(A.‡ Ò­­X¹¥‹ñzz Z#µúñg7Õ÷ï¨;¸nkf®çÎÌ0]÷¿æÃŽ38¡Ã½>Æ»pÚ–’7bŒcþ¢PJd,ÆlOFGÃþRéø—Æ|f½öÑ÷ZÓåüÞg^aß  ñÑF³-ÝAS*ý{ù|íwØ·oML@áØöãk@JÐÆÇIÌΪx6µ@Ò:°ûå}7~»ŒHéé$2aY‰£b¤ê’týršµóóÄ|õàfaƒe,e ¨|ž¤Ö¢3°ŒÒçe½.Rº±¬,oJÌ9÷83ûo†u$;`nòy„”P´(B-už¸ Ö¤?ŽS Î%1‰…]þd"|B4‘-Þ¼sîéÀÀÂéˆZZƒYãí—ºç¶ Ùg®•Ǥä£cªÌoWœˆ= ÞŒcÆT¹ÅbéºfYUŠì‹ìæKtÃÍc÷º`[¦Mý`ÌV3# -«~F”RPJ!Q榩Ut~½^ƒ·ƒuUòr:¨ªªzàbœúÃeWŽ~êzV6ø®hÀ!%/ ‘úÇ«•¡4‘ʃ:ÍÌUÏè¬Þðôòs,M‘ZWáûÙì%¾ÑNQÝa†¿ÅMÂÓ)^…„Ç…¦ÒîÀYcR.Ôé OjüI_W˜ø1+ ˆÚAà/}2!ÛÖ‚¶[Z@ÄÙÒ…OypÓsWº@Ôß Ïàpp£#èKádþ…@¡ &3 wqÆo[»GX+ b¯’¸97?çý…©KþUrG{qÍâ §ölöpnÿFa…“§˜Ãø‡/úÛ9Žf#Os¤£õ¼¸ýÆwè±Í‰o„€qAÐD|6™a2™À0ŒÀ‘†ch.u6Š< MðñC¯·ÀʲkR2ùšþFÙ_NZXÖ;jgŸIEND®B`‚drpython-3.11.1/bitmaps/24/Save Prompt Output To File.png0000644000175000017500000000216311150445515023473 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  @¾áAtIMEÕé8IDAT(Ï­–]ˆUUÇûœ{ïܹ~ÎL3:ꨃ8£ISS=D„!Fö áCBF=Õ‹!ÔS† ¤C=$=1&“`¢`åjæ¨0ã4sgîǹ瞳÷Z=œ{ýbt†pÁá,6ìõÛkïÿZ{7|XK#ç9wâ8C#ùc;¿<ý,÷ÑŒûñ- %Ëh)ÍõñÂùÁègÇÎ8:µå~Ä4…Sê¯è!Ýõ RqŒNDœ)rêR+ã…%ëŸ$•‡*(  ¢ò® šDIÆ•ü¿y|O.‘µ´76ºSæðv_;[ g™Á4¯Â|^1~eŒ¡K“<´õâL™Vãçšp N`1¨ª‚ª"5Ÿ[|UÅÿfX_-„ƶdY0ŸféõAttˆìS¯ÐÕ¹œðÜ1Îþú=~®‰†æ¬—Á Hiœ(ޱ±Å:‡¸$`’”AU @Cü]àíߨnØ·) åÁ†åIúnó¼L;ÓÃg:6a»¶`Mš¾Oq*Xu8qXœ:¬:ªQÄ£-«ÙñÄs¤^xþÒ íËBïÁ47©)–ÿ´‡‰üZr_ÆŒýÍ”9A¼æiº{º âÀV)GÊ6¤b«T£ ù|‰ “וP·¶%óÚß‘?BïÁ}|µ­™ÖŽ•È…XÔZ!W qÖÌ lHW)Û° )Å&Ã"K]*z;ÀóRdÓÚ¶‚¯þSøøíí,¾:ʃm%š²—YØbøz?í»w%RŽ+¶J‡LUK¢2ÆoCõ@Ý|ß§³{NàÝOa äÒ>Å(´Tb~†j€*¥¨B`C QÀxe §‚çù¨¸™ XV`]O/NßJ"ÑœBpéä-*Eùj‘BTFTj:âîD. V^×RŒ&ÃÓQÀTX$’©W^­ gx&~¿ü0x£jEoV°üO4þ9K—PôN/ƒgVñÛ‘¿î=ÓìhÆ âH¹z {–ésÌA¹¬ éím­¥›¬¨þÍTdæC^´È£¿%£cUâÈâœË ¾/8ç°Öòú™Yîcî­"€¾/&)—ÙmÛš¥k­7ç‹ •i˜y‹æjË®e¨÷Τ øÔ/‘ ¬î¼ûÍŽù>"IÿW¾çßrF‚s–°\üÿ€8ª&=_…Zÿ¯´æÏ Íù¤Òæ¶±}Ÿ'jRA@¸xæ/ôñ}El#uÀ€¸`o¹pæ=œ²~£ïÀ“㬅j`8ú³ÇÉÜM©z©Ç’Õ«bjcc ~ŠtÆ .ØëìôþËzéÅÖ›ïã‹eàÛþÝÿš ;1å˜%IEND®B`‚drpython-3.11.1/bitmaps/24/Print File.png0000644000175000017500000000253211150445515020603 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDùC» pHYs  šœtIMEÕ Ï4žçIDAT(Ï•–Ëo\õÇ?¿Ç¹óðŒ±glcìˆåP‡B¬¨Š…%H(R„xH‘@ˆE»a H쪲bUµ»ª 6‘aÁ?P ’ª(Rp¡ISâÇ™‰=/{<÷ñ;,îØØ®­Â•Ž~¯£óýžóûs®âïÍ7izú‘wK¥~DÖRªÑhº/¿¼ö»wÞyëÏiØÃJ¥¾¾“'›œ<¢÷žÈ.Û·«²²²Z:ÌΡ"ˆÈ~渮Ä8çÁýl­Jd<Þ’x¢ö*þT ¨˜Ë”Rãý|cL—Ùnƒ²Ëƒmö`Ì¡fÐm>ýôS* ƒ´Öf_Xâÿ¥4aØIŸ;wVÿ_Μ™ëwN†”2ã››õW”ÒúÇÐì¿ë†Õn·žO§ýoææN/)¥î.,\]ݸpáAÉç{ž›œ?}òä©¿œ=ûë'‡‡G±Öb´â½ùYº°F ‘Á¡v wç jëëmáüùÓƒJ§ÅÅÜ­¬žYXøèÅÅÅÏ^³ÃÃ#fgOÍŒEÎElµÛä†ÈYƒ´¥ ràB‘Aà³²²Šõ²T‚:ùt–ãÓ»yóÆ%[,fGFF<¥c Æh6šâÞQÖMíš!Ô;B-HŒ;±¢47Ê)ÕBønc•#ú~Ê¥²*ŠOØB¡øhook5Q$DAH}³ÃuéçßÅ\[ƒõ@p¢QŠn¨’q€nyv°ÉC=Îåf”bhhhܦRé>c Zk°.¦ÞŽùO#÷·áFM±Þ“­jï4ðY® S—$ŸRßÏäìúzË.-Ý¢\.’ÏgÈfSÜÙ´,ü=Ãzb•dËÅfûΟï&²ø‹ëÆ&kk-ÖÖZÊÆ±ëܽ[§R©áy½Å ÷¥²¼>S§§¨–ZÚ¡"r‰=«!ã EzÓ1=:à–kÿ\¡VÛ¤Ó ÐÚEQhE\5›MjmqÜZþžVƒ #(cÐÖ  ŠXÔN&(À(ADpaŒs1•ëŠf6O©4@.—é–×´ïyzÆ÷}œ‹¹zõ ?%•JíªE쪬ª[Îe»ç N‚ÇÏpñâ‹x^š(ŠÃNÅ*Å’1òL¡UN‡tÚ0::ÌåË—I§Ð»‚ìÌ“QvH\¹rßO‘Éxd³9šÍ:Î…ÿ²AÐù|k«Õ(Ç‹Qä37÷=öKNœ8Aƈqì’p8‡s‚sÛ{Ž8òù —.½„1†r¹ÏKQ­®lEQ¸h¦¦Žmø¾,—ËMã™ ÆÆ \îÇZ‹çyX›êŠ·kôºgJiúûûh·cø"Þ@ßÄÅ—¾*X)•T#¤Š±^›¤mÒšæb.sÉd.ÉÌœ¹uÎeûpN2W¥à‚ÃÞkïsþ­íu¶À±—_9w¸Èÿ´ÌF]/Ÿ8ª\xõø£=Ϫ՛@+õ ë>”ο­è:üùë8=æÃû{ƒý÷õ쥆 ¸kÏ Å멬.”@¶ö¥‹Ê<µÑ›Wèóf_†rë ̵(–† ’,Äi^˪³úÙ$‰Eü‘q¼÷·Q—¾ƒÄï(fCÀêºd._ÞQkPÖa%æ4”´ÇÍùÝ2ø xôYÔÎÝè;ó¿aE¯¡X9 ¡I æbpqFe,,~jÈ@ðnsšÇÉB:™é&¨††Ç+!°¹ º‰XÅÿþê £¿Ü&—œ~ñ-â.Õ…ÛíAÏÔGWÖ„@QÀ×Vi°H,É gߣkß>o;-Ûàq"®ºÑ, îÒ=H@¸@X¶?üÒ›;÷²­Õ‘·…EØ{[·`‰&`õÒã.ä Ç—ÐÞ1ôX†£‚eG" 8ÙŠÿ’¨+ EùöòH“8îÝrZ®Æÿ,Xfñ;íIEND®B`‚drpython-3.11.1/bitmaps/24/Indent.png0000644000175000017500000000273611150445515020076 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ­#½utIMEÒ}®kIDATxœ…–]hWÇÿ÷cg'³Ùìl6]í‡ký¨V)æ%YÚ—¾„B±}i}è‹Ð‡†&Ô¦¶’ _|ðABk¡Eìƒ/…R«¥Xj m‰¡d5š°n7›ÍÌܹ}˜Ùtµj/\fÎåòÿÝsî9g†àÉÃàÈpðx]X°  Àœy‚pÀ@Ç{%ÓÙdYÀ8ç÷‚ ˜WJýô(@À–ø´^µZí­V«ë’É$»ÿ¾×jµ‚z½îÏÌ̬ÔëuiŒá”R³,ëÆìììÝ'ÖÇâ«###îððp±R© zž'jµÚâµká”Ö?½R«Õ<Çq(¥RJ›s.ƒ °|ßgŽãüzåÊ•[<@ŒŽŽnصk× eYV«Õj7Ö7WV¶|ž÷ýËÙlVqÎ !œs"¥4ÍfÓnµZÉ\.÷ã… níŠùVÞèèè†}ûö=—ËåÒ”Rµ°°Ð8þüí¥¥%>;>Žžž—.÷÷÷³b±ÈJ¥ïïïg¥R‰W*•pûöí+„¡ƒ:Ý€2322âîÞ½{1Œ12==]»xñâR¡P ®ëvöâÄñqܹ3x¹P(p×uY>Ÿg®ë²B¡ÀضmÛüJ` †‡‡‹™L&Õn·W®^½:séÒ¥¿‹Å"q]— ¶˧€O>Çõ블Ïç¹ëº<ŸÏó|>ßq×uËccc)Ž(ÏYµZuÊå²{öìôÇqbãÆ@»M€¤žÞAŽ›¼xàÀæ×Œ1F)e¤”FÛ¶I"‘XϑٿIJ©`|bŒFî0å,!€Ž”Ïî\ƒ|uèЋ¯+¥ŒRÊA`„„1V ˆ*T;Žc-,,ÔH¤ü>@æãF9Æ{P1Dj`S 9sæç/Óé4K§Ó,“ɰT*Å2™L/ J5›MqqqL—@·˜Ô€ÒÙØüB9uêÊŽãðT*Õôtz‹n4ÞÜÜÜ2¥C„A’¨X‰m½w¯u“ã8LBPЍ¿ ^¯ûµZÍëlü¿“w¯Ýþ 8rl'N¼ñ–mÛÔ¶mfÛ6M&“Š#ꊽ333+ŽãÐ8Q]ŽOIF{cÁ½iÞÆÆ'qúôÛï(¥8¥”Zk„a¸Ì,[–•«×ë²\.38qlNN€Õ;À‘#“˜š:üžR*)¥ @km”R†RºÄõóg(¥0Æ$ç÷j©TêT(Ïår,›Íòt:ÍNžüîs…8D÷€&&qîÜ»ã”R‡s.´•Rš1Fây‹ð9ç÷„½žçÙB+¾ B@b£ó„äR$>5uø}B±,ËBc,I£AŒ1sCCCM AÌ3ÆÚA$…Ęè›bŒ‰ÎS86±sß !¨Ö:TJ ­µ6Æh)å/^¥”Oùƒ"‚ àFÃÒZ¯Å²3àÓ£Q¶(¥´”2B„aúa )¥PJi!ĵ;v4×0;;{7•JM7›Í!„‘R®ÍnÀÄÄ«o†a¨„J!ƒ ð}ßoù¾¿*„¾ï_¯T*¿ut×:$ÌÏÏ7wîܹ†áF<—ËéD"A9ç„sNöî­|M)í܇1Æ@k­co¤ïû?lÚ´iº[óܼysyÏž=·úúúˆeY™D"A‰¡”JéÚ]cˆ1Æh­âOÏó¾Ýºukía½ÇýUÆÆÆR}}}ë³Ùl!“Éôf2™žN…&‰eJécìÖÐÐPóqÿ10Õ”ô¦IEND®B`‚drpython-3.11.1/bitmaps/24/Expand All.png0000644000175000017500000000044711150445515020562 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~üÇIDATxœc`ê€ÆhZ÷ø?5 ® ’ed````¢¦¡Ø ± ?¾yÎðøÖYY5c~IêZðøÖY†U=™ a%ÓøE|ˆÒGó µ€ ÀˆdäÔ‚ žÜ<‡• °¥. S .plól†Í˜âØRýƒHV͘!¬d:†Â'7ÏA\ÎÀÀ`å›Ê £n„¡FV͘°ü"’¸34XdÔt¬F3ÚP±€èÒ9uaK-[€7uá4¢¡Lv1Ñ™ÀûIEND®B`‚drpython-3.11.1/bitmaps/24/Toggle Prompt.png0000644000175000017500000000167611150445515021342 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDùC» pHYs  šœtIMEÔ+)pþa8KIDATxÚÕ–OkUÆgîMblš&6±õM Ò@«X³ â"tQP².‚àF¿BW…Vü¥Ÿ nŠ«.‹ ‹µ(¥b¯`Rcæ&÷Þù?ó¾.Ι3sSÄlºðÀeÞûœá}ÎyÎ{žwŒªò,GÀ3]€K—>ûôø ‹+ŠÛºHEqPÿlvmcûN=Êþ`?¼rõÚå.À… ››kkï¾§*¨ªŠª "–ÄŪn®×8­XUùñ§¶K`A!ÜÝ%ŠbŒcì `ŒÓŠÞ`5n<©ˆ/‘Š‚(_ݽÍÖÎï,ÎÍSŠPiE%B‰{ªÃT(µ¢’Êc¥VdyΛǗ¸¸¶Ú&PAT(¥býì9Þ~}•Qž—)q‘2*ê8³q‘—Qž•)I™‘å ýþˆ_ÂmD{NÕÛê¬FI«œ¨H‰Š„È%Š‹tü爣úY$ŒŠ„0’W%*ŠºJŒ1pŒ– Y}M¹„MœØ9‡íe#y„éõ‚Ç%R%q24Õ²$ÄeÖà­xÇì${T*A• uuëZVµµœ–Dq™‘”™Oî婉ó˜~6dGˆŠ¯.—ïé`”´Êx®3Á|BeÊ0 ÓûyÌ^:$—»xžààQevr†•¹WéªáûílþäI:‚̯ô߇º‹'Õ·Ǧf؉ú\»w“[[ßðÒ‘μ¸ÂDÐ=DòÆ>ÄIÔMTHÊœ[½;$yÌæé ŽÍÎÓë?f}á >_ÿ„¥é…Cˆ÷«À–(…üÜÿ/î}Ébg†·æ–yyf‘SGOp¿wŸp"9Ö«Dxú1¬ÎŸâ£3°;Øåá_=Ž™åò××y”ý “ÿI`Œiª²íE"‚1p÷ÉC^ëä×?ÑËC´1Ap¨äÝÉ©Z"=°eyþ'<Ïo¿”WtšVâÛE ‚NÝ™äìÒrmçf¬LQáüésœ_}Ç—-ÖSmzDíû¨¢:A‡¶ŸUUI ì@¬ûyËP×<ÚøX3R±þå›‘Ž¿ãúQU>¾øþ•©©é  tüÊøvYWÛjÝ.Ä£áðñ›·?4ÿû¯Š6Ž^•“/eFIEND®B`‚drpython-3.11.1/bitmaps/24/View WxWidgets Docs.png0000644000175000017500000000232011150445515022333 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs¸¸jAõ[tIMEÔ4:ZШA]IDATxÚ¥•[lUdz³¥ÛíZH/Ò–6–ÐÖÄ[¹$"7BÒˆFñÅŸL41>ÔH¢ ‰ßÐ4ˆHp3¡ˆX„%mÅ®°miéÞfggçræø°]v¶ëzý’™óe2ùÿÏùþÿï;Š”’ùñÊ«ïhoo:ÔÐP €÷—|šÿ&„KøZ$œÑ3¯Y¦uæðá·\/–Ÿ2±iãj֮鯓2îzW ÃbßÞ¯{­Zkßo‘ÈpÙ‹ã+GàJpóë\.ò¹›Ï“´.]ÄK/?»²½­í@(4øp(4¨þ-”µ!: –S+!“ (°xY;·Ý×ÕÙñðPY‚£ç¥RSW¼õq),¹:&9{A2ü d³žråK8Bɘ,l °õ™õ«›? …W(óEÞRÖ«hðK( ™4ĦazÚâæìYŒôèbZŸ:E:žE¸à €­Ù\ v•ˆüSÛ¥Ú¶YºÀ¦ëQïGÇŸ‰ð>Û õü~¶¿° ý6„‡O°vã&"Ã)®…GšÎ'åàš6ZÚà¦nr+¡per 39Žßšº«…—ĕઠªIňUEÈÑÑþwW޾sg2‹K‘M¦˜ŽÍ`e¦PŒ(®6Qp•ÇeR‚Páþ¾çI™…^ðËóç«€ÅÀeEEÚnNÇ*QdËÈâjq|©ÕÄq‰¢{sÕ„s§°.ô"Å62òÀ1AñQOòˆ=ÃÕdx6€£ORíÞ¦ÒùºÚ‘‚]=B»€SíËÚPçùÒ/Nœ@ú|¸ÈŽN’ºFíåo1‹Á.Ô…}ÔùG¸§yŒ¶Ž$ŸœÞE_÷–·öÙUq¡µc#³Æ¼™š†ë8XÑ(ââE~㺑¦fo =[tßù‚:{%ÈlÌäèð—,¬~®–þ"‘NßË–o0ëað[Ù,±±³&Ò²¶À§¨Le&ˆNÎP£Ô³¤Feò×$7ž 1®c¬7Í•Ê@ßc˜?:ýÂ04Û¶¯˜†q¯0ÍŠ)Ç&&vFbÅtk–[±± ×Gó!LJ´PM0¥Ä2Å%ò5 k¹ti•¡ëo[ŽsfŸi/é:¢V¶b¦ÀÔÀHœ4 „®U°jÞI¸0üãAªŠOpWóÞHä=`Àþ–Í»? Ôv£f«±S Ò¹ÇIC•[JeÉØ¶ƒðäSÏåÈÊëÞHäÖžŒ6°{å~öõñhóvüFÍÁå¬`;§M³eÃÎ\sÍí^Hðë06’$‘碲ãh«ëáÍuŸòxË·ÔÒDoÏš’1áµêð–¯é%þ<@}=›  ¥à.`×ÂÓ¯£ ŠŽP–@è`Ç §ÉOu9÷R<ÿª2Wë ½)sM÷—©DJ?öÕw·O?§òB ý§N>B¡ÁN ƒâÍþÛ˜.K0GüŸüªûFèÝIEND®B`‚drpython-3.11.1/bitmaps/24/Print Setup.png0000644000175000017500000000325411150445515021026 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDùC» pHYs  šœtIMEÕ-¹$F½9IDAT(Ïu–[lTÇÆsæœõÞ¼»^¯ÁØÆÆÛÁ8.à­„±CÂEÍCoIU¤¨RUõ©jßR)yªB¥$JµU¢$"(Ri%JHÓjHH¸Ô`›Kc fíÅö.llïýzÎô›@jFú4ÿýg¾OsûFðò⋯|¿½½õõ@ Ò¥Î"‘HZçÏ_þÝîÝ¿}o¡ = J·Ûµzzz&pñâÅ^ øý]]k𛵇¨û““155 <¹ @$É_»vå¨YJ½;591ÙÞÜRYéÛËe+V4)ùÖÚ[÷J).]ºúU±˜<1:zS-H0_š››™L*911VÖÚúèFÓ4e6› ¡¡vÁÉÒiK œ«š˜ÅjjªµÆÆe"Kß;ÈÛ·o§P(4ºÝå?lnnyª¾¾q‰ßï¯ …B5‹×âtè,_^ÍúõÁH‘©GŽôâ.wFc±X,¿3<<Ô›HÌî×ucXw»Ýí]]ötwoýnMMº®#5ÁÞ¿ ¯91L‰r5ü-íèR¢Jy¤Í†Ð³3%f²ŠmÛžX,4Ûbe™Ü¾ÝrìØçÏ÷õú¹Üºõé¶nÝöÓææ©T Pä²iÂñ-ÁÇHe’”Òit3éÙk7üXÆÄÖÔAÁp’ÊåðI“l®ÄØlͰQáònMŒÍj^¯g]mm­!„BJ‰aHŠ…<¦¯Žd™OÛò¥d•Ætá·^cE>Æàþ}ôÞ±qbÖÁM£!š„±t”L1GU Jx<Þ îñxñù<èºF©¤(ŠÄ3y®«JFï")¡Ä£,þü$›?ù;¶‹ŠÎN|Ù˾Ó!Š‹‘y/ß[œdy¹ƒ§\«Q(‚êêêeºÍVæ—R¢iÅb,“xÖ$”ppmnÌ Üc#ÒÃõµÏóu$„çê)™$¾Æ6>û4ëfNpãJ?¸üLESD"3d2"‘p\WÊŠ9¶:M“(e1ž JÐ$BJ4]"*¦O €ì¢g¸µwï…sؽåh(6<÷c´£Ÿq|ïÛ´<ûªjëç@+©ƒ9aÚj»ÝŽe™|ùe?}}'±ÙlsIjÎZ殦¥px}䦯 žE Í2éÚ±gùW:°—êß¼Œa‹ù;º I©vxì£ò GÏhÚÒ&œ»~)û>úè½ñÃ÷V܈CîW°6Æ×IEND®B`‚drpython-3.11.1/bitmaps/24/Cut.png0000644000175000017500000000251611150445515017404 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDùC» pHYs  šœtIMEÕ :¦zÛIDAT(Ï­•[lSÇ¿õœn§]ËzÊV ƒÝzÙÆÜXw)°(Ymt@ˆH" *1/3åI11}0GbŒ/ AÑhˆd¼à—»uݺÕZºíôzÚrh»³ÓÓsé9õIB¤$kðÿüO~ß÷ÏwAà)d·Û[¶lÁ].—A–å‚ÏçóF"‘‰'ùËX,–÷êëë-™LH’c±ØM·ÛM<É_VD/Ûl¶w8Žš¦!‘HÄ=ÏÐÂÂûԀݻwc}}}ïVWWMÓÀ²,,..Îx<]}cc£Ùápؼ^ïZF4=&“©3ŸÏÏóN§Áív_&"³}ûö†ææfWGG‡Çñf£ÑhH&“5óóó£ÿ.Œnii}¯ÍöB…R¹UÁóK#Áà/Ãp:Z§Ó¹§ªªj#ÏóËå €Ãáxsß¾}Ÿ×ÕÕµZ-pÅb²Ù¬8??erròÔ 0…B[û{zN<ã{4ÈÒ4 ¹\÷Q<ŽJRÑ‹}„rÜE–e!N‚ ÐÑÑÑ'Š"Ȳ ËËËP,!“Ɉ>Ÿï§±±±o=Oµ –ÝÝ_÷›ÍöKCC‰éBÝk³™ú׮퟊Åb“©±Û`Øj5222z½²Ù,` Ã<ŒeY™ ˆ¿‚Áàù©©© ^¯— m©¯ØÕÒÒ=6= _d2ûk õ6Šú¾aÍš'7oþÀ€a4 R¯ÚïŽã —ËJ¥’S©Tša˜ûápøÞøøøYŸÏ7JÓôNQ €]g4‚X,BϧÖI’©¬Tj•Jh`Y¸yïÞ²ìtæÍ8nloo‡P(ÄúýþÛ’$MÇãñÙ@ 0‰DB+++ô£Óô—eIØÖÙ ÇR©s›ªªcmmmš¢à2A,^¡é¯¬W¯µR”Ñ 0 ÞŸH&OÏùýà ÃV[JˆM£yP™Ï¿´ ÇÕ;ššê4šõáXŒ;53óëEž?Õn6ï8ît$˜M NN~6N¿ ‚/UñcÜÎå®Ûýa,•z]‡a›³EÜ$É룢xñ¶¶£û{{nÀ0ˆLÄã1Aþ€Üj÷§À¾n*1Ì3Ï"…B6 z»±ñÓÃNç1«Ñ¨Ah¤t’‘ˆtáîÝß~@Ñ÷g“ÉøjÉ0rBVþ„D¢PÈöhµ/žèëûÎf2UÞ¹q#séÖ­™e†-55ºJås ñxÒ#㫉¨ä5ݰ²âjíê‚û¡ü ^ý$xåüìì—¤ Ð QD1]³Ú;VP],V" S© ú:Uª·8ÞsœÚŸJ%î ÂH«Žè1i4ȶêê׌²³®níïïÒél¡p˜?IQ§ïär?®öÿ–¬om ±KK*YÌI’ÔÙ¬4MQá‹Éä¹k Å7<ÏÓeMQ)íÄ0m}MM‹Z’ ¼(*€”G|d>Ÿ-çIý•ñfy»\zIEND®B`‚drpython-3.11.1/bitmaps/24/View In Right Panel.png0000644000175000017500000000046111150445515022165 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs ?@"ÈtIMEÔ *tj¢2¾IDATxÚcüÿÿ?-Í-`Aæ¶P%¼Ö®¯aÄjÃôi5 ÿÿ3@0*ýî-Ccc ÃÚ Zœ†¯kÆí¨ABâ ÿþcâWÏ©ÿÿc7üß*EòZ[@~±+ú`€}ÀóiÏ÷Eùàï?úàï?Â>øÁ¡Dž`†ã³à‡Ç{¤ûÙp|à2{iÊÀÀðóÄ@X1Í€D“ ‘ëdZT8Œ£•>!]óîoÁ?ôIEND®B`‚drpython-3.11.1/bitmaps/24/Customize Shortcuts.png0000644000175000017500000000164111150445515022610 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  šœtIMEÕ9v­q.IDAT(ϵ–MkW†Ÿû1Òȱ"¹q‰ˆ 6¤ oºè*þ.t×BÿCMW…Pò ]Š -„vg)øƒD(²;’Fi4sn’•‘d¹q .œ;3œ÷œ÷=çÞÿÙTvspðÝ—¥Òú"’ÓZ9­'ªìR(µð\)å¢Zíï?^½úååuL{íoµÚ(eh6[DQŸJå!aØ%vvaŒ¹‘ ‡ï{~µZÙ{ñâ§ïÃðÝ@0(¼R.硵ÆZC½~J³Ù¤XÜàââ Æ[¶·w–(åPJ±ºZÀóì&°:羟CÄ1Æär——W ‡Êå++…¥b:çð[[Ÿ°µµ‰ÈˆR©ˆÖ*“Zèvc iênPJMZR³»[Ek…µ†ÃïH’”|>?Sé¼`­A$¡h¡k5…B~*œïçµ”û¬£TÁf5q“6L'Ù‰ÕSß9nôÇø”"Iñ<óѧÎ`)E ‡ÖcÜÝã*mvÓt  µû¸ÔP”$)Öš‘îRsŽ$I–QƒAŒçY|_ãÜݪÐZÑïÇ £åmÚj…œŸ·¨TÊÓ{àCÌ9ˆcáô´I§-¯@DÈçÏc8.ðy[ÿ¯­ùìímÇ· Z¯7äê*$z æIkE’AЧßQJ/8炵Zƒn7î¦A»Ýçää-a8@)·Eíãׯ/¾.7Íøò¸õú¾A‡”z½I»}!ApÙ’€““—?[ë=[[Û80Fç²Y¼¤ì~¾Ma4Š¥Ñ¨½i4Î: i=xP­£ŸŠ¤×ï²óç÷""Î?Í^¯û;ÐÜ¿´:u¶u¢ÇÓIEND®B`‚drpython-3.11.1/bitmaps/24/View In Left Panel.png0000644000175000017500000000045311150445515022003 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs ?@"ÈtIMEÔ Es+í¸IDATxÚcüÿÿ?-Í-`Aæ¶P%¼Ö®¯aÄjÃÚ Z¬šþp(1°ü¸Ç¼®™¡ob Ãÿÿ ÿ0芢Ü>ÀëÕ÷àl.a†ÿ1ñÏwTŠl†Ã0Í,øûD4±àï?ýŸ>€þï?ó6Ãqù€…\ Ð §ª°N³8@±€ÖŒú`Pú€¬|Àô™ñ?ÄuèÅ5:`D®“iQá0ŽVú„‰åæ]úIEND®B`‚drpython-3.11.1/bitmaps/24/Check Syntax.png0000644000175000017500000000255511150445515021140 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  šœtIMEÔ 3.P`P*úIDAT(Ï}–[l”ÕÇße¦Ó¹¶P`œ–¶ÔK)´œ£ƒ&æx šx*/èy: ÆøÀ‹Ñc|Ð󢯼ãƒ1Q"Å„œá$„ >(H!FMk[@ tZJ¯sùfæûöZ>Ì00½¸“/{íµ¿üÿ{ý÷^koKUøòÈ #"qTAU©Ú"Z/÷ßöÕǘ|÷í· €K­…£­û’m÷ì·‘0("UbU]ñˆ ª+çZ•kã¿~nYÖaU \€ÃƒGÓ‰LßÁ‡ûï{̱ PÖhZ†z/Z³|Ù[3þ¾çù –e ߎ ¢b¢­±p”/>Þ[b[î‚¿&kضŽ©j °íµÖé‹ÏéÙÓ|<úqãú•ÆV±ïnk|»p†s•SX!¿î]E–eಌÁ]\4ENÜ:ÎÅÒEîm}œIÿÿ8ûÑ­<˜ú+}ñ¿Ð›Úö§­AÑùÿ &Ìï $žgdÉ"æ>Éöν,%Z82†~þpM‰ŠÏ_¹u˜‚=Ç£©çørv˜‚] ìJ˜Zâi¼Âñ˜*°0 ^°’ÀØíçtþÇ+'ÉŚЪƒâ`ðý%#uý=S ã×€EWîAƒD;ãóLü–¯Òš‹¸SÀxc,ÌœGo^b ñªUÀ¯¯ ’-ݬ®FàäsK‘PóM÷·׸<]~–cóGÉÜkq9{‰ÎCô&ž#ÝÔA:ÒQ×ú¿3G¸Xø™wØé¨È2‚ÁÁÁÎþ¾¾;‘ø6OBxe%e:Ù“{™¡±S¨åóÆŽ7ë+œ,Lq9ƒ©ò©hŒžôf>üˆý™÷h µ¯ŒÀ²ÝÑDjowW—ŒGUr… ß_PrMV%8|ùsF*˜§H9d³®mâöñPG;'?å±ÈKt4ÝßHL¥^Œ'’n"ÖŒ¨²”/3·Xf]ëz‚ì{7íÃ7Õsrú(;vsûIÚ DCÜð|‚P»6%9yý?ü-º¿‘ ÌVÁA\¡B¾è#¢¸ŽCs¤‰f'EÅTåqFÈ`;9ÄõQ”|&mº¹¿­›o²_“f×ST.—~RãS*T‚;;CÑóŒÖOG¡\ÆóGiŽMб]ƒã ns‰³Åÿ16s“g[4ӥҝæçü¢Wj˜X˜Ÿ!‹`»¡:Áë=ï³i¶ë¿ qõêqÂÁ8qWˆéud vÇ^eChs£DCçü̶蜜žy-•l‰‰B¡èáx×g¿ÀžÀ8ˆå6³cÝ.¶·ìB²Þ >ûÝíS¬Ï p0ó^5Ù–WÓC‡Í^ŸÌ~’]ôoŽ„ˆ49´µµÒÞÕÉö éü1J¿|B¥”¯G" šÚqý‰¹­ìi}£¾j¢mééÉ—’¿ë¾>Œ€e;HPfîÊ›»l¼t”éÑ0Vï+¨®“ìnù'¬ßMÜY‡©¯H´Zo,,ñ c9µºbG±»ö12¡·2“Ǹ–íEÒOÖ žÚô2¢P‘;‘TÄ÷+ —þ-ÛÏùeìj¿kIXîºÌ}ÝFvtœVÍ3íÏB~Q­evõQP©öà/d¯ ÏjÝõlÙpu¦¸szrb½c©*Jí¥àÍ¡ùË|ܬòÒÐÛ¤ÆÈ¯Cߟ?wnXUs(2@‘©¤ IEND®B`‚drpython-3.11.1/bitmaps/24/View In Top Panel.png0000644000175000017500000000044311150445515021652 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs ?@"ÈtIMEÔ (¨R¡œ°IDATxÚcüÿÿ?-Í-`Aæ¶P%¼Ö®¯aÄjÃÚ ZŠ ^×<Ìâ`ÔÒ-øÃ¡D[ X~Ü£]FÃ–Ž©nAßÄ.a†ÿ±ã¿ÿpË1}f`h,oÁDÿÿ“gø¿ÿ½ãà?y†ÿûÑKØ2 'ÛÄN–H1—X°ùàç;„‹`š`4㈫`ô$uÿ‰I¦E-TÍŒ£•>!÷¿ÞúLyIEND®B`‚drpython-3.11.1/bitmaps/24/Side Panels.png0000644000175000017500000000125611150445515020740 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGD¹ÛÿHJäF pHYs ?@"ÈtIMEÒøŠ;IDATxœ¥–=haÆ×D[:ªE¢“àR‡ÐH)è ÎÑ`(nf±RAk‹IàJšŠƒ‚[Dt;Rtq"”HB³ÕEM1RÒ&--Iîî.¹|]òÀÃËýß»ç¹ç}ÿ÷! bj:†'\²¥¦áÚÕ+—Ht-ÒzMlÀ=V4§yry)„,£ûãÜý…ºÖ¤?b5e8v$Ù>·­išô"®`#ë¨ëÕ䲪½ ×$åZ€àÃP#Áû;ý'¨IÊ(«™×Þ‘p‹%²™@×– YˆàïH¸¿=Ћëèa颿[ ûE&m2ò]\hq‰=xÆg`¾¿ëOŸ…>Þý²è9P‚ùÆ´µíÄÍ{I+›Ýuu—äÆs`;A7â­º¨c‚nÅÛ&ÐZÊœÀޏ>;&Yˆ4 ~ ·VŠP-‚´ò° ®Ò-Ž8Ëp¤ G÷`p¯‘  š€î9py‚°f|Ÿ÷Šu\‡ßd€?ëAò™¨áä—ésf¨J´eê¬À`Xe1½*NMŦ¦¡´i¬9Têj¾u™ÄDã~7ü0'h†I¤Ó)M¡ýYüiþ0>OÛIEND®B`‚drpython-3.11.1/bitmaps/24/Find Previous.png0000644000175000017500000000176211150445515021330 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿBß ¯. pHYs  šœtIMEÕ/7ƒ¤ºIDAT(ϵ–Kl[E†¿ñ+~ÜÆy4¨U‚R@P¤€ª¦ª µB,‚@jÙ   X°É‚¤ìº‚ .`Q! †‚KJ…DMS*ä†bÇqý¨í{ï ‹ØÉuìZI#Í™«¹ÿÿsÎ̹5Äÿ9ë^ß=Z÷}œ ì iÿpq!š¹:7{š_¯e* àÙ×_<:2p—æ²ÛnÐ;º€©á8J¢d L ÿè)¾ñf$††RV‚‡ ºz:j ‹ªG=¡Vd X)Ö}»ÖêÂÔ÷^ 먫·py( xÙ—¥5 J†c»Àå!-à뾪—d gDl9™©ÔM´ÆÆY¬Š@ ‡ƒámUËw?h÷Óyg€¶ŽN6 ‰\å>ÛNËÑlêbüºÎ·?üÌÌÌ y ÄkˆSCB\81º‚çÞÍñ§úð‡ú8?6M,ÃÕ!ªPðÛ; N©-äò¹\®6þÐÃLŽGÖ’ÍB$Gæ‡õ‰Vnæ)M4—Àãi¤XÔI$õ`©e ,¼uƒÎÕÎYBàk°³¬{) U¥j«yxJ³vš$‘×Ò¨QIþ}}Ón@ né Íi‚Í^»L+,g—ßCOóçr=èA7™÷ru †,)P,¥ò¸o%ñîò£2u 0ÈÒûÂá¦Ak&±p™çS覬øÝTÌþ•ÖœCk `wº‘õ’¼”Ä¢„¢¹FòèàAŒÕLO]â•eæ– ,&uæÿ)2M2=9Æø¹ÏÙתaä2õC¤Ë åcowº8|ä ~¹aâüYü-m¤•Ëãu7p@‹Óý˜ØµÃ˜îgnO KwºTkDª47µ¶sèÉ£¬&Wùýê Å<ç Â×ègÅCÓtåÏ0»˜ÂGžlÍ$[.¬2xy-lü-»Ùßÿ’ ¥¦{ÿq.E>`ÿž(O7EêñD÷÷i¼_@ƶYAÙÖÁ-Ф¤ \*ðu1œ`r1ˆÁóG¼ÇÞ~¥÷…Ó}aUAäë‰ë'ã ÍcíP›;–´6kGS¤_b~ê“âËDý÷ö:Fò©nÃJpöË3Ÿ¾ûMS{”ØÉ «”Â]ÉÞ/Òý¡€·/™QñÛ"ÂvÀUnw;¯ö·‡‚{ZöÅW2cÿvã‘ѾãlIEND®B`‚drpython-3.11.1/bitmaps/24/Close All Documents.png0000644000175000017500000000205411150445515022326 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~üÌIDATxœí”Ïk\UÇ?çÞ÷c&É$ó¢3Rf‚–"$РT JUпÀeWnÜõpé¦{—‚ÿ@(¸i‹B¥¡N¥&…ŽMAÚØÒØ¦“ÌsÞ¼_÷º˜yiS´nÜxàòxó¾Ÿs¾÷Ü ÿÇrø¥Õj©z½>¶¸¸8Q¯×ÕK ‰¦)ëëëñÖÖVomm-MÓÔ:EB³ÙTsss¯ÔjµkµÚGAŒ¿Œ8@žçvvvö­õ²Rj½Ýn’šÍæôÅ‹?»|ùò~Çö߯öö¶½téÒ7.\xPNaÓÒÒR³Ñh||æÌ™‰<Ïéõzÿ¤tD ` "ÂØØ ïGQtvrr²SìÔÔ”ïû~Uk-ý~Ÿ<Ï_,ê8 ‚Il–!Žƒ.—!Ë Ëð}ß‘Šïû~¥”ÒZ+c ƒÁàD€8&Méol°çÑæ&&ŠÐå2¥f“àÜ9ÆZ-D) hQÅ&¬µ$I‚1樸ë’>yBwe…¨Ó¡\©0=3ƒö<ò8¦ÿè›kkL?i4D{žˆRr0EŽãàº.J)Œ1XkŸ‹kM†ì^»Ftû6SÁéÓøÕ*⺘4e"xººÊ³åe’¥%Ìî®hÏãàºîä¸çÊu oÝ"¼z•09?Žc’­-°DОGÐjñG»Íþ•+Äij1†¿tàyÞQ}­‡¾ß¸étpO"}øäÁƒ¡øsQ¥¥,ÃY]3”Ç­uZk\×Å÷ý#åyDØû÷q¶·!ωÓ\÷è5 ››Tº]]β™S0ù÷€R‰A·‹»¿MôÎ6 ‘rD†kÔIÞï£{=&‘ ¨7 r µ–b’"hkñ ¸i {{Ðë!JAqÐò=š<ðA{£“ @–eyEýn·Û;|”ï‹ Zû%¥\Ϙ¡3Æ ×áý=sÀˈdT˜j6›µjµºÁ¬1FÃÛTĪ,s>½{÷“·ÃðÝic&,/žAz>ÿ¾r†0xüøq7 ÃöÎÎŽ—e™[d­­Tþ]¦oójÞ’â§ÂnBûWøqö €I’$K’ÄHu,€¬À÷oBkª§áu9A\«ð __ƒŸÈõ±œVVXÚ…Ø…ß ìY¨ŒCàƒç lâ›Ð^/¯Ã·?ÀSÙáBŽT|ì»ÿ˜yæ_ƒ³c0ç@)…(‚‡÷à§+p·»Ä@rR§Ç£:#‹2”g!˜ƒ© ¸ûÞƒÝßáYÉÈâÈÿ€&Ô}¾ñ,…IEND®B`‚drpython-3.11.1/bitmaps/24/Last Document.png0000644000175000017500000000210411150445515021304 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ 0Žñú`ÑIDATxœí”KoUÇ÷Þ_qfœÚ )nZhD)}PuAD%„løݳë§è¾Ÿ¯€*u „ TQ -QiÝÒ”âįı=žÇ½,bGà&•ʆ éŒ4š£ÿïœ{îø_ÿµÄß_Nž<)ËåröÒ¥Kùr¹,_ËH¢(¢Z­ŽkµZÿáÇQEÆš&T*¹¼¼¼P*•>.•JŸxž—{s€$IÌÒÒÒs¥ÔWRÊêÚÚZpT©TŠ×¯_ÿâÖ­[½ñxlþ­vvvÌÍ›7o_»ví@ZÓcZ]]­,..~º²²’O’„~¿ÿʪ¥P(¡ÅCºÁÚ$̧=ܼËÅó? ‚àb¡Pøu 0óóóŽã8®RJ ‡C’$y¥ù ìó¨uŸ'„&BÁÊü»XÆuj.“Î8S€RJ¥”ÔZÁ‘%{AŸÛwø#¨²R:G!SD †>ÏÚèuÆfËo‰Ó!OcíõËÃDèë»w¹×ý†7Bæ4ììZi ÞOÚ?©§z³8òÚÙƒ[dY¶m#¥Dk1æåꥤ5Þæ‘—ßÍ:9©è¶ê„aŒ)éL ß­É`¡y.{%X&AŠÄsHÀ8àÍÌYÀ­­­D"‘4©•ݧ»ef` Ú•‰>àˆé®³ž7#U„âf˜ô*ÏŸ@ø„€œp¸¼ Ò¬e—(ËÚ1KHN–kevº„ŸQ ÓÀó {ó|ëƒ`Щt©'òAb«4ó,¶2º¤­³Œ]”>\}Gò=·ù€Îz‘ù)¤ Bð‘ÿsi—@îÈ pN„7͹Š(tuˆl’R÷Ý%0¶%Ý"}ÑXÚä^F]‚/1E¯Ù˜3ÐãX•…øªDF•-.A) Ý' à«Ù/v^‚X4ýêÝVèÍ¢6ùl¨nd|>sI@[UF¼33ç4-ÚÈ6mÁ°?D•é»Ýàtš~ke™‡ÝììØM læ#†ýNÕ¹·x†ÿ½ðª`þ<èYIEND®B`‚drpython-3.11.1/bitmaps/24/Open Imported Module.png0000644000175000017500000000115111150445515022516 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ 2.Øz?öIDATxÚµ•1oA…¿‰R $DIɲHg ›†Š†‚4ü À›" É¿H¤¬Cŵ.ÜÑP î8 ¤@×Ñ ÅKώݻ½ä‹‘VšÛÛyoÞÌÍ-üg“Kœ5W‰—+ÇpL OZ‚KKòËT¤UæÅ9Ót^Vìá… ‚tÜ®œë…£·1½§º»€eV%‘|x ÃjÚ•½Q‚œ—Äz´U‹Òï=ÖÑ}¥£f¥%A%8{«ªY}ŠZµ…²P%ɧ ½çËÁ˜ÒÜs“eGÒ¬ ÿ’Ð{¢áϹ®0Æ8’ÂwD?u}cØ\¢üSÂ|rÍ–hï|"R#ÉŽÄ5¾ÖäÓiÂÝ`è{Ÿ›îv»Ìf³š"G²1T\Až.³`ÓKi ¸µt9Ž*Še°æ+˜}H¸÷BÇ»Ö÷Ö+ 10y¤‚Ú×äYÂü¯÷æ[X¢À6m UÚìs ¾¾O¸ÿRÛjx 4<Œìm¹Y‘¨‚ÜUì³æ‡(:ï"`ûÀ¯²/ådiÓ$Wì»(nŸiÌ8³Ÿ±õå¦7åc/è°ën6üì|ð‡0Ùn÷·T‡Éصeêc˜FN,óI»Í|üm'hl×^gÖª«ªÓ⾞L`p£Þlúå]þqÒÜÒ#jÿIEND®B`‚drpython-3.11.1/bitmaps/24/Go To.png0000644000175000017500000000105411150445515017555 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs úG>tIMEÔ0(×J© ¹IDATxÚÕ–ËJÃP†¿9)j+ŠøâJ×^ZÝPÁ (ø(Ášw·ö| ¢T­M;.:)iMÓªuáÀÅ™33ÿ?—QUþR,…Ÿ^É;W£FöwOs9ºº>©ë)§Îs@D€ÄM šßEàEõ~F~È Pj¢ª·}ìË–¼#QÀûê6H±¥®ÔR)ÂÍ9ø!KÀ£iµp°wV sm4Ïó¶ ×ù0š¢I Æqÿªå„ónç®ÔaZÞ€:Ðü‚ ]ÔŽ~vN€d;ß<‡.ü•TªzÛ¥ªªt«]4~DU²Ì4 P`˜FzÕ@óÐ$œ'™§ÅÜù!sÀG‚L4i–å!p™¶`*goŠŠæ` Xå$ˆÀ,0Ñw’¹¼ *žçùÀ„©Z·8`2 ¸óCv€Wàxžždç6þUàÃú¼nÈjÆù˜}^€xInO´ˆ¸T &Ã$¶›Æìï@¬ªÍ/õêœ6kGàö6Í@PNmÉ_KÏ"ÿIf€œ É·œa# ù÷Ÿb"0ã^* IEND®B`‚drpython-3.11.1/bitmaps/24/Comment.png0000644000175000017500000000056211150445515020252 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ.¯·o“ÿIDATxÚÕT±ƒ0 |ç2YÁ5 Aaöƒ„= ð. f؃4„Óé0²IH.®0zI÷ÿjžgœy.8ù\C>Ê‹¡`–k嬮 ¶®ÀY­ŽN’çŽß|ECà¶\GguOàìm²è#°`ÚeëÜÕíÖÏŠÊ4/ ù€xZguù™žN öœÌô_Ò=KúÀxôo$yŠÌD£³z’Œ·»"ÖÕ«HEŠÔ»‰>¨¸\i5‚2Vñ¦–¦t´„t<²HI6u¦h™2G¯®”¤£¢=)Bç¿HÀò±ù2AP<ûò?*‹þ"MŸA*gÓCÅIEND®B`‚drpython-3.11.1/bitmaps/24/drpython.png0000644000175000017500000000163611150445515020522 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  šœtIMEÔ h–1§tEXtCommentCreated with The GIMPïd%nIDATxÚ–MHTQÇç5BN5)ø10 ÄáBKÈV„³jQË¢M¸(áÇ¢Ù(QÎNÈhÓ&W î¨6}‘.¤4$h4È G4pâ´x÷ͼ÷æMÓýï¼ûÎÿœsÏÿÞ'ªJ5P¸ ´ 7˜>b¯PÏΗ ¯ö³ûtXÓëU}ˆ´ äw"‚âJ˜‚æû^ _6“ÿeóùA~ÌŒhz±6€H»ÀŠª""øA┿ SйÝv–_Çør'­ÃóªZR¤2lŽ8v÷sõèIÖ‹}̼ã^ÊíÓòÔ;d0lG-"$ œŒœ rˆ'Ðï´ì{ÏéŸIŽËDÊ["Ssf€×WK®ùår—Ê‘&6þôðüE‚O7G4½2öîÀètÍ€t™¨³öâKZ‘É*§¢l^CˆDJk>§n9 d|¶”/K#_‰×ÿ¤ñÌ„Œ·Z@;Э€©*½¶{°CD¾Ñvü7õçBà€.ÛI(ÀYø4ûìÀråò bÑm"=–ah+E äôªW®drµœE±5)ü ©n—ðËôMÄq^M 8\.wS ÂGH‘ºˆåŽœ"5%‡ð~Ë•I§Í ÜQ×MéLdƒ [ ZK]X°I (Y—v–ÙÍ”Œ½ÆòÀz­È€®.ûùóŽo?ú]5kÚ°€U`¥ªã$ˆ©mc#:dÏõuNޤ=Þâþí»Œuù’ý¶ ‘$[|òšx<÷¿¿-qÿ†^6ÄZIEND®B`‚drpython-3.11.1/bitmaps/24/End.png0000644000175000017500000000053211150445515017353 0ustar dktrkranzdktrkranz‰PNG  IHDRoª¯bKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÕ"L—ÍçIDATxœí•MnÂ0…¿‰ T)ër9ŽGà\£âP•X$°@l3]ð+D§dѳ±5’?½çy–ÅÌ裲^(@<.³²5Mò«¨D¦Ûíô©:žL¬(ð8‘¯ùüJQûÍ&å¹ëÊ¢HJé „Ù®®S¿§ ìdf»å2Åè²DLõVÑa½ÖÌ7Äx¯³ýj¥".ÐkU¥Îp°ÎD€½¸ à›—ß5¨wI)Å)å‹$IV­µÿGô&‚'òl£jµZ¬V«G}ßÛÛÛQ§ÓIšÍf¼¼¼Üm6›†ˆ$ç\&I"”RwWVVž¿àX¾W«Õ§§§G*•Ê‘(ŠôÚÚÚÆÆÆÆÞÇ¿~òdþGarÎ9Œ1”Ò$I¢â8aþkqqññ›F|€ž™™;}úô¥”êt:»­V«s÷îÝn÷ÄDÑ_>èïï·RJƃ”’c¨ÝnNÇ/•J¿uëÖSà¯h> š™™;wîÜwK¥Òaι]__oݼyói·{bá—7ꀱ±1###bttT‹ÑÑQY©TÒ“'OvcS—/_}W”P­V“R2Î{9Î9c¨T*ÅqW,É<û#ìôôôH¡PèÛÝÝíÞ¿ÿÙíÛ·¿¯ý~îJ#ï/re¥R 9cŒˆàœ#c i­Çqyvvö?™ÏEµZ Ëåòà³gÏ6·¶¶: ­ññÚïæ®Ôñ­S@j÷ º¸ÿö ë_¼8vQk ˜çyÇ$²&¢óçÏcl·Ûæçç7ÆÇk˜»RÇw&3pãGÀŸ×A”5„uQÖ$Öë ‹E™$ i­™bH"ëP†¡Z__oÞ»wo³~|H]n Ždd©È&ß§P­ì‡J)Šã˜1ÆŠ2/´m·Ûq§Ó‰ºÝ sWêx÷ûûà½e¿þMû{/—/ CéyžB0!Ä¡ž‹\«ÕŠ=z´Ãù€×}•Ôí­5cÀ929Ñl6ãµµµhoïÏ®~ÑÀÓÿ¾9ëƒ^Ò‹ x"îû¾åȦ"–——»aòb±hŽ]ÿàg³ l=y=ký0mr;Ó=ü èßÙŸ€¾ïK¥WJ Ïóv$€¥T©Ùlšr¹,¤”Ìó<öÞ{øñl½q{n®5šeíÌ]k¼Ñž½PJ çYk‰s¾)‘ÍóosÎADcŒ„ŒsŽ ¾ñáÕ«ß|~½ 6ùòË>‚Àó}ßWJ…œsˆL’$»I’ð¼ÀLñ˜ˆ¥”/´ÖÅ(Š­µÊ Æ.]z÷'Ÿ_kÀl"{Î9ãœs!DÀcJ)bŒ !„ϳ`DôhjjªÍ I’U!Än’$¾ÖšeŠˆˆ>ùä?ýâZ£‡ç9眵6&¢TkÍs©µV;ç9cÌ?|šZkcÆØ¿c:IÙjµ”s=-­µôé§?¼ô‹ë™þù™3ƤZë4MÓ8MSmŒÑÖZ§µþÛ©S§Ú/ `eeåy__ßR»Ý>¤µ&cÌËÕ#ùì³ó— MS«µ¶Zk“$IÇq'Žã=­µ‰ãø•Jå~W¼ê€ÕÕÕöäääNš¦ãd©Tržçq)%“R2!{ÿý‰y–‰ò êòט8Žÿzüøñ¥W1_#€ìœ={öñÀÀSJ<Ïcžç±¼°¬g"bDDÎ9ÒZ?Œ¢èOk_Ç;è¯0;;Û700p¬¿¿¨P( …¡^‡zž·Ã9ßB<žššj„ñ?â žÚ]ì´IEND®B`‚drpython-3.11.1/bitmaps/24/Uppercase.png0000644000175000017500000000037311150445515020577 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~ü›IDATxœí•Û „ EOŒehX…Xˆ°…ìÖáâ~ˆÉH†!¸ñÇpÂk˜ óqF%ØŒv`Å™°»ûÆ}2ÇÞc¿”srÍÇþ |DYªjin/QhpÆÞpU@ZÁdœ÷b¬YJ–³Cz%Æ«ˆ)¾&eIDVv¿ Iâ-Æ^¢ô?dM®‡~ëÌÿ&oð0#<ÝåIEND®B`‚drpython-3.11.1/bitmaps/24/Preferences.png0000644000175000017500000000332111150445515021105 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  šœtIMEÕðÄ¥Ü^IDAT(ϵ•kL[çÇÿÇÇ>¾aƒmÀ6`nÁpJBÑ´nH¡]HI´lY”fí¶¬k¿MT«ºíÓ4iS«n½,Rº¶Ó´´R’^%isQ˜J œÆ@ @€`lãËûØ>—÷݇%RI´}Øÿã£WÏOzŸçÿ€ÿ³˜û mmm&θÕn/Ü¢å´úX<õû}£ããßÜ„Tú°÷¼Þ¶½íí¯·¶î:°mû¶ÝOÝ®ü|§—ak&#Üày^بááǵyy¹Üì쬼àõ~WÍqZ¬­­f;…­ÍÍ¥ååEj—Ë©¯«Ûê(.®hY[[«žž¼,ŠbòþÆ]]]Žƒí­­ÝöŽ(’Ω©‰áT*aà‰'¼¦ªªÚ# Ãöö~y5XœbTÚF{~¡Å`ÐìößH< Œ¿ xþùŸüþñÇ[^µÚŠÜ—.]Tüþ±aI’fX¨®ö4ttìÿæMUOƒËŸoä AHÎg2òöÂB—Õ`Ða‹Å¦šœ¼ióûÇú…,ßkÞÑÑÁy½»Ž•”VÛñÞ_ß¼FΫ ¨¨¬Æá(pVW»M ü–“cÍ»rå‹¿ÄùÍÍÍ{ÿþ=vBôz›7o)°Zsk——×;;Ÿ‘ÊË79\®²W¸ýÔ©ßÆ|3ÀÌ jÐh8ްТàÑG³I’ò+IQä*±åÛÚLF!*{onF¬Û]™ëv{~òºCï¾ûvßÈÈàÇ¢(¸ j‡!ž'ÓiÉÀ²*457[­Ö¼_¦¤Ä••Jýç»F(fXŽã8›Í¦.)©ø ÙwâÄS_ÝLQH7Y·¦ C‹%ÿ±ŠŠªbY–A)…Ýž¯ÍÎÎÑBYV +”*¨¬tëôcé#õõO[,ŽÝÇ¿Õ?0Ðó'Bè9IôÄbÑUJ1/¿àI›-cH’E‘A,ËH­%e6è×@£Ñäj8cÙï»644ð&!ô €ÔCF¡<›ÎdÒ:Já1›-z­V0*P¨0}æ$Ÿ ’eDD‰Äk³"#’t$¼Äóq?!”lèät:-MMMôù|CÃ~¿NOßTŽ ¯ö^í‹Yf&ržn÷2'OàåP¹½ÍM ¨ñl±²*]ƒ$I¡¥¥…qBÙ0*(¥r"‘˜››í½~ýڿƇ{òf'Õ{švîp”–ª´‹‹Xº|¹ÛwÀVZKŽEEÅQ"õáP`2ÜV¢l˜Ew‡”<¢Õ¦÷•—þà¹gt{<æHÿWˆôõAX¸ƒ¤Ý gÃw V©`µe£|SE¿š®][ã#‘ð-E!ä¡€Ÿ«XU«Ž«ljmùGûÑŸ>ët¹L+ÎáVw7ù\a¢ò³žöµÁlÃPXrL¨Ú\mÕ4)Š]º3CVòà@í0hyªíµ–£?k1€"öå{zèE^žN¤þnto¾å(*«°Z¬Z††¥f“.Wqv:­ìàùè\$ž‘eY^ø^–®agçž7š_zq'»Rñ=ÝHô÷à«0/œN“óó©Ôq!±zA’Ù&³Õãp84D! X\ Á`С¦¦Ú§ªÃ¡¥Ép84§€—Á€­iÞ÷ÌGM/þ¢L¾=ƒø¥sH âZ0.K’3·’Éwø§§§¤……Û¯„B¥/tÕm­5€(ʈÅP++Ak,­ÐË@#`¯ojøcK×/›™åE½Ý®öa,ËüMÀàpBø3€¡{­(JfqáöˆF­É1²«m6›V¯×be%†ÓŸä?ûäÃSÀÒg–Y8­ooyîÐK³É(ô\†<ÔÑÅéýé2ÇEJ.Xw. !IÊŒ%“kFƒÑ\˲:îìÙOùsgO_X˜ À8ðºAý£ñ=Máäѽt¾¾ˆžt’u:Ý?Á0OÝM·ŠÓhL-Þ]/ÿðàŸ³ à [8ú€}·IóJEÿýo¢p>© g¤÷ ß ° ÅqœQ­VoM¥R+”Ò9Ò:À äe±LÓe˜B'dÐéo?ü/¤ºkÒuiúo·.úp”T¦IEND®B`‚drpython-3.11.1/bitmaps/24/folder.png0000644000175000017500000000146711150445515020130 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  šœtIMEÔ822ùõ£ÄIDATxÚÕ–ÏkUGÇ?óró|I%1&Š­h ‚(A\dc¡K7B‘®ºè¢¿Ö¥]´ÿC]ê²t×.»pçR4Ùˆ`’Db06Ñüx/y¿î9çt1÷¾wM ‚=0ÌÌ9÷~¿ß9ç0÷:3ã}Z…÷lÿ‚à³ß–<3UûþÔØð9 ÔŒíýŒÅÍ¿üzáËAÜ™_ÿøjöä§7f&¯z)¼P­ÀÜÒ.w®üð÷ÏWî¼ó &Ôònb­ÍìÍà‰c£œ?=}û»ßWoSî63ÀÀŠu>—Ö^…¥{ fœ=f|~ê]HCÿùáJ•™§Q3TA1âÚJ#ß ý}PøSZGÌzä4ØÀ9‡sîHu1.9áCãÜÊ åqIžr*ªC5õÓñSÓ׫£#oÒàñÝÉï0£ÝnsyªCÅ9ž¼rlÖ;´WŸÞwÅoËÄ·s7k#µ¯“Šõ>&”îéÞÖ4ÅT‰×½Ñít87¡¼¨ ÍT AÐÝ— ÿz”X fE"IEND®B`‚drpython-3.11.1/bitmaps/24/back.png0000644000175000017500000000071411150445515017547 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDùC» pHYs  ­#½utIMEÔ {š>YIDATxÚíUËJÃ@=#¡ˆ —¢+q§~LæcÄA©vôWæO|ÐÄÖ×B„¢E¥ ŠI済¶æY¸ðÂ…IιwΙ;‚$êŒÔ@JÍÚª‚W"Ró`_ÕsDRjN^Š@JMoGaay:‘2à+ë@`±Æ(1öƒdjºn›Ýò5$‡oäà…¼¾ ¯ÎÉËÙí‘þÙ ÈÓ€<ê®Ûæ$Ž“WùêZ ²@L`v)é$´c ú\‡1Ðx*©ÁøÚfÙŸŒíÄ÷È~ÖÄÉ9²é™EjË£ÄnKãî&½ê¬N*ÙÔ%¶¶5·ãU¿÷èàp“sŸ{æ‡ß+oSc”RÓó‹IÕ€×ÔÕ.B–MGíê¤ß'ƒt+æeáM6F‰½¦Fô€¤…:f‘1J´šzüüQ‘¦I­ί9S"Äÿ£_I¦NáWÝIEND®B`‚drpython-3.11.1/bitmaps/24/Save As.png0000644000175000017500000000173511150445515020075 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  @¾áAtIMEÔ/%ß}ï/jIDATxœí“[h\U†¿}ΙKN“ILjL¦5Ôæb4BaÄ€ˆö¡­HÛZÅ|hðÁQ°R¨ ˆ¤Rèƒ-ú PP°Œ¨HÔÆ i©6—V­Æ€“Ä&Í$sÉœ}ña&™2‰©ôÑ6ë¬ûÿ×^ë_BŸ3ËS×™¾ÈèÔÂ`ÏG?=É„P_¿hÒ:HlÙÇì\üzE2öþàDœ[îÿˆ¿å»±_óè”"v3ÃØÔWnÔ2O³½íQœ`9Æ€Œ]ð]'G¯!¥êâ@'ðŽ8wÄ6M5Ðq¯@TïÄ~ä¬t†¹?g½1ÏC{ñü!üw߇í†P”©A™\Ì÷^ë#±”l?=6ÖÝuâ3`Ðþ|Ü<O Y¤bqa‘{f‡0±Q‚¥¹©ôÄ c?~‰í†T‡‘–T—¾ÆËxß¶µîµCÀ¤Ê_ëôžzÁ©}I Ú²MTûcùëY!Þ‡l>€¾|å&ÿšÓoô‘Jx ÆH0º×xú©×ñêYJh"gz¨.ƒ+= ßçæÂnÜ=Ï f~ã–ÆÛõx–8G®s¯0À¶P'¶½D|oå/œÂ‘×m˜çžÿ‚…¹ DΜàãÃÕÔ†w ùÊÚn*’’ôý{‹Z¥ti X–C°¬ŠÚºF>øeàí—ŽP5ãºeBÁ?¸+à0>åïúNzßìˋ䜴©À*lÛ¦©¥¥á•w?Ap}6ƒ0P“òH;x*?i(©PRÀRe/¶vDò$¹jÝ\î刕ÎîÆ¿¶¨µÞ%…ý^%V&¿h[°„ì0?|5´¶µÚä7XSœÛN8{3aù±ÄN.]˜Üèq"XނŔ뼌az å¶ >¿ØX ‘0\J‰”­³ö0Œ1%NþÿÕ«p¨«œªÍ*+-¢ÑÄfVð2¥4®«±mR )%Rfc6W(%éîë¸6tÀÙçI$²+zø`æÝÖÖúT€Û¿ñ¿@)]Ç·~€[ÁêûµJžLÄG^EÚZg?˜b~.…”°’ |oqÙ-°ª6h£‹,û`; qVÉ“@ÿZYÝ]'vûÿS™¥Ñ>zì×dVèsZvcIEND®B`‚drpython-3.11.1/bitmaps/24/Customize Pop Up Menu.png0000644000175000017500000000163411150445515022604 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  šœtIMEÕ"SI€)IDAT(ÏíUMoU=çγ=¶Ç ®bƒ R©Œ*–HlØÓ-‹ ñXó+ø¬Ê@ªR¤"*Á®E‰±Ò4\\׉cÇö¼y—ÅÌØã4J`‹¸ÒhôžÞ½ç¾sϽøß®0À;Ÿ3 Ïàœ‚ô " àA„ %Y"DTÞj6ßù®V{m€#EH@(â…Ïžín¬¯û¥¹{÷‹Z¹\ú¤X,\¨çÍÖ&û¢íö_Ë««ÍæÚZahg3ÎûÁƒSo8ì¿o––ª7×ÖÞûêöí[UãPåôpì8û«*Ö×¹Éd‚ã“cØÐBçh!F£‘DQä›|>ïU*¥røÅ(Š.åS5ÎÐ9 —Ïáùþ.|»ušI‚ N:GNU™L&zôgÇ™\ιLÆiöéM0 ¢ÀqßbõÇø°ô#`g~ñð2÷&=Q8‹`¼·O†F.F‚‡”0 ¶ì ŠÁ *ÕmÀfR@iàó@ãû6‚_åVé>œÆA²ÙÄ>3ÉPÕܧø}øžŒWŠ/!ÑXU© m„¡ïvѼp*…)HæFL– Á>ꯄ…›7`ÃùÚ‘‚ÂΠü£0:)~ŒAý3¨º„sf52K€T»Ýt„Ѱ‹0 35P‚ÈŽHRL¹\fµV—êò D.šçä¢Îd¬¦¼ ¿ ™ŠƒIHÁÎ΃ñxš0´ètºÚjí&78WعbOe‚ÞËîäÞ½¯¿Y\¬½˜I"ýz½Nïèhïcm¤¤§ ‹S§AfLñ\ù\A·¶ßôá¼F§æœ™ (syùš4Kpî²F›ïÕRÉ!€“$Ø…f¬uèv{úôé^ Û\|¥qz:Ðtl\f& ­F´P(BõÕ¹38S˜1y¨B¯×&JR¯×¼ë׸je-ŠqK_@zè÷ØÛ;8G/”h:ŸÎÎÆB U/OÊln>yÞjm~/¢ïª*SgAH™£ˆ¶Ûí>àúÿäE#€*€ò/^C`@ÿ¿ýèÿ Ko±n•IEND®B`‚drpython-3.11.1/bitmaps/24/bookmarks.png0000644000175000017500000000125511150445515020640 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDùC» pHYs úG>tIMEÔ "+ æs:IDATxÚµ–=hSQ†Ÿ“¤ZPAâÒAW1›u´Žw°ƒ "ˆÕèà(FAüE‡ÞÁA:HºœJ1kÁAº&ƒR:‚ B£ †ÔÜó:$'=÷Þ¤i‡ø¸ÜsÏùžï}¿ûg$1Ê‘(ÊE£‘¦g: Q,@p¿²kÈ0õÐrA(^_q‰ƒP,Õæ®Ëõ›¼ü²¹º Ó/±+d'Ãöú“VpþER.šöÔ#1žƒÈB67€OÀ¡ ÔñÞI¼¿þ®"ý©H’šÿ¤¦ô½.• H¥úº!ý¬K¿›R«­Þ˜-ÌkÓ;w{$‘ñ+—:Õ[Û= ÎÌu”œ~*"AÛEw¯Ú‹Wèõ1`+±Ze¾—4J„ðÏSÏALA" ¸Àj0 Š)H¡S},<«¢!€š{Ú|ÿÕµ)¦@ÝH¨p{’6ÅØ´ÿ=^ÅÉ€ôúþ=`÷=ðDÛ ðß)N%önY¿}A¨c+K`¾äÉ4ª1ÿÝ‘nîúÇW,—î𠼉¤Øú”EA(³²ckyL½š²ÈUé|X¼G­Ö`êÂ’ˆdz6 |Ù¡L¹h4=“§5YÁŽL=­k凌çàĹgìÉuæÚÖÍlß’J˳o³Û°¾|‹ƒûaâìc" k…U"ì^×¾’£GJ,ŸßÝàW£Í¥SÏáÇ“rƒ.lA®191 丼añíМP˜aå¢iY¼›OªõoËŠ(¨¿vIEND®B`‚drpython-3.11.1/bitmaps/24/Set Arguments.png0000644000175000017500000000146311150445515021332 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDùC» pHYs  šœtIMEÕ  5é3#ÀIDAT(Ïí”=K+[†×œŒ1’Bµˆƒ‰…¢0]D›¨ Uþ€–BD´D¬´T?°S$Æ"Dl,4m@;ÑÊÊQP¢ 1  f4óÜêÆ“ÑsàØ\î »Ùkïõðîµ×RäõC¾YÖÖÖDÓ4QUUt]—T*õi’\.'ÛÛÛùE÷÷÷(ŠÂÎΗ——LOOãñxøL†aðA**v3™ "Âòò2gggäóy à ›Í ±Ûí´´´J¥Ðu!| ˆÅbttt ª*.—‹ÕÕUÂá0H$¢(ŠÌÎÎJCCƒ$‰2§n·[&''% IWW—\\\ˆ×ë-ů®®$Êîî®$“I9??"˲hkkÃï÷“Éd¤¦¦†\.WrP,PU•“““R×ÿë X,255…ÏçÃãñ077÷þDÇÇÇ#@DˆÇãc@×u"‘777ÌÏÏ—Ùl–‰‰ X__§ººú‡©­­åññ€··7Z[[ ƒ€££#ÚÛÛ±Ùl ”Õ  áp8p:åþD‘H„x<Žiš$“ID„ÛÛÛ¯Ñï*‹ÑØØˆ¢(hšÆÊÊʧçÿŸE_êð󹕸Ø IEND®B`‚drpython-3.11.1/bitmaps/24/Reload File.png0000644000175000017500000000151711150445515020717 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øgAMA± üabKGDÿÿÿ ½§“ pHYs  ÒÝ~üßIDATxœÍ•[HTQ†¿Q˱йxɲȇ@ ­¤$°ˆB0J±¢2¢—¢ è"Ý|íN¢‡ JMÔŠ‚0±æ¡ˆ0t¨ ª‡Æš.¤SÓÅjjÎÞ=œ9zÎÌ™‚,öaíµ÷¿þuÙþ±X" åûåß^rõZuÔ=š$E敳vå,$ð[€” Â*õ+ê÷Ï¿Hc•—vš‚$˜Ó3lª¦Ûpfõîë6NŽtvgySh½ùÄ”¹)@H¨ªHP„Q··lâ²»‰(Be0£hÍ7N¹j¢Z)+\϶ң#ÎÁˆ  e…ëðøÜ4vž 3u³r0.m›KêT?íÑ‹@ßvR¶ÒZƒß¸öð®AÜ ôc¯E—”0šªEÇèèm5L®Ð ¥Ù/Í ß÷y8]úUÂÜÌR‚ºý°ƒ(ø382À=×}î¹î›áþŸò_s¯©ò~^äIEND®B`‚drpython-3.11.1/bitmaps/24/home.png0000644000175000017500000000131411150445515017574 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  d_‘tIMEÒ4THªYIDATxœ­•¿oÓ@Ç¿6‘ÚHø£*S¥"$+[¥´S b  $T¤tè` QYXèÌØ¥)ˆ (*˜„$P§IÓü°¿ wÎï9Oú(ν÷¾_ŸïÎvÂn³ÆÎZ‘°¼ÙwÌÜ‹‘[vUÞu]³°³V¤W¼Š02óp 7¤¨–äQ-ÏÓÛ0x ZžgºN5îæ=–jyŽÞ&€¡Æðžˆ\^¿KÓ¨–çè=V¢Ïî&&… ™öÑ5vû™ø%¿% Ð/A“ š¤_ùKˆÜÀÃâu ®ƒ?ž…_ùSòC‰'11ù.9/o.u­lqÙÄo¶¸eòEòYÔÞ_6 Z;üȯªiš¸er(ù(ztM4Ú!íPˆy$È·Lj’}Ñ›è*ñ’÷ÙâqlI&&ûŠÄY‰ IŽ#Á(‹19ÔŒ§›8~ ©M|uƒ¸rYîg}o›'ˆöøi¼½kœê“z'õ6––0h’çC²7${ÅÅˆì› É³ EG4ÉÅÅu&º…¼£Û+ÖË»ÇëxýæQnoÚ$£ÇÖS”·Ÿª?{«Ø½'êÍ:5&FS3ˆ˜Ý4-ÆI‘¶‘ј2ˆca)¾·j Y7C¡‘2p´wyDyW;$59CLŸA¢[¸ä:é‚d¦zM]3ÐË“ßD·àºê›c.²nr  ¿;Hd-r¢›^äèŸÉ&Çþš18WŽt1Ù©·BÀí[³lœ™ãù+q¤zëôêZñ¯ø|²Éž1IEND®B`‚drpython-3.11.1/bitmaps/24/Restore File From Backup.png0000644000175000017500000000325611150445515023210 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ #)…ì%;IDATxœ–ËGÇ?]ÝÕÓ³óî×Î>œ}ÚkgmÇv± NGø¸$åù8 NÈ'p@9 Ä-\A@+¶0~H(ƶüZÛ»¶wÖ³»ÞÝyìÎôLOOw‡u6 X’~ú•ªT¿Ç·êûû•Æÿ1„‰mÄÖ- šŽ¥|œ ÃJÏ¡¢|_uVûªÍ¾A†ãSŒ›i&L“a]#£ ^/¤êw)ûuæ6f™s×Xyž ã?d aÚ$»˜N¤ôSÙlþh:›™N&ûú­ˆŒ¡ižï+§ÝqõͧµõêíH¦õn•³Íyî»ë8¡zn=6H.>d¼š+e~4µgèè‹£ÍÉâ^ ©âV¡étýµÖS¯ÏrçɿԽGwÇw+çÚµð·Î’ºÜ|D=p ¿”чˆ ‘K Êï”v%zâÈ«Ão¼ôC& 3$£ta|)EˆëµYn”µK÷þÿ0ý›oÏÝ^š@ù§QêìÆj*@éÛxLMj¯wÆOŸC™iÆrû)ÚÃè ’¨MªçXÿ® -2ëÓƒýC¼²óM,#fОbþágôB¡m_(…R!OÛó´z5Þ9ð3úcƒÚqŠ ógè„uI«éX‰Q!ã a¨?ŸÍù&»Š‡ÑЈQ¾1öýÉ]Õ¢Ôè„õ-Q :jƒZ·Âõ•s\­| Àdî cùi¬Hf’b$EIˆ¹˜Õ—™*ÍDŽO¾EÌLm:’y‘ãcï`'Š(½‡Ò½-mx {(£G3\ãæÚ§„* ÏL1š›Á²1â†EZ„‚H­|@/l ë [æs¥ÀÐ-FR{04Ш»KÂ%è²éw© ¿Íªç¨ÅnK-wÂM›7 TMÓØ—?E>1‚.%Ú³èucKk&èI!±ƒƒÅ7Ð4A7hQnÝÂS-z-–º ž²¹¹À|¯Á-×ßgWXwËì±_ç•ÁïRLNbÈ(BŠg0 ¥˜äøàÛÌØ§x¸y•…ÖM:®x nmÌóHp«t3S$e2üºŠv­¨4™JÅ’ÑÄ×HD’ôhh.†4ˆ›6ã©—99ðÇ‹ï¡ “^ØáÌüifkW©>ì.7ø`ñç…ÎáÄ@í{-ÿšñÌ!f2ßB ‹c¹pÈ~“ªW¦4ˆéilsKOàmþVyŸ‹+gè´ª·ùËêu.†>õmz†M˦xLËnéîÆßé3¢˜"Š.Lâ†MÆ$ad1„„4¼%>©üŠþ§Ý¦|žóyÞ¯ßçvàâo;èµðu‹jèSö»jTÏ;CÚŸQiß g4‚@à†M–;³\­~ÄÇ‹¿äòÊG4,žç\í¿h–ùg«‚ó_MˆÜ^’©qÅŠ¼›áµìH²MçtÛÊ“’Y¤°pƒÞ:5wµÚš¿>ïTÖnðI³Ìï7¸V@¶:Úóš¾ÀÊL1nOsÄLq4šew_Z°b2!tÝð{~Ïmõ6z¸ÔYã¶»ÎåÕk\j=aÁ­ã~A–ÿñ«0,ìüKŒ¤'y!’¦¤[dÐÊÇó;ÔÝ*•ú=¯ÝdQÔŸgãßßÅ¡g—NTIEND®B`‚drpython-3.11.1/bitmaps/24/Paste.png0000644000175000017500000000176711150445515017734 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDùC» pHYs  šœtIMEÕ Cz¥Þ„IDAT(Ͻ”Oh\UÆç¾73™j*ùÛ´†Hÿ¤¶Uˆh±ŸеàÞUA‚ .ÝܹsãRé".¤Ñ…U H¥µ•D[ÄÄL&qf’Ìdæ½{Ž‹û&3;™®¼›ó¸Ü{¾ï|ß÷®ðë…«WNEÅÆ‰š­QN°“lÒÚmmèç•AwãAÞ~óåüÎSÇ?½ôôÌ«»T¬’–¨µªróö÷·&.¯¾¾ôÃVý‘tŽsšpÁ{hÄŠ~\Û8ݼüäk¯\:ŸKÕ£f ùÿùæúw§¸S÷D‰W°¿Í¯óóÃ'˜þÒÍŸ}†¨ÉyÖB)š!wê¾X»‡ ˆñ…4Úz~ꚎMsæ(x"¼ᯯWî³^=ùPÿØÐXtî(ÑÖm’f›2ÁÝ“°þû"ê ‘öI#Ê9Êçŵ2ïŽlS(ÑÉ‹”¾+CµDjiÂF3æ“Òû,Ù2wV–¨þTEIi ê@#¬!|VŽÕæïÍ^çøX‚WÓþˆ@ÎómmŽgßúˆwfÖù»ºŠ™õ4F3Á ÆÇǸõç87îqu¶†·CLöv$†Ñ‚1=:ÅôèTÏ3ЬàîozÖâDzÀõNÄ1ĹÐáÀ2OHKªÐò¡ªO‘‘³päzá¿ä‡!?…˜Q4÷XÒà5øcjÙ 0'¤XÛƒìRB{Ëz ô è)Òi’jómæ>Ë$Ú›“ Bÿ DÈG)¥Rcަ¶,Hä;“¤Þ ‚ry—ÉØƒÉ“MxéL……oðÕÊQLSP5L-«ôTö¶yc¾*¨; Šat–“\9m4üN–jz~m±ýï‚+0R¼HÒØDãÅþ{ÕÊvey!uù<¤FAÿ`[²jR ÙÕP£$–ìl–ë}ª¿Ô?\¾öë¬IÐ[¼I–uնцv¯™ùIŠl®éþÏõ/ÊC] •³IIEND®B`‚drpython-3.11.1/bitmaps/24/Lowercase.png0000644000175000017500000000033511150445515020572 0ustar dktrkranzdktrkranz‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  ÒÝ~ü}IDATxœc`d€U ÿ àPb c¢Q ±ãHl Y({5’øcj99¸È4¢Q †Çp¤6jY` ¥W£K ™ 8 °•EÈå ’8®T‡8N@Lq ¯B7ŒæAĈE 9ˆHÇžïœ ÑÍ$;‘aIEND®B`‚drpython-3.11.1/bitmaps/drpython.png0000644000175000017500000000243111150445515020267 0ustar dktrkranzdktrkranz‰PNG  IHDR szzôgAMA± üabKGDÿÿÿ ½§“ pHYs÷Nå©IDATxœ¥×hžÕÀñÏ“µšwš¬µÉÚ•%«¸œ³¥u]µ¥ýCû!Nü§2:&§¬sPX3¦”vàd7¶ÆAqÎÆd‘‚©]Õ0«Ig¥NêÞt mÒ¦­]›éLðìçyãûãÉ›7îÀá¹÷Ü{ÏýÞ_çÞ'ñH7:¦É‡á>ôšuÉ||4\9ˆ|™›]±Äy׸d‘©yÃÌÚñ0ÑÑѸ@D¦eÉ mv9V{36x9¼áÎ_'îÚ°!JÒÛÛˆ2¥V"®57˜D©õa¢‹(‹ÑÓÓ½½½ÑÝÝiµ’þ¡.D³Ë±ÖÑÆ ‚x•ØYrÞ–”:Œîî•´¬çcA4UŽc=~¿ÅCtvvŠahh¬Y³F’$&&&‹Å¬òì2©à>ïV‡+ *‚8WÊÄòŒæI’$‘$‰]»v'NèïïW(êOiÄ7üibæ˜1‚›»{ ×Tµ/K+k©Ÿ•kVýÚ»ç¹ÁŽ»1 ã·•¥âW$íÿþÌþÁv°³®«¢N_÷|üÙI™•xæ-ÜÓÐYÇûËl­hÆXݦ“ ƳÕlÂöR¢§sZŸÆm³x^;žÆ_êÀYË|[OÔ,Áj¼Žµõ–rÏœþç” K·Ä‚¼ß%=½/$œª*{y9¿þA–Ù']·rÙˆ×~Û2O÷eO+ïjRÁ”…’j€ÿâª`*aaù¼•¥ùCŸT;#»Ñ×_²çÙÔöj;¿«€ØìÅœÛ$Äx½V¦§ Šáá`™Þ^º#FB›°Ex^øfK5S_öRTlÂéì»—rFŸ'+Vl2r”öEeÆíز•¦aƃCýüíïfÞŸ©Z° PˆÚ8”'÷âÈ‘QŸ¹Šß}¡ªp®Ý”eZ¸ÐÅ-¥Â°ØªŽaRõEуC(EâöEÜÚRUq3ÀM}4=ÚÀV\±Àtm¨'Etc-î_E?K—¦e]Í|gEUƒH×C 1´…ëÓÜb§,q^SÒà³ì\™Ý’OaÕ|Ð3€¿oá4÷)®öïÆï‚;[Øñq:ΗO;í)& -Á& ì­ßùÀ%¶¿W2Šm5Ö6£ÈNA½e8ƒá¥ÈÖÚ{´ì¥£wǘžf:~Ÿ‰©mÓ<ù,m ßíæöÔ¼, gsÎÀ½}¢ÌðWúcº!¾ÑQœeÛ9OdßÕÒ[ónŒpõuË쳯ò=¨ ˹²œc«èy‡±u¸Ìö“³Ô}ïÝCßSkïu.ž<93ã5S_ ±‡ö«|ËôŽ*{¹ôaï÷™Ü‰',ôåþåK¦<ç¹Ùª!zñUÒWÐ\rgéÖqq ®Xïonñ’Çü¸¢ÏY7_9Ä+ØøEé¨ó@J×ó…¯0òh–¹ -Ú±ÙaëõC{æ÷«V~óý“xfaúŸP£Š™ž›iRp96:ûYÝ}ÕQ½ÍYþsZpE»3:]ïmŸujÎQÏkJò@nÓ§Ù¤f“Z]´ÌY;ý´a¿ÿðY!ÖÞÉ žIEND®B`‚drpython-3.11.1/bitmaps/drBeginner.png0000644000175000017500000001377411150445515020513 0ustar dktrkranzdktrkranz‰PNG  IHDR–21îµMgAMA±Ž|ûQ“ cHRMz%€ƒùÿ€èu0ê`:—o—©™Ô‡IDATxœb`˜%ßÀàé#s)ùeÚÆ)|‚GÑbõ_¾|ù rŠWØØ"«ÛƒKã?€™bËÎyG˰PA­÷ã;sêz{8€Â™´!QÌ À`†& ,о}“Ôø$ÍÃ÷TU»áÃ[Ó'÷³~þ”«õ<ô ©©å54“E$¶>{˜ ÌUÌ÷ €&c”ý§ºÎ&•=`“YÞ½r¦i( i@øJ'Høƒ˜¥€A ä²°°Ü½m¬oü(+ |šO0ýÅãO"ÿÿç†;<Êy’™Ä%ߨ¨½A3–™ù› Èþ7/ÂKNHFêЍjž¶°ÙÆÎñ¢þý‹?øpÔ¿£€ €T0Àˆ10d±dÛçN©ê231ýe57~ËU!±ïd¼}eÉIßa¨ËÒæ1VcEv¿|æ‰ùý; $ÿòÓßn^ϰšÏ/tŽéÞׯBü .r_[Úï5·ºŒ¦ò×/ï̘pVÙ£€ €pæB`ä1Á Œ22p12ð02ð22ðƒ˜ÍÍÈÀ)#úÇW LWƒ"ç†ï  RÔy4þð€" QÈÀ6@€Ù X ž8*êà‚VH2‚³¨èÏ¢òKW/‰êè edF6 ,/óßßÿ ¿$ç/¯ÀU2²™˜u«]HîD_>Ëÿø¦ÌÂ2…ø@ákÎ@2"0 r€$âÀXܶY) !AÌ Ž-6FFN.]}`þ2Ù@‚ H*û÷ŸáÃÿŸÿ~ügü¦¨øí?ƒÀÿÿÀü÷ã?0"ÿ¢Eäëçn@Gs!~€rÉ¢`ÏmfÃF¸ÿÄ1ß`3O#l9€w…zUŸ2³9÷P,ò°*9ͶŒ&¦'KJ²ii¦Š%›äŒ^g½´wYè|Kœ8@#¨z¨4&ùÆ ò xMýWô}»"…ð²\\\ȱ¸m³`bêK`ü1‚ÊINFF`%Œ6&F1Æ‚,oî3~ºÌøù6Ãÿ¿ÈfBë^VÿÚ…ÕþqJücxýÿÿ«ŒÀhþÄÀÌ—Àdñƒï^›üÿ'È8Ú%ˆØHÁ:àÉ€4î ŒH`´AjD`ŒB¢p÷v¡ÄÔ×àÂXZò1«=F ¦â,¯1½ÜÀðç+>k`|}”åõÑÿüZ%Íÿrò1üþŸñÃ[`»æÏ‹§NÀf0Ðv\"ŽLŽL@,Àþ8$1ÇÀeæ×/ªo—üø†GŽ©©©°[ZZlllˆóÝPÄωý»{ÇWIUÕÕk7/ßg¼ºÁ]=`›Øxaþ-Àrw)<ÿ=|Îpà,[7`h˜Å0¿ž!ÁÉÐ×Yž ý–Vaüÿ‘ñÃÿ_ Ã_ÜÆ€ÀŸ?\ïżyÌÉ‹¨`Íš5Èìa…Äìëë ‰Â/_¾|ýúõá¶#YX+(¡Ï0 ëbd`7aÄ™åYž`üþYZQŠáÂ-†¿ \`nf; Ì/Þ"”m<Èà`Œš¿=cà7øÏÊnš+Âß ²xùÌèê¹ÚÏM ÝGÌêðÅ‹ÀRÂöðð–e)@1‡„„@æÇ!3®à ÷_gO œ=-¢¢ú_à6]À^ #°•fþÌÀü|²0J€óó"/D2Ìoe¸Œ`††™kŠ?~aˆpCÖýŸñǧÿÂZÿ¾00»üðõ‹ÀÙã)ïF01ñCÉ(&Äk×®ñððÏ@eð8Æ_BBya4È@±@ºíf'dŶQo^ç,Ì6ðö{“ðˆ9+“:°Èb~ 0¿½D’}ÀìŒ`xì~À(°¿Ü;¼[ëÀñ—ÿÿ••ÿgcÏ('Þç¹rÁææ• /¾Þ¹³èZ` Œ*##£;wîcQEEeΜ9ÅÀ˜æE`¥iÔ ›T‡´t€º€l J`ôË[ LÇÃÕ@RD;´O iO@3a5vìØ1âZp²:—±p@ („,pb€µô +!@«.¾ÿY»RrÿÞœ¢‡æ–Ÿu10°ƒºƒ9?^!hxðÁö·G‘Ö‘‰ÀxEieå1uôB{ø¯_‰ÝñîܬY3€¹ ®fÑ¢EÀ ù àòH.X°Ê@6dÇ%$  ¬!R@.°r­9eÊ `NN²P=¼LšÓÑÑÑ@ÛÍ%`\"»h,PÄIp€f2Бð8f§¸ ö °/CÄÂÁÁ‚LJÀµlˆàûwŒuå궯³ ž ýŒe3‚&€8™¾%¦ñÖÀ湉ËÀÆV…jAB°) Œ?ðó—“Sø½xáËþM›ôïã†É3ØNuºwË‹‹„ÆÀý ôð 0r¹ž'€¡ƒÕ=Àð‚$s@ŽC„€qDÈXœæG¢4Gq ¿'–•ë¼þþ¿¦£÷+#ÔþYºèŸ²b¬Œ´©€÷¥K—àñ— ‘””HKx)!Y@ 4 8<u3Pp@Ñ BL£€"@-@r¦ËC9þ Q Éa àØê…ŽË‘ H9~@ÐÑ `lqqqñòò  ‰ŠŠŠ‰‰ ¹ÜÜÜÀHfÊßY{Ûeú:¥a‘™ñþ¾Nl¯›£f«»’ö|qèà'y6¸à‰ã.|úÑúÆ8€9" –BÈE¥ =`Å )fáæ 4£ &Ø€Zá‰é  ±¢¹„+@3¨"Èy xý™×… ‡2W:ÀW¤A+ÛØÄgÁáïø@ƒ6ÀN7Qk;¹ Ø‘g¤À¨Vx àj˜óöÏåH ûú6 òüÅC`"–|||pA`΃„ ¼Z"¦þǸšd«GΑÀzSÖlÇŽBR’¤R¶e 3õð©ÖïR³n‹ˆþ—¢ÿÀ=î?ÿÙ¸‰±CAÔ …`ý瘎¨g1¬ï²á !‹û¯¨Æ¿ÿ¯ÿ3|-;÷+¤eÉ(lvámmm§M›Q ¬9€©ðD=H:ïÈM¬R @Ð(D[O %Õ¼|Ÿc’N›½„iͼÿÿùŸ]„ +‘;ðÌìõÃc1.\AÊFëïÿ›ÿÿÿý‡èݳÄ$÷sÝ..//ïììd§eä–°LÃZrÒ x,K]*F& &xäâìçÈ0 d9=°-chz²²q3RüA0Lýgøþ•ƒdÇ+B8ÆÀ³),ØL&_ÁSù ø»tñ¿·Ë_`£¸yoK+fï?8¢4ÀÈ&v`-B^AJu€\"׋ °d‡ÖÓ  ò*lÈJC`ü#‹çvRæIé÷˜zþKQ`dü ,èþ ê0=Ç2»ôá 60Ÿ›¦ÈÕ°\…`.ÞÔy•GìwVþÿ~Nü{Ú$PüE…üݺ4©TYòûÔ‰W@†¯ŸQQaïàœc‚ô5!l`·Òâ…ô( `@LŸ@ŒÀ4‘翟?ߘÛìµ²Ã3eÁZ…Æ(ÂÌ ÀôW‘íÚ†¿?àr™ ‚#Ý à,x~)bŒØ©@ë{À¿0þôôA±ÅÇŠ2䦪ªÀÍ-Ì…À`Bk;¼¿È.Ü %-¤îDîuÅ5 80¸1ÕIL£€Å#P (ŽfÐÂØ@ËpÔoãr$Ö†.V@,qQxæ“>ïé·_ïœ;¨-,â¾ýcxÇÈ"øOÒ‘éÉv¸13 à’s~=Ê7+ÀÏ1aÉ4•ròŒËÖ2Aâ¢ã˜€ÝD¸ìíÛzÁôiA u (@“‚ô‘ƒY=V£ MJLsà%90MÙ˜ãhã8¸É@4 HþÆß¿ÿO<ü7ihÝ#F¸9óñã¿ÿ/ÿˆª°~3f|7{c††4|zõÕ 耉µ{zXFã«Å /:ø˜Pä@c¤ 8CV5}.ˆ‹‹Èèy`N®qmH¿S 8¶V%~qf&`z‚çxˆh]OÊÛ«ĸhÑ"`æûû÷¹–þ>F¦¯Àö蟿Aóôà妪˜øÞßÅæd蘻  ƒ,ƒëýƒŒÑ71‘™ÿ*…ýácú÷ÿþ?†çß¿}}úì?dé°²ƒ-´`üû—­¬èûŽ­ !›˜8٠ٯ_ÿ>{úóÙ³ï×®~Þ½:Xé “ï˜!ˆ² óË®}; Kî!=Š0ßBß+ À¾0Fû§>|ÿ…‘é·‚-ËS>¦7'Èq+ïyß¿¼Œÿþ?þÇðæÿÿ/¿~ÿénvýû±:2„{ýúõC‡A4™—üü*ÆÏÍ-ªÃfbÈàËtÿn*¤|£i#~°€b,Mãààr€aÄÅÅõœ!ë “ð-d_¿~…¬ÌA¡ïºïÿÿgÆß?`_‘ñïY].1¦§»[7Á~­?röÿXÞþûÿìëÿÿ½‡ï¼|¿míÞ¸¦ˆ¼Ò èTAAA¸ÆÊÊJmmm`¥&¾‹/‡< £—# '''dPyÀ¨‚d;HÌÁ!Â÷§ ’ÀÃû-h€†Ü×gjøóØÓgâOd~}ƒéÍ)ëúx”þJXþãåúÇð´””áíèRRPwÐÂæá—O¶ð¹xHv”””VÛûö&™Uøi0@6˜ÿ€íâ›sÃh¾2Ìœíà+!"üÇ^ŠJ†¦«ç{pìý/zæÃŒŒ¿€eàf¡’RŒ’‰L_>0}yÁøùÿߌߟ*66¡ÿ,Ü ’_ù¯Ø?Ö?À6íÿÿOþI†ÿÿCºó Ëò”¯KËpþþÅ‹¶^4%%%((èÌ™3=zýú5$Žyyy!sL#*ò €@ó…hëH‘㲎m@5À ²b(¨¥óIF²ƒ2Þö‹‘hÈ/Æï>3þÇÈÀû‡—‘G”QB޶§å?@YíÿÃÿÿ?ƒ—åþlÜ‚"ï'l5>下¿jšŸ> £­÷åççWRRB^GŠuáÌš#ĺš…µÂȃ7pœÝGAb<öýX~g`ø|ù²ˆ®Þ+vFÐü> rû”ÿAÛ'~\¿Â¤ªñŽ™ùXäææ&)ÙCï_‡1àXæ;ºšˆ… ïZÈ) ð}ô@Ì”LÌ¿œß¡*„d`´›øL³§I=Å×ÖûPWï7##dgÜ`4ƒFÉ?~d¬«ÔãÈÌ{ £÷ f àæ½ÃÃ÷ðÇ7e*yvx€"p\dîsðã €lSó×\ÜX–wþúÅ´q­ÒÚÀ¨²e›ŽÞëÿÿ™¡[!û ÿ—‹ÿ;rPØš}ô€·$WÃÉõuFÞc>>,‹Õ„Åö<}0…ø@áË‚h#àðÓK\=^a*¾vY¾§%xÿ.cVV^`á ììÝÅìwƒ·œë¹ïÿAMÍïà ˜çþœ?­ ¬Òøøø€-áCû%S¢·o‘Æ4VHt##öuˆ£ˆ¨(DŽ?a‘Ÿz‘•}|Ï·aUÈŽM±LŒ µÀŽ xê˜yËa¬&?¼§ÄĨ _ÛÁÃÃó÷/×ü™š5¥öî‰"«de{ÏËOÄëÄŒk,üÐÈêÇý `)êèúHÏð5DÍŸß,§OØÞÿë§ dU°â„¼ÀàÍ&¿ ·˜†_»è¬á€=øªÈj¯_¸ÎÒúõSLAù tm#ÓïohâûaˆÀéOðI|`¥ b`¾?ûÞmåSGþþQàÆP=0²!}`dI`Ü«º«—yµuQVIýùÍùñ½‹°ð?ÈžS¦`FŒËs§5_<5sö<¤¢šr>ÎÂòéÏ>,® „/ ‘‡I! hEå’R?â=²ßûÕss`ÈÏÇŒW ,$Ž!'!ãæË—/îÊîíRÚº7‘M~öØ•›‹Ÿ“ãP#|Í#5µó10îýb?y8üåSw}“<|wDö¿yáOûÐ’ €°G!Ú¡’À0…Ä“¥Íé3'l¯\ðä俆ìÛfAÈÁ4@áææF!P=äšóg%¿¿ÇɉX1üîµ0æ ÆdÁ*P#0ÖZ€†@µf~x§pöXœÒ~a±££Qˆ U„ÀŒ9ñÈFçíëÞÿÿ‰ ðƒöÝÃk2ø©¡•Äð²@=LXÎW´u‚.˜ùø^óçwe .øþoÈj9Hv„Ì“0€Ü!#y@ö«gžŸÞÙ+ÙÑó,±€"|â$Ç@úø,,¢°†1òÈ|?>PÁÀ¼l AbèÜi=xã® ¾x2‘4~"P’¿!±>Fo䎿àåÞp¶Ô}IEND®B`‚drpython-3.11.1/bitmaps/16/0000755000175000017500000000000011246265352016145 5ustar dktrkranzdktrkranzdrpython-3.11.1/bitmaps/16/Save All Documents.png0000644000175000017500000000114511150445515022160 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ# 9aÂòIDATxÚ‘»kTQ‡¿s_FÍcW‹àš`«Ä.¨‰…B Á"ˆ!…¢±ô´UH'ؤS° $v),+#Ò¹†n "ͺ{Ï93÷î#20ü΋ï73ÇŒ?|¦Á‘>NÅ¿>ƒ‡i2…ïV©|®Î£/g DQÏq‚b‰“G7»r‹ÁÍ5ËØØøÆÌý;×îMÏ‘‡¹1½¨A±¯Þƽ ”¶¹8„—ÌÕ)ˆäªà>.¯°^þ:ŒFMR”#>t‚ÁïŒ]½@êÁ ;Ô X_6yúäîÄõñÇs-@3¼BÝñO€W˜œ|®a\`_@ÃïxH%ß»¬Ãݧ±j0A Y6wl:€^Û†@%­ѼÜ<÷kAvR1te¥Pûë•M¬Ï&ïr€•ÌYl#{ÛXQº€ H¨V_¼FЦ殮ÑC$m@3ÒVWzéî. 9!í*µ e/ÀZ(b¦¦ú¨ÕRÂPCÁ9‡µ粜U¬Mˆö~cÈÖoÇÛå:ç†c._бÒT±VHSÃÒR{Š‘ßþîháÑmpóÖ‚v^&4ÿ4ÎþD¤Œ3kå˜FÝRY y£‘l^ïxrï×§/r€šn€´3ƒ¨Èf9Yñµ¹ùžÎ!>* ß¾üexùðƒ P÷÷ ·î¾b`dae”—fà•QVzûìµ÷7o÷103¿A¾ÿG  loIH>4Ýáö÷ìé[>øúú* 8'ÂÎéëî÷ %íàÞ-üïò°A¾ÿ6AF0\:1îïåçô3$ ¡¾ñНï [Cìðöîêê1<<RA¾ÿ j+1%ÿüòõüÁÕîËÚô êðúÕàõ3& ëëñûûýêkˆETZÔîüK^†Ÿ2hŠþ†'#ÃËïÜ ¯Ÿþdxÿå7'ÓwU1†w_þ0|øô¨, ?Êù•CDH €Xxù¸ù^~øÏpäì† 69!FdgùÍàgÌÂài,Å !ÄÎ0où#†—þþùÎðæý;®< ,œ\lA¾ÿÿýÿýø÷ú¢Â÷1 ,cHòöý„§ã—²íóöùõ÷òþüøý ÿýˆåÛÇÏ_øþÿæf`úÇðïß/†³w€ñ탈ÃçïlŠ®2Üyø•‘õ/PÃO`‚û ÆL@¯þùôå@1½úê8Ë¯Ï ÜL ÷10°^jZpð#ÃG_˜3ü´áÏo`Ä“PٯׯïÓ—wŸ¦}zpAZ” ˜ä€Š~maùÇào)Èà®ÏÅæ,LL¿!†ÿÊÿùÉÀÎÍËð÷Í'†ßÞÏ ¦ÿÿ½âü:þ_ÄĸŠ2°þÿÇ`­Ãà§ÀÉ`¦ÁÇÀJ÷@›~å8¹Ø¹¾ß¸yŽá߯UA¾ÿ EûûòôÌõéìF$ õñòÎÚóÑßø ³ÝôöóøÎÑæüìèZ݈™Ý èG¦÷?ß}ÚñéÑ3%~n5> !†ÿ3œ¸òáÏFN FnÆ·Àd~þâÉßožF5Ÿ†@12ˆ¶A2$Ãÿï?¹ÞçÈgÖfÆ3(š}úúû׫7÷þ~x3óÿ¿¿Ëþ¿cªa€KÌ¢Zt›ŽIEND®B`‚drpython-3.11.1/bitmaps/16/Customize ToolBar.png0000644000175000017500000000147011150445515022155 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<ÊIDATxÚbüÿÿ?% €˜(‚£€`(€¢·ú¼´j?F³ˆáø0†XAB…Ðâ™ûîX›Ö?ûöa |åHò›0Ö"¥bÅÏQ¡Žx%‚ª‡iù ·þ Ž?Úÿ|úÍøå#Ã?Æ Þÿcàæfb`ecføü™‘“ñ;3Ã÷Ÿ, ÌêXþž}*@,ÿ?ÿ—äúäßO†÷ÿ2ð³üb`bùÃð’ùƒÇ í^üùà *ô—¨ñÙ‡¿ â‚@6#ß¶ÄòW$—E.šáÿGAÆ· ¿¿20ü|Ç &ÿ‘è, ÁŸÄ¥>CØ?3H‰|‹1p}ºô@110C‚™‡á×ý 7{“ÿ¹²(ÉÌÀÈðñ/3þÒpþ& füÅðèb€bb`ü”üÀpßÂÿÑåç·ÞÚ¸æ3óKˆ-ÿ>mýÁÿ@4PìþóLÿýý‹ €˜˜@¦ÿg4¶dìH5Sq4ádøÅ ƒˆCèß`˜€–1~ºˆ™¾2üûý› €XþÞªYÎÀ§ÁÌàÒg/Æð è Í ¿€~ý Ôð¨øïO†ÿÅØ0üýö‹ €Xþ~=Çðôà†ïßñü—áǧ÷ Rò¿89õ1üâßHl£€öüš@,ÿýexrå+Ãß/ß~ýøÁÀTÉÂÎÀ ¯Tô ”Ô `¾B2€ÖÄòïËoFmv Kÿ]úœÚY˜¾?ºè‚¿þ“ÿ…²ÿ3üÿý hà× ÌÄh'ÇÕÏÌÁ²ï7#Pò?#ÃÿÀHbP>ûŒ*`:Ò€¡þuÿ€âÿ@c}õá@1RšˆâÜ`…+—€ó¶IEND®B`‚drpython-3.11.1/bitmaps/16/Save.png0000644000175000017500000000104711150445515017546 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ 1 Áôx'´IDATxœ¥‘;kTa†Ÿs˲ Ù5il"ØÄÎJ‚ì¯P¼ù)öwXì/°´Jk "Apm´ŒÉIrâ&~—™±ðì}ĆápxŸïøO%<ídŵ6z囨‚j£2@ʳ ¾ïîcfÝ +–ÚÅÛ-|d£ó ࢂWˆÕwPøÔûÌç/žô/.Vòñ8¸XeÔƒBª¼“N’äÒüŠc†±>ZãV»Æ"îêkw&7H5‚‚€uòÁ¿'ÉQb°Áöç†;˜š;Äê"s$IFšÝ`óÙÖðdZÒÆŒîÒȲeTÂ$À,¡,[¼{SN‡šP’æ4[uŠ)@ Ƈ^àþ½ë8'˜ ijˆªJŒúÞžrzY]³ƒÚBÂúz‹W¯Ïi63î®åEÄû€÷ž"ÛÛÂÖË‘'Žø³¯|Ù ìQlú÷ŒfÿªÀL9£^_cÎáAFQ1DBŒÄé÷…"w¨8̤¨ë÷msyIè½?æªï9>JÙÙIÈRCU‡urb4êÞ¦îíoz7?Ž©;IEND®B`‚drpython-3.11.1/bitmaps/16/Run.png0000644000175000017500000000060211150445515017410 0ustar dktrkranzdktrkranz‰PNG  IHDR‘h6bKGDÿÿÿ ½§“ pHYs  d_‘tIMEÕ"7žšŸ0IDATxœcüÿÿ? 0Êå200ü4™7`BæHhX:@´¥ÁËÍpçš"´ˆG÷;ƒ0ƒ0ÃïW÷OBW]ƒ” ÿW÷·´cQEƒ/Ó·÷çWbWÅW]:²q/žËHjòòon¢ÓsIEND®B`‚drpython-3.11.1/bitmaps/16/Print Prompt.png0000644000175000017500000000151311150445515021204 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕ&[Î<ØIDATÓu“MhœuÆï»ÿ}»›ìn7nšM¶1n­m• I£¨×¢'¡X%‡\D¤=Ø£ųg/BŰ7?¥^y¼R~jD¤R JL+èлýA¿EÁ¦QlbÓfzºòñåË|xúÌYý.ëÖÙnôÈx.–VØ¥=lò0Øç^ÏgÂÌ"* ñ9³´´øÎ¹å%â0¤ÙïAùIZÙ£±Ò•VÐá~ßçA¿M;ì\±>Q5óó'ŠiA'¤ ¿÷JloºüÝ‚N¢í-3!—Ï¥L«Õw Ÿüa?ÉðÃoYnûÃ*Ç¡øì¡|D,Ql1¾ÿH¶¶þ%ãAbÆx¿ÓŸóèÛA ×ç£"„ƒã8vP.OïÜÙåûï>cbÜÉÁ äpàÌÿm (VÌ`ðhof¦4-¦ÊS¼úÚ+äsy¢(BÌ`ç±”P©ä&±ÄqšÝݾ¨×7?-•¦ÆVWßãÔ©ˆ@[¬žnCÄ¢CùŠ:Ä^§½c|ßÿüÚµ/oO¯\¹ri ITUáÆÆMDk×q°ÖR«mÞ£Þö7o}k‡2?¥ÓÙ—÷÷ÛÝn·cG¿  §Ÿ UAÎO:mR[õ‡×ÿÚ®½;1ùÿk¹¢YÿÈ'EIEND®B`‚drpython-3.11.1/bitmaps/16/Close Prompt.png0000644000175000017500000000134711150445515021162 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕ.-û tIDATÓ¥“ÍOaÆ»í²k±Zá`ä#Å=Ðc°•‹ ÄÄ á/ðN !Ä‚«ñ Ec¢ÃŃx"@ð B=èÚEÛÒ‚ÝwÆÃ–‚ñÈ›Lf2yßwæyæKU9ᦦžô$“í£Žãx¨¢€ª€Bô¹rPäh¾þ1Õjõ…5?ÿi¸»ûÊëĉ„†TUE5ò¨4bUD„¢nä¿?Ž‹D>.|¦îcÙ6¢BˆÁ¨š †P §œ7Ïw¢"ÄïÝ{ø.“Éàºîø._íãÚ资ÔÊ”ê»l—¼ÍìÙ‹ˆñd2ÉØØCCC,//]]]´··377ÇêûRƒ—øíîQþ³Kq¯DÊÄQ‰ ØÕj•¥¥%R©¹\Žd2I6›¥T*‘ÏçÙXYåëóyÊ…›»EüÚ/°@LˆŠ!¦ªO}ßÇ÷}úûûéëëcee…ééiñý?òë$*-Ô/xìÚûœ–Vrç{Ùùµ3¯×ë D„X,F¥RÁó¼fa⺎ë±oÛÑ8ƒª`ôôô011Áöö6“““¤ÓiÆÇÇI§Ó¸®Ç­ÜÊmr“`mŒ3333ÌÎβ¶¶ÆÖÖ„¡áΣÊm-•Ãñ(ˆ1¨V££H–¶ËÉV·™ÈÞdoøÜ?•Å9ÇTï}ÝÈo<Žüðj¤»;óúËæš³¼µÞ”îEòV°,l,4¦tžéhrD„»½7Ì\G!ÊEcmÈØ ÆPüéG¼}óò›ã´<³°ZõAQ' À%;êëahöjµuë¸ëüÔÏ™qÍóIEND®B`‚drpython-3.11.1/bitmaps/16/not running.png0000644000175000017500000000070111150445515021105 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕ +5«j¼ÅNIDATÓ¥“Ar›PD߇{!¤r¥¤Ø;ûh9Jî‹ä9E’}¶”µLY–`º³àƒ ä( ³ù0ÐÝ3=M²Í{®üã×ÏÇf³þ 3"ƒYÏŸFÑèúoxºß€†—flÌö@V ö¹¶ßï?屨î[RªÞhÒç# gª*ÖÍ ãœ)l}»-¡@ "DHHB ,2Ft§ö y. "i VÙÈBÌÏó9ð .‚ñÞF1¥ªš&›ð`Ü[à±æÐ¤¬òýb„Û›¤àõp¤ë;¬³ûÿ2·b¶)8žŽ`÷qKþÿ#3íM!þ¼¼p·¹£N‰®ïPÄUð´…1u’hŸ[Ááðz]{ÀlšuCßwÔuM]××tÉU]$MvakVkÆPMQ^Ä›©î±…ÒÁïö¹ýjq{Ý…ß—ÛèOÝ÷ôÞßù/wl2T1˜Ç÷IEND®B`‚drpython-3.11.1/bitmaps/16/def.png0000644000175000017500000000155211150445515017407 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÔ27r;sz÷IDATxÚu“Ëo[U‡¿s_vœÇ1¶“·Å©jHpÛ€*Ć¢ (¨°„ˆ5,PüHe6¨lx- ˆH¡M!Òº­B‰hœôåÔvý<¾s}X„X #4‹™Oó›‡ÐZP(NÎÎÎæ¤”Òà8¶ýÝÂz¹¶vu^ë[·ø?ÓZ£µæã3g®ëÿØæÍŠ~ñôO:ùò×ÓÇÞzg'÷^7v@[[å: €í®1ŇÏiö4Æ'_øô£ï­l +¿·>ÀJ¨ ÿÊ X¦àùC5þømŽ;vnâøûW«â¾©Çûu;ºn7ä—»έöxý0¤Bá»HX z›DþþŒ|~/™·O/ !¢ZkO€i~óì«/<þ‰‰[ŽÉ¥‹5¦Ç4ù¸K´UYcoÂ"=>Aéf•'Ÿzö˜ÖzÉ"]8%Ó_œ_ Éf:håá·êÌd‡ÈMSmÂZãAª•K¼»ßÅJâ…w‚m •?Ò¶D•;,Û '‡xúÄ#8JóÍÙ+Äb™Ù,Õõ¦©0M‹°€0´ßÚÀƒ©‡rÌä³JÅùöó9¾^i2úD3ö±Lb&HÙ% Ãþü €ÚúùsMi°U“d''(Hã$SŒŽA·!¹øó D½Œ G«ÓFm/Lôvظväè‰û‡Y^¹F¥ÙÃÝ(qeþ/ZÕ:ãS)cÏ—´Ú|ßß X]ü~îÂ…ÛF„}“IBOú>ÙÇrd>ˆŠšô:wèJ—f³…R Ó4Í> ]ZþÊ]øàw]+Òh»(¡c¬K‹¿rdLRkHÙE)…aæ®C:šË§^Iñãr‘ËG³%X½ÌûŠLÇ$©¶<4Ó4±mÛÙ¨wÔžÛÕ3xmF±¸ñ%ÏLB|ôÊ2Dºm\×!ÐZã8Î €ØyçG#'Û U;jÑ3uˆMj4Ûï!„À0 Ëqœ=•Je^k]ÿ"…~yÛøIEND®B`‚drpython-3.11.1/bitmaps/16/pyw.png0000644000175000017500000000150011150445515017461 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs··[AtIMEÔ:$õ.ÃÍIDATxÚm“]h“gÇo¾l›¶1íÚÑ¡kkt¸*L/&®º"~0•Bƒ:x³iõn"¢»Ú°è./ÄDQÆÍ”ʼÄÂÚ!VªlÚªmYSõM5i’¼m¾Þçì"Mþ<‡sþçÎóMD(ر®žÝmm-ÿÔÖT¡VÜ ¥„±g³‹ú\äX8¹çóÍØXe;vlbƒ§¥@Så ²9E6+5›š›x˜óz»ÿôùΊ¥4ÙfwX¢ é×0†¥˜9É£}Ö}[¶|õõ—×*Îv¯·Û^TÐãkË~ïÁ7QzLXœ–ÒËýƉ”€©ß%1ëÖº]?& c¶Hð$,²gÞ¦qd LêLÎMòí‘”€hvíÙNh*DÅZp•¹¿sw[±…_Z¦¾°Gãë^Í-08¡ó8ø#:)+ÕW°Âå¢Üé*vm“Û·wR[{ƉuÿÇñˆ3¨[1b1ÊâÊs/Q*ÿLFòÓ-0¨ááU]Ý‘mh qz‚¡ç)T™‡Ö¯ŸbdÆÇæupتirkLëËñ<M§™D¼ž£êZŸo~DEª†PÈàúàeNÜN«ÇEáÏhšðagçyl©d2–I§’IèL˜‚¾¨£ÞEPoÞ[bæÒ8ý?xÀŸO‘R¢ë–úáዉÅèÞp:ÓkÔ{nb~D<”cþEŒÄ¿™|£~ЍÝ× °| Ž,™ê”­íè­CŸüL«û0öeÍîÏx¯­ᇢ$áûãWw=ÕefA䯱1}•ò3ü%§äþ¿]0—!—„¦ê­(Æg…–& í@IÐwÀ°oÕ2ÅcñÐo7úÿ°Z­åßÕÞ®ö“]½÷N¬*Ôs¡«h¥ë àõv»*_ß¹ ·ó|cKãúúίü ÿg| ÿôIEND®B`‚drpython-3.11.1/bitmaps/16/New.png0000644000175000017500000000070711150445515017403 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ -2‘åGTIDATxœ’1KA…ŸMN! ¦P¢ ±³ ˜N!–b!ÚXYÚ+ ± ˜_à/ ±µ" A$‚ù±¸½Û½Û=–aØoß¼Ù>h«¼y^ÙZ$1ÀÄçö7¼Î+Nê§zMFO& Ž»¼P\'„, ãH> ¯›ÃQý¬v°·Ö°†‡0]ÌC0 P€vÇCoÔAy~üx0{1µ¿³R€~ÀòEÁªXP\·h]Ýáç«ëV—v]CðIƒh-Ì•ÆPšY„OAþtÿRЈˆÍbÝ _ËÙæ . Ò€P­„Û Ž« $üÐvH0<èÉ—(1ݛԘ㲓ÿáo@8…DÏ1€<‡ @)ýSjíS øK€„XÝ7¤}¤H/ÙŸ7—ÍÃíëÈ (²™¼½7“êÿµ~ñŽ-4†ç¬ZIEND®B`‚drpython-3.11.1/bitmaps/16/Next Document.png0000644000175000017500000000127611150445515021331 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ -97ÑÏKIDATxœÅ’»O“aÆï­ßEl+—Kk5jƒ89¸329»ù¸¸ººº¹(1q1jbP〠¤@TnÕ–€Tháëûõu $FGÏtNržóœç9þwˆ£dhhH–ËeS,åßÎ9Ö××;•J%š››s P(ˆ|ooït:Ýÿ/Öv»½U(^*¥j X,vݽ™ÉdÔ™—8šÍ&ããã'''ïj@”J¥t*•º¤”RÛÛÛ'Bsˆýœ¿ äóùr¥RéÓ€4Æh)¥iµZÇ܈NŒW!¨Í“Øo%’4sÃHPq‡„PJ ­5ÖÚì^ušÓ«ïðû‘ÝÃ$6W1ŸžÆ%‘°»Bø¾çyc~³ËÆ éÏ“á¥`wÂSß97û^öÕw•ÐZãû>APè¼xáШƒ8º¸¾‘ –ÂcÏhc A†áA4(¹…J7Àûb¤`ÁßCží„Ézôás¸(Šö›ÍfË9R“Zê¤6*´Ç ˆˆö»PÙl¶+—Ë]ö·Ø½°¸ø$‘è[pSa­­Mìj¬G)ÀT _PäóRÛ ^I&' †Ñÿ8‘è“ •% ”µ› L‚X{Uµ›ƒíáð±ã‡ïlòù: £¿Êí0¥²a¶_)ÆÇ¦ù»jnÕþ r¹ôZ€²~VbIx5æ ‡Ž4“ù˜Á«ƒ£gløÑ>GöªõjØEÖ4 43›ÃãXp;t̨•("ÿžO¼ªp,¢\‚Œi%ǰÃÜë*­bnt à½ZG}è¨x(¿Çáú¥h£SÁ\VhÐ5´ò¤S@htË5ñæ~Ý€4èŸÏöo9À7¦g'¹wm²€aÅþÚœ>Yª°ˆpúÌ­6ùÔÓ+ò~Adæ§È»"©y@n!\Dˆ#€¬Q0ɶíõ|8z3g̓ì j$°·öÁTÄ¡ +ٕ̃§¯â.—ËÀ³ƒ·£á0„Bиs0ew¦|œ £?ÔŒŒœÿÂU Âç ƒåeèꂯw­ø2gÿ£ww µIEND®B`‚drpython-3.11.1/bitmaps/16/active not running.png0000644000175000017500000000103111150445515022336 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕ )ƒ¦iD»Ãž=*ê|>çÕ‹—D3¢EÌŒh†%ÃÌHÉH)‘rf<£ÍÂ(ô{Žf,âë%ZJ K¤zöì (˾qAŒ±$'ì&%£ëºA°Ô4ñrÆýÂä#)%ºt6ó¥°¡?ºÛ7oafÿúÉd2Ás½x kˆò0;fÆÉé MÓðìñS6nl\j ÷¢Ûš(;ÅÄ·ßyôà!×B`:›c¼@+E¥)ÌŒ½O‰ÿ×ÂîŽ •­{#¦³)mÛÒ¶í?Ö=_y½]G$‚€ìÎhs„ª}³;rG¢Zºž—V¯EU[øº°ÿγ_¯%ú¡ê­³ûÞf§¿?4WýÿDIë.MèüIEND®B`‚drpython-3.11.1/bitmaps/16/Toggle Fold.png0000644000175000017500000000057511150445515020743 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ )Ò3Ø IDATÓcüÿÿ?%€…¡yý“BKõ¯ ”égr,BÉp@?ºÈ±Í³I2À§w.‘ «ûr˜YXžÜ<˰nr!ƒ„‚ƒ•o*ë'Ø8¹¤”tñZ4bP.CPn?\Á½ËGt­ýˆ÷Âÿáì¿~3|z÷‚A@L†xЧÁÙw/aS7f`eç$Þ„Sþ3Ü»t„AIÏ–¸@Dß>gøÿÿƒ€¨4Æ)% ŒÌÌ ~ý`ààæcðNiÆoÀ»„$äáü€œÒ\ ¨cÉ ¨cIzB"+3100'CïqFJ³3÷>GÜ¡wøzIEND®B`‚drpython-3.11.1/bitmaps/16/class.png0000644000175000017500000000163611150445515017761 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÔ1:'§\+IDATxÚu“HÜuÇ_ŸûÞ÷{¿<ï‡âv§Ž¦tš§ÑÎ,GÛ¢†­ZDN#’A`8ˆhkƒÙ_Á †DµfÅü§’Ê¢ Ñnmé9—NÝRϦsçéwßûùéŸõ†žžçÅû÷#¤”!œo뺾–ÍfòfMQB“«ãÃãA)ÿšàÿ$¥DJ‰×ëÝ'ÿC§> ʯ fÊ÷¿ûáæîö2l‚Òz*YHÇÿ d7¢JòtÅ-ÕýØÉw}ÑÍo»-@>—.,'yàïuáÛ0—°±f(£­ÑÌòõfãE¦æ“áIQì lÞ7›X2™îøRPVª!°D‘‰ñÕzGg1ëWPfÎQûHeoœB˜¥”é-@¥Û’©´gHk6~Îqi"ÍÍÙi‚ßþŽwG„OUÞåþj3‹Ë¾‚Z`Ôð^[{ÝçÏŸžøî`• Ÿ:ö‰' ¿‚?Ct½ô8ϼð*Ÿk#‘·¹³ `0¾8|õ“‡ ZóÕ¸*lÄêö€4E…lÌ%<»§—k~¿‚½ØAww÷P¢4Ö<à}8и]ÇÒw/æã,xeⲑÈè-G ¼üš ±h%cÆá²cµY- #†+z"D¹ž?Œ÷¾*š†º 4°¸ûG>þž3gJ¹ÈÏì ÖÒûËgØŒVb±ýýý±d2yÉx;—›âÖ<ÔÕA¬×á »‹¦® Xç­È †¾Y"3Îzƒ$4ö===¯K)S†¾káÙŽ¾ÞöÐÙ³7 á«h€"]S},Ü]"3 ¥š@®ƒÕnÃ_ï˜ÛÊÁç7§/•—‡Ïµ½¶³æMrb'NR)Àw3­‡[IhkÜ^BUUë=A*¤ÓE¾ãÇÐ’ – ›‘â{ð2kpdW 'üï‰/03?UUM÷Jm6{tf†\&‡¢k<¹ÔÊÔX-»âͨl!–Xeq.‚ªª AÓ4€ØöÎF·Û}H×u)²ŠP¤I˜1Œ¤d’¼Ì! !„QÓ4ÇÊÊÊORÊØ?ÔÂk"Wí¾IEND®B`‚drpython-3.11.1/bitmaps/16/View Regular Expression Howto.png0000644000175000017500000000134111150445515024342 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs··[AtIMEÔ2$ìʇ¥nIDATxÚ“ÝKÓQÇ?Ûo˽8÷b**¥f¾¤I†ii&EDô†Á ëDè¶;õ*Hè†A„P&(V•!DD˜^’™º‘s/εÍmçtñ››©P_8<ððœïùœçê^бEMMì+/D@R¨ñ„ —ŽŠ²²ccïNgßèÐP·Ôn5„PcR€Ï ‘ß” ÏÒÑrº¶öì¹w³Íæ‹NgŸ~Gƒdj-/À£ð{6 ã¯&ñ‡By6»µ¨Î\ÁåÒµS&„zòÌ'ÁÃQ ¬& -ÇOÆýÍÉVƒµäñ“‘ú AqqaËŠNá×ܼãazz–ðJ†JH0Y­ÍÖ]º A{ùÛ‰ý?Ï\àölÇŽ,ÒXZË@Ïßç%¶’=`Í¿¢v7%•`j*»£#«²j<{â%ÎK Ímx¯ópðz½5»Uf[zs^ÚC%¾¼úl¬ÊÒ;áe-ã<¨­ãùä8ká0 W±H#BB(à!ÒZ€™‘/•3>ÇëÑCçoMï®'0ãF‚TäØXŠÇø‰¤ŸÖdÉGkÈÿ› æÃ`/À½.Wkóµv,¥…Ô-.àõ¨´å’H$ÒMŒ„}(úL¶M¢LVQ~ª€+±uŒƒ:`vl©]Á 6&´(Š«QŸÎ ÑX][š¸IÉ$ÖÔ!Õ(S f[Z-hd`»Áj`Õ=pxPQ#ÿP4 ~Íæï àtöÙ ÿ§øårœ ñIEND®B`‚drpython-3.11.1/bitmaps/16/Redo.png0000644000175000017500000000124211150445515017536 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  @¾áAtIMEÔ /nÏÊ/IDATxœ¥’ÁoÒpÇ¿-e…jc‘•1—ãÁÄ£1fQ›%.<¸ƒz¢Gÿo³€;z0ÅD Ñx!Å‹c§Æ($ʆPJ[ZêÁ ‰àfâ;¾üòyŸß÷=à?‹ø³qb-'}ô)Úï¯={þ^ÔŠéê?\gð†Ù0Ø9#@· tÚp©m1jw«5Àò#v1”¢‡ XÍžÜ f£ ±p8€æ76ŽÀ G3Ÿ¨id(—8ææGÀÙõ§’ ²¶=€«\pÿ$±Ô¨Ì»>¼-Ó‚_â°öRƵ,tÔ>ÕPü¬N>í´bZ€rvµª=¼(P[["Yÿ DbRU3¡jæo€E9~† ÉÈ'…©JE  `!ÎÁ7+)&E8µ> ª˜“ÖŠi‘ªV™Y¨”ÝQƒ«\ ¥Þ¡i$o=–v·ÂÒ+y™Nl:U°‰YOÆ9ÐAë]¨-e˜Áp¾TÞÞöàkÕkǽàKåK-F$ÇŒw¢•×ì"¦營vwÚ¼›¤¥mÆÇ6íÎææÓÉweA Ü$MY€ µ¡Á¹õ'ìë/ºÔž[àÈ^ç§ÕÂõËñÛéK±vkì”§–sr?äÓçÑßݼMî!ÇŠÂ;ÒÀíF©‰Ä«7õÌ~­© YùèJN>èÝøåì™h:¿£éú Í»ÙØœdvÂIEND®B`‚drpython-3.11.1/bitmaps/16/UnComment.png0000644000175000017500000000132711150445515020556 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  ­#½utIMEÔ3$õѶädIDATxÚ•“]HÓQÆÿ}üÝÒùÑ"¬4q~‹ DÉU ³É6I…’Ô ¡«Ä ‹ Ë.‚èÒ.ª‹¤¬Hb…$%Õü€(S³Wø‘bj¢ÛÒm:vºð¯ÌÁ.|áð^œç}ÎsÞGB°­’¤D@x"¬‰‡³8‡oùÀM·ËŽÏ|Ì®˜|ɪJVwfWÊó‹ürŠHn!à:нI !ŒiÁ“uº+¥j쩤H{^Ã|W¦mÍ›–ÈÀ°{Ãß ã4óŸï×þ|¨=°ôÑԺžôSSSƒ_N*wXyuD™Ý´^@¢€FåÔÐmó5q®¬³UA‰c(©Ä1$JC¾Xó¢M”̈¤šíÜoï3ÊÓÿi“¿(üÇ”>/3À Üûº«ðÝ“Üz‡ON5½Ê½AÙ×qùí8ÇÔº€ývØåIEND®B`‚drpython-3.11.1/bitmaps/16/Find Next.png0000644000175000017500000000116711150445515020432 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDùC» pHYs  šœtIMEÕ()°ÍIDATÓ“]HSaÇg[«m¥Æ‚±ŠZ0p,%IŠ]]H_]vÑEtJw…aà­»*ˆº Š.úRª •È-tlRY7!ͤeÎæv¶sÞ·‹uæÑMŠxxþÿ?Ï׋ìEÊ^$ÿiÊZòÝcë% eÅ?/¸6ØÅ̃˜c-ðÌó(š ×+º&É„!!½WÔ³Õ”¤©• O>¥†lºi¶¿õh»¨˜JSÕ*ÙÚóºÒîàÕù šgÑûãÄãt˜[ZÁ9ÖˆvráT'€ÖÝÜ|2‰Ã5ƒÞ®­Àpn@ IžöŒs4ÒŽò‡¼-ÉØ×d6=‡Qo_úsˆ!‰LÏ lÛˆ”’\¾D¾¨àopðá[ CX”(ÊësW…eÚ»$ÓË4­lTÁ_s:A¯½þ4te6xšx<:Éb^¯Õ¢ –œÆëÛ¾ª…ê.ƒ3B-m|ÿñ’[÷ÞÛ‚nHRɼHØfʨ¢BÖ:¦y1Ë»·)„„“'Ž#Ú|ìÙôŒâì%vð‹y«€•l¾î†&öwFª¹R¨›±7"þ âýîËÃQ†M±Û#)‚>תs•fÌJN×Ûy1ò‰Á#åÖÈY×År;€û±=z:ÔãßêÉýUþárÉIEND®B`‚drpython-3.11.1/bitmaps/16/unknown.png0000644000175000017500000000077011150445515020351 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<ŠIDATxÚbüÿÿ?\¼øÂÀΜ¹Î°ø¥;ãùÙ6 \ ÏÏ‹ ²"}}8ûׯÿ þücøòåÔ”ÿÜ?Æ(aW@,¸ldffdøÿŸ H31@É`n®Í0wîöÿŒŒÿaꈟ³À€\ò ´¤Å‚Œ@,ø4ƒÄùÿ¼¼¬>~üÊðéÓW†Ë—ïÀÕ~Û4#˜þòå;Ã÷ï?Àld@]¢ÿþýÏðû÷_f†ÿPí ¬€í÷oX,|gøùó;;+PœhØ?µÄ‚M3ƒlýùó'˜ÍÊÊ –û÷ï?ØKÈ €X°9dû¯_¿ À렯 rª„ˆ µ¿ÿÛà˜€&: þþyá?Ö@…ˆ ÃPh#4a·/ü…ä0,p±€bBw>²s‘52âp@± gWäôN,0ÑC™”šDìIEND®B`‚drpython-3.11.1/bitmaps/16/import.png0000644000175000017500000000152411150445515020162 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÔ3¹-ÇÆáIDATxÚu“ÏK#gÇ?ïLf&5ަ»«K7ÖÂHP¤ l«UDrh÷(öPð(´›ƒ‡ÒàíÁCA„â%x”^„ …í¥T(´Õƒbm ˆ°KÌ'’̤»™™·—ÍT ý ïááó>Ï÷ù¾BJ Àôôô‡³³³YÏó|d„¡k‰ÇGU§úçéc)ëþORJ¤”lnn–åäz/ä꣟äÝ~¬Ý›ÿôó^íõ£ô@µZí ‚žˆžñðƒ.¯•»#÷¿ùúþ¥Frðµìõb@†Q¯£ž\? Œ`m¦ÍÙï?P3·>;)‰ñùø‘ÞE€¦i1 Œ$M÷ïêÜVkè&Þ¼G&ÿå/B(oH=ADWWWt:TUå¯F§åâºÏùø[¯„¼=ÛO£ÕáûAsø išhµZôõõ‘N§ÑuL&á;tüªâùÏyúä Õzƒ0Š¢x˲޻¸¸˜»nN¹\f}}±±1èv» àzæææyð ÿ-ð]`yyù“Þ‚ ™LryyÉðð0SSS´Z-ŽŽŽ(‹lll022B.—»•J¥ÞW …ÂW…B×uÙÞÞfggÓ4988àøø˜ÕÕUR©“““LLLP©TØÛÛ{æûþω—«ûceeåWà]Ó4±,‹ÃÃC,Ë"ŸÏS*•899ammÝÝ]J¥[[[¥”Ç&ŽŽŽŠ¥¥%ŠÅ"ççç¤R)r¹ûûû4›M±m˲˜™™!N;7r ªªêû>Ùl–¡¡!ÆÇǰm›v»”Ó4 ó³3t]OÞ$ =™Lâ8§§§˜¦‰"Î}­V£Z­¢ª*š¦7@½^§Ùl"„ Ûíâ8š¦†!žçáû>š¦¡ë:†aôˆ^ö ÃxK×õÑ(ŠÚRÊHQ¢(Šÿ†¢(¨ªŠB5 cжíߤ”åági{xâ IEND®B`‚drpython-3.11.1/bitmaps/16/Open.png0000644000175000017500000000073711150445515017556 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÕ%,£ohlIDATÓ•“;KÃPÇ7Vuq°ÆA„‚©“Kq¨8;§(® ~wQ¿‚àdq¡qÅ¥Fã`kUD ¾rnb›6)õ—s9ÿ=¯«D„8(¥þŒ"¢âüR Á”btJsÕÉTscË‹5ÚŒ˜àLBº±µ*awUÉÂò¼ÞžŒZ¶¸tµ³‚Ìä–ÜéÜ’‰À×Û3åýÍ$ÿŒeK©¥‰ƒÃiðÁ«8˜™5°hhYsŽŠW{‘êFS¡‘ðªµò9c‹ÅØçû§ê÷‡Ó j—[wþ‡ÇÃÅcÙuxß…à›ºô£dF÷€ ˜©°¿ï•z†Æõ¤  Y†ÉS-(Ó²Ea×'ô™“š î„ïêÅ-ÌcÙzÔ€Wsøô¡/=®5a@£ zç½8¼ÞY¤§Ê ‹kÁ`iKòæ}»-c™Í6lF›“ÎS=ÔµG‰ ¿ÝôG’¾s§ø±{‘ýìO°IEND®B`‚drpython-3.11.1/bitmaps/16/active running.png0000644000175000017500000000110311150445515021555 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕ *n§€KÐIDATÓ¥“?kQÅw³IÄXˆE‚…( ‚âQÁ?¥`aaP;K{?ClDRø,ÁJK ˆ¯ ˆÁ¿‰¼$&¾Ýìœcq÷彈±ÉÂ…¹s÷Ì çœI¶ÙË—.^ºyôöô;FØ&˜(Ç™÷o_¾ø¯…ûË>GÎÝ¥óa8Ž'NÂNôwÅËÀ‡‡Thɘ:}éü¶uÊcFæ›øËÞVVáÓÌÌãGu]ÛF /Lk°Lý7å©:ïç^§½®ó½/P$IEND®B`‚drpython-3.11.1/bitmaps/16/Close.png0000644000175000017500000000133411150445515017714 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ *!Zß^iIDATxœ]“ALA†¿v·l«”¦T*hM<$ÄØD =MÊEî„rB˜xL„Lõ`L¸È‰è…x2*M8/p2ñˆQ±T šÖªÐUJ] ÝñÐmÝ:É›yÙùæŸyÿ¸p4åôüÂñ£þA$HG^Ú=÷šCÆÒlîó‡ªÐÒìáÙL–K€Õ, e£Â½‡nÎn_y¾øõÓÇÌl@UÜDO„0E`Iµ¯„írK€±ÉÛ¨ªrß»ràX@Z»üú]ª* ¨,jj$æ¾Áöv‰¡Ê;;ã.ŸÏ'»»»Ñ4ÿ[ÏÉ(×'“´µAøc\»<„´ïè{>‡+ËD"A?ëëë‹E:;; ,//ó³´Ë¥‘«„;"»{û[áâ“G¸ à N ‰Çãøý~b±¥R‰l6Kæí+îÞºI>ŸÇ’ z4;ÜŠEJyG×ut]§··—h4J&“!™L²¶¶†®Èe¿ð-Ÿ§çÔ|Í-XT¼÷µR©P(B ( år¯×[W`š&šæ¥Éë·ŠiWDØevtuu‘H$ØÚÚbjjŠP(ÄÄÄ¡PMór.~‘ѱi‚míõ’Z¶?T€b±ÈÜÜ©TŠ 677‰D"˜¦ÅÀðFǧimëh0WmìÂáZ—[£ù VOÄÎ÷‘œy@k¸½¾Àr–žÎ£R…Ðza~auqxÐr8±nkño\ƒÔà|4Î3ZŽy='•4 º“éüÙ±³pÎíhìÿxAêñ^}¡¤ñEÊš;Ÿ^}É_ƒúq/ŒÄ«@IEND®B`‚drpython-3.11.1/bitmaps/16/Replace.png0000644000175000017500000000114211150445515020217 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕ <†w…ïIDATÓ¥“MkSA†Ÿ[£6‰¶ÑBTHÄhcl0m5B¥+Q¸)ú¥ta…®]èFÁ Aü@ mܤJ’¢Ö ”j‚¨­m“”4_wf\´¹Í¥i:p˜aæ}^Î93£©;(þcX´Gƒ‘[ׯE=Öm… Pj=¾/¹=Ú«ŸÆ,ç‘Ë!<Žà$)A*Hç`dxÕ ÐÒ,½Fp-L%4ƒ§ãq¤‚#Ga³ïE*LM³lOŒ3ù­Â™žÓH©¸ûä}Ç÷ ÷’É51P R©³Ë­ ]9‹¦iõsÿÕë,z{Àз4J{.³ÀùHØ€—²E³ENvú˜Ogu5l1ÀÌÞŽÝ(¥È*J:î6 _~U²¬ëv·g‰ôŲ \†øg^ÇçÜaºà,@—P°ÓîàåÄ+Ý®–$“‰œ®¦Œ&þY÷ ü]!~/¼åÁãNt¡ E2‡ÏÏ8L[½[ ¤\‡u BBwß9:W²|ú˜D*¸tñ2äâpëkJó78Ȳ٠®Í¶6§z"Æ^ÅßOôÃ"wŒ÷C¶›ä6 ¢Ç’ø\VÓsUµ5›{ºæÍØ£Õà×”õ¹ö¯ßù^ÌսϞÿ qþÕmi0IEND®B`‚drpython-3.11.1/bitmaps/16/Toggle View Whitespace.png0000644000175000017500000000107111150445515023036 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ 7t ÜÆIDATxœ¥‘;hSa€¿¤ÕZo*”‘Ø%}`lJkQ 7\ƒ‚ Hé謓»¸ ÒY¬“¸tò1H|€CM 楘@S%¡Ñ4CïÿŸãpÓÛÔ[£àŸóÎ9ßyÁJèo«‹,uÚIÃà:ó¤ºVŽ M/œ¸=u 4?ÝxÁÚì%΄.†z·®^»»«RdèÁpãgl®õæÄƈBí[†ê¾ËÅû~œ8urìÂÂüY¶šeêïoPû>K8\f³QgóÓ[r­ ¯j zf¾ø€pgUU¨Òd_§é;~…ž©›¾ON<Ä}D>.=ùüs*Ð(F”'éCœ>ÿ’§ÏVU", }õq¦34M®rùQp­÷·²ƒmhQˆ¶;ü]vDINâ 8›Áˆâ X«ìw¤@Œ…-ã%¹¢Xc=–éÀ*™•""Ù%DAD•Á#‡9: ü+¨‚+Û;–ÒöëÒâZe<9Bÿ€C<Ç´G0½ý"]Š·c½kxÉm-ÞŒ{äïÖ¿nðn9@e­ê;ý€-Êë¹?J…bªT(îQ# •NãtÚÚ³åQFIEND®B`‚drpython-3.11.1/bitmaps/16/Select All.png0000644000175000017500000000066011150445515020560 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ 12M o=IDATxœÍ’Ñ+CQÇ?´–å®DÊ݆åA”RËŠ¦=íqòBÉ€7%IÞý<ÉÚZ‘RÔjZyÚ )›,u™¦m[š‡_¹ìšnyàÔét¾çôùý¾ßsà¯GSm‰Úo¶za; ׯ~°½ Ø-Š/pW‚ì3Ü—!–¯ Á¾ïÍõÂÜDBÐߪ…*g[0ÚZ ø ‰<¬ŒÁü0l&¡¬[„3Ò¿¦Ä8cÒ`÷\ œ=Jª;ç UÌSˆ‰¼xõG7†Þá` õ€þ[I˜èÕñ¯§¢°q Þ Uˆ^BúF]RÑ熑.pÚeßÊüè –ƒ™=ébí–ã¢kX8”ÏUÒav_Š˜,øÜ™4ÏÓ}á­…-„­âƒ"d1!†»gýý~Ï\Ïzñâ¡7£˜J8`¢C"” k»¼´´víî>/L+FNò?Ìdæ73™þ·Î9æçç‰ïû9Ïó BÈ_ ªÕªÚÞÞζ¶¶0ß÷ Ïó&‹ÅâýB¡PøWÇN§S+•JkF#‚@3ß÷§———¯¬¬½{Çðè鬬 ßÅĘxxÊÈðï/(Ð!16€êœ@áçëÖ30&§0ˆùÌðè’¿ŒÌ ò,L ¿{:>Õ±ù1üùÏ7 €Àaðšú>¼zÍð;=ƒAîÃ{† ×ÕÍÀÞ×ÏðñÛ1.NÁiS¾Ý{Àð—言ðò „Ã%(Àð?;‹á!ÐI?këDKг3~–U2¼xþœá½“+³”40&á. °þ@ýô˜ù*kÞ9¹1ðè3üû ñ/GJÃ=c}3&†?¿$ ð”jþ°0ÛZŸþþð $ÆÎÀecŒ:†0ÍP=Ä?VèM& AI ˜Þ™ÿAb”þAbÌècãgI°^€'ŽŸ:?›ßŒ˜›ÿ€t€¢ó?,f Yù?ÂfFf&¦“‡]cÈ1f0¹Hv;Ò׎IEND®B`‚drpython-3.11.1/bitmaps/16/Default.png0000644000175000017500000000143111150445515020231 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÕ9+Š ¦IDATÓ}ÒÁO#eÆñï;L‡JqÝÙR·4 e…âBá²HØ+&$ÜvÜzò þ'œ½ÖpaÏbL8HB€–6Ñ@*JwBʶÌtÚ‘™jûz@Ó˜€ÏùÉçðü~‚G’J¥ÈçóÄãqNOOÙÚÚz°§?˜¦I&“!NÓn·« €|>Ïää$Éd’ããcFGG™žžfvvß÷ÙÜÜDÓ4Òé4N‡@,cuuÓ4Ñuññq&RhºÆBnÕW„2dee…““J¥ÒF£mÛÌÏϳ±±Á¥cóGëœJ£L42ÌÂrŽÄ“OñZ®ëR.—úhµZH)y9÷’fð_®+t#]4C#PÕgD”N§ù'…B½½=úý>º‚µµ5¦¦¦xúÔäæÖg»úŽq1@BоiQ¼ú™o¬oYZZ"“ÉP©Tî™™r¹/^|FWÜò«,r-jè=@¡}I+L2Ñx½òšêoUêõ:ºRŠ^¯G$A2ĈuQ7èi€bè/A”çø¾”Ïóð}ÿ~ƒ»»;‚ àý{›ñxGûö³*ѱ>Ñ…1¢VQ¬›¯H†Y~üi—ƒƒŠÅâ=P¯×©T*AÀÌYÒ±ÏiõmTÌ'U wG˜¼ZfY½Áw~ØÝåÝ»šÍæà Ùl–¹¹9r¹cú'Œy)¢Nœ˜óœ‰«W|~Í=ÐÝnÛ¶ñ㔇õ ìØbx÷øûâ Œjÿ‹ãO+ÀÊe•ÕÉރѽdë?bÊOÞ6HÁgó6s:ÓF5®µUì¿|š›;/rVýógM_5%‡ †Ï*#ÜmÝqRS)HÕݤӨ'±û@”ÿ_*|Ø!zúÄIEND®B`‚drpython-3.11.1/bitmaps/16/Zoom In.png0000644000175000017500000000154211150445515020123 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ 8z†ãœïIDATxœ}’KOa†ß¹I§¥ÓiQ{ÃRJ)! º`å^v&Ä á¸Ð+ÿƒŠ.L4,LÔÄDLlŒ‰ñB‹¦F‰¢Ö*˜vnB/ÓùæsƒZ¼ä$gsžsÞ÷mÑÛÛëJ¥R‘D"!†ÑÊf³J.—[ÂùQŒŽŽúÇÇÇO —$)jYVcyyùÓôôô…t:=G)%ÿ¤ y¦¦¦. …-UU©¦iTÓ4ª( ™™y;111‰DØ¿õr<ϳ“““ãcccçlÛ–*• 4Mƒ®ë0M@`/Çqájµú0ŸÏûÀƒA÷ÈÈÈ1—Ëåk4pŽã€Û¶AAww÷‘X,vàoð’$¹DQÜ-Š" ,ûkSJ)xž‡?è$„„¶=£;ªª¶,ËÒDQtAøC'ÏóX-—M› `‡™¬¢(ÍL&ó¼Õj™>ŸgGºÜnl¬¬|3K+õíéL;€£”² …X,æO&“C6„Z“BöyÀ±,2ÒtÅ7’è;ìµ­¹ÜçbÕi“Á!„–J¥E–å¬é{Ÿznß[ôtpúòÇÌ£¯úÍ+{¶róè îïˆïåË~ÈWH;Û/̾.¯åÖ¥T^C×üÜýóÙ§o ÒõxPDÄ(~à¢}}ûC±}É[˜Í.åMÒ œ8m'N^¤R0I½N£³ÿèº+q´YLŸíH‘ÄÇkå‚Çʲœp›kó¯ÊºúÀ"z$ 9‚·Ë o×.´Œ%Xæçbîî ^`ßô†}ɨ,ôÔ««è’=1¡¦o>[QŸq?¥Xæ”·pèD þ¨ÙËgðåÅUèÅú;e³Jfa [û;´®:FÓÎÜY\{òÓÔª5…Aò¸ Æ®`ñÎ#gMäýƦ!ìâßì‘E¢[äÕõléÚË’®´ß”˜Ha7øÆêˆÕØ~€À®}w§íPZÖë€æwoØ\yí½ïñIEND®B`‚drpython-3.11.1/bitmaps/16/Zoom Out.png0000644000175000017500000000153711150445515020330 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÔ 8&¼Š:.ìIDATxœ}‘ÁOYÇ¿3ó¦ítºÓÒ‚@Ë–‚µt!$ •ÄĽxX¹ì&r0!‰ÙÞôâ¡õº7 Íî&$\»lL$n hš¨×XJ§kƒvfZ ´3óæy¡kqÕoòM^òËû¼ß÷û8t)™LúÆÇÇ£©T*T¯×íl6«år¹=|F\ç033Ó377÷ãÔÔÔeEQb–eµŠÅâ륥¥[«««Œ1úIÊä䤜Édî …C]×™aÌ0 ¦i[YYy>???FùÝ!üÂÂÂÜìììMÇq”jµ Ã0`š&Âáð)AkµÚù|~ÿCßßßž¾èóù‚­V ®ëÂu]PJá8(¥ú&~l¢(ŠO’¤^I’xàù÷›2Æ@AO8 ”wÆNt]·-Ë2$IrEQü_NBÞ”Ë ‡R àD™¼¦ií­­­¿lÛnƒAȲ|Â>¿UÝo”Ô£ã×¹n€Àã··· ñx¼'NO*Š"z½^x½^p‡­µU(¦œNùú ÇÚÈíìÖÜ®PJ™ªª/DQl5›MiØ-î¾Ýþó÷Jý—Ÿûs›ž˜èû*qJ@.û*_íäàŽM E$e``$î‹„½GmÛjWJÖb¯y3ðœcYH|wÅ®´Ý‡ë63Ëkj› ‘¾ú“3úCFó¤¾WÙéKe2v¹â=s¶õïút4PH¢Y.ˆ±Dât(Jù{›O˦ÞðH~;†ØD’Oƒì¯BT ¢TÌþö€ˆü³ä`0 ‰ÃGµ7ˆ„䏨4«úcò`gí>êùe´ö À8/…KæRú닽¿!ðׯ]H܉çíú“eB,—ñ €ƒ ƒö £àÀصP{mCß±´З•ƒºè!ÏúB5-úô^¶t÷IÉÔºÿ”ërGn×Läß—aÀq+›Guíw6Vý×~IEND®B`‚drpython-3.11.1/bitmaps/16/Select None.png0000644000175000017500000000071411150445515020747 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ 1'O±ñYIDATxœÅ’±ŠÂ@Eï.Ë@ ©¦Š¤¶J'c“ÖÂNÀȈ‘> Zj«X™Zbc'$E!…hs· Ä\XؽðŠy<ÎÜûf€ÿÖIþðõÚð}Ëå²8Û¶ ×u¡ëúÏ·Û išâx<"Ë2¬×k´Ûmt»Ýz |Ñõze’$t‡¦i]×}+TdÇBÐó<ŽF#†Á<ÏkŸu®Â0D³Ù„ã8‡ÐuaÖ&¨v»æó9öû=²,ƒiš˜N§8Nïwày…P*)%W«U%Bé<ŸOt:H)1™LJõû}´Z-,‹zçó™APÁñxÌÃá@’|<Œã˜½^†ap³Ù”Zf³YÉò`0 I&IB¥TÑ·,‹Ûí¶!MSDQT8³, J)ÜïwDQ„ËåÐ4 J)H)k_åïõ 8@òÆ{IEND®B`‚drpython-3.11.1/bitmaps/16/Python.png0000644000175000017500000000061011150445515020124 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿagAMA± üabKGDÿÿÿ ½§“ pHYs  ÒÝ~üIDATxœ“¿JAÆ{"í±Ó"M0Í"¾ƒ Øø ‚…ˆ]Z_!MHksˆÄ4––ZÚÙXX};á²s·Á-nf¾?3{ íEð`)aC¥ž,ªLµn€’0²•nì¢v•“Db„EeGV"©\“¥˜˜È ”I\ÛÀ±sOΑʋ—ˆ:»Úì»2åP"¹?fÙI9$—Õ§Sôþ‰΋¸ä Ó6h8„Áú»Ðÿ±Jmõ«Æ'wÀC“˜ÏÓiEZ$k8§ÀlA¢«nƒˆ.êJ¡/D%H^d²ZëÑm]Q×—UÏëtq41¢.æ™ç÷ûÃÿ^Â4ME¥RÉ”J%Cñ×µZ-©V«áÜÜ\ *•ŠQ*•Š…BáV>ŸÏÿëÇv»Ý(—Ëo·¶¶<Ïó´vGFFŽÞvMj Ð4›ÍxbbâéîîîÏó6”mÛ…ÞÞÞ¡(NØÞÝCî!´F[ BǧRJ™Ëåúúúº§¦¦6Uœ1@ú_¦qê³d‚«‹ƒâ¾;Œ6$è#Ã0LÓ4`¨LÔÎÆ‚ȵ–°Êýg®Ù\EÕ^Æ!¾{í”…R )¥P…õ7òüò{Ãêû,´gSUKàØ ’ïc´ò.I×¹_–e‘ÍfSX¹’ÏÙÊ ÛÛp\žÖÝÄŠ:Ⱦ G}d³Y”R) «G÷nèý  Á ÝÝØÆqGgzضiš)àPÒ¦“€|쟞™Ö$û*94T´÷’!AøZ§yÔÊŸ{TóW¸ˆümè1,~ؘ~øèÞ“™åÇM!bß÷[õz½ &?êE—ñžKÜ(^ÀE’F¡U§93Ž¿xW{µ²±zh!D„¾ïû€–Þ:,­P74ŸeL¤ D»ÅúB•×Ï'ypŒg‹^²EÑAEÁѵÖ1@™¾2]7¯St]Ê€h¬QŸ©²6ÿ H´s|ø ˆaãIEND®B`‚drpython-3.11.1/bitmaps/16/Find.png0000644000175000017500000000116411150445515017530 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕ-1AGåíIDATÓ¥“ßKÓQÆ?_]å¶RkÂX­´åHÚ.Ô ]`DT7A—uQô…QWÑ] tQQBÚM+T6)m7¢9¢réÖbî×÷œ·‹±¯®tàå^žç9ïóžó"Âÿ,€¼1xïÖÍéö6û_ˆ”âËz–ûFúea<Œˆ@àúÝ•¤Ô\Z‹(%RP"¹¢ÈfA$–Á{öŠˆÐP¯¼ò дlE•…zäÙ¹9´Àá#Gq8÷ ¥d§®€LNM^)0ØDkatü-ÇöáôÿUG@b±‹M _=…aø1öb›}³Ågáj•½_ã|(`‘×SY©,':½,¯ÆQ¶ (`þkŽŽ¶]ˆéLLÎÀÓlãó÷J×ÐÝîmßIdu“l^‘/* ü-mâu5V½‚%W`j(*ØálåùÔ ÉŒiç4áÈ<.÷þ* Vn‚g7(®î~¬½áá“gøŽwc*!™ƒ…§ø\>fíÛ´.‘M JCïÀi:“)>}Œ¢.]¼€îqs¨é%¹åÛ`£Z ’\ÞÍ­œì Y¹B×Ó„<ïx?ì¸34^•¦MDñºíUßUÊg¶r¦àõÄ#gŠþÐ5ûc£<Άa´ŽœâÆÑË]ç<{é?õ­'¾»ëà€IEND®B`‚drpython-3.11.1/bitmaps/16/Undo.png0000644000175000017500000000125611150445515017557 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  @¾áAtIMEÔ 7*2¤jÊ;IDATxœ¥’ÏK“qÇ_{öÌg›¸šF˜=ÓŠA8ºE‡G„D ‚uRxõÒmóÖ?µSt°C‡!1£ÔD(=Þ„§.Øt3n>>>›Ï¶6Ë0wèsü~Þß×çýþðÿ,K5½=ì¹Óy=ßÜ”3ÛùÙ¹‘îç'ƒã²µÁIhe–—2~¦zS­}oå„¥.h8]ê\P[ ?Ö©I­¦]2¢Pš}-Šï†G” yYtGŠž«<-@¶6Àjå°©I.9Ï*:@Ó ìé‡G/>É<œ‰¼­JÑ,b µfš¾e±Ï/Ëå…¦FùöàıtÃD7Ì_¡„-×!½†¸¸2ÞtçG{“Ft TodÁ&MhˆGL4Ó õ ®xÒkÔÄãA#:ú{©œ"Û@Q´þްo˜è¢e„ôb2:í3@R;rj3Oî@ßÕòûØJy, ®€Ô?]–ú§ËRÏǘ½=,Üô>rP{´}ÊEõ8‚n˜äÅ"v›Üî‹;»Š¹¾¥t ާ¾l p^¢þ ËÈ“»¡ uÍfÍýÓcO¦ÕWÛæž¾‹m;ëd‡–ű—óWúU/1<¹â}=±ôâsÖÙUr8p­~Wo^–ü3Ã÷RUáÉïËñĘš“|eQĖɨ…©î¶?5ÂY€Ù¯é€º…¯äp`ËdTAÓügéO­K=b5£±õÅj€uÍ–ÍŸïïê“G)è¥IEND®B`‚drpython-3.11.1/bitmaps/16/Exit.png0000644000175000017500000000174311150445515017564 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<uIDATxÚbüÿÿ?% €X@ÄJFF1øƒ 3S>¯‚¼?¼¼È¿?Þ=|øîųçÛ¾þþÓTsùTm;Ðr€bA6 (˜.cfܧž—Ç%áäÌðæÅ †¯Þ0ˆþÿ#þôÀþÄSë7Ä^»u·¨´b@ øá¥k„Ì0š>“EDŒáÓ£G ÷/]eøûë' ++ƒ‚¹ƒ¿ ïêU‡Î_iëÄ ƒ%ŒŒZ’æ¦gí7oæ`gxwñ"Ã÷þ‹Š‚ ÿ¶~=7Pï¿ÿ \ß1,ݾýï¥ç/Íúþÿ?@L`Ss4‹ Àšï¬]ËðàìY†§§N10ýÏôëÃë§OÞèë3ܹw—áïË7 VRÒÌÀpªé °¼2ââ¿^3¼ß¿“á3ƒŠ‹ ÃÓ' ¿30þýËðÿÉÁÔ4†{W.1°üûÁ ÀÃã Ò @à0à’’þ·m ËûŸ$6ìfx³fƒ´°( 33ƒä—¯ /;;dººŽ 1p=¾ÇÀËÊÂÒ @`þýöóËwF6†ÿ@'ÿ=}‚éÿ?†Ÿ×o‚ƒøÿ·O ?Nœ`øûý›‚ÃÏ[ÀÀåàÇ@ øðîÃûŸŠ²bÌO_30 0üyóŽáÑÎm wodøó›áëÛ¯ BÖ¶ ,<| ÿ_¾døÏÈÄðá×ïo ½ƒ×O_l{ÃÄÃÀòöï#ÇÄ[;XÅ¥~<ÿÊðíÍWn!¥în†Ÿ7®1|»xŽá';ó?‚ô8»õ´ÕÏZ+‹²|¹õŒArÐv^.†¯ë73ü"ŸŸ+Ã//†Ÿn3œd`úwñóWÛeÿÿ &¨?.ݸz³âì³/ ¬"Ü /üÝ~-[ÎÀmlÈÀkaÆð}ëf†kv ¿ïÞb¸ÅÄÂpáó×6 žã ½vÁ`^ø 4è©%%ù656F>`fùûáߟ¿ Ÿ¿~gx L7€~¿ðå[0q5³Ó×B ^€‚ þÎÀ`ÂÌÎ^*ÄÁîÎÎðç/Ð þþÿöê÷ïýÿüí:ù#P+ƒ  FJ³3@€ÖÁc튢BIEND®B`‚drpython-3.11.1/bitmaps/16/Close All Other Documents.png0000644000175000017500000000137011150445515023371 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  ’ù¥tIMEÔ *ñËâ…IDATxœÅ“ÍK”qÇ?¿—]sWÝmÛÖÂ]ž@ÄuK"¨ Šè’D„éÒ­S§þ¡S×.Ý  QQ„$È"hn˜/`k¶­i¾ô¸¹®û<ûü:lörÉc_˜f¾ß™ÿmbÇI¥R2™Lú,Ë’ÿj0ÆÏç½L&Sžœœ4 ‘Hˆ¦¦¦x4=‡ì6ÕqœõD"ñ\)µ¬,ËŠtuuÝîì켋ÅÔnÅb‘¾¾¾étºG¢¹¹9 …Ú”RÊ¶í¿«¥DH‰çºÕÐçƒJ…x<žÌd2ûu5çÓRJßÖÖÖê0†âÜ›SS8ËËø©O¥B(Ï¿PJ ­5®ëb0Žëà|Ȳ18HCc#ÑÖV6æçù:0€ÓÖ&„ãÝÝs¡f16ÚòVø÷çú9¾ˆŒÁÂ8¬(ÿŒ¦á2íCIEND®B`‚drpython-3.11.1/bitmaps/16/Toggle Source Browser.png0000644000175000017500000000105611150445515022716 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  ’ù¥tIMEÔ 17ø¡•»IDATxœÅ‘1HqÅIþ—4ׇ6Ö¡P…"‰¥‹E´íPB7'·‚»8ªƒzÞ®ƒqQKi!‰hÓ‹m!…XOÉÝ…9c E }ðñ‡ï½ÿû>ø'ð)·ð)ÞëH…õ¶O€qüŠd€;üâ>Él8¢êU ìŠ\à¦[N‡$ç%Èòجjà$‡B“ì›èKƒô >{äz÷ö=óSŸCA<¦AGê¸6²ðéyÀÒ;v ^Ü85á8ŒR ¸67Ð`M=àEƒÀv::¦4ùGº6–ö·vWoH'Zàp`’°P Ug+*HäK„LfGKe^j©õû¢þe;87GÔ,𣚨Â@”àW<ÀCÀn1ލ‡—ü ‡ \­¾W·ÃÐÕÓé]ni®w}ÿ#ñ!ù"dÅ4ju§êÖS·¥5ìÙL'¹^`àq»—á¡Vº;Ï‚3[!(ÖŒ°ÛÚjüÍýß¾&ÙÜÐIĘ$ ¨+*”£‘D,º¶ÿ:¶î†nD¯²Ìÿ‡¿»~Õ¿PIEND®B`‚drpython-3.11.1/bitmaps/16/Save Prompt Output To File.png0000644000175000017500000000134211150445515023472 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs íÀ,tIMEÕ(déVPoIDATÓ•’ËoMaÅßy¸Ô½mÑÛ¢ ¯!I„‰t`fä¿c3‰‰&Á ñº¨z¤%Jï#=mÏ}ŸsÏù¾m Å’XÉÎÊNvvÖ^{©ðÑY™Ï›Óç¢ :wåëÿšj\Ø.zÍ.ê­DñÃTµxs,‡Ê¬&Ý;€Æ@__0 "ˆ@;l4›¾RÒvfÔé«¶“J­Û¼Õ^¾v ¥8Gœ"èÞBfÃ0&™¥Ûxc0F# ¼ØÛãžU|VX¶-¬Ìöö7Þ³&J[˜ …´Z´{6ríñ òß&ÈOO/L’/L25[bÊì}NÕ2CG¾¨î8ÿ°@We «ô–dÅÁ‡H¾¬4ÔžÓdZ*|ÒS^‘¡í8‹n¬[¿—ܪ,å!—_Ü¢g®ÎàÌs’ã“Ì݇ÖÖLsžŒvc~-PÊ&‘LsìÄIŠ¥QZͶRıð:¼ƒÔðÃ:^P¡Ø˜£ÇY‹‘ß,"Œ!ÓÛO²"ý£æ'®SnÎ1ÓôñÃ:‚`ŒîT`Ùƒ\½xûçû ` ¾Z2'ˆ(ªÕ,OUÿœ\:E âHÈ¿Œ8|(GjD4–%h­ùü—v(H,SŒŽf¹{¿B&c³g·ƒëÆÜö7K˜Xo&?EôõYÄÚÆuatÅðã„Vw­ì<á_8¾yøË;@€˜ÏZû;S©ˆRÑ%jW‰c‡bÁÆu5ß=Akƒ1†YÏP.[¤»âÈÂ{íe£›gÚ­1¿?'Ü»ëR¯jÚ-…ïR€$0bFC¨Õõ–ú*&ué;LrèW¥EÉIEND®B`‚drpython-3.11.1/bitmaps/16/Print File.png0000644000175000017500000000177411150445515020613 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<ŽIDATxÚbôðˆf€ß¿3˜™Ì ñrÿüÿÿH12022‚h–-[vo9vìd4Û?˜€bùõë7”ùŸáÇ ||¼ÂFFz< XÀñãgD€j˜þ Äòÿÿ;ffn&&^VVF ¥þýûä3Ä¡˜,ÇÆÆõŸ……ƒáׯ÷@þ7€b‚(úÂÀÆ¢iŽ_0!4ƒäþ-àøýïßï?¬¬¿š¿ñ€b9åïß@ü–áíÛ›Âÿÿÿ’Á´ý/8,þÿÿ-õòå5™Ÿ?_ÕCĈè\N>>¾x99…@##KUi)qùï?~½õè†ß@%@ƒø#ƒ˜¨Q``ȱ¯_¾Ü~ðàᦟÞÍ  ©ºììü ]=†ïß¾0;“áÚÓ¯ lŒ L@›ÿ bbøõØ\‚Œ1QI²\¼|²wîÜtš?o†&@±˜››EZXš3üþù“áí·¯ â² ï9ù~üþÏðáç†Ï¿~ýÆÐf ¿d¿|`xôõ-ƒˆ´4ƒ©¡y@±()) °²00üøü“á˯ '¾ 3\»ÄÄpç=Ãç?ÿþý‡¦ þò5}gÐ``æàcPPVä –÷ï¿1>}úŽ—ýÃÇ? ës2Ü{xFF( ¡>þãbx«Áà ÀËÊðâÆÏ_~ý –wï>ý»zõ!ÐÏÀpgábÈPøÍðMŽáÛ_f 7 Ù.ädýËÀËô 芟 §.|eøþ“¨— €Xÿ~xôèúµS¹Y88ØX€Aǵ€ì—ÀT»äÃw_ÿ(UM†»wÿ –ïß?½”–üñã=ƒ˜¸ƒ½-//0¥ý'¥ÿÀTù˜™™€yåÃáÇÄa ##ÆðíÛ§wÄòàÁݹ7o^êãŠOcÐÒRdê*þ N`þ€ð_ þL¥¬ JJ:àDvçΕï÷îÝZ@ÌŠŠ çŒ³W¯Þe°··Òãããj&" ­ <ŒAÉ›••™aæÌyÛ÷íÛ]þõëûÅ PRãØÎÊÊiýñã‡/_¾|þ Ë  Üüÿ?( ÿ³A€••…™‰‰õÙë×?6spp2j臠¢³èzIEND®B`‚drpython-3.11.1/bitmaps/16/modified.png0000644000175000017500000000106211150445515020425 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕ"§ÎÚl¿IDATÓ¥“1k”A†ŸÙû‡à ©D°P°ÿ€øü ¶iôïØXÙhgie@ѨIÄxzÞåvg^‹ï»»ï$]–ÙÙygöÛÛÛã<«8xúìAÿÆÍçãk» #$\ A„jœŸ?ðûàýÛ'oWk[ú»×)Wvpî"²ƒ\‹hÖÈ/¾ÏÕ‹—o-2¨Å…Má!A„a– H˜fF²„½ÛÂmÌ ©D`VÇJ©vœËùyb •%€$PÔ0áÿŽmx,L¢œù,]áÈ[UP%VŒ™î¾Z»4wU‰ G¬¿|¹ œQ)È£–ÅÁGîts¡D´¥púé+'ƒKtRª_ªk½:ê¯?øÑOú½u¬ÓAmˆ€\ „îÞÁ¶ô¶6YOö?’k¼öÒœGáL§SÊ‹×äoG”R;tI˜Ü)M_Ö$(ÏPhAX¸“s^ÁzC xÀ‚úO¡ºQÞ§ª*Ô0‰ §@¢=L¹Ì^ý ïyd8:¦Ó­PZ•³“!c 3ĈÙ÷mÀÎ;Îÿåš«e»mqIEND®B`‚drpython-3.11.1/bitmaps/16/Insert Regular Expression.png0000644000175000017500000000134511150445515023617 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs íÀ,tIMEÔ -ÓW+rIDATxœe“KOQ†Ÿ™Þèeˆ€I€`¨xK%UIŒ£ 7€Ñ•¿ÀøL\»péNÔ¨1¢ÈÂ1Š D …BZJi¡…^¦s9.¦×ð%'sæÌùžyßï;G¸{ïéE·ÛõÍívQ‚£!¤’iºó¯ÒØ+üC½ƒƒHRm£¦Ȳõn Ð4˜ú8IÏ÷û†úÚª€fÅÃÉþ㸜µ¿¥2ÖSñ‚!À‚x$ÌÙ¦Î_îïn-E¨`˜Ö¨(0Lk]3@5—amü1þžvÚ !¤Øt `˜H[2VbI³,ì@>±Âî×'ûZð.ÀÆ$%C­$ Ú[Áå(Ë5­D!½” zÆP—ßÁ2">MQ×XÛ±ÕYPTA7,†i)pxR³tµ)xSsûLQ5øµ/ÿÊÙ@®hI®T\-7ÅݬPHzѶ—ÐU•m‰±[vb÷Uø¼`·×,øR1g³˜c/ô5fc#íæÍ²Waíy"“{×h¡²^.¤¡áÕÓØô<©Õ0‹ÑM¢ ™ùÖ• 8›Cßͽ¹¥*À¯³ ewhÎFØ\YäçY¦"v9FàÖ#:ö /"Ñè\¼fp{@¶aèÌL¼¦##Zå÷æ>¾37¸9rOc“´´tZÃA*¨V;ãóK*-8¸ÂÈs ^µŠ«YûŽ& 5ÐËg~y‹áQNôè÷#ÙeŒr{1iˆ€$[#põ6.‚$œ„ÍJ6ËÝ:P‹*ÿÖ¶˜ùâ@¢î‹Æ+]™'·“Õµÿ¼{;Æ6f;ìIEND®B`‚drpython-3.11.1/bitmaps/16/Indent.png0000644000175000017500000000167011150445515020073 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  ’ù¥tIMEÔ -CèºEIDATxœU‘ËKœgÅÏ{ûfœu:3f’ˆ3ÎŒ1J5‚šHÝ…”º¥k‘n\ -”Ò]¡Pè¦ÐUÿ ´‹7¥Å4iBK‹ô2QC¦Öñ2ã§ó]üÞ[*M<œÕïá<ç!ø¿(€.i€qÎ]ÆØ¡RÊÕZ›s€¼ }.”J¥øÌÌLOEzoo/¨×ëA£ÑPŒ1KÙwçÙÆÆ†|qðr¥RÉÌÎÎö–ËåœëºÞãÇ­9Ï{¾èûëkBJ¡a )åa.—û±Z­Fì,v±R©\\XX¸288˜w]÷xeeå¹”™W^{õΛÍv­··ó —ËÑl6k“Éd"Š"111±Ïtè™››ë+ ÙF£Ñ\^^þ+KJ)î¼~³'™L~úÓÏßÞ+?@)e}ßÏK)@¦T*%ŒÉŽ/-mÞ<:ò÷€ýS“—Ñÿ¶ šæ'Ë 5˰O‡ÊïÐ×䣰qò`ÿˆfÆJ@9ê0 Á p½½¥¹uØ1_wR¶k*µG!Ö úóàQ ØfᩦƒÀæ¬u/©o.ÂPIc\ŠÂŠFË)Ò¿y±ºna_ˆðº ^å*'{øGª5š$(ˆ›hèVÑ+íÔäo¥÷q3Á)®ÍwS]ÂÁãyìi.À’“•àAœ@W`¨ÉÙVJO·²][þŠ©X¡dZšy1¢ƒS’ü8ù¼b€ ´µï|õv_w$Ì$6×?!!ùNîu\ºðXö&t_„ ¤IEND®B`‚drpython-3.11.1/bitmaps/16/Expand All.png0000644000175000017500000000054411150445515020561 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ ,ÞMý%ñIDATxœ­½ÁPÅnÛA¤Ñ˜½‚Ýh’X¼€Ù`1 –f/`4í^Ád`"  U±¸—jŠ3›“ÿ¹çø €ÁtÓª1oýFi¤ßU ù¬^¯gç@ÒÌ „f2QögçÄ|b3ŸØÊ( z”p¹¸ì×KÅ£™àS¨²³üÍ9îðÜWºáÛDÈÎ2¶çº¶+fãšaP(W¨µº¤Òù?WHšj­®¯ÂlÜ Þbf-_…€šŠ%!c›Y‹t®šà‚nP(Wm 7‘üÁâUÛ䛯põÌOµÛbÃIEND®B`‚drpython-3.11.1/bitmaps/16/Toggle Prompt.png0000644000175000017500000000115211150445515021330 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<üIDATxÚbüÿÿ?% €X""œäCBâ@Að?$6Bhÿù‹§ˆÈP Šmøÿï/ÿÿ€ø/P„ñq‰ƒè çˆË°¢ ³·®bà`ecò€ø”þÏðΆÒ@W°r2xi˜0üùó‡ €Xþý þexüå-C^@ ÇŸ_Ððg(ýáÈËËŸ j†`Ãî‚?ÿþ0¼‡)þÍ~ýí=ß_Vˆ¾ÿ ÄóÏo?>CðOdü.þúû†ç_ß10³°‚m@, SÀ.øû‡áçßß`…èÞxùíÐæ`6P58úÀ 4 €X@QrÈšBò ÿ¾~g8üæ"Õ·÷¾üþÎðãÏ/¬ñó@Á½ðå×w†Ÿ?¿3{sƒ™‰™a–kƒ6Ÿ,ÎŽV åÄóÂ+ 37=:ÉcÄÀËÆÅðîÝ+†_>à4øÄO$@Áß_¾0ä¯ib8þë Æ;‡ñ&a°>  ˆIf^ w?½dPUgPeP‡$]±`„Lÿgâ¦Ìÿ ÄIžÿœU q&]ìÉ$@ ¼ð`ÆŒI“ýúÅÉ0H™‡á?Zf‚²¡.9qúü€b¤4;õ¬ü‘òmª|IEND®B`‚drpython-3.11.1/bitmaps/16/View WxWidgets Docs.png0000644000175000017500000000145111150445515022340 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs··[AtIMEÔ222ô¶IDATxÚ“_H“QÆûömÎ}º?šŠ•™Ya”I%ʈ YuÑ}DHWEBÝug E]„Tƒ¢îLè‘aÔÈJ£´Úf[ÛÚöÍ}Û¾sºØœQõܼ‡ÎsÞçyÏc‘R2cÇ·vw·?©­©F”Ú„¼yý9œ‰‹D£÷ýþþ€ÊèêZÅŠÖF„ ˜¢H/òyY³ª¥åìè賂Ï7pÏïï—Êï—U›]‰§,L}…p2Y0%d±Ú*T6ïìèØ½gÛP•¦íõùlå G¤µ½Ç·ï[ÜN0!‰…%cŽ£‡4 $˜BððÁ+ŒœYçñºÏ¤uýs™àeD*ä+?ÎØs:O'‚LÌLpø`/B‚´(lÙÞIh2„Ón‡»ùæí»ëË.¶On²Å“K¿ÌüàÑÛ /¦? Ç§0eéõRuºÝTjî²jUo¤¶ö´†µgY2ªM­è‰Žd€Ê„(nb¾¦ã?ŠîÎ3ˆ±±^árõæižzËãwY„£•EöMM“ŒôÓ¶tvÕ…” yê°i I ô@€¼aŽF |¡z¨Ž mÏqfk…t®<ºÄ©}4x] ©D”§P³ét"gdÓi]¯J™’`,ˆøE|›%ò&ëF!¿ ÁY]âÉ'”ú±± ©X|GÄÈ]Öë[¯a.&*~Ÿ õ)‡LÚ0 EMsz 3+{ ¬™žϘâ¤Ú}ôúÕçØìíÃ6ç¦Å»Ž‡Îãq7 J[°;< zLœ?ôE¿§GŽæ:ëzØÛ|„ý-<ËqTT•>Q‘ küD­XXÄ_Y0砆宵D¦˜Y2Nó,FQÀ"$ÉЫwnY­ÖJþlÖHqËïqðù¼@5ÿ‡ü/X\WÁ“ñ9IIEND®B`‚drpython-3.11.1/bitmaps/16/Print Setup.png0000644000175000017500000000174011150445515021025 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDùC» pHYs  šœtIMEÕÍ vmIDATÓm“]L[uÅ·½…mi®+mé¨ÑéãÄ%èŒ3q†,ó#1{1$.чéââÃ\Œ§A–À2ç^H`ºâtê`‹#¸96t[È™Pô¶½½÷öþ}@Œ1žä¼œäwÎÓ‘::ö°.]ש¯ßµkG'`! I’I½¼§  À\gdMÓ‰FË~VÕôÝÁƒííÍe[¶Ô9ø])WUÕ*I’ ÒZK¤”’åÃ|òZ0 Á‚išX,ÀòÛ†ÅB–íhÚ2Bd°€Áì̵·º¿ø|¬ººfÛÔÔõMk{â_°˜ØlvÝ4uÃfÓ"p¹\wf¦¯4ž;7øv,Û622òŸõ< !„^qÿþ@.·@>¿–YC¡P‘ÓéÜW…ÂÏʲÕJiÒbržÊpÓÔÉ ¼!HÜ[ôy<¥/•ºÜÏ©jΓÍe&¥ÎÎÝvuí{§¦¶ŽlFatâÙl%9£¼ŒÇƒl“) F‰ßœ¡&â§Øébvö_èí“êw?µµ=—#™Iƒ7ˆ¯"H|â2óÃgq%âü’“ñ€b ò€¹t’r¿Ÿ'77¼`‰F#n› y-‡¢™\J»9rͱ›¥¸¿?{tÎ?—¾]rþèÑ£k/^¼¸èÈ ¯‹—¼¼ó«¯_ß2°±}çäççÐcggßðäÉ…ÛÏŸsÇZZêLÙ»÷ÁÂ5kÊ_½zuèì;èi €JÌÌ–ÿ(/ÿÿ =ýÿuW×ÿ®ÜÜ|¼¼v{BCïïut|+ÅÂŒ/%ƒª¾>›µ°p^¢¼ü\IOqcii/þ··ÿŸ¨©yK^VVŸ~€bÐ25…³5ÔÕ…ö&&>¿žžþ­ÍÀàÄÛ  ?SUUÏ¥Øqé ¤Ì¤ÉÍꤩ)5ašå¯_Ç(ñòž”þÿ_(ÅÄ?±@, Do~ÿ¾ùôÑ#†IŽŽA±·nÝ–üôI6êÑ£l Ôg\. ff`2þòé˜Ã.&öàà•+ŸØ¿Wþúùóÿ¢Û·ë¯ÿú5_<*0¾«îÏIEND®B`‚drpython-3.11.1/bitmaps/16/View In Right Panel.png0000644000175000017500000000056311150445515022171 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs ?@"ÈtIMEÔ ±KIDATxÚÅ“¿JAÆ»Y’t´!ÅU>‚baRÆÊDZJi!ˆØùú!$r¶ÞÞŒÅí’[rç¿N5ÅÎ|¿ùøÖ¨*‡”åÀr±™N®4ËF ™ŠÞ^Ÿ8.“¡—í˜ùí…IdÙˆÙÙ Ö(” ›5<^ßs~|—,¸|>Ý'@Á:èt«^0¿8A©” ê¥B“¿jûˆí7†$,õÓCM¯@@ AÕ|CàŠWä÷ ÕÄèÀ H“5ü$‰‘ â—ÂÞ Þ ¾ Pð e5,1 õÇþ½}Áb±âfþP‰eñoÇIòb”c™ÿŸÜSŽ T/}@IEND®B`‚drpython-3.11.1/bitmaps/16/Customize Shortcuts.png0000644000175000017500000000132311150445515022606 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<eIDATxÚbüÿÿ?ƒµuv¿““a3üÿ÷ï#ûŸÄFF1yx¸;tkÆy~ı·×ψŽvãxñâ=ÃÝ»dd¤>~|4…AJJŠáÏŸ? 0²ŸŸ—AMMVkÿþuU6€——“¾}ûÁpùò5†?~0|úôŽAZZlÈß¿ÿàØVy€ðë×ïÿ\\ì _¿~ePTT`xùòPÓO%%9V BFpqqÕüzïÿ€b ƒ<tö'y “¿3<{ö‘AHH,ËÄÄŒb ˜a€ (3Aš…„øy€^ø´™™ ¨°²2ƒiÅ6¤™‰‰AAA ¬ŸŸè&†ß¿¢h†ó@f ÌT˜™A~e› ,VVlà00Ü L@'€401ýc XX˜À.€‚rÈi@4dHÈ6àçÏß`ÿ óýßP î?)ó?@Á xþüÇl 4AÐvv`”ÀÈ@Ð@d`x÷î ÃÙ³wÀÑÉØH“¹¹6X34%þa¸qã%Ãû÷?þýCV ‹{¤„ ¼›7_-üŠ5&€pãÆ¹ll¼:ll¬`¡€nßþÌtg€Iÿãu€b…¤””šêÏŸßÚØÙÙ¥€üßè eeä Öwï^ÞøöíK@€©­ýjdf”IEND®B`‚drpython-3.11.1/bitmaps/16/View In Left Panel.png0000644000175000017500000000053211150445515022002 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs ?@"ÈtIMEÔ ;5÷ÑçIDATxÚÅ“=n1…¿Eä´‘Ž$ç@H”(Uš(G ÌP$:Š='@” lKE…Ö~;`ŠŸ#=ËòhÞ<Ÿ#I<Œêa3è}«U[ŠòÔ|ûF󵞟ْ$)ãÏèA«¶âë}¨`¸lÓÿèà^í`2Š‹ ¡Ìˆ€ÀƒÞ™’{g ÀÉàsœ2ToXafÅ^%_A„·9ˆ ¼Bw'ðþÂ3^“àN Ãý ήpnÜÒ (; ´³Î ö(,6 ~fÝÁz›ÿÆÁÊÀz™Ã>ý7îÞžíIIEND®B`‚drpython-3.11.1/bitmaps/16/Check Syntax.png0000644000175000017500000000151311150445515021132 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÔ 4©GëÐØIDATÓ]“ÏoTUÇ?ïǼ7Ói§„i™BC« Qˆ!Ä "qÁJ7FݸñÇ‚h¢ÿCHظ×6BÂB£!¶–¢m!CµŠÄÖ™yïͼ7oæÍ=‡ÅL-pr“ï=ÉÉù~rî=À…K߆†gPãˆ(ªŠˆ *ˆÒÏEÁ(æá_ËsŸ|øþªûõù 9¯4òöîÏ|j[j«€¢ôŽ¢ ¢}è*ò]µzæøk'¾tØ1QÙTHLÂb°È¡ò!DAÌSj9Þ ªZ´y*®F³|ûßù>E¯Xúúx¾îú¥a"æ‚Y~ËþÅœâ½[3ås¤4ÃòÁ'Dz `¯]  egÔM™PËä‡öqŸëµùÿB» ­.Ä  °Fs~lͱš÷ÀrèfjÅøf#°?¤äV±{ë­VbeIäl©±«ú^óoÜt…éÄç{xuË :¾úã,·£›óØÜg'&OV¶¾!Z`ÚÙO{ ó|´÷4k­5ÃE~ æé*³éeÔrÏíÜhàù…wÇ·Ž‹ÔÔJíyŽû£d.?¸È-ûâ“÷÷à»EþÔë„qs£²l‡ j'y¯@ÉßD» µ¬F§ì¢¶OêD‘S‡Z|(÷f¦É\³™¨ô¿`ÚŠQËÂ(ì*Àª¯„×ðí¹:µz—ü×7~_ºóY5L†¶Uwº†|t•Bp›vásöo>Â^9J#kòÅýwØW:ÊÉá0\ë8~~9v†ïŒoŸdrjÛ¦²y¤€{ïY㌂ï òrî$3oaxòìR©”å¼üZj hŸ†ÿ"w½S«Ikù"Õ°A-hðJñMHòAD=ˆ4Kã ŠBã;‹¾ùeáW¯Ä"‚Á^óg•lå "ŠhoE#*K ?_º·´?hÔ’-ŽOò¼IEND®B`‚drpython-3.11.1/bitmaps/16/View In Top Panel.png0000644000175000017500000000051111150445515021647 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs ?@"ÈtIMEÔ ðÝU ÖIDATxÚÅ“1 Â@EßJ¼@Zí¼žC,K ±`%^@¬,‹Äˆe4i­¬$Ùo± ÑAPp`ؘÿø3ËI|5¾ /¿LFsuüËG¢ÓµÉz·4/€ŽaÖÛX†¿áwŒ÷ÇW8Þº,Î}0 @r§ °¸S‚èW­vƒñtuH©u™Ø§Z ;›  ×@Ö˜ØòЛr»RIXJ²ÑªÉlêÄVYÚl¹8yã c¶ëÀÑU¸‚Âv^Gçb‰æï¿ñ Ù¿i7ÛMIEND®B`‚drpython-3.11.1/bitmaps/16/Find Previous.png0000644000175000017500000000117611150445515021330 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDùC» pHYs  šœtIMEÕ)2#³÷³ IDATÓ’OH“aÇ?ï¶VÛÊŒcÍ`°1F^¬ :T—èB¡‹‚"J3¢C;„· èÒhÒ…Ž-ªÙ%¤Id™97æ6÷¾ÏÓa¾¯ï´Y?xx~ü¾Ÿçù}¬²){ëÕØhín¿vá\Ì·Ý@×P°¦hðÕg))«ëë\‘þëI?³-×Dº:ÃøzäÆ-kn9s$€BBfú¯ä›€1 €oˆÍ‹r@Zíue×n¢ÞRTazÁPÞv÷e®–ëÚ›wpþtãÉtU¬c»#·«Ôì+fÎe‹Ìf‹ì ø™ÊL£ÉzY5ìFø9Ö[9#_(©xlLÎ,¡‰Õÿ€ª9ºÛm>;ÉÌ"› ¥ ,¾çTünkí £4PT4Øàjdèõ8óÕ(Ì—cÉ÷¸=;kZ0^ðk¼›A“l óãçKî?|J¨¹U“¤’ øô„;Ä„£é/-ˆªX  h;|”À|–R 'OG„=ìÙôŒÒÔEvñ›of€Y¬ïΆFöˆ¹¥`±w³D¼£Ä/;/ GÖ±#)üGÍw•ú™•œª¶òbä •½‘³ŽAÅ4Å­€“ÿ kôTð˜w›+÷ÛÁø”1Ø)IEND®B`‚drpython-3.11.1/bitmaps/16/bookmark.png0000644000175000017500000000103311150445515020450 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDùC» pHYs íÀ,tIMEÔ°\9æ¨IDATxÚ¥“ÏKbQÇ¿šíž´jU³«VE Ä4­ßkõ*ƒìа Cgiá Êm!‰eQA»Úµ.&#^è8E÷Àÿq™”ËeY*•L¡Pÿ8çh4q¥R ···Èçóbff&—Édž§R©{·©FQtšÏç?*¥Z P(¤ÞÎÏÏ¿˜ššR·AÀÒÒÒûõõõ7Åb1•L&ç”RªÓéüÝ-%BJbk‡¥10ËåJ•Jå®Þ-¥4ý~ÿš;œ#ØÛãlw—¨ÕÀd³L”Ë!Tì܈PJ ­5öBå’ ¨Vé®®r'›%3; @wŸöò2ÑÜœQ$4@"‘Àó<Œ1Wà°Ùätq‘±Á€ÑtšA­À˜R„õ:ÁÚšˆz=©´Ö$ |ßâ•"<<$ÞØÀù>gBˆ?ž4øÕªïEQRcð}ŸÑÑÑ!1ôšMÆŽQ½®V­AœµÈ³3ÒÖŽg`J8ç\†çAôsHcˆ…¾”f$ %a84UˆcÁ@@(•Ífǧ§§{ž—rÎ)À•Žr/ëõW¬}ânìvàó ¼Ö€k·Ûýn·û0Î9 ˆŸÖî<µv²“¼úà:[°¼‡êâÎZ;°ÖFÖÚÐZ¶ãø¼ß&à‡#Ä/èÀæ'x÷V¾@WܘN\;0ò &KP¸¸|߀ƒM8qþtîÅ–“•ÊIEND®B`‚drpython-3.11.1/bitmaps/16/Last Document.png0000644000175000017500000000126211150445515021311 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ -#ûU(µ?IDATxœÅ’KOSQ…¿sî9½$½Òb±6Rhš2wbŒ3b0rîïpjâÐ_ààc¨C$ B$j¦XJ(½…–öÞÛãÀCw²“½³³ÖÞkgÁÿñ½(•J²X,ê|>/ÿ0ÆP«Õkkkýr¹l@.—SSS—R©ÔMß÷'ÿµ5 Ãf.—{fYÖ¾Èçócóóóçææî¥ÓiëOdžqƒ!êE,,,v*¼¶¾)0QÅQ…QõÏdxZ7-!Ù²“øÊF›A»ÂjõvŸ²(Žßõ w/{‹é‘W¤"Ñ©³³÷ŠÍãmÚ_½0ñ<.O(IEND®B`‚drpython-3.11.1/bitmaps/16/transparent.png0000644000175000017500000000076211150445515021214 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs íÀ,tIMEÕ$a`ÂÂIDATÓ¥“]+ƒaǛ׳gŸ‡ˆh+%o§ÛަÌ9Û9Å'àÀ›X9ÛΜP,&=²PjÅÍkñx¸œ-ìÁjWÝ÷ÿ¾îß}ýÿu›D„RªüëÆåšÄ¢(hÚ3ሯ(€ù§Ðf³ÒÙÞÅ wºø \®Éo¢­Ãå&ú<,Gýÿ,ŠB›Í @]m z5´t[©,«ÀáðOü дçüËz5¼W€˜¡©»àtŽ‹~Ï ñ±¾±F2±¢AÕ¼½BkO#ý½œÎqãD$¿<îóA•½S!u!] gYá$­³T±ÛǾõ‹‚Ý>ÆBPåà\g÷X8L gBæF‡T<îÀßÁáð³Úç$­sý$drBö^¸ÌósI¼Sù^³‘­X,ÀÒJ”ÄjŠ·'x|€‡|õ 5XÅ8#;áJöVx}¶6/™ýßBA°sI¶™‚ËEDïÀÃC3†g¦R£™ë’=ÃÚ¯ÏjIEND®B`‚drpython-3.11.1/bitmaps/16/View Python Docs.png0000644000175000017500000000131511150445515021673 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs¸¸jAõ[tIMEÔ2½‡ŸZIDATxÚu“]H“Q€Ÿ¹™éÒ©%j®t©Q“ÂÐl[¦D] Š„ ºkÝIFt¡a±%¨0-Ë‹ê"È‚†E êF¢dÓ¥–"NÑí;§‹o«túÞ¼?ç=Ïy8:)%qin¹[]Sc}³5; @JBòùSà÷äølóÌìì3¯·uÀÀ©ª*eWq>B€T¡"QA$"³K-–Ãþ¨ÓÙþÔëm•IkB‚šV¨¢RÓÉ)ueeõÇÜßb4žp:Û“ ëTÅañ¸¼~égyEÍÉÌ2]]‡‰ˆØËB³'B!†¼¤.‰ÃG°oïNjj-8l òõ[ÿ*¹×í&#š›Nó~ÄGšÉDªÑO7$mÔÂ×ñ³,…;0›Í”™¹yí ×[ŽþÍ_w=wÚ.¨‡éØ}væçç±Ùl¸\.:o»qº¸1à݈.›!´=„gÆßÀºÍŠû‰›.¿BZöž qcÈÒ€B ” ¢ÝhƒÞ‡·¨æ|"@ÐÝ;ˆ¸äà£ÑÇT^ì`(*5÷çoûús2¶®L*/ó]ü}^‚€(‚_3ºµ¡édÅ›‚çÈS ¨öUkw¹è_PøQ<€„5ªK 6¹Pà†A,‚\¹zÊ÷+Ø'c³9«*hlì,6e¤wèõúÔÿ¡Ss_¬cA~QΫT–õ`ªÓ†¹ àt¶géqd| jºd´GÝÍiX‚ÁA-®«Õu©îsÅãIEND®B`‚drpython-3.11.1/bitmaps/16/Open Imported Module.png0000644000175000017500000000104311150445515022517 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÕ%"ÍO °IDATÓ“1HqÆÿA0`@Ô­NA­KpªÉâRp¾\39utv/¤S²u)%: ½vë¤(“¦¥­åÐê=‡K.g¼+ýàÏqï}ß÷ÞÿÝ;ˆ‡HèD"àwDL…ž±øWÅG¹dL•8q4Ì"™óƒE9ß_”/ïf?œ”ÑøO(³Hfaeµ2¿²ª!ð÷êŸö¬«¯ÇNK7°z¯ ¥GÇ4<À·a“ž\ʤ'–ü¦½6Óƒ–]Ë”í|Ho%;IîÀmÚ´NÖK MùÜŸõ ÃsË·iÑú¼• ¼k—Ëã·<É–àö*U@ÄŸ›Rþ\Å1ƒÒ×ýCà$;óýÓ¨302(øŒš/‘F☚¡ù¾`éV¢ÓÁ·³CRšˆ“}t@ß ÎÇ tƒ<@ÀmÙÜx›ŽþVm#j Fר©ØA*ð½Qçé‹õ® Ûc~¯Âækç¡Áø³.C<Ó_¹lèÀA›™=G”Y$”:1c—\¹Hµ÷…]r¬/ƒŽÔ£õ–v@¢÷^¶ß ¼B¨vª{Gú¡† î4IEND®B`‚drpython-3.11.1/bitmaps/16/Go To.png0000644000175000017500000000115411150445515017557 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  À½¥ÚtIMEÔ1qù[ùIDATxÚ¥“]H“aÇç}ß¡ö5•>…´µ›‘£‹b]D7y!hT¸« ­« ºkK2‚`v¤4¢¨iV3ŠnÚ»ö®”¢°Õ¤Ú"ª™ÛÓÅ>Ë`àsõœ?çüÏ×ÿˆRŠÅ<£\G‘b[å2{[{ÿ)¡³«%º«y‹CDdô~§ÑÇ€ DdH]-ÑR‚&gƒ5÷Õkj\· d hUðí3„î2<¾¦9UWJ`šSØíkßÇb±£n¯¦ÎúJЖÁ½ã„õsP@¦0›mM²Ý½ó<ð2×cE$yc±€¾<¬UÁÖÝØ:^³Ñÿ€ç€’ñàÄ$€aèÖéé™@<žxäñºM`VD*Ÿ]ågý¶lpu}6ÙÛÇàïcÿ™a‚Z¾‚ùùt²±qUskÛvàÊãÉŒ\bìÖÆïþ¶ù)A °Ôè¿x§g­UlnÚ°Ç4͉É+®³‡ææ¾òjGO÷â Rpó?{Ÿu8í®Î uįû#/†BDà{aµuÕ)§³! ÄsÖL&ÐuýI^;€Tæì_J©ta º®­‚ÀhÓ4©§EäG±¥çÔx±‡Çë¾t—+q­𜼶ïþøÓ¾²oD)å]_t”K°¨sþ2¯Udúß IEND®B`‚drpython-3.11.1/bitmaps/16/Comment.png0000644000175000017500000000073511150445515020255 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ3YmO¤jIDATxÚ¥Ó?HQðß]ä âÙ¤ b‘êØ€!…Å"¤;¶Ð2éRAk B «€XZÆb›©Ò¬Á*’,Vgc!¤ „Hl.Í<õ®r`ùæß›7ó½Æ`0p™È‹z °]•Ùq^Ô‹XÃQUf;üæ˜Ã-¬â~…û%–ÑJs›cX@ýªÌ†ž§‰á ò¢~-C¯ñûáû¸ø³*³~:ƒ7qÇTzñ¥2,´Žk~à,â/ŽpöLØç‘zí É{ñ—Ãh÷^ØO±R•Ù—[kÌ‹ºƒûá{ú¦ÐÅ|lã*/êü®Êì2åÁ–BŸ |‡Ûxˆø¸¯ifcÇp±Ù°[ø:LÞdâN¬«‹=ôñ6b{áßÀIøú·x³xM|¬Êì]^ÔS¸ÀEUfÓ£×¼Aßn˜ßŸŒb߸ÇÔŽÖvñ-ñ#GJã®Ïù?½:cþ1çŒIEND®B`‚drpython-3.11.1/bitmaps/16/down.png0000644000175000017500000000072111150445515017615 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÔ(MC­^IDATxÚ¥“=H‚Q†Ÿûa¡ YaD[CеDC-:„PàƒD­-%ÑA”-en”äÔÐÑT`‘Z`RøÛÈmÉÏO´°¼párÎû¼÷ÜùBJI5K÷SÂ8°ˆ©¥•\N‹=‘ L—J)‹vÛ¨‡¥Ã;‚Ñ ]`tqJ0»¤ih¹D_ Û×98&ÏpI¨·I"ñ žÀ= Öµ"F}BM«ÝI4öÊe(šÖøNÃ( Ô×éèêwŠÏ³„”a°ü«“òíD(ùÃ`@,1ß ù ÔD%°–QòѾ™…JL@¿KÕ ÒÑ+†Ý[¿™€÷6éh°ÔŽòàê5ͦF¼ã6µWZxlÃGü%ÅÑD{iþÉ’™w»ûÚ[€coŸTö£.;ÊRJÌs~F7@o½›7Œeþ¸¬VTûª\_](Á=îø UIEND®B`‚drpython-3.11.1/bitmaps/16/End.png0000644000175000017500000000053311150445515017355 0ustar dktrkranzdktrkranz‰PNG  IHDR‘h6bKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÕ"-cøfJèIDATxœ•’1ŽÂ0Eÿ8ö"¡h ·â\„‚«PlË…è(X!ÇÎÌP؉²«x¿°<#?ÍŸ/“ªâYÛº^Îçdm &"e¾Þï»ÇÃXÌf›õÚ­VÂ4àœÜnûÃ!O€·-5Ä8 ˜Õ{a·ðsŸwr¹œíêêJ !øäädƒH蟟/ å|ß?[YÙônôÙ÷·nV±öp”J%7‘HB.+¥l§Óé—Rú @¶X,¦3õzýleeóµ[ï~òŇ³U„-@)òÆö¶ó!’B`-P(\û¥PðvÃ0 Þ^XX(•ËåôÚÚ_=µ>]º}· p qH  (ìlìàÉÖÚ““ùõv»Ýd¸µÖlmÕûß™žý|önNˆ$@R€å€Ö€@¬/;M&4“É0Î¹ÇØãããŽ1øçÍqk ”º<ŽÕ¥óÕ0öR N3Ƙ¥zS©c,¬Ÿ­=-3µÂÈuHq mÀÆ€‰Gç~2:}4>þú‘1¦ÍcA½^ïp³Ùpgcã·{­Vøå{ßÌËXúfé<›õž1Æ¥µÖš™™Íd2IµÖ>£”^B Bˆ$3<ìîúþö¿ÿzí»êt==]Oïß¿ó³çyi×u]¥”ðÕl6…ëº/¥TàºîQ§Óq£(¢06Ö½œî|ý`õÁ©µ€ÖÚj­c¥”ÖZ ­µðTký·£µ6Žã¼ „4‚ àJ)+¥4•JßžÕ/²ÖZ)¥Ž¢(ðEQ(¥B¬ŽŽ†@¯^q_OMM5²ÙlÀ9Wœs—RÊÇ1¦m­}n­ÝŠãxobbB\qÿd‡¶ÜÎŽã’IEND®B`‚drpython-3.11.1/bitmaps/16/unmodified.png0000644000175000017500000000077011150445515020775 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕↅIDATÓ¥“»nA…¿Öqœ82" (È @O% “!JJž!j9‚â\ììÌ9{±c‡*³Z­æòsæœÙ°Í]ÚàýÇÃ7Ov?<ØŸC¶±…»Ç¢)::žp8yûúá‹Àh4x÷èñ˜ÉýŒ,ŠÅÂhc×éïcFã{Ï{]Ûñ6²°0AD}ÿÇ^Ål’áFgtE±Ùj,-«6ÞZ°6fyÅDŠè'SJÿ…È | ±±°I÷Œ´8ŸÃ×ïŠ (2Òò+‹¢f÷\*켩`zš™ g¤”¨€ ØJ@‚Ëœž‰Áö˜±æîéOÌŸ ØßKìîlõÒ-8™%hÏ߆@êdu]óù›89+”²|mCTÈѯĈM)ݵuë´È9ß04Äîb_(¢5ªIâå³kªª¢V@‚2¸4r{@]>]],^9‹¿3¨Rj¯×’p~X×à õÕ/€¸ëïüø*9èúæ!IEND®B`‚drpython-3.11.1/bitmaps/16/Uppercase.png0000644000175000017500000000040611150445515020575 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ 73VÏ “IDATxœíÒ± Â@ …áOˆ RQ…*° °@` „X€6U(âH§#"”)ø%K'ÛïO>–Dƒ>‹}DžoFÑ:1¸`ƒ-nxFÀ*<¢w’:¹9gœ¤N“«žö•¿Á§Á¸¶ÝDo•õLRVuO ÿ£Z97Õ ^!jãÜEm–‡DØãŠcÔÆUr%áòñ]áIEND®B`‚drpython-3.11.1/bitmaps/16/Preferences.png0000644000175000017500000000213611150445515021111 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<ðIDATxÚbtuue`ddfPTT^ïààâÁÎÎÆrûö«W/Ûvöì©‚ÿÿÿ¿c11Q+++Q ï?ËÏŸ¿ÕÖ­[{ €X¾ÿÆóî݇/¿ÿû›Èamm R/ìèè[X˜¯yôèOVV–722Ò ¿ÿf`ffv355ï{ðà™4P]@1de劋KºÅË˧¬­c°lã¦ÿ¾}ÿõÖ®Ýö_HHd:33“¿¿ƒ‹‹Ã’%K¾{÷õBbÎ_&&æl€ ¬ýñøñ›ÿññi99¹Äut ·œ8qéÿŸ?ÿÿß¾óô¿™™õ}.OO7†²²Šé ¬üŸ”œó———Ð|ôË/A†ââ29vvöKœ\€4Ãû÷_¾}ýÁðïß?ssó?VVvsøøÄ’Ûڟܺu­¨y f11‰X]#a^.C#3nCc^vN†o¿þ2°³±2|ÿú•MPH8˜‡GÐ}Ú´ ÷îÞ½é Ô¸ˆ€ €˜<¸ó_@ÄGIY™‹“› hû—Ÿž]½Ì !Ê ¬¦ÂòõËwÉ™3'?»{÷–1+Û£ÿ2À@1ÿñãÒÅKg^?|üÈâͧ·=d¸µoƒØÓŒnßbøÀÍË`maÂÀË'ÄqãÚõ¬l,‡¾}ûÖÌÈÈÀ@@Y˜X™˜eÍXYåYÙæ•9Øýx¿`öÿ]¦ÆÿDÇþÿôõûÿ?ÿÿŸ5kñ_yy¥~˜í ˆ9úßm Vþÿÿ“Ú¿R áÁ%1Aþüovlc¸rö<£¼*ƒ…-'ƒ…¹£°¤ùõë×¥¾|þ¸åÏŸ¿ Äì4‰ ˆe„&„×Tô¹z{ð}ß´ŽaÙú ÿ'±qß—ö ç6ÐÖgþõó'##ƒ©‰£¸¸¬Ñ¥KTÞ¼y½ €˜õ@ÉNLtNLGK†ž¡.ó‡ÙSìÞËÐöõßÍ_¾Ø_½zá''·‹––>óß¿ž]h³Ð ”w¢ÒîÄp-ñ?¸–Á®DP)Š–"ŠHÝh0–”h &hrï33.nL[»hÕ/8ðÌ3s&rwþç$§o,-^¿Özpan€æŠZ˜DQ˜LŠ­µgYyùåM÷þâB03säÎ¥‹-ZÍu‚刢†X x~[F<{¾JãäÜù.K˜>EÌ_ØW9Ø)–Î>fóã Ã.øþ=Çâ(´°ŠÜµƒ3˜#;j á/êˆÚ6ÀÜÉõßIaà´¿GÜ{8$#%% F&6½çbäÁÈ‚&3'cåíR‡r¹L ¨O°1P^lÔ™mæPï5H¥ Þ¾\åíׄsÍÍÆÑ©öòëMžtcÔœ|‡A1Dw2QÔŒápÈ­eXkÇÓhPÊå2êŒ`´Šß#€ˆ0¦ªJµZÅ<`j„]-8dÁPuJ¥nö©T*{õzÏ~ º½7 @ú3}Úýüíj¤¼ïµZ IŠó©Ðþy:"!ïõº€FîNEpæîLNxú¯ÞÑ_]ÿ€Ì;7þS>½IEND®B`‚drpython-3.11.1/bitmaps/16/running.png0000644000175000017500000000115411150445515020327 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<þIDATxÚbüÿÿ?% €X"#œåƒCâ@Að?$6BhÿÅ‹§ˆåßÿ AA± ÿÿýeø÷ïÿªƒÐ >.q½`Ñ1€bùÿï?Xböš= l¬ ÿ˜€˜‘á?˜†°ÿý‡ÒP1~Ö_ žb ~ÿa °iÿÿ21ˆ Æ@ö( âÿ~Á]è —ˆìO !¿.ùÕðá'B#²! úõ7®¿,`= ׈ùçÏ?ˆ-øð æ—_XXXÁ¶ƒ, H@ýcøó÷?ï¿§";ùÕWˆf°ó¡Ñ T€b¸ä5a†?@޾b`¸þšáëo†°Ç?8F€Q @L°¨ùúë?ÃÏï §€š™&y20¨óãN@0Ì ¯¾þgØþ!͘—áí[ 7>ã6à?T@±À也@ ÅËÎý¾åþ$ ¶è€bùÆ{Y†ûo/2¨10¨0€’*Øx^%_-@$Éûž"ˆÿœtÅñ$Ý¿ °ÀFVŠF€yáÁŒ“&ÿúõ‹’a2ôÌe3@اÏ^Ü @Œ”fg€XÃd!^éIEND®B`‚drpython-3.11.1/bitmaps/16/Save As.png0000644000175000017500000000132311150445515020067 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs íÀ,tIMEÔ 1Ï/ð`IDATxœ•’MlLQ†Ÿsïv¦j¦2­– )!" ‰ˆb%µ¶²´³”ëJì$,,ĆD‚ÑŸ’¨I5Š¶Ú™¢t~nïÜ{~>‹*Z?‰gs'ï“ó½ßQqÿy+ ñrx¢O×ußµñ}üU^Ü"¶c;µ¨±øz¬R¼5˜GeWÒÔÚŽÎD@€Z%¤ôá㨈T‚:»Ï«Ø 2k6nò—vvS2yLÓjê-Ýd»váÒ9Œ…Ä‚vPx>Ì+7OÇQüØí>{ŧ“ ›ãòtk[8DG®N¦ÉÃÕ#$ŠH–­'q mA[˜*M34ðºSDí™ñ÷zh ÒÓ~áÑ$ÍåA¼Ò+Òå_´Ô—´Q—€ÄÁ§â4ÞÈò†ôºNkÊ/ƒù6Ö¬ÝK~EŽ©­1Wn³ìKUŸž‘.Œð>÷˜=ÇO¡Ýܨ﹥|ÓM;q’b©—h6ÄW c„´õ©0ß¿°ˆØ@¶µt ?æöÝ\‰FÀÉ_Jùxþ*®_º³`}NæV8ŒgßoÅY½P ¢¨Tr<é¯üóç(/ ›ËÐZ$0Zxñ\säpž8¶ˆX´Ü¹û3ã-~b-tŒ¼ÕLLZŒ•Å׿ñ›à €:âÞY;³-“Ñ”Š)tRÁ˜€â¤O*e1Ú ÁCZRAŒ³Id<¦œ=—Dƒ3myáþ½µŠ%‰3ŸA)@'Cai³"ŽÔ¸8}ùÙ†OKðŽ]§IEND®B`‚drpython-3.11.1/bitmaps/16/Customize Pop Up Menu.png0000644000175000017500000000152711150445515022606 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<éIDATxÚbüÿÿ?% €XÂÂÒEþüùÍËÈÈø™™™‰ Aü?þýâääȲµ1©àåãaúûçß6vvÆïßþoi©› @,**òg¤¤$„þþýû¢‘h.##Ø€ÿþþ}þü ·Ž¡.‹¸„(ÃÏŸ?ØÙ9Þ¿ûÈÀÂÂb@,–FrövæŒ_¿}c`diþÏðì«ÿ ÌLL@’‘aó¦ƒ 7Îex'ÌÉð÷ïv6†¯ßþ3üýó÷'@±Ü½uÿïÿ_?Y~þþÍÀÄÈ5ä ÉÌÈð÷3ÇwŸœä'1È3ÝšË ”ûËðšIŠƒ™ €XX1:ý?Îðó/HP;H'È~ 3Xþ32üâÏÿÞrÊ1òýaøó› (Æ,Èðá#@±ü`üþÿÛ ý@m@˜ Á d°0þôá/ËO†bÞ‹³1üüõ‡““áˇ¯ ÿ˜ˆå7_ÃgÕZ†?~AœÏÕt 3Ð4 Kþ¾½ÃÀðç3ß| ¿ÿ{õÏïÀ@fa VVÆŸ?þ3üøþâ|¨@ÈÄôŸ•…áÅ‹§ÿ7m\ÿ““¼Œ@MÀüÃôøñý›ÄòåËÿ_¿þšüì&&¸ÀQÊÊÂÌðúÕËß[·®ˆ ^bN¤tô €XDD„¥¥…¾ÿv,aBÃÈÀÅÅÍÀÃÃzÄ ar!Ð Äòúõ»ÿwï>†º€ êˆ7@®áââaøúõ'ˆÇ ÒÑÈw@±ÈÉI3é2|ûöá}$/psó0ìÝ+”ùÏ †€byöìåÿ“'3üúõêFx,@¼ÀÃðöí; “‘ ‘ñþ1@¼ÂÀ@Œ’’òm@ÚˆC›™™‰õË—OOß½{YxŠžˆ‘Òì `ŸÉüë¯i_IEND®B`‚drpython-3.11.1/bitmaps/16/Set Arguments.png0000644000175000017500000000113711150445515021331 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕ  9DNIìIDATÓÅ’½KjqÇ?Ñ"‚æ 5,lJì€88G`ý‚¤Nµ9:mA.Ž‚â 5(è A ‹&¾¡‹Mr!üîÐ ‡Ë¥ ÷Ùž·/Ÿ‡ï³!„ü ¤¯I»Ý&‰Ç™L&këՊÁ`ð½(~Çëë«…BâîîNÜÞÞŠëëkñöö&Êå²(‹B×uQ©TD0ÓéôsMÈŸB²,s||L&“akk‹‹‹ ªÕ*ù|›ÍF§ÓAUÕ5*ù f³™t:ÍÃÙL—ËE£Ñ@QÜn7;;;X­V¬V뺀$IèºN4E’$ÎÎÎP…Z­†Éd"c±Xxzz¢Ûí²¿¿ÀÆ?uáG§§§x½^þHxyy¡Õj±X,ǘÍfR©‡½½=r¹‡ŸÏÇîî.777F‰ÄA¡Pàðð““²Ù,‹Å‚F£ªª\]]‹Å˜Íf ‡CšÍ&Ëå’ÍÍM¦Ó)Ò|>§T*Ñl6©×ëÜßߣiv»¯×Ëûû;ƒIú¸Öétrpp@¿ßGÓ4¤ççg\.´Z-|>Ëå¿ßÀÑÑ———ŒF#dYf{{›^¯‡ÝnÇãñüÙÆd2É`0@–eÎÏÏ ßúÿÿ~Òâ[PËœ}IEND®B`‚drpython-3.11.1/bitmaps/16/Reload File.png0000644000175000017500000000121011150445515020706 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ /v³+!IDATxœ•’]H“QÇs_~¬zmk2š9VäG`E­""B ìƒnºì>ŠÊRIwBu‘Cˆby3rJ0Å”@4G-Ë`nmí=§‹wÎ-Ç þpxàùÿó?GG¾Îv÷9•+½-nÖo³¯e¯}Äjµ $%’T!˜šüf”#e6»•ƒ‡Zp»íääòÃÃï†8Ó~ƒ®štFõÇ—Æã¿=º¼Q€ªbš*) «BÓÝ×~žEž  H§3äþä|ÑÅØÈ&Bht6Ã`h€±ÙWüH®pçå5jM ÚOZËa4}å@*›áùÄ0÷ÇúHgSè« ¬eSè¶Jš¬~fJVâé$Ét¶#Ò»„³ÞÅíÓ Î˜Z~*AÍ”$ùÔZ“Ƕ]ø»Øïê ²B!´W) È MRjëÄ1,f}•y#äâëÿÍ`ÝA©Žæ/ýÁ›Ô×5pÜÓ­­(7–¨ª[¸|¬—‡oüDB ½íçðlm‡eÐëÍ8·ï!ù;€Cqá¶µråÔ#ŠUTp òŸG©ÙÁ½óOy¼Ê¾Æ.½šÿ`RVQäƒR%4Y=\ïÄek-ô„ÐTÖÁÏ•U>N|Â2»\@a'3±PÞ·/_7æ¦çÃsÓó=ügý¯õ­Ò =IEND®B`‚drpython-3.11.1/bitmaps/16/Restore File From Backup.png0000644000175000017500000000173011150445515023204 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ 0#9D©eIDATxœ]“OL[uÇ?ï÷^ûþ•Bÿ@ÒB7Â0À¦((¸)á°8]–©3;y1M<˜Ì³‰w½,fÆÄ,ñâÁÄÄeNLœ3Ñ1g¶¨0\Ù@ä_)¥íƒ–òÚ¾÷ó`fŒßÓ÷ðÉ÷ðI¾ ÿ‹•Dµz Á€â‘QÀöa[ªÌ7Jl•ç©ü—ו€ Ázì¨ÆZ_hOƧl;Ø!„¢ÕÜz­/Í·Ê?C/÷–È×¶ñÍ‚ø1‘ˆfÌsO_˜y.õxßq¥ÍŽ£*×á;ÜÎÞ¨÷Ó7_ï¬í_,.øßWVhhF =r(øêÑÑ#Þ|éô¡Ž!¢v'šª_z¤ã §ÆƒŠæ½xýæL´îì¯6÷XTí.ÔöQžêjûð̳çÓý‰P$Î6ÊÙs‹€$lÆ0&ˆºº^Ÿëu*Å€¢rW‹6"œlïŽõ ÷LRm”¸¶p‰jc¨ŠF‹a"s–‘䩨lË&œây·ÄUM19IéS';%†’8µ¢e‰–ó £»]|¥HR  ¥g°²Nwñ FZ@«ó‘ëmâæ7ÎΦÖl¢ã &ä%$!=¾OóãK‹Z8=¡þýâ õŸ1ã§´7-=šƒÁ€ðð)ùû Š¢˜‘ÈAjÔ’@ˆ¬"P¤(0b¡ÅÉó|B "!É"ª{jÉa>B²,cçõ3Z­6%àD8NÆ3rŒ4½Le9\ûÕû~+¦û´I³ÝÆ€éŸáº]úìš0Äè1Ü^Ü~×ù/˜CVžúÓIEND®B`‚drpython-3.11.1/bitmaps/16/Paste.png0000644000175000017500000000161711150445515017727 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<!IDATxÚA¾ÿÿÿÿ.üð øÿþû÷k8@PSXž÷þìüèÉçÖ¦¾e™Ïõ©ðþ ûüõ@ìÿýˆ…¸Ù:¥ù4Ùþÿþýå÷ouSí)>9NVF]õO: ›NÞîfýö4P˜ƒõÇ_f–o>ÜêÌ F þÅÈÿg d`xv‰aÇ;†&]=†_ªßþÿÍÀÌÈÈÀÄÍÊpïÀk†®ëÏâ400J2Ü\òŠAcÍF€‚¸€éïwöïÌ;ÿ„2lábxùòß»ß~²10üeº‚™í''Ãf_î·ÿü”.30s2ýi °L ¿þÝÿÊÌüX)Ÿ¡ÚY¡äÃM¦ÿ@͘þ3 abøÏøYP–aí¦‹ 7^¥1pÿûù¤ €ÀüabdøÏÆÆ Àö“A†‡…•W›øýA˜h(«"Ãÿ¯Áb6èJF.I  ;(R€nƒ¿@ ü?@üû/Ä1]& €‚t#‹ã/V° H¤dÀ?;þû„áûO Èÿ?`ß@ ø2¨”éß?° ˆú÷¢ù'Pó÷_ ÀP‚Ì”†Bœ @P/9LL¡ÿgÿ1äw°€ ^dºb@A 0pp1üûƶåLj¿@šÿ#0Èeÿ#ÐÅ¡á@ð@d`bfø ÔRøxÿ ®aŒ`Jóî…ÿÿ2üøÉÌðèÔ@9 å ¿¶ÿ„†É÷ŸL ÿ€¡ûˆ6à÷)V†ç¯0lÜt"#0”V‚0(&þüùÄ o13p}¸Á +ÎÆp‰c1€•…U@SŠ!œï&ów7€Y šþAÃJÿ(áÌÄ   Å𓙬 €ÀÄ»ËÏî1Ï_,Äðãß?~`HÀüüH€£ŒÿƒñƒßL ÷™˜}ò ¤ Àå+XJi‚µIEND®B`‚drpython-3.11.1/bitmaps/16/Lowercase.png0000644000175000017500000000040111150445515020565 0ustar dktrkranzdktrkranz‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  d_‘tIMEÔ -*‚‰ŽIDATxœÝÒ1 Â@…á ©,„T‚µ•ð^ÎÚä vvVVBÀBÁÂF‹¬°D–è"þð`ffø%æhpïhIj©ˆê 68cú¶¸å$©ß|âüK\±È5ã”eðBüCíýg(QiOú¤ ’¤>±«&6Ž°Â¨'õûž™/ò; jïÐvöIEND®B`‚drpython-3.11.1/bitmaps/uninstall.wizard.png0000644000175000017500000006121211150445515021732 0ustar dktrkranzdktrkranz‰PNG  IHDRª,Sè(óbKGDÿÿÿ ½§“ pHYs  šœtIMEÔ *+åOtEXtCommentCreated with The GIMPïd%n IDATxÚì½wœ\w}ïý>uzÝ™­ZmS—lI–-K²±å† `ìJ¨¹„À…n$Üä¹Ix^¯'Hnò$<Óœ‰)66r·bÙ²dKVYi{ïmúÌ™Sž?ÎÌì®´«.¹p>¯×ÑhÏœ9{Î{¾¿oûýFxàÉ‚…#G¯s‰Î%pä€êÈ‘ª#TGŽP9r@uä€êÈ‘ª#G¨ŽP9r@uäÈÕ‘ª#G—ZòkõÆÁÔtßä J6ššà;]·ƒÏM ÞZ/ÞˆDÍöçN9 ^…úŽé>BÝ=Dzâ™EÍ$ ¹EÇ]Ç|ס„OÌõÌ«*²qs‘Ö­.ZvÇœ;÷k&ár÷£¶ìù­{¾O¤ûU<³g?!Î|:ª ÑJ°e›Æ¶»Ü¬Üpî¢ê…kýþš¶G Ôߎhšç~Bœûé•,×lšãÆûݬ¹ÑïÜÍJærŒNŒ2>=E2“F+—ªòù©«ŠQ­Âçýz‚ºî'ËšŸ‹ÐÀ RÀÏÎÏ7÷‘KjY.Qcçæinù€—–k<¿¶pŽOOq ˜cÒJ† º°,ÀÄ0 4]Ã*æåÆXíʱÑ[dóªU„#Õo~PcÇ^`ë·¾@õ‘½ˆ¦IèE¾ð¬ªVŽÛ^,òç©k ï%µâ»²¼ý¾,w~"økhÏð ¿šqsŒzË"`p+2ª( ‰vbÇÂfÕ´,4Ý ¯Éèi­@N/˳Cf÷úÕT×4¾9AÝøàWÙøà×p%g*û ‡Y÷ñS{Í5•ý“ÇŽqìÿ‘;ÇÇy' \BPDt6®Jñ¾Ï¹h\+¿©M¦æøé°ÉóF U¦A[ äq©&`X`š`– ¦eÃj˜ö~­h’/IärÌòd EªrCÜšeçU[†^?AëEßÉë¿þ)Úû.RQ ­\I~ÇvýæorÝu×UŽ?|ø0G8òÜs¨==§ G€u€rAçc"s¤+Âôÿ•âß5ØpƒëM éÉÑq¾7¦(øÙ±h«‘ xmË™Õ £A¡EÃӲʵ¯ nEÄ«»ð©2Áœ‹¼k†ºÚZ’®~y²—ÚÜóÜ|ó½o|‹zÛçßFíËOV‚¥pøÐöۿͧþäOˆÅãȲŒ ¸\.LÓd|lŒøêWùþ7¿‰KU%©òš}ÅS(|˪¾èÏQÐã}×¹ñ¾7¬ÿÙ=ȃùVZ\7­M-àrÁl&ç`& ™‚ ªQ¶¤ÌÃjY¶…5L0 Ðtò 6ÇS|üæ8>Aæþbœ±‰ VÌžäæ[î?ãùdR³LŒt2;9ˆ`jÅ<`Xþ`œÚ•멪iB„+oQoÿÜ]Ô½òTågx øWà Ðä÷ãñzùÑ~ÄñãÇñx<¼óïdÇŽÄ««1ý~¬úzî}Ï{X±bEåuöïOñÐCß ›ý `ëÅ y|C oXŸîèçß´U\_eñÞ[š!/@ÿ4äJ–T3ìaD±T~´,LËÂ4mPe ЏŒ$ëk“|ææZâ~…LJ,âUA4ÝdVx機pó-ïZt…\†®£Ï27v #;Ž×% ª –e!XÅb½P`¸?C×ÉSCÓ†›Y¿õvÕue@½íóo£î•§0€A`ПÄà{AÐÇìãŠÅ"ìß¿Ÿ@ À®]»H$œÆÚµk+¯ýÈ#06öO>\Ïô´hÔ ¾±ù¢ÊßÅ£sýolŸõ`ÿ0?ÒVqSÅ»]äº(ÌcyŸ…©$¤ó ™` ˆ  ò¸æ† „x‚f‘+¸\"[ZdîÛP‹ß­ðP' §`u€[¢oT +oäÙ§ÂM»ßEQËÓ~à´™cÔTy¨]éE’VaYöÀlš&¦ibY†aP(H¥RLLLpäé`¨ë 7Üý ü¡*ADÏ­ŠÞCÿõ_ÿ«ù‚i’þ_~(€%ÁÔÝ0¹¬§îø_üÂÉesd2$I¢¦¦†ÎÎN¾ò•¯°}ûvÞóž÷P[[‹ÛíF$I"‘HÐÞÞÁŸýÙÿÇ£JÀ—‹/¡ÆƒY>ñ%5[¤7$¤Ã“|m²«Ã&t·ÄmQ˜kÐ> C“0—…‚>?Ô ØU@Àœ¦ª8ËM›[¹j… K0©q ]23ExqF3 Š`Y&0<§x†Ù±>ü#ÇðhÃlÙ¸’H$B2™¤X,’ÏçI$ÌÍÍ‘ÍfEŸÏ‡ßïÇëõ"Š"¹\Ž¡¡!zzzPC-Üö®Ï Ç‘õœ\‚ó21ü*m}Ñ4éþ]†_lcëía†«€•ÀÛà€v€o?ðm~ó¿ÉÆçý™L†žžvìØÏçãÁddd„H$Â;ÞñZZZXµª…P($J¶úâ5™ôòƒ¯§ùÒoøµJtß|SmPÉ3‰¥Ç·Âg0ôó!ªjªÐõyØÐ4û5æææxòÉ'ioo§¡¡ë¯¿ž–––Ë—oòóO–áw¾¨¼¡@}îD“ÞÍ|hÜÞh­Ç-h‡Áñ¤º†…y@%$aVÁ%aÕ5’ë£o"€.ð¹,Ë~^•ì„«XØ).I°X÷0› 2’ZÍ¡žX[—'‘ÊðÂþL΄ª×ÓÚÚH Ãåò"«.´BŽ™ñº÷33s„M›6RUUE[[Ùl–'Ÿåä«[Øtí¢ˆ$É—Ô­ßú¢<©‰íˆ›Ò™$ Ì-&S‘)þÏÏþüÕ§‰“““466òÇüǤÓiÜn7«V­ºì7ý…½*)²óž7†¿šI'x4ßÈúZؽÁ¾a›€Q˜-Aj,€T’@^«¸ÀWÃ~´|Œéñ1\n5îA,å\Ë)ìùì€|I’D<âc|*L×H¹_ kpŽ`õ:6lßD0Ljàr{‘dQ±,‹†¦õ¬Ûr3Gö?̉“‡ØºÅC(¢©©‰ÑÑQN¼ò+Û®&RUä¹ ®ûÉßR}d/`9Ï¿¨†Ìv u™_Š‚æÒ8>|Š M3(«^˜~–GZ¸íÖÛˆÇã•§ÛÛÛyì©Çè uÂŽ<úäß l¾$7¾ +<òÃ";ï¹t0‰é4jw7îC‡í]r¹, °e3…«/üÜ÷õŽ`y6³¥ª#0œœþQ˜NA®hû¤‚0¦,‚,(•@l"ˆ5q²=I¦¦fq»¢s PM LKDÀ"èw˜ 4ñòÁ§Ù´é6âuÍBq‚‘¸=„Ë‹ýM˲0 ·˜Ÿèáꫯ&S]]͉ÎNƆºð«py|ꚟ«’+Íÿ¶ò¿Ôžá½À§»™E½Èc=Æø?«Ž±qݼûÔóOñµïñ·ŽC£_‡ò+€Ð¥¨Q08ìâ—ß-p÷‡.îµä±q"ÿò/Ô¾ü4áU~‚M~ðxÀ0±LŠsßÿ&þFdjýõ¤>øŒšs MËbŸ²z¡ÈʸBÚ„ÉôŽØ~V³-aÅ-[SÉ~”J?—Û3ST «¾Žéî^·EáVʽCeHULBb·U¯H*æflª)ÒL¸ªŽÚ«ñ"ÈŠ I’O ŠA@UQdû­ïç©ÿ¹\¿ßO,Cììbf¼}ÍVLÓøa,ßÙ»½F™.¶Ñ5‘e;h›‰„Ð×MJM' |RqRYY`I%û8¡ôs  =êbrbQ–©«ò!‹‚m*!‹¢¥™˜¦{2ÉLÖBt‡PU7jÃj Ó°-¡Û{Ö¿C’d|µ­Û)'p»Ýx½^dI$“žA× ˜¦qq ¶=úÀ¢Ÿ]À`d„Ü& á|ï4ÐI%ÉÞ®½Zð\k){Pn‚Ú¬ÃËÇ ðÑK6\Ëìy°Àï;?«ªvuS÷×_eÓUYBŸ¹ae‹ ¥¦iy¿ (š¢l»YqüqáU¦þü«g…õØð8>o+>—D6Ù"L&!™·«I–0?ä—”KT’@ÏHOÌ`z)J²ðÇÂÈŠ„ XøªãLvÈg© y™˜•$33ʯŽôÑ9+’ÎZärY<Ê$­µøÖ0=üêyWš\n/‘H—Ë…®ë¦‰(*FÑ.tèoÙóBýí‹öùK¸ÔöÃç¾ ¹÷_¨•ä&ð¾RY«Bà>õ/¼ä“`æJmU÷=!pÇûÎo¨oüã?dÓ}q|w݉àö, ©•ÏC: ™ hEÐu°LâÍ>®÷N²ï‹ŸcæÏ¾vFX¼m¸<¢àe6 ºsy»4jZóŸùòÐ.-€4ŸÊÑfÙµÚe•P,z‘¹L†dÚ ÕˆD"üε!|>‘LBTÒÈ¥¦ùñ~Fò.VmÜ…^T™žMÑ72ÀÄì8ñª0ý‰…|ÕåÁ4MfÆ{PÈ"èIŒBËÈ1L“©©Y%€Ç&j ‘H0>>N±há F+nƒںçû§5=‹%O1¬ƒ˜*ø/Tp¶}ØÐ{þ ¦?¼½ô˧¾^…£û 6mÎi¸oø‹/• ݽ$¤V>“03 ¹œMS¹UiA7H@±Øæù?ýÓÿÏß/êu¨äNM‹É¸T{ˆŸÍØþh^/Eè ýÎÁ’Pæ ù<‚(rçú9͆츶`ZM‹”a±Ú%w‹ü´Û ZÈá‘L^ž(0’ØqÓn2iÈíÔ•Gu3•u(šŒç-æ&ûr}T4Ö¯ö#‰¢A«Ð4Í®XµU£i™Œ‡T*…¦i¶Oê ãõ‡‘$Q”. T{ŽÓ«ËþbØnÀKC0t¸´³¦´é¾§aìÎéséÓ•õ°ï!˜^Ü}I@ÕM™C{‹lÚ~ö׊üˬ_ÆwÛíKC:<cPÔçÁ\Òrï]ÐëfúÙÿÃï`|ðc§g' ƒ”)ãl šÊÙVB/•GËîœ(,ö=Ë®¦ÁÀLžGG †&$ò…’ÕTEÀçðª0aÁ\ÁDLÏ0=3É`Ò l—Ûmû¾B9“ " "ÉàG%G÷®‹Á/Z]Ç¥sò÷ÿ’ÈçnDCšœÃêí±‡xÓ<'HËû[ê†öþŒî{Þ‰/zÏ\:‰!Û àšyÍ.ƒRÊ•–ƒ¨2¤Â‚ø@VdfóEÆft$QªtLéØîs:_:MÀ'›¸ :ØO E•¹æúëÁœ‡_3EªÆ îY£R]âöáv»ñxwªëzeX_¸éºŽ,ˈ¢ˆ ÌÍÍqòäI,ËbmK GO„»y]å}=Š‚˜ŸÅTª0M ÃJ‰x©T9Â:P«4i¨*w¶zxuÂ"¯›˜§Z^¼b¿6ÍÃÇzÅ¢Ô7ÄIgÀÒ Ö Cl¹ ÇVFQUõ,9S©RB-[†Ô4ÍÊðïóùˆÅb=z”mÛ¶11ÒN¼®IV–,, ªšN fg<¡"  ”zÑÞGy|€F;=zF…sèƒéûö»aoth¶pz ªh² j„öRTö ¸†ë~ '$Içà@ Òo/9Ãg†ujrùª…<>†'¦‚ê¦èv“jh‚|ªëæ;8* H±¬ÒK¥ý–e[Ôu¬ŸþŒÀä$A·ŒÕÓ @u»\x £˜þ(¦i`"¦d{§Bº°kß*eúG“lkðQ£ˆtMšè¦uÚPgUžñä(›Ä!ÂDâCar¹étQ+[9‚/[PI’–,¡–·²e•e™™™™Š›Ëå0u|6…¡kóö³ªdÓg÷O„«ôó Ü¥E§²î5`“aÂo?üQÈÞ•:‡>”› ã†_ü%ì}ÑûíÀz~; ÿ+<=Öç€5Ë¾Š¡YËZ]KË´°4 Ñ4 .㟯A@·,4ÃXÒÝm„W=µ˜†Ži*X¦h[ÍS·’7! ` !pí5hïèg|b ·ÇCsÔ`Vƒ|^E%dÑÄ-˜¤t‹iMÄ‹ÉÚt‘¹’Å" QÂ55‹ÛíFUUÜnw%ÂWUUOs–‚u!°²,“Éd˜žžÆãñËåÐuQÑ Ý(bšÆ¹GýåË–óK‹oé ðwA”÷hh£y¤o^xf³©K=´Ef¸z­É+a;“uZxÛìLÀ‘_ÂÜ;@ ôôÛÉVW@è„U&Ôt—J¯©3¾¿–7—Í©™~?ú„š†t–Ɖó‘a Í(¥r–jŠúy>©VE{ø7ÅÊ|§…Z¦ ¨)‚hQ„`$®~ùä+$'F8–4ȉ^C¬ŠzXÈ¡çó &tªÕ"ÛÌ>z{‘ý‰4¹\U‘©­«£®¶–ªª*|>‡B¡P¶<„—ýÎrà$-QÀP…\.Ggg'ªªR(*íž²,#ˆJÉ’žgzjùÒ#hQÿ¤Ï')þ‡Yþ6 ³³2æË…ˆ¥8)6¹¿…£I(üX¶ÿ@mžùSHuÂï”*­~²³`dJIµóKÜjmmdökT¥ˆfÝ%UÓ ¤òdû%´º¹ ß‹ÃÔ¨ŠŽlH¢ˆQî”2çã2QË(@QA…Úˆ‡£‡^A’e$IÅ_ÓÂ&Ÿ‡ý‡†84–Áof¹Aè !"“BÄ2t ½Èt*Éøø8Ç…H$BCCµµµÄb1^¯¯×‹Çã©X]EQ*Ж]„²…öövòù<@€ááa¦¦¦í\±ìò#ŠÒ²×÷¼AùÇ`ý xÈÄ|,wÁÍwð8ðËìü8lG†5ð‰Ôùà‡a¦xJšj…a'p£ÂÓÐ~Øjߥ¼j“/–J¯òüâÃØG€wSÊj¨«ÚHOkNQìê"õÏÿ´ `²ÿÑ ]7J×nØK禉^NÕXV%n–š?­±1dËb¢ ¢µ­==Vð¹J<È!½OQÃ$LIÅ4ì9j¦i§‘ a~Ø7ùbQƒ«6­cú6dRÉ4Ïí;ί^îIbËêFÖŒ=ÅîÍ[ؼí:Ž9ÊñãÇÉçóX–…®ëär9’É$œ8q‚@ @]]+V¬  ñù|‹ër¹NƒàÈ‘#LNNRUUE"‘`llŒT*ÅÊ•+Étd5€¬¸—éô_r¯ˆ.ï[îÑ£Ë2æEY—và9üænؾÝÞ·Ó s:|wt™jÃV` ö¦A+O­VìšYr;? WeaÛ,<³ƶ÷-0¹—·’–ÏψÜÀšÉ9ä©i"GTRK–iYÔ tÝ<Xs°†QÎ+ÎçT1-$ÉMOëÕ(®¥#ÇÛyáä8y©E’ECP0ô )%H…ÉÿR»ž`,)@,!ñâq‡Øºe#âþå†õÜq÷Û1 ÇC4¥P(, ‚4M#—Ë‘J¥H$ôõõÑÛÛ[¶±±±m À盯X‰¢H{{;CCCÔÔÔ i###Œ!Š"UUUô Ln ãöeuÉrê’ ½—we< ÐJ›X*x}pjŒ"> T4k™™Û²ÓEf®¦}à?‚w÷æ’U4(fJ?,vR$õÌî@ú7~ƒ©ÿü&µ-žÅyRÃÄÐK[©¦]ÔÞÊÖÕÄ('ÀK>)¦I@Ë©dÖmÄç/ùÞ+WqÝÉ_qX‹â’E$Q@DtAš•ùéj&óÀš%_Í*¹9Z›©®¡<@›1Îmw~˲8yò$ÓÓÓ§ Ûå“išTWWS,Éår•)Eǧ½½X,FKK MMMÄb1"‘†apòäI&''+³;;;c||œúúzA ¯Ëxý!Üß²s§¤û?ò…/vÿ³iZžø!¢¡_Pu쵩¾ < È»áöµÛ!´`DI€*’ôç—5hÁT :°Úîí2' ø0¬Ÿµ›‚Ø5ȱ0ªÅ¾à:ƒí·žá|ÛVQøþ/hˆkvù²d²Õ4ùeH‹eX͸¦ ¬ýhÑ"«ì™ü«mBXÆ?«÷»y¾gS ¢ˆ6<¢ ØóâOñºÕüä-@,äCh™žcÿÁ[oºžÆ¦fúúúèìì$ŸÏ#I²,W†î…~9ˆòz½ªªª¨ªªÂív377Gww7}}}äóùʪ8ÇŽ#Ûi®ŽŽºººH&“¬]»–É©òB±º¢ñ¸<¶¯zNyTÍBó…ΚK=_8ûí( ü8ßó5Ÿ¿Þ÷AðžÒ,ÞìÕCGž™]ªeàèÏ`@-•·6™Öf˜ÈÃÌ0ì&À¡iÐo>-U‹9ÛZW3ý$|… [<•²¨a˜†iØ–ÒXV}Ðóˬp4ågä·ÞC0_²Õ¯r~Õ Ü_ÝÃ÷fgQˆ”,¨ ,,{&©`Í[PË,uúca˜"j)9ÎØToaœAÛšõLOOÓÛÛK±XDQ”JŠ©œN*ÿa²ß4M<>ŸP(DUU555LOO344ÄsÏ=Çðð0ï~÷» ‡ÃŒá÷û+Vxtt”•+WÚë8d BÕõx¼AT—q™×’ ¦׋Õá»$š¥JüwDxHK‰›À\Â÷.‡Í^ú—`ïß@âÛðá3ûÐÍëÎÉvÞ@×Ñ·î{„ú:Ê]B¥áÜXðX¶ ÆH‹¦aX¦I$QÐ}¼ºónôÕ†ÏÞï¸ýšxâ—ìÍlD´L„2¦…eÊ•1_’ì¦ ¦ˆ‰ßc]µÄ[š}¨gª}µ/MW7c}}}ÌÎÎ200@*•BQZZZˆF£È²¼dn´ k¹áDQ\.>Ÿp8ÌÐÐÇçðáÃìØ±ƒÏç™››cxxÓ4©««#™L¢Y^ê"Õxý!$Y±×r=Ÿ¨¶eU¯\lN?Qá—×À±Õ%ñê’K©^P}`¬„”ò IDAT­‚¹˜½Þv†#ÝumòY:J ,¿û)^øê ÛúŸ§©AÄ*YÒ²ïYy,ý!¤å¡¿MQÉižY}#©[禮¾õŒÖ´’mEÞyãnæö<ÆQs µ–eÚ½*˜'¤E —$¢*"UAXSÙ²"JkÈM΄Óu‘„þ ±êZ&''9xð ‡F²Ù,¹\Žýû÷sÏ=÷ÐÒÒrš•=Ô²«PÞ$IB×uFFFèììä†nÀï÷S(e``€æf»unlboh5þ`¾@IRà ~VPG¯½ƒU}÷¢‡ûQàqüÝ ˜¸ ¸ùÅ*z_û6¿šzÎØâwªrð'ìýöß1ýÂ/XÕ  !µo qêfX‘ÅCg&Àñ[ï'³k7Õ ­¨®s_!ÛåññþÝ»yðé'y¹¸j¿Ÿ»€Ðù/»ëhˆ(„DÉIq‹Ð„Gú ktQÀ•ŸÀã•™˜œâáG~ÉÔÔ;wî$‹ÑÙÙI¡PàÙgŸåرcÄK+1ªªzZ~³ kÌ2\å^Ó`0ÈÜÜÅb·Û¦i´··£( µµµÌÌÌÔ<44ÖáFq{üËûg¶¨mW‘‹TŸÓD,§D©¯ék`ú½`®âB—=½lj[[8¯Üª(I˜ýoÚx}=Hs²›Ú*«â X¦…e˜¨@D’P97׬cú½ïÀjl¡¶þü ­40£¼ÿÖ;ï}‚ÇÇcSW]Íu5öŽ[ %,Ri(-t Y°WïSdA†ì@£==9~’5kÖp×]w‘ÉdÀív3==]é- ‹NNµªöthqÑÏeßVUU2™ †a Iôöö²yóf …cIBñ«„ª*S®A<P͘m»ÏÇ/€W_¹áÑÍpâì4ÑyÞ—þ<ür §Ïåè.àûÀØÙg—,êl½ùü}Q’ð캅ÄÖëØ÷ü“ø_xžØp7±ü A—‰È–Åd^¤ßejå*R[¶¡µ®%‰ WŸÓp¿œ¼þï¼õmÔ¿ôefÈi1þägCLë*‘ ·ª¢`è"¢ !Êù\‘ä‰çH¿ò+ëbÜýöÛ¨®®¦§§‡d2‰,Ëô÷÷³ÿþJ€TÊË.´ªåô•µ q*ÌåÖ>MÓ8tèõõõøý~º{ÁUG$VO´ºéŸÒ³V¦zîøÀ¢…zÏG/剷ןâ‹ZØK®$X<õudᯠ7o¨ï× 'C!äÁ“±SSË0ÑÜrnó¥–“ÛãÇ}Û½äwÝJObš3“H½v-kiCe—Ÿ?Lu°ê¢]Ü]åb× wáyùž|ôa†å‘êZª«‚TGT¢>>ŠO•0Æz˜Ø÷0®ä÷Ü~›¯¹–Ù™ÚÛÛ+½¡¯¼ò /½ôÑh”uëÖQUU…ßï_T·/Ã(Ë2‰D‚_|Ã0غu+ªª.¨¼Ù®P9kÐ××G:fÕªUŒŽŽ1›÷R×¼Šh|PÜž‚"^¨½w¼Ÿ~•Hï±ó¾@_j »ÏùQ`ü >®iÃ^ïó¬Z]„;&àÙoÁË‚lÂ]p—µäj.";o»4_ãöøíîüÚ&Øpíu]¶^s3­Íëèë=ÆK'_ ¯Sà R…,+Ü«µ“¬Hwpõú5ÜüÞãóûééé!—ËUr›Ï?ÿ<‡¢¶¶–ÖÖVjjjˆÅb¸\®ŠÕ,o²,“L&yæ™g0M“½{÷ÒÑÑÁÛÞö6dYF×õÊ”ÇC&“a||œ•+W’L&œÔ‰5n Z½‚pU-.·÷¬3PÏ©Öß}ׇ¹öÿãœ/\ 8ªƒâU¥¶¨SWé8¬ß kع?å<ñ+¸~TWCÁ„C)øÏ9È«1¯¶Á|ü¯ÚÙ vEu)ÕÖèç½øÄëU¡h ›£5¬¿jSc}ŒŽôrüø>¬‰^Ö×…Ø}ÿý¬ß°‘ññqzûúp»ÝÔÖÚQÿž={èêꢡ¡•+WÒÐÐ@MM Á`Q1Œ¦¢(¢ë:{öìaÛ¶mƒAFFF8rä¬]»¶²xo.—«TžZ[[éîî¦{pŽHÝF¢ñ¢±{ª´¼|¤^ ¶¿û3¬~ø;‹–õ9“Æ€¯Ïl†üN+Á(߇{ûáÓ¥zô·÷À_ÁÿýWŠÁH¾9MÚU©eU,µ^éÌ/tð–rSB)‰› n°‚€ŒˆÁÍ÷¼†_{Y¤ªn"±zºófggyì±Çðz½ÔÖÖÚ)¡în^zé%:º‡ˆ4l¥a} É©^ Z†b±H6›­´õ¹\. è4¤är9ž|òIvïÞMss3?ÿùÏñxaûvŽj¹=ñ`–÷VzSBšÏ¦ŠSèzˆ§Ÿ~š@ €®ëtvv222Bo_?J°™5[w«m"«'©A’d¢ñ$[¯¦ûØóœì;BØ;I¬*Z™n2::J&“á3Ÿù ÃÃÃŒãõzéèè`nnŽ–––J6 P(L&) ÍJ¬\½†p´–h|O`QãeàÅÏþ=þ±~ê—©XÕ Ô¼—„ôKU©SaÎ2´/LÈ><µà´zÿ`ÝÁâyPK¿¨[ÑxÏ'yÃ~uÏÙ47=‚*ô÷÷“Íf™žžfjjй¹9L)@uÓ.Û6®ª#\U‡?EqÙ‘½i„£ulºî.R‰kî;J÷Ы¨Ö—H&“á£ý(áp˜çŸ¯×[é+E‘b±hÏËÏdÈd2$ ò–ŸÚš6ÂÑZâuÍx¼Á‹.t\PèûÄ_>|Ú7÷-´¨kw& x~ú(t/U¦¶`/0qÆ*vTUvŠ*¼ôèܶà jàVξ܅ é‡?Yàú;ߜ߉jçQë˜Îz™ëí$›ÍR4Àª%Þ¶™x]Áp(F4Þ€×Wj§+Y4Q’PÝ^ÕËã'©&»zƒÝ‡>úsîºóVn¾ùfž{î9ŠÅ"@€öövFGGíuQgfìyù–ˆ¦ (zZ6n&ZÓH8VwI ½`PÿÚ£§}êB]4daú)û›SL/Ìè:[½ÿe?ü[dKÄåý=ÀO1Çg÷5߬߅zª<¾ 7Ý÷9zO¼D*1…¢zp¹}¸½<Þ þ`7ˆ¬º–ìžA’PE’¬àóGhßÿ¬j[Éý÷ßO?ÃÃÃAÒé4'Ož$•³ð‡ë1ÝU¨"àà ÅKŠ*B‘|þÈ%+_T2ñ‰¿|ø´o—^øÂ5ÀáCEHá…_8[Ôv$þ+¯ÔzJrô쪤øðgyÓ~»ô"OɲPU+Wm¡Ï€e!J2ŠâBqyPT÷’ë9*»óIáä¡Ç‘ ýÜû¾à÷ûyî¹ç*3K{zz覡m;+Wm&VÛ„Ç´{VEEuãñq¹}çôEgWԲϚ®oeãƒ_;-uåb~±“œÂ\?pæ×ûÿ»ÊsAç#¢³qUŠ÷}ÎEãZ™_ ‚€¢ºd»eÎs„J è|—ÉÑ_ý)7]»vñÜsÏ‘N§‰F£ÌÎÎrâÄ dO5më·Sß´ŽXmS©Â$,zÏ ˜.+¨ålÀøU7²õ[_ úÈÞ%]poi;3¨÷]¸¯æÊòöû²Üù‰ ¿Ž²Ûð.| Ó49öŸß%^à¾ûîc``€žž¼¥Él]]] S»æ6±:¡˜]a’.*^ªšÚ¸ƒ=µ‡ƒŸüK+×]Ñä5voå³_)þÚBz)ôêó?FOqçw …Ø·o†a ª*“““œ8qS «i&¬Âí ,;söRë’'ÞõiN¼ëÓ¬ÿÑ_Óöè„úÛ/¨Ÿõ\T²\³iŽïw³æÆ*‡´‹14c}Œw>ɶ­[¸å–[xöÙg™œœ$ ¡iZÉšoy ¾`_0Š¢º/éð~EA-«ýÝŸ¡ýÝŸ¡eÏhÝó}"ݯ^Ô´–²TA£!”`Ë6mw¹Y¹-æPv ÔñòÃýnî»ï>Nž<É¡C‡*õûññqººº0E?uMëñ¢öÔæ+dM/+¨eõÞñ~zïxé[VŽPw`‘Þ£x¦FQ3‰3® aà³D=YbUE6n.ÒºÕEËnÎK)­%5ÙÉšÖZ&&&Ø·oš¦Èçóôõõ1<7þ øê¼x#5Ûkš.£ÒÉ,³@*•â©§ž¢P( +ëDutt`J!êš6âõ‡ñùÃgýÚò7,¨§*Õh¯V2½þºEûw8Ü\q¹=tݪô‘úý~²Ù,½½½ôöö29“fÕ–{ˆÆð#ȪëŠù¦¯9¨Ž^?òúCøbk™ÞO2™Äår‘N§™šš"W”hÚx5+Ö‰ÛÓGÎeŽ“ª£Ë¢kv€=ÿÖÏØÀLÃÀñ66¬º–XM‘XƒÝOêö]qk <ðdÁrn“#Ó0˜¡ëØó$fÆp{Ã#ÕB1B‘j|Á(.—÷Š$÷‹êè &K б~ë­dÓsèEÍþ¦ØnhYæõP]Q‰¥†YVñúBxËÝV¯%¤¨ŽN1ªv»ßk5¼ŸñƒäÜGo‹ï\G¨Ž9 :r@uäÈÕ‘#TG¨Ž9 :rä€êÈÕ‘#TGŽP9 :rä€êÈÕ‘#TGŽP9 :rä€êÈ‘ª#TGŽP9r@uä€êÈ‘ª#TGŽP9r@uä€êÈ‘ª#G¨ŽP9r@uäÈÕ‘ª#G¨Ž9 :r@uäÈÕ‘ª#G¨Ž9 :r@uäÈÕ‘#TG¨Ž9 :rä€êÈÕ‘#TG¨Ž9 :rä€êÈÕ‘#TGŽP9 :rä€êÈ‘ª#TGŽP9r@uä€êÈ‘ª#TGŽP9r@uä€êÈ‘ª#G¨ŽP9r@uäÈÕ‘ª#G—A²s .@F1{´I3‡eYXJ ËU®:¼Î5r@}m%ä3G,A’Q|qLCCËL!§°R¯b‰^Xw¨qç¢9 ^aH‹SHéW$…ðÊkñÅ›+Ïé… ùäÙéar³ÃXÙ.Èva!ƒ»Ô¸DŹríx²`9—á?Õ³ƒ‘¥zãí¨¾0. ª¼PÐa.Æ‚+™";3LfzÓ(bYö“–Cð4 ¸ëdŸsQP/½5•“ûðT­$ÚzUØP½ø˜©,$ò0…‚1¿¿ž%5ÑC>1N!=kkY y< ˆÞf5â\dgè¿ jcX–…'RÀÊðéÇļöÖ…´fC;žü\þmói2ÓC俯ÈLa¦:0S (6´žw5‚¨:Ýõü%jc¸q\øÏ‘_µ·† è¦me§³0ŸpÃ: ë0tÜÜ8é©2Sƒ™^ÌL/–eU€•¼Ž‹à€zŽ2²fw¤QV ¹Ïó"‹Pã··²‹0…D^EŠ5â5OÏí&5ÕžÆÊ¡Ï¼ JÑ]ìoCtEP-oM-ËB Ø©¦ª‹L“–]°]„²µÅŽ:Jõêë(æÒ¤¦HO™ÅÐfÑ'@T¼H¾Fd_£ª£Åþ)€'R$ÌCv)TvšÂ×烱iüD7mÜ€Q,*›š@Ou£§ºÉ[VXÉS‹¨øPmeõidoÙå#ì¾|oå–Á½„‹0u®_M¸~5™™Q’“ý$'ú(fÑÓ¶åW#Èþ•Ⱦ•Hî¨ꯣ5ub—dØ¿a`×ðß(.Ú·Ä1‰Ìdmk»ØE˜dv´‡Ù‘n2‰Iûw, I  ›q‡ZqP_7Ö4׃˜9J¤Åî;]¿´‰þ+ èÂãN}.¯ÛÀNf [œß_È$IN 13ÒÍìhwůETp‡Zq‡[ñ„[¡ÿ5µ0€+¿äÕ¨×  åç\2ÔìM7lhgs‚¸|ˆ7m`f¤‹™‘n¦‡»ÈÍœ ;ÝŽêo jÕÛ.»?ëXÔ¥dQfEö„¨Ùtû’½§o@OÝa-ñ»³9ۯ̓¶ÀEÈÌMÐsè)’“CÈî*âkß…(_>XY¨ËDûveGûUÞ× –µ˜2k?Ô²JÛRÏ è‚ãN}ˆÇî½Ý\ ãоp5Wí~/ÕM)æ¦HOº¼#œƒåÒѾeY¸Ã¯P_ @—ú¯j÷!lŒÃ†8H´lÙ¤¸H¿â€zÅ-ª>U©F…\¯]5êõèRïáQì°¬º ű -;é€z%‡}ÁÒq]¢ÞÓ+(WÐ…R%ûѩƲ,L½àDýW ÔâÔ¢jÔ•õrJ–uá¯Ï2ðÂ|þ51agHdWÐõJú§¢¤TªQnù èr‘ü¥zDÞ~LÏM ©Ë ª3ô/”ž@0s¨Á+7쿞ýÐ3½GA·ÓUÓÃèZO¤í²^'Ç¢.üÔ§íaÿ DûoD ºð=æJÖtz¸ w`…êµT*ϺÓNÞ耞:ì'&$Õ±¨WLFÁH"{ȲzÉ­é›P 0L»ï5=;A>“¸"õ~ÔJ´? €7fÏ/ºTÖôRFÙ h±¨¡(ê%û”­éÌHWijs@=í„gF‘gFÀÓ@kXsÉ¢}˲.iþôb-ÜùÀ“èÇÈfIŸ<žÉ’íëÁÈÈ Àöí\óÉß»d‚DÅ?µçcy¿¦ º†;s)<]siÔ¡“H¹®áûâ-H ênéëïeöžO`z.¼¹W,Ž!^¢jÔå‚S'N`d³dЦ&)LM¡¡ÍÎ` âЬÊëZXä»».©•NkÏ$ÈÌM¢xb—µå5ÕÓýr>efyz×pR>½ÄSÁ<õ9)—&ôôð¿ø3&?øe²WßrþÃ~¹ å"£ý‹tÂ)´©)rƒö¾ûqá5°¶¤@Ý0Èd2ˆÅ"ÙL¯ÏwÑ&JËk&&±, _lÕI¯$œÁ—&ú샸G:Ïß©ƒA$IÂçóár¹p¹ìOp¡P`||œd2‰˜MQóŸeòƒ_&½ãÞóöGíaÿó§çè<„ƒè¥¡ÚÈfÉ .ü£½Æ¢kUÚ$IÂëõâR]¨.ªªâr¹ðz½H’}[“É$ÇGM$Éf3x|¾‹ÆÒÚâ´”+¸âͪ˜K³òï?‰{¤si«X¾è%½^/²,WY³<hl¯V”.NGÕO<ÁôІAü{JaÅZŠ+ÖžW U®Fù”s¯F-wcs¹é“'+jÓ6 ,ßRªªŠªª%øìk$JÁ@©T_årA,‚X±ÿ¿½3 ’ã¾ïû§ïé9ö»8( ™æ!R’e’uØVlɲ’JÑ~ˆ*)û!.»TÅr*¶+Uv*y‘E»*ypb»—+–¢ŠlT%ŽÌC2U2%T$Q€X,°÷1³3=ÝÓ×?Ý3Ó3Ósì; Bó¯ôL÷ΞÏü®ïïÿï0 xùeŒø‡ÆkU–—˜>tø–«¥Z3‘RôzöÐݪlW8õ>âT >ùLNF«Ò5!œžn½ÕÁì6Ξ…˜égžáÃàµ×^CÁÔþˆÕOýÅ`°®FM̃Í4Ð áÆ&îfd%ë.ºÓ½¦{Ó4Q…B¡Ð€QQÌlt=†p 1V€é£GS¥88ºa4Ô¦°Tºår–í«QQ?Ä)†5öÔ£ÿýß4 žžæÄ‰¨ï?<üpèÙÁ-‹‹P­Â¥(©âøñèuž~šüïý'Nœ`aaóÍï¡Ý¸8U­gûõø´¾îSÓnânn6 ´êïÝ'vNŽ|>"Ëd³Ù†•¬»êÈ" c…®Ã¡Céå*߇„€eA­µªDÇb2E©•Û²Y,«Jei©ERÝK,Ýîö‡‘íÔñï>KîÊ+ HOÞ?<ýtX·qñ"ØvÊ7`s3º¥cÇ¢×üÙŸe¾\faa!‚ã;_aûŸþNÏϧ-^D®¾†ºöæ«—áG¯²ôÐYœÕÕbçdè’ÉdÖ­¤išQè23YÇ£G#ë®zl,ŽZ Êe°ªˆ ˆÎCÀÎN¡HXh!âJ4!дø³E_±(•n9ÙÛnS£2CŠO÷ÔÉoþφ»?qâ|ò“¤u«¸¸Ýê`Úv7*Òã8!àÚ5øô§‘Ÿz õ¹çÈårX–…ºð£(Ø¿ô½xû]d»Œ¶øcÔÍ%ÔÍ%„ªâœ<‰\­"¿ñÚô4Α‰t¨5­Â|>ß°– Ýa}_Ú°m¨T¢@¹Ü„R$LüŸ…T4Mq6›egg‡âåËaÂ.ÊeAÍV­«QÙéw·~¾Ÿ±i=yšœœDÜôâ"üéŸvZÈ^06¾¤Ö}" £ûo¾‰ò½ï¡™L†J¥BöÊ«Üó¯êYê âøW-#èî¹3—#ŸÏ#Ër‹el¸è±±WÝuÔ]³ãDѶÁu£[¶Öÿçm€Tˆx@UÕh©uÏÅu]4]ïCÑÔzµví‡Cµ¦û ª±ÔŒå&&&"]­"žy¦qÛ¿¤¾Û:˜Éûñ6xýuL —˱‘È®Û!˜˜@UUòù<ÎÜŒSÈdÈ>Œù‹¿ˆ>7× a=^Lu èyÑÍu£­ãDñ"tÙi?!°PˆÃ cs‹íâ6“Ó³„1œ¢ œirîVaÕ‚âòâÐãÓ¡$S 6=Møå/#qV'Œ" ›ûbÛÉm6÷ç;è÷ÜC.—c||œL&ƒaäóyTU~,•º€ðôi–4°Ç¸q7<8 IDAT ´|¤Û5†çE–°Vƒ0lµŽÝàKƒ³ýXòü4@o¤DR¨ŠÒx¹òV‘üälWë™h}ߦ ]Â/¯aŽE:˜‚ÿ¶Mè8]­c¾ÄýäþŽcÉ[à;3Ç3óØc%¯¶RWͶakVWÐ %ŸGªT"ëPÖjmó8D 9(¤‰iRq› ­[öØÃ4ÀÊ2âÔÙ] Ñê€~îÆå±¦ûjÝš±‹ô]— Zí\7ÛnÊÜÊÜú™3Hù<Ú¹sÈù<Æ{ßÛýÃT«Q&í8àºØÅXêoÀN mzŠÅž`½- "ª¥&€3 ÇqpŠÛ]çO‰ûV­Ø¹l×ûuï"PíS$©2yãÎÕ«ýÁ D¢ÅfÞýîHÞ|Ï{ ôsçÒ¾OhYÈAŇu]ß&¿T!°wÊßC)ï€$¡:tw@*lo·€fè¨þÊò®MºýÐsð6.ïûܨ±¨A&âT¨Õ¢”Ñw|Çi@©?ú(r>völ´=wu~µK&Öjå2¡mCÄñnX.C¢è:F¡Ðd0BàB„„;;dÂ)ŸGÎdÞ†Ò ©ë‚ã´¸vÝÐA@uùf’ë Ý©Ee)¿¸8t5jh ÖŽžÁ¼|lj*Å…ßÿ}˜žF?{y,ýWV«Œ•Jd%c(ÃD÷P7Eô…!¨º.PvÊQôÈ‘·)¤¢R!`c££¼d™èéõ¢›ªÛ ÚµØí»ëŸî;¨ÞÔ&4,jæüùí>¬Õð–— ŠÅ¦‹îøvPV”¾"®­TIBŸŸï i¯÷¾“ D\N~äl|Îõ2›ë+LÍé(ú‹¹Vˆ¨—‡®FµÔå÷óÅÝɨÑÃuݦVŸ”­76p~øC‚ÍÍ[†@Ñõ¾úaˆø–…îy ë(ù|oH»Á'A ˆÍͨZÑ_TôÙóñ<·ÃЦYV7¡”]ðËk„žs`ÖtßAõ§æ"Õ¢FùÅ"n¬ËXBè ©¢ª=!Eœ¸l#•JÈB ÍÎÞúAËùM~Œñññ¦—‹»ýÛ—JÛ·kûµåHÊN¨ûìúçeª h=‘^›uÝ3¤’„–É ™f_H‚ZÜa¤ooCÔ¡AÊþ@*€õµ†5Më¥Q?ð"Ьj§õ¶‚4vmÖÖšÇëÿçFKd=3q{Ÿj;ì7û&SE'R£üâ"š9s jÔPA­Ç©ÕzÁþâŨunäé6BZó}D–vÐÃy|9ÙÔ|GB*Ò!"’‰ßºÖv<í9Ñûñü)Õ¶£r¡h]¡/ mÙÔ(wãr<;÷`ÝþP@õâqH¡ª[UI¤uk  –ŠM·ß ÒŽJø m'IC ¤" RÒ! xë-„ï·½ObyÉæ[ˆ\ýÇ`]¹Ô³ŽºO:ðã&”aÍÝ?XP§›µÔZ­Ö,ú§YÕ}‚”8ÛG€RŽdS}~¾7¤ýöÝ2¤´BJ ¤ WÞéÕ·¶Óš8u„­–U‘划ï÷týE»Uê5%:\Y ¨ûžLù‰ZªeYŒ×CUú=‡©†"Ä/ïu]ˆûOo¤‰§Û>º¸ÿœ-°×+"©Ú©¿ñdV”Öo:^(P*—±®\„Ç?œšP9>X^ÔÒzÙéw|ÿ›P)^þ>¢RB\þ>be±A*zÌŸ÷íê\k_êMP‡)€7«(år¤F9ÒÒ>Í)é±#éûÒ\y®ö8µi"n ¸r5Ò´’T»vŸðïAÕj™†’ü»f¶ÍwSþøßâ¾þ£Þ)ŬêP–F¯Å+î•J¥¦:Uwýû i#>ÍI| Ù´ßûuQÅ: Ý B*Z¦àtXlÛ†K—Z!m‹A£IP‰çŒƒ£ÇãùwõJW·__©¯^?Õ®^éø>§M“¹|³F.?üäÛßõ'KT@TYÞ_HãýaÜ-8M5J«×O»É³=’(Ñò˜f(‘ µB ¤íŸ9a¡[ ¶·`i „)ó­Zˆ4+›x (JÔœâûØÖ™ÜX‹UõÃæÜ¨À.1wõ*NN’×u †Á´ibÄžðZ±ÈrP߇ú”z/hP}÷&ÕÒW°Š_!ð£˜JR dþ ¹ŸÀ˜yORZˆb¯ÍE¢û²ž%ê×ÈŸú5ÜÒT¯ ëú—ñj)­þ¥Õ?B3Îûerc¿Œ,çSÕ¢¾ÖAðýha´R Q«E÷ë«ó¥@ÕëâºûDºâ”òÄvwŸ|¨ÊJ¼hšW«¡ê5ª^Tä=‡™•‚N)‘ñ+’ÄBœDÕݾ"«è†y÷€ê;‹ùæ*ÕjcZ/““ †þöÎsXÅ/S«^h<ߘy7¹Çœû²Vw5ƒÍ©ûõñûÐø&øìåç°—ŸÇºþ\ç®ó ŵg0sO’É}3û$²’KWœáyÑr‘–Í¡¯XÑýx‚bZ¼Ø žTËØÍ*ŠîuÒô²•hyÎX\¨ÏK”·×™˜=ÆVœí×WB™½¾ÐˆO“7M’n?0óÔ:OÖÌÝZ{Bå×;~66¢UóêõÎÒßSÝy{çyDýj•ì…S¿Š9÷AÔì|Çt«½x)îmí=£Õœ{sîI&x{ùyÊW>‹Wº„m½ˆm½È6Í”LöILïÁh) Z *•hñ±4×Ý#^ìêÞEw˸«K™wIÀDû1ŘõÇ®WAÔzýtæúõ·/fü¼…¸îydhnèµniŠ;;L¬¯ã7)¯~†êÖÿ%ð–"×®åÉý(…Ó¿Š>~¦/œ-?†â2²¡ô·²–%wâ£äN|¿ºDùòç¨.¿HP]Æ*?‹U~)Ì`Vï'g=Š^;Ù=¤³1$ýoz»é€#­lÕ]ÿOÊgÌÆëùW/ãÏjL‰ì3 -IT=ã×Ö4ŸšCH¤Ä¢JF€}êMªKŸÄ»y­q<;wsþ<ù{>¶+8[Þcí-C)Øý‰ÈÍ2ùЧ˜|èS8ë¯`-|êò7 ½ VþVþŠ?‰Yý)²åGѼ¹žvZÌ)úXÚžÓžh V¤…!ª,ãµÒVÓíÇ3M§cPÛݾ‘Èö#PŸDÓ TM¿»@Í_fæŸÝ${®‚ ‚6~šü=¿Dþž_BÖ {‚³å ÛXDÖõ[z €Ì¡‡ÈzˆI÷·©.‹ÊÂש­¿J lS)¼D¥ðŠ?A¾ô8™êO¡“}²îħ2gúsèº t×MôŽ{sf”ù‹•evâl¿>w?¿¼„Ÿ„TLYF“¤5*4óòãÃÂgÿAr¾ÊÙÒ¯£Šœ%{„ìüäïùEô‰ûºZϰ´‰ØI,¨PÚhy®^GÔª÷¬O2¶ÞYäÙýíäã­WNQŽ7à YÏ’¿ç#äïù¾µLué[ì\þ~u_-Rœ~=û:‡V~½;piõLÑÇ*v'º×I»Äµ"ùOÛ£.¥:Ë‹Tã¹QAeìæ&Z¹ÜŒOãŒ?+Ë©jTÆ,Ü= æ¼ï£„%ŒÌ}f#;ÿD×Å‹ø\l‚·~j­½–ÒÌQ¤DéCJ¾Ê\¸wDKQ?þ.¸6ÒÌ|—ØÀE,_n­´?~ùÙÖÏpèXã3dÉ’;û»xöåµ—©l>OÍ÷Ù¬V˜0̨‹¾gæN:©Ø[4%vݪñãLì®åâV‹5yébdMÛ\ÿ˜¢ðúúzKY*5÷€Úp§ï8OîÁ?Œ` n {Çmi#г”_þWûô¿0A>†""zT>?ëû¬mmãŽùÉõ.Aõ,[Ýž:i·«Ò’P™¿ÎÆöbsJôÒR”H%2þŒ,c¦¨QÃM‡ª€¿å¿A(Ó Ÿí~$Š®öíõð/1Ü:i¿ð¢¾T) `5Qüâ"j¹Œ¶±Ñáö󲜪F +ÛºEm8’`ªßŠ"/í$h'‘ôŸ‚ð&ˆUê ÓžÞA×ã9ï·Tiäà … ü(=K¤xË€ÒK³;oe«½ÖIQlzý6eßD6vá¹È_ÿ¯„GÆ)¼õAŠÛŸTU–ÚšP†Y?¨I¥Q’d„£`S„à]÷2¢ªƒ~ 2 ÉÂE[{ÈÜÁÊÂ-€:ò±èVý>ÿÊ߄Њ¿65‚TŠZ4DKct¿DªGâÔ£ÐßÚGnY{Öb»¼¶´-ø+–¯Â‘w¡/݌Ԩ¤EfT• mjÔ°dÓá»þ„Eí€U’A¸P{œ"ädîý$ÉqÄ€¡¡Åï¶ P%¤9ƒ³Å¿‰\»·Ú2:MRœÍÉû ‹ÕÒȲ‹xq­z¢k)ÿ–ç„!9Û¢¨ëHÛÛHµÚÕ«­n˜§´«QÆdÓá»~Aó‹aXãmX†ê·Áz ¡‡ÌOƒ6‹Ä Ë€×âNÅð ªt"ÔÊ/@ñ?‚ófl1e”æýF“›œ€WaÍÁ¯T2fï:)·¯Uo7Òk{=6‚õí-ÔЧ_²H»y3rû4%S 8¬i©jÔ°Ýþp\?É¥cê¿Õ(PQÒÒM›74 o|ibyæ0ª™ æyJP¢{Æ/€¢ëQñ}¤í EAè:¢VC½t©£[jRQÈÉr‡5LÙôàbÔ4WCÕ~¤è,‰Ûpª/CõêaȾôsH¼ bÉÐ"‹*Í‚t| Öÿ:Ž;—›û3 ^‘VB–SST [º•y¬ ÆÖ&ÒÆ:ÁÕËø…1¤ñIäC‡Qr9$I¾}%¨´€6ÉVžlÕjàÖÀ¶¨™Y"—JàØºÞÒ$=¯i©jTvˆ²éÁºþ6WßÔ·ÝÀ®oý5(})*ÏgÁ<g”#Pü{(þT/$ S[-f/ëÙ¬HWбmdÃ@Ñ5©IjS“X~€V)£V«•2j©ˆX¸Škfab ùð,R.ß vѪ×WDhVÀ²ílo …!ža zÊβïS‹Wð®gýÇt·ÖÖRÔ¨ÂÝ jk2%¥ºvI i.?Ö´˜¨½Îaê_Ââ¿‹¤{WkÚv\ôú[r2±³Ã|­Æx­†£ëT3PÄø8ÞØ8N";6ŠU%cUЗoÀò BU#Ÿ@š>„4>‰R¿([JX0È•βUôhËõpãïÌÎc½nÕFäjd¹¥cjL–™RUžoS£"Pów/¨ÍDª{ÁšâêÏ¥+è-[IŠëžj¼¢×sëuÔ6‹—­VÉV«L®¦áè:•l4 af L“òÔ’[Cµm´Š…¹¹›ëIÆ-Œ!ML"MÍ gsŽE׆”VjÓ4; ÙŠ¯£™eâÁŸ¦ø½ÛA äZ MU L³‘ñÏjZª5lÙôÀ þýa¥{ÙªËöK¼"‘°5IÚCüÙßòÊ©‹õÖ‡îºè®ËX¥B(IT3ª™ ŽnaàS C4«‚^±Ð­2Ji®âçò0>YÛ\¡žõÙ°¬Ö¢SÎd8ò+G.­!LŠ%&$‰’HaØRì‡a4’¨¤Û?ˆlÿ`$Ôº›&a)Û,hÏkKâÕVo­3aÚeü9˜åmÿ5¦ìe!È[y+š“«S͘HªBX(à TCäØèÕ*FµŠ¾´K‹„ºŸ/ ff‘Ç&âžÛ^@tÃõðãÏtø©§ ^|‘ÚÍ› +èNd1õ hqý§ ƒÿ¯c[W£2w;¨Bô°¦)ÉS_X{þz³&Ú:ÑÇböK¼„ m?Ñï$D!‚m“µm¦J%\UÅŠ­­«i`šx“Úä¸.šã U-²õA–ñóc0}Æ&‘Í,R¼zwòÝ+A@9žlXxÏ{0ï»ùë‹ûÜsdÆÆØ Ct×%›ÍR­V‘„ ÎÆqr»¥ÈêŧC¶¨ýbÌÖxt A x:ãÓv—½›ZiOkKç Ó€šºç¡».“;;xŠ‚c0CÇ×5¼BË÷Q½ja–KÈ;q¢“B19ƒ”‹bHOÖÜ(.U''™þÄ'¥"Êç>KY–Q% ݉Í•8¤Ð}GÓ8m©jÔAȦ£J}ê¤.~`A Ýõ§XÓfü9€ƒÁÛ\êiï &i¾æûâÁÊd°â0ÁWÂ|'—Ã!r­FƲÐ}é:,]'02㓬æÆóã ª~ê)¤ €ÿôXZ‹.¤¬Ç±k&“agg5® ܣ뼖(K¤uçüûmw#4¤Ðzf.P;M¬lÕhJ¡ËR•{µ}äl›\¼ªLMÓ¨ÆàºšF†ša` ÀsÑmÍqp—oà’ª1ù±“©UàKŸG}á9Jcc (Èa؈OµxZŠ†Ìª*ªÚ¡F”¾@uÔn°v©‹îUˆ³þ[?R­’5 o;¨Éc†ëb$B„j&ƒ­ëX™ hžªQÎç¹Y( 95r…®ÏÍqìé§rùÉa­¨ÐÈüc)¶Ÿ´lz€®?Éê¥R¦5ß®ä©ó¹)Ü>—¦êãJ¬Í·¸ügži^q&U¢dõ^¨rü89¯Wo»€r]:hÙtøY§IM¯£î¦Qº« ÐÃõßfxEÊ%x†áö— ÍýÆoPxôQª.PüÜçb8Ýø6Èpã’•$I-j”y‡¸ýƒµ¨É(àV¥ÛX™Ú/wßúÜÊS·bQSFXN<.¾ðËĤõaÛ6Aà8AP©T°×X­«QwJýtx1jë…CúTnƒ œö¼/î^jHµõÿ›´WP÷0VÛÁksõ]t. £ã8¸®Û°œÍ&:î»±Û¿dÓ,øïÖ] Hmj· oÓâw^b\ìÛ9¬x–çQò<à <ÏÃó<\×Åó¼˜i ÖGÉá;Mhpž&˜:‚?}ïØ} —§ù‡ïúÅ ´ö‚upA ùßÚ… ïkM“} »ý >¶7 Y³mÜ h<Þvœ®ð¥YEorêîÑÓ„fïè}Qmô¾‡þ,w’Û?ÀòÔ> H­å©=ÇŸ=móÒ.ÎGÂb­†åyX¾ß°–½àë(OÍŸ"4óاÀ9ý0¡™Ç=zú¶|o?yu×VçVø¿u‹ñç@ø¥üßÜ  èºT}ËóØ®Õð°±Ô*TO>Hhæ¨ÍG–Ñ?…7uêȾ~e9ÛôÀcÔ¯23ÿ0ÆìÙK{’å©[ˆ?û…—€ø¼±±Á5E!L$+ƒXE?“Ã;‰75¹ëÉ#x“³Qì¸Ï5LÝ0‘e#“E–2Ù²¬ }9É;Ôjö<¶þUÄÚÿ㵯ý.ÙÜ!Žœþ“g>ˆ:vøö í®¿¯»—†Ó*^gõò7Ø^~•À‹J:U?`ÛuA’˜lÌÃo‚éNÆ›œ¥6w’ ¶ŽA&‹}ê¡}ÿr3f¾F=“EUõ;*›ØÏþÕs51”_„»@néÓ¬¯“•¢.É™3̼ó˜¼çgŒ\ZcØÜ"bËY߆­“ý'ˆ•Ïï=Aj­ 6®›õ…—p«Í«²x¶`ãuÕW4VË'Ë¡Ÿ}a&‡3’ “£6j_Ï©"«hF¦QJRTM7ÐuóŽsÝoP¦fc¿H¶øE¦ýçѰPC÷>Á¡“O¿IÕ[‡ÆU›Û@m‡”Ì Vÿæ–âOß­²½ô*ë׿Myýb˱¥å9®m<Àuçü±)üÂ4Šª1>5»/ ˆ¦(ªÖ´ŠFYQî¸d箵ÚÊ Ìâ—˜(ý5“¼€aN0wúƒLžz‚Ì̽ýam‡ÖüÄê—R¤Òþ€n-½ºðí–ý×퇹^{„Eç]¸a´„¤¢jd²²¹14=s[âźdy§Ç‹?q ÖG„•706¿Àlõ/ɇ‡Î0uêqù’‘í«ÁüyÄúßðrïVñ:ë ßf{éUjVÓµozǹb?Îuç]XÁ @œtäÉd »¶hwS¼ø j‹Ûõ\(~sí/˜ ¾†!Û¨²ÆäÜý~çG;þ’¢uSÍŸC_w¥§k__x‰õk߯*-6öWüi~\ýù8!Z´œíñbÝEßñâ][žÚÕÒt8tïÐy^]¹Ž´ôW ŸÅ¿ñë7^÷öèÊIDATÃгºïƒ>õ™Ã§S:°º[еk/Eîýæk}å`šÅÚ»¸b?ζ׼`&›'cÈd#K˜/Ö›ŠÒâÅ‘EM«W®,PÞÙį.3|“{¥/2¥EVplê>ùÓ§Þ‡šŸ‰,jæCˆâ+ ‹j¯³tél-5KJµÐä†ó.®8³êžk&.z†ñ©YòcSäò =ŠG î V€0 í«ÌÏr\yŽ‚í?tô!¦O¾©3Ÿ¢¶ù¬]ú[Ö®½D-QRºR}ŒÅÚ#¬ò²¬ éŒLŽÉCóŒ"“Yƨ·8Ê¥M6VZöy®CÁ}™£â3§¾Œ!w^jÉ/ëòûY—ßê’¢ iÙü8ù±é‘¥º¿°¶Ç‹¡LYÿ‹|ùYL±Ì¢úÏÙÏãIùF²“Í36yxçÔƒa`UŠTv6ñjÙü8ÙüÄ]Íc4îÒ¬ÿV‡¬(Ƨ)ŒO¾Ý»é{‚Ñ:£1u4F ŽÆhŒ@Ñ:#PGc4F ŽÆhŒ@¨£1#PGc4F ŽÆÔѨ£1u4FcêhŒÆÔѸÛÇÿ/{YìDà¤IEND®B`‚drpython-3.11.1/todo.txt0000644000175000017500000000321011150445514015754 0ustar dktrkranzdktrkranzSome random remarks: (FS) ... Franz Steinhauesler (AB) ... Antonio Barbosa by Franz Steinhaeusler: Priority 1 (highest): - tackle the bug entries on sourceforge. - tackle the feature request entries on sourceforge. - a user reported about problems in UTF-8. Priority 2 (would be useful): Priority 3 (when time): - put edit scripts to DrScript Menu? - put edit bookmarsk to Bookmarks Menu? - add "Posititon Marker" to the core (most programs have it by default). - update doku for new plugins Priority 4 (when much time): - use icons from tango project (already three people gave me that hint). - Add a "What's new" to DrPyhton help (if a say 1.66 is released, it should show all new features/fixes in that version. A more button could show previous changes. - test on linux ("segmentation fault" happens often on program exit) - make some controls more userfriendly, as in windows on gtk. listctrl, listbox, combobox should have more keyboard support. - some problems in findautocomplete plugin on gtk. - split export/import files to drscrips, drplugins and preferences as it was before. - add a function (Check for updates on drpython) (automatically and/or manually (setup switch)) - add a function (Check for updates on plugins) (automatically and/or manually (setup switch)) - install plugins from sourceforge - assign plugin shortcuts right away? Priority 5(lowest): - download and install plugins or core automatically, if a update is found. - write a second "SearchInFiles" (a simple one) and add it to the core. -------- by ...: -------- by ... :) drpython-3.11.1/drPrompt.py0000644000175000017500000004342311235325201016433 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #The Prompt import os.path, re import wx import wx.stc from drProperty import * import drEncoding import drKeywords import drSTC reserved = [wx.stc.STC_CMD_NEWLINE, wx.stc.STC_CMD_CHARLEFT, wx.stc.STC_CMD_CHARRIGHT, wx.stc.STC_CMD_LINEUP, wx.stc.STC_CMD_LINEDOWN, wx.stc.STC_CMD_DELETEBACK, wx.stc.STC_CMD_HOME] class DrPrompt(drSTC.DrStyledTextControl): def __init__(self, parent, id, grandparent): drSTC.DrStyledTextControl.__init__(self, parent, id, grandparent) #Maximum Number of Commands to Keep Track of in Prompt self.MAX_PROMPT_COMMANDS = 25 self.CommandArray = [] self.CommandArrayPos = -1 self.IsAPrompt = True self.editpoint = 0 #Process self.process = None self.pid = -1 self.pythonintepreter = 0 self.commandinprogress = False #Goto Traceback: self.reTFilename = re.compile('\".*\"') #self.reTLinenumber = re.compile('line.*\d') #AB: self.reTLinenumber = re.compile('line \d+') self.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER) self.foundvalidline = False self.Bind(wx.stc.EVT_STC_MODIFIED, self.OnModified, id=id) self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) self.Bind(wx.EVT_KEY_UP, self.OnKeyUp) self.Bind(wx.EVT_UPDATE_UI, self.RunCheck, id=id) #Horrible hack by AB: #I don't know why, but on Linux wx.EVT_IDLE doesn't work without focus self.Bind(wx.EVT_IDLE, self.OnIdle) if wx.Platform == '__WXGTK__': self.Bind(wx.EVT_TIMER, self.OnIdle) self.t1 = wx.Timer(self) self.t1.Start(500) else: self.Bind(wx.EVT_IDLE, self.OnIdle) #End AB self.Bind(wx.EVT_IDLE, self.OnIdle) self.Bind(wx.EVT_LEFT_DCLICK, self.OnGotoSelectedLine) def _addoutput(self, checkinput=True): wx.Usleep(25) a = '' if checkinput and self.process.IsInputAvailable(): a = self._getoutput(self.inputstream) if self.process.IsErrorAvailable(): a += self._getoutput(self.errorstream) self.AddText(a) return a def _getoutput(self, targetstream): #used to get the output of a command in the prompt, and immediately add it to the prompt. added = False while not added: if targetstream.CanRead(): text = targetstream.read() added = True return text def _waitforoutput(self, targetoutput): ''' Dangerous! Only use this if you know what you are doing. Waits for output that has not yet appeared to show up in either the stdout or stderr of the current process. ''' # For some reasons, sometimes the python interpreter hangs, # waiting for something to read on stdin. # To solve this problems, we write an extra EOL on stdin self.outputstream.write('\n') #patch by Luca Falavigna - dktrkranz, 07/04/2008, thanks text = '' while True: if text.find(targetoutput) > -1: return #patch [ 1356168 ] Python and Import All Sometimes Jam Up #reverting: this freezes the pc. # while text.find(targetoutput) < 0: # wx.Yield() text = self._addoutput() def AddEncodedText(self, text): try: etext = drEncoding.EncodeText(self.grandparent, text) wx.stc.StyledTextCtrl.AddText(self, etext) except: print 'Error Encoding Text' def AddText(self, text): ro = self.GetReadOnly() self.SetReadOnly(0) self.AddEncodedText(text) self.SetReadOnly(ro) def ExecuteCommands(self, text): '''Executes Commands Separated by '\n' ''' if not text: return self._addoutput() self.commandinprogress = True text = text.rstrip() commands = text.split('\n') for command in commands: command += '\n' self._addoutput() try: etext = drEncoding.EncodeText(self.grandparent, command) except: print 'Error Encoding Text' return self.outputstream.write(etext) self.GotoPos(self.GetLength()) wx.stc.StyledTextCtrl.AddText(self, etext) self._addoutput((len(command) > 1)) self.editpoint = self.GetLength() self.ScrollToLine(self.LineFromPosition(self.editpoint)) self.commandinprogress = False def GetEditPoint(self): return self.editpoint def InsertEncodedText(self, pos, text): try: etext = drEncoding.EncodeText(self.grandparent, text) wx.stc.StyledTextCtrl.InsertText(self, pos, etext) except: print 'Error Encoding Text' def InsertText(self, pos, text): ro = self.GetReadOnly() self.SetReadOnly(0) self.InsertEncodedText(pos, text) self.SetReadOnly(ro) def OnIdle(self, event): if (self.process is not None) and (not self.commandinprogress): if self.inputstream.CanRead(): text = self.inputstream.read() self.AddEncodedText(text) self.EmptyUndoBuffer() self.editpoint = self.GetLength() self.GotoPos(self.editpoint) self.ScrollToLine(self.LineFromPosition(self.editpoint)) if self.errorstream.CanRead(): text = self.errorstream.read() self.AddEncodedText(text) self.EmptyUndoBuffer() self.editpoint = self.GetLength() self.GotoPos(self.editpoint) self.ScrollToLine(self.LineFromPosition(self.editpoint)) def OnGotoSelectedLine(self, event): self.foundvalidline = False self.grandparent.PPost(self.grandparent.EVT_DRPY_PROMPT_GOTO) line = self.GetLine(self.GetCurrentLine()) #pattern for traceback? if not self.foundvalidline: fn = self.reTFilename.search(line) ln = self.reTLinenumber.search(line) if (fn is not None) and (ln is not None): self.foundvalidline = True self.gotofilename = fn.group().strip('\"') try: self.gotolinenumber = int(ln.group().strip('line ')) - 1 except: self.gotolinenumber = 0 #pattern for pycheckeroutput? if not self.foundvalidline: line = line.replace ('\\', '/') pos = line.find (': ') if pos > -1: s = line[:pos] split = s.rsplit(':', 1) if len (split): self.foundvalidline = True self.gotofilename = split[0] try: self.gotolinenumber = int(split[1]) - 1 except: self.gotolinenumber = 0 if self.foundvalidline: if os.path.exists(self.gotofilename): self.grandparent.OpenOrSwitchToFile(self.gotofilename, editRecentFiles=False) #self.grandparent.txtDocument.ScrollToLine(linenumber) #patch: [ 1366679 ] Goto Line Should Not Display At Top Of Window top = self.gotolinenumber - self.grandparent.txtDocument.LinesOnScreen()/2 if top < 0: top = 0 self.grandparent.txtDocument.ScrollToLine(top) self.grandparent.txtDocument.GotoLine(self.gotolinenumber) self.grandparent.txtDocument.EnsureCaretVisible() self.grandparent.txtDocument.SetFocus() def CheckAndCorrectAsciiText(self, text): newtext = str() corrected = False for c in text: if ord(c) > 127: c = '-' corrected = True newtext = newtext + c return newtext, corrected def OnKeyDown(self, event): if self.pid == -1: return result = self.grandparent.RunShortcuts(event) if result > -1: pos = self.GetCurrentPos() if not self.pid == -1: if (pos >= self.editpoint) and (result == wx.stc.STC_CMD_NEWLINE): self.commandinprogress = True text = self.GetTextRange(self.editpoint, self.GetLength()) l = len(self.CommandArray) if l < self.MAX_PROMPT_COMMANDS: if text in self.CommandArray: self.CommandArray.pop(self.CommandArray.index(text)) self.CommandArray.insert(0, text) self.CommandArrayPos = -1 else: self.CommandArray.pop() self.CommandArray.insert(0, text) self.CommandArrayPos = -1 if not text: text = '\n' self.GotoPos(self.GetLength()) self.AddText(self.GetEndOfLineCharacter()) elif text[-1] != '\n': text += '\n' self.GotoPos(self.GetLength()) self.AddText(self.GetEndOfLineCharacter()) try: etext = drEncoding.EncodeText(self.grandparent, text) except: print 'Error Encoding Text' return #ugly hack, but otherwise, drpython crashes etext, corrected = self.CheckAndCorrectAsciiText(etext) if corrected: self.grandparent.ShowMessage("Sorry, only ascii codes until 127 possible.\nOtherwiese the program crashes", "DrPython Error") self.outputstream.write(etext) self.GotoPos(self.GetLength()) self._addoutput() self.editpoint = self.GetLength() self.ScrollToLine(self.LineFromPosition(self.editpoint)) self.commandinprogress = False elif result == wx.stc.STC_CMD_LINEUP: l = len(self.CommandArray) if self.CommandArray: if (self.CommandArrayPos + 1) < l: self.GotoPos(self.editpoint) self.SetTargetStart(self.editpoint) self.SetTargetEnd(self.GetLength()) self.CommandArrayPos = self.CommandArrayPos + 1 self.ReplaceTarget(self.CommandArray[self.CommandArrayPos]) elif result == wx.stc.STC_CMD_LINEDOWN: if (len(self.CommandArray) > 0): self.GotoPos(self.editpoint) self.SetTargetStart(self.editpoint) self.SetTargetEnd(self.GetLength()) if (self.CommandArrayPos - 1) > -1: self.CommandArrayPos = self.CommandArrayPos - 1 self.ReplaceTarget(self.CommandArray[self.CommandArrayPos]) else: if (self.CommandArrayPos - 1) > -2: self.CommandArrayPos = self.CommandArrayPos - 1 self.ReplaceTarget("") if ((pos > self.editpoint) and (result in reserved)) or \ (pos >= self.editpoint) and (result == wx.stc.STC_CMD_CHARRIGHT): event.Skip() def OnKeyUp(self, event): if self.pid == -1: event.Skip() return keycode = event.GetKeyCode() #franz: pos was not used if keycode == wx.WXK_HOME: if self.GetCurrentPos() < self.editpoint: self.GotoPos(self.editpoint) return elif keycode == wx.WXK_PRIOR: if self.GetCurrentPos() < self.editpoint: self.GotoPos(self.editpoint) return if keycode == wx.WXK_RETURN: #patch from merwinb, 2009-0728, thanks (Prompt window scrolls to wrong position) self.GotoPos(self.GetCurrentPos()) event.Skip() def OnModified(self, event): if not (self.grandparent.prefs.promptwordwrap): ll = self.TextWidth(wx.stc.STC_STYLE_DEFAULT, "OOO") x = 0 spaces = "" while x < self.grandparent.prefs.prompttabwidth: spaces = spaces + " " x = x + 1 current_width = self.GetScrollWidth() line = self.GetCurLine()[0].replace('\t', spaces) actual_width = self.TextWidth(wx.stc.STC_STYLE_DEFAULT, line) if current_width < actual_width: self.SetScrollWidth(actual_width + ll) def RunCheck(self, event): if (self.GetCurrentPos() < self.editpoint) or (self.pid == -1): self.SetReadOnly(1) else: self.SetReadOnly(0) def SetupPrefsPrompt(self, notmdiupdate = 1): self.SetEndAtLastLine(not self.grandparent.prefs.promptscrollextrapage) if notmdiupdate: self.SetViewWhiteSpace(self.grandparent.prefs.promptwhitespaceisvisible) self.SetViewEOL(self.grandparent.prefs.promptwhitespaceisvisible and self.grandparent.prefs.vieweol) if self.grandparent.prefs.promptwordwrap: self.SetWrapMode(wx.stc.STC_WRAP_WORD) else: self.SetWrapMode(wx.stc.STC_WRAP_NONE) if self.grandparent.prefs.prompteolmode == 1: self.SetEOLMode(wx.stc.STC_EOL_CRLF) elif self.grandparent.prefs.prompteolmode == 2: self.SetEOLMode(wx.stc.STC_EOL_CR) else: self.SetEOLMode(wx.stc.STC_EOL_LF) self.SetTabWidth(self.grandparent.prefs.prompttabwidth) self.SetUseTabs(self.grandparent.prefs.promptusetabs) self.SetMarginWidth(1, self.grandparent.prefs.promptmarginwidth) if self.grandparent.prefs.promptusestyles: self.SetKeyWords(0, drKeywords.GetKeyWords(0)) self.SetLexer(drKeywords.GetLexer(0)) self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, self.grandparent.prefs.txtPromptStyleDictionary[0]) self.StyleClearAll() self.StartStyling(0, 0xff) self.SetCaretWidth(self.grandparent.prefs.promptcaretwidth) self.SetCaretForeground(self.grandparent.prefs.txtPromptStyleDictionary[15]) if self.grandparent.prefs.promptusestyles < 2: self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER, self.grandparent.prefs.txtPromptStyleDictionary[1]) self.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT, self.grandparent.prefs.txtPromptStyleDictionary[2]) self.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD, self.grandparent.prefs.txtPromptStyleDictionary[3]) self.StyleSetSpec(wx.stc.STC_P_CHARACTER, self.grandparent.prefs.txtPromptStyleDictionary[4]) self.StyleSetSpec(wx.stc.STC_P_CLASSNAME, self.grandparent.prefs.txtPromptStyleDictionary[5]) self.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, self.grandparent.prefs.txtPromptStyleDictionary[6]) self.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, self.grandparent.prefs.txtPromptStyleDictionary[7]) self.StyleSetSpec(wx.stc.STC_P_DEFNAME, self.grandparent.prefs.txtPromptStyleDictionary[8]) self.StyleSetSpec(wx.stc.STC_P_WORD, self.grandparent.prefs.txtPromptStyleDictionary[9]) self.StyleSetSpec(wx.stc.STC_P_NUMBER, self.grandparent.prefs.txtPromptStyleDictionary[10]) self.StyleSetSpec(wx.stc.STC_P_OPERATOR, self.grandparent.prefs.txtPromptStyleDictionary[11]) self.StyleSetSpec(wx.stc.STC_P_STRING, self.grandparent.prefs.txtPromptStyleDictionary[12]) self.StyleSetSpec(wx.stc.STC_P_STRINGEOL, self.grandparent.prefs.txtPromptStyleDictionary[13]) self.StyleSetSpec(wx.stc.STC_P_TRIPLE, self.grandparent.prefs.txtPromptStyleDictionary[14]) self.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, self.grandparent.prefs.txtPromptStyleDictionary[14]) self.SetSelForeground(1, getStyleProperty("fore", self.grandparent.prefs.txtPromptStyleDictionary[16])) self.SetSelBackground(1, getStyleProperty("back", self.grandparent.prefs.txtPromptStyleDictionary[16])) def SetText(self, text): ro = self.GetReadOnly() self.SetReadOnly(0) wx.stc.StyledTextCtrl.SetText(self, text) self.SetReadOnly(ro) def SetSelectedText(self, text): ro = self.GetReadOnly() self.SetReadOnly(0) self.SetTargetStart(self.GetSelectionStart()) self.SetTargetEnd(self.GetSelectionEnd()) self.ReplaceTarget(text) self.SetReadOnly(ro) drpython-3.11.1/drPopUpMenuDialog.py0000644000175000017500000003174211150445514020171 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Pop Up Menu Dialog import os.path, re import wx import drScrolledMessageDialog import drShortcutsFile def GetPopUpMenuLabels(filename, frame): try: f = file(filename, 'r') text = f.read() f.close() except: drScrolledMessageDialog.ShowMessage(frame, 'File error with: "' + filename + '".', "ERROR") return [] rePopUpMenu = re.compile(r'^\s*?DrFrame\.AddPluginPopUpMenuFunction\(.*\)', re.MULTILINE) allPopUps = rePopUpMenu.findall(text) PopUpArray = [] for s in allPopUps: #From the Left most '(' start = s.find('(') #To the Right most ')' end = s.rfind(')') if (start > -1) and (end > -1): s = s[start+1:end] i = s.find(',') e = i + 1 + s[i+1:].find(',') arglabel = s[i+1:e].strip().strip('"') PopUpArray.append(":"+arglabel) return PopUpArray class drPopUpMenuDialog(wx.Dialog): def __init__(self, parent): wx.Dialog.__init__(self, parent, -1, ("Customize Pop Up Menu"), wx.DefaultPosition, wx.Size(-1, -1), wx.DEFAULT_DIALOG_STYLE | wx.THICK_FRAME) wx.Yield() self.ID_PROGRAM = 1001 self.ID_POPUP = 1002 self.ID_LIST = 1300 self.ID_ADD = 1003 self.ID_REMOVE = 1004 self.ID_UPDATE = 1005 self.ID_SAVE = 1006 self.ID_UP = 1111 self.ID_DOWN = 2222 self.parent = parent self.theSizer = wx.FlexGridSizer(5, 4, 5, 10) self.menubuttonSizer = wx.BoxSizer(wx.VERTICAL) self.listSizer = wx.BoxSizer(wx.HORIZONTAL) self.datdirectory = parent.datdirectory popupmenulist = [] map(popupmenulist.append, parent.popupmenulist) if not popupmenulist: popupmenulist = ["", "Undo", "Redo", "", "Cut", "Copy", "Paste", "Delete", "", "Select All"] else: popupmenulist.insert(0, "") programmenulist = drShortcutsFile.GetShortcutList() programmenulist.sort() programmenulist.insert(0, "") self.ListArray = [] self.ListArray.append(programmenulist) #STC stclist = [] map(stclist.append, drShortcutsFile.GetSTCShortcutList()) stclist.insert(0, "") self.ListArray.append(stclist) #DrScript drscriptlist = [] map(drscriptlist.append, parent.drscriptmenu.titles) x = 0 l = len(drscriptlist) while x < l: drscriptlist[x] = ":" + drscriptlist[x] x = x + 1 drscriptlist.insert(0, "") self.ListArray.append(drscriptlist) #Plugins plist = os.listdir(parent.pluginsdirectory) self.PluginList = [] plugins = [] for p in plist: i = p.find(".py") l = len(p) if i > -1 and (i + 3 == l): self.PluginList.append(":" + p[:i]) plugins.append(p[:i]) poplist = [] for plugin in plugins: pluginfile = os.path.join(self.parent.pluginsdirectory, plugin + ".py") pluginlist = GetPopUpMenuLabels(pluginfile, self) plist = self.parent.GetPluginLabels(pluginfile) for p in plist: if not (p in pluginlist): pluginlist.append(p) if pluginlist: pluginlist.insert(0, "") self.ListArray.append(pluginlist) else: poplist.append(":" + plugin) for popl in poplist: i = self.PluginList.index(popl) self.PluginList.pop(i) list = ["Standard", "Text Control", "DrScript"] list.extend(self.PluginList) self.cboList = wx.ComboBox(self, self.ID_LIST, "Standard", wx.DefaultPosition, (200, -1), list, wx.CB_DROPDOWN|wx.CB_READONLY) self.programmenu = wx.ListBox(self, self.ID_PROGRAM, wx.DefaultPosition, wx.Size(250, 300), programmenulist) self.popupmenu = wx.ListBox(self, self.ID_POPUP, wx.DefaultPosition, wx.Size(250, 300), popupmenulist) self.btnUp = wx.Button(self, self.ID_UP, " Up ") self.btnAdd = wx.Button(self, self.ID_ADD, " ---> ") self.btnRemove = wx.Button(self, self.ID_REMOVE, " Remove ") self.btnDown = wx.Button(self, self.ID_DOWN, " Down ") self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(self.btnAdd, 0, wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(self.btnUp, 0, wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(self.btnDown, 0, wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(self.btnRemove, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.listSizer.Add(wx.StaticText(self, -1, "List: "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.listSizer.Add(self.cboList, 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.listSizer, 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Current List:"), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Pop Up Menu:"), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.programmenu, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.menubuttonSizer, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.popupmenu, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.btnUpdate = wx.Button(self, self.ID_UPDATE, "&Update") self.btnSave = wx.Button(self, self.ID_SAVE, "&Save") self.btnClose = wx.Button(self, 101, "&Close") self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.btnClose, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.btnUpdate, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.btnSave, 0, wx.SHAPED | wx.ALIGN_CENTER) self.btnClose.SetDefault() self.SetAutoLayout(True) self.SetSizerAndFit(self.theSizer) self.Bind(wx.EVT_BUTTON, self.OnbtnUp, id=self.ID_UP) self.Bind(wx.EVT_BUTTON, self.OnbtnAdd, id=self.ID_ADD) self.Bind(wx.EVT_BUTTON, self.OnbtnRemove, id=self.ID_REMOVE) self.Bind(wx.EVT_BUTTON, self.OnbtnDown, id=self.ID_DOWN) self.Bind(wx.EVT_BUTTON, self.OnbtnUpdate, id=self.ID_UPDATE) self.Bind(wx.EVT_BUTTON, self.OnbtnSave, id=self.ID_SAVE) self.Bind(wx.EVT_BUTTON, self.OnbtnClose, id=101) self.Bind(wx.EVT_COMBOBOX, self.OnList, id=self.ID_LIST) self.parent.LoadDialogSizeAndPosition(self, 'popupmenudialog.sizeandposition.dat') def OnCloseW(self, event): self.parent.SaveDialogSizeAndPosition(self, 'popupmenudialog.sizeandposition.dat') if event is not None: event.Skip() def OnbtnAdd(self, event): tselection = self.programmenu.GetStringSelection() tsel = self.programmenu.GetSelection() if tsel == -1: drScrolledMessageDialog.ShowMessage(self, "Nothing Selected to Add", "Mistake") return sel = self.popupmenu.GetSelection() if sel == -1: sel = 0 separator = (tselection == "") if separator: tselection = "" self.popupmenu.InsertItems([tselection], sel+1) self.popupmenu.SetSelection(sel+1) def OnbtnClose(self, event): self.Close(1) def OnbtnDown(self, event): sel = self.popupmenu.GetSelection() if sel < self.popupmenu.GetCount()-1 and sel > 0: txt = self.popupmenu.GetString(sel) self.popupmenu.Delete(sel) self.popupmenu.InsertItems([txt], sel+1) self.popupmenu.SetSelection(sel+1) def OnbtnRemove(self, event): sel = self.popupmenu.GetSelection() if not sel: drScrolledMessageDialog.ShowMessage(self, "You cannot remove the root item.", "Mistake") return if sel == -1: drScrolledMessageDialog.ShowMessage(self, "Nothing Selected to Remove", "Mistake") return self.popupmenu.Delete(sel) self.popupmenu.SetSelection(sel-1) def OnbtnUp(self, event): sel = self.popupmenu.GetSelection() if sel > 1: txt = self.popupmenu.GetString(sel) self.popupmenu.Delete(sel) self.popupmenu.InsertItems([txt], sel-1) self.popupmenu.SetSelection(sel-1) def OnbtnUpdate(self, event): y = 0 c = self.popupmenu.GetCount() popupmenulist = [] while y < c: pop = self.popupmenu.GetString(y) if not pop == "": popupmenulist.append(pop) y = y + 1 self.parent.popupmenulist = popupmenulist if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, ("Succesfully updated the current instance of DrPython.\nClick Save to make it permanent."), "Updated Pop Up Menu") def OnbtnSave(self, event): y = 0 c = self.popupmenu.GetCount() popupmenustring = "" popupmenulist = [] while y < c: pop = self.popupmenu.GetString(y) if not pop == "": popupmenustring = popupmenustring + pop + "\n" popupmenulist.append(pop) y = y + 1 self.parent.popupmenulist = popupmenulist popupfile = self.datdirectory + "/popupmenu.dat" try: f = file(popupfile, 'w') f.write(popupmenustring) f.close() except IOError: drScrolledMessageDialog.ShowMessage(self, ("There were some problems writing to:\n" + popupfile + "\nEither the file is having metaphysical issues, or you do not have permission to write.\nFor metaphysical issues, consult the documentation.\nFor permission issues, change the permissions on the directory to allow yourself write access.\nDrPython will now politely ignore your request to save.\nTry again when you have fixed the problem."), "Write Error") return if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, ("Succesfully wrote to:\n" + popupfile + "\nand updated the current instance of DrPython."), "Saved Pop Up Menu") def OnList(self, event): sel = self.cboList.GetSelection() self.programmenu.Set(self.ListArray[sel]) drpython-3.11.1/drRegularExpressionDialog.py0000644000175000017500000003573511150445515021771 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Regular Expression Dialog import re import wx import drScrolledMessageDialog import drFileDialog wildcard = "Text File (*.txt)|*.txt|All files (*)|*" class drRETextCtrl(wx.TextCtrl): def __init__(self, parent, id, value, pos, size): wx.TextCtrl.__init__(self, parent, id, value, pos, size) self.Bind(wx.EVT_CHAR, self.OnChar) def OnChar(self, event): if event.GetKeyCode() == wx.WXK_ESCAPE: self.GetParent().OnbtnCancel(event) elif event.GetKeyCode() == wx.WXK_RETURN: self.GetParent().OnbtnOk(event) else: event.Skip() class drRegularExpressionDialog(wx.Frame): def __init__(self, parent, id, title, prompthasfocus = 0, infiles = 0): if wx.GetApp().GetTopWindow().PLATFORM_IS_WIN: size = wx.Size(500, 160) else: size = wx.Size(500, 110) wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, size, wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.THICK_FRAME | wx.RESIZE_BORDER) self.ID_OK = 1001 self.ID_CANCEL = 1002 self.ID_LOAD = 1003 self.ID_SAVE = 1004 self.ID_ANYCHARACTER = 1010 self.ID_ANYCHARACTERD = 10101 self.ID_ANYCHARACTERND = 10102 self.ID_ANYCHARACTERW = 10103 self.ID_ANYCHARACTERNW = 10104 self.ID_ANYCHARACTERA = 10105 self.ID_ANYCHARACTERNA = 10106 self.ID_SETOFCHARACTERS = 10107 self.ID_START = 1011 self.ID_END = 1012 self.ID_STARTD = 1111 self.ID_ENDD = 1112 self.ID_EDGEW = 1211 self.ID_EDGENW = 1212 self.ID_REPSZEROPLUS = 1013 self.ID_REPSONEPLUS = 1014 self.ID_REPSZEROORONE = 1015 self.ID_REPSN = 1016 self.ID_GROUP = 1017 self.ID_OR = 10171 self.ID_POSITIVE_LOOKAHEAD = 1018 self.ID_NEGATIVE_LOOKAHEAD = 1019 self.ID_POSITIVE_LOOKBEHIND = 1118 self.ID_NEGATIVE_LOOKBEHIND = 1119 self.ID_INSERT_NORMAL_TEXT = 1050 self.insert = (title == "Insert Regular Expression") self.theSizer = wx.FlexGridSizer(4, 1, 5, 10) okcancelSizer = wx.BoxSizer(wx.HORIZONTAL) self.parent = parent self.prompthasfocus = prompthasfocus if self.insert: self.defaultdirectory = self.parent.prefs.defaultdirectory self.enablefeedback = self.parent.prefs.enablefeedback self.filedialogparent = self.parent elif not infiles: self.defaultdirectory = self.parent.GetParent().prefs.defaultdirectory self.enablefeedback = self.parent.GetParent().prefs.enablefeedback self.filedialogparent = self.parent.GetParent() else: self.defaultdirectory = self.parent.GetGrandParent().prefs.defaultdirectory self.enablefeedback = self.parent.GetGrandParent().prefs.enablefeedback self.filedialogparent = self.parent.GetGrandParent() FileMenu = wx.Menu() FileMenu.Append(self.ID_LOAD, "&Load", " Load Regular Expression") FileMenu.Append(self.ID_SAVE, "&Save", " Save Regular Expression") TextMenu = wx.Menu() TextMenu.Append(self.ID_INSERT_NORMAL_TEXT, "Normal Text") TextMenu.Append(self.ID_ANYCHARACTER, "Any Character \".\"") TextMenu.Append(self.ID_ANYCHARACTERD, "Any Decimal Digit \"\\d\"") TextMenu.Append(self.ID_ANYCHARACTERND, "Any Non Digit \"\\D\"") TextMenu.Append(self.ID_ANYCHARACTERW, "Any Whitespace Character \"\\s\"") TextMenu.Append(self.ID_ANYCHARACTERNW, "Any Non Whitespace Character \"\\S\"") TextMenu.Append(self.ID_ANYCHARACTERA, "Any AlphaNumeric Character \"\\w\"") TextMenu.Append(self.ID_ANYCHARACTERNA, "Any Non AlphaNumeric Character \"\\W\"") TextMenu.Append(self.ID_SETOFCHARACTERS, "A Set of Characters \"[ ]\"") RepetitionsMenu = wx.Menu() RepetitionsMenu.Append(self.ID_REPSZEROPLUS, "0 Or More \"*\"") RepetitionsMenu.Append(self.ID_REPSONEPLUS, "1 Or More \"+\"") RepetitionsMenu.Append(self.ID_REPSZEROORONE, "0 Or 1 \"?\"") RepetitionsMenu.Append(self.ID_REPSN, "n \"{n}\"") LimitMenu = wx.Menu() LimitMenu.Append(self.ID_START, "The Start Of Each Line \"^\"") LimitMenu.Append(self.ID_END, "The End Of Each Line \"$\"") LimitMenu.Append(self.ID_STARTD, "The Start of the Document \"\\A\"") LimitMenu.Append(self.ID_ENDD, "The End of the Document \"\\Z\"") LimitMenu.Append(self.ID_EDGEW, "The Start or End of a Word \"\\b\"") LimitMenu.Append(self.ID_EDGENW, "Text That is Not at Either End of a Word \"\\B\"") lookMenu = wx.Menu() lookMenu.Append(self.ID_POSITIVE_LOOKAHEAD, "Lookahead: Positive \"(?=)\"") lookMenu.Append(self.ID_NEGATIVE_LOOKAHEAD, "Lookahead: Negative \"(?!)\"") lookMenu.Append(self.ID_POSITIVE_LOOKBEHIND, "Lookbehind: Positive \"(?<=)\"") lookMenu.Append(self.ID_NEGATIVE_LOOKBEHIND, "Lookbehind: Negative \"(? 0: if self.insert: if self.prompthasfocus: pos = self.parent.txtPrompt.GetCurrentPos() self.parent.txtPrompt.InsertText(pos, result) self.parent.txtPrompt.GotoPos(pos + l) else: pos = self.parent.txtDocument.GetCurrentPos() self.parent.txtDocument.InsertText(pos, result) self.parent.txtDocument.GotoPos(pos + l) else: self.parent.txtSearchFor.SetValue(result) self.Close(1) def OnbtnOr(self, event): self.insertText('|') def OnbtnRepsN(self, event): d = wx.TextEntryDialog(self, "Enter The Desired Number of Repetitions:", "Insert N Repetitions", "") answer = d.ShowModal() v = d.GetValue() d.Destroy() if answer == wx.ID_OK: self.insertText('{' + v + '}') def OnbtnRepsOnePlus(self, event): self.insertText('+') def OnbtnRepsZeroOrOne(self, event): self.insertText('?') def OnbtnRepsZeroPlus(self, event): self.insertText('*') def OnbtnSetOfCharacters(self, event): self.insertText('[]') pos = self.txtRE.GetInsertionPoint() self.txtRE.SetInsertionPoint(pos - 1) def OnbtnStart(self, event): self.insertText('^') def OnbtnStartD(self, event): self.insertText('\\A') def OnLoad(self, event): dlg = drFileDialog.FileDialog(self.filedialogparent, "Load Regular Expression From", wildcard) if self.defaultdirectory: try: dlg.SetDirectory(self.defaultdirectory) except: drScrolledMessageDialog.ShowMessage(self, ("Error Setting Default Directory To: " + self.defaultdirectory), "DrPython Error") if dlg.ShowModal() == wx.ID_OK: refile = dlg.GetPath().replace("\\", "/") try: f = file(refile, 'r') text = f.read() f.close() except: drScrolledMessageDialog.ShowMessage(self, ("Error Reading From: " + refile), "DrPython Error") text = "" if (text.find('\n') > -1) or (text.find('\r') > -1): drScrolledMessageDialog.ShowMessage(self, ("Error Reading From: " + refile), "DrPython Error") text = "" self.txtRE.SetValue(text) dlg.Destroy() self.Raise() def OnSave(self, event): dlg = drFileDialog.FileDialog(self.filedialogparent, "Save Regular Expression As", wildcard, IsASaveDialog=True) if self.defaultdirectory: try: dlg.SetDirectory(self.defaultdirectory) except: drScrolledMessageDialog.ShowMessage(self, ("Error Setting Default Directory To: " + self.defaultdirectory), "DrPython Error") if dlg.ShowModal() == wx.ID_OK: refile = dlg.GetPath().replace("\\", "/") try: f = file(refile, 'w') f.write(self.txtRE.GetValue()) f.close() except: drScrolledMessageDialog.ShowMessage(self, ("Error Writing To: " + refile), "DrPython Error") return if self.enablefeedback: drScrolledMessageDialog.ShowMessage(self, ("Successfully Saved: " + refile), "Save Success") dlg.Destroy() self.Raise() drpython-3.11.1/drSourceBrowser.py0000644000175000017500000004003611150445514017761 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Icons taken from "Noia Kde 100" by Carles Carbonell Bernado from the KDE-LOOK site (some edited a bit). # An excellent artist. #Source Browser import wx import drScrolledMessageDialog from drProperty import * import wx.stc import re recolour = re.compile('#\w+') def GetCount(line, compchar): l = len(line) x = 0 y = 0 while x < l: if line[x] == compchar: y = y + 1 elif not line[x].isspace(): x = l x = x + 1 return y class drTree(wx.TreeCtrl): def __init__(self, parent, id, point, size, style, ancestor): wx.TreeCtrl.__init__(self, parent, id, point, size, style) self.grandparent = ancestor self.parent = parent style = self.grandparent.prefs.sourcebrowserstyle yarrr = convertStyleStringToWXFontArray(style) if self.grandparent.prefs.sourcebrowseruseimages==1: imagesize = (16,16) self.imagelist = wx.ImageList(imagesize[0], imagesize[1]) self.images = [wx.BitmapFromImage(wx.Image(self.grandparent.bitmapdirectory + "/16/class.png", wx.BITMAP_TYPE_PNG)), wx.BitmapFromImage(wx.Image(self.grandparent.bitmapdirectory + "/16/def.png", wx.BITMAP_TYPE_PNG)), wx.BitmapFromImage(wx.Image(self.grandparent.bitmapdirectory + "/16/import.png", wx.BITMAP_TYPE_PNG)), wx.BitmapFromImage(wx.Image(self.grandparent.bitmapdirectory + "/16/transparent.png", wx.BITMAP_TYPE_PNG))] map(self.imagelist.Add, self.images) self.AssignImageList(self.imagelist) w = wx.Font(yarrr[1], wx.NORMAL, wx.NORMAL, wx.NORMAL, yarrr[2]) w.SetFaceName(yarrr[0]) if yarrr[3]: w.SetWeight(wx.BOLD) else: w.SetWeight(wx.NORMAL) if yarrr[4]: w.SetStyle(wx.ITALIC) else: w.SetStyle(wx.NORMAL) self.SetFont(w) f = convertColorPropertyToColorArray(getStyleProperty("fore", style)) b = convertColorPropertyToColorArray(getStyleProperty("back", style)) self.TextColor = wx.Colour(f[0], f[1], f[2]) self.SetForegroundColour(self.TextColor) self.SetBackgroundColour(wx.Colour(b[0], b[1], b[2])) self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnItemActivated, id=id) self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnItemActivated, id=id) self.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnExpandedCollapse, id=id) self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnExpandedCollapse, id=id) def OnExpandedCollapse(self,event): event.Skip() #AB: it is necesserary to do something to refresh scroll bars def OnCompareItems(self, item1, item2): #Overriding Base, Return -1 for <, 0 for ==, +1 for > t1 = self.GetItemText(item1).lower() t2 = self.GetItemText(item2).lower() x = 0 l = len(t1) if l > len(t2): l = len(t2) while x < l: if t1[x] < t2[x]: return -1 elif t1[x] > t2[x]: return 1 x = x + 1 if l == len(t2): return -1 return 0 def OnItemActivated(self, event): sel = self.GetSelection() if not sel.IsOk(): return t = self.GetItemText(sel) try: i = self.parent.ItemsIndex.index(sel) pos = self.parent.ItemsPos[i] line = self.grandparent.txtDocument.LineFromPosition(pos) if self.grandparent.prefs.docfolding: #Make sure the line is visible. self.grandparent.txtDocument.EnsureVisible(line) self.grandparent.txtDocument.ScrollToLine(line) self.grandparent.txtDocument.GotoLine(line) self.grandparent.txtDocument.GotoPos(pos) self.grandparent.Raise() self.grandparent.SetFocus() if self.grandparent.prefs.sourcebrowsercloseonactivate: self.parent.OnbtnClose(event) else: self.grandparent.txtDocument.SetFocus() except: drScrolledMessageDialog.ShowMessage(self.parent, 'Error Activating Item', 'Source Browser Error') class drSourceBrowserPanel(wx.Panel): def __init__(self, parent, id, Position, Index): wx.Panel.__init__(self, parent, id) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.mixed = 0 self.renext = re.compile(r'^[ \t]*[^#^\s]', re.M) self.reinspect = re.compile(r'(^[ \t]*?class\s.*[(:])|(^[ \t]*?def\s.*[(:])|(^[ \t]*?import\s.*$)|(^[ \t]*?from\s.*$)|(^\s*#---.+)', re.MULTILINE) self.panelparent = parent.GetGrandParent().GetParent() self.parent = parent.GetGrandParent().GetGrandParent() self.classtree = drTree(self, -1, wx.Point(0, 0), wx.Size(400, 200), wx.TR_DEFAULT_STYLE|wx.TR_HIDE_ROOT, self.parent) self.btnClose = wx.Button(self, 101, "&Close") self.btnRefresh = wx.Button(self, 102, "&Refresh") self.theSizer.Add(self.classtree, 9, wx.EXPAND) self.bSizer = wx.BoxSizer(wx.HORIZONTAL) self.bSizer.Add(self.btnRefresh, 0, wx.SHAPED | wx.ALIGN_LEFT) self.bSizer.Add(self.btnClose, 0, wx.SHAPED | wx.ALIGN_LEFT) self.edSearch = wx.TextCtrl(self, -1, "",size=(-1,-1)) #edit for search in tree self.bSizer.Add(self.edSearch, 1, wx.ALIGN_RIGHT) self.theSizer.Add(self.bSizer, 0, wx.EXPAND) self.position = Position self.Index = Index self.Bind(wx.EVT_BUTTON, self.OnbtnClose, id=101) self.Bind(wx.EVT_BUTTON, self.OnbtnRefresh, id=102) self.parent.PBind(self.parent.EVT_DRPY_DOCUMENT_CHANGED, self.OnbtnRefresh, None) self.edSearch.Bind(wx.EVT_KEY_UP, self.OnedSearch) self.edSearch.SetToolTipString("Search in the class-tree") self.eol = self.parent.txtDocument.GetEndOfLineCharacter() if not self.Browse(): self.mixed = 1 msg = 'This document is mixed. It uses tabs and spaces for indentation.\nDrPython may not be able to correctly display the class browser. Please use "Edit:Whitespace:Clean Up Indentation" to fix this.' drScrolledMessageDialog.ShowMessage(self, msg, "Check Indentation Results") self.SetAutoLayout(True) self.SetSizer(self.theSizer) #AB: self.Bind(wx.EVT_WINDOW_DESTROY,self.OnClose) def OnClose(self, event): """Cleaning old references. It is necessary when the notebook panel is closed on his tab menu. Otherwise we get: wx._core.PyDeadObjectError: The C++ part of the drSourceBrowserPanel object has been deleted, attribute access no longer allowed.""" self.parent.SourceBrowser = None self.parent.PUnbind(self.parent.EVT_DRPY_DOCUMENT_CHANGED, self.OnbtnRefresh) #AB end def Browse(self): #Submitted Patch: Christian Daven self.classtree.Freeze() #/Submitted Patch: Christian Daven self.classtree.DeleteAllItems() self.root = self.classtree.AddRoot("") self.ItemsIndex = [] self.ItemsPos = [] self.targetText = self.parent.txtDocument.GetText() if self.mixed: return 1 RootArray = [self.root] Roots = [self.root] currentRoot = 0 Indents = [0] currentIndent = 0 #What is this document using? result = self.parent.txtDocument.CheckIndentation() wasnotmixed = 1 if result == 0: wasnotmixed = 0 if self.parent.prefs.docusetabs[self.parent.txtDocument.filetype]: result = 1 else: result = -1 if result == 1: compchar = '\t' dec = 1 else: compchar = ' ' dec = self.parent.prefs.doctabwidth[0] #Handle Triple Quoted Strings: self.targetText = self.RemoveTripleQuotedString(self.targetText) matcher = self.reinspect.finditer(self.targetText) #Get On With It! try: match = matcher.next() except: match = None while match is not None: matchedtext = match.group().strip() if matchedtext[0] == '#': nextmatch = self.renext.search(self.targetText[match.end():]) indent = 0 if nextmatch is not None: indent = GetCount(nextmatch.group(), compchar) cR = currentRoot cI = currentIndent while indent < Indents[cI]: cR = cR - 1 cI = cI - 1 i = matchedtext[4:].find('---') if i > -1: a = matchedtext[4:i+4] else: a = matchedtext[4:] m = match.group().find('#') currentitem = self.classtree.AppendItem(Roots[cI], a) #applied patch from bug report [ 1215144 ], 11.04.2007: Roots.append(currentitem) self.classtree.SetPyData(Roots[-1], None) currentRoot += 1 RootArray.append(Roots[currentRoot]) self.ItemsIndex.append(currentitem) self.ItemsPos.append(match.start() + m) colours = recolour.findall(matchedtext) if len(colours) > 1: try: self.classtree.SetItemTextColour(currentitem, convertColorPropertyToColorArray(colours[0])) self.classtree.SetItemBackgroundColour(currentitem, convertColorPropertyToColorArray(colours[1])) except Exception, e: print 'Error Setting Label Colour:', e self.classtree.SetItemImage(currentitem, 3, wx.TreeItemIcon_Normal) self.classtree.SetItemImage(currentitem, 3, wx.TreeItemIcon_Expanded) else: indent = GetCount(match.group(), compchar) while indent < Indents[currentIndent]: Roots.pop() currentRoot = currentRoot - 1 Indents.pop() currentIndent = currentIndent - 1 Indents.append(indent + dec) currentIndent = currentIndent + 1 currentitem = self.classtree.AppendItem(Roots[currentRoot], matchedtext) Roots.append(currentitem) #Submitted bugfix, Franz Steinhausler self.classtree.SetPyData(Roots[-1], None) currentRoot += 1 RootArray.append(Roots[currentRoot]) self.ItemsIndex.append(Roots[currentRoot]) self.ItemsPos.append(match.start()) if matchedtext[0] == 'c': try: fg, bg = convertStyleToColorArray(self.parent.prefs.PythonStyleDictionary[5]) self.classtree.SetItemTextColour(Roots[currentRoot], fg) self.classtree.SetItemBackgroundColour(Roots[currentRoot], bg) except Exception, e: print 'Error Setting Class Colour:', e self.classtree.SetItemImage(Roots[currentRoot], 0, wx.TreeItemIcon_Normal) self.classtree.SetItemImage(Roots[currentRoot], 0, wx.TreeItemIcon_Expanded) elif matchedtext[0] == 'd': try: fg, bg = convertStyleToColorArray(self.parent.prefs.PythonStyleDictionary[8]) self.classtree.SetItemTextColour(Roots[currentRoot], fg) self.classtree.SetItemBackgroundColour(Roots[currentRoot], bg) except Exception, e: print 'Error Setting Def Colour:', e self.classtree.SetItemImage(Roots[currentRoot], 1, wx.TreeItemIcon_Normal) self.classtree.SetItemImage(Roots[currentRoot], 1, wx.TreeItemIcon_Expanded) else: self.classtree.SetItemImage(Roots[currentRoot], 2, wx.TreeItemIcon_Normal) self.classtree.SetItemImage(Roots[currentRoot], 2, wx.TreeItemIcon_Expanded) try: match = matcher.next() except: match = None if self.parent.prefs.sourcebrowserissorted: self.classtree.SortChildren(self.root) x = 0 l = len(RootArray) while x < l: self.classtree.SortChildren(RootArray[x]) x = x + 1 #Submitted Patch: Christian Daven self.classtree.Thaw() #/Submitted Patch: Christian Daven return wasnotmixed def OnedSearch(self, event): #search on tree o=event.GetEventObject() s=o.GetValue().lower() if len(s)<2: return #s=self.classtree.GetItemText(self.classtree.GetSelection()) sel=self.classtree.GetSelection() found=False start=False #First try after selected item: for item in self.ItemsIndex: if start==True: z=self.classtree.GetItemText(item).lower() if z.find(s)>0: self.classtree.SelectItem(item,True) self.classtree.OnItemActivated(None) o.SetFocus() o.SetInsertionPointEnd() found=True break if item==sel: start=True #Second try from start if found==False: for item in self.ItemsIndex: z=self.classtree.GetItemText(item).lower() if z.find(s)>0: self.classtree.SelectItem(item,True) self.classtree.OnItemActivated(None) o.SetFocus() o.SetInsertionPointEnd() break event.Skip() def OnbtnClose(self, event): self.parent.PUnbind(self.parent.EVT_DRPY_DOCUMENT_CHANGED, self.OnbtnRefresh) self.parent.SourceBrowser = None self.panelparent.ClosePanel(self.position, self.Index) def OnbtnRefresh(self, event): self.mixed = 0 if not self.Browse(): self.mixed = 1 msg = 'This document is mixed. It uses tabs and spaces for indentation.\nDrPython may not be able to correctly display the class browser. Please use "Edit:Whitespace:Clean Up Indentation" to fix this.' drScrolledMessageDialog.ShowMessage(self, msg, "Check Indentation Results") if event is not None: event.Skip() def RemoveTripleQuotedString(self, text): text = self.removeStringTripleQuotedWith(text, "'''") text = self.removeStringTripleQuotedWith(text, '"""') return text def removeStringTripleQuotedWith(self, text, target): start = text.find(target) while start > -1: end = text[start+3:].find(target) if end == -1: text = text[:start] else: end = start + 3 + end text = text[:start] + "".zfill((end - start) + 3) + text[end+3:] start = text.find(target) return text drpython-3.11.1/drKeywords.py0000644000175000017500000002512611150445515016770 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public Lisense) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Keywords import keyword, string import wx.stc from drProperty import * def GetKeyWords(number): if number == 0: return string.join(keyword.kwlist) elif number == 1: return "".join(GetCPPKeywords()) elif number == 2: return "".join(GetHTMLKeyWords()) return "" def GetLexer(number): if number == 0: return wx.stc.STC_LEX_PYTHON elif number == 1: return wx.stc.STC_LEX_CPP elif number == 2: return wx.stc.STC_LEX_HTML return wx.stc.STC_LEX_NULL def GetCPPKeywords(): return ["asm ", "auto ", "bool ", "break ", "case ", "catch ", "char ", "class ", "const ", "const_cast ", "continue ", "default ", "delete ", "do ", "double ", "dynamic_cast ", "else ", "enum ", "explicit ", "export ", "extern ", "false ", "float ", "for ", "friend ", "goto ", "if ", "inline ", "int ", "long ", "mutable ", "namespace ", "new ", "operator ", "private ", "protected ", "public ", "register ", "reinterpret_cast ", "return ", "short ", "signed ", "sizeof ", "static ", "static_cast ", "struct ", "switch ", "template ", "this ", "throw ", "true ", "try ", "typedef ", "typeid ", "typename ", "union ", "unsigned ", "using ", "virtual ", "void ", "volatile ", "wchar_t ", "whileasm ", "auto ", "bool ", "break ", "case ", "catch ", "char ", "class ", "const ", "const_cast ", "continue ", "default ", "delete ", "do ", "double ", "dynamic_cast ", "else ", "enum ", "explicit ", "export ", "extern ", "false ", "float ", "for ", "friend ", "goto ", "if ", "inline ", "int ", "long ", "mutable ", "namespace ", "new ", "operator ", "private ", "protected ", "public ", "register ", "reinterpret_cast ", "return ", "short ", "signed ", "sizeof ", "static ", "static_cast ", "struct ", "switch ", "template ", "this ", "throw ", "true ", "try ", "typedef ", "typeid ", "typename ", "union ", "unsigned ", "using ", "virtual ", "void ", "volatile ", "wchar_t ", "while "] def GetHTMLKeyWords(): return ["a ", "abbr ", "acronym ", "address ", "applet ", "area ", "b ", "base ", "basefont ", "bdo ", "big ", "blockquote ", "body ", "br ", "button ", "caption ", "center ", "cite ", "code ", "col ", "colgroup ", "dd ", "del ", "dfn ", "dir ", "div ", "dl ", "dt ", "em ", "fieldset ", "font ", "form ", "frame ", "frameset ", "h1 ", "h2 ", "h3 ", "h4 ", "h5 ", "h6 ", "head ", "hr ", "html ", "i ", "iframe ", "img ", "input ", "ins ", "isindex ", "kbd ", "label ", "legend ", "li ", "link ", "map ", "menu ", "meta ", "noframes ", "noscript ", "object ", "ol ", "optgroup ", "option ", "p ", "param ", "pre ", "q ", "s ", "samp ", "script ", "select ", "small ", "span ", "strike ", "strong ", "style ", "sub ", "sup ", "table ", "tbody ", "td ", "textarea ", "tfoot ", "th ", "thead ", "title ", "tr ", "tt ", "u ", "ul ", "var ", "xml ", "xmlns ", "abbr ", "accept-charset ", "accept ", "accesskey ", "action ", "align ", "alink ", "alt ", "archive ", "axis ", "background ", "bgcolor ", "border ", "cellpadding ", "cellspacing ", "char ", "charoff ", "charset ", "checked ", "cite ", "class ", "classid ", "clear ", "codebase ", "codetype ", "color ", "cols ", "colspan ", "compact ", "content ", "coords ", "data ", "datafld ", "dataformatas ", "datapagesize ", "datasrc ", "datetime ", "declare ", "defer ", "dir ", "disabled ", "enctype ", "event ", "face ", "for ", "frame ", "frameborder ", "headers ", "height ", "href ", "hreflang ", "hspace ", "http-equiv ", "id ", "ismap ", "label ", "lang ", "language ", "leftmargin ", "link ", "longdesc ", "marginwidth ", "marginheight ", "maxlength ", "media ", "method ", "multiple ", "name ", "nohref ", "noresize ", "noshade ", "nowrap ", "object ", "onblur ", "onchange ", "onclick ", "ondblclick ", "onfocus ", "onkeydown ", "onkeypress ", "onkeyup ", "onload ", "onmousedown ", "onmousemove ", "onmouseover ", "onmouseout ", "onmouseup ", "onreset ", "onselect ", "onsubmit ", "onunload ", "profile ", "prompt ", "readonly ", "rel ", "rev ", "rows ", "rowspan ", "rules ", "scheme ", "scope ", "selected ", "shape ", "size ", "span ", "src ", "standby ", "start ", "style ", "summary ", "tabindex ", "target ", "text ", "title ", "topmargin ", "type ", "usemap ", "valign ", "value ", "valuetype ", "version ", "vlink ", "vspace ", "width ", "text ", "password ", "checkbox ", "radio ", "submit ", "reset ", "file ", "hidden ", "image ", "public ", "!doctype ", "dtml-var ", "dtml-if ", "dtml-unless ", "dtml-in ", "dtml-with ", "dtml-let ", "dtml-call ", "dtml-raise ", "dtml-try ", "dtml-comment ", "dtml-tree "] def SetSTCStyles(frame, stc, number): if number == 0: stc.StyleSetSpec(wx.stc.STC_P_CHARACTER, frame.prefs.txtDocumentStyleDictionary[4]) stc.StyleSetSpec(wx.stc.STC_P_CLASSNAME, frame.prefs.txtDocumentStyleDictionary[5]) stc.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, frame.prefs.txtDocumentStyleDictionary[6]) stc.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, frame.prefs.txtDocumentStyleDictionary[7]) stc.StyleSetSpec(wx.stc.STC_P_DEFNAME, frame.prefs.txtDocumentStyleDictionary[8]) stc.StyleSetSpec(wx.stc.STC_P_WORD, frame.prefs.txtDocumentStyleDictionary[9]) stc.StyleSetSpec(wx.stc.STC_P_NUMBER, frame.prefs.txtDocumentStyleDictionary[10]) stc.StyleSetSpec(wx.stc.STC_P_OPERATOR, frame.prefs.txtDocumentStyleDictionary[11]) stc.StyleSetSpec(wx.stc.STC_P_STRING, frame.prefs.txtDocumentStyleDictionary[12]) stc.StyleSetSpec(wx.stc.STC_P_STRINGEOL, frame.prefs.txtDocumentStyleDictionary[13]) stc.StyleSetSpec(wx.stc.STC_P_TRIPLE, frame.prefs.txtDocumentStyleDictionary[14]) stc.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, frame.prefs.txtDocumentStyleDictionary[14]) stc.SetSelForeground(1, getStyleProperty("fore", frame.prefs.txtDocumentStyleDictionary[16])) stc.SetSelBackground(1, getStyleProperty("back", frame.prefs.txtDocumentStyleDictionary[16])) elif number == 1: stc.StyleSetSpec(wx.stc.STC_C_CHARACTER, frame.prefs.txtDocumentStyleDictionary[4]) stc.StyleSetSpec(wx.stc.STC_C_PREPROCESSOR, frame.prefs.txtDocumentStyleDictionary[5]) stc.StyleSetSpec(wx.stc.STC_C_COMMENT, frame.prefs.txtDocumentStyleDictionary[6]) stc.StyleSetSpec(wx.stc.STC_C_COMMENTLINE, frame.prefs.txtDocumentStyleDictionary[6]) stc.StyleSetSpec(wx.stc.STC_C_COMMENTLINEDOC, frame.prefs.txtDocumentStyleDictionary[6]) stc.StyleSetSpec(wx.stc.STC_C_COMMENTDOCKEYWORD, frame.prefs.txtDocumentStyleDictionary[6]) stc.StyleSetSpec(wx.stc.STC_C_COMMENTDOCKEYWORDERROR, frame.prefs.txtDocumentStyleDictionary[6]) stc.StyleSetSpec(wx.stc.STC_C_COMMENTDOC, frame.prefs.txtDocumentStyleDictionary[6]) stc.StyleSetSpec(wx.stc.STC_C_VERBATIM, frame.prefs.txtDocumentStyleDictionary[7]) stc.StyleSetSpec(wx.stc.STC_C_WORD, frame.prefs.txtDocumentStyleDictionary[8]) stc.StyleSetSpec(wx.stc.STC_C_WORD2, frame.prefs.txtDocumentStyleDictionary[8]) stc.StyleSetSpec(wx.stc.STC_C_IDENTIFIER, frame.prefs.txtDocumentStyleDictionary[9]) stc.StyleSetSpec(wx.stc.STC_C_NUMBER, frame.prefs.txtDocumentStyleDictionary[10]) stc.StyleSetSpec(wx.stc.STC_C_OPERATOR, frame.prefs.txtDocumentStyleDictionary[11]) stc.StyleSetSpec(wx.stc.STC_C_STRING, frame.prefs.txtDocumentStyleDictionary[12]) stc.StyleSetSpec(wx.stc.STC_C_STRINGEOL, frame.prefs.txtDocumentStyleDictionary[13]) stc.StyleSetSpec(wx.stc.STC_C_GLOBALCLASS, frame.prefs.txtDocumentStyleDictionary[14]) stc.StyleSetSpec(wx.stc.STC_C_REGEX, frame.prefs.txtDocumentStyleDictionary[15]) stc.StyleSetSpec(wx.stc.STC_C_UUID, frame.prefs.txtDocumentStyleDictionary[16]) stc.SetSelForeground(1, getStyleProperty("fore", frame.prefs.txtDocumentStyleDictionary[18])) stc.SetSelBackground(1, getStyleProperty("back", frame.prefs.txtDocumentStyleDictionary[18])) elif number == 2: stc.StyleSetSpec(wx.stc.STC_H_TAG, frame.prefs.txtDocumentStyleDictionary[4]) stc.StyleSetSpec(wx.stc.STC_H_TAGUNKNOWN, frame.prefs.txtDocumentStyleDictionary[5]) stc.StyleSetSpec(wx.stc.STC_H_ATTRIBUTE, frame.prefs.txtDocumentStyleDictionary[6]) stc.StyleSetSpec(wx.stc.STC_H_ATTRIBUTEUNKNOWN, frame.prefs.txtDocumentStyleDictionary[7]) stc.StyleSetSpec(wx.stc.STC_H_NUMBER, frame.prefs.txtDocumentStyleDictionary[8]) stc.StyleSetSpec(wx.stc.STC_H_DOUBLESTRING, frame.prefs.txtDocumentStyleDictionary[9]) stc.StyleSetSpec(wx.stc.STC_H_SINGLESTRING, frame.prefs.txtDocumentStyleDictionary[10]) stc.StyleSetSpec(wx.stc.STC_H_OTHER, frame.prefs.txtDocumentStyleDictionary[10]) stc.StyleSetSpec(wx.stc.STC_H_COMMENT, frame.prefs.txtDocumentStyleDictionary[11]) stc.StyleSetSpec(wx.stc.STC_H_XCCOMMENT, frame.prefs.txtDocumentStyleDictionary[11]) stc.StyleSetSpec(wx.stc.STC_H_ENTITY, frame.prefs.txtDocumentStyleDictionary[12]) stc.StyleSetSpec(wx.stc.STC_H_TAGEND, frame.prefs.txtDocumentStyleDictionary[13]) stc.StyleSetSpec(wx.stc.STC_H_XMLSTART, frame.prefs.txtDocumentStyleDictionary[14]) stc.StyleSetSpec(wx.stc.STC_H_XMLEND, frame.prefs.txtDocumentStyleDictionary[15]) stc.StyleSetSpec(wx.stc.STC_H_SCRIPT, frame.prefs.txtDocumentStyleDictionary[16]) stc.StyleSetSpec(wx.stc.STC_H_ASP, frame.prefs.txtDocumentStyleDictionary[16]) stc.StyleSetSpec(wx.stc.STC_H_ASPAT, frame.prefs.txtDocumentStyleDictionary[16]) stc.StyleSetSpec(wx.stc.STC_H_VALUE, frame.prefs.txtDocumentStyleDictionary[17]) stc.StyleSetSpec(wx.stc.STC_H_QUESTION, frame.prefs.txtDocumentStyleDictionary[17]) stc.SetSelForeground(1, getStyleProperty("fore", frame.prefs.txtDocumentStyleDictionary[19])) stc.SetSelBackground(1, getStyleProperty("back", frame.prefs.txtDocumentStyleDictionary[19]))drpython-3.11.1/drShortcuts.py0000644000175000017500000007511011150445514017154 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Shortcuts import re import wx.stc import wx wxKeyDictionary = {wx.WXK_F1:'F1', wx.WXK_F2:'F2', wx.WXK_F3:'F3', wx.WXK_F4:'F4', wx.WXK_F5:'F5', wx.WXK_F6:'F6', wx.WXK_F7:'F7', wx.WXK_F8:'F8', wx.WXK_F9:'F9', wx.WXK_F10:'F10', wx.WXK_F11:'F11', wx.WXK_F12:'F12', wx.WXK_MENU:'Menu', wx.WXK_PAUSE:'Pause', wx.WXK_CAPITAL:'CAPS', wx.WXK_PRIOR:'Page Up', wx.WXK_NEXT:'Page Down', wx.WXK_END:'End', wx.WXK_HOME:'Home', wx.WXK_LEFT:'Left', wx.WXK_UP:'Up', wx.WXK_RIGHT:'Right', wx.WXK_DOWN:'Down', wx.WXK_INSERT:'Insert', wx.WXK_PRINT:'Print', wx.WXK_BACK:'Backspace', wx.WXK_TAB:'Tab', wx.WXK_RETURN:'Enter', wx.WXK_ESCAPE:'Esc', wx.WXK_SPACE:'Space', wx.WXK_DELETE:'Delete', wx.WXK_ADD:'+', wx.WXK_SUBTRACT:'-', wx.WXK_SEPARATOR:'_', wx.WXK_MULTIPLY:'*', wx.WXK_DIVIDE:'/', wx.WXK_ADD:'+', wx.WXK_NUMPAD_SPACE:'Space', wx.WXK_NUMPAD_TAB:'Tab', wx.WXK_NUMPAD_ENTER:'Enter', wx.WXK_NUMPAD_F1:'F1', wx.WXK_NUMPAD_F2:'F2', wx.WXK_NUMPAD_F3:'F3', wx.WXK_NUMPAD_F4:'F4', wx.WXK_NUMPAD_HOME:'Home', wx.WXK_NUMPAD_LEFT:'Left', wx.WXK_NUMPAD_UP:'Up', wx.WXK_NUMPAD_RIGHT:'Right', wx.WXK_NUMPAD_DOWN:'Down', wx.WXK_NUMPAD_PRIOR:'Page Up', wx.WXK_NUMPAD_PAGEUP:'Page Up', wx.WXK_NUMPAD_NEXT:'Page Down', wx.WXK_NUMPAD_PAGEDOWN:'Page Down', wx.WXK_NUMPAD_END:'End', wx.WXK_NUMPAD_BEGIN:'Begin', wx.WXK_NUMPAD_INSERT:'Insert', wx.WXK_NUMPAD_DELETE:'Delete', wx.WXK_NUMPAD_EQUAL:'=', wx.WXK_NUMPAD_MULTIPLY:'*', wx.WXK_NUMPAD_ADD:'+', wx.WXK_NUMPAD_SEPARATOR:'_', wx.WXK_NUMPAD_SUBTRACT:'-', wx.WXK_NUMPAD_DECIMAL:'.', wx.WXK_NUMPAD_DIVIDE:'/'} recontrol = re.compile('Control') reshift = re.compile('Shift') realt = re.compile('Alt') remeta = re.compile('Meta') rekeycode = re.compile('\d+') def MatchControl(shortcut): return recontrol.search(shortcut) is not None def MatchShift(shortcut): return reshift.search(shortcut) is not None def MatchAlt(shortcut): return realt.search(shortcut) is not None def MatchMeta(shortcut): return remeta.search(shortcut) is not None def BuildShortcutString(keycode, control, shift, alt, meta): keystr = "" if control: keystr = "Control" if shift: keystr = keystr + "Shift" if alt: keystr = keystr + "Alt" if meta: keystr = keystr + "Meta" keystr = keystr + str(keycode) return keystr def GetKeycodeStringFromShortcut(shortcut): kstr = rekeycode.search(shortcut) if kstr is not None: return kstr.group() return '' def GetKeycodeFromShortcut(shortcut): kstr = rekeycode.search(shortcut) if kstr is not None: try: k = int(kstr.group()) except: return 0 return k return 0 def GetShortcutLabel(shortcut): label = '' if MatchControl(shortcut): label += 'Ctrl+' if MatchShift(shortcut): label += 'Shift+' if MatchAlt(shortcut): label += 'Alt+' if MatchMeta(shortcut): label += 'Meta+' try: kc = GetKeycodeFromShortcut(shortcut) except: return '' if wxKeyDictionary.has_key(kc): label += wxKeyDictionary[kc] return label if kc < 128: label += chr(kc) return label return '' def GetDefaultSTCShortcut(stcindex): shortcut = [ ["Back Tab", wx.WXK_TAB, "Shift"], ["Cancel", wx.WXK_ESCAPE, ""], ["Char Left", wx.WXK_LEFT, ""], ["Char Left Extend", wx.WXK_LEFT, "Shift"], ["Char Left Rect Extend", wx.WXK_LEFT, "Shift, Alt"], ["Char Right", wx.WXK_RIGHT, ""], ["Char Right Extend", wx.WXK_RIGHT, "Shift"], ["Char Right Rect Extend", wx.WXK_RIGHT, "Shift, Alt"], ["Copy", ord('C'), "Control"], ["Cut", ord('X'), "Control"], ["Delete", wx.WXK_DELETE, ""], ["Delete Back", wx.WXK_BACK, ""], ["Delete Back Not Line", wx.WXK_BACK, "Shift"], ["Delete Line Left", -1, ""], ["Delete Line Right", wx.WXK_DELETE, "Control, Shift"], ["Delete Word Left", -1, ""], ["Delete Word Right", wx.WXK_DELETE, "Control"], ["Document End", wx.WXK_END, "Control"], ["Document End Extend", wx.WXK_END, "Control, Shift"], ["Document Start", wx.WXK_HOME, "Control"], ["Document Start Extend", wx.WXK_HOME, "Control, Shift"], ["Form Feed", -1, ""], ["Home",-1, ""], # See Visible Character Home ["Home Display", wx.WXK_HOME, "Alt"], ["Home Display Extend", -1, ""], ["Home Extend", wx.WXK_HOME, "Shift"], ["Home Rect Extend", wx.WXK_HOME, "Shift, Alt"], ["Line Cut", ord('Y'), "Control"], ["Line Delete", -1, ""], ["Line Down", wx.WXK_DOWN, ""], ["Line Down Extend", wx.WXK_DOWN, "Shift"], ["Line Down Rect Extend", wx.WXK_DOWN, "Shift, Alt"], ["Line Duplicate", ord('D'), "Control"], ["Line End", wx.WXK_END, ""], ["Line End Display", wx.WXK_END, "Alt"], ["Line End Display Extend", -1, ""], ["Line End Extend", wx.WXK_END, "Shift"], ["Line End Rect Extend", wx.WXK_END, "Shift, Alt"], ["Line Scroll Down", wx.WXK_DOWN, "Control"], ["Line Scroll Up", wx.WXK_UP, "Control"], ["Line Transpose", ord('X'), "Alt"], ["Line Up", wx.WXK_UP, ""], ["Line Up Extend", wx.WXK_UP, "Shift"], ["Line Up Rect Extend", wx.WXK_UP, "Shift, Alt"], ["Lowercase", ord('U'), "Control"], ["New Line", wx.WXK_RETURN, ""], ["Page Down", wx.WXK_NEXT, ""], ["Page Down Extend", wx.WXK_NEXT, "Shift"], ["Page Down Rect Extend", wx.WXK_NEXT, "Shift, Alt"], ["Page Up", wx.WXK_PRIOR, ""], ["Page Up Extend", wx.WXK_PRIOR, "Shift"], ["Page Up Rect Extend", wx.WXK_PRIOR, "Shift, Alt"], ["Paste", ord('V'), "Control"], ["Redo", ord('Z'), "Control, Shift"], ["Select All", ord('A'), "Control"], ["Tab", wx.WXK_TAB, ""], ["Toggle Overtype", wx.WXK_INSERT, ""], ["Undo", ord('Z'), "Control"], ["Uppercase", ord('U'), "Control, Shift"], ["Visible Character Home", wx.WXK_HOME, ""], #Begin of Line ["Visible Character Home Extend", -1, ""], ["World Left", wx.WXK_LEFT, "Control"], ["Word Left Extend", wx.WXK_LEFT, "Control, Shift"], ["Word Part Left", wx.WXK_LEFT, "Alt"], ["Word Part Left Extend", -1, ""], ["Word Part Right", wx.WXK_RIGHT, "Alt"], ["Word Part Right Extend", -1, ""], ["Word Right", wx.WXK_RIGHT, "Control"], ["Word Right Extend", wx.WXK_RIGHT, "Control, Shift"], ["Zoom In", ord('+'), "Control"], ["Zoom Out", ord('-'), "Control"] ][stcindex] return (shortcut[2] + str(shortcut[1])) def GetKeycodeText(keycode): wxkeycodes = [wx.WXK_BACK, wx.WXK_TAB, wx.WXK_RETURN, wx.WXK_ESCAPE, wx.WXK_SPACE, wx.WXK_DELETE, wx.WXK_START, wx.WXK_LBUTTON, wx.WXK_RBUTTON, wx.WXK_CANCEL, wx.WXK_MBUTTON, wx.WXK_CLEAR, wx.WXK_SHIFT, wx.WXK_CONTROL, wx.WXK_MENU, wx.WXK_PAUSE, wx.WXK_CAPITAL, wx.WXK_PRIOR, wx.WXK_NEXT, wx.WXK_END, wx.WXK_HOME, wx.WXK_LEFT, wx.WXK_UP, wx.WXK_RIGHT, wx.WXK_DOWN, wx.WXK_SELECT, wx.WXK_PRINT, wx.WXK_EXECUTE, wx.WXK_SNAPSHOT, wx.WXK_INSERT, wx.WXK_HELP, wx.WXK_NUMPAD0, wx.WXK_NUMPAD1, wx.WXK_NUMPAD2, wx.WXK_NUMPAD3, wx.WXK_NUMPAD4, wx.WXK_NUMPAD5, wx.WXK_NUMPAD6, wx.WXK_NUMPAD7, wx.WXK_NUMPAD8, wx.WXK_NUMPAD9, wx.WXK_MULTIPLY, wx.WXK_ADD, wx.WXK_SEPARATOR, wx.WXK_SUBTRACT, wx.WXK_DECIMAL, wx.WXK_DIVIDE, wx.WXK_F1, wx.WXK_F2, wx.WXK_F3, wx.WXK_F4, wx.WXK_F5, wx.WXK_F6, wx.WXK_F7, wx.WXK_F8, wx.WXK_F9, wx.WXK_F10, wx.WXK_F11, wx.WXK_F12, wx.WXK_F13, wx.WXK_F14, wx.WXK_F15, wx.WXK_F16, wx.WXK_F17, wx.WXK_F18, wx.WXK_F19, wx.WXK_F20, wx.WXK_F21, wx.WXK_F22, wx.WXK_F23, wx.WXK_F24, wx.WXK_NUMLOCK, wx.WXK_SCROLL] wxkeynames = ["BACK", "TAB", "RETURN", "ESCAPE", "SPACE", "DELETE", "START", "LBUTTON", "RBUTTON", "CANCEL", "MBUTTON", "CLEAR", "SHIFT", "CONTROL", "MENU", "PAUSE", "CAPITAL", "PRIOR", "NEXT", "END", "HOME", "LEFT", "UP", "RIGHT", "DOWN", "SELECT", "PRINT", "EXECUTE", "SNAPSHOT", "INSERT", "HELP", "NUMPAD0", "NUMPAD1", "NUMPAD2", "NUMPAD3", "NUMPAD4", "NUMPAD5", "NUMPAD6", "NUMPAD7", "NUMPAD8", "NUMPAD9", "MULTIPLY", "ADD", "SEPARATOR", "SUBTRACT", "DECIMAL", "DIVIDE", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24", "NUMLOCK", "SCROLL"] try: i = wxkeycodes.index(keycode) return True, wxkeynames[i] except: pass return False, "" def GetSTCCommandList(): return [wx.stc.STC_CMD_BACKTAB, wx.stc.STC_CMD_CANCEL, wx.stc.STC_CMD_CHARLEFT, wx.stc.STC_CMD_CHARLEFTEXTEND, wx.stc.STC_CMD_CHARLEFTRECTEXTEND, wx.stc.STC_CMD_CHARRIGHT, wx.stc.STC_CMD_CHARRIGHTEXTEND, wx.stc.STC_CMD_CHARRIGHTRECTEXTEND, wx.stc.STC_CMD_COPY, wx.stc.STC_CMD_CUT, wx.stc.STC_CMD_CLEAR, wx.stc.STC_CMD_DELETEBACK, wx.stc.STC_CMD_DELETEBACKNOTLINE, wx.stc.STC_CMD_DELLINELEFT, wx.stc.STC_CMD_DELLINERIGHT, wx.stc.STC_CMD_DELWORDLEFT, wx.stc.STC_CMD_DELWORDRIGHT, wx.stc.STC_CMD_DOCUMENTEND, wx.stc.STC_CMD_DOCUMENTENDEXTEND, wx.stc.STC_CMD_DOCUMENTSTART, wx.stc.STC_CMD_DOCUMENTSTARTEXTEND, wx.stc.STC_CMD_FORMFEED, wx.stc.STC_CMD_HOME, wx.stc.STC_CMD_HOMEDISPLAY, wx.stc.STC_CMD_HOMEDISPLAYEXTEND, wx.stc.STC_CMD_HOMEEXTEND, wx.stc.STC_CMD_VCHOMERECTEXTEND, wx.stc.STC_CMD_LINECUT, wx.stc.STC_CMD_LINEDELETE, wx.stc.STC_CMD_LINEDOWN, wx.stc.STC_CMD_LINEDOWNEXTEND, wx.stc.STC_CMD_LINEDOWNRECTEXTEND, wx.stc.STC_CMD_LINEDUPLICATE, wx.stc.STC_CMD_LINEEND, wx.stc.STC_CMD_LINEENDDISPLAY, wx.stc.STC_CMD_LINEENDDISPLAYEXTEND, wx.stc.STC_CMD_LINEENDEXTEND, wx.stc.STC_CMD_LINEENDRECTEXTEND, wx.stc.STC_CMD_LINESCROLLDOWN, wx.stc.STC_CMD_LINESCROLLUP, wx.stc.STC_CMD_LINETRANSPOSE, wx.stc.STC_CMD_LINEUP, wx.stc.STC_CMD_LINEUPEXTEND, wx.stc.STC_CMD_LINEUPRECTEXTEND, wx.stc.STC_CMD_LOWERCASE, wx.stc.STC_CMD_NEWLINE, wx.stc.STC_CMD_PAGEDOWN, wx.stc.STC_CMD_PAGEDOWNEXTEND, wx.stc.STC_CMD_PAGEDOWNRECTEXTEND, wx.stc.STC_CMD_PAGEUP, wx.stc.STC_CMD_PAGEUPEXTEND, wx.stc.STC_CMD_PAGEUPRECTEXTEND, wx.stc.STC_CMD_PASTE, wx.stc.STC_CMD_REDO, wx.stc.STC_CMD_SELECTALL, wx.stc.STC_CMD_TAB, wx.stc.STC_CMD_EDITTOGGLEOVERTYPE, wx.stc.STC_CMD_UNDO, wx.stc.STC_CMD_UPPERCASE, wx.stc.STC_CMD_VCHOME, wx.stc.STC_CMD_VCHOMEEXTEND, wx.stc.STC_CMD_WORDLEFT, wx.stc.STC_CMD_WORDLEFTEXTEND, wx.stc.STC_CMD_WORDPARTLEFT, wx.stc.STC_CMD_WORDPARTLEFTEXTEND, wx.stc.STC_CMD_WORDPARTRIGHT, wx.stc.STC_CMD_WORDPARTRIGHTEXTEND, wx.stc.STC_CMD_WORDRIGHT, wx.stc.STC_CMD_WORDRIGHTEXTEND, wx.stc.STC_CMD_ZOOMIN, wx.stc.STC_CMD_ZOOMOUT] def SetSTCShortcuts(stc, Shortcuts, useDefault = 0): #KeycodeArray = [] wxDefArray = [wx.WXK_DOWN, wx.WXK_UP, wx.WXK_LEFT, wx.WXK_RIGHT, wx.WXK_HOME, wx.WXK_END, wx.WXK_PRIOR, wx.WXK_NEXT, wx.WXK_DELETE, wx.WXK_INSERT, wx.WXK_ESCAPE, wx.WXK_BACK, wx.WXK_TAB, wx.WXK_RETURN, wx.WXK_ADD, wx.WXK_SUBTRACT, wx.WXK_DIVIDE] PreDefArray = [wx.stc.STC_KEY_DOWN, wx.stc.STC_KEY_UP, wx.stc.STC_KEY_LEFT, wx.stc.STC_KEY_RIGHT, wx.stc.STC_KEY_HOME, wx.stc.STC_KEY_END, wx.stc.STC_KEY_PRIOR, wx.stc.STC_KEY_NEXT, wx.stc.STC_KEY_DELETE, wx.stc.STC_KEY_INSERT, wx.stc.STC_KEY_ESCAPE, wx.stc.STC_KEY_BACK, wx.stc.STC_KEY_TAB, wx.stc.STC_KEY_RETURN, wx.stc.STC_KEY_ADD, wx.stc.STC_KEY_SUBTRACT, wx.stc.STC_KEY_DIVIDE] #Note: If stc.CmdKeyAssign is used, then DrPython will never process # that combindation in the keybinding code. cmdlist = GetSTCCommandList() stc.CmdKeyClearAll() x = 0 l = len(Shortcuts) while x < l: modifiers = 0 if useDefault: Shortcuts[x] = GetDefaultSTCShortcut(x) ikeycode = GetKeycodeFromShortcut(Shortcuts[x]) if MatchControl(Shortcuts[x]): modifiers = modifiers | wx.stc.STC_SCMOD_CTRL if MatchShift(Shortcuts[x]): modifiers = modifiers | wx.stc.STC_SCMOD_SHIFT if MatchAlt(Shortcuts[x]): modifiers = modifiers | wx.stc.STC_SCMOD_ALT if (ikeycode >= ord('A')) and (ikeycode <= ord('Z')): stc.CmdKeyAssign(ikeycode, modifiers, cmdlist[x]) elif ikeycode in wxDefArray: i = wxDefArray.index(ikeycode) stc.CmdKeyAssign(PreDefArray[i], modifiers, cmdlist[x]) x = x + 1 return Shortcuts def SetShortcuts(frame, Shortcuts, ShortcutNames, useDefault=0): shortcutsActionArray = [] shortcutsArgumentsArray = [] l = len(Shortcuts) x = 0 while x < l: #File if(ShortcutNames[x] == "New"): if useDefault: Shortcuts[x] = 'Control' + str(ord('N')) shortcutsActionArray.append(frame.OnNew) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Open"): if useDefault: Shortcuts[x] = 'Control' + str(ord('O')) shortcutsActionArray.append(frame.OnOpen) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Open Imported Module"): if useDefault: Shortcuts[x] = 'Control' + str(ord('M')) shortcutsActionArray.append(frame.OnOpenImportedModule) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Save"): if useDefault: Shortcuts[x] = 'Control' + str(ord('S')) shortcutsActionArray.append(frame.OnSave) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Save As"): shortcutsActionArray.append(frame.OnSaveAs) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Save All Documents"): shortcutsActionArray.append(frame.OnSaveAll) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Save Prompt Output To File"): shortcutsActionArray.append(frame.OnSavePrompt) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Reload File"): shortcutsActionArray.append(frame.OnReload) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Restore From Backup"): shortcutsActionArray.append(frame.OnRestoreFromBackup) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Close"): if useDefault: Shortcuts[x] = 'Control' + str(ord('W')) shortcutsActionArray.append(frame.OnClose) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Close All Documents"): shortcutsActionArray.append(frame.OnCloseAllDocuments) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Close All Other Documents"): shortcutsActionArray.append(frame.OnCloseAllOtherDocuments) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Print Setup"): shortcutsActionArray.append(frame.OnPrintSetup) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Print File"): if useDefault: Shortcuts[x] = 'Control' + str(ord('P')) shortcutsActionArray.append(frame.OnPrint) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Print Prompt"): if useDefault: Shortcuts[x] = 'ControlShift' + str(ord('P')) shortcutsActionArray.append(frame.OnPrintPrompt) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Exit"): #applied patch from Cedric Delfosse (cdelfosse) of bug tracker : [ 1214909 ], on 11.04.2007: #ctrl_q_to_exit_as_default_shortcut.patch if useDefault: Shortcuts[x] = 'Control' + str(ord('Q')) shortcutsActionArray.append(frame.OnExit) shortcutsArgumentsArray.append("frame, event") #Tabs elif(ShortcutNames[x] == "Next Document"): if useDefault: Shortcuts[x] = str(wx.WXK_F10) shortcutsActionArray.append(frame.OnSelectDocumentNext) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Previous Document"): if useDefault: Shortcuts[x] = str(wx.WXK_F9) shortcutsActionArray.append(frame.OnSelectDocumentPrevious) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "First Document"): shortcutsActionArray.append(frame.OnSelectDocumentFirst) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Last Document"): shortcutsActionArray.append(frame.OnSelectDocumentLast) shortcutsArgumentsArray.append("frame, event") #Edit elif(ShortcutNames[x] == "Find"): if useDefault: Shortcuts[x] = 'Control' + str(ord('F')) shortcutsActionArray.append(frame.OnMenuFind) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Find Next"): if useDefault: Shortcuts[x] = str(wx.WXK_F3) shortcutsActionArray.append(frame.OnMenuFindNext) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Find Previous"): if useDefault: Shortcuts[x] = 'Control' + str(wx.WXK_F3) shortcutsActionArray.append(frame.OnMenuFindPrevious) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Replace"): if useDefault: Shortcuts[x] = 'Control' + str(ord('R')) shortcutsActionArray.append(frame.OnMenuReplace) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Find In Files"): shortcutsActionArray.append(frame.OnMenuFindInFiles) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Replace In Files"): shortcutsActionArray.append(frame.OnMenuReplaceInFiles) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Insert Regular Expression"): shortcutsActionArray.append(frame.OnInsertRegEx) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Insert Separator"): shortcutsActionArray.append(frame.OnInsertSeparator) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Comment"): if useDefault: Shortcuts[x] = 'Control' + str(ord('[')) shortcutsActionArray.append(frame.OnCommentRegion) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "UnComment"): if useDefault: Shortcuts[x] = 'Control' + str(ord(']')) shortcutsActionArray.append(frame.OnUnCommentRegion) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Indent"): if useDefault: Shortcuts[x] = 'Control' + str(ord('I')) shortcutsActionArray.append(frame.OnIndentRegion) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Dedent"): if useDefault: Shortcuts[x] = 'ControlShift' + str(ord('I')) shortcutsActionArray.append(frame.OnDedentRegion) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Find And Complete"): if useDefault: Shortcuts[x] = 'Control' + str(wx.WXK_RETURN) shortcutsActionArray.append(frame.OnFindAndComplete) shortcutsArgumentsArray.append("frame, event") #View elif(ShortcutNames[x] == "Go To"): if useDefault: Shortcuts[x] = 'Control' + str(ord('G')) shortcutsActionArray.append(frame.OnGoTo) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Go To Block Start"): if useDefault: Shortcuts[x] = 'Control' + str(ord('B')) shortcutsActionArray.append(frame.OnGoToBlockStart) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Go To Block End"): if useDefault: Shortcuts[x] = 'ControlShift' + str(ord('B')) shortcutsActionArray.append(frame.OnGoToBlockEnd) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Go To Class Start"): shortcutsActionArray.append(frame.OnGoToClassStart) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Go To Class End"): shortcutsActionArray.append(frame.OnGoToClassEnd) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Go To Def Start"): shortcutsActionArray.append(frame.OnGoToDefStart) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Go To Def End"): shortcutsActionArray.append(frame.OnGoToDefEnd) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Toggle Fold"): shortcutsActionArray.append(frame.OnToggleFold) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Fold All"): shortcutsActionArray.append(frame.OnFoldAll) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Expand All"): shortcutsActionArray.append(frame.OnExpandAll) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Source Browser Go To"): if useDefault: Shortcuts[x] = 'Control' + str(wx.WXK_F8) shortcutsActionArray.append(frame.OnSourceBrowserGoTo) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Toggle Source Browser"): if useDefault: Shortcuts[x] = str(wx.WXK_F8) shortcutsActionArray.append(frame.OnToggleSourceBrowser) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Toggle View Whitespace"): if useDefault: Shortcuts[x] = 'ControlShift' + str(ord('W')) shortcutsActionArray.append(frame.OnToggleViewWhiteSpace) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Toggle Prompt"): if useDefault: Shortcuts[x] = str(wx.WXK_F6) shortcutsActionArray.append(frame.OnTogglePrompt) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "View In Left Panel"): shortcutsActionArray.append(frame.OnViewInLeftPanel) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "View In Right Panel"): shortcutsActionArray.append(frame.OnViewInRightPanel) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "View In Top Panel"): shortcutsActionArray.append(frame.OnViewInTopPanel) shortcutsArgumentsArray.append("frame, event") #Program elif(ShortcutNames[x] == "Check Syntax"): shortcutsActionArray.append(frame.OnCheckSyntax) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Run"): if useDefault: Shortcuts[x] = 'Control' + str(ord('E')) shortcutsActionArray.append(frame.OnRun) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Set Arguments"): shortcutsActionArray.append(frame.OnSetArgs) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Python"): if useDefault: Shortcuts[x] = str(wx.WXK_F7) shortcutsActionArray.append(frame.OnPython) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "End"): if useDefault: Shortcuts[x] = 'ControlShift' + str(ord('E')) shortcutsActionArray.append(frame.OnEnd) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Close Prompt"): shortcutsActionArray.append(frame.OnClosePrompt) shortcutsArgumentsArray.append("frame, event") #DrScript elif(ShortcutNames[x] == "Dynamic DrScript"): shortcutsActionArray.append(frame.dynamicdrscript) shortcutsArgumentsArray.append("frame, event") #Prefs elif(ShortcutNames[x] == "Preferences"): shortcutsActionArray.append(frame.OnPrefs) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Customize Shortcuts"): shortcutsActionArray.append(frame.OnCustomizeShortcuts) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Customize Pop Up Menu"): shortcutsActionArray.append(frame.OnCustomizePopUpMenu) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "Customize ToolBar"): shortcutsActionArray.append(frame.OnCustomizeToolBar) shortcutsArgumentsArray.append("frame, event") #Docs elif(ShortcutNames[x] == "Help"): shortcutsActionArray.append(frame.OnViewHelp) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "View Python Docs"): shortcutsActionArray.append(frame.OnViewPythonDocs) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "View WxWidgets Docs"): shortcutsActionArray.append(frame.OnViewWxWidgetsDocs) shortcutsArgumentsArray.append("frame, event") elif(ShortcutNames[x] == "View Regular Expression Howto"): shortcutsActionArray.append(frame.OnViewREHowtoDocs) shortcutsArgumentsArray.append("frame, event") #General elif(ShortcutNames[x] == "Toggle Maximize"): if useDefault: Shortcuts[x] = 'Control' + str(wx.WXK_F5) shortcutsActionArray.append(frame.Maximize) shortcutsArgumentsArray.append("maximize") elif(ShortcutNames[x] == "Inspect Tool"): if useDefault: Shortcuts[x] = 'Alt' + str(ord('T')) shortcutsActionArray.append(frame.OnOpenWidgetInspector) shortcutsArgumentsArray.append("frame, event") x = x + 1 return Shortcuts, shortcutsActionArray, shortcutsArgumentsArray def RunShortcuts(frame, event, stc, SplitView): keycode = event.GetKeyCode() #Treat Numpad Enter as Enter. if keycode == wx.WXK_NUMPAD_ENTER: keycode = wx.WXK_RETURN allowControl = not (frame.ShortcutsIgnoreString.find("Control") > -1) allowShift = not (frame.ShortcutsIgnoreString.find("Shift") > -1) allowAlt = not (frame.ShortcutsIgnoreString.find("Alt") > -1) allowMeta = not (frame.ShortcutsIgnoreString.find("Meta") > -1) control = (event.ControlDown() and allowControl) shift = (event.ShiftDown() and allowShift) alt = (event.AltDown() and allowAlt) meta = (event.MetaDown() and allowMeta) strkeycode = BuildShortcutString(keycode, control, shift, alt, meta) #Get the active stc: if stc is None: if frame.txtPrompt.GetSTCFocus(): stc = frame.txtPrompt else: stc = frame.txtDocument allowControl = not (frame.ShortcutsIgnoreString.find("Control") > -1) allowShift = not (frame.ShortcutsIgnoreString.find("Shift") > -1) allowMeta = not (frame.ShortcutsIgnoreString.find("Meta") > -1) allowAlt = not (frame.ShortcutsIgnoreString.find("Alt") > -1) drstc = -1 drpy = -1 drscript = -1 plugin = -1 if strkeycode in frame.PluginShortcuts: plugin = frame.PluginShortcuts.index(strkeycode) if strkeycode in frame.STCShortcuts: drstc = frame.STCShortcuts.index(strkeycode) elif strkeycode in frame.Shortcuts: drpy = frame.Shortcuts.index(strkeycode) elif strkeycode in frame.DrScriptShortcuts: drscript = frame.DrScriptShortcuts.index(strkeycode) if plugin > -1: r = frame.PluginAction[plugin](event) if r is None or (r == 1): return -1 if stc.IsAPrompt: if (frame.STCCOMMANDLIST[drstc] == wx.stc.STC_CMD_NEWLINE) or \ (frame.STCCOMMANDLIST[drstc] == wx.stc.STC_CMD_CHARLEFT) or \ (frame.STCCOMMANDLIST[drstc] == wx.stc.STC_CMD_CHARRIGHT) or \ (frame.STCCOMMANDLIST[drstc] == wx.stc.STC_CMD_LINEUP) or \ (frame.STCCOMMANDLIST[drstc] == wx.stc.STC_CMD_LINEDOWN) or \ (frame.STCCOMMANDLIST[drstc] == wx.stc.STC_CMD_DELETEBACK) or \ (frame.STCCOMMANDLIST[drstc] == wx.stc.STC_CMD_HOME): return frame.STCCOMMANDLIST[drstc] elif frame.STCCOMMANDLIST[drstc] == wx.stc.STC_CMD_DELETEBACK: return wx.stc.STC_CMD_DELETEBACK if drstc > -1 and (not drpy > -1) and (not drscript > -1): try: if frame.STCCOMMANDLIST[drstc] == wx.stc.STC_CMD_PASTE: stc.Paste() else: stc.CmdKeyExecute(frame.STCCOMMANDLIST[drstc]) except: return -1 return frame.STCCOMMANDLIST[drstc] if SplitView: return -1 if drpy > -1 and (not drscript > -1) and (not drstc > -1): if frame.ShortcutsArgumentsArray[drpy] == "frame, event": frame.ShortcutsActionArray[drpy](event) elif frame.ShortcutsArgumentsArray[drpy] == "maximize": #Work Around Bug in wx.Python 2.5.1 try: frame.ShortcutsActionArray[drpy](not frame.IsMaximized()) except: pass return -1 if drscript > -1 and (not drpy > -1) and (not drstc > -1): event.SetId(frame.ID_SCRIPT_BASE + drscript) frame.DrScriptShortcutsAction(event) return -1 event.Skip() return -1 drpython-3.11.1/drSingleChoiceDialog.py0000644000175000017500000001601011150445514020624 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Single Choice Dialog (Keyboard Navigation, FindCompletion with TextCtrl Echo.) import wx #******************************************************************************************************* class drSingleChoiceDialog(wx.Dialog): def __init__(self, parent, title, choices, sort=True, point=wx.DefaultPosition, size=(250, 300), SetSizer=True): wx.Dialog.__init__(self, parent, -1, title, point, size, wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.THICK_FRAME | wx.RESIZE_BORDER) self.parent = parent self.ID_CHOICES = 101 self.ID_TXT_CHOICE = 102 self.ID_OK = 111 self.ID_CANCEL = 112 #/Constants #Components: self.listChoices = wx.ListView(self, self.ID_CHOICES, (0, 0), (300, 300), style=wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.LC_NO_HEADER) self.txtChoice = wx.TextCtrl(self, self.ID_TXT_CHOICE, '', (0, 0), (250, -1), style=wx.TE_READONLY) self.choices = choices self.listChoices.InsertColumn(0, 'Choices') if sort: self.choices.sort() self.setupchoices() self.OnSize(None) self.btnOk = wx.Button(self, self.ID_OK, " &Ok ") #self.btnOk.SetDefault() self.btnCancel = wx.Button(self, self.ID_CANCEL, " &Cancel ") #/Components #Sizer: self.theSizer = wx.BoxSizer(wx.VERTICAL) self.textSizer = wx.BoxSizer(wx.HORIZONTAL) self.textSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED | wx.ALIGN_RIGHT) self.textSizer.Add(self.txtChoice, 1, wx.EXPAND) self.textSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.listSizer = wx.BoxSizer(wx.HORIZONTAL) self.listSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED | wx.ALIGN_RIGHT) self.listSizer.Add(self.listChoices, 1, wx.EXPAND) self.listSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.commandSizer = wx.BoxSizer(wx.HORIZONTAL) self.commandSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED | wx.ALIGN_RIGHT) self.commandSizer.Add(self.btnCancel, 0, wx.SHAPED | wx.ALIGN_LEFT) self.commandSizer.Add(wx.StaticText(self, -1, ' '), 1, wx.EXPAND) self.commandSizer.Add(self.btnOk, 0, wx.SHAPED | wx.ALIGN_RIGHT) self.commandSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED | wx.ALIGN_RIGHT) self.theSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.theSizer.Add(self.textSizer, 0, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.theSizer.Add(self.listSizer, 9, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.theSizer.Add(self.commandSizer, 0, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.SetAutoLayout(True) if SetSizer: self.SetSizerAndFit(self.theSizer) #/Sizer #Events: self.Bind(wx.EVT_BUTTON, self.OnbtnCancel, id=self.ID_CANCEL) self.Bind(wx.EVT_BUTTON, self.OnbtnOk, id=self.ID_OK) self.listChoices.Bind(wx.EVT_LEFT_DCLICK, self.OnbtnOk) self.txtChoice.Bind(wx.EVT_CHAR, self.OnChar) if wx.Platform == '__WXGTK__': self.txtChoice.SetFocus() else: self.Bind(wx.EVT_CHAR, self.OnChar) self.listChoices.Bind(wx.EVT_CHAR, self.OnChar) self.listChoices.Bind(wx.EVT_SIZE, self.OnSize) #/Events if self.listChoices.GetItemCount() > 0: self.listChoices.Select(0) self.listChoices.Focus(0) self.typedchoice = '' def GetSelection(self): return self.listChoices.GetItemData(self.listChoices.GetFirstSelected()) def GetStringSelection(self): return self.listChoices.GetItemText(self.listChoices.GetFirstSelected()) def OnbtnCancel(self, event): self.EndModal(wx.ID_CANCEL) def OnbtnOk(self, event): if self.listChoices.GetItemCount() > 0: self.EndModal(wx.ID_OK) else: self.EndModal(wx.ID_CANCEL) def OnChar(self, event): keycode = event.GetKeyCode() if keycode >= 32 and keycode <= 127: self.typedchoice += chr(keycode).lower() self.UpdateTypedChoice() elif keycode == wx.WXK_BACK: self.typedchoice = self.typedchoice[:-1] self.UpdateTypedChoice() if keycode == wx.WXK_UP or keycode == wx.WXK_DOWN: i = self.listChoices.GetFocusedItem() if keycode == wx.WXK_UP: i -= 1 elif keycode == wx.WXK_DOWN: i += 1 if (i < self.listChoices.GetItemCount()) and (i > -1): self.listChoices.Select(i) self.listChoices.Focus(i) return if keycode == wx.WXK_ESCAPE: self.OnbtnCancel(None) elif keycode == wx.WXK_RETURN: self.OnbtnOk(None) else: event.Skip() def OnSize(self, event): self.listChoices.SetColumnWidth(0, self.listChoices.GetSizeTuple()[0]) if event is not None: event.Skip() def setupchoices(self, findstr=''): self.listChoices.DeleteAllItems() x = 0 sofar = 0 if findstr: for c in self.choices: a = c.lower() if a.find(findstr) > -1: self.listChoices.InsertStringItem(sofar, c) self.listChoices.SetItemData(sofar, x) sofar += 1 x += 1 else: for c in self.choices: self.listChoices.InsertStringItem(x, c) self.listChoices.SetItemData(x, x) x += 1 def UpdateTypedChoice(self): self.txtChoice.SetValue(self.typedchoice) if wx.Platform == '__WXGTK__': self.txtChoice.SetSelection(len (self.typedchoice), len(self.typedchoice)) self.setupchoices(self.typedchoice) if self.listChoices.GetItemCount() > 0: self.listChoices.Select(0) self.listChoices.Focus(0)drpython-3.11.1/drOpenImportedModuleDialog.py0000644000175000017500000001147311150445515022054 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Open Imported Module Dialog import os, sys, keyword import wx from drSingleChoiceDialog import drSingleChoiceDialog #******************************************************************************************************* #Utility Functions for parsing import strings, #and getting the path for each module. def GetModulePath(filepath, selmodule, platformiswin): moduletext = selmodule #Special Cases: if selmodule == 'os.path': if platformiswin: selmodule = 'ntpath' elif os.name == 'mac': selmodule = 'macpath' else: selmodule = 'posixpath' selectedmodule = '/' + selmodule.replace('.', '/') + '.py' #Handle cases like 'import wx' == import 'wx.__init__' selectedinitmodule = '/' + selmodule.replace('.', '/') + '/__init__.py' if os.path.exists(filepath + selectedmodule): return moduletext, (filepath + selectedmodule) if os.path.exists(filepath + selectedinitmodule): return moduletext, (filepath + selectedinitmodule) #Search for the file: for somepath in sys.path: modulefile = somepath.replace('\\', '/') + selectedmodule initfile = somepath.replace('\\', '/') + selectedinitmodule if os.path.exists(modulefile): return moduletext, modulefile elif os.path.exists(initfile): return moduletext, initfile return moduletext, None def ParseImportStatement(matches): targetarray = map(lambda x: x.strip().split(), matches) results = [] for item in targetarray: x = 0 isfrom = (item[0] == 'from') l = len(item) while x < l: if item[x].find(',') > -1: y = item.pop(x) ya = y.split(',') ly = len(ya) counter = 0 while counter < ly: if not ya[counter]: ya.pop(counter) ly -= 1 else: counter += 1 item.extend(ya) l = l + len(ya) - 1 elif item[x] == 'as': item.pop(x) try: item.pop(x) l -= 2 except: l -= 1 elif item[x] == '*': item.pop(x) l -= 1 elif item[x] in keyword.kwlist: item.pop(x) l -= 1 else: if (x > 0) and isfrom: a = item.pop(x) item.insert(x, item[0] + '.' + a) x += 1 results.append(item) return results #******************************************************************************************************* class drOpenImportedModuleDialog(drSingleChoiceDialog): def __init__(self, parent, modulelist, point=wx.DefaultPosition, size=(250, 300)): drSingleChoiceDialog.__init__(self, parent, "Open Imported Module", modulelist, point, size) #Why is this needed? Who knows. But it is. self.Move(point) self.Bind(wx.EVT_CLOSE, self.OnCloseW) self.parent.LoadDialogSizeAndPosition(self, 'openimportedmoduledialog.sizeandposition.dat') if parent.PLATFORM_IS_GTK: #does not get initially the focus (bug tracker #1903778, "Open Imported Module: focus problem", 29.02.2008: from Jon White, thanks. self.SetFocus() def GetSelectedModule(self): return self.GetStringSelection() def OnbtnCancel(self, event): self.OnCloseW(None) drSingleChoiceDialog.OnbtnCancel(self, event) def OnbtnOk(self, event): self.OnCloseW(None) drSingleChoiceDialog.OnbtnOk(self, event) def OnCloseW(self, event): self.parent.SaveDialogSizeAndPosition(self, 'openimportedmoduledialog.sizeandposition.dat') if event is not None: event.Skip() drpython-3.11.1/drGetBlockInfo.py0000644000175000017500000002145511150445514017467 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Functions for getting information about blocks import re reNotEmpty = re.compile('\S') def CheckIfBlockStart(lines, targetline): LineIndent = GetLineIndentation(lines, targetline) if LineIndent == -1: LineIndent = FindValidLine(lines, targetline) if LineIndent == -1: return False #try till the end l = len(lines) li = 1 result = -1 while result == -1: if targetline + li >= l: break result = GetLineIndentation(lines, targetline+li) li += 1 if result > LineIndent: return li - 1 return False def FindValidLine(lines, targetline): #try till the end l = len(lines) li = 1 result = -1 while result == -1: if targetline + li >= l: break result = GetLineIndentation(lines, targetline+li) if result == -1: if targetline - li <= 0: break result = GetLineIndentation(lines, targetline-li) li += 1 return result def RestructureExplicitLineJoining(lines): editedlines = [lines[0]] x = 1 l = len(lines) while x < l: lline = len(lines[x-1]) if lline > 0: if lines[x-1][lline - 1] == '\\': editedlines.append(' ') else: editedlines.append(lines[x]) else: editedlines.append(lines[x]) x += 1 return editedlines def RestructureImplicitLineJoining(lines): editedlines = [] x = 0 l = len(lines) while x < l: p1 = _get_paren_spread(lines[x], '[', ']') p2 = _get_paren_spread(lines[x], '(', ')') p3 = _get_paren_spread(lines[x], '{', '}') end = 0 if p1: end = _find_paren_end_line(lines, x+1, p1, '[', ']') if end == -1: editedlines.extend(lines[x:]) break if p2: tend = _find_paren_end_line(lines, x+1, p2, '(', ')') if tend == -1: editedlines.extend(lines[x:]) break if tend > end: end = tend if p3: tend = _find_paren_end_line(lines, x+1, p3, '{', '}') if tend == -1: editedlines.extend(lines[x:]) break if tend > end: end = tend editedlines.append(lines[x]) if end > 0: newlines, x = _make_lines_whitespace(lines, x+1, end) editedlines.extend(newlines) else: x += 1 return editedlines def RemoveComments(lines): lines = removeStringQuotedWith(lines, "'''") lines = removeStringQuotedWith(lines, '"""') lines = removeStringQuotedWith(lines, "'") lines = removeStringQuotedWith(lines, '"') editedlines = [] for line in lines: c = line.find('#') if c > -1: editedlines.append(line[:c] + ' ') else: editedlines.append(line) return editedlines def removeQuoteFromSingleLine(line, start, target): ft2 = line[start:].find(target) s = reNotEmpty.search(line).start() #Only remove the string if it is not the first bit of the line. if (ft2 > -1) and (start > s): ft2 += start return line[:start] + ' ' + line[:ft2] return None def removeStringQuotedWith(lines, target): editedlines = [] x = 0 l = len(lines) while x < l: ft = lines[x].find(target) if ft > -1: sameline = removeQuoteFromSingleLine(lines[x], ft, target) if sameline is not None: editedlines.append(sameline) else: editedlines.append(lines[x][:ft]) start = x x += 1 end = -1 while x < l: ft = lines[x].find(target) if ft > -1: end = x break x += 1 if end == -1: return editedlines else: newlines, x = _make_lines_whitespace(lines, start, end) editedlines.extend(newlines) else: editedlines.append(lines[x]) x += 1 return editedlines def spacefill(length): result = '' for x in range(length): result += ' ' return result def _get_paren_spread(text, openp, closep): opencount = text.count(openp) if opencount > 0: closecount = text.count(closep) if opencount > closecount: return opencount - closecount return 0 def _find_paren_end_line(lines, pos, spread, openp, closep): x = pos l = len(lines) count = 0 while x < l: count += lines[x].count(closep) spread += lines[x].count(openp) if count >= spread: return x x += 1 return -1 def _make_lines_whitespace(lines, startline, endline): newlines = [] x = startline while x <= endline: newlines.append(reNotEmpty.sub(' ', lines[x])) x += 1 return newlines, x def GetLines(Document): text = Document.GetText() eol = Document.GetEndOfLineCharacter() lines = text.split(eol) lines = RestructureExplicitLineJoining(lines) lines = RemoveComments(lines) lines = RestructureImplicitLineJoining(lines) return lines def GetBlockStart(lines, targetline): LineIndent = GetLineIndentation(lines, targetline) if LineIndent == -1: LineIndent = FindValidLine(lines, targetline) if LineIndent == -1: return -1 x = targetline - 1 while x > 0: i = GetLineIndentation(lines, x) if i != -1: if i < LineIndent: return x x -= 1 return 0 def GetBlockEnd(lines, targetline): l = len(lines) LineIndent = GetLineIndentation(lines, targetline) if LineIndent == -1: LineIndent = FindValidLine(lines, targetline) if LineIndent == -1: return -1 x = targetline + 1 last = targetline while x < l: i = GetLineIndentation(lines, x) if i != -1: if i >= LineIndent: last = x if i < LineIndent: return last x += 1 if last != x: return last return len(lines) - 1 def GetKeyWordStart(lines, targetline, kword, kwordlength): start = GetBlockStart(lines, targetline) if kwordlength == 0: return start while lines[start].strip()[:kwordlength] != kword: start = GetBlockStart(lines, start) if start == 0: break return start def GetKeyWordEnd(lines, targetline, kword, kwordlength): if (kwordlength == 0) or (lines[targetline].strip()[:kwordlength] == kword): startofblock = CheckIfBlockStart(lines, targetline) if startofblock: targetline += startofblock else: targetline = GetKeyWordStart(lines, targetline, kword, kwordlength) + 1 end = GetBlockEnd(lines, targetline) return end def GetLineIndentation(lines, current): result = reNotEmpty.search(lines[current]) if result == None: return -1 return result.start() def GoToBlockEnd(Document, kword=''): lines = GetLines(Document) kwordl = len(kword) l = GetKeyWordEnd(lines, Document.GetCurrentLine(), kword, kwordl) i = GetLineIndentation(lines, l) if i < 0: i = 0 Document.EnsureVisible(l) Document.GotoLine(l) p = Document.PositionFromLine(l) + i Document.GotoPos(p) Document.SetSTCFocus(True) def GoToBlockStart(Document, kword=''): lines = GetLines(Document) kwordl = len(kword) l = GetKeyWordStart(lines, Document.GetCurrentLine(), kword, kwordl) i = GetLineIndentation(lines, l) if i < 0: i = 0 Document.EnsureVisible(l) Document.GotoLine(l) p = Document.PositionFromLine(l) + i Document.GotoPos(p) Document.SetSTCFocus(True) drpython-3.11.1/examples/0000755000175000017500000000000011246265352016076 5ustar dktrkranzdktrkranzdrpython-3.11.1/examples/DrScript/0000755000175000017500000000000011246265352017630 5ustar dktrkranzdktrkranzdrpython-3.11.1/examples/DrScript/drscript.dat0000644000175000017500000000113411150445515022146 0ustar dktrkranzdktrkranzexamples/DrScript/ReverseAssignment.pyReverse Assigment examples/DrScript/PrintEndOfLineCharactersInPrompt.pyPrint End Of Line Characters In Prompt >Run In Terminal examples/DrScript/RunInTerminal.pyRun In Terminal examples/DrScript/SetTerminalArgs.pySet Arguments For Run In Terminal >In Selection examples/DrScript/ReplaceAllInSelection.pyReplace All In Selection examples/DrScript/SwitcherooInSelection.pySwitcheroo In Selection drpython-3.11.1/examples/DrScript/SwitcherooInSelection.py0000644000175000017500000000130611150445515024460 0ustar dktrkranzdktrkranz#drscript #Updated to new namespace. #By Daniel Pozmanter #Released under the GPL target = "" newtext = "" d = wx.TextEntryDialog(DrFrame, "Switch What?:", "Switch All In Selection", "") if d.ShowModal() == wx.ID_OK: target = d.GetValue() d = wx.TextEntryDialog(DrFrame, ("Switch " + target + " With:"), "Switch All In Selection", "") if d.ShowModal() == wx.ID_OK: newtext = d.GetValue() drpytemp = "DRPYTHON111TEMP" selection = DrDocument.GetSelectedText() selection = selection.replace(newtext, drpytemp) selection = selection.replace(target, newtext) selection = selection.replace(drpytemp, target) DrDocument.SetSelectedText(selection)drpython-3.11.1/examples/DrScript/ReplaceAllInSelection.py0000644000175000017500000000072511150445515024342 0ustar dktrkranzdktrkranz#drscript #By Daniel Pozmanter #Released under the GPL target = "" newtext = "" d = wx.TextEntryDialog(DrFrame, "Replace What?:", "Replace All In Selection", "") if d.ShowModal() == wx.ID_OK: target = d.GetValue() d = wx.TextEntryDialog(DrFrame, ("Replace " + target + " With:"), "Replace All In Selection", "") if d.ShowModal() == wx.ID_OK: newtext = d.GetValue() DrDocument.SetSelectedText(DrDocument.GetSelectedText().replace(target, newtext))drpython-3.11.1/examples/DrScript/PrintEndOfLineCharactersInPrompt.py0000644000175000017500000000047511150445515026514 0ustar dktrkranzdktrkranz#drscript #By Daniel Pozmanter #Released under the GPL drdoctext = DrDocument.GetText() l = len(drdoctext) x = 0 s = "" while x < l: if drdoctext[x] == '\r': s = s + "\n" elif drdoctext[x] == '\n': s = s + "\n" x = x + 1 DrFrame.ShowPrompt() DrPrompt.SetText(s)drpython-3.11.1/examples/DrScript/RunInTerminal.py0000644000175000017500000000117311150445515022726 0ustar dktrkranzdktrkranz#drscript #This currently only works on linux (if you have rxvt installed). #You will need to modify it otherwise. #By Daniel Pozmanter #Released under the GPL import os, sys if sys.platform.find("linux") > -1: pathtoterminal = "/usr/bin/X11/rxvt" termarg = "-e" withargs = "" if DrScript.VariableExists("RunInTerminalArgs"): withargs = " " + DrScript.RunInTerminalArgs pyexec = "/usr/bin/python " + DrFrame.GetFileName() + withargs os.spawnl(os.P_NOWAIT, pathtoterminal, pathtoterminal, termarg, pyexec) else: wx.MessageBox("Only supported under Linux", "RunInTerminal", wx.OK, DrFrame)drpython-3.11.1/examples/DrScript/ReverseAssignment.py0000644000175000017500000000100611150445515023636 0ustar dktrkranzdktrkranz#drscript #By Daniel Pozmanter #Released under the GPL endOfLineChar = DrDocument.GetEndOfLineCharacter() targets = DrDocument.GetSelectedText().split(endOfLineChar) l = len(targets) c = 0 newselection = "" while c < l: x = targets[c].find('=') if x > -1: targets[c] = targets[c][x+2:] + " = " + targets[c][0:x] newselection = newselection + targets[c] if c < (l - 1): newselection = newselection + endOfLineChar c = c + 1 DrDocument.SetSelectedText(newselection)drpython-3.11.1/examples/DrScript/SetTerminalArgs.py0000644000175000017500000000076211150445515023246 0ustar dktrkranzdktrkranz#drscript #This currently only works on linux (if you have rxvt installed). #You will need to modify it otherwise. #By Daniel Pozmanter #Released under the GPL import os pathtoterminal = "/usr/bin/X11/rxvt" termarg = "-e" withargs = "" if DrScript.VariableExists("RunInTerminalArgs"): withargs = DrScript.RunInTerminalArgs d = wx.TextEntryDialog(DrFrame, "Arguments:", "Set Arguments For Run In Terminal", withargs) if d.ShowModal() == wx.ID_OK: DrScript.RunInTerminalArgs = d.GetValue()drpython-3.11.1/drMenu.py0000644000175000017500000000327711150445515016070 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Menus import os.path import wx class drMenu(wx.Menu): def __init__(self, parent): wx.Menu.__init__(self) self.parent = parent self.bitmapdirectory = self.parent.programdirectory + "/bitmaps/16/" def Append(self, id, label, LaunchesDialog = False, AmpersandAt = -1, AbsoluteLabel=''): ''' Appends the item, any applicable bitmap, and also any keyboard shortcut. ''' item = wx.MenuItem(self, id, self.parent.getmenulabel(label, LaunchesDialog, AmpersandAt, AbsoluteLabel)) bitmap = self.bitmapdirectory + label + '.png' if os.path.exists(bitmap): item.SetBitmap(wx.BitmapFromImage(wx.Image(bitmap, wx.BITMAP_TYPE_PNG))) return self.AppendItem(item) drpython-3.11.1/History.txt0000644000175000017500000045210211150445514016460 0ustar dktrkranzdktrkranzFor Version 3.10.13: Bugs Fixed: Properly loads multi line preferences. (Bug-Report, Thanks bugmenot) Autoindent no longer checks for non whitespace lines when determining indent. Syncs the prompt with an exact method (waits for correct output) when adding in a startup script. Gracefully handles a user opening new prompts faster than wx.Yield can cope. Properly handles locale error (Bug-Report, Thanks fstephens2) Properly saves prompt. (Bug-Report, Thanks Franz Steinhausler) Only trims whitespace on tab when at the end of the line. Fixed bug in drFileDialog that caused the interface to stop working when switching the view from detailed to list. Checks indentation type rather than prefs when handling backspace. Sets indentation type initially to prefs, checks indentation type when setting up doc prefs. Removed superfluous OnRemoveScript in drScriptMenu.py (Bug-Report With Fix, Thanks Franz Steinhausler) Strips trailing whitespace on autoindent. (Bug-Report, Thanks Dan Kruger) Removed SetTabs from Side Panel Pop Up Menu. (Bug-Report, Thanks Franz Steinhausler) In Side Panel Pop Up Menu, Close now works. Sets untitled number to -1 on open (Bug-Report, Thanks Franz Steinhausler) Treats NumPad Enter as Enter (Bug-Report, Thanks Franz, indefual) Properly handles permission denied error in OpenFile. Add Folder works in Edit Script Menu (Bug-Report, Thanks Franz Steinhausler) No longer prints indentation type on paste. Added a brief README.TXT to note drpython itself does not need to be installed. Changes: The File ComboBox in the File Dialog now contains the listed files in the current directory, rather than recent files. About Dialog Title String now size 12. ******************************************************************************************************************************** For Version 3.10.12: Bugs Fixed: Properly sets the indentation type in OpenFile. Cursor no longer stuck at the editpoint in the prompt. Proper keyboard navigation after autoindent. Changes: new setup.py from Christoph: Classifiers, post installation, setup.cfg. (Submitted Patch, Thanks Christoph Zwerschke). ******************************************************************************************************************************** For Version 3.10.11: Bugs Fixed: Removed unnecessary variable self.needtoindent in drText. Indentation: (Bug-Report, Thanks Franz Steinhausler) Off by one error in autoindent fixed. lstrips extraneous whitespace from the next line. tries the current line's indentation first. Checks the indentation level of the previous line and whether or not it has whitespace, and includes that indentation in the autoindent if the user has indented in a relevant manner. Minor doc fix for shortcuts. Remove trailing whitespace is off by default. Added Check for alreadyopen to drbookmark menu (Bug-Report With Fix, Thanks Franz Steinhausler) PrefsDialog stores doccomment mode.(Bug-Report With Fix, Thanks Franz Steinhausler) Add New, Existing Scripts, Shell Command all function properly with regards to shortcuts. (Bug-Report, Thanks Franz Steinhausler) Properly checks for None when running a plugin shortcuts. (Bug-Report, Thanks Franz Steinhausler) Updated setup.py with the full version by Christoph. (Submitted Patch, Thanks Christoph Zwerschke) Changes: Added a default shortcut for Close (Bug-Report/Feature Request With Co-Fix, Thanks widhaya3) Changed the default for toggle view whitespace to control + shift + w. Updated docs. ******************************************************************************************************************************** For Version 3.10.10: Bugs Fixed: Shortcuts work properly again: Returns -1 instead of 0 at the end RunShortcuts. Handles event.Skip in RunShortcuts if no relevant shortcuts are found. Reserved stc commands for the prompt only cause an early exit if the target stc is a prompt. cleaned up OnKeyDown in drPrompt. Reworked autoindent handling. Changes: Implemented Auto Back Tab for spaces. (Bug-Report/Feature Request, Thanks Christoph Zwerschke) ******************************************************************************************************************************** For Version 3.10.9: Bugs Fixed: Fixed Run, End images on windows. Sourcebrowser: regex updated, now compiled on startup rather than on browse. def colour fixed. (Bug-Report With Fix, Thanks Franz Steinhausler) Now sets level of separators based on the next non whitespace item. (Bug-Report With Co-Fix, Thanks Christoph Zwerschke) Updated Documentation. Added Patch to setup.py (Submtited Patch, Thanks Christoph Zwerschke) Shortcuts: RunShortcuts now returns the stc command (if applicable). (Bug-Report/Feature Request, Thanks Franz Steinhausler) More flexible code allows for both plugin and stc/frame/drscript items to be run. Fixed drscript shortcuts handling. (Bug-Report, Thanks Franz Steinhausler) Changed how shortcuts are stored in the string (no whitespace, no commas). (Bug-Report, Thanks Christoph Zwerschke) Changed the get key display. Indentation correction only runs if the text up to the current position is whitespace. (Bug-Report, Thanks Christoph Zwerschke) Changes: You can now set the indentation guide style (for python). (Bug-Report/Feature Request with Co-Fix, Thanks Christoph Zwerschke) ******************************************************************************************************************************** For Version 3.10.8: Bugs Fixed: Auto Indentation now indents based on the indentation of the last non whitespace line. Replace: From Cursor is now disabled. Removed scroll width code from OnModified. Fixed drscript menu: arguments to Append. Separator Dialog button fix (on windows). (Bug-Report With Fix, Thanks Christoph Zwerschke) Better method of getting the character of interest for context sensitive autoindent. Renamed Go To Source Browser bitmap to Source Browser Go To. Changes: Added icons to the menu. (Bug-Report/Feature Request, Thanks Franz Steinhausler) New Icons (From Nuvola 1.0) (Some Edited): Help, Preferences, Customize Pop Up Menu, Customize Shortcuts, Customize ToolBar, Run, End, Exit, Print File, Print Prompt, Print Setup, Save Prompt Output To File, Cut, Copy, Paste, Delete, Find, Find Next, Find Previous, Replace. Edited Open, Open Imported Module Icons. Comment Block is now its own Python Style. Default is now a transparent bitmap. Default shortcut for BackTab is now Shift + Tab. (Bug-Report/Feature Request, Thanks Christoph Zwerschke) Added Cautionary note about shortcuts to help. ******************************************************************************************************************************** For Version 3.10.7: Bugs Fixed: Saves favorite colours in the user's preferences directory, instead of the program directory. Shortcuts: Reset Shortcuts works properly. ShortcutIsAlreadyTaken returns properly if the shortcut is empty. (Bug-Report, Thanks Franz Steinhausler) Properly loads default stc shortcuts. (Bug-Report, Thanks Franz Steinhausler) Separators are now nested purely based on indentation. (Bug-Report, Thanks Christoph Zwerschke) Separators can now include any amount of whitespace. The Configure Plugins, DrScript, Documents, and the Options menus now display shortcuts. ExecuteCommands: now preceded by a call to wx.Yield. changed the order of events. increased Usleep to 75. Promptly returns if no commands are given. Documentation Grammar Fixes. Indentation correction properly checks for spaces. Removed .separator.favorite.colours.dat. Changes: Added SourceBrowser separator info to documentation. Menus are now drMenus, Append automatically adds labels. New Icon for Close Prompt. Optionally Removes Trailing Whitespace (Bug-Report/Feature Request with Co-Fix, Thanks Franz Steinhausler) Updated Preferences Documentation. Default separator colours. (Bug-Report/Feature Request, Thanks Christoph Zwerschke) Reoganized the whitespace menu. (Bug-Report/Feature Request, Thanks Franz Steinhausler) ******************************************************************************************************************************** For Version 3.10.6: Bugs Fixed: Close Panel bug squashed. (Bug-Report, Thanks Franz Steinhausler) FileDialog: Now always blanks the combobox when switching directories. DrText: Only updates titles if the modification state is changing. OpenFile: removed SetTitle Argument, code. SourceBrowser: Uniformly adds transparent bitmap, (Bug-Report, Thanks Christoph Zwerschke) New method of adding labels. (Bug-Report/Feature Request, Thanks Christoph Zwerschke) Now uses the correct starting position for separators. Minor bug in OnbtnApplyProperty in drPrefsDialog fixed. Increased the Usleep time slightly in drPrompt. Removed uneccessary styles from default.css Shortcuts: Shortcuts are now stored as strings instead of as python objects. Now shortcut handling code ensures no shortcut is called twice. Alt, Meta order is now consistant internally. Shows dialog on all exceptions, not just IOError. Fixed Tab Correction Code. (Bug-Report, Thanks Franz Steinhausler) Removed unused variable, menuspacestring. Fixed Open Imported Module Menu Label. Changes: Now keeps track of modifications to drTreeDialogs, and prompts the user to save on close. SourceBrowser: Allows whitespace after label (Bug-Report/Feature Request, Thanks Christoph Zwerschke) Uses a blank bitmap for labels (Bug-Report/Feature Request, Thanks Christoph Zwerschke) Separators: Added GetValue to drColorPanel. You can now save 5 colours. (Bug-Report/Feature Request, Thanks Christoph Zwerschke) The Pop Up Menu now displays shortcuts. (Submitted Patch, Thanks Franz Steinhausler) ******************************************************************************************************************************** For Version 3.10.5: Bugs Fixed: Removed Icon File from Preferences Documentation. View In Panel Bug Fixed: No longer destorys the panel when the size is 0. Sash Resize: Minor sizing bug fixed with top panel. Checks the proper part of the top tuple when resizing. (Bug-Report, Thanks Franz Steinhausler) Adjusted the regular expressions for classes and definitions in the SourceBrowser and SourceBrowserGoTo to be more permissive (and work with multiline declarations). removed unused BTN_Y_POS in drSimpleStyleDialog. Documentation error fixed in drscript.html. Added docutils to help. Changes: DrPrompt: added ExecuteCommands, runs commands separated by '\n' in the prompt. added optional startup script. (Updated Preferences Documentation). The Find Dialog text controls are now a bit bigger. documentation: css: made the code block backgrounds a bit lighter. Now uses SilverCity, and an ASPN recipe by Kevin Schluff to highlight python code for the documentation. (Co-Fix, Thanks to Marek Kubica) Edited help.html Added the wrapper I made, plus the ASPN recipe to documentation directory. (Read the source drdoc.py for details on usage). SourceBrowser: You can now add SPE style labels to the source browser: #---Label and #---Label---#Foreground#Background (Bug-Report/Feature Request, Thanks Christoph Zwerschke) added convertStyleToColorArray to drProperty.py SourceBrowser uses style colors in document for class/def (Bug-Report/Feature Request, Thanks Franz Steinhausler) Added Insert Separator. ******************************************************************************************************************************** For Version 3.10.4: Bugs Fixed: Windows bugfix, in OnSize. (Bug-Report, Thanks Christoph Zwerschke) Properly keeps track of panel indexes. (Bug-Report, Thanks Franz Steinhausler) Removed unused code in drSidePanelNotebook. Checks to ensure a valid selection when changing document/prompt. (Bug-Report, Thanks Franz Steinhausler) Proper Menu title for toggle source browser: (Bug-Report With Fix, Thanks Christoph Zwerschke) Error Messages for Remembering Sizes and Positions are now more clear. (Bug-Report, Thanks Franz Steinhausler) Reworked side panel code with sizing fixes OnPageChanged, and during addition of pages. Removed unused debugging code in drEncoding. Changes: AboutDialog: Messed with the dialog to make gpl.html display nicer. Removed dis.html from the documentation. Documentation: Now uses docutils. (Thanks Marek Kubica). Edited (through a wrapper python script): To tone down gpl.html, and remove encoding info. I also messed with the css a bit. ******************************************************************************************************************************** For Version 3.10.3: Bugs Fixed: in drNotebook.py, calls wx.Yield before OnSize in ClosePanel. (Fixes Windows specific bug) (Bug-Report, Thanks Christoph Zwerschke). Panel error in drShortcutsFile.py fixed. Changes: Now autodetect encoding first checks for a special comment that gives the encoding, and will try that encoding first. (Bug-Report/Feature Request, Thanks Christoph Zwerschke) Updated drPrefsDialog. Updated Help, Preferences Documentation. The top panel is back (Bug-Report/Feature Request, Thanks Christoph Zwerschke) View In Top Panel is Back. Updated Preferences Documentation. ******************************************************************************************************************************** For Version 3.10.2: Bugs Fixed: Removed Clear Prompt bitmaps. Properly handles closed sourcebrowser. Minor cleanup in help.html Find From Cursor now just starts at the cursor, and does not limit the search from the cursor on. Minor internal fixes for remembering dialog size and position. If a file argument to DrPython does not exist, Asks the user if they want to create the file. Fixed c++ style order in drKeywords (Bugfix, Thanks Franz Steinhausler) c identifier default style no longer bold. wx.Yield Problem fixed in drPrefsDialog. (Bug-Report, Thanks Christoph Zwerschke) (Bug-Report, Thanks Franz Steinhausler) Changes: Reworked Plugin Events: No uses DrFrame.PBind, PUnbind, and PPost for events, to enable more flexibility, and allow events to be removed with greater ease. Updated Plugins Documentation. New Icons for Set Arguments (Bug-Report/Feature Request Thanks Toronto DrPython Project). Find From Cursor is now enabled by default. Added Remember Panel Sizes to Preferences. Updated Preferences Documenation. Updated Plugin List. ******************************************************************************************************************************** For Version 3.10.1: Bugs Fixed: Adjusted font size in About Dialog: System Info Panel. Display bug in open file (when in a new tab fixed): (Bug-Report, Thanks Marek Kubica). Now uses DrFrame.OnNew for new tabs. Removed unused view in panel methods. Reworked Side Panel Sizing to ensure proper sizing on windows: (Bug-Report With Co-Fix, Thanks Toronto DrPython Project). "--preferencesbasepath": Now expands '~'. Changes: DrPython now uses mainpanel.ShowPanel(Position, Index) instead of OnSize when creating a new side panel. ShowPanel's third argument is now True by default. Updated Plugins Documentation. Removed Clear Prompt. Plugin List: Updated Removed SimpleDebugger, ToDo, ThemeMenu. Removed icon file support from the toolbar, preferences. ******************************************************************************************************************************** For Version 3.10.0: Bugs Fixed: New Interface: drNotebook: Removed unused menu items in pop up menu for tabs. Binds all events within the class. Removed residual sdi comments. Removed wxpython bug workaround in OnNew (no longer needed). prefs are now no longer updated when switching documents. Now this is only done when updating preferences. Checks for extra output in the correct Prompt. Preferences Documentation: Removed duplicates, added wxPython unicode note. wxFileDialog works again (Bug-Report, Thanks Franz Steinhausler) Now raises an exception if there is a bad encoding. Removed Non Ascii Character from Changelog (Bug-Report, Thanks Richard Townsend) Encoding: Encoding now supported in View In Panel. Encoding now stored in the Document, used for SaveFile, View In Panel. Properly Decodes files when saving. Properly updates indentation types when changes line endings. Now DrFrame, Dialogs start at wx.DefaultPosition by default. (Bug-Report, Thanks Christoph Zwerschke). Minor code cleanup in PrefsDialog.py Shortcuts Double Launch Problem Fixed. (Bug-Report, Thanks Franz Steinhausler) Changes: No longer uses running bitmap in the statusbar for an active prompt. New Interface: Two Side Panels. Each Side Panel, the Document, and the Prompt panels have their own notebooks. mdinotebook -> documentnotebook. Prompt: New notebook icons for active, inactive running, not running. Running a new process opens a new prompt if one is already running. Added Close Prompt. The Source Browser is no longer a member of DrText (now DrFrame). Removed drPositionChooser Widget. Updated Preferences GetTargetSashWindow -> GetTargetNotebookPage Removed View In Top/Botom Panel. (for preferences.dat: sourcebrowser.pane -> sourcebrowser.panel). (Single Instance for Side Panels, Prompt)(Bug-Report/Feature Request, Thanks Toronto DrPython Project) (Tabbed Side Panels)(Bug-Report/Feature Request, Thanks Franz Steinhausler) Updated Preferences, Plugins Documentation. View In Panel: x -> Close Now uses the default background colour. Plugins: AddPluginXFunction (OpenFile, SaveFile, OnClose, OnNew) has been replaced with events. Events are defined as members of DrFrame (DrFrame.EVT_DRPY_DOCUMENT_CHANGED). You can bind functions to these events. Updated Plugins Documentation. New AboutDialog: Displays the version, logo at the top. A notebook displays: about: with links to the drpython website, and credits. license agreement: the gpl text. system info: wxPython, Python, Operating system version info. Removed uneccessary spacing in gpl.html. (Bug-Report/Feature Request, Thanks Marek Kubica). Update Indentation is now off by default. The Margin Width is now determined based on the length of the document When the file is opened and closed, with a one digit of extra room. (Bug-Report/Feature Request, Thanks Marek Kubica). You can now set whether or not to use the margin width in the preferences. Added SourceBrowser size as a preference (25% by default). (Bug-Report/Feature Request, Thanks Toronto DrPython Project) ******************************************************************************************************************************** For Version 3.9.10: Bugs Fixed: Only try encoding/unicode detection if wxpython was built with unicode support. Updated Encoding Documentation. (Bug-Report, Thanks Franz Steinhausler). Now uses encoding safe TextWidth method (more accurate) for determining scroll length. Properly checks syntax for files with non unix line endings: (Bug-Report, Thanks Marek Kubica). (Bug-Fix, Thanks Thanks Franz Steinhausler). os.startfile works properly (Bug-Report, Thanks Marek Kubica). Properly prints warning if there is an encoding error with an entry in a directory. Changes: C++ Styles: Added C Identifier, Global Class, Additional Comment Styles. (Bug-Report Feature Request, Thanks Thanks Franz Steinhausler). Changed the default colour for preprocessor. ******************************************************************************************************************************** For Version 3.9.9: Bugs Fixed: Now checks ascii even if no default encoding is set for file dialog. (Bug-Report, Thanks Marek Kubica). When handling trailing spaces, checks to ensure only spaces are chopped, and properly handles lines that include eol characters. Added a section on Encoding support to the Documentation. Changes: You can now optionally double click a tab to close it. (Bug-Report/Feature Request, Thanks RunLevelZero). Added Optional Auto Refresh to the Source Browser. (Bug-Report/Feature Request, Thanks Toronto DrPython Project). Updated Preferences Documentation. ******************************************************************************************************************************** For Version 3.9.8: Bugs Fixed: Moved common Encoding code to drEncoding. Updated OpenFile, SaveFile, OnSavePrompt Now safely checks encoding before saving file in SaveFile, OnSavePrompt. The prompt no longer segfaults from bad encoding. Properly handles empty drscript shortcuts in the menu. (Bug-Report with Co-Fix, Thanks Franz Steinhaulser) Append Extension onto Filename if there is no extension Added Default Extension (".py") to preferences. (Bug-Report, Thanks Toronto DrPython Project) Fixed Apply Text Property To All Styles in Prompt Preferences. Properly handles trailing spaces when adding indentation. (Bug-Report, Thanks Toronto DrPython Project) FileDialog: EndAndCheck now uses .GetPath to get the filename. Patch in OnbtnOk fixing the filename on windows. (Thanks Franz Steinhaulser) Fixed changelog error in 3.9.7 (read file twice -> read from file twice, ditto for save). Changes: Updated Preferences Documentation. ******************************************************************************************************************************** For Version 3.9.7: Bugs Fixed: Properly handles encoded text in the Prompt. SaveFile, OnSavePrompt Bug: Wrote to File Twice! (*Fixed 3.9.8*) No longer tries encoding mess in file dialog on non windows platforms. Properly handles bad encoding in the file dialog. OpenFile: Read From File Twice! (*Fixed 3.9.8*) Shows all errors in OnSavePrompt. References the correct txtDocument for writing encoded text in SaveFile. Reorganized file write code in SaveFile, OnSavePrompt. OnSaveAs: Checks to see if the save was successful, and resets the filename and returns otherwise. Changes: You can now add Plugin Shortcuts to the menu. (Bug-Report/Feature Request, Thanks Franz Steinhaulser) Added DrFrame.PrintTraceback() Updated Documentation: Plugins, Preferences. ******************************************************************************************************************************** For Version 3.9.6: Bugs Fixed: SourceBrowser launches again (bad function name for Bind). (Bug-Report, Thanks Peter Mayne) drUTF8.py -> drEncoding.py No longer double checks syntax during save as. (Bug-Report with Fix, Thanks Franz Steinhaulser) pychecker codefixes: drPrefsDialog, pnlLineEndings. duplicate method in drRegularExpressionDialog Bugfix in drOpenImportedModuleDialog (selmoudle -> selmodule) Removed unused variables (and cleaned up relevant code) in: drpython.py (EditRecentFiles, ovrstring, l (3 times), code, pos, txtDocument) drTreeDialog.py (y, frombranchtext) drDragAndDrop.py (doCut) drFileDialog (imagesize) drFindReplaceDialog (doclength, dText (2 times)) drNotebook (ID_CLOSE, edge) drPrefsFile (evaltext (2 times)) drShortcuts (keycode, keyindex) drSTC (wasnotmixed (2 times) (Submitted pychecker report, Thanks Franz Steinhaulser). Cleaned up the menu code in drScriptMenu.py stc shortcuts error fixed. Documentation fix in Plugins. New method of guessing the scroll width that is non ascii friendly (overestimates a bit). Cleaned up DrFrame class, removed arguments for title, preferences, and relevant code in __init__ Encoding: Properly encodes in the Prompt. Properly encodes in SaveFile, OpenFile, OnSavePrompt. (Bug-Report, Thanks Marek Kubica) Windows File Dialog encoding bug fixed. (Bug-Report, Thanks Marek Kubica) Prompt properly handles shortcuts when no program is running. File Dialog: Open error with recent files fixed in file dialog. Removed callafter selecting an item in the file dialog. Changes: doc browser: The default for windows is now os.startfile. (' for docbrowser preference). (Bug-Report/Feature Request, Thanks Marek Kubica) DrScript menu now displays shortcuts too. (Bug-Report/Feature Request, Thanks Franz Steinhaulser) Encoding: Added Default Encoding to preferences Added Encoding Menu to file dialog Updated Documentation ******************************************************************************************************************************** For Version 3.9.5: Bugs Fixed: drscript dialog: Properly adds pydata when adding a folder (Bug-Report, Thanks Franz Steinhaulser) no longer reports error activating item if there is no selection. py-lint codefixes: Removed unused function CheckBranch from drTreeDialog.py variable error in drPluginDialog.py (parent) Removed unused imports from: drBookmarksDialog.py (os.path) drFileDialog.py (string) drFileDialogPrefs.py (os.path, re, drGetKeyDialog, drShortcuts, drShortcutsFile) drFindReplaceDialog.py (os.path) drPopUp.py (drShortcuts, drShortcutsFile) drPrompt.py (locale) drpython.py (drPopUp, operator) drSetupPreferences.py (os.path) drShortcutsFile.py (wx.stc) drSingleChoiceDialog.py (os, os.path, sys, keyword) drSourceBrowser.py (inspect) drSourceBrowserGoTo.py (string) drSTC.py (locale) drStyleDialog.py (drPreferences) drTabNanny.py (sys, getopt). drText.py (locale) drTreeDialog.py (drFileDialog) lnkDecoderRing.py (struct) (Submitted PyLint report, Thanks Rene Aguirre) Spelling Error in northstar.html (Bug-Report, Thanks Peter Mayne) Cleaned Up Menu Ampersands. Closes the clipboard if it is already open in drSTC.Paste Returns in drText.OnModified if it is a Dynamic DrScript. Patches to drFileDialog: in OnFileSelected (filename bug). tab order fix. initially selects listctrl entry extension fix. (Submitted Patches, Thanks Franz Steinhausler). Changes: You can now right click a selected item to activate it. (Submitted Patch, Thanks Matthew (Endless Cascade of Prawns)) Now displays the shortcuts for each command in the menu. (Bug-Report/Feature Request With Co-Fix, Thanks Franz Steinhausler) (Updated at startup). Added getmenulabel to DrFrame Added GetShortcutLabel to drShortcuts.drShortcut ******************************************************************************************************************************** For Version 3.9.4: Bugs Fixed: SourceBrowser GoTo: Properly shows lines when folded. Code Cleanup. Go To Block: Properly shows lines when folded. Prefs Dialog: Now uses a ListView instead of a ListBox. (Selection works properly on GTK2). UnComment now works with C/C++ (Bug-Report with Co-Fix, Thanks Franz Steinhaulser) Rewritten sizing code now calculates panel sizes, and corrects if they hide the document. Changes: Added drText.EnsureVisible (overrides default). (checks for folding first). Updated Plugin List. ******************************************************************************************************************************** For Version 3.9.3: Bugs Fixed: FileDialog: Fixed menu title in bookmark menu. Prompt: When running the python interpreter, properly syncs output before continuing. SingleChoiceDialog: Properly handles uppercase characters. Updated Documentation. Properly handles situations where the text control at the top has the focus. (Bug-Report, Thanks Franz Steinhaulser) Updated GetPluginsDirectory in the Documentation. Removed unused NewWindow method in DrFrame. Editing DrScripts now updates the recent file menu. Changed the second argument in OpenFile to OpenInNewTab. Prompt: Fixed encoding error. The prompt now prints encoding errors to standard output, instead of displaying them in the prompt. Removes duplicate commands from command history. if -> elif in OnKeyDown. Plugins Menu: setupmenu: Returns if "default.idx" does not exist. (Bug-Report with Co-Fix, Thanks Franz Steinhaulser) --preferencesbasepath (Bug-Report with Fix, Thanks Franz Steinhaulser) SourceBrowser docusetabs bug fixed. (Bug-Report with Fix, Thanks Franz Steinhaulser) ExecuteWithPython: Removes extra whitespace from the end of commands before running them. Changes: Plugins now have more control over keyboard shortcuts: If a plugin shortcut is found, it will be executed even if an alternative exists in the drpython core. A plugin shortcut can alo pre-empt handling in the prompt by returning 1 at the end of the called function. Documentation: Added a useful methods section to plugins.html, detailing a few useful DrFrame methods. OpenFile now handles recent files internally. Added constants to drSTC: drSTC.PYTHON_FILE = 0 drSTC.CPP_FILE = 1 drSTC.HTML_FILE = 2 drSTC.TEXT_FILE = 3 (Bug-Report/Feature Request, Thanks Peter Mayne) The Whinge Level for Tab Timmy is now perpetually '1'. (Set in drSTC). (Bug-Report/Feature Request, Thanks Franz Steinhaulser) Updated Plugin List. ******************************************************************************************************************************** For Version 3.9.2: Bugs Fixed: prefs.docusetabs bug fixed in OpenFile. Removed unused argument to drframe block. Properly handles no default.idx file (Bug-Report with Co-Fix, Thanks Franz Steinhausler) Edit Index Dialog bug fixed (Bug-Fix, Thanks Franz Steinhausler) PrefsDialog: Plugins Default Directory Fix. (Bug-Report With Fix, Thanks Franz Steinhausler) Removed unused about.html from documentation. Fixed title in dis files (Bug-Report, Thanks Peter Mayne) Changes: Source Browser Go To is now case insensitive. Added DrFrame.GetPreference() as an alternative method for retrieving a preference: eg: DrFrame.GetPreference('doctabwidth', 0) (Bug-Report/Feature Request with Co-Fix, Thanks Peter Mayne) Added Bookmark functions to the File Dialog: You can now add the current directory to bookmarks You can now file the current directory in a bookmark folder You can now edit bookmarks from the file dialog You can now set the base directory for preferences from the command line: '--preferencesbasedirectory=' (Bug-Report/Feature Request with Co-Fix, Thanks Franz Steinhausler) You can now set the String EOL style for Python/C++, and the Prompt. (Bug-Report/Feature Request, Thanks Franz Steinhausler) Added Peter Mayne's updated documentation files (credits.html, drpython.css, dis.html, drscript.html, gpl.html, help.html, plugins.html, preferences.html, thanks.html). Updated Documentation. ******************************************************************************************************************************** For Version 3.9.1: Bugs Fixed: Documentation error in plugins fixed. Style Dialog: Forgot to update the size array when selecting a style. HTML syntax highlighting: The squiggle is gone. (Bug-Report, Thanks Peter Mayne) (Bug-Fix, Thanks Franz Steinhausler) Context Sensitive Autoindent Only works with python files. Changes: SourceBrowser Go To: Dialog is a bit bigger. Added Line Number, Defined In text controls to the dialog. File Types: DrFrame.txtDocument.currentlanguage is now DrFrame.txtDocument.filetype The prompt now has its own eol and tabwidth prefs. For supported filetypes (Python, C/C++, HTML/XML, Text), you can now set: extensions tabwidth usetabs folding eolmode commentstring wordwrap (Bug-Report/Feature Request Thanks Franz Steinhausler and Peter Mayne) Updated Documentation. ******************************************************************************************************************************** For Version 3.9.0: Bugs Fixed: drPreferences.py: cleaned up GetPreferencesDictionary userhomedirectory now always points to '~'. cleaned up preferences directory code in InitializeConstants Now uses 'APPDATA' envornment variable first on windows machines and follows up with the program directory instead of c:/ or /. (Bug-Report, Thanks Peter Schott, theomurpse, Franz) uses 'rb' in drScriptMenu.py Properly checks for modification when open a plugin source file. Now sets the directory to default only if there are no command line arguments. Removed unused DrFrame.OnIdle. Go To Blocks: Properly ensures current line is visible if folding is enabled File Dialog: Clears the filename on delete. Cancelling "Save As" when closing an untitled document now behaves like "Cancel" instead of "No". Only removes extra spaces from the first line when pasting to a document using tabs if the text is being pasted at the beginning of the line. (If no non whitespace characters are found). Cleaned up line joing in shortcuts, pop up menu. You can now select odd numbers for font size in style dialogs. (Bug-Report, Thanks Franz Steinhausler) GoToTraceback in the Prompt now updates the recent file menu. Sets ddirectory to userhomedirectory if prefs.defaultdirectory does not exist. Changes: Preferences: no longer uses 'exec' in copy, reset, ReadPreferences, or WritePreferences. You can now optionally treat DrFrame.prefs as a dictionary. Style Arrays are now all stored as dictionaries. Variable Names Changed to reflect this. (PythonStyleArray is now PythonStyleDictionary) homedirectory is now userpreferencesdirectory. (homedirectory still exists for backwards compatibility). added GetPreferencesDirectory() to DrFrame. GetPluginDirectory() is now GetPluginsDirectory() (old version still exists for backwards compatibility). Added an icon to the status bar to indicate a program is running. Pop Up Menu and ToolBar dialogs are now a bit bigger. Icons for Document Tabs are higher contrast. (Bug-Report/Feature Request, Thanks Franz Steinhausler) Added DrFrame.Ask(question, title). Added drSingleChoiceDialog.py OpenImportedModule now uses drSingleChoiceDialog OpenImportedModule Properly saves window size (if prefs call for it). (Rewritten OpenImportedModuleDialog using ListView, you can now use keyboard navigation to scroll, etc.) Now simply finds the string, instead of autocomplete. Also made it a bit bigger. Added GetIndentationCharacter to DrSTC. Added Source Browser Go To Added to Shortcuts, the Pop Up Menu and Toolbar. Added SetupPreferences to General panel in Preferences Dialog: Ability to Import/Export: Preferences, Shortcuts, Pop Up Menu, Toolbar Plugins DrScripts All of the above at once. Updated Documentation. Find/Replace: Finder is now a member of drSTC. Added Find/Replace in the Prompt. Added drSTC.EnsurePositionIsVisible: (Makes sure the entire selection is visible). Now uses drSTC.EnsurePositionIsVisible instead of EnsureCaretVisible in Find. Remember Window Size and Position is no longer enabled by default. ******************************************************************************************************************************** For Version 3.8.5: Bugs Fixed: Removed unused thread import in drPrompt. Properly uses statustext in ExecutePython. ExecuteWithPython/ExecutePython code has been tuned up. Indentation Error in Set Args. drNotebook.py: Source Browser: operator is now imported (Bug-Report with Fix, Thanks Franz Steinhausler) View In Panel: DrText is now imported (Bug-Report with Fix, Thanks Franz Steinhausler) removed superfluous code in drToolBarFile.py You can now set arguments even if there is no file. Changes: Added GetActiveSTC to DrFrame. drPrompt now Overrides stc.AddText and stc.InsertText, to ensure text can always be added, even in read only mode. (drPrompt now directly calls wx.stc.StyledTextControl.AddText instead of self.AddText) Added ExecuteWithPython (to run a command with the python executable). Updated Plugin List. ******************************************************************************************************************************** For Version 3.8.4: Bugs Fixed: Minor fix in help.html (grammar). For Plugin Function Menus (Preferences, Help, About): Now loads plugin modules only once, and references them via an array when calling member functions. Open Imported Module now Refreshes the Recent File Menu drPreferences.py: Uses map and range to create a sequence of empty strings for cleaner code. In drPrefsFile.py: now gets all the evaltext together first, then compiles and executes it all at once in Read, Write Preferences. Syntax Check: Properly handles untitled files. Now shows results in a message dialog. (Bug-Report, Thanks Franz Steinhausler) Restores the active Document in SaveAll (Bug-Report With Fix, Thanks Franz Steinhausler) Displays an error message when the user tries to do a find previous with regex. (Bug-Report With Fix, Thanks Franz Steinhausler) Properly fixes file separators in drBookmarksDialog. (Bug-Report With Fix, Thanks Franz Steinhausler) Checks if plugin being edited is already open (Bug-Report With Fix, Thanks Franz Steinhausler) (Edited slightly by me). Changes: Moved drNotebook and related classes to their own file. Documents Menu: The Documents menu is alphabetically sorted. The range submenus now show the filenames instead of the document number. ******************************************************************************************************************************** For Version 3.8.3: Bugs Fixed: drGetBlockInfo: Properly treats strings. (That is, it now only ignores single line strings if they aren't the first part of the line). Updated Documentation. Fixed indentation in drRegularExpressionDialog OpenRecent uses x in y instead of try except. drPluginDialog: Close Button can now be used with ESC (Patch, Thanks Franz Steinhausler) Cleaned up uneeded close function, constants. Only Lists Plugins not in the current index. (Patch, Thanks Franz Steinhausler) drPluginMenu: No longer lists loaded plugins. (Patch, Thanks Franz Steinhausler) Properly Copies PyData when moving Folders in drTreeDialog. (Bug-Report, Thanks Franz Steinhausler) ******************************************************************************************************************************** For Version 3.8.2: Bugs Fixed: drGetBlockInfo: Properly handles implicitly joined lines with extra parenthesis after the initial line. Properly returns last valid line, instead of last line in file. Rewrote handling of explicit line joining. Properly removes triple quoted strings. Properly removes single line triple quoted strings. Sets STCFocus in GoToBlockStart, GoToBlockEnd. Now removes all comments. Now removes all strings. Removes explicit line joining first. Updated Documentation. Inserts '-i' argument in proper location when running the python interpreter by itself. Minor changes in sizing code: replaced map(lambda with map(local function Now checks for already open when opening an imported module. Changes: Added GetAlreadyOpen() to DrFrame. Added in Drag and Drop, OnOpen, OnOpenRecent ******************************************************************************************************************************** For Version 3.8.1: Bugs Fixed: Removed uneccessary argument in drGetGlockInfo Prefs Dialog is bigger, vertical scroolbars are longer. drTreeDialog: Sizer error fixed in drTreeDialog, drBookmarksDialog, drScriptDialog. Removed uneeded wxPython 2.4.x compatibility code in drTreeDialog Rewrote Drag and Drop moving code for drTreeDialog Sorting now uses a home brewed method, so as to work where wx.TreeCtrl.SortChildren Does not. Properly saves drscript menu changes. In OnOpen, removed needless try, except statement, replaced with x in y statement. except statement in SaveFile now catches all errors. returns on exception in SaveFile. except statement in OpenFile now catches all errors. Changes: drGetBlockInfo now handles implicitly joined lines. ******************************************************************************************************************************** For Version 3.8.0: Bugs Fixed: Restored cut out text in comments of drpython.py drTreeDialog: Removed wxPython 2.4.x compatibility code from bookmarks/drscript dialogs. BuildTreeFromString functions now take the same arguments. Fixed menu grouping in shortcuts. Runs OnModified after restoring from backup. Find Dialog: Restores focus to text control after using the pop up menu. Properly changes addstring, stc.SetUseTabs, drSTC.indentation type when switching the indentation type. (Bug-Report, Thanks Franz Steinhausler) Properly handles regular expression not found in Find/Replace Dialog. (Bug-Report with Fix, Thanks Franz Steinhausler) Removed superfluous code in OnCleanUpSpaces. SetToTabs and SetToSpaces now both take an unaltered tabwidth as an argument. Now removes properly extra spaces when Setting indentation to tabs. Title for Preferences page fixed. Now shows "search string not found" if occurances replaced == 0. (Bug-Report, Thanks Franz Steinhausler) Properly updates indentation type on undo/redo/delete text. Changes: Bookmarks, DrScript now use a single base class (drTreeDialog): Added Sort function to drTreeDialog. Edit DrScript Dialog now sorted. (Bug-Report/Feature Request, Thanks Franz Steinhausler) Added GoTo: Block Start/End Def Start/End Class Start/End Added to Shortcuts, Pop Up Menu, Toolbar Changed Default Shortcuts for GoTo Block Start/End, and Toggle Source Browser Updated Documentation Cleaned Up Shortcuts Documentation '-t' (warn on mixed indentation) is now a default python argument. New Plugin Functions: Added AddPluginOnNewFunction, to run code whenever "OnNew" is called, without overriding the function. Added AddPluginOnCloseFunction, runs code at the end of OnClose. Added AddPluginOnOpenFunction, runs code at the start or end of DrFrame.OpenFile Added AddPluginOnSaveFunction, runs code at the start or end of DrFrame.SaveFile (Help with how to implement the Functions in discussion: Bug-Report Feature Request with Co-Fix, Thanks Franz Steinhausler). Updated Documentation. Added Toggle Fold to Menu, Shortcuts, Pop Up, Toolbar (Bug-Report/Feature Request, Thanks Jon Schull) Check indentation on Open is now a preference. It behaves the same way as check line endings on open. (Bug-Report/Feature Request, Thanks Franz Steinhausler). Added optional extension restrictions for Check Syntax on Save (Bug-Report/Feature Request, Thanks Franz Steinhausler). ******************************************************************************************************************************** For Version 3.7.9: Bugs Fixed: Index error in OpenImportedModule fixed. (Bug-Report, Thanks Franz Steinhausler) Checks if drscript file is already open on edit. (Bug-Report, Thanks Franz Steinhausler) Changes: Drag and Drop, you now set the default drag action (cut or copy), and the other option can be executed by holding down control. (Bug-Report/Feature Request, Thanks Matthew Thornely) Updated Documentation. Updated Plugin List. ******************************************************************************************************************************** For Version 3.7.8: Bugs Fixed: Now shows what is producing the output, tabnanny or compile. Open Imported Module: No longer adds (or subtracts) empty entries. Parse function properly handles keywords such as 'as'. Properly handles from, ignores '*', allows from directories: eg from from wx.lib import dialogs will let you choose from wx.lib and wx.lib.dialogs. Only shows modules that exist. Updated Documentation. Paste from Edit Menu, Pop Up Menu now call drSTC.Paste Edit Menu: Copy, Cut, Paste, Delete now also work in Prompt. Changes: Rearranged options for Add in Bookmarks Dialog. Bookmarks, DrScript dialogs are bigger. Updated Documentation. ******************************************************************************************************************************** For Version 3.7.7: Bugs Fixed: Bugfix in drShortcuts (stc) (Bug-Report with Fix, Thanks Franz Steinhausler) SetToSpaces variable bug fixed. (Bug-Report with Fix, Thanks Franz Steinhausler) regex fix in OpenFile. (Bug-Report with Fix, Thanks Franz Steinhausler) eol fix in OpenFile. (Bug-Report with Fix, Thanks Franz Steinhausler) Removed code that replaces all 1's with 0's in Paste. Fixed bug where extra spaces are removed whenever SetToTabs is called. (*Spelling Error, Fixed for 3.8.0) (In Paste, and in Set Indentation to Tabs). Sets STC Focus in Document in OnNew. Plugin Menus (preferences, help, about) code cleanup: now derived from base class. Properly sorts plugin menus (preferences, help, about). (Bug-Report, Thanks Franz Steinhausler) Properly handles selected text in drSTC.Paste() Open Imported Module: Properly Removes duplicates. Removes empty entries. Properly handles commas. Changes: Added Check Syntax Feature. Checks for syntax, indentation errors. (uses compile, tabnanny). Added to the toolbar, shortcuts, pop up menu. Added to the default toolbar selection. Added Check Syntax on Save to Preferences. (Bug-Report/Feature Request, Thanks RunLevelZero) Updated Documentation. ******************************************************************************************************************************** For Version 3.7.6: Bugs Fixed: Properly handles mixed line endings (Bug-Report with Fix, Thanks Franz Steinhausler) Properly detects unix/mac line endings (Bug-Report with Fix, Thanks Franz Steinhausler) extra '/' in homedirectory fixed. (Bug-Report with Fix, Thanks Franz Steinhausler) removed locale error in drText removed superfluous import in drText shorcuts code cleaned up: stc is now found at the beginning of RunShortcuts Now formats for indentation on paste (incorporated from Franz Steinhausler's CopyCutPasteExtend Plugin, Version 1.0.7) STCCOMMANDLIST only stored once in DrFrame, instead of in each DrText instance. Changes: Added SetToTabs, SetToSpaces, to make messing around with indentation more modular. About Dialog now shows os info, wxPython info (Bug-Report/Feature Request, Thanks Franz Steinhausler) DrText and DrPrompt are now the proud children of DrStyledTextControl Plugin Menus: Preferences, Help, About now in alphabetical order. (Bug-Report/Feature Request, Thanks Franz Steinhausler) Updated Plugin List. ******************************************************************************************************************************** For Version 3.7.5: Bugs Fixed: File Dialog: Now properly handles .lnk files on windows lnkDecoder: Properly removes strings with invalid characters Properly shows EOL characters too if view whitespace is on by default. Sets up preferences for document, prompt, in OnNew. Removed old preferences from documentation. No longer resets whitespace when updating preferences. Changes: Grouped Line Endings with General in Preferences Dialog. Added View EOL with whitespace to prefs. (Bug-Report/Feature Request: Thanks RunLevelZero) Updated Documentation. ******************************************************************************************************************************** For Version 3.7.4: Bugs Fixed: Properly handles non ascii characters in the plugin list. lnk (and desktop) files properly reset the file combobox if they point to a directory. Updated Changelog 3.7.3 Changes: Added '>' to View In Panel menu items. Added support for KDE desktop entries. Updated Plugin List. Updated Credits (Donations). Refreshes Source Browser on Open, Close. ******************************************************************************************************************************** For Version 3.7.3: Bugs Fixed: Fixed update prefs bug in dr text regarding the addchar for autoindent. Default directory bug (general and plugins where switched in reset). Changes: Set Indentation to Tabs removes space indentation less than the tabwidth. Shortcuts now work in split view if it is a view of the current document. Changes to default directory when loading preferences. Updated Documentation. Updated Plugin List. Updated Credits, Donations (*Added in 3.7.4*). ******************************************************************************************************************************** For Version 3.7.2: Bugs Fixed: DrScript default directory bug fixed (Bug-Report, Thanks Franz Steinhausler) Minor Autoindent with spaces bug fixed. Updates statustext on set indentation. Changes: Added "Use File's Indentation" to preferences. On by default. Updated Documentation. Updated Plugin List. ******************************************************************************************************************************** For Version 3.7.1: Bugs Fixed: Constant Wildcard value saved in prefs dialog. Fixed filter parsing in file dialog. Selects the tab under the pop up menu to ensure the correct tab is referenced. (Bug-Report, Thanks Greg Smith). Bug Workaround: Assigned Shift + Backspace to "Delete Back Not Line". (Bug-Report, Thanks Greg Smith). Added a note to the Documentation. ******************************************************************************************************************************** For Version 3.7.0: Bugs Fixed: File Dialog: Index error in loop building wildcard array. Encoding: Error Opening Files with Swedish (Unicode) Text. (Bug-Report, Thanks Bo Jangeborg). Changes: Drag and Drop: Optional Drag and Drop Support for Text Thanks to Robin Dunn for the code (modified slightly/integrated by Dan). (Bug-Report/Feature Request, Matthew Thornely) Drag and Drop of Files now works in the prompt too. Preferences: Dialog: Removed Images from listbook. Removed extra bitmaps. Redid Listbook with a simple listbox, and sizing code. Now all Panels are based off of the PrefsPanel base class. Cleaned Up Code (Corrected Labels, etc). Removed Text Type from the Prompt Preferences Panel. Moved Styles to the Top of Preferences for All Panels. Moved File Dialog Settings to its own Panel. Added Drag and Drop to Preferences: Drag Files, Drop Files and Text Drag and Drop Files and Text Drag and Drop Files Only Cut on Drag Copy on Drag Added Auto Refresh on Save to Source Browser. File Dialog: Added a wildcard editor Added constant wildcard Added lnk replace table editor Now updates plugin list from the website, which automatically updates version numbers. Added lnk support for linux using replace strings. Replace strings use Regular Expressions. By Default, set to guess default linux setup (/mnt/win_x) where x is a lowercase drive letter. ******************************************************************************************************************************** For Version 3.6.12: Bugs Fixed: Mistyped the bugfix for the plugin index dialog (Bug-Report with Fix, Thanks Franz Steinhausler) Ditto for the Finder addition in OnClose (Bug-Report with Fix, Thanks Franz Steinhausler) Fixed SourceBrowser error handling triple quoted strings. SourceBrowser now handles single and double triple quoted strings. Changes: Updated Plugin List. ******************************************************************************************************************************** For Version 3.6.11: Bugs Fixed: Style Dialogs: Now look nice with wx 2.5.3.1 on Windows (Bug-Report, Thanks Franz Steinhausler), and on GTK2. GTK2: Redid events a bit so the color panel properly responds to the sliders. properly loads default directory (Bug-Report with Fix, Thanks Gregory Smith) No longer tries to autoreload files on drag and drop. (Bug-Report, Thanks Gregory Smith) Mixed Line ending in status text fixed. (Bug-Report, Thanks Gregory Smith) Properly moves plugins around in index file (Bug-Report with Fix, Thanks Franz Steinhausler) Properly copies Regex for Find/Replace between documents (Bug-Report with Fix, Thanks Franz Steinhausler) Retains Finder info when closing a document (Bug-Report with Fix, Thanks Franz Steinhausler) Plugin Install Wizard: Syncs pluginlabellist with list control in Run(). ******************************************************************************************************************************** For Version 3.6.10: Bugs Fixed: UnComment no longer adds an extra line. (Bug-Report, Thanks Matthew Thornley) Comment properly handles no selection. (Bug-Report, Thanks Franz Steinhausler). Properly saves default directory. (Bug-Report, Thanks Richard Townsend). Changes: File Dialog: Added support for windows shortcut files (*.lnk). (On Windows, Local Files Only). You can now change directories with the directory text control. Prompt only acts like a prompt if a program is running, otherwise acts like a text control. (Bug-Report/Feature Request, Thanks Matthew Thornley) Updated Plugin List. ******************************************************************************************************************************** For Version 3.6.9: Bugs Fixed: uncommented Bind: OnLeftDown context sensitive autoindent: compile regex's in __init__ works with win line endings. (Bug-Report, Thanks Matthew Thornley) Comment Region: now works with mac line endings. goes to the start of the commented region after commenting. Changes: You can now set the comment string in prefs. Updated UnComment. You can set the comment type: comment at the start of the line, or the word. comment at the start of the word does not comment blank lines. (Bug-Report/Feature Request, Thanks Matthew Thornley) Updated Documentation. Updated Plugin List. ******************************************************************************************************************************** For Version 3.6.8: Bugs Fixed: Only norms path if not http address (Bug-Report, Thanks Steve Holden) wx.FileDialog now has proper Save button, Overwrite prompt (Bug-Report with Co-Fix, Thanks Matthew Thornley) Properly quotes file argument in OnRun. Proper handling of extra arguments in OnRun. Handles non-existant files properly for program argument. drText Indentation properly handles (event is None), tabs->spaces, spaces->tabs, none. Prompt now also allows deselect with cursor. Drag and Drop Files: Sets document to 0 for first file if current is untitled. No longer sets modified untitled to -1. OpenFile only sets untitled number if not opening in a new tab. Removed read access code in OpenFile. Changes: Shows console command as first line in prompt (Bug-Report/Feature Request, Thanks Matthew Thornley) Added AutoWrap to Find/Replace preferences (Bug-Report/Feature Request, Thanks Matthew Thornley) ******************************************************************************************************************************** For Version 3.6.7: Bugs Fixed: (Credits Error Fixed, Changelog Too). EOL Mode is now only set during stc initialization for drText. print statement in soucre browser -> message dialog drText: Indentation detection error fixed Faster Indentation checking on delete/undo/redo. Sets untitled number after checking for read/access errors in open file. Changes: source browser: Focus is set in the document on activation (Bug-Report/Feature Request, Thanks Franz Steinhausler). Checks for read access in OpenFile ******************************************************************************************************************************** For Version 3.6.6: Bugs Fixed: OnFormat re's compiled at startup. setDocumentTo no longer resets eolmode. (This is the very unexpected result of a lot of debugging stemming from a seemingly unrelated bug report from Franz Steinhausler [Thanks!]). STC Shortcuts are now read properly even if a new shortcut has been added. Proper argument for OnPositionChanged in OnModified in drText. Faster Indentation Checking for statustext in drText (Only checks modified text. Checks full text on delete/undo/redo). Changes: Find and Complete Patch, now stops at '.', orders matches by proximity. (Thanks Martinho DOS SANTOS). Added Line Duplicate to stc shortcuts (Bug-Report/Feature Request with Co-Fix, Thanks Franz Steinhausler). (*Fixed 3.6.7*) Updated Plugin List Write Access Error Patch (Thanks, Franz Steinhausler). Added Rectangle Selecion to stc shortcuts (Bug-Report/Feature Request with Co-Fix, Thanks Franz Steinhausler). (*Fixed 3.6.7*) Added defaults for rectangle selection removed "home display extend", 'line end display extend' default shortcuts. ******************************************************************************************************************************** For Version 3.6.5: Bugs Fixed: Source Browser works again (Bug-Report With Fix, Thanks Franz Steinhausler). (And Bug-Report Richard Townsend). End of Document Reached dialog works again. re compile now takes place in drtext init instead of in check indentation. on position changed is not called from onModified during an event anymore. Changes: Submitted Patch Speed up indent/dedent region (Thanks Franz Steinhausler). Added identifier characters to indentation strings in statustext. Updated Documentation. ******************************************************************************************************************************** For Version 3.6.4: Bugs Fixed: No longer shows default.idx in Load From Index menu. Save All: Now shows a message dialog when there are no modified documents. Prefs Dialog: btnCancel -> btnClose Check Indentation now correctly handles mixed indentation that is not immediately preceeded by an end-of-line. (Bug-Report, Thanks Franz Steinhausler). Find: You can now use the ESC key to cancel the continue dialog. (Bug-Report/Feature Request, Thanks Franz Steinhausler). Changes: Added Help button to Preferences Dialog. Double Clicking a file entry in a traceback causes drpython to open the file at the line specified. (Bug-Report/Feature Request, Thanks Matthew Thornley). Check Indentation is now a member of DrText. Now uses Check Indentation in OnPositionChanged. ******************************************************************************************************************************** For Version 3.6.3: Bugs Fixed: OnClose: Only clears the document if it is the only one left. PluginDialog: Downloads now done one byte at a time. Download updating now occurs before total is incremented in loop. Update Plugin List Dialog: Removed the Done status text, and the close button. Automatically closes on successful completion. Select Plugin Dialog: Keyword is now default (windows) Properly processes enter (windows) Properly handles keyword search. Properly handles invalid ascii values in Plugin List. Updated Plugin List. wx.ShowMessage -> drScrolledMessageDialog.ShowMessage ******************************************************************************************************************************** For Version 3.6.2: Bugs Fixed: Correctly Unpacks Files from Zip (Bug-Report, Thanks Franz Steinhausler). Added Encoding support back into the core as a preference (Bug-Report, Thanks Bo Jangeborg) Also added back encoding support to the prompt (same preference). SavePrompt now uses correct file dialog. No longer maximizes when updating preferences. Changes: Encoding support is now a single preference. Updated Preferences Documentation. ******************************************************************************************************************************** For Version 3.6.1: Bugs Fixed: Fixed credits/changelog error from 3.6.0 Plugin Install Wizard: variable not defined error in local install (Bug-Report, Thanks Franz Steinhausler). Changes: You can now use the default wx.FileDialog instead of the DrPython Version. Added A Search Function to the Select Plugins Dialog. SaveFile now assumes it can make a backup by default. SaveFile now takes the document array index as the first argument. Being Prompted in OnSaveAll is now optional. Updated Preferences Documentation. ******************************************************************************************************************************** For Version 3.6.0: Bugs Fixed: Re Dialog: Insert Normal Text Indentation Fixed. File Dialog Bug Fixed (Bug-Report, Thanks Franz Steinhausler). Plugins: On Install, always handles default.idx does not exist. ScrolledMessage Dialog argument bug fixed. (Bug-Report with Fix, Thanks Franz Steinhausler). Properly sets eol mode in Open (Bug-Report with Fix, Thanks Dan Kruger). Default printing tabwidth is now 4. Correctly Handles Already Open File in OnOpen (Bug-Report, Thanks Franz Steinhausler). IsMaximized Bug Fixed. (Bug-Report With Fix, Thanks Franz Steinhausler). Open Imported Module: Handles Indented Import Statements (Bug-Report, Thanks Dan Kruger). Handles variables named "import" properly. Handles special case 'wx' properly (Bug-Report, Thanks Michael Stather). Handles any case where __init__.py is used to import a directory. SourceBrowser now handles triple quoted strings. (Bug-Report, Thanks Dan Kruger). Only shows recent files for Main Open Dialog. Windows homedirectory error. (Bug-Report With Fix, Thanks Dariusz Mikuiski). Properly handles default preferences in ReadPreferences. Properly handles urls in web browser. (Bug-Report, Thanks dataangel). Now remembers main window size and position in preferences. (Bug-Report/Feature Request, Thanks Michael Stather). Removed useless prompt.Show() code in panel sizing. Assert Error (Scintilla Editor.cxx Line 1825) Work Around. (Bug-Report, Thanks dataangel). Prefs Dialog: AutoIndent -> Auto Indent. Error if cursor moved near start or end of document in find next/previous chain. (Bug-Report, Thanks Franz Steinhausler). Search String Not Found now works properly for regular Find. patch to make bitmap directory handling cleaner. (Submitted Patch, Thanks Radoslaw Stachowiak) No longer runs find next, or find previous if there is no search string (Bug-Report, Thanks Franz Steinhausler). Removed superfluous variable in drPrompt. Code a bit more efficient in OnIdle in drPrompt. Changes: Plugins: plugins.dat -> default.idx Configure Plugins Dialog -> Configure Plugins Menu No Longer Loads Plugin on Install. Downloads updated list of plugins from sourceforge servers. New Install Wizard: Download Plugins From SourceForge Install From Zip Only Allows Install From Index if .idx file exists. New UnInstall Wizard: Removes Plugin from any Index Files it is referenced in. Removes the indexfile itself if it is empty. Optionally Removes Preferences and Shortcuts File for each Plugin. New Dialog for Editing Indexes. Added ShowMessage(parent, message, title) to drScrolledMessageDialog. Updated Files. Credits: Everyone is listed under Contributors. Also changed the colors a bit, and some of the text. Numbers for all Bug-Reports, etc. Added AutoReload. (Bug-Report/Feature Request with Co-Fix, Thanks Franz Steinhausler).(*Fixed*) View In Panel now goes to the current line in the target document. Find now stops at the Start/End of the Document, and promts to continue. Open Imported Module: Now Ctrl + m by default. Double Clicking now activates. Updated Shortcuts Documentation. Added drpython.ico to bitmaps directory. Added support for distutils (Submitted setup.py, manifest.in, Thanks Radoslaw Stachowiak) ******************************************************************************************************************************** For Version 3.5.9: Bugs Fixed: File Dialog: Now checks to see if file exists in file dialog. (Bug-Report, Thanks dataangel). Now checks for lnk files, warns the user. (Bug-Report, Thanks dataangel). Properly handles typed in files. Default shortcuts now work properly when there is no shortcuts file. DrScript Menu Editor Dialog was broken. Fixed. ******************************************************************************************************************************** For Version 3.5.8: Bugs Fixed: Non-STC shortcuts are disabled in View In Panel. Changes: Added View In Panel. You can view any open document in any side panel. Panels now have labels. Panels now have distinct background color. Panels now have close buttons. Removed Split View. Updated ToolBar Icons. Updated Documentation. ******************************************************************************************************************************** For Version 3.5.7: Bugs Fixed: Now sets horizontal scroll when creating a split view panel. Preferences Documentation: removed old preferences. Windows NT ToolBar Crash fixed. (Bug-Report with Co-Fix, Thanks gero). DrScript Dialog: Handles empty script file properly. Changes: Added the file dialog wildcard to prefs. Preferences Documentation: Added a table of contents. ******************************************************************************************************************************** For Version 3.5.6: Bugs Fixed: Panel selection bug fixed. Open Imported Module now searches the same directory as the current file first for matching modules. Replace Prompt On Selection Skip Bug Fixed (Bug-Report, Thanks Dan Kruger). Fixed documentation. (Fixed some minor spelling errors, accuracy errors in help.html). ******************************************************************************************************************************** For Version 3.5.5: Bugs Fixed: Select None residual code removed from drShortcuts.py (Bug-Report with Fix, Thanks Chris Wilson). Split sizes correctly again. Now resets STC shortcuts in Shortcuts Dialog. Fixed OnClose Error with targetPosition. Open Imported Module now removes duplicates. Now checks to see if custom toolbar file exists, and creates it if it does not when adding plugin icons. (Bug-Report, Thanks Greg Wilson). Removed undeeded code in OnCancel in drFileDialog. Changes: Open Imported Module: Sorts ModuleList New Dialog with Keyboard navigation. ******************************************************************************************************************************** For Version 3.5.4: Bugs Fixed: Removed unused sizertarget code. moved document creation, sizing to top of OnNew. Panels: Only calls OnSize code if the size has changed. (Calling with None overrides). Sourcebrowser crashed if set to atuomatically load: (Bug-Report with Fix, Thanks Chris Wilson). OnTextChnaged -> OnTextChanged: (Bug-Report, Thanks Chris Wilson). Added rectanglefind to reset in drFinder (Bug-Report, Thanks Franz Steinhausler). Off By One Error in Rectangle Find (Bug-Report, Thanks Franz Steinhausler). No more internal find error -> Now sets findpos to -1. Find Button not enabled when there is selected text. (Bug-Report with Fix, Thanks Chris Wilson). In OnSize, only calculates length once for all arrays. Changes: Added Open Imported Module (Bug-Report/Feature Request, Thanks Chris Wilson). Added ToolBar Icons for Open Imported Module. ******************************************************************************************************************************** For Version 3.5.3: Bugs Fixed: Properly updates tab icons OnClose. Selection is None bug in drFindReplaceDialog.py. Changes: Find/Replace in Rectangular Selection (Bug-Report/Feature Request, Thanks Franz Steinhausler). Added a relevant section to the docs. ******************************************************************************************************************************** For Version 3.5.2: Bugs Fixed: Now only refreshes side panels. Now calls OnModified automatically on load of first document. Rewritten code in setDocumentTo, OnNew Calls OnModified in OpenFile instead of OnPositionChanged. Now Only does OnSize code for Panels if the length of the Array for each Position is greater than 0. (ToolBar Sizing): Fix! Check on Linux! Now uses SetToolBar instead of adding to sizer, for correct ToolBar display (Bug-Report, Thanks Richard Townsend). Fixed credits (bur-report -> bug-report). Changes: Now shows active document via the bitrmap (Bug-Report/Feature Request, Thanks Franz Steinhausler). Modified icons for "modified, unmodified", added active variants. ******************************************************************************************************************************** For Version 3.5.1: Bugs Fixed: drPrefsDialog: wx.SHAPED -> wx.EXPAND to ensure proper text display. (Bug-Report with Fix, Thanks Franz Steinhausler). No longer messes with the title in a split view (Bug-Report, Thanks Franz Steinhausler). No longer takes Index as an argument for drSplitTextPanel. Changes: Rewritten Prefs code now uses regex to scan preferences file. ******************************************************************************************************************************** For Version 3.5.0: Bugs Fixed: OnSize in mdinotebook now Refreshes notebook (to make sure display is correct). Now calls to OnPositionChanged in OnFormat.* use None as the argument. Faster OpenFile: Removed useless ConvertEOLs call. For each line ending type: removed multiple eolist search with .count, replace with a single re search. File type re compiles now done on init instead of on open. Rewritten, faster horizontal scroll code. Removed superfluous statusbar code. Moved drScrolledMessageDialog import statement. Find/Replace no longer searches if the Search For Field is empty. (Bug-Report/Feature Request, Thanks Franz Steinhausler). drText: Searches for [Modified] instead of * When changing the document, sets modified document titles to [Modified] instead of '*' (Bug-Report, Thanks Franz Steinhausler). No longer erases text on indent, properly handles dedent, (Bug-Report, Co-Fix, Thanks Franz Steinhausler). Updated credits. Now Uses drFileDialog in DrScript Menu. DrScript Dialog now syncs the shortcuts file when saving. (Bug-Report, Thanks Franz Steinhausler). Shortcuts Dialog: Now only adds plugins to list if they export shortcuts (Bug-Report, Thanks Franz Steinhausler). Updated Icon for Toggle Prompt (16x16). PrefsDialog: "Icon size:" renamed "Toolbar Icon Size:" Changes: Prompt now takes up the entire bottom. Sizing Code: Now uses Move, SetSize instead of SetDefaultSize and Layout Sash Code now smaller, cleaner. SashDrag now only for center bottom, prompt top, panel sides. You now have to create a panel to resize it. Added Top, Bottom, now all side panels (Top, Bottom, Left, Right) and the center are in their own panel. Now uses a Sash Window instead of a SashLayout Window. Removed LeftIsVisible, RightIsVisible Code. Side Panels are now arrays, you can now have multiple panels on each side. 0 is now Left, 1 is now Right for Panel Position. Updated ShowSourceBrowser Code. No Longer needs AppendPanel, ClearPanel Functions. Added TogglePanel, ShowPanel, IsVisible Functions. drText: Moved regex compile to document creation to speed up indentation code in OnPositionChanged. Line Endings: Now uses regex instead of builtin ConvertEOLs. It is now much faster. Removed Encoding Code. drScrolledMessageDialog is now smaller. Replaced direct drScrolledMessageDialog statements with calls to DrFrame.ShowMessage in drpython.py Default Prompt Size is now 50. Preferences: Rewritten code now uses a dictionary to read, write, copy, and reset preferences. Added Position Chooser Widget for Selecting Panel Position. Added Split Horizontal, Split Vertical: Splits Text Horizontally, Vertically. Split Text Panels close automatically if they are sized to 0 using the Sash. Added to Shortcuts, Pop Up Menu, Toolbar Added Icons. Updated Documentation. Removed Select None (Same as Home). Added Top/Bottom Panel Size to Preferences. ******************************************************************************************************************************** For Version 3.4.9: Bugs Fixed: Now properly handles manually set sizes in style dialog. Save Customized ToolBar now works (Bug-Report, Thanks Richard Townsend). Find And Complete no longer runs if there is no word. ******************************************************************************************************************************** For Version 3.4.8: Bugs Fixed: Fixed changelog/credits error. Autoindent works correctly again (Bug-Report with Fix, Thanks Franz Steinhausler) Changes: You can now manually type in the size in the style dialog. (Bug-Report/Feature Request, Thanks Franz Steinhausler) ******************************************************************************************************************************** For Version 3.4.7: Bugs Fixed: Took out unneeded sash border at top of document. No longer autoindents after find and complete (Bug-Report, Thanks Franz Steinhausler) Updates status text properly again (Bug-Report with Fix, Thanks Franz Steinhausler) Now sets document to already open file instead of warning user. (Bug-Report with Fix, Franz Steinhausler) (*Fixed*) Normalizes filenames in drag and drop (Bug-Report with Fix, Thanks Franz Steinhausler) (*Fixed*) Clicking in selected text now clears the selection (Bug-Report/Feature Request, Richard Townsend). File Dialog: Normalizes path for txtDirectory (Bug-Report, Thanks Franz Steinhausler) Makes sure there is no duplicate slash after returning to root directory. (Bug-Report, Thanks Franz Steinhausler) Find no longer skips a match when switching direction (Bug-Report, Thanks Franz Steinhausler) Properly remembers selected panel in preferences dialog. ******************************************************************************************************************************** For Version 3.4.6: Bugs Fixed: Now loads default shortcuts correctly if there is no shortcuts file. Moved Bind Statements down in init function for drPanel. Fixed parenthesis matching code. Now always updates tabs (if update tabs is selected in preferences). Removed unused argument in bookmarks menu append in file dialog. notebook.top renamed to notebook.center. Changes: Moved folding above syntax highlighting in View Menu. Parenthesis Matching is now optional. ******************************************************************************************************************************** For Version 3.4.5: Bugs Fixed: Removed dependency version from comments. Style Dialog: Indent error in style dialog fixed. Behaves better on font error (Bug Report, Thanks Dan Uznanski). Sizing for color sliders fixed. Prefs Dialog ListBook Now aligned Left. FileDialog: Arrows point in the correct direction. Sorts modified time correctly. Sorts Down by default. ******************************************************************************************************************************** For Version 3.4.4: Bugs Fixed: Now sets to current document on save all (Bug-Report, Thanks Franz Steinhausler) Updates tabs modified status correctly. No longer toggles maximize on preferences. No longer destroys menu items, simply removes them (Fixes Segfault on GTK2). Updates Range on Find Next/Previous. (Bug-Report, Thanks Franz Steinhausler) Find Previous Bug fixed. (Bug-Report, Thanks Franz Steinhausler) ******************************************************************************************************************************** For Version 3.4.3: Bugs Fixed: Proper size for Prefs Dialog with GTK2. Apply Property to All Styles Now Works, applies to ALL Types. (Python, C++, HTML): Sets the normal text as default for each Type. On Font Error, displays font. Properly loads preferences again(Removed check for version number). Only updates tabs if changing modified status. Only calls OnPosition Changed from modified. Save All only saves modified files (Bug-Report, Thanks Franz Steinhausler) Drag and Drop filename error fixed (Bug-Report With Fix, Thanks Franz Steinhausler) If font is not in fontlist, try to guess lowercase, capitalized versions. Now uses users homedirectory if SetDirectory fails for file dialog. Now uses same icon for Toggle Prompt, prompt. ******************************************************************************************************************************** For Version 3.4.2: Bugs Fixed: File Dialog: Changed button order. Now uses homedirectory on load, if given directory does not exist. Removed outdated version number in prefsfile.py (no longer writes version number). Changes: Added 'Look In' Button to the File Dialog. (Bug-Report/Feature Request Tom De Muer). Added Save On Run to Preferences. (Bug-Report/Feature Request, Dominique Buenzli). ******************************************************************************************************************************** For Version 3.4.1: Bugs Fixed: Updates Documents Menu OnClose. Get Key Dialog now processes tab/enter events (Bug-Report with Fix, Thanks Christian Daven) Find Error Switching Documents (Bug-Report, Thanks Franz Steinhausler) Changed sizing to Fit() in Prefs Dialog. Minor credits spacing update. ******************************************************************************************************************************** For Version 3.4.0: Bugs Fixed: SourceBrowser now freezes interface/thaws during browse (Submitted Patch, Thanks Christian Daven) name error fixed in toolbar dialog. Sets Current Directory to Active Tab (Bug-Report/Feature Request Franz Steinhausler) Fixed Recent Files Bug (Bug-Report, Thanks Jean Luc Damnet). Minor internal switch from os.path.split to os.path.basename. Initialize Plugins Path at the start of the init function of DrFrame. Added Close All Documents, All Other Documents to Shortcuts. Fixed First, Last Document option in Pop Up Menu. Changes: New File Dialog: New Icons for Folders, Files, Commands Access to Bookmarks, Recent File Menu Back/Forward Buttons Delete File Button Information Menu now Help Menu New Icons For Bookmarks Dialog. File Modified State now indicated by an icon in tabs, '[modified]' in title. Added Save All Removed Window Width, Window Height from Prefs. Now Optionally Remembers Window Size, Dialog Sizes and Positions (For Main Dialogs). Plugins: Added Plugin Documentation to the Help Menu. Added Plugin Preferences to the Options Menu. Added Plugin About to the Help Menu. Moved Edit Bookmarks, Edit DrScript Menu to the Options Menu. Preferences Dialog now has a Listbook instead of a Notebook. Tabs -> Documents Moved Documents Menu to MenuBar. Now lists all Documents in the Documents Menu. Added Update Indentation to Prefs. Added Check Indentation Type to the Whitespace Menu. ******************************************************************************************************************************** For Version 3.3.7: Bugs Fixed: Indent/Dedent: Two Submitted Patches by Christian Daven Prompt was scroll happy. (Bug-Report Dominique Buenzli) ******************************************************************************************************************************** For Version 3.3.6: Bugs Fixed: Fixed Preferences Dialog Bug (Did not launch) (Thanks: Dominique Buenzli{Bug-Report} Jean Luc Damnet{Bug Report With Fix}) ******************************************************************************************************************************** For Version 3.3.5: Bugs Fixed: Removed arrow code from drText.py Icons: Removed Background on Linux for some icons. (Switched Black->White). Renamed Show Class Browser -> Toggle Source Browser Drag And Drop File now updates recent file list. ******************************************************************************************************************************** For Version 3.3.4: Bugs Fixed: Find: Properly updates position for RE find. Properly updates RE flag. No longer shows blank filename when closing a file. Changes: Scrolls to Current Line on Prompt Output. ******************************************************************************************************************************** For Version 3.3.3: Bugs Fixed: No longer warns on failed encoding (Bug-Report, thanks Jean Luc Damnet) PrefsDialog: Documentation: Correct Title for Doc Browse. No longer hides readonly files. (Bug-Report, thanks Dominique Buenzli and Ulf Wostner) ShortcutsDialog: Index error fixed. No longer loads commented out add * functions in plugins (Bug-Report, Thanks Franz Steinhausler) alphabetized shortcuts list. ******************************************************************************************************************************** For Version 3.3.2: Bugs Fixed: Shortcuts Dialog now handles plugin with no shortcuts correctly. Load Plugins From Index menu now only shows unloaded indexes (Bug-Report, Thanks Franz Steinhausler) Cleaned up ToolBar/Pop Up Menu dialog code. Shortcut Dialogs now only show plugin if the plugin has added functions (Bug-Report, Thanks Franz Steinhausler) In Prompt, Shortcuts did not handle direction keys correctly. (With help via bug-report, Thanks Franz Steinhausler) Nasty Close Error Fixed (Bug-Report, Thanks Franz Steinhausler)) ClassBrowser browse error when there is no text. Mac SashWindow Display Error (Document, Prompt, ClassBrowser did not display properly). (Huge Thanks to the Dogged Testing of Dominique Buenzli) Now uses AssignImageList, instead of SetImageList in Bookmarks Dialog. classbrowser: No longer highlights text on activate removed unused drSash class. RE error in Find now protected against. RE Find Next now wraps with a warning. Sourcebrowser now None instead of 0 by default. PluginDialog now sorts plugins/indexes alphabetically (Bug-Report, Thanks Franz Steinhausler) Find Dialog now has an empty string as the first entry in history to aid selection. First Tab, Last Tab now work correctly (With help via bug-report with fix, Thanks Franz Steinhausler). Changes: Speed Optimization in drText for Find (Thanks Franz Steinhausler) (also added to drPrompt). Added Tab Menu (Bug-Report/Feature Request, Franz Steinhausler) Updated Tab Pop Up Menu. Now uses icons in classbrowser. Uses regular expressions to parse for classbrowser, now much faster. ClassBrowser has been renamed sourcebrowser. SourceBrowser also checks for import statements. Updated Documentation. ******************************************************************************************************************************** For Version 3.3.1: Bugs Fixed: Shortcuts Dialog: Reset now updates selected shortcut. Properly handles new version of a plugin having extra shortcuts. Changes: Dialogs are now set automatically using SetSizerAndFit, so there is no need for extra code for different platforms. ******************************************************************************************************************************** For Version 3.3.0: Bugs Fixed: Now, if a keycode is not recognized for stc, it is run through drpython instead of through the stc. (Bug-Report, Thanks Franz Steinhausler) Statustext only changed (section 1) in one function. Check indentation has been rewritten. (*Spelling Update*) Fixed error message in classbrowser. Fixed Clean Up Indentation. Error in SetupToolBar is no longer fatal. Shortcuts dialog width 640. Removed print statements from Shortcuts Dialog. replaced themedefault with icondefault. Save on Close Prompt now include quotes, Untitled if filename is empty Save on Exit Prompt for each file when closing. (Bug-Report, thanks Franz Steinhausler) Start/End of Document dialog now shows find text. (Bug-Report, thanks Franz Steinhausler) Alphabetized Help. Find Next/Previous now wraps with a warning. Added note on Shell Commands to documentation. Changes: Reworked the Preferences Dialog Reworked the StyleDialog: Now two dialogs: drStyleDialog for Document and Prompt (multiple), drSimpleStyleDialog for other styles (single). StatusBar no longer displays menu help strings, also displays insert/overtype, indentation, divided into 2 visible sections instead of 3. ToolBar: Reworked the ToolBar Dialog. You can now add STC commands, Plugins, and DrScripts to the ToolBar. ToolBar Loading function is now faster, uses a single array isntead of building a dictionary. You can now specify icons for every item on the toolbar. Plugins: Added AddPluginToolBarFunction, and AddPluginFunction (which adds all three). You can now write a default Install script that will be automatically called by drpython on plugin install. You can now write an UnInstall method automatically called by drpython on plugin uninstall. Added AddPluginIcon, RemovePluginIcon, to facilitate setting default icons during install/uninstall. Removed Find/Replace in Files. (Removed Documentation too). Added GetFilename() to drText, returns "Untitled" or filename. Updated Documentation: Plugins, ToolBar, StatusBar Cleaned up indentation menu. Added GetPluginDirectory() to DrFrame. Now notes contributors in credits. Now shows untitled numbers. Changed default current line highlight color, default brace match colors. ******************************************************************************************************************************** For Version 3.2.5: Bugs Fixed: Drag and Drop variable error (Bug-Report With Fix, Thanks Franz Steinhausler) Combobox in Shortcuts/Pop Up Menu dialogs now readonly (Bug-Report With Fix, Thanks Franz Steinhausler) Fixed a small bug when initializing plugins (if there was an error with shortcuts). Error updating new plugin shortcuts (Bug-Report, Thanks Franz Steinhausler) No longer creates empty shortcut files for plugins with no shortcuts. Error writing/updating pluging shortcuts (shortcut name error) (Bug-Report, Thanks Franz Steinhausler) Changes: Now keeps user from loading the same plugin twice. ******************************************************************************************************************************** For Version 3.2.4: Bugs Fixed: Now sets stc shortcuts for all documents. (Bug-Report, Thanks Franz Steinhausler) Added to standard list in pop up menu dialog. (Bug-Report, Thanks Franz Steinhausler) Find All now sorts in ascending order. (Bug-Report, Thanks Franz Steinhausler) Cleanup up Drag and Drop code, added already open check. (Bug-Report, Thanks Franz Steinhausler) Bug-WorkAround for Assert Error on Linux. Toolbar repeated itself. (Bug-Report, Thanks Franz Steinhausler) Removed 2 unused constants. toolbar dialog: No longer moves items around on add/remove added to list. Plugin Shortcuts are now properly updated. updates STCUseDefault if neccessary on save in Shortcuts Dialog. Find Dialog: self.lastpos -> self.findpos Now handles find next, find previous correctly if you move the cursor. Changes: Franz added Configure Plugins, Customize Shortcuts, Pop Up Menu, and Toolbar to Shortcuts and the Pop Up Menu. Added above to the toolbar too. (And New Icons for Each). Changed the default colors for matched brace. ******************************************************************************************************************************** For Version 3.2.3: Bugs Fixed: DrPluginDialog error (did not remove shortcuts code from OnBoxClick). ShortcutsFile.py error, now UnComment, Toggle View Whitespace can be customized. Minor grammatical fix in drpython.py Did not load changed stc shortcuts (Bug-Report With Fix, Thanks Franz Steinhausler) Toolbar dialog error (Bug-Report, Thanks Franz Steinhausler) Shortcuts typo kept del word right from working (Bug-Report, Thanks Franz Steinhausler). Closed all open files when overwriting a plugin (Fixed). Updated Documentation. Changes: You can now update plugin shortcuts. ******************************************************************************************************************************** For Version 3.2.2: Bugs Fixed: Removed commented out code in drPopUp.py DrPopUpMenu now loads all pop up menu functions for each plugin, even if the plugin is not loaded. ShortcutsDialog now resets shortcut panel on list. You can now save STC Shortcuts. (Bug-Report, thanks Franz Steinhausler). Plugin Dialog: "Edit" Now "Edit Plugin" Update: Now updates prompt size. Now updates highlight current line. Changes: You can now set all shortcuts from the shortcuts dialog. ******************************************************************************************************************************** For Version 3.2.1: Bugs Fixed: Char Right Extend now works. ShortcutsFile bugfix (Bug-Report with Fix, Thanks Nathan Jones). /bin/env now /usr/bin/env (Bug-Report with Fix, Thanks Ulf Wostner). ******************************************************************************************************************************** For Version 3.2.0: Bugs Fixed: Still referenced themes for icon file browse. Major find next/previous bug fixed.(Bug-Report, Thanks Franz Steinhausler). unused import in drPopUpDialog. findtext is always highlighted. stopped writing version number in shortcuts. select none now implemented as home. Now handles insert character bug in findtextctrl (Bug-Report, Co-Fix, Thanks Franz Steinhausler). Fixed invalid text control in prefs dialog error handling (prompt, doc: txttabwidth -> txtmarginwidth). Only changes size if prefs for default size where changed. Synchronizes DrScript Shortcut Names on Rename. syntax error: AddPluginPopUpMenuFunction Fixed Reload bug (when file was modified). Find Previous End of Document -> Start of Document. Fixed find previous/next bug near start/end of document. Changes: Added "Under Cursor" to Find/Replace Options. Save now saves and updates: Preferences, Shortcuts, Toolbar, PopUpMenu Shortcuts Dialog: Rewritten, new interface Same basic interface as popup dialog. Shows Key in addition to Keycode. Shortcuts: You can now set all STC commands via shortcuts. PopUpMenu: You can now add all STC commands to the pop up menu. Preferences: Added Highlight Current Line (Code for highlighting submitted by Franz Steinhausler). Removed enable warnings (only used in find/replace in files, where the warning SHOULD exist). Added Caret Width (Bug-Report, Feature Request Franz Steinhausler). Changed default color for brace-no-match Added browse buttons to each item for Documentation. ******************************************************************************************************************************** For Version 3.1.5: Bugs Fixed: Re Dialog: Now uses re.escape when inserting normal text. Side Pane Preference now stored correctly. Cut out unused findtext, replacetext, findpos, findflags variables. Find Next/Previous: Skipped on Find Previous. Switching from Find Previous to Find Next messed up. Find Previous now finds first instance of find text. Shortcuts: No longer says shortcut already taken if shortcut is None. (Bug-Report, Thanks Franz Steinhausler). Now allows you to erase the shortcut for a given function. (Bug-Report, Thanks Franz Steinhausler). Scripts: Function Arguments proper in OnLeftUp. (Bug-Report, Thanks Franz Steinhausler). You can now rename script titles. (Bug-Report, Thanks Franz Steinhausler). RecentFile List now has consistent folder separators (Bug-Report, Thanks Franz Steinhausler). cleaned up OnOpen. ******************************************************************************************************************************** For Version 3.1.4: Bugs Fixed: Now checks for existance of .pyc file on plugin uninstall. python interpreter now launched unbuffered. cleaned up python launching code. no longer sorts history for Find. Find history now lists last item first. SetHistory for drFindTextCtrl now automatically clears history if there is any. Now removes duplicates when appending to history (reshuffling the item to the top of the list). Now checks to see if drpython is being imported before running (Bug-Report With Fix, Thanks Franz Steinhausler). in drpython.py (used my own fix for drpython.pyw). (Fixed Franz's name in Changelog For Version 3.1.3) Rewrote bits of runcommand, changed arguments to make it more efficient. spelling error fixed in plugins.html. Changes: DrFrame.Execute/ExecutePython: Added DrFrame.ExecutePython, which also has an optional command argument. Added optional statustext argument for. Added Plugin Note to Credits. ******************************************************************************************************************************** For Version 3.1.3: Bugs Fixed: Used Try/Except where if/else statement more appropriate in drShortcuts.py (Bug-Report with Fix, Thanks Franz Steinhausler) Scrolled Message Dialog now closes on by default. (Bug-Report/Feature Request Franz Steinhausler). Changes: Find/Replace: Uses ComboBox instead of Menu for History (Bug-Report/Feature Request Franz Steinhausler). Right Click Menu Accesible from a Button (Bug-Report/Feature Request Franz Steinhausler). Added History to InFiles Dialogs. ******************************************************************************************************************************** For Version 3.1.2: Bugs Fixed: Plugin Dialog: Overwrite Index File Bug Fixed. Shortcuts Dialog: MultipleChoiceDialog Error fixed. MultipleChoiceDialog size fixed on windows. Tells you the name of the shortcut if the key combination is already being used. Context Sensitive AutoIndent: Does not dedent if '\' is the last character on the line. PluginDialog: Now checks to see if the shortcut is already taken when adding a new shortcut. drScrolledMessageDialog: Now has position, size arguments. Cleaned Up Traceback Code. Changes: drScrolledMessageDialog: Now automatically displays a traceback if one occurs. Updated documentation. ******************************************************************************************************************************** For Version 3.1.1: Bugs Fixed: Handles removed DrScript on the PopUpMenu. Context Sensitive AutoIndent now uses regular expressions, and properly handles statements such as "return 1" Changes: Context Sensitive AutoIndent now handles "pass", "continue", and "raise". Updated Documentation. ******************************************************************************************************************************** For Version 3.1.0: Bugs Fixed: Drag And Drop Bug Fixed (Bug-Report, Thanks Franz Steinhausler) Documentation now encloses urls in quotes, prepends "file:///" for about, help (Bug-Report plus fix, Thanks Franz Steinhausler) Unused variable used for filename in WriteRecentFiles(bug-report, Franz Steinhaulser) Old pref hanging around in drGetKeyDialog (bug-report, Franz Steinhausler) 15 Codefixes in drpython.py, Thanks Franz Steinhalser! 1 Codefix in drPrompt.py, Thanks Franz Steinhalser 3 Codefixes in drText.py, Thanks Franz Steinhalser OpenFile: uses os.path.abspath to ensure an absolute filepath. Bookmarks: Dialog: OnLeftUp, uses correct icons for folders. Dialog: OnLeftUp, correctly handles drop into a folder. Now handles empty folder correctly Dialog: Now allows empty folders, and empty bookmarks to be written. Dialog: Handles user erasing folder character. sys was imported twice. DrScript: indentation error fixed with example script count. documentation reflects new namespace. documentation shows import statements. cleanup up function order in drpython.py, drScriptDialog.py Removed Sessions from Documentation. PopUp Code cleanup in drPrompt.py, drText.py Handles bad itrem on pop up menu. Shortcuts: extra keys no longer bound for copy, paste (Bug-Report With Fix, thanks Franz Steinhaulser) Added Cut, Copy, Paste, Delete to the Edit Menu (Bug-Report With Fix, thanks Franz Steinhaulser) Cleaned up DoBuiltin Code (uses ID instead of string). Now uses drFindTextCtrl in Find/Replace In Files. Filename in the tab incorrectly labelled as changed on open for plain text files. Changes: Updated Credits. Removed Shell Menu. Removed Shell Menu from Documentation. Removed Chop. Removed Chop from Documentation. DrScript: New Edit DrScript Menu Dialog You can now organize DrScripts Into Folders You can now add shell commands as DrScripts organized examples into folders. alphabetized lists for PopUp Menu/ToolBar dialogs optional context sensitive auto indent. New Scrolled Message Dialog: closes the dialog. replaced all wx.lib.dialogs.ScrolledMessageDialog with drScrolledMessageDialog.ScrolledMessageDialog. Pop Up Menu: No longer removes items currently in pop up menu from program list. You can now add DrScripts to the Pop Up Menu You can now add Plugin Functions to the Pop Up Menu Only adds the plugin to the menu if currently loaded (If you uninstall, it will still show up until you restart). Updated relevant documentation. Split "Edit" Menu into "Edit" and "Search" Menus. Added Find History to Find/Replace Dialog. ******************************************************************************************************************************** For Version 3.0.8: Bugs Fixed: EOL problem with Dynamic DrScript (Bug-report, Fix (edited), thanks Franz Steinhausler). Changelog, Comments: (francescoa -> Franz Steinhausler) Run W/Debugger Leftover bug: Toolbar (Bug-report, thanks Ronald Hollwarth). ClassBrowser problem with bad indentation fixed. (Refresh did not work properly self.mixed was not updated.) Changes: Reorganized Credits, categories and alphabetical order. ******************************************************************************************************************************** For Version 3.0.7: Bugs Fixed: DrSript examples updated to new wx namespace. classbrowser sorting bug fixed (bug-report with fix, thanks Franz Steinhausler). Changes: Updated Credits. ******************************************************************************************************************************** For Version 3.0.6: Bugs Fixed: ClassBrowser Visible By Default now works on file open. Cleaned up some find code in OnMenuFind. Changes: Added DrFrame.ShowClassBrowser function (shows classbrowser no matter what). ******************************************************************************************************************************** For Version 3.0.5: Bugs Fixed: ClassBrowser: Uses eol instead of "\n" for def for classbrowser. got rid of highlighting bug. Changes: ClassBrowser: If folding: uses EnsureVisible instead of unfolding everything. Only highlights keyword and definition, still searches for arguments. Show ClassBrowser -> Toggle ClassBrowser Added Visible By Default to Preferences. import statement no longer in function. Preferences: Visible on startup -> Visible By Default Updated Documentation. ******************************************************************************************************************************** For Version 3.0.4: Bugs Fixed: Class Browser: .ClassBrowser now a member of txtDocument (You can use the classbrowser on multiple files.) Close On Activate now works for panes. Prefs: Changed classbrowserpositon to classbrowser pane. Changes: Removed the class browser dialog. ******************************************************************************************************************************** For Version 3.0.3: Bugs Fixed: Homedirectory check (and os.mkdir if necessary) (bug-report, thanks Sean McKay). (*grammar update for version 3.0.0 changelog*) ******************************************************************************************************************************** For Version 3.0.2: Bugs Fixed: Handles no plugins directory. (bug-report, thanks Thomas Klinger). Handles no "plugins.dat" Changes: Plugins Dialog: Save -> Save Index Made plugins docs a bit clearer. ******************************************************************************************************************************** For Version 3.0.1: Bugs Fixed: Plugins: Properly handles situation where no shortcut exists. Properly determines if a plugin has shortcut support. GetKeyDialog: now has a clear button. properly handles empty strings. ******************************************************************************************************************************** For Version 3.0.0: Bugs Fixed: Bookmarks dialog wxTreeCtrl GetFirstChild Bug Squashed. Uses correct call for correct version of wxPython Bookmarks dialog wxTreeCtrl No Bookmarks Bug Squashed. Now defaults to root item when no item is selected if there are no other bookmarks. Help Dialog now non-modal (bug-report/feature request, thanks Keith Nash). C++/Html Style bug fixed (STC.SetEdgeColour) Replace Prompt Dialog has a rpoper frame in windows. Class Browser comments bug fixed. Speed Optimization/Code cleanup in DrPrefsDialog. Removed some superflusous code for word wrap on windows. Cleaned up code commented out during cvs changes. Fixed some workaround code. Fixed bug in OpenRecent. Minor optimization in drToolbarDialog.py, drPopUpMenuDialog.py Whitespace fix in drPrefsDialog.py Properly updates file list OnSaveAs. Fixed shortcuts bug in loop. removed pyc files from examples/DrScript directory Warning on RE compiling for Find/Replace in Files. Workaround for Tab Title bug. Fixed event type for shortcuts in main frame. Line Endings Detected Properly in linux. Line Endings Status now updated on set to default. If document has mixed indentation, class browser still warns the user, but now displays anyway using the user's default indentation type. Class Browser now properly detects indentation (rewritten using regular expressions). Class Browser now handles different kinds of line endings. Shortcuts Dialog only alerts the user if the same key binding is being used if the key binding not for the currently selected function. Toolbar and Menu are now updated from a single function. Cursor color bug fixed. Removed superfluous logfile code. Now refreshes tab siz on Save As. Find/Replace/Goto now makes sure folded lines are visible. (bug-report, thanks John Bell)(*grammar update*) Tab selection on close now works properly. Changes: Internal Changes: Switched to "wx" namespace. Removed drBoolean.py. Removed "readme.txt" Switched to Bind method for events. all menus are now members of DrFrame. The wx.STC bug work around for control characters has been removed. in wxPython 2.5.1.x, it is no longer needed. The filename is now part of txtDocument. use os.path.split instead of "".find for filename. txtDocumentsArray -> txtDocumentArray txtPromptsArray -> txtPromptArray Removed Loggers. Removed Startup File and psyco support. DrPython is now Only MDI. DrPython now uses a Sash Window instead of Sizers. Added File drag and drop support (submitted code by Slim Amamou) Added two side panes (left and right). Class Browser can now be a dialog/ left pane/ right pane. Updates Tab filename Removed window list. Plugins: All plugins listed in /plugins/plugins.dat are loaded. Added Configure Plugins Dialog Support for Index Files, to load groups of plugins. Default directory added to preferences. You can add a plugin to the pop up menu. You can set the shortcut, or let the user set shortcuts via the configure plugins dialog. OnPreferences, OnAbout, OnHelp let the plugin designer write preferences/about/help code, and launch it from DrPython. The user can directly edit plugins. View Whitespace now shows end of line characters. This no longer causes the display error it used to in wxPython 2.5.1.x Updated Documentation. Preferences Dialog: Added a wxChoiceBox for easier navigation. Preferences are now in alphabetical order. Remembers last panel Added Side Panes to Preferences. Now sets the directory to the directory currently selected on browse in the find/replace in files dialog. Default Directories Preferences point to the user's home directory, or to the appropriate directory in examples. Find/Replace Dialog: Added Pop Up Menu: Insert Special Characters, Cut, Copy, Paste, Delete, Clear Text. Removed Clear Buttons Changed button placement. Options are now persistent. Separate options persist for Find/Replace. Options are reset if Find/Replace Options are changed. Added Pop Up menu, Keybindings to Switcheroo Dialog. Dynamic DrScript: text is now persistent. dialog is bigger. Context Sensitive Find and Complete. Help, About Dialogs are now solely launched with the native web browser. GetKeyDialog now displays current shortcut for the selected function. Removed example files for Themes, preference files. Added functions for adding panels to the left or right pane whether or not something else is already there. Switcheroo now imported in the function. Components Removed, and Reimplemented as plugins: Python Debugger Support Sessions Documentation Bookmarks Themes AutoGotoOnTraceback Insert Traceback Switcheroo Autoindent now indents one extra level when following a ':' (Thanks, bug-report/feature request Vincent Foley-Bourgon) DrPython now handles multiple file arguments. ******************************************************************************************************************************** For Version 2.4.6: Bugs Fixed: Spelling error fixed in ChangeLog. limodou: saving doc.cstyle.verbatim lost '<' in drPrefsFile.py limodou: double &t in View menu limodou: when make a new finder, copy the old finder's value to it Incorporated patch (thanks John Bell) that makes textctrls larger for window width/height. Find and Complete (properly finds current word) (bug-report, thanks limodou). Find and Complete is now Case Sensitive. Find and Complete now grabs the whole word (bug-report, thanks limodou). Huge Open Error With Encoding Fixed. (bug-report, thanks John Bell). Find And Complete now uses correct re syntax (bug-report, thanks Chris Wilson, bug-fix, thanks limodou). European Keyboard Support Removed (bug-report with diagnostic test, thanks Pawel Dzierzanowski). Clean Up Spaces/Tabs now only affects indentation (bug-report, thanks limodou). Changes: limodou: when save a file prompt its filename in saving dialog limodou: switch document with copy previous finder to the current drpython: (persistant find across documents) Changed Credits Format ******************************************************************************************************************************** For Version 2.4.5: Bugs Fixed: (forgot to add the thanks!) Put the fixed help.html file in the correct directory. limodou: Saving each file's encoding in txtDocument.locale You can now resize the find/replace in files prompt dialog. Added Chop Beginning/End to ToolBar If the user allows for autodetection, updates syntax highlighting OnSaveAs. Changes: limodou: If defaultdirectory is empty, then use the last recent file's dir (drpython: only if no default is set in preferences) added pref for european keyboard, skips event when both control and alt are pressed. Find and Complete Updated Documentation ******************************************************************************************************************************** For Version 2.4.4: Bugs Fixed: Does not save properly due to bug in encoding code (Erased File!). Selection for Indent/Dedent, Coment/Uncomment now works properly (bug-report with fix, thanks Chris Wilson)(*added the thanks*) limodou fixed a minor error in help.html regarding the line ending for windows. ******************************************************************************************************************************** For Version 2.4.3: Bugs Fixed: Encoding (locale) stored in each txtDocument and txtPrompt instance. Changes: You can now select which matches to replace in a file (Double Clicking a match gives you the option of removing that match from the list of matches replaced in the given file.) limodou: Added auto detect utf-8 encoding. Updated Documentation Added Run Shell Command In Prompt to Shell Menu. ******************************************************************************************************************************** For Version 2.4.2: Bugs Fixed: Fixed error opening file with "" selected as encoding. Fixed problems undoing replace in files. Changes: Replace In Files: Added a dialog to show all matches in each file ******************************************************************************************************************************** For Version 2.4.1: Bugs Fixed: The default for encoding is now "" Fixed Shell error with and Encoding menu now only sets mode for writing files, and writing to prompt. limodou: Unicode can be run in two versions of wxPython(unicode or non-unicode) limodou: switch tab when tabbed file is plain text will correctly invoke highlightmenu.Check() function limodou drpython: edited GetText, SetText Functions, renamed, put in alphabetical order. Load prefs default encoding fix. ******************************************************************************************************************************** For Version 2.4.0: Bugs Fixed: Duplicate number for constant in drPrefsDialog.py Used Set Control Char Symbol. DrPython no longer gets tripped up by ascii characters under 32. superfluous code removed in updatePreferences() DrPython Icon File (.dif) is now DrPython Icon Set (.dis) Remove superfluous code in drScriptDialog.py Caught possible exception in OnCloseW with windowlist Now runs with wxPython 2.5.1.5 (Subject to Implementation Limitations in 2.5.1.5: Check the website for more information) "fixed" is now the default font for the prompt in linux. Removed superfluous code in drShortcutsFile.py Fixed indentation problems with DrScript shortcuts in drShortcuts.py DrScript Shortcuts were broken (did not load properly), now fixed. Reworked the loop that evaluates keyboard shortcuts in drShortcuts.py Updates DrScript Examples when this option is selected in Preferences. Properly handles built in shortcuts in Dynamic DrScript Dialog. Find In Files now handles already open files correctly when selected. Find In Selection now uses the whole document if there is no selection. Properly Supports use of spaces for indentation with the class browser, thanks to Chris Wilson for the bug-report. Properly saves preferences with wxPython 2.5.1.5 Handles New Script filename correctly. Documentation Bookmarks Menu Fixed (Dialog Launch Error during "Edit Bookmarks"). limodou: Fixed reference bug in drToolBar.py Changes: Support for Syntax Highlighting for C/C++, HTML, Plain Text Added. You can save style preferences for each file type. Added C/C++ HTML types to wildcard for file dialog. Autodetects syntax highlighting by extension (option to turn this off in preferences). Shell Menu Added. Runs shell commands in the prompt. You can attach keyboard shortcuts to shell menu items. Added to Prefs Added Austin Acton to Credits (Mandrake Packages). Unicode/Locale Encoding Support (Thanks to limodou for the submissions) Added to Edit Menu. Encodes text sent to a process from the prompt. Added to Prefs Added Chop Updated Documentation ******************************************************************************************************************************** For Version 2.3.5: Bugs Fixed: Updated Credits. Fixed an SDI error opening recent files. (Bug report, thanks Ivar Marohombsar). Fixed DrScript documentation. Updated documentation to reflect drpython.lin changes made in 2.2.0 Changes: New Default Font (Lucida) for Document and Prompt on non windows systems. ******************************************************************************************************************************** For Version 2.3.4: Bugs Fixed: Errors with running programs (bug report, thanks Bo Jangeborg)(*Name Added for 2.3.5*). (inputstream/errorstream errors due to bad indentation). Did not open files correctly in SDI mode. Now gives txtDocument focus (or txtPrompt if only the prompt is visible) when updating prefs. ******************************************************************************************************************************** For Version 2.3.3: Bugs Fixed: Dynamic DrScript was broken: Now fixed. Recent Files Bug Fixed (Bug Report, Thanks Stephen Anderson) Fixed spacing in drpython.py Session:Folding State Bug Fixed (Bug Report, Thanks Stephen Anderson) Overrode builtin wxStyledTextControl.SetText for prompt. Changes: Added DrFrame.ShowPrompt() updated Print End Of Line Characters In Prompt DrScript. ******************************************************************************************************************************** For Version 2.3.2: Bugs Fixed: Removed extra .xvpics directory created by the gimp (smaller download). Prefs: with find/replace in files did not properly save prefs. Find/Replace in Files only worked if promot on replace was enabled. Changes: Reworked DrScript, made variable names more consistant, vastly simpler. Updated Docs ******************************************************************************************************************************** For Version 2.3.1: Bugs Fixed: Cancel Buton in Find/Replace In Files Dialog closed the entire Program! ******************************************************************************************************************************** For Version 2.3.0: Bugs Fixed: Dedent did not work properly with mac file format. Autotraceback with badfilename caught. Removed some superfluous code. Now automatically checks for inconsistant line endings in files on open. (Bug Report, Thanks Stephen Anderson) Now lets you select any line ending mode when the line endings are mixed. Indent/Dedent now support spaces as well as tabs. Autobackup now works. Now defaults for win/mac line endings work properly. (Bug Report, Thanks Stephen Anderson) Actually two bugs, one in OpenFile, one in drText. In an abstract sense, it is one bug. So also: (Bug Report With Fix, Thanks Stephen Anderson) Typos in drFindReplaceDialog.py variabgle names fixed. If there is a parse error finding the filename for autotraceback, DrPython now aborts the traceback. Did not behave correctly opening a file in bookmarks in mdi mode. Updates Save state status in title properly when switching to and from mdi mode. Bug work around with multiple files and prompt is visible status. Updated dialog language in pop up menu dialog feedback. Properly closes file when there is only one file open in mdi mode. Remove startup script now behaves correctly, does not try to close the current file unless that file is the startup script file. Now Properly keeps view whitespace setting for each open tab in mdi mode. Cleaned up pop up menu dialog code, it was going through an unnecessary loop on update. Properly updates arguments array during Set Program Arguments. Updated the example scripts for Run in Terminal. Minor bug removing "" in Pop Up and ToolBar dialogs. Changed the way Items are removed from the ToolBar. DrScript: Prompt_Text and Prompt_Selection Now work properly. Regular Expression Dialog: Insert Normal Text Now works properly (Backslash bug fixed). Made Character -> Character (Single Quoted String) in Prefs (Thanks Ruben Baumann). Made prefs style text a little clearer in general. Reset panel now works for general: recent files limit. SetupPrefsFile -> SetupPrefsDocument DrScript: Fixed Switcheroo in Selection. Now decrements the current tab position on close. Changes: Added psyco support to the startup script. Updated Docs Moved "File Format" Menu to new "Whitespace" Menu in "Edit", renamed it "Line Endings" Changed prefs to reflect this. Updated Docs Reflects line endings in the status bar. Changed Docs, Doc Bookmarks to Reflect wxWindows -> wxWidgets Name Change. Changed Shortcuts, PopUp command lists to reflect this. Line Endings now reflected in the status bar. Mix is used if the file is mixed. Line Endings Menu no longer uses radio menu items. Default tabwidth is now 4. DrPython now keeps track of all open windows. Find In Files Support Added. Double Clicking a File opens the file in DrPython, then performs the find operation on that file. Replace in Files Added. Only Supports RE Operations. Allows the User to Undo Replace In Files. Allows user to choose whether or not to be prompted on each file. Double Clicking a File opens the file in DrPython, then performs the find operation on that file. If a Replace Operation has taken place, and no undo has occured, then the matched file will perform a find operation on the "Replace With" text. Added Customize ToolBar Dialog Changed ToolBar file method. You can now specifiy a defualt Icon ("") in your icon file/theme. Replace In Files/Find In Files added to Pop Up Menu Selection. Sessions: Added Quick Save Session Added Load Session Sessions Save: Open Files, And for Each File: Program Arguments, Folding State if folding is enabled. Recent Sessions List DrScript: Prompt_Text and Prompt_Selection automatically toggle the prompt visible when used as returns. Added Print End Of Line Characters In Prompt example script. Vastly Simplified DrScripts in General. Now Checks to see if a file is already open. Default Iconsize is now 24. Added Dynamic DrScript: Run Python Code in the current DrPython process. Added Sessions, Replace In Files to Preferences. Reworked Shortcuts Code. Nowadding new shortcuts will be MUCH easier for future versions. Updated Documentation for Preferences, Find/Replace in Files, and Sessions Added Check Indentation: Checks to see if the current file has indentation, and if so, does it use tabs, spaces, or both? Auto checks indentation when displaying the class browser. Updated Documentation for Indentation. ******************************************************************************************************************************** For Version 2.2.9: Bugs Fixed: Nasty filename error editing startup script. DrScript messed up with Document, changed Document to Document_Control. (Noted in Documentation). Updated DrScripts as neccessary. ******************************************************************************************************************************** For Version 2.2.8: Bugs Fixed: Fixed a variable bug loading default shortcuts (Thanks Stephen Anderson for the bug report). ******************************************************************************************************************************** For Version 2.2.7: Bugs Fixed: Removed superfluous code in drpython.py, several dialogs. programdirectory and homedirectory now consistent in use of path separators at the end. Pop Up Menu works in prompt again. Localized Variables in all files. Prompt on Replace for Regular Expression Operation has been fixed. Prompt on Replace now properly keeps new position even when the user skips a replace operation. minor changelog aesthetic fix. Replaced txtFile with txtDocument in all files for consistency. Selecting the tab with keyboard shortcuts now properly changes tabs. Changes: Updated Documentation Speeded Up the Shortcuts Dialog, made the code cleaner. Use of wxYield to make dialog opening cleaner. ******************************************************************************************************************************** For Version 2.2.6: Bugs Fixed: Pop Up Menu Dialog works again. ******************************************************************************************************************************** For Version 2.2.5: Bugs Fixed: Correct Size for Customize Pop Up Menu Dialog on windows. No longer has superfluous slash when editing example scripts. Auto Goto For Traceback no longer switched on by default. Now updates current directory on save prompt. Custom Pop Up Menu now works on all open tabs in MDI mode. Changes: Updated Credits Added insert traceback to the "Edit" menu. ******************************************************************************************************************************** For Version 2.2.4: Bugs Fixed: Now properly sets tab text on Save As in mdi mode. Now finds most recent file in autogoto for traceback. Changes: Auto Goto For Traceback now works opens files if they are not currently open. (Only for MDI mode. In SDI mode, opens files in a new window regardless.) (Updated Documentation, Credits)*->This was added in after the fact. I forgot to add it when I initially released. ******************************************************************************************************************************** For Version 2.2.3: Bugs Fixed: Load Themes Bug Fixed. (self -> self.parent when copying old prefs) Sets tab title correctly on restore from backup classbrowser now correctly adds classes/definitions that span more than one line. Does not try to backup a file on save as. (Will still back up if the save as operation saves the file with the same path/name as before.) PromptIsVisible variable now set correctly on Open. Fixed bug in toggle prompt when there is no toolbar. Changes: Now keeps focus in Prompt or in Document when switching tabs. Added a right click menu to the tabs in mdi mode. You can now customize the right-click pop-up menu for DrPython. Now reports Line, Column instead of raw position in Replace. ******************************************************************************************************************************** For Version 2.2.2: Bugs Fixed: Defaults now set for tab traversal. MDI mode now checks all currently open tabs to see if any need to be saved on close. DrPython no longer empties the undo buffer after each save. Now properly adds filename, logfilename to their respective arrays on open when not in a new window. Autoupdate for classbrowser now functions correctly. Changes: Move Scripts is now "Rename | Move Scripts". You can now rename scripts. Added Close Tabs Menu: Close All Tabs Close All Other Tabs ******************************************************************************************************************************** For Version 2.2.1: Bugs Fixed: Removed Superfluous Slash when loading Example Scripts. Remove Script Now Works Properly When Example Scripts are enabled. Now handles an empty shortcuts file. Now sets ignore Meta on linux systems as the default for shortcuts. Changes: Autodetect now checks to see if DrPython Version is at least the last version a change was made. ******************************************************************************************************************************** For Version 2.2.0: Bugs Fixed: Needlessly references GetParent() in drText.py Changed "Cdric" to "Cedric" to ensure compatibility with python's encoding standard. (In drThemeMenu.py) (*Non Ascii Character removed, drpython 3.10.0*) Removed some superfluous code in drpython.py Fixed focus bug, bad variable bug: You can now insert a Regular Expression into the prompt. ClassBrowser now automatically refreshes whenever it regains the focus. Version number now correct in drpython.py comments. OnModified in Prompt now works, set to self rather than parent. Added Quotes to strings in the Reporting of the Number of Replace Operations. Changed Sizing for Switcheroo Dialog on Windows. Made RE dialog clearer, removed status bar. Moved Save Title Change to SaveFile, so it is no longer set on an error. Reload no longer affects recent file menu, and now correctly sets the save state notification in the title. Properly sets the Prefs Dialog prefs viariable after each update. Fixed brace matching code in drText.py updated dependencies notation in comments in drpython.py updated readme.txt removed some superfluous code in drScriptMenu.py Insert N Repetitions in RE no longer checks for an integer value (you can now type "9,15" for example). Autoscroll in prompt removed. Now Sets End Of Line Mode correctly for prompt. Changes: Added toolbar to the sizer rather than directly to the frame. I could then clean up the update prefs code. Replaced .GetParent() with .parent in drPrompt.py, drText.py Moved Some process Handling Code to drPrompt.py from drpython.py (OnIdle, self.process, self.pid, self.writeposition, self.editposition) Added Optional MDI mode to Prefs. MDI mode supports opening multiple files, with a prompt/process for each file. Changed menu items which launch dialogs to read "original text" + "..." Now keeps track of line number, column in status bar. Buttons in dialogs no longer expand when you maximize. Reworked interface a wee bit for drShortcutsDialog. Changed function call to variable for prompt output pipe, speeding up the prompt a bit. Added Save Prompt Output to File. drpython.lin now works from any directory. Changed DrScript Variables, text-> Document_Text, selection-> Document_Selection, frame-> Frame. Added: Document, Prompt, Prompt_Text, Prompt_Selection, Filename. Added traceback to DrScript error dialogs. Added Prompt on Replace to Regular Expression Replace. Clear Button Now Sets the focus to the corresponding text control. Added Find Previous. (Does not work for Regular Expression Searches. Added the ability to enable or disable feedback messages, and warnings to prefs. DrPython now optionally backs up your files each time you save. Added Restore From Backup to File Menu. Added backup files to wildcard. Added optional Always prompt on exit to prefs. Added GetEndOfLineCharacter() to both drPrompt.py and drText.py for use in DrScript. Changed Run In Terminal Example Scripts So they behave like Run in DrPython: You set the arguments, and they remain each time you call run in terminal. Created a wxObject calls "DrScript" (attached to "Frame"). You can either include it directly, or via Frame. The object provides a separate namespace for DrScript variables the user wants to persist for the run of the main program. Added function .VariableExists("variablename") to DrScript. Returns True if "variablename" is a member of DrScript. Added "Load Example Scripts" to Prefs under "DrScript" User can now move DrScripts around. Added Auto Goto for Traceback in prompt(added to prefs): If enabled, if a traceback is found when the program exits, DPython automatically scrolls to the last line cited in the traceback (only when running a file) Currently only works on the current file. Switcheroo Default is now Ctrl-Alt-S Find Again is now Find Next Added Save Prompt Output To File, Restore From Backup, Next Tab, Previous Tab, First Tab, Last Tab, Find Previous, Insert Regular Expression, Set Log File, Insert Logger, Insert String Logger, Insert Arbitrary Arguments Logger, Remove All Loggers, Preferences, Help, Python Docs, WxWindows Docs, Regular Expression Howto to Shortcuts. Shortcuts now automatically detects and (if necessary) updates user's shortcuts file. ******************************************************************************************************************************** For Version 2.1.9: Bugs Fixed: Did not properly load themes. Thanks Cédric Delfosse. Reset Panel now works for printing. Preferences Dialog Now Behaves Correctly, and on launch reflects current preferences, and only updates drpython preferences on explicit request. Reworked Reset Just This Panel Code, made it cleaner. Changes: Defaults for Find/Replace Changed: From Cursor no longer default. Added Scroll Extra Page to Preferences for Document and Prompt. Added Use Tabs Option to Prompt. Updated Documentation. ******************************************************************************************************************************** For Version 2.1.8: Bugs Fixed: Properly saves preference for default option in find/replace dialog: Regular Expression Changes: Added Match: Start/End of document, Word Boundary, and Not Word Boundary to RE Dialog. Also added: A Set of Characters, Positive, Negative Lookbehind assertions. ******************************************************************************************************************************** For Version 2.1.7: Bugs Fixed: Correct Version Number. Changes: Added Or, Group, Positive, Negative Lookahead Assertions to RE Dialog. Also added any decimal (not decimal) whitespace (not whitespace) alphanumeric (not alphanumeric). Added '|' check to insert normal text. ******************************************************************************************************************************** For Version 2.1.6: Bugs Fixed: Fixed an absentminded error in Bookmarks. ******************************************************************************************************************************** For Version 2.1.5: Bugs Fixed: Fixed Remove for DrScript Remove, Edit for DrScript and DrLogger now handles an empty list No longer says your bookmarks file is messed up when it doesn't exist. Changes: Added Custom Bookmarks to Information Menu. ******************************************************************************************************************************** For Version 2.1.4: Bugs Fixed: Bookmarks: Drag and Drop Move Now supports wxArt. Classbrowser now works properly if you use spaces instead of tabs In Prefs Dialog: "Margin Width" now reads "Line Number Margin Width" in prompt as well in as document. Changes: Updated Documentation Added wxYield() at appropriate points. Added Arbitrary Logger Added DrLogger Menu, with custom loggers. Reworked Logger code. Added Ensure Caret Visible, so txtFile scrolls somewhat in the direction of text if it is off the screen. ******************************************************************************************************************************** For Version 2.1.3: Bugs Fixed: Removed superfluous code in drRegularExpressionDialog.py Save/Save As now leave the window title alone if no save occurs. Fixed bug with clean up indentation, now works fine. Changes: (Updated Documentation)*->This was added in after the fact. I forgot to add it when I initially released. User can now save blank files. Added wxArt to bookmarks dialog. Added browse button to documentation preferences for setting the browser. Moved Cean Up Indentation to "Edit->Indentation" Moved Go To to "View" Added some menu separators to "Options", "Information" Made the line width code faster in OnOpen Only allows "In Selection" if there is selected text. Added Busy Cursors to File Open, Line Ending Format, Folding, Clean Up Tabs Removed depdendence on win32all on windows, use wxProcess_Kill instead. ******************************************************************************************************************************** For Version 2.1.2: Bugs Fixed: Now properly sets End Of Line Mode to Default on File Open. Fixed bug in insert Regular Expression. Flags Set Correctly for Switcheroo. Fixed bug in class browser, now handles lines joined with a backslash. Fixed autoscoll in prompt so it only autoscrolls once after all output has been piped. Changes: Changed "Help" Menu to "Information" Menu Added "View Help With Browser" to "Documentation" in Prefs. Added "Reset Panel" to each panel in Prefs. Changed "Reset" to "Reset All" Added Clear Buttons to Find/Replace. Cleaned up update code in drPrefsDialog. Changed "Print" panel to "Printing" panel. Added All Find/Replace/Switcheroo options to Preferences User can set defaults. (Added Regular Expression HowTo to Information Menu, Preferences)* -> "Custom Item" Removed. Oops, never actually made this change Changed Scrolling/Size for drPrefsDialog Redid Switcheroo with sizers Switcheroo is no longer modal Disabled Find Backwards for Replace Dialog Setting use tabs to False in preferences will tell the document to insert spaces instead of tabs when the user hits the tab key. Added Indentation Guides to Document/Preferences. Uses "Normal" for foreground/background. ******************************************************************************************************************************** For Version 2.1.1: Bugs Fixed: Proper default for documentation browser on windows. Cancel button now works in drRegularExpressionDialog. In RE Search:Find Next, start from the end of the last RE, rather than the start of the last RE + 1. RE Dialog size set correctly in windows. Added Code to Load/Save Regular Expressions. Changes: Added Insert n Repetitions to RE Dialog Changed RE Dialog to a wxFrame, changed from a button interface to a menu interface. ******************************************************************************************************************************** For Version 2.1.0: Bugs Fixed: Printing now prints spaces correctly. Default tabwidth for printing and general are now the same (8). Printing now prints strings preceded by an ampersand (" ", "<", etc) correctly. Made "***" lines consistent in Changelog. Removed superfluous code in updatePrefs Moved import os to the import statements used before setting the home directory. Removed some superfluous html in help.html Save State Now updates correctly: Fixed bug in drText.py Updating preferences: word wrap (prompt and document) now handles update of line numbers. OpenFile now handles update of line numbers if word wrap is in effect. Prompt On Replace Code now uses quotes. Cleaned up OnGoTo Code. Fixed Find Code, now properly increments for find next, sets proper value for initial find. Replace now properly keeps track of number of replacements if prompt on replace is in effect. Changes: Now loads Bookmarks Dialog, About, Help, Preferences, Customize Shortcuts, and the ClassBrowser on first use rather than on program load. Added Python, WxWindows documentation to preferences, Help. Rearranged Help menu a little. ToolBar can now be removed during runtime. Wordwrap now default for prompt. Added Use Styles to Prompt and Document. Now, you can use styles, use only normal and caret foreground, or not use styling at all. Added Loggers: Write Linenumber, and (optionally) a string to a log file (the current file + ".log" by default) at locations specified by the user. Prompt now autoscrolls on output (once output is finished.) Prompt On Replace Dialog now stays wherever the user moves it to the next time it pops up during a replace operation. Added Regular Expression Support to Find, Replace. Added A Basic Regular Expression Dialog To Find,Replace, Edit Menu. Updated Documentation ******************************************************************************************************************************** For Version 2.0.7: Bugs Fixed: Printing without line numbers now works properly. Fixed bug after clear recent file list in DestroyRecentFileList called from OnOpen. ******************************************************************************************************************************** For Version 2.0.6: Bugs Fixed: Fixed Documentation: help.html: spelling error all html: made "Back To" links work properly. Updated Credits, gave credit to Mike Foord for his bug report/feature request and his fix. (Oops. He wanted the tabs->spaces change, and noted that the tabsize for cleanup tabs was hard-coded (a bug, fixed in 2.0.3). Only Adds DrScript to Customize Shortcuts if there are DrScripts loaded. Changes: Added "Support" to help.html ******************************************************************************************************************************** For Version 2.0.5: Bugs Fixed: Made sure all Modal Dialogs are destroyed after they are closed. Shortcuts can now only be set through the "GetKey" dialog. event.Skip() for Shortcuts now works properly. Printing works again. (Oops. Accidentally Commented Out.) Changed Zoom Shortcuts to Number Pad. Removed Psyco support. Changes: Added Shortcut Support for DrScript Updated Documentation ******************************************************************************************************************************** For Version 2.0.4: Bugs Fixed: Toolbar no longer updates when icon size is changed to 0 homedirectory code now works in the event of no home directory on windows default size and font set during a failed font lookup now apply to the preview box fixed no toolbar code in OnClose Changes: Added Startup Script to Options Added Psyco support to Startup Script margin width now reads: line number margin width in drPreferencesDialog Updated Documentation ******************************************************************************************************************************** For Version 2.0.3: Bugs Fixed: File Dialog now defaults to .py on linux AND windows. Replaced parenthesis with quotes in findreplace-dialog "string not found" dialog. Fixed Clean Up Tabs Code Fixed toolbar/menu update when there is no toolbar. Fixed Problem with Find Flags in Find Next. Fixed DrScript Documentation: "#returns" reads better. Shift+Tab Now functions as "Backtab" instead of Newline. Bad Pathname for programdirectory and bitmapdirectory on windows systems. Thanks Bjorn Breid. Now sets font AND size to default when a bad font is loaded from preferences or a theme. Changes: Add Select All, Select None to the Edit Menu under Select Removed compiled/object python filetypes from default wildcard. Reworked Clean Up Tabs into Clean Up Indentation, now you can go spaces->tabs or tabs->spaces. Added Use Tabs to Preferences Autoindent now uses spaces or tabs based on the user's preference Updated Documentation Changed Default Uncomment shortcut from Ctrl+Shift+']' to Ctrl+']' to better match Comment. Customize Shortcuts Checks to See if shortcuts are already being used when using "GetKey" Optimized some code in drpython.py, DrText.py, and DrPrinter.py with map, zfill, and expand tabs instead of while loops. removed superfluous preferences.dat from main directory. ******************************************************************************************************************************** For Version 2.0.2: Bugs Fixed: prompt code (OnIdle) slimmed down, now faster. font not in fontlist bug fixed. reset now resets icon file too colors fixed in aqua theme fixed html links in help.html removed some unneccessary code in drText.py In the "Hit a Key" dialog, now leaves customize shortcut text field blank if the user does not select a key customize shortcuts now handles all keys. event code changed in DrText.py and drPrompt.py to handle all shortcut keys default shortcuts now work on windows shortcuts documentation updated updated comments in example scripts. ******************************************************************************************************************************** For Version 2.0.1: Bugs Fixed: Tab Width now works for Printing. ******************************************************************************************************************************** For Version 2.0.0: Bugs Fixed: Autoindent/Newline code reworked. Now scrolls properly. Comment Region used to mess up the line about the selected region. Fixed. Ucomment Region fixed Preferences: Prompt is Visible Behaves Scrolling problem fixed in txtFile now fixed for txtPrompt License now spelled correctly in comments Autoindent now only counts tabs up to first non whitespace character Rewrote Code for sizing/showing txtFile and txtPrompt Fixed improper reporting of error on when setting default directory on toggle prompt, focus now given to txtFile or txtPrompt Error check toolbar bitmap loading Default directory code fixed Changes: Updated Documentation Documentation images now smaller Changelog Format Changed Preferences File Format Changed to markup language format, Defaults now loaded from code. Selection now stored as a single preference Code is now more Modular. You can now maximize select directory dialogs You can now open multiple files at a time MenuBar Rearranged Changed Search to Edit Added View Menu Added Change Case Added Indentation Added Zoom Add Undo/Redo File names and import statements have been changed for dialogs. File Dialog: Now views all python source file types at once. You can set ToolBar size to 0 You can load custom bitmaps for the ToolBar Update no longer closes preferences window Cancel button now reads "close" Preferences Rearranged Main -> General File -> Document Redid Preferences Dialog interface with wxFlexGridSizer Added Text Styles to Prompt Added Window size to Preferences Preferences Dialog is now resizable Apply font/size now work on style line number You can now set margnin width (linenumbers) for Document and Prompt Toggle Whitespace now works on the text control with focus (works on document and prompt) wordwrap, whitespace is visible added to preferences for prompt Default Shortcuts Changed Added a second field to the StatusBar for Program Status Icon/ToolBar bitmap format changed to png Default colors changed Printing Support Print File Print Prompt Print Setup Preferences stores tabwidth, whether or not to use line numbers Print File, Prompt added to ToolBar Added DrScript: run custom python scripts from the program menu, optionally takes frame, text, selection as arguments, optionally sets new values for text, selection via return statements Added Classbrowser activating an item goes to that item in the document, optionally closes the classbrowser window Unfolds on activate Added Bookmarks (you can bookmark either directories or files) Drag and Drop support for moving bookmarks/bookmark folders Added Themes Stores style information for Document, Prompt, Classbrowser Dialog, Bookmarks Dialog, and stores the list of icons being used. Created a Find/Replace Dialog: supports forwards/backwards, match case, whole words, in selection, from cursor hitting enter now acts the same in linux as in windows Added in selection support to switcheroo Added support for custom shortcuts Added Indent/Dedent Region to menu Added Folding support to Document Added foldingstyle to document ******************************************************************************************************************************** For Version 1.1.7: Bugs Fixed: Removed scrolls to current line when hitting . Fixed path problem with finding bitmaps. Thanks Guillermo Fernandez. ******************************************************************************************************************************** For Version 1.1.6: Bugs Fixed: View whitespace was broken. Took away view line-endings. Now only adds arguments if they exist. Changes: Scrolls to current line when hitting Added Comment, UnComment Out Region. ******************************************************************************************************************************** For Version 1.1.5: Bugs Fixed: caught exception with os.environ["APPDATA"] Changes: updated documentation ******************************************************************************************************************************** For Version 1.1.4: Bugs Fixed: (Bug request: Anonymous) If a user does not have a home directory on windows, drpython will now try to use the path os.environ["APPDATA"] first, then resort it c:\ if nothing is found. Changes: Updated Documentation: OS support. ******************************************************************************************************************************** For Version 1.1.3: Bugs Fixed: Really nasty infinite loop with replace-all fixed. Now works fine. Changes: Added North Star Blurb to Help. ******************************************************************************************************************************** For Version 1.1.2: Bugs Fixed: Did not adjust horizontal scrollbar on modify/open if text length exceeded scroll width. Horizontal scrollbar now dynamic (with extra padding). updatepreferences.py changed the preference file even if the user said no. autoindent misbehaved. It indented automatically when it shouldn't. remove all breakpoints did not remove visual indicators of break points if lines were edited between breakpoint creation and removal. Changes: Removed "Make Background Universal", Added "Apply Text Property To All Styles" which allows the font, size, foreground and background of the "Normal" style to be applied to all styles except "Line Number", "Caret Foreground", and "Selection" ******************************************************************************************************************************** For Version 1.1.1: Bugs Fixed: Did not clear prompt when a program was not running. Did not keep current directory with open/save. Changes: ******************************************************************************************************************************** For Version 1.1.0: Bugs Fixed: Prompt got ugly when lines were too long - switched to word wrap. Out of sync problem has been greatly reduced, practically non-existant. The speed problem came from updating the styled text control. DrPython now uses a much faster method. The result is that the lag has been reduced to almost nothing. DrPython also used to skip output as a result of the lag. This no longer is a problem. Replace-all infinite loop fixed. Preferences -> Save : wrote caret foreground incorrectly. When opening a file, incorrectly reset the status of run buttons. Reload button/menu did not work. Changed home directory in preferences dialog on open Added some code to use the systems root directory when a home directory cannot be found. Changes: Clear Prompt: Feature Request Carsten Eckelmann Added Selection Foreground/Background to Preferences Added Small Script to update a users preferences file from version 1.0.8 to 1.1.0 ******************************************************************************************************************************** For Version 1.0.8: Bugs Fixed: Replaced rstrip('\n') with rstrip(): Thanks Christof Ecker. Known Bugs: Out of sync while running python prompt alone, or program in interactive mode. ******************************************************************************************************************************** For Version 1.0.7: Bugs Fixed: Added code to handle no Booleans: Thanks Christof Ecker. Fixed bug with pathnames that include spaces for running a program. Fixed bug with single-line files and file format. Known Bugs: Out of sync while running python prompt alone, or program in interactive mode. ******************************************************************************************************************************** For Version 1.0.6: Bugs Fixed: Removed the linux install check, added a linux-launcher instead. Updated Documentation accordingly Changes: Check Save State on Run/Debug: Feature Request Carsten Eckelmann Known Bugs: Out of sync while running python prompt alone, or program in interactive mode. ******************************************************************************************************************************** For Version 1.0.5: Bugs Fixed: Updated Documentation With Unix/Linux Specific Notes: Thanks Carsten Ecklemann. Added Bash Script to check Unix/Linux install. Cut a jpg down to size. Fixed Notes pertaining to running python in Documentation and in Program. Known Bugs: Out of sync while running python prompt alone, or program in interactive mode. ******************************************************************************************************************************** For Version 1.0.4: Bugs Fixed: Fixed error setting program directory: Thanks to Mark Rees. DrPython now properly keeps track of the current directory when opening/saving. Changes: Goto scrolls so the target line is at the top of the screen. Scrapped drVerboseDialog for wxScrolledMessageDialog. Updated Documentation. Known Bugs: Out of sync while running python prompt alone, or program in interactive mode. ******************************************************************************************************************************** For Version 1.0.3: Bugs Fixed: Updated Documentation. Made changelog format clearer. Fixed Does not properly set savestate/undo state on open in new window if file format was changed. Fixed savestate/undo state not properly set on normal file open. Fixed index error in font style dialog, updated error handling for color strings. Known Bugs: Out of sync while running python prompt alone, or program in interactive mode. ******************************************************************************************************************************** For Version 1.0.2: Bugs Fixed: Fixed Current directory not set to current open file when running. Cleaned up code in drpython.py and drpython.pyw, removed superflous code in drHelp.py Changes: Added line ending code, plus optional checking. Added Relevant Help. Added F5 Toggles maximization. Known Bugs: Out of sync while running python prompt alone, or program in interactive mode. ******************************************************************************************************************************** For Version 1.0.1: Bugs Fixed: Fixed Does not toggle prompt on icon size change. Fixed prompt toggle not properly set in pref, should be based on file rather than current state. Fixed Does not apply default directory to save dialog. Fixed Home and Page-Up buttons take you past edit position in prompt. Fixed Prompt misbehaves on max recent commands. Some unused code removed. Changes: Find/Replace now uses selected text as find text, and the old find text hangs around. Known Bugs: Out of sync while running python prompt alone, or program in interactive mode. Frequency: Rare. Severity: Minor, only seems to affect output of python prompt text (sys.ps1). drpython-3.11.1/manifest.in0000644000175000017500000000016111150445514016406 0ustar dktrkranzdktrkranzinclude * recursive-include bitmaps * recursive-include examples * recursive-include documentation * prune build drpython-3.11.1/setup.py0000644000175000017500000000567211235243572016002 0ustar dktrkranzdktrkranz# DrPython installation script # Copyright (c) 2004 Radoslaw Stachowiak # Last modification: 2004-10-12 # ####################################### # # Version 0.9.2: Classifiers and post installation added by Christoph. # # Version 0.9.1: The full modified version by Christoph. # (Plus minor comment changes by Dan). # # (Daniel Pozmanter, 0.9.0: Added Christoph's Patch. # # (Daniel Pozmanter: 0.8.1: Modified version number.) # ####################################### # """\ DrPython - a highly customizable cross-platform Python IDE DrPython is a highly customizable, cross-platform, extensible editor and environment for developing programs written in the Python programming language. It is implemented in wxPython (a set of Python bindings and extra widgets for wxWidgets) and uses its Scintilla based editor component. You can get the latest Python version from http://www.python.org. You can get the latest wxPython version from http://www.wxpython.org.""" # version (should be imported from drpython.py or __init__.py) MY_VER='3.11.1' # package name, do not change MY_NAME = 'drpython' AUTHOR = 'Daniel Pozmanter' AUTHOR_EMAIL = 'drpython@bluebottle.com' URL = 'http://drpython.sourceforge.net' # Trove classification (get list with python setup.py register --list-classifiers) classifiers = """ Development Status :: 5 - Production/Stable Environment :: MacOS X Environment :: Win32 (MS Windows) Environment :: X11 Applications :: GTK Intended Audience :: Developers Intended Audience :: Education Intended Audience :: Information Technology Intended Audience :: Other Audience Intended Audience :: Science/Research Intended Audience :: System Administrators OSI Approved :: GNU General Public License (GPL) Natural Language :: English Operating System :: MacOS :: MacOS X Operating System :: Microsoft :: Windows Operating System :: POSIX :: Linux Programming Language :: Python Topic :: Documentation Topic :: Software Development Topic :: Text Editors Topic :: Text Editors :: Integrated Development Environments (IDE) """ # take name and description from setup.py docstring description = __doc__.split('\n\n', 1) name=description[0].split(' ', 1)[0] # please add every package data file to be installed to the list DATA = [ 'documentation/*', 'examples/DrScript/*', 'bitmaps/*.ico', 'bitmaps/*.png', 'bitmaps/16/*.png', 'bitmaps/24/*.png', # adding runner scripts, TODO: drpython startup should be probably redone 'drpython.pyw', 'drpython.lin' ] from distutils.core import setup # and now standard distutils installation routine setup(name=name, version=MY_VER, description=description[0], long_description=description[1], classifiers = filter(None, classifiers.split('\n')), author=AUTHOR, author_email=AUTHOR_EMAIL, url=URL, platforms = "any", license = 'GPL', packages=[ MY_NAME ], package_dir={ MY_NAME : '.' }, package_data={ MY_NAME : DATA }, scripts=['postinst.py'], ) drpython-3.11.1/README.TXT0000644000175000017500000000045711150445515015617 0ustar dktrkranzdktrkranz========== DrPython ========== ------------- Installation ------------- You do not need to install drpython. You do need to have python, and wxPython installed. (www.python.org, www.wxpython.org). Just run drpython.pyw (double click in windows, python drpython.pyw on other systems). drpython-3.11.1/drpython.py0000644000175000017500000051140411235322053016474 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Requirements(Dependencies): Install Python, and wxPython. # # Tested On Windows, Linux, Mac OS X # # Icons taken from "Klassic New Crisp Icons" by Asif Ali Rizwaan (therizwaan) from the KDE-LOOK site (some edited a bit). # A humble and excellent artist. # Oh, the python icon is taken from wxPython. # The basic design of the program is meant to roughly (ROUGHLY) mimick DrScheme. # The purpose is the same, to provide a simple IDE(integrated development environment) ideal for teaching. # The DrPython icon itself was based on the DrScheme icon, with a slightly edited wxpython icon inserted(note yellow tongue, googly eyes). # # This program could not have been written without the wonderful work of the people behind # python and wxPython, in particular the Styled Text Control. Thank you. Hopefully this tool will be of use. # # Replaced all rstrip('\n') with rstrip(), thanks Christof Ecker: (drpython.py and DrPrefs.py). # # Version: 3.11.1 #franz: stat is not used import sys, os, shutil, re, string, traceback #import wxversion #wxversion.select('2.8') import wx, wx.stc import wx.lib.dialogs import drScrolledMessageDialog import drHtmlBrowser from drNotebook import * from drText import DrText from drPrompt import DrPrompt from drPrinter import DrPrinter from drFindReplaceDialog import drFindReplaceDialog from drBookmarksMenu import drBookmarksMenu from drScriptMenu import drScriptMenu from drPluginMenu import drPluginConfigureMenu, drPluginIndexMenu, drPluginAboutMenu, drPluginHelpMenu, drPluginPreferencesMenu import drGetBlockInfo import drSourceBrowserGoTo import drFileDialog import drPrefsFile from drPreferences import drPreferences import drShortcutsFile import drShortcuts import drToolBarFile import drTabNanny from drSourceBrowser import drSourceBrowserPanel import drEncoding from drStyleDialog import drSeparatorDialog from drMenu import drMenu import pydoc import tempfile import time logdir = os.path.expanduser("~").replace("\\", "/") if sys.platform == "win32": if os.environ.has_key("APPDATA"): logdir = os.environ["APPDATA"].replace("\\", "/") if not os.path.exists(logdir): logdir = '/' if not logdir.endswith('/'): logdir += '/' err_file = logdir + 'drpython.err' out_file = logdir + 'drpython.out' firsterr_file = logdir + 'drpythonfirst.err' #******************************************************************************************************* class drObject(wx.Object): def __init__(self): #wx.Object.__init__(self) pass def VariableExists(self, varname): try: eval("self." + varname) except: return False return True #******************************************************************************************************* class DrFrame(wx.Frame): def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(680, 480), name="DrPython") self.ignoreevents = False self.disableeventhandling = False self.preferencesdirectory = "" #Preferences Directory: self.invokeuserpreferencespath = False if len(sys.argv) > 1: x = 0 for a in sys.argv: if a.find('--preferencesbasepath=') == 0: self.invokeuserpreferencespath = True self.preferencesdirectory = os.path.expanduser(a[22:]) if not os.path.exists(self.preferencesdirectory): wx.MessageBox("Preferences Directory: '%s' does not exist!" % self.preferencesdirectory, "Creating Directory!", wx.ICON_INFORMATION) os.makedirs(self.preferencesdirectory) del sys.argv[x] x -= 1 x += 1 self.InitializeConstants() self.viewinpaneltarget = 0 self.lastprogargs = "" self.DrScript = drObject() #self.DrPlugins = drObject() self.Printer = DrPrinter(self) #Regex Line Endings: self.relewin = re.compile('\r\n', re.M) self.releunix = re.compile('[^\r]\n', re.M) self.relemac = re.compile('\re[^\n]', re.M) self.FormatMacReTarget = re.compile('((? 1: f = sys.argv[1] if self.PLATFORM_IS_WIN: f = f.replace("\\", "/") if not os.path.exists(f): if self.Ask('"' + f + '" Does not exist. Create?', 'File Does Not Exist'): try: fobj = file(f, 'wb') fobj.close() except: self.ShowMessage('Error Creating "' + f + '"') if os.path.exists(f): self.OpenFile(f, False) self.txtDocument.OnModified(None) x = 2 l = len(sys.argv) while x < l: f = sys.argv[x] if self.PLATFORM_IS_WIN: f = f.replace("\\", "/") self.OpenFile(f, True) self.txtDocument.OnModified(None) x = x + 1 #Load SourceBrowser: if self.prefs.sourcebrowserisvisible: self.ShowSourceBrowser() self.Bind(wx.EVT_END_PROCESS, self.OnProcessEnded, id=-1) self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) self.Bind(wx.EVT_CLOSE, self.OnCloseW) self.LoadPlugins() def Append_Menu(self, menu, id, s, LaunchesDialog = False, AmpersandAt = -1, absolutelabel=''): label = s item = wx.MenuItem(menu, id, label, label) menuiconfile = self.bitmapdirectory + "/16/" + s + ".png" if os.path.exists(menuiconfile): #try: img = wx.Image(menuiconfile, wx.BITMAP_TYPE_PNG) bmp = wx.BitmapFromImage(img) #except? #else: #bmp = wx.EmptyBitmap(16, 16) #width the same, background colour frame colour, so alignment is assured item.SetBitmap(bmp) #item.SetBitmap(bmp) menu.AppendItem(item) def AddKeyEvent(self, function, Keycode, Control=0, Shift=0, Alt=0, Meta=0): if Keycode == -1: return shortcut = drShortcuts.BuildShortcutString(Keycode, Control, Shift, Alt, Meta) self.PluginShortcutNames.append('Plugin') self.PluginShortcuts.append(shortcut) self.PluginAction.append(function) def AddPluginFunction(self, plugin, label, function): self.PluginShortcutFunctionNames.append(plugin + ":" + label) self.PluginShortcutFunctions.append(function) self.PluginPopUpMenuNames.append(plugin) self.PluginPopUpMenuLabels.append(label) self.PluginPopUpMenuFunctions.append(function) self.PluginToolBarLabels.append(":"+label) self.PluginToolBarFunctions.append(function) def AddPluginIcon(self, name, location16, location24): ctbfile = self.datdirectory + "/toolbar.custom.icons.dat" if not os.path.exists(ctbfile): f = file(ctbfile, 'w') f.write('\n') f.close() f = file(ctbfile, 'r') lines = f.read().split('\n') f.close() name = ":" + name f = file(self.datdirectory + "/toolbar.custom.icons.dat", 'w') for line in lines: if line: currentname = drPrefsFile.ExtractPreferenceFromText(line, "Name") if currentname != name: f.write(line + '\n') f.write("" + name + "<16>" + location16 + "<24>" + \ location24 + "\n") f.close() def AddPluginShortcutFunction(self, plugin, label, function): self.PluginShortcutFunctionNames.append(plugin + ":" + label) self.PluginShortcutFunctions.append(function) def AddPluginPopUpMenuFunction(self, plugin, label, function): self.PluginPopUpMenuNames.append(plugin) self.PluginPopUpMenuLabels.append(label) self.PluginPopUpMenuFunctions.append(function) def AddPluginToolBarFunction(self, label, function): self.PluginToolBarLabels.append(":"+label) self.PluginToolBarFunctions.append(function) def Ask(self, question, title='DrPython'): answer = wx.MessageBox(question, title, wx.YES_NO | wx.ICON_QUESTION) return (answer == wx.YES) #ugly hack: on windows and gtk, yes no behaves different (on gtk, you can escape with ESC, on gtk it is the other side def AskPlatformDependent(self, question, title='DrPython'): if self.PLATFORM_IS_WIN: ok = wx.OK stylemsgbox = wx.OK | wx.CANCEL else: ok = wx.YES stylemsgbox = wx.YES_NO answer = wx.MessageBox(question, title, stylemsgbox | wx.ICON_QUESTION) return answer == ok def checkiffileisCPP(self, filename): return self.refiletypeiscpp.search(filename) is not None def checkiffileisHTML(self, filename): return self.refiletypeishtml.search(filename) is not None def checkiffileisPlainText(self, filename): return self.refiletypeistxt.search(filename) is not None def checkiffileisPython(self, filename): return self.refiletypeispy.search(filename) is not None def CheckSyntax(self, docnumber=-1): if docnumber == -1: docnumber = self.docPosition fn = self.txtDocumentArray[docnumber].GetFilename() if not self.txtDocumentArray[docnumber].filename: self.ShowMessage('Cannot Run Check on "%s"' % fn, 'Cannot Check Untitled File') return False #Check Syntax First try: #begin patch Knut Gerwens, DrPython 164, Dec. 2006. #there was former a problem using unicode version of wxPython with encoding cookie encoding = self.txtDocumentArray[docnumber].GetEncoding() ctext = drEncoding.DecodeText(self, self.txtDocumentArray[docnumber].GetText(), encoding) ctext = ctext.replace('\r\n', '\n').replace('\r', '\n') compile(ctext, fn, 'exec') #end patch Knut Gerwens, DrPython 164, Dec. 2006. except Exception, e: excstr = str(e) result = self.rechecksyntax.search(excstr) if result is not None: num = result.group()[5:].strip() try: n = int(num) - 1 self.setDocumentTo(docnumber) self.txtDocument.ScrollToLine(n) self.txtDocument.GotoLine(n) self.ShowMessage('compile:\n' + excstr) self.txtDocument.SetSTCFocus(True) self.txtDocument.SetFocus() #Stop the function here if something is found. return False except: self.ShowMessage('Line Number Error:\n\n'+excstr, 'SyntaxError') else: self.ShowMessage('No Line Number Found:\n\n' + excstr, 'Syntax Error') #Now Check Indentation result = drTabNanny.Check(fn) results = result.split() if len(results) > 1: num = results[1] try: n = int(num) - 1 self.setDocumentTo(docnumber) self.txtDocument.ScrollToLine(n) self.txtDocument.GotoLine(n) self.ShowMessage('tabnanny:\n' + result) self.txtDocument.SetSTCFocus(True) self.txtDocument.SetFocus() return False except: self.ShowMessage('Line Number Error:\n\n'+result, 'TabNanny Trouble') return True def CreateRecentFileMenu(self): x = 0 numfiles = len(self.recentfiles) while x < numfiles: self.recentmenu.Append(self.ID_RECENT_FILES_BASE+x, self.recentfiles[x]) self.Bind(wx.EVT_MENU, self.OnOpenRecentFile, id=self.ID_RECENT_FILES_BASE+x) x = x + 1 def DestroyDocument(self): self.txtDocumentArray.pop(self.docPosition) self.lastprogargsArray.pop(self.docPosition) def DestroyRecentFileMenu(self): #You need to call this function BEFORE you update the list of recent files. x = 0 mnuitems = self.recentmenu.GetMenuItems() num = len(mnuitems) while x < num: self.recentmenu.Remove(self.ID_RECENT_FILES_BASE+x) x = x + 1 def DestroyToolBar(self): if self.toolbar is not None: x = 0 toolbarsize = len(self.ToolBarIdList) while x < toolbarsize: if self.ToolBarIdList[x] == -300: self.toolbar.DeleteToolByPos(0) else: self.toolbar.DeleteTool(self.ToolBarIdList[x]) x = x + 1 self.toolbar.Destroy() self.toolbar = None def DoBuiltIn(self, event): objid = event.GetId() if self.txtPrompt.GetSTCFocus(): stc = self.txtPrompt else: stc = self.txtDocument if objid == self.ID_COPY: stc.CmdKeyExecute(wx.stc.STC_CMD_COPY) elif objid == self.ID_PASTE: stc.Paste() elif objid == self.ID_CUT: stc.CmdKeyExecute(wx.stc.STC_CMD_CUT) elif objid == self.ID_DELETE: stc.CmdKeyExecute(wx.stc.STC_CMD_CLEAR) def dynamicdrscript(self, event): self.drscriptmenu.OnDynamicScript(event) def Execute(self, command, statustext = ''): if not statustext: statustext = "Running Command" self.runcommand(command, statustext, command) def ExecutePython(self): self.txtPrompt.pythonintepreter = 1 self.ExecuteWithPython('', 'Running Python Interpreter', '-i', 'Python') i = self.promptPosition try: wx.Yield() except: pass #workaround by Dunderhead. if self.PLATFORM_IS_WIN: self.txtPromptArray[i]._waitforoutput('>>>') #self.txtPromptArray[i]._waitforoutput('>>>') self.txtPromptArray[i].ExecuteCommands(self.prefs.promptstartupscript) def ExecuteWithPython(self, command = '', statustext = '', pythonargs='', pagetext='Python'): commandstring = string.join([' -u', pythonargs, self.prefs.pythonargs, command], ' ').rstrip() if self.PLATFORM_IS_WIN: self.runcommand((self.pythexecw + commandstring), statustext, pagetext) else: self.runcommand((self.pythexec + commandstring), statustext, pagetext) def GetActiveSTC(self): if self.txtPrompt.GetSTCFocus(): return self.txtPrompt else: return self.txtDocument def GetAlreadyOpen(self): def _get_filename(x): return x.filename.lower() return map(_get_filename, self.txtDocumentArray) def getfileextensionstring(self, index): thelist = self.prefs.extensions[index].split(',') thestring = '' for t in thelist: thestring += '(\.' + t.strip() + '$)|' return thestring[:-1] def GetFileName(self): return self.txtDocument.filename def getmenulabel(self, label, LaunchesDialog=False, AmpersandAt=-1, absolutelabel=''): shortcuttext = '' if label in self.ShortcutNames: i = self.ShortcutNames.index(label) shortcuttext = drShortcuts.GetShortcutLabel(self.Shortcuts[i]) elif label in self.STCShortcutNames: i = self.STCShortcutNames.index(label) shortcuttext = drShortcuts.GetShortcutLabel(self.STCShortcuts[i]) if absolutelabel: label = absolutelabel else: if (AmpersandAt > -1) and (AmpersandAt < len(label)): label = label[:AmpersandAt] + '&' + label[AmpersandAt:] if LaunchesDialog: label += '...' if len(shortcuttext) > 1: return label + '\t' + shortcuttext return label def GetNewId(self): return 10000 + wx.NewId() #Begin Backwards Compatibility def GetPluginDirectory(self): return self.pluginsdirectory def GetPluginsDirectory(self): return self.GetPluginDirectory() #End Backwards Compatibility def GetPluginLabels(self, filename, doNotAppend = False): try: f = file(filename, 'r') text = f.read() f.close() except: self.ShowMessage('File error with: "' + filename + '".', "ERROR") return [] rePopUpMenu = re.compile(r'^\s*?DrFrame\.AddPluginFunction\(.*\)', re.MULTILINE) allPopUps = rePopUpMenu.findall(text) PopUpArray = [] for s in allPopUps: #From the Left most '(' start = s.find('(') #To the Right most ')' end = s.rfind(')') if (start > -1) and (end > -1): s = s[start+1:end] i = s.find(',') e = i + 1 + s[i+1:].find(',') arglabel = s[i+1:e].strip().strip('"') if doNotAppend: PopUpArray.append(arglabel) else: PopUpArray.append(":"+arglabel) return PopUpArray def GetPluginMenuLabel(self, plugin, functionlabel, menulabel=''): shortcuttext = '' searchlabel = plugin + ':' + functionlabel if searchlabel in self.PluginShortcutNames: i = self.PluginShortcutNames.index(searchlabel) shortcuttext = drShortcuts.GetShortcutLabel(self.PluginShortcuts[i]) if not menulabel: menulabel = functionlabel if len(shortcuttext) > 1: return menulabel + '\t' + shortcuttext return menulabel def GetPreference(self, pref, key=None): if key is not None: return self.prefs[pref][key] else: return self.prefs[pref] def WriteUserPreferencesDirectoryFile(self): if not self.invokeuserpreferencespath: f = open(self.preferencesdirectoryfile, 'w') f.write(self.preferencesdirectory) f.close() def InitializeConstants(self): #Constant messages for file format checking. self.FFMESSAGE = ["Unix Mode ('\\n')", "DOS/Windows Mode ('\\r\\n')", "Mac Mode ('\\r')"] self.TABMESSAGE = ['Spaces', 'Mixed', 'Tabs', 'None'] self.ID_DOCUMENT_BASE = 50 self.ID_PROMPT_BASE = 340 #Application ID Constants self.ID_APP = 101 self.ID_NEW = 102 self.ID_OPEN = 103 self.ID_OPEN_IMPORTED_MODULE = 1000 self.ID_OPEN_RECENT = 104 self.ID_RELOAD = 105 self.ID_RESTORE_FROM_BACKUP = 1051 self.ID_CLOSE = 106 self.ID_CLOSE_ALL = 6061 self.ID_CLOSE_ALL_OTHER_DOCUMENTS = 6062 self.ID_CLEAR_RECENT = 107 self.ID_SAVE = 108 self.ID_SAVE_AS = 109 self.ID_SAVE_COPY = 1092 self.ID_SAVE_ALL = 1098 self.ID_SAVE_PROMPT = 1091 self.ID_PRINT_SETUP = 1010 self.ID_PRINT = 1011 self.ID_PRINTPROMPT = 1012 self.ID_EXIT = 1014 # define import all id self.ID_IMPORT_ALL = self.GetNewId() # end import all # define pydoc ids self.ID_PYDOC_ALL = 1016 self.ID_PYDOC_CURR = 1017 self.ID_VIEW_PYDOC = 1018 # end pydoc self.ID_INSPECT_TOOL = 1019 self.ID_NEXT_DOCUMENT = 801 self.ID_PREVIOUS_DOCUMENT = 802 self.ID_FIRST_DOCUMENT = 803 self.ID_LAST_DOCUMENT = 804 self.ID_DOCUMENT_NAVIGATION_MENU = 810 self.ID_DOCUMENTS_BASE = 8000 self.ID_DOCUMENTS_MENU_BASE = 7950 self.ID_COPY = 850 self.ID_PASTE = 851 self.ID_CUT = 852 self.ID_DELETE = 853 self.ID_FIND = 111 self.ID_FIND_NEXT = 112 self.ID_FIND_PREVIOUS = 1122 self.ID_REPLACE = 113 self.ID_GOTO = 115 self.ID_GOTO_MENU = 1150 self.ID_GOTO_BLOCK_START = 1151 self.ID_GOTO_BLOCK_END = 1152 self.ID_GOTO_CLASS_START = 1153 self.ID_GOTO_CLASS_END = 1154 self.ID_GOTO_DEF_START = 1155 self.ID_GOTO_DEF_END = 1156 self.ID_SOURCEBROWSER_GOTO = 1157 self.ID_SELECT_ALL = 1161 self.ID_INSERT_REGEX = 1163 self.ID_INSERT_SEPARATOR = 1164 self.ID_COMMENT = 1116 self.ID_COMMENT_REGION = 116 self.ID_UNCOMMENT_REGION = 117 self.ID_WHITESPACE = 1118 self.ID_INDENT_REGION = 118 self.ID_DEDENT_REGION = 119 self.ID_CHECK_INDENTATION = 1650 self.ID_CLEAN_UP_TABS = 1670 self.ID_CLEAN_UP_SPACES = 1671 self.ID_FORMATMENU = 2000 self.ID_UNIXMODE = 2001 self.ID_WINMODE = 2002 self.ID_MACMODE = 2003 self.ID_FIND_AND_COMPLETE = 2071 self.ID_CASE = 1191 self.ID_UPPERCASE = 1192 self.ID_LOWERCASE = 1193 self.ID_UNDO = 1111 self.ID_REDO = 1112 self.ID_ZOOM_IN = 161 self.ID_ZOOM_OUT = 162 self.ID_FOLDING = 1610 self.ID_TOGGLE_FOLD = 1613 self.ID_FOLD_ALL = 1611 self.ID_EXPAND_ALL = 1612 self.ID_TOGGLE_SOURCEBROWSER = 163 self.ID_TOGGLE_VIEWWHITESPACE = 164 self.ID_TOGGLE_PROMPT = 165 self.ID_VIEW_IN_PANEL = 170 self.ID_VIEW_IN_LEFT_PANEL = 171 self.ID_VIEW_IN_RIGHT_PANEL = 172 self.ID_VIEW_IN_TOP_PANEL = 173 self.ID_VIEW_IN_PANEL_BASE = 1700 self.ID_HIGHLIGHT = 580 self.ID_HIGHLIGHT_PYTHON = 585 self.ID_HIGHLIGHT_CPP = 586 self.ID_HIGHLIGHT_HTML = 587 self.ID_HIGHLIGHT_PLAIN_TEXT = 589 self.ID_RUN = 121 self.ID_SET_ARGS = 122 self.ID_PYTHON = 123 self.ID_END = 125 self.ID_CLOSE_PROMPT = 1250 self.ID_CHECK_SYNTAX = 126 self.ID_PREFS = 131 self.ID_SHORTCUTS = 133 self.ID_POPUP = 134 self.ID_CUSTOMIZE_TOOLBAR = 135 self.ID_CONFIGURE_PLUGINS = 4005 self.ID_LOAD_PLUGIN = 4050 self.ID_PLUGIN_HELP = 4051 self.ID_PLUGIN_PREFS = 4052 self.ID_PLUGIN_ABOUT = 4053 self.ID_EDIT_BOOKMARKS = 301 self.ID_EDIT_SCRIPT_MENU = 3004 self.ID_ABOUT = 140 self.ID_HELP = 141 self.ID_PYTHON_DOCS = 142 self.ID_WXWIDGETS_DOCS = 143 self.ID_REHOWTO_DOCS = 144 self.ID_OTHER = 9000 self.ID_RECENT_FILES_BASE = 9930 self.ID_RECENT_SESSIONS_BASE = 8330 self.ID_SCRIPT_BASE = 7500 #STC Shortcut List: self.STCCOMMANDLIST = drShortcuts.GetSTCCommandList() #System constants self.PLATFORM_IS_WIN = wx.Platform == '__WXMSW__' # (sys.platform == "win32") or #wx.PLATFORM_WINDOWS or wx.PLATFORM_WINDOWS self.PLATFORM_IS_GTK = wx.Platform == '__WXGTK__' self.PLATFORM_IS_MAC = wx.Platform == '__WXMAC__' self.PLATFORM_OTHER = False if not self.PLATFORM_IS_WIN and not self.PLATFORM_IS_GTK and not self.PLATFORM_IS_MAC: self.PLATFORM_OTHER = True #Thanks to Mark Rees. #Thanks to Guillermo Fernandez. #Thanks Bjorn Breid #Preferences Directory Initial Setup: self.userhomedirectory = wx.StandardPaths.Get().GetUserConfigDir().replace('\\', '/') if not self.preferencesdirectory: self.preferencesdirectory = self.userhomedirectory self.preferencesdirectoryprefix = "/.drpython" if self.PLATFORM_IS_WIN: self.preferencesdirectoryprefix = "/drpython" self.preferencesdirectory += self.preferencesdirectoryprefix self.preferencesdirectoryfile = self.preferencesdirectory + "/userpreferencesdirectory.dat" if not os.path.exists(self.preferencesdirectory): os.mkdir(self.preferencesdirectory) if not os.path.exists(self.preferencesdirectoryfile): self.WriteUserPreferencesDirectoryFile() f = open(self.preferencesdirectoryfile, 'r') pth = f.read() f.close() if os.path.exists (pth): self.preferencesdirectory = pth else: wx.MessageBox("Changing Userpreferences directory to default:\n '%s'" % \ self.preferencesdirectory, "Userpreferences Directory not found:", wx.ICON_EXCLAMATION) self.WriteUserPreferencesDirectoryFile() #backwards compatibility todo remove that later self.homedirectory = os.path.expanduser('~') if self.PLATFORM_IS_WIN: self.pythexec = sys.prefix.replace("\\", "/") + "/python.exe" self.pythexecw = sys.prefix.replace("\\", "/") + "/pythonw.exe" else: self.pythexec = sys.executable def InitializePlugin(self, plugin, ShowDialog = True): #Check to see if the plugin is already loaded: if plugin in self.LoadedPlugins: if ShowDialog: self.ShowMessage(('"' + plugin + '" has already been loaded.\nDrPython will not reload this plugin.'), "Plugin Already Loaded") return #Load the Plugin pluginfile = os.path.join (self.pluginsdirectory, plugin + ".py") self.LoadedPlugins.append(plugin) try: exec(compile("import " + plugin, pluginfile, 'exec')) exec(compile(plugin + ".Plugin(self)", pluginfile, 'exec')) exec(compile('self.PluginModules.append('+plugin+')', pluginfile, 'exec')) except: self.ShowMessage("Error with: " + plugin + "\nDrPython will not load this plugin.", "Plugin Error") #Menus self.pluginsaboutmenu.AddItem(plugin) self.pluginshelpmenu.AddItem(plugin) self.pluginsprefsmenu.AddItem(plugin) def LoadPlugins(self, plugins_file = ""): #todo remove this? is this used? franz 22.03.2007: if plugins_file: pluginsfile = plugins_file else: #end todo remove this? is this used? franz 22.03.2007: pluginsfile = self.preferencesdirectory + "/default.idx" if os.path.exists(pluginsfile): try: f = file(pluginsfile, 'rU') pluginstoload = [x.strip() for x in f] f.close() for plugin in pluginstoload: if plugin: self.InitializePlugin(plugin) except: self.ShowMessage(("Error with: " + pluginsfile + "\nDrPython will not load plugins."), "Plugins Error") else: try: f = file(pluginsfile, 'wb') #f.write('\n') f.close() except: self.ShowMessage('Error Ceating Default Index for Plugins.\n\nPlugins may not work correctly.', 'Plugins Error') def LoadPluginShortcuts(self, plugin): if plugin in self.PluginShortcutsLoadedArray: return self.PluginShortcutsLoadedArray.append(plugin) shortcutfile = os.path.join (self.pluginsshortcutsdirectory, plugin + ".shortcuts.dat") if not os.path.exists(shortcutfile): return try: shortcuts, names, ignorestring = drShortcutsFile.ReadShortcuts(shortcutfile, 0) x = 0 l = len(shortcuts) while x < l: shortcut = shortcuts[x] try: i = self.PluginShortcutFunctionNames.index(plugin + ":" + names[x]) self.PluginAction.append(self.PluginShortcutFunctions[i]) self.PluginShortcutNames.append(plugin + ":" + names[x]) self.PluginShortcuts.append(shortcut) except: pass x += 1 except: self.ShowMessage(("Error with: " + plugin + "\nDrPython will not load shortcuts for this plugin."), "Plugin Shortcuts Error") def LoadPopUpFile(self): #check for preferences file in user userpreferencesdirectory popupfile = self.datdirectory + "/popupmenu.dat" if os.path.exists(popupfile): try: f = file(popupfile, 'r') line = f.readline() while len(line) > 0: self.popupmenulist.append(line.rstrip()) line = f.readline() f.close() except: self.ShowMessage("Error with: " + popupfile + "\nDrPython will use the program defaults.", "Pop Up Menu Error") def SetDrPythonDirectories(self): #bitmaps code directory self.bitmapdirectory = self.programdirectory + "/bitmaps" if not os.path.exists(self.bitmapdirectory): self.ShowMessage("Bitmap Directory (" + self.bitmapdirectory + ") does Not Exist.", "DrPython Fatal Error") sys.exit(1) #for backward compatibility (can be removed in the future). self.userpreferencesdirectory = self.preferencesdirectory #Update to DrPython 165 and later (part1) can be removed in the future. self.DrPythonUpdateFrom164AndBefore = False if self.CheckForDrPythonBefore165(): self.updirbackup = self.updir + '164backup' answer = wx.MessageBox("All files are backed up into the directory:\n\ '%s'\n\n\ Nothing can happen (No data loss, the worst thing is, that it is not working properly).\n\n\ If this is not working, then you still copy the files with a filemanager.\n" % self.updirbackup, "Do you want to update to DrPython 1.65 now?", style=wx.YES|wx.NO) if answer == wx.YES: try: self.DrPythonUpdateFrom164AndBefore = True #backup files and directories and delete all except preferences.dat. #before the mess begins. if os.path.exists(self.updirbackup): shutil.rmtree(self.updirbackup) os.rename(self.updir, self.updirbackup) #this must exist before if not os.path.exists(self.preferencesdirectory): os.makedirs(self.preferencesdirectory) if os.path.exists(self.updirbackup + '/preferences.dat'): shutil.copyfile(self.updirbackup + '/preferences.dat', self.preferencesdirectory + '/preferences.dat') #DrPlugins default directory self.prefs.pluginsdirectory = os.path.join(self.preferencesdirectory, 'drplugins').replace ('\\', "/") #DrScript default directory self.prefs.drscriptsdirectory = os.path.join(self.preferencesdirectory, 'drscripts').replace ('\\', "/") #Write preferences file drPrefsFile.WritePreferences(self.prefs, self.prefsfile) except: answer = wx.MessageBox("Sorry, something went wrong!\n(Maybe the directory is accessed now by another program).", "Update to DrPython") self.DrPythonUpdateFrom164AndBefore = False #Update to DrPython 165 and later end (part1). #plugins code directory if not os.path.exists(self.prefs.pluginsdirectory): os.mkdir(self.prefs.pluginsdirectory) self.pluginsdirectory = self.prefs.pluginsdirectory sys.path.append(self.pluginsdirectory) #drscripts code directory if not os.path.exists(self.prefs.drscriptsdirectory): os.mkdir(self.prefs.drscriptsdirectory) self.drscriptsdirectory = self.prefs.drscriptsdirectory #dat directory self.datdirectory = os.path.join(self.preferencesdirectory, 'dat') if not os.path.exists(self.datdirectory): os.mkdir(self.datdirectory) #shortcuts directory self.shortcutsdirectory = os.path.join(self.preferencesdirectory, 'shortcuts') if not os.path.exists(self.shortcutsdirectory): os.mkdir(self.shortcutsdirectory) #plugins directory self.pluginsbasepreferencesdir = os.path.join(self.preferencesdirectory, '.plugins') if not os.path.exists(self.pluginsbasepreferencesdir): os.mkdir(self.pluginsbasepreferencesdir) #plugins preferences directory self.pluginspreferencesdirectory = os.path.join(self.pluginsbasepreferencesdir, 'preferences') if not os.path.exists(self.pluginspreferencesdirectory): os.mkdir(self.pluginspreferencesdirectory) #plugins shortcuts directory self.pluginsshortcutsdirectory = os.path.join(self.pluginsbasepreferencesdir, 'shortcuts') if not os.path.exists(self.pluginsshortcutsdirectory): os.mkdir(self.pluginsshortcutsdirectory) #plugins dat directory self.pluginsdatdirectory = os.path.join(self.pluginsbasepreferencesdir, 'dat') if not os.path.exists(self.pluginsdatdirectory): os.mkdir(self.pluginsdatdirectory) #Update to DrPython 165 and later (part2) can be removed in the future. if self.DrPythonUpdateFrom164AndBefore: self.ProcessUpgradeToDrPython165() #Update to DrPython 165 and later end (part2). def LoadPreferences(self): #check for preferences file in user userpreferencesdirectory if os.path.exists(self.prefsfile): try: drPrefsFile.ReadPreferences(self.prefs, self.prefsfile) except: self.ShowMessage(("Error with: " + self.prefsfile + "\nDrPython will load the program defaults."), "Preferences Error") self.prefs.reset() drPrefsFile.WritePreferences(self.prefs, self.prefsfile) else: drPrefsFile.WritePreferences(self.prefs, self.prefsfile) wx.GetApp().debugmodus = self.prefs.debugmodus # already restted if self.prefs.defaultencoding: reload(sys) #this is needed because of wine and linux sys.setdefaultencoding(self.prefs.defaultencoding) wx.SetDefaultPyEncoding(self.prefs.defaultencoding) def AskExitingDrPython(self): answer = wx.MessageBox('Would you like to quit DrPython?', "DrPython", wx.YES_NO | wx.ICON_QUESTION) if answer == wx.YES: sys.exit() def LoadRecentFiles(self): f = self.datdirectory + "/recent_files.log" if not os.path.exists(f): try: t = open(f, 'w') t.close() except IOError: if self.prefs.debugmodus: self.ShowMessage("Error Creating: " + f + "\nMaybe you don't have right access or harddisk is full" , "Recent Files Error") self.AskExitingDrPython() try: fin = open(f, 'r') s = fin.readline() x = 0 while (len(s) > 0) and (x < self.prefs.recentfileslimit): s = s.rstrip() if s: self.recentfiles.append(s) x = x + 1 s = fin.readline() fin.close() except IOError: self.ShowMessage(("Error Reading: " + f), "Recent Files Error") self.AskExitingDrPython() def LoadShortcuts(self, UseDefault = False): #Load STC Shortcuts stcshortcutsfile = self.shortcutsdirectory + "/stcshortcuts.dat" if os.path.exists(stcshortcutsfile) and (not UseDefault): try: self.STCShortcuts, self.STCShortcutNames, t = drShortcutsFile.ReadSTCShortcuts(stcshortcutsfile) self.STCUseDefault = 0 except: self.ShowMessage(("Error with: " + stcshortcutsfile + "\nDrPython will not load STC shortcuts."), "STC Shortcuts Error") #check for shortcuts file in user userpreferencesdirectory shortcutsfile = self.shortcutsdirectory + "/shortcuts.dat" if os.path.exists(shortcutsfile) and (not UseDefault): try: self.Shortcuts, self.ShortcutNames, self.ShortcutsIgnoreString = drShortcutsFile.ReadShortcuts(shortcutsfile) self.ShortcutsUseDefault = 0 except: self.ShowMessage(("Error with: " + shortcutsfile + "\nDrPython will load the program defaults."), "Shortcuts Error") self.LoadShortcuts(True) #Load DrScript Shortcuts drscriptsshortcutsfile = self.shortcutsdirectory + "/drscript.shortcuts.dat" if os.path.exists(drscriptsshortcutsfile) and (not UseDefault): try: self.DrScriptShortcuts, self.DrScriptShortcutNames, t = drShortcutsFile.ReadShortcuts(drscriptsshortcutsfile, 0) except: self.ShowMessage("Error with: " + drscriptsshortcutsfile + "\nDrPython will not load DrScript shortcuts.", "DrScript Shortcuts Error") namelen = len (self.DrScriptShortcutNames) shortcutslen = len(self.DrScriptShortcuts) if namelen != shortcutslen: self.ShowMessage("'drscript.shortcuts.dat' (%d Entries) and 'drscript.dat' (%d Entries) file are out of sync." % (shortcutslen, namelen), "DrScript Shortcuts Error") def OnActivate(self): if self.prefs.docautoreload: x = 0 for Document in self.txtDocumentArray: if Document.filename: #Get Stat Info: if os.path.exists(Document.filename): #bug 2010127 reported by by Luca Falavigna - dktrkranz, thanks current_mtime = int(os.stat(Document.filename).st_mtime) #Check Stat Info: if Document.mtime > -1: if current_mtime != Document.mtime: if self.Ask('"%s" has been modified by an outside source. Would you like to reload?' % (Document.filename), "Reload File?"): self.setDocumentTo(x) self.OpenFile(Document.filename, False) else: Document.mtime = current_mtime x += 1 def OnCheckIndentation(self, event): wx.BeginBusyCursor() result = self.txtDocument.CheckIndentation() if result == 2: msg = "No indentation was found in this document." elif result == -1: msg = "This document uses spaces for indentation." elif result == 1: msg = "This document uses tabs for indentation." elif result == 0: msg = "This document is mixed. It uses tabs and spaces for indentation." wx.EndBusyCursor() self.ShowMessage(msg, "Check Indentation Results") def OnCheckSyntax(self, event): if self.CheckSyntax(self.docPosition): if self.prefs.enablefeedback: self.ShowMessage(self.txtDocument.GetFilename() + '\nPassed Syntax Check', 'Syntax Check Ok') else: self.SetStatusText('Passed Syntax Check', 2) def OnCleanUpSpaces(self, event): d = wx.TextEntryDialog(self, "Replace a tab with how many spaces?:", "Replace Tabs With Spaces", str(self.prefs.doctabwidth[0])) answer = d.ShowModal() value = d.GetValue() d.Destroy() if answer == wx.ID_OK: wx.BeginBusyCursor() wx.Yield() try: x = int(value) except: self.ShowMessage("You must enter an integer (number, eg 1,2,128)", "DrPython") wx.EndBusyCursor() return if (x > -1) and (x <= 128): self.txtDocument.SetToSpaces(x) else: self.ShowMessage("That number seems WAY too high. Just what are you doing, replacing a tab with more than 128 spaces?", "DrPython Foolish Error") wx.EndBusyCursor() return self.txtDocument.OnModified(None) wx.EndBusyCursor() def OnCleanUpTabs(self, event): d = wx.TextEntryDialog(self, "Number of spaces to replace with a tab:", "Replace Spaces With Tabs", str(self.prefs.doctabwidth[0])) answer = d.ShowModal() value = d.GetValue() d.Destroy() if answer == wx.ID_OK: wx.BeginBusyCursor() wx.Yield() try: x = int(value) except: self.ShowMessage("You must enter an integer (number, eg 1,2,128)", "DrPython") wx.EndBusyCursor() return if (x > -1) and (x <= 128): self.txtDocument.SetToTabs(x) else: self.ShowMessage("That number seems WAY too high. Just what are you doing, replacing more than 128 spaces with a tab?", "DrPython Foolish Error") wx.EndBusyCursor() return self.txtDocument.OnModified(None) wx.EndBusyCursor() def OnClearRecent(self, event): if self.Ask("This will clear all recent files.\nAre you sure you want to do this?", "DrPython"): self.recentfiles = [] self.DestroyRecentFileMenu() self.WriteRecentFiles() def OnClose(self, event): self.PPost(self.EVT_DRPY_FILE_CLOSING) if self.txtDocument.GetModify(): #prompt saving filename limodou 2004/04/19 answer = wx.MessageBox('Would you like to save "%s"?' % self.txtDocument.GetFilename(), "DrPython", wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION) #end limodou if answer == wx.YES: if not self.OnSave(event): return elif answer == wx.CANCEL: return #franz: oldpos is not used #11/24: :) It is now! (Adding Franz's BugFix, ironically enough). oldpos = self.docPosition oldfinder = self.txtDocumentArray[oldpos].Finder if len(self.txtDocumentArray) > 1: self.DestroyDocument() #Update txtDocument.targetPosition x = 0 l = len(self.txtDocumentArray) while x < l: self.txtDocumentArray[x].targetPosition = x x = x + 1 self.documentnotebook.DeletePage(self.docPosition) if self.docPosition > 0: self.docPosition -= 1 elif len(self.txtDocumentArray) > 1: if self.docPosition > 0: self.docPosition += 1 if self.docPosition < len(self.txtDocumentArray) -1: self.setDocumentTo(oldpos) else: self.setDocumentTo(self.docPosition, 1) #11/24: if oldpos > self.docPosition: if self.txtDocument.Finder: self.txtDocument.Finder.Copy(oldfinder) else: #Clear the current document: self.txtDocument.SetText("") self.txtDocument.filename = "" self.txtDocument.mtime = -1 self.txtDocument.EmptyUndoBuffer() self.txtDocument.SetSavePoint() self.UpdateMenuAndToolbar() #The set size stuff ensures that wx.widgets repaints the tab. x, y = self.GetSizeTuple() self.SetSize(wx.Size(x-1, y-1)) self.SetSize(wx.Size(x, y)) self.txtDocument.untitlednumber = 1 self.txtDocument.IsActive = True self.txtDocument.OnModified(None) self.documentnotebook.OnPageChanged(None) self.reloaddocumentsmenu() if self.SourceBrowser is not None: self.SourceBrowser.Browse() self.txtDocument.SetupLineNumbersMargin() self.PPost(self.EVT_DRPY_FILE_CLOSED) # Feb. 17 05 - Adding import all function def OnImportAll(self, event): """When the Import All button is clicked, get the path of each open file, and append it to sys.path, then import each file into the interpreter (via ExecuteCommands)""" if self.txtPrompt.pythonintepreter == 0: self.ExecutePython() self.promptSaveAll() x = len(self.txtDocumentArray) - 1 while x > -1: filePath = self.getFilePath(self.txtDocumentArray[x].GetFilename()) self.txtPrompt.ExecuteCommands("sys.path.append(\"" + filePath[0] + "\")") self.txtPrompt.ExecuteCommands("import " + filePath[1]) x = x - 1 def getFilePath(self, path): """Takes a path including a file name, and returns a tuple containing the path (minus file name), and just the file name.""" if path.find("\\") == -1: return (path[:path.rfind("/") + 1], path[path.rfind("/") +1:path.rfind(".")]) else: return (path[:path.rfind("\\") + 1], path[path.rfind("\\") + 1:path.rfind(".")]) # End Feb. 17 05 import all changes. # Feb. 17 05 - Adding pydoc functions def OnPyDocAll(self, event): """When the generate pydoc for all files item is selected, get the path of each open file, and append it to sys.path, then document each file (via pydoc.writedoc))""" self.promptSaveAll() # specify output directory to save html files to dir = self.promptDir("Select output directory:") if dir: cwd = os.getcwd() os.chdir(dir) # grab output of pydoc commands in a temp file oldstdout = sys.stdout fd, tempname = tempfile.mkstemp() temp = open(tempname, 'w') # go through each open file, documenting for x in range(len(self.txtDocumentArray)): filePath = self.getFilePath(self.txtDocumentArray[x].GetFilename()) sys.path.append(filePath[0]) # create html doc sys.stdout = temp pydoc.writedoc(str(filePath[1])) sys.stdout = oldstdout temp.close() temp = open(tempname, 'r') msg = temp.read() temp.close() os.chdir(cwd) # pop up a message to say it generated the file wx.MessageBox('PyDoc: \n'+msg+'\nLocation: '+dir, 'PyDoc', wx.OK) else: wx.MessageBox ("Please specify a valid directory!", "PyDoc All", wx.ICON_INFORMATION) def OnPyDocCurrent(self, event): """When the generate pydoc for current file item is selected, get the path of the current file, and append it to sys.path, then document it (via pydoc.writedoc))""" self.promptSaveCurrent() # specify output directory to save html files to dir = self.promptDir("Specify output directory:") if dir: cwd = os.getcwd() os.chdir(dir) # grab output of pydoc commands in a temp file oldstdout = sys.stdout fd, tempname = tempfile.mkstemp() temp = open(tempname, 'w') filePath = self.getFilePath(self.txtDocument.GetFilename()) sys.path.append(filePath[0]) # grab output of commands in a temp file oldstdout = sys.stdout sys.stdout = temp # create html file documenting python module pydoc.writedoc(str(filePath[1])) #pydoc.writedoc(filePath[1].encode (self.prefs.defaultencoding)) sys.stdout = oldstdout temp.close() temp = open(tempname, 'r') msg = temp.read() temp.close() # pop up a message to say it generated the file os.chdir(cwd) wx.MessageBox('PyDoc: '+msg+'Location: '+dir, 'PyDoc', wx.OK) else: wx.MessageBox ("Please specify a valid directory!", "PyDoc Current File", wx.ICON_INFORMATION, self) def OnViewPyDoc(self, event): """ Pop up PoyDoc view window, which allows the user to view pydoc in a browser for all files on the path""" self.promptSaveAll() if self.txtPrompt.pythonintepreter == 0: self.ExecutePython() self.txtPrompt.ExecuteCommands("import pydoc") for x in range(len(self.txtDocumentArray)): filePath = self.getFilePath(self.txtDocumentArray[x].GetFilename()) self.txtPrompt.ExecuteCommands("sys.path.append(\"" + filePath[0] + "\")") # pydoc gui doesn't close from within drpython, display a message to # tell the user to close it with the end button self.txtPrompt.AddText('\n***Press the red "End" button on the DrPython toolbar (or CTRL+D) to stop***\n') self.txtPrompt.ExecuteCommands("pydoc.gui()") # End Feb. 17 05 pydoc changes. def OnCloseAllDocuments(self, event): x = len(self.txtDocumentArray) - 1 while x > -1: self.setDocumentTo(x, True) if self.txtDocument.GetModify(): #prompt saving filename limodou 2004/04/19 if self.Ask('Would you like to save "%s"?' % self.txtDocument.GetFilename(), "DrPython"): #end limodou self.OnSave(event) self.OnClose(event) x = x - 1 def OnCloseAllOtherDocuments(self, event): if not self.txtDocument.filename: self.ShowMessage("Sorry, does not work when an untitled file is selected.", "DrPython Error") return farray = map(lambda document: document.filename, self.txtDocumentArray) try: i = farray.index(self.txtDocument.filename) except: #franz: (Updated Namespace) self.ShowMessage("Something went wrong trying to close all other tabs.", "DrPython Error") return x = len(farray) - 1 while x > -1: if x != i: self.setDocumentTo(x, True) if self.txtDocument.GetModify(): #prompt saveing filename limodou 2004/04/19 if self.Ask('Would you like to save "%s"?' % self.txtDocument.GetFilename(), "DrPython"): #end limodou self.OnSave(event) self.OnClose(event) x = x - 1 def OnClosePrompt(self, event): oldpos = self.promptPosition oldfinder = self.txtPromptArray[oldpos].Finder self.OnEnd(None) if len(self.txtPromptArray) > 1: self.txtPromptArray.pop(self.promptPosition) self.promptnotebook.DeletePage(self.promptPosition) if self.promptPosition > 0: self.promptPosition = self.promptPosition - 1 elif len(self.txtPromptArray) > 1: if self.promptPosition > 0: self.promptPosition = self.promptPosition + 1 self.setPromptTo(self.promptPosition) #11/24: if oldpos > self.promptPosition: if self.txtPrompt.Finder: self.txtPrompt.Finder.Copy(oldfinder) else: self.txtPrompt.SetText("") self.txtPrompt.EmptyUndoBuffer() self.txtPrompt.SetSavePoint() self.UpdateMenuAndToolbar() self.promptnotebook.SetPageText(self.promptPosition, "Prompt") #The set size stuff ensures that wx.widgets repaints the tab. x, y = self.GetSizeTuple() self.SetSize(wx.Size(x-1, y-1)) self.SetSize(wx.Size(x, y)) self.promptnotebook.OnPageChanged(None) def OnCloseW(self, event): self.ignoreevents = True if event.CanVeto(): try: x = self.docPosition if self.docPosition > 0: fromzero = self.docPosition l = len(self.txtDocumentArray) while x < l: if self.txtDocumentArray[x].GetModify(): answer = wx.MessageBox('Would you like to save "%s"?' % self.txtDocumentArray[x].GetFilename(), "DrPython", wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION) if answer == wx.YES: self.setDocumentTo(x) self.OnSave(event) elif answer == wx.CANCEL: return x = x + 1 if fromzero > 0: x = 0 l = fromzero while x < l: if self.txtDocumentArray[x].GetModify(): answer = wx.MessageBox('Would you like to save "%s"?' % self.txtDocumentArray[x].GetFilename(), "DrPython", wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION) if answer == wx.YES: self.setDocumentTo(x) self.OnSave(event) elif answer == wx.CANCEL: return x = x + 1 except: if self.prefs.alwayspromptonexit: if not self.Ask("Are you sure you want to exit? ", "DrPython"): return self.disableeventhandling = True if self.prefs.rememberwindowsizeandposition: wasMaximized = 0 if self.IsMaximized(): #only to get the right values self.Maximize(False) wasMaximized = 1 #if not self.IsMaximized(): #else some problems appears (?) try: f = file(self.datdirectory + "/drpython.sizeandposition.dat", 'w') x, y = self.GetSizeTuple() px, py = self.GetPositionTuple() f.write(str(x) + '\n' + str(y) + '\n' + str(px) + '\n' + str(py) + '\n' + str(wasMaximized)) f.close() except: self.ShowMessage("Error Saving Window Size", 'Error') self.mainpanel.MemorizePanelSizes() event.Skip() def OnCommentRegion(self, event): selstart, selend = self.txtDocument.GetSelection() #From the start of the first line selected oldcursorpos = self.txtDocument.GetCurrentPos() startline = self.txtDocument.LineFromPosition(selstart) self.txtDocument.GotoLine(startline) start = self.txtDocument.GetCurrentPos() #To the end of the last line selected #Bugfix Chris Wilson #Edited by Dan (selend fix) if selend == selstart: tend = selend else: tend = selend - 1 docstring = self.prefs.doccommentstring[self.txtDocument.filetype] end = self.txtDocument.GetLineEndPosition(self.txtDocument.LineFromPosition(tend)) #End Bugfix Chris Wilson eol = self.txtDocument.GetEndOfLineCharacter() corr = 0 l = len(self.txtDocument.GetText()) if self.prefs.doccommentmode == 0: self.txtDocument.SetSelection(start, end) text = docstring + self.txtDocument.GetSelectedText() text = text.replace(eol, eol + docstring) self.txtDocument.ReplaceSelection(text) else: mask = self.txtDocument.GetModEventMask() self.txtDocument.SetModEventMask(0) wpos = start while wpos < end: ws = self.txtDocument.GetLineIndentPosition(startline) le = self.txtDocument.GetLineEndPosition(startline) if ws != le: self.txtDocument.InsertText(ws, docstring) startline += 1 wpos = self.txtDocument.PositionFromLine(startline) self.txtDocument.SetModEventMask(mask) corr = len(self.txtDocument.GetText()) - l self.txtDocument.GotoPos(oldcursorpos + corr) def OnUnCommentRegion(self, event): #franz: pos is not used selstart, selend = self.txtDocument.GetSelection() #From the start of the first line selected startline = self.txtDocument.LineFromPosition(selstart) oldcursorpos = self.txtDocument.GetCurrentPos() self.txtDocument.GotoLine(startline) start = self.txtDocument.GetCurrentPos() #To the end of the last line selected #Bugfix Chris Wilson #Edited by Dan (selend fix) if selend == selstart: tend = selend else: tend = selend - 1 end = self.txtDocument.GetLineEndPosition(self.txtDocument.LineFromPosition(tend)) #End Bugfix Chris Wilson mask = self.txtDocument.GetModEventMask() self.txtDocument.SetModEventMask(0) lpos = start newtext = "" l = len(self.txtDocument.GetText()) ldocstring = len(self.prefs.doccommentstring[self.txtDocument.filetype]) while lpos < end: lpos = self.txtDocument.PositionFromLine(startline) line = self.txtDocument.GetLine(startline) lc = line.find(self.prefs.doccommentstring[self.txtDocument.filetype]) if lc > -1: prestyle = self.txtDocument.GetStyleAt(lpos + lc - 1) style = self.txtDocument.GetStyleAt(lpos + lc) if self.txtDocument.filetype == 1: #if not ((not (prestyle == wx.stc.STC_C_COMMENTLINE) and not (prestyle == wx.stc.STC_C_COMMENT) and not\ #(prestyle == wx.stc.STC_C_COMMENTDOC)) and \ #((style == wx.stc.STC_C_COMMENTLINE) or (style == wx.stc.STC_C_COMMENT) or (style == wx.stc.STC_C_COMMENTDOC))): if 0: newtext += line else: newtext += line[0:lc] + line[lc+ldocstring:] else: if not ((not (prestyle == wx.stc.STC_P_COMMENTLINE) and not (prestyle == wx.stc.STC_P_COMMENTBLOCK))\ and ((style == wx.stc.STC_P_COMMENTLINE) or (style == wx.stc.STC_P_COMMENTBLOCK))): newtext += line else: newtext += line[0:lc] + line[lc+ldocstring:] else: newtext += line startline += 1 lpos = self.txtDocument.PositionFromLine(startline) self.txtDocument.SetModEventMask(mask) self.txtDocument.SetSelection(start, end) self.txtDocument.ReplaceSelection(newtext.rstrip(self.txtDocument.GetEndOfLineCharacter())) corr = len(self.txtDocument.GetText()) - l self.txtDocument.GotoPos(oldcursorpos + corr) def OnCustomizePopUpMenu(self, event): from drPopUpMenuDialog import drPopUpMenuDialog d = drPopUpMenuDialog(self) d.ShowModal() d.Destroy() def OnCustomizeToolBar(self, event): from drToolBarDialog import drToolBarDialog d = drToolBarDialog(self) d.ShowModal() d.Destroy() def OnCustomizeShortcuts(self, event): from drShortcutsDialog import drShortcutsDialog d = drShortcutsDialog(self) d.ShowModal() d.Destroy() def OnDedentRegion(self, event): #Submitted Patch: Franz Steinhausler #Submitted Patch (ModEvent Mask), Franz Steinhausler beg, end = self.txtDocument.GetSelection() begline = self.txtDocument.LineFromPosition(beg) endline = self.txtDocument.LineFromPosition(end) mask = self.txtDocument.GetModEventMask() self.txtDocument.SetModEventMask(0) if begline == endline: #This section modified by Dan pos = self.txtDocument.PositionFromLine(begline) self.txtDocument.SetSelection(pos, pos) self.txtDocument.GotoPos(pos) self.txtDocument.BackTab() self.txtDocument.SetSelection(pos, self.txtDocument.GetLineEndPosition(begline)) self.txtDocument.SetModEventMask(mask) return #Submitted Patch: Christian Daven self.txtDocument.BackTab() self.txtDocument.SetModEventMask(mask) def OnEditBookmarks(self, event): from drBookmarksDialog import drBookmarksDialog d = drBookmarksDialog(self, self.datdirectory + "/bookmarks.dat") d.ShowModal() d.Destroy() self.bookmarksmenu.reloadBookmarks() def OnEditScriptMenu(self, event): from drScriptDialog import drScriptDialog d = drScriptDialog(self) d.ShowModal() d.Destroy() self.drscriptmenu.reloadscripts() def OnEnd(self, event): if self.txtPrompt.pid != -1: self.promptnotebook.SetPageImage(self.promptPosition, 2) self.UpdateMenuAndToolbar() wx.Process_Kill(self.txtPrompt.pid, wx.SIGKILL) self.txtPrompt.SetReadOnly(1) def OnExit(self, event): self.Close(False) def OnExpandAll(self, event): if self.prefs.docfolding[self.txtDocument.filetype]: wx.BeginBusyCursor() self.txtDocument.FoldAll(True) wx.EndBusyCursor() def OnFindAndComplete(self, event): #Submitted Patch by Martinho #now stops at '.' (repre) #re-ordered the text so the list shows the nearer completion words first. #Get The Current Word text = self.txtDocument.GetText() pos = self.txtDocument.GetCurrentPos() repre = re.compile("\(|\)|\[|\]|\{|\}|\<|\>|\.", re.IGNORECASE | re.MULTILINE) regex = re.compile("\w*\Z", re.IGNORECASE | re.MULTILINE) #franz: regexend is not used eol = self.txtDocument.GetEndOfLineCharacter() #Get the left bit i = text[0:pos].rfind(eol) if i == -1: i = 0 else: i = i + len(eol) #Check for characters to stop at. t = re.finditer(repre, text[i:pos]) if t is not None: try: preresult = t.next() except: preresult = None try: while t.next() is not None: preresult = t.next() except: if preresult is not None: t = i + preresult.start() + 1 #If t == pos, then you do not want to stop #at the character. if t < pos: i = t #Find Non Whitespace Characters. result = regex.search(text[i:pos]) if result is None: start = i else: start = i + result.start() if (pos - start) <= 0: return #Handle special characters oword = text[start:pos] word = oword.replace('\\', "\\\\").replace('^', "\\^").replace('*', "\\*").replace('$', "\\$") word = word.replace('+', "\\+").replace('?', "\\?").replace('{', "\\{").replace('}', "\\}") word = word.replace('[', "\\[").replace(']', "\\]").replace('(', "\\(").replace(')', "\\)") word = word.replace('.', "\\.").replace('|', "\\|").replace('<', "\\<").replace('>', "\\>") #Find all matches in the document. findandcompleteregex = re.compile(r"\b" + word + r"\w*\b", re.MULTILINE) text_lines = text.split(eol) cl = self.txtDocument.GetCurrentLine() s_i = cl e_i = cl sorted_text = "" while (s_i>=0) or (e_i < len(text_lines)): if s_i>=0 : sorted_text += text_lines[s_i] + eol s_i = s_i - 1 if e_i < len(text_lines) : sorted_text += text_lines[e_i] + eol e_i = e_i + 1 r = findandcompleteregex.findall(sorted_text) results = "" tr = [] for item in r: try: tr.index(item) except: if not item == oword: results = results + " " + item tr.append(item) results = results.strip() if tr: try: self.txtDocument.AutoCompShow(len(oword), results) except: #What is this mess? pass def OnFoldAll(self, event): if self.prefs.docfolding[self.txtDocument.filetype]: wx.BeginBusyCursor() self.txtDocument.FoldAll(False) wx.EndBusyCursor() def OnFormatMacMode(self, event): wx.BeginBusyCursor() wx.Yield() self.txtDocument.SetEOLMode(wx.stc.STC_EOL_CR) text = self.txtDocument.GetText() text = self.FormatMacReTarget.sub('\r', text) self.txtDocument.SetText(text) self.txtDocument.OnModified(None) wx.EndBusyCursor() def OnFormatUnixMode(self, event): wx.BeginBusyCursor() wx.Yield() self.txtDocument.SetEOLMode(wx.stc.STC_EOL_LF) text = self.txtDocument.GetText() text = self.FormatUnixReTarget.sub('\n', text) self.txtDocument.SetText(text) self.txtDocument.OnModified(None) wx.EndBusyCursor() def OnFormatWinMode(self, event): wx.BeginBusyCursor() wx.Yield() self.txtDocument.SetEOLMode(wx.stc.STC_EOL_CRLF) text = self.txtDocument.GetText() text = self.FormatWinReTarget.sub('\r\n', text) self.txtDocument.SetText(text) self.txtDocument.OnModified(None) wx.EndBusyCursor() def CenterCurrentLine(self, linenr): self.txtDocument.EnsureVisible(linenr) #patch: [ 1366679 ] Goto Line Should Not Display At Top Of Window #self.txtDocument.ScrollToLine(v) top = linenr - self.txtDocument.LinesOnScreen()/2 if top < 0: top = 0 self.txtDocument.ScrollToLine(top) #self.txtDocument.GotoLine(linenr) def OnGoTo(self, event): d = wx.TextEntryDialog(self, "Go To Line Number:", "DrPython - Go To", "") answer = d.ShowModal() v = d.GetValue() d.Destroy() if answer == wx.ID_OK: try: v = int(v) - 1 if (v >= 0) and (v < self.txtDocument.GetLineCount()): self.CenterCurrentLine(v) self.txtDocument.GotoLine(v) else: drScrolledMessageDialog.ShowMessage(self, "That line does not exist", "DrPython Error") except StandardError: drScrolledMessageDialog.ShowMessage(self, "You must enter an integer (1, 2, 3, etc)", "DrPython Error") def OnGoToBlockEnd(self, event): drGetBlockInfo.GoToBlockEnd(self.txtDocument) def OnGoToBlockStart(self, event): drGetBlockInfo.GoToBlockStart(self.txtDocument) def OnGoToClassEnd(self, event): drGetBlockInfo.GoToBlockEnd(self.txtDocument, 'class') def OnGoToClassStart(self, event): drGetBlockInfo.GoToBlockStart(self.txtDocument, 'class') def OnGoToDefEnd(self, event): drGetBlockInfo.GoToBlockEnd(self.txtDocument, 'def') def OnGoToDefStart(self, event): drGetBlockInfo.GoToBlockStart(self.txtDocument, 'def') def OnIndentRegion(self, event): #Submitted Patch: Franz Steinhausler #Submitted Patch (ModEvent Mask), Franz Steinhausler beg, end = self.txtDocument.GetSelection() begline = self.txtDocument.LineFromPosition(beg) endline = self.txtDocument.LineFromPosition(end) mask = self.txtDocument.GetModEventMask() self.txtDocument.SetModEventMask(0) if begline == endline: #This section modified by Dan pos = self.txtDocument.PositionFromLine(begline) self.txtDocument.SetSelection(pos, pos) self.txtDocument.GotoPos(pos) self.txtDocument.Tab() self.txtDocument.SetSelection(pos, self.txtDocument.GetLineEndPosition(begline)) self.txtDocument.SetModEventMask(mask) return #Submitted Patch: Christian Daven self.txtDocument.Tab() self.txtDocument.SetModEventMask(mask) def OnInsertRegEx(self, event): from drRegularExpressionDialog import drRegularExpressionDialog d = drRegularExpressionDialog(self, -1, "Insert Regular Expression", self.txtPrompt.GetSTCFocus()) d.Show() def OnInsertSeparator(self, event): d = drSeparatorDialog(self, 'Insert Separator') answer = d.ShowModal() label = d.GetLabel() d.Destroy() if answer == wx.ID_OK: pos = self.txtDocument.GetCurrentPos() self.txtDocument.InsertText(pos, label) self.txtDocument.GotoPos(pos + len(label)) def OnKeyDown(self, event): self.RunShortcuts(event) event.Skip() def OnLowercase(self, event): if self.txtPrompt.GetSTCFocus(): self.txtPrompt.CmdKeyExecute(wx.stc.STC_CMD_LOWERCASE) else: self.txtDocument.CmdKeyExecute(wx.stc.STC_CMD_LOWERCASE) def OnMenuFind(self, event): stc = self.GetActiveSTC() d = drFindReplaceDialog(self, -1, "Find", stc) d.SetOptions(self.FindOptions) if stc.GetSelectionStart() < stc.GetSelectionEnd(): d.SetFindString(stc.GetSelectedText()) elif self.prefs.findreplaceundercursor: pos = stc.GetCurrentPos() d.SetFindString(stc.GetTextRange(stc.WordStartPosition(pos, 1), stc.WordEndPosition(pos, 1))) d.Show(True) def OnMenuFindNext(self, event): self.GetActiveSTC().Finder.DoFindNext() def OnMenuFindPrevious(self, event): self.GetActiveSTC().Finder.DoFindPrevious() def OnMenuReplace(self, event): stc = self.GetActiveSTC() d = drFindReplaceDialog(self, -1, "Replace", stc, 1) d.SetOptions(self.ReplaceOptions) if stc.GetSelectionStart() < stc.GetSelectionEnd(): d.SetFindString(stc.GetTextRange(stc.GetSelectionStart(), stc.GetSelectionEnd())) else: d.SetFindString(stc.Finder.GetFindText()) d.Show(True) def OnNew(self, event): l = len(self.txtDocumentArray) unumbers = map(lambda x: x.untitlednumber, self.txtDocumentArray) unumbers.sort() x = 0 last = 0 while x < l: if unumbers[x] > 0: if unumbers[x] != (last + 1): x = l else: last = unumbers[x] x = x + 1 else: x = x + 1 last = last + 1 nextpage = drPanel(self.documentnotebook, self.ID_APP) self.txtDocumentArray.append(DrText(nextpage, self.ID_APP, self)) nextpage.SetSTC(self.txtDocumentArray[l]) self.documentnotebook.AddPage(nextpage, "Untitled " + str(last)) self.txtDocumentArray[l].untitlednumber = last self.txtDocumentArray[l].Finder.Copy(self.txtDocument.Finder) self.lastprogargsArray.append("") self.txtDocumentArray[l].SetTargetPosition(l) self.txtDocument.IsActive = False self.txtDocument.OnModified(None) self.setDocumentTo(l) self.txtDocument.SetupPrefsDocument(1) self.reloaddocumentsmenu() self.txtDocument.SetSTCFocus(True) self.PPost(self.EVT_DRPY_NEW) def OnNewPrompt(self, event): l = len(self.txtPromptArray) nextpage = drPanel(self.promptnotebook, self.ID_APP) self.txtPromptArray.append(DrPrompt(nextpage, self.ID_APP, self)) nextpage.SetSTC(self.txtPromptArray[l]) self.promptnotebook.AddPage(nextpage, "Prompt") self.txtPromptArray[l].Finder.Copy(self.txtPrompt.Finder) self.setPromptTo(l) self.txtPrompt.SetupPrefsPrompt(1) self.txtPrompt.SetSTCFocus(True) self.PPost(self.EVT_DRPY_NEW_PROMPT) def OnOpen(self, event): dlg = drFileDialog.FileDialog(self, "Open", self.prefs.wildcard, MultipleSelection=True, ShowRecentFiles=True) if self.ddirectory: try: dlg.SetDirectory(self.ddirectory) except: #self.ShowMessage("Error Setting Default Directory To: " + self.ddirectory, "DrPython Error") #don't care, when next files are opened, ddirectory will be set properly. pass if dlg.ShowModal() == wx.ID_OK: filenames = dlg.GetPaths() filenames = map(lambda x: x.replace("\\", '/'), filenames) for fname in filenames: self.OpenOrSwitchToFile(fname, encoding=dlg.GetEncoding()) dlg.Destroy() def OnOpenImportedModule(self, event): from drOpenImportedModuleDialog import drOpenImportedModuleDialog, GetModulePath, ParseImportStatement text = self.txtDocument.GetText() importmatches = self.reimport.findall(text) fromimportmatches = self.refromimport.findall(text) modulelist = [] rmodulelist = [] imatchesarray = ParseImportStatement(importmatches) for imatch in imatchesarray: rmodulelist.extend(imatch) fmatchesarray = ParseImportStatement(fromimportmatches) for fmatch in fmatchesarray: rmodulelist.extend(fmatch) for mod in rmodulelist: modulelist.append(mod.strip(',')) docpath = os.path.split(self.txtDocument.filename)[0] pathlist = [] x = 0 l = len(modulelist) while x < l: if modulelist.count(modulelist[x]) > 1: modulelist.pop(x) x -= 1 l -= 1 else: n, mpath = GetModulePath(docpath, modulelist[x], self.PLATFORM_IS_WIN) if mpath is None: modulelist.pop(x) x -= 1 l -= 1 else: pathlist.append([n, mpath]) x = x + 1 modulelist.sort() pathdictionary = dict(pathlist) d = drOpenImportedModuleDialog(self, modulelist) answer = d.ShowModal() d.Destroy() if answer == wx.ID_OK: selectedmodule = d.GetSelectedModule() modulefile = pathdictionary[selectedmodule] self.OpenOrSwitchToFile(modulefile) def OpenOrSwitchToFile(self, filename, editRecentFiles=True, encoding=''): filename = filename.replace("\\", "/") alreadyopen = self.GetAlreadyOpen() if filename.lower() in alreadyopen: self.setDocumentTo(alreadyopen.index(filename.lower())) else: if not os.path.exists(filename): self.ShowMessage('"' + filename + '" Does Not Exist.', "File not found") else: if len(self.txtDocument.filename) > 0 or self.txtDocument.GetModify(): self.OpenFile(filename, True, editRecentFiles, encoding) else: self.OpenFile(filename, False, editRecentFiles, encoding) def OnOpenRecentFile(self, event): recentmenuindex = event.GetId() - self.ID_RECENT_FILES_BASE self.OpenOrSwitchToFile(self.recentfiles[recentmenuindex]) def OnPrefs(self, event): from drPrefsDialog import drPrefsDialog d = drPrefsDialog(self, -1, "DrPython - Preferences") d.ShowModal() d.Destroy() def OnPrint(self, event): self.Printer.Print(self.txtDocument.GetText(), self.txtDocument.filename, self.prefs.printdoclinenumbers) def OnPrintSetup(self, event): self.Printer.PrinterSetup(self) def OnPrintPrompt(self, event): self.Printer.Print(self.txtPrompt.GetText(), self.txtDocument.filename, self.prefs.printpromptlinenumbers) def OnProcessEnded(self, event): #Set the process info to the correct position in the array. i = 0 epid = event.GetPid() try: i = map(lambda tprompt: tprompt.pid == epid, self.txtPromptArray).index(True) except: return #First, check for any leftover output. self.txtPromptArray[i].OnIdle(event) #If this is the process for the current window: if self.promptPosition == i: self.txtPrompt.process.Destroy() self.txtPrompt.process = None self.txtPrompt.pid = -1 self.txtPrompt.SetReadOnly(1) self.txtPrompt.pythonintepreter = 0 self.UpdateMenuAndToolbar() self.SetStatusText("", 2) self.promptnotebook.SetPageImage(i, 2) else: self.txtPromptArray[i].process.Destroy() self.txtPromptArray[i].process = None self.txtPromptArray[i].pid = -1 self.txtPromptArray[i].SetReadOnly(1) self.txtPromptArray[i].pythonintepreter = 0 self.promptnotebook.SetPageImage(i, 0) self.txtDocument.SetFocus() def OnPython(self, event): if self.prefs.defaultencoding == "cp1252": self.ShowMessage("Python Interpreter with encoding cp1252 not possible, otherwise the program crashes.\nPlease change the encoding in preferences for the python interpreter", "DrPython Error") return self.ExecutePython() def OnRedo(self, event): if self.txtPrompt.GetSTCFocus(): self.txtPrompt.Redo() else: self.txtDocument.Redo() def OnReload(self, event, ask = True): if self.Ask("This will reload the current file.\nAny changes will be lost.\nAre you sure you want to do this?", "DrPython"): if self.txtDocument.filename: pos = self.txtDocument.GetCurrentPos() self.OpenFile(self.txtDocument.filename, False) self.txtDocument.SetCurrentPos(pos) event.Skip() def OnRestoreFromBackup(self, event): if os.path.exists(self.txtDocument.filename + ".bak"): if self.Ask("This will restore the current file from the last backup.\nAny changes will be lost.\nAre you sure you want to do this?", "DrPython"): if self.txtDocument.filename: old = self.txtDocument.filename filename = self.txtDocument.filename + ".bak" self.OpenFile(filename, False, False) self.txtDocument.filename = old self.txtDocument.OnModified(None) else: self.ShowMessage(("No Backup File For: \"" + self.txtDocument.filename + "\""), "DrPython Error") def OnRun(self, event): #patch [ 1367222 ] Improved Run Command + HTML Browser if not self.txtDocument.filename: return if self.txtDocument.GetModify(): if self.prefs.saveonrun or self.Ask("The file has been modified and must " + "be saved before it can be run.\nWould you like to save it?", "DrPython"): if not self.OnSave(event): return else: return root, ext = os.path.splitext(self.txtDocument.filename) if ext == ".htm" or ext == ".html": drHtmlBrowser.ShowHtmlFile(self, self.txtDocument.filename) return cdir, filen = os.path.split(self.txtDocument.filename) cwd = os.getcwd() try: os.chdir(cdir) except: self.ShowMessage("Error Setting current directory for Python.", "DrPython RunError") largs = "" if (len(self.lastprogargs) > 0): largs = ' ' + self.lastprogargs if self.PLATFORM_IS_WIN: self.runcommand((self.pythexecw + " -u " + self.prefs.pythonargs + ' "' + self.txtDocument.filename.replace("\\", "/") + '"' + largs), "Running " + filen, filen) else: self.runcommand((self.pythexec + " -u " + self.prefs.pythonargs + ' "' + self.txtDocument.filename + '"' + largs), "Running " + filen, filen) #patch: [ 1366679 ] Goto Line Should Not Display At Top Of Window os.chdir(cwd) def OnSave(self, event): if not self.txtDocument.filename: return self.OnSaveAs(event) else: self.SaveFile(self.docPosition) if self.prefs.sourcebrowserautorefreshonsave and (self.SourceBrowser is not None): self.SourceBrowser.Browse() return True def OnSaveAll(self, event): oldpos = self.docPosition x = 0 if self.prefs.promptonsaveall: tosaveArray = [] tosaveLabels = [] for document in self.txtDocumentArray: if self.txtDocumentArray[x].GetModify(): tosaveArray.append(x) tosaveLabels.append(self.txtDocumentArray[x].GetFilenameTitle()) x += 1 if not tosaveLabels: self.ShowMessage('No Modified Documents.', 'Save All') return d = wx.lib.dialogs.MultipleChoiceDialog(self, "Save All Modified Documents?", "Save All", tosaveLabels, size=(300, 300)) l = len(tosaveArray) y = 0 while y < l: d.lbox.SetSelection(y) y += 1 answer = d.ShowModal() selections = d.GetValue() d.Destroy() if answer == wx.ID_OK: for selection in selections: if not self.txtDocumentArray[tosaveArray[selection]].filename: self.setDocumentTo(tosaveArray[selection]) self.OnSaveAs(None) else: self.SaveFile(tosaveArray[selection]) else: return False else: for document in self.txtDocumentArray: if self.txtDocumentArray[x].GetModify(): if not self.txtDocumentArray[x].filename: self.setDocumentTo(x) self.OnSaveAs(None) else: self.SaveFile(x) x += 1 self.setDocumentTo(oldpos) return True def OnSaveAs(self, event): dlg = drFileDialog.FileDialog(self, "Save File As", self.prefs.wildcard, IsASaveDialog=True) if self.ddirectory: try: dlg.SetDirectory(self.ddirectory) except: #franz: ddirectory self.ShowMessage(("Error Setting Default Directory To: " + self.ddirectory), "DrPython Error") if dlg.ShowModal() == wx.ID_OK: old = self.txtDocument.filename if self.txtDocument.untitlednumber > 0: self.txtDocument.untitlednumber = -1 self.txtDocument.filename = dlg.GetPath().replace("\\", "/") self.ddirectory = os.path.dirname(self.txtDocument.filename) self.DestroyRecentFileMenu() if not self.SaveFile(self.docPosition, not (old == self.txtDocument.filename)): self.txtDocument.filename = old self.CreateRecentFileMenu() return self.UpdateMenuAndToolbar() #Highlighting if not self.prefs.doconlyusedefaultsyntaxhighlighting: if self.checkiffileisPython(self.txtDocument.filename): #Python self.txtDocument.filetype = 0 self.highlightmenu.Check(self.ID_HIGHLIGHT_PYTHON, True) elif self.checkiffileisCPP(self.txtDocument.filename): #C/C++ self.txtDocument.filetype = 1 self.highlightmenu.Check(self.ID_HIGHLIGHT_CPP, True) elif self.checkiffileisHTML(self.txtDocument.filename): #HTML self.txtDocument.filetype = 2 self.highlightmenu.Check(self.ID_HIGHLIGHT_HTML, True) elif self.checkiffileisPlainText(self.txtDocument.filename): #Plain Text self.txtDocument.filetype = 3 self.highlightmenu.Check(self.ID_HIGHLIGHT_PLAIN_TEXT, True) else: #Default pass self.txtDocument.SetupPrefsDocument() #Update Recent Files if self.recentfiles.count(self.txtDocument.filename) != 0: self.recentfiles.remove(self.txtDocument.filename) if len(self.recentfiles) == self.prefs.recentfileslimit: self.recentfiles.pop() self.recentfiles.insert(0, self.txtDocument.filename) self.WriteRecentFiles() self.CreateRecentFileMenu() dlg.Destroy() self.reloaddocumentsmenu() #Refreshes the tab. x, y = self.documentnotebook.GetSizeTuple() self.documentnotebook.SetSize(wx.Size(x+1, y+1)) self.documentnotebook.SetSize(wx.Size(x, y)) else: return False return True def OnSaveCopy(self, event): #add feature to save a copy, midtoad 2005-10-03 dlg = drFileDialog.FileDialog(self, "Save Copy To", self.prefs.wildcard, IsASaveDialog=True) if self.ddirectory: try: dlg.SetDirectory(self.ddirectory) except: self.ShowMessage(("Error Setting Default Directory To: " + self.ddirectory), "DrPython Error") if dlg.ShowModal() == wx.ID_OK: cfilename = dlg.GetPath().replace("\\", "/") self.ddirectory = os.path.dirname(cfilename) try: shutil.copyfile(self.txtDocument.filename, cfilename) self.ShowMessage("Saved %s to %s" % (self.txtDocument.filename, cfilename), "Save as Copy") except IOError: self.ShowMessage(("Error copying file to: " + cfilename), "DrPython Error") dlg.Destroy() def OnSavePrompt(self, event): dlg = drFileDialog.FileDialog(self, 'Save Prompt Text To', 'Text File (*.txt)|*.txt|All files (*)|*', IsASaveDialog=True) if self.ddirectory: try: dlg.SetDirectory(self.ddirectory) except: #franz: ddirectory self.ShowMessage(("Error Setting Default Directory To: " + self.ddirectory), "DrPython Error") if dlg.ShowModal() == wx.ID_OK: pfilename = dlg.GetPath().replace("\\", "/") self.ddirectory = os.path.dirname(pfilename) try: ctext = drEncoding.DecodeText(self, self.txtPrompt.GetText()) cfile = file(pfilename, 'wb') cfile.write(ctext) cfile.close() except: self.ShowMessage(("Error Writing: " + pfilename), "DrPython Error") dlg.Destroy() def OnSelectAll(self, event): if self.txtPrompt.GetSTCFocus(): self.txtPrompt.SelectAll() else: self.txtDocument.SelectAll() def OnSelectDocument(self, event): eid = event.GetId() i = eid - self.ID_DOCUMENTS_BASE self.documentnotebook.SetSelection(i) #self.documentnotebook.SetTab() def OnSelectDocumentFirst(self, event): self.documentnotebook.SetSelection(0) #self.documentnotebook.SetTab() def OnSelectDocumentLast(self, event): self.documentnotebook.SetSelection(self.documentnotebook.GetPageCount()-1) #self.documentnotebook.SetTab() def OnSelectDocumentNext(self, event): self.documentnotebook.AdvanceSelection(True) #self.documentnotebook.SetTab() def OnSelectDocumentPrevious(self, event): self.documentnotebook.AdvanceSelection(False) #self.documentnotebook.SetTab() def OnSetArgs(self, event): d = wx.TextEntryDialog(self, "Arguments:", "DrPython - Set Arguments", self.lastprogargs) if d.ShowModal() == wx.ID_OK: self.lastprogargs = d.GetValue() self.lastprogargsArray[self.docPosition] = self.lastprogargs d.Destroy() def OnSourceBrowserGoTo(self, event): drSourceBrowserGoTo.SourceBrowserGoTo(self, self.txtDocument) def OnSyntaxHighlightingPython(self, event): self.txtDocument.filetype = 0 self.txtDocument.SetupPrefsDocument() def OnSyntaxHighlightingCPP(self, event): self.txtDocument.filetype = 1 self.txtDocument.SetupPrefsDocument() def OnSyntaxHighlightingHTML(self, event): self.txtDocument.filetype = 2 self.txtDocument.SetupPrefsDocument() def OnSyntaxHighlightingText(self, event): self.txtDocument.filetype = 3 self.txtDocument.SetupPrefsDocument() def OnToggleFold(self, event): try: self.txtDocument.ToggleFold(self.txtDocument.GetCurrentLine()) except: self.ShowMessage('Error Folding Line', 'Fold Error') def OnTogglePrompt(self, event): if self.mainpanel.PromptIsVisible: self.mainpanel.PromptIsVisible = False if self.hasToolBar: self.toolbar.ToggleTool(self.ID_TOGGLE_PROMPT, False) self.mainpanel.OnSize(None) self.txtDocument.SetFocus() else: self.mainpanel.PromptIsVisible = True if self.hasToolBar: self.toolbar.ToggleTool(self.ID_TOGGLE_PROMPT, True) self.mainpanel.OnSize(None) self.txtPrompt.SetFocus() def OnToggleSourceBrowser(self, event): if self.SourceBrowser is None: target, i = self.mainpanel.GetTargetNotebookPage(self.prefs.sourcebrowserpanel, 'Source Browser') self.SourceBrowser = drSourceBrowserPanel(target, -1, self.prefs.sourcebrowserpanel, i) self.mainpanel.SetPanelSize(self.prefs.sourcebrowserpanel, self.prefs.sourcebrowsersize) target.SetPanel(self.SourceBrowser) self.mainpanel.ShowPanel(self.prefs.sourcebrowserpanel, i) else: if not self.mainpanel.IsVisible(self.SourceBrowser.position, self.SourceBrowser.Index): self.SourceBrowser.Browse() self.mainpanel.TogglePanel(self.SourceBrowser.position, self.SourceBrowser.Index) def OnToggleViewWhiteSpace(self, event): if self.txtPrompt.GetSTCFocus(): c = self.txtPrompt.GetViewWhiteSpace() self.txtPrompt.SetViewWhiteSpace(not c) if self.prefs.vieweol: self.txtPrompt.SetViewEOL(not c) else: c = self.txtDocument.GetViewWhiteSpace() self.txtDocument.SetViewWhiteSpace(not c) if self.prefs.vieweol: self.txtDocument.SetViewEOL(not c) def OnOpenWidgetInspector(self, evt): if self.prefs.debugmodus: # Activate the widget inspection tool try: from wx.lib.inspection import InspectionTool except: self.ShowMessage(("Inspect Tool not found\nPlease check your wxPython version!"), "DrPython Error") return if not InspectionTool().initialized: InspectionTool().Init() # Find a widget to be selected in the tree. Use either the # one under the cursor, if any, or this frame. wnd = wx.FindWindowAtPointer() if not wnd: wnd = self InspectionTool().Show(wnd, True) else: self.ShowMessage("Please switch on debug modus in preferences menu", "DrPython Error") def OnToolBar(self, event): try: i = event.GetId() - self.ID_OTHER txt = self.ToolBarList[i] if txt in self.stcshortcutlist: pos = self.stcshortcutlist.index(txt) if self.txtPrompt.GetSTCFocus(): self.txtPrompt.CmdKeyExecute(self.txtPrompt.STCCOMMANDLIST[pos]) else: self.txtDocument.CmdKeyExecute(self.txtDocument.STCCOMMANDLIST[pos]) else: if txt in self.PluginToolBarLabels: pos = self.PluginToolBarLabels.index(txt) self.PluginToolBarFunctions[pos](event) except: self.ShowMessage("ToolBar Action Error", "DrPython Error") def OnUndo(self, event): if self.txtPrompt.GetSTCFocus(): self.txtPrompt.Undo() else: self.txtDocument.Undo() def OnUppercase(self, event): if self.txtPrompt.GetSTCFocus(): self.txtPrompt.CmdKeyExecute(wx.stc.STC_CMD_UPPERCASE) else: self.txtDocument.CmdKeyExecute(wx.stc.STC_CMD_UPPERCASE) def OnViewAbout(self, event): import drAboutDialog drAboutDialog.Show(self) def OnViewHelp(self, event): self.ViewURLInBrowser(self.programdirectory + "/documentation/help.html") def OnViewInLeftPanel(self, event): self.viewinpaneltarget = 0 self.ViewInPanelMenu(event) def OnViewInRightPanel(self, event): self.viewinpaneltarget = 1 self.ViewInPanelMenu(event) def OnViewInTopPanel(self, event): self.viewinpaneltarget = 2 self.ViewInPanelMenu(event) def OnViewPythonDocs(self, event): self.ViewURLInBrowser(self.prefs.documentationpythonlocation) def OnViewREHowtoDocs(self, event): self.ViewURLInBrowser(self.prefs.documentationrehowtolocation) def OnViewWxWidgetsDocs(self, event): self.ViewURLInBrowser(self.prefs.documentationwxwidgetslocation) def OnZoomIn(self, event): if self.txtPrompt.GetSTCFocus(): zoom = self.txtPrompt.GetZoom() if zoom < 20: self.txtPrompt.SetZoom(zoom + 1) else: zoom = self.txtDocument.GetZoom() if zoom < 20: self.txtDocument.SetZoom(zoom + 1) def OnZoomOut(self, event): if self.txtPrompt.GetSTCFocus(): zoom = self.txtPrompt.GetZoom() if zoom > -9: self.txtPrompt.SetZoom(zoom - 1) else: zoom = self.txtDocument.GetZoom() if zoom > -9: self.txtDocument.SetZoom(zoom - 1) def OpenFile(self, filename, OpenInNewTab, editrecentfiles = True, encoding=''): wx.BeginBusyCursor() self.PPost(self.EVT_DRPY_FILE_OPENING) filename = os.path.abspath(filename).replace("\\", '/') if not os.path.exists(filename): self.ShowMessage("Error Opening: " + filename + " (File not exist)", "DrPython Error") wx.EndBusyCursor() return try: cfile = file(filename, 'rb') except: self.ShowMessage("Error Opening: " + filename , "DrPython Error") wx.EndBusyCursor() return if (self.txtDocument.untitlednumber > 0) and not OpenInNewTab: self.txtDocument.untitlednumber = -1 if editrecentfiles: self.DestroyRecentFileMenu() if self.recentfiles.count(filename) != 0: self.recentfiles.remove(filename) if len(self.recentfiles) == self.prefs.recentfileslimit: self.recentfiles.pop() self.recentfiles.insert(0, filename) self.WriteRecentFiles() if (((not (self.txtDocument.filename == filename))) and (self.txtDocument.GetModify())) or OpenInNewTab: self.OnNew(None) self.txtDocumentArray[self.docPosition].filename = filename self.txtDocumentArray[self.docPosition].untitlednumber = -1 try: oof = cfile.read() if not self.prefs.doconlyusedefaultsyntaxhighlighting: if self.checkiffileisPython(filename): #Python self.txtDocument.filetype = 0 self.highlightmenu.Check(self.ID_HIGHLIGHT_PYTHON, True) elif self.checkiffileisCPP(filename): #C/C++ self.txtDocument.filetype = 1 self.highlightmenu.Check(self.ID_HIGHLIGHT_CPP, True) elif self.checkiffileisHTML(filename): #HTML self.txtDocument.filetype = 2 self.highlightmenu.Check(self.ID_HIGHLIGHT_HTML, True) elif self.checkiffileisPlainText(filename): #Plain Text self.txtDocument.filetype = 3 self.highlightmenu.Check(self.ID_HIGHLIGHT_PLAIN_TEXT, True) else: #Default pass self.txtDocument.SetupPrefsDocument() #Encoding try: oof, e = drEncoding.EncodeText(self, oof, encoding, True) self.txtDocument.SetText(oof) self.txtDocument.SetEncoding(e) except: self.ShowMessage('There was an error opening the document %s.' % (filename), 'Open Error') wx.EndBusyCursor() self.OnClose(None) return self.txtDocument.EmptyUndoBuffer() self.txtDocument.SetSavePoint() cfile.close() self.txtDocument.SetupLineNumbersMargin() #Indentation Type: self.txtDocument.indentationtype = self.txtDocument.CheckIndentation() #Save Stat Info: self.txtDocument.mtime = int(os.stat(filename).st_mtime) self.txtDocument.SetScrollWidth(1) self.UpdateMenuAndToolbar() #Indentation if self.prefs.docusefileindentation: indentation = self.txtDocument.CheckIndentation(oof) if self.prefs.checkindentation: if self.prefs.docusetabs[self.txtDocument.filetype]: i = 1 else: i = -1 if (indentation != i) and (indentation != 2): answer = self.Ask((filename + ' is currently '\ + self.TABMESSAGE[indentation+1] + ".\nWould you like to change it to the default?\nThe Default is: " + self.TABMESSAGE[i+1]), "Indentation Not Default") if answer: indentation = i if i == 1: self.txtDocument.SetToTabs(self.prefs.doctabwidth[self.txtDocument.filetype]) else: self.txtDocument.SetToSpaces(self.prefs.doctabwidth[self.txtDocument.filetype]) if indentation == -1: usetabs = False elif indentation == 1: usetabs = True else: usetabs = self.prefs.docusetabs[self.txtDocument.filetype] self.txtDocument.SetUseTabs(usetabs) self.txtDocument.SetupTabs(usetabs) #Line Endings self.txtDocument.lineendingsaremixed = 0 winresult = self.relewin.search(oof) unixresult = self.releunix.search(oof) macresult = self.relemac.search(oof) win = winresult is not None unix = unixresult is not None mac = macresult is not None if (win + unix + mac) > 1: #Which came first, unix, mac, or win? first = -1 useemode = 0 if winresult is not None: first = winresult.start() useemode = 1 if unixresult is not None: if first == -1: first = unixresult.start() else: i = unixresult.start() if i < first: first = i useemode = 0 if macresult is not None: if first == -1: first = macresult.start() else: i = macresult.start() if i < first: first = i useemode = 2 self.txtDocument.lineendingsaremixed = 1 emodenum = useemode else: if win: emodenum = 1 elif unix: emodenum = 0 elif mac: emodenum = 2 else: emodenum = self.prefs.doceolmode[self.txtDocument.filetype] self.txtDocument.lineendingsaremixed = 0 dmodenum = self.prefs.doceolmode[self.txtDocument.filetype] if self.prefs.checkeol: if not emodenum == self.prefs.doceolmode[self.txtDocument.filetype]: if self.txtDocument.lineendingsaremixed: answer = self.Ask((filename + " is currently "+ self.FFMESSAGE[emodenum] + "(Mixed).\nWould you like to change it to the default?\n(Since the file is mixed, this is highly recommended.\nThe Default is: " + self.FFMESSAGE[dmodenum]), "Mixed Line Ending") else: answer = self.Ask((filename + " is currently " + self.FFMESSAGE[emodenum] + ".\nWould you like to change it to the default? The Default is: " + self.FFMESSAGE[dmodenum]), "Line Ending") if answer: #Bugfix, Thanks Stephen Anderson. if self.prefs.doceolmode[self.txtDocument.filetype] == 1: self.OnFormatWinMode(None) elif self.prefs.doceolmode[self.txtDocument.filetype] == 2: self.OnFormatMacMode(None) else: self.OnFormatUnixMode(None) self.txtDocument.lineendingsaremixed = 0 emodenum = dmodenum if emodenum == 1: emode = wx.stc.STC_EOL_CRLF elif emodenum == 2: emode = wx.stc.STC_EOL_CR else: emode = wx.stc.STC_EOL_LF self.txtDocument.SetEOLMode(emode) #/Line Endings #Scrolling lines = oof.split(self.txtDocument.GetEndOfLineCharacter()) spaces = "\t".expandtabs(self.prefs.doctabwidth[self.txtDocument.filetype]) line = '' length = 0 x = 0 for l in lines: if len(l) > length: line = l length = len(l) x += 1 line = line.replace('\t', spaces) + '000' scrollwidth = self.txtDocument.TextWidth(wx.stc.STC_STYLE_DEFAULT, line) self.txtDocument.SetScrollWidth(scrollwidth) self.txtDocument.SetXOffset(0) #/End Scrolling self.txtDocument.OnModified(None) #Load SourceBrowser: if self.prefs.sourcebrowserisvisible: self.ShowSourceBrowser() #Refresh SourceBrowser: if self.SourceBrowser is not None: self.SourceBrowser.Browse() if editrecentfiles: self.ddirectory = os.path.dirname(filename) except: self.ShowMessage("Error Opening: " + filename + "Processing failed" , "DrPython Error") #The following chunk of code is an ugly way to work around a bug in wx.STC. #As things stand, word wrap may not update on file load. #This fixes the problem, by forcing drpython to reset the wx.STC instances. if self.prefs.docwordwrap: x, y = self.GetSizeTuple() self.SetSize(wx.Size(x+1, y+1)) self.SetSize(wx.Size(x, y)) #End of the chunk. self.reloaddocumentsmenu() if editrecentfiles: self.CreateRecentFileMenu() self.PPost(self.EVT_DRPY_FILE_OPENED) wx.EndBusyCursor() def PBind(self, eventtype, function, *args): self.drpyevents.append((eventtype, function, args)) def PPost(self, eventtype): for evt in self.drpyevents: if evt[0] == eventtype: if evt[2]: apply(evt[1], evt[2]) else: evt[1]() def PrintTraceback(self): slist = traceback.format_tb(sys.exc_info()[2]) l = len(slist) if l > 0: x = 0 rstring = "" while x < l: rstring = rstring + slist[x] x = x + 1 tracebackstring = "Traceback (most recent call last):\n" + rstring \ + str(sys.exc_info()[0]).lstrip("exceptions.") + ": " + str(sys.exc_info()[1]) message = "\n\n\n" + tracebackstring print message def PUnbind(self, eventtype, function): x = 0 for evt in self.drpyevents: if (evt[0] == eventtype) and (evt[1] == function): self.drpyevents.pop(x) else: x += 1 def reloaddocumentsmenu(self): mnuitems = self.documentsmenu.GetMenuItems() for mnuitem in mnuitems: self.documentsmenu.Remove(mnuitem.GetId()) #mnuitems[x].Destroy() self.setupdocumentsmenu() def RemovePluginIcon(self, name): toolbarfile = self.datdirectory + "/toolbar.custom.icons.dat" f = file(toolbarfile, 'r') lines = f.read().split('\n') f.close() name = ":" + name f = file(toolbarfile, 'w') for line in lines: if line: currentname = drPrefsFile.ExtractPreferenceFromText(line, "Name") if currentname != name: f.write(line + '\n') f.close() def RemoveTrailingWhitespace(self, docPos): #only for python files? #if self.prefs.docremovetrailingwhitespace and self.txtDocument.filetype != 1: if self.prefs.docremovetrailingwhitespace[self.txtDocument.filetype]: text = self.txtDocumentArray[docPos].GetText() #newtext, n = self.retrailingwhitespace.subn('', text) #patch, 23.03.2006: newtext = re.sub(r"\s+[\n\r]+", lambda x: x.expand("\g<0>").lstrip(" \t\f\v"), text) if newtext != text: #save current line curline = self.txtDocumentArray[docPos].GetCurrentLine() self.txtDocumentArray[docPos].SetText(newtext) #jump to saved current line self.txtDocumentArray[docPos].GotoLine(curline) self.SetStatusText("Removed trailing whitespaces", 2) else: self.SetStatusText("", 2) def runcommand(self, command, statustext = "Running Command", pagetext="Prompt", redin="", redout = "", rederr=""): if self.txtPrompt.pid > -1: self.OnNewPrompt(None) self.promptnotebook.SetPageText(self.promptPosition, pagetext) self.txtPrompt.SetReadOnly(0) self.txtPrompt.SetText(command + '\n') if not self.mainpanel.PromptIsVisible: self.mainpanel.PromptIsVisible = True self.mainpanel.OnSize(None) self.promptnotebook.SetPageImage(self.promptPosition, 3) self.txtPrompt.SetScrollWidth(1) self.txtPrompt.editpoint = self.txtPrompt.GetLength() self.txtPrompt.GotoPos(self.txtPrompt.editpoint) self.SetStatusText(statustext, 2) self.txtPrompt.process = wx.Process(self) self.txtPrompt.process.Redirect() if self.PLATFORM_IS_WIN: self.txtPrompt.pid = wx.Execute(command, wx.EXEC_ASYNC | wx.EXEC_NOHIDE, self.txtPrompt.process) else: self.txtPrompt.pid = wx.Execute(command, wx.EXEC_ASYNC, self.txtPrompt.process) self.txtPrompt.inputstream = self.txtPrompt.process.GetInputStream() self.txtPrompt.errorstream = self.txtPrompt.process.GetErrorStream() self.txtPrompt.outputstream = self.txtPrompt.process.GetOutputStream() self.txtPrompt.process.redirectOut = redout self.txtPrompt.process.redirectErr = rederr self.UpdateMenuAndToolbar() self.txtPrompt.SetFocus() def RunShortcuts(self, event, stc = None, SplitView = 0): return drShortcuts.RunShortcuts(self, event, stc, SplitView) def LoadDialogSizeAndPosition(self, dialog, dialogfile, defaultdir=''): if self.prefs.rememberdialogsizesandpositions: if not defaultdir: defaultdir = self.datdirectory sizeposfile = defaultdir + '/' + dialogfile try: if os.path.exists(sizeposfile): f = file(sizeposfile, 'rb') text = f.read() f.close() x, y, px, py = map(int, text.split('\n')) dialog.SetSize((x, y)) dialog.Move(wx.Point(px, py)) except: drScrolledMessageDialog.ShowMessage(dialog, 'Error Loading Dialog Size. The file: "%s" may be corrupt.'\ % sizeposfile, 'Error') dialog.Bind(wx.EVT_CLOSE, dialog.OnCloseW) def SaveDialogSizeAndPosition(self, dialog, dialogfile, defaultdir=''): if self.prefs.rememberdialogsizesandpositions: try: if not defaultdir: defaultdir = self.datdirectory f = file(defaultdir + '/' + dialogfile, 'wb') x, y = dialog.GetSizeTuple() px, py = dialog.GetPositionTuple() f.write(str(x) + '\n' + str(y) + '\n' + str(px) + '\n' + str(py)) f.close() except: drScrolledMessageDialog.ShowMessage(dialog, "Error Saving Dialog Size", 'Error') def SaveFile(self, docPos, IsSaveAs = False, encoding='FromText'): self.PPost(self.EVT_DRPY_FILE_SAVING) #Submitted Write Access Patch. #Edited slightly by Dan (one if statement, string format). if (not os.access(self.txtDocumentArray[docPos].filename, os.W_OK)) and \ (os.path.exists(self.txtDocumentArray[docPos].filename)): self.ShowMessage('Error: Write Access: "%s"' % (self.txtDocumentArray[docPos].filename), 'Save Error') return False try: if self.prefs.backupfileonsave and not IsSaveAs: try: shutil.copyfile(self.txtDocumentArray[docPos].filename, self.txtDocumentArray[docPos].filename+".bak") except: self.ShowMessage(("Error Backing up to: " + self.txtDocumentArray[docPos].filename + ".bak"), "DrPython Error") if encoding == 'FromText': encoding = self.txtDocumentArray[docPos].GetEncoding() self.RemoveTrailingWhitespace(docPos) ctext = drEncoding.DecodeText(self, self.txtDocumentArray[docPos].GetText(), encoding) cfile = file(self.txtDocumentArray[docPos].filename, 'wb') cfile.write(ctext) cfile.close() #Save Stat Info: self.txtDocumentArray[docPos].mtime = int(os.stat(self.txtDocumentArray[docPos].filename).st_mtime) except: self.ShowMessage(("Error Writing: " + self.txtDocumentArray[docPos].filename), "DrPython Error") return False self.txtDocumentArray[docPos].SetSavePoint() self.txtDocumentArray[docPos].OnModified(None) if self.prefs.checksyntaxonsave: if self.prefs.checksyntaxextensions: exts = self.prefs.checksyntaxextensions.split() cext = os.path.splitext(self.txtDocumentArray[docPos].filename)[1][1:] if cext in exts: self.CheckSyntax(docPos) else: self.CheckSyntax(docPos) self.PPost(self.EVT_DRPY_FILE_SAVED) return True def setDocumentTo(self, number, ignoreold = 0): if not ignoreold: self.lastprogargsArray[self.docPosition] = self.lastprogargs #copy old finder limodou 2004/04/19 oldfinder = self.txtDocumentArray[self.docPosition].Finder #end limodou #save show eol and whitespace state try: prev_vieweol = self.txtDocument.GetViewEOL() prev_viewwhitespace = self.txtDocument.GetViewWhiteSpace() except: prev_vieweol = False prev_viewwhitespace = False self.docPosition = number self.txtDocument = self.txtDocumentArray[self.docPosition] #set from prev eol and whitespace state self.txtDocument.SetViewEOL(prev_vieweol) self.txtDocument.SetViewWhiteSpace(prev_viewwhitespace) #copy old finder limodou 2004/04/19 self.txtDocument.Finder.Copy(oldfinder) #end limodou self.lastprogargs = self.lastprogargsArray[self.docPosition] self.currentpage = self.documentnotebook.GetPage(number) if self.txtDocument.filename: self.ddirectory = os.path.split(self.txtDocument.filename)[0] #franz: (Bad Argument). self.updatePrefsMDI() #Syntax Highlighting if self.txtDocument.filetype == 0: self.highlightmenu.Check(self.ID_HIGHLIGHT_PYTHON, True) if self.txtDocument.filetype == 1: self.highlightmenu.Check(self.ID_HIGHLIGHT_CPP, True) if self.txtDocument.filetype == 2: self.highlightmenu.Check(self.ID_HIGHLIGHT_HTML, True) if self.txtDocument.filetype == 3: #comment limodou 2004/04/13 self.highlightmenu.Check(self.ID_HIGHLIGHT_PLAIN_TEXT, True) #end limodou if not self.txtDocument.filename: title = "DrPython - Untitled " + str(self.txtDocument.untitlednumber) else: title = "DrPython - " + self.txtDocument.filename if self.txtDocument.GetModify(): title += '[Modified]' if self.disableeventhandling: self.SetTitle(title) self.txtDocument.IsActive = True self.txtDocument.targetPosition = number self.txtDocument.OnModified(None) self.documentnotebook.SetSelection(self.docPosition) self.txtDocument.SetFocus() self.PPost(self.EVT_DRPY_DOCUMENT_CHANGED) def setPromptTo(self, number): oldfinder = self.txtPromptArray[self.promptPosition].Finder self.promptPosition = number self.txtPrompt = self.txtPromptArray[self.promptPosition] self.txtPrompt.Finder.Copy(oldfinder) self.currentprompt = self.promptnotebook.GetPage(number) #franz: (Bad Argument). self.updatePrefsPromptMDI() if self.txtPromptArray[self.promptPosition].pid != -1: if self.txtPrompt.pythonintepreter: self.SetStatusText("Running Python Interpreter", 2) else: self.SetStatusText(("Running " + os.path.split(self.txtDocument.filename)[1]), 2) else: self.SetStatusText("", 2) self.promptnotebook.SetSelection(self.promptPosition) def setupdocumentsmenu(self): self.tabnavmenu = drMenu(self) self.tabnavmenu.Append(self.ID_NEXT_DOCUMENT, "Next Document") self.tabnavmenu.Append(self.ID_PREVIOUS_DOCUMENT, "Previous Document") self.tabnavmenu.Append(self.ID_FIRST_DOCUMENT, "First Document") self.tabnavmenu.Append(self.ID_LAST_DOCUMENT, "Last Document") self.documentsmenu.AppendMenu(self.ID_DOCUMENT_NAVIGATION_MENU, "Navigation", self.tabnavmenu) self.documentsmenu.AppendSeparator() self.documentsmenu.Append(self.ID_SAVE_ALL, "Save All Documents") self.documentsmenu.AppendSeparator() self.documentsmenu.Append(self.ID_CLOSE_ALL, "Close &All Documents") self.documentsmenu.Append(self.ID_CLOSE_ALL_OTHER_DOCUMENTS, "Close All &Other Documents") self.documentsmenu.AppendSeparator() #Sort it first def _get_title(x): return x.GetFilenameTitle() def _x(x): return x indextitles = map(_get_title, self.txtDocumentArray) sortedtitles = map(_x, indextitles) sortedtitles.sort() #End Sort x = 0 l = len(self.txtDocumentArray) if l > 10: y = 0 yl = 10 if yl > l: yl = l a = 0 self.documentsubmenus = [] while y < yl: self.documentsubmenus.append(wx.Menu()) self.documentsmenu.AppendMenu(self.ID_DOCUMENTS_MENU_BASE+a, sortedtitles[y] + " - " + sortedtitles[yl-1], self.documentsubmenus[a]) while x < yl: i = indextitles.index(sortedtitles[x]) self.documentsubmenus[a].Append(self.ID_DOCUMENTS_BASE+i, sortedtitles[x]) self.Bind(wx.EVT_MENU, self.OnSelectDocument, id=self.ID_DOCUMENTS_BASE+i) x = x + 1 if y == l: break y = y + 10 yl = yl + 10 a = a + 1 if yl > l: yl = l else: while x < l: i = indextitles.index(sortedtitles[x]) self.documentsmenu.Append(self.ID_DOCUMENTS_BASE+i, sortedtitles[x]) self.Bind(wx.EVT_MENU, self.OnSelectDocument, id=self.ID_DOCUMENTS_BASE+i) x = x + 1 def setupfiletypeextensions(self): self.refiletypeiscpp = re.compile(self.getfileextensionstring(1), re.IGNORECASE) self.refiletypeishtml = re.compile(self.getfileextensionstring(2), re.IGNORECASE) self.refiletypeistxt = re.compile(self.getfileextensionstring(3), re.IGNORECASE) self.refiletypeispy = re.compile(self.getfileextensionstring(0), re.IGNORECASE) def SetupToolBar(self): return drToolBarFile.SetupToolBar(self) def ShowMessage(self, msg, title='DrPython'): drScrolledMessageDialog.ShowMessage(self, msg, title) def ShowSourceBrowser(self): if self.SourceBrowser is None: target, i = self.mainpanel.GetTargetNotebookPage(self.prefs.sourcebrowserpanel, 'Source Browser') self.SourceBrowser = drSourceBrowserPanel(target, -1, self.prefs.sourcebrowserpanel, i) self.mainpanel.SetPanelSize(self.prefs.sourcebrowserpanel, self.prefs.sourcebrowsersize) target.SetPanel(self.SourceBrowser) self.mainpanel.ShowPanel(self.prefs.sourcebrowserpanel, i) else: self.SourceBrowser.Browse() self.mainpanel.ShowPanel(self.SourceBrowser.position, self.SourceBrowser.Index, True) def ShowPrompt(self, Visible = True): if Visible: if self.mainpanel.PromptIsVisible: return self.mainpanel.PromptIsVisible = True if self.hasToolBar: self.toolbar.ToggleTool(self.ID_TOGGLE_PROMPT, True) self.mainpanel.OnSize(None) self.txtPrompt.SetFocus() else: if not self.mainpanel.PromptIsVisible: return self.mainpanel.PromptIsVisible = False if self.hasToolBar: self.toolbar.ToggleTool(self.ID_TOGGLE_PROMPT, False) self.mainpanel.OnSize(None) self.txtDocument.SetFocus() def UpdateMenuAndToolbar(self): isrunning = self.txtPrompt.pid != -1 thereisafile = len(self.txtDocument.filename) > 0 #Toolbar if self.hasToolBar: self.toolbar.EnableTool(self.ID_RELOAD, thereisafile) self.toolbar.EnableTool(self.ID_END, isrunning) #Menus self.filemenu.Enable(self.ID_RELOAD, thereisafile) self.filemenu.Enable(self.ID_RESTORE_FROM_BACKUP, thereisafile) if not isrunning: self.programmenu.Enable(self.ID_PYTHON, True) self.programmenu.Enable(self.ID_END, False) self.programmenu.Enable(self.ID_RUN, thereisafile) else: self.programmenu.Enable(self.ID_PYTHON, False) self.programmenu.Enable(self.ID_END, True) if thereisafile: self.programmenu.Enable(self.ID_RUN, False) #franz: oldprefs not used. def updatePrefsMDI(self): #Determine What is showing self.mainpanel.OnSize(None) self.Layout() self.UpdateMenuAndToolbar() #Shortcuts self.STCKeycodeArray = drShortcuts.SetSTCShortcuts(self.txtDocument, self.STCShortcuts, self.STCUseDefault) def updatePrefsPromptMDI(self): #Determine What is showing self.currentprompt.OnSize(None) self.Layout() self.UpdateMenuAndToolbar() #Shortcuts drShortcuts.SetSTCShortcuts(self.txtPrompt, self.STCShortcuts, self.STCUseDefault) def updatePrefs(self, oldprefs): #self.bSizer.Remove(self.mainpanel) #Styling: for prompt in self.txtPromptArray: prompt.StyleResetDefault() prompt.StyleClearAll() prompt.SetupPrefsPrompt(0) for document in self.txtDocumentArray: document.StyleResetDefault() document.StyleClearAll() document.SetupPrefsDocument(0) self.mainpanel.OnSize(None) self.setupfiletypeextensions() #Find/Replace: if (self.prefs.findreplaceregularexpression != oldprefs.findreplaceregularexpression) or \ (self.prefs.findreplacematchcase != oldprefs.findreplacematchcase) or \ (self.prefs.findreplacefindbackwards != oldprefs.findreplacefindbackwards) or \ (self.prefs.findreplacewholeword != oldprefs.findreplacewholeword) or \ (self.prefs.findreplaceinselection != oldprefs.findreplaceinselection) or \ (self.prefs.findreplacefromcursor != oldprefs.findreplacefromcursor) or \ (self.prefs.findreplacepromptonreplace != oldprefs.findreplacepromptonreplace): self.FindOptions = [] self.ReplaceOptions = [] # #SourceBrowser: # if not (self.prefs.sourcebrowserpanel == oldprefs.sourcebrowserpanel): # for document in self.txtDocumentArray: # if document.SourceBrowser: # document.SourceBrowser = None #DrScript: if self.prefs.drscriptloadexamples != oldprefs.drscriptloadexamples: self.drscriptmenu.reloadscripts() #Toolbar if self.prefs.iconsize > 0: if self.hasToolBar: self.DestroyToolBar() self.SetToolBar(None) self.toolbar = wx.ToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.TB_HORIZONTAL) self.ToolBarIdList = self.SetupToolBar() self.SetToolBar(self.toolbar) self.hasToolBar = 1 else: if self.hasToolBar: self.DestroyToolBar() self.SetToolBar(None) self.hasToolBar = 0 if not (oldprefs.recentfileslimit == self.prefs.recentfileslimit): self.DestroyRecentFileMenu() self.recentfiles = [] self.LoadRecentFiles() self.CreateRecentFileMenu() #Styling: self.txtDocument.StyleResetDefault() self.txtDocument.StyleClearAll() self.txtPrompt.StyleResetDefault() self.txtPrompt.StyleClearAll() self.txtDocument.SetupPrefsDocument(0) if self.txtDocument.GetViewWhiteSpace(): self.txtDocument.SetViewEOL(self.prefs.vieweol) self.txtPrompt.SetupPrefsPrompt(0) if self.txtPrompt.GetViewWhiteSpace(): self.txtPrompt.SetViewEOL(self.prefs.vieweol) if oldprefs.docfolding[self.txtDocument.filetype]: if not self.prefs.docfolding[self.txtDocument.filetype]: self.txtDocument.FoldAll(True) #Add The Stuff to the Sizer #self.bSizer.Add(self.mainpanel, 1, wx.EXPAND) self.txtDocument.OnModified(None) self.txtDocument.OnPositionChanged(None) #Parenthesis Matching: if oldprefs.docparenthesismatching != self.prefs.docparenthesismatching: if not self.prefs.docparenthesismatching: #Clear Parenthesis Highlighting self.txtDocument.BraceBadLight(wx.stc.STC_INVALID_POSITION) self.txtDocument.BraceHighlight(wx.stc.STC_INVALID_POSITION, wx.stc.STC_INVALID_POSITION) self.Layout() def ViewInPanel(self, event): docnumber = event.GetId() - self.ID_VIEW_IN_PANEL_BASE target, i = self.mainpanel.GetTargetNotebookPage(self.viewinpaneltarget, "View In Panel") if docnumber < 0: drsplit = drSplitTextPanel(target, self, self.txtDocumentArray[self.docPosition], self.viewinpaneltarget, i) else: drsplit = drSplitTextPanel(target, self, self.txtDocumentArray[docnumber], self.viewinpaneltarget, i) target.SetPanel(drsplit) self.mainpanel.ShowPanel(self.viewinpaneltarget, i) def ViewInPanelMenu(self, event): docMenu = wx.Menu() x = 0 l = len(self.txtDocumentArray) docMenu.Append(self.ID_VIEW_IN_PANEL_BASE-1, "Current Document") self.Bind(wx.EVT_MENU, self.ViewInPanel, id=self.ID_VIEW_IN_PANEL_BASE-1) docMenu.AppendSeparator() if l > 10: y = 0 yl = 10 if yl > l: yl = l a = 0 docSubMenus = [] while y < yl: docSubMenus.append(wx.Menu()) docMenu.AppendMenu(self.ID_VIEW_IN_PANEL_BASE+a, str(y+1) + " - " + str(yl), docSubMenus[a]) while x < yl: if self.txtDocumentArray[x].filename: docSubMenus[a].Append(self.ID_VIEW_IN_PANEL_BASE+x, os.path.basename(self.txtDocumentArray[x].filename)) else: docSubMenus[a].Append(self.ID_VIEW_IN_PANEL_BASE+x, "Untitled " + str(self.txtDocumentArray[x].untitlednumber)) self.Bind(wx.EVT_MENU, self.ViewInPanel, id=self.ID_VIEW_IN_PANEL_BASE+x) x = x + 1 if y == l: break y = y + 10 yl = yl + 10 a = a + 1 if yl > l: yl = l else: while x < l: if self.txtDocumentArray[x].filename: docMenu.Append(self.ID_VIEW_IN_PANEL_BASE+x, os.path.basename(self.txtDocumentArray[x].filename)) else: docMenu.Append(self.ID_VIEW_IN_PANEL_BASE+x, "Untitled " + str(self.txtDocumentArray[x].untitlednumber)) self.Bind(wx.EVT_MENU, self.ViewInPanel, id=self.ID_VIEW_IN_PANEL_BASE+x) x = x + 1 self.PopupMenu(docMenu, self.ScreenToClient(wx.GetMousePosition())) docMenu.Destroy() def ViewURLInBrowser(self, url): if url.find('http:') == -1: url = os.path.normpath(url) if self.prefs.documentationbrowser == '' and self.PLATFORM_IS_WIN: os.startfile(url) return wx.Execute((self.prefs.documentationbrowser + ' "' + url + '"'), wx.EXEC_ASYNC) def WriteRecentFiles(self): recentfiles = self.datdirectory + "/recent_files.log" try: fin = open(recentfiles, 'w') x = 0 length = len(self.recentfiles) while (x < self.prefs.recentfileslimit) and (x < length): fin.write(self.recentfiles[x] + '\n') x = x + 1 fin.close() except IOError: self.ShowMessage("Error Writing: " + recentfiles, "Recent Files Error") #Initialize menus for Advanced mode (more items) def CreateMenus(self): self.filemenu = drMenu(self) self.filemenu.Append(self.ID_NEW, 'New', False, 0) self.filemenu.Append(self.ID_OPEN, 'Open', True, 0) self.filemenu.Append(self.ID_OPEN_IMPORTED_MODULE, 'Open Imported Module', True) self.recentmenu = wx.Menu() self.CreateRecentFileMenu() self.filemenu.AppendMenu(self.ID_OPEN_RECENT, "Op&en Recent", self.recentmenu) self.filemenu.Append(self.ID_RELOAD, 'Reload File', False, 0) self.filemenu.Append(self.ID_RESTORE_FROM_BACKUP, 'Restore From Backup') self.filemenu.AppendSeparator() self.filemenu.Append(self.ID_CLOSE, 'Close', False, 0) self.filemenu.AppendSeparator() self.filemenu.Append(self.ID_CLEAR_RECENT, 'Clear Recent File List') self.filemenu.AppendSeparator() self.filemenu.Append(self.ID_SAVE, 'Save', False, 0) self.filemenu.Append(self.ID_SAVE_AS, 'Save As', True, 5) self.filemenu.Append(self.ID_SAVE_COPY, 'Save A Copy', True, 2) self.filemenu.Append(self.ID_SAVE_PROMPT, 'Save Prompt Output To File', True) self.filemenu.AppendSeparator() self.filemenu.Append(self.ID_PRINT_SETUP, 'Print Setup', True) self.filemenu.Append(self.ID_PRINT, 'Print File', True, 0) self.filemenu.Append(self.ID_PRINTPROMPT, 'Print Prompt', True) self.filemenu.AppendSeparator() self.filemenu.Append(self.ID_EXIT, 'Exit', False, 1) self.commentmenu = drMenu(self) self.commentmenu.Append(self.ID_COMMENT_REGION, 'Comment') self.commentmenu.Append(self.ID_UNCOMMENT_REGION, 'UnComment') self.whitespacemenu = drMenu(self) self.whitespacemenu.Append(self.ID_INDENT_REGION, 'Indent', False, 0) self.whitespacemenu.Append(self.ID_DEDENT_REGION, 'Dedent', False, 0) self.whitespacemenu.AppendSeparator() self.whitespacemenu.Append(self.ID_CHECK_INDENTATION, "Check Indentation Type...") self.whitespacemenu.Append(self.ID_CLEAN_UP_TABS, "Set Indentation To Tabs...") self.whitespacemenu.Append(self.ID_CLEAN_UP_SPACES, "Set Indentation To Spaces...") self.whitespacemenu.AppendSeparator() self.whitespacemenu.Append(self.ID_UNIXMODE, "Set Line Endings To Unix Mode (\"\\n\')") self.whitespacemenu.Append(self.ID_WINMODE, "Set Line Endings To DOS/Windows Mode (\"\\r\\n\')") self.whitespacemenu.Append(self.ID_MACMODE, "Set Line Endings To Mac Mode (\"\\r\')") self.casemenu = drMenu(self) self.casemenu.Append(self.ID_UPPERCASE, 'Uppercase', False, 0) self.casemenu.Append(self.ID_LOWERCASE, 'Lowercase', False, 0) self.editmenu = drMenu(self) self.editmenu.Append(self.ID_UNDO, 'Undo', False, 0) self.editmenu.Append(self.ID_REDO, 'Redo', False, 1) self.editmenu.AppendSeparator() #Order changed by drpython ##for keyboard macro (Keyboardmacro) recording; #ugly hack franz # removed again self.editmenu.Append(self.ID_CUT, 'Cut') self.editmenu.Append(self.ID_COPY, 'Copy') self.editmenu.Append(self.ID_PASTE, 'Paste') ##end patch keyboard macro recording #end ugly hack franz # removed again self.editmenu.Append(self.ID_DELETE, 'Delete') self.editmenu.AppendSeparator() self.editmenu.Append(self.ID_SELECT_ALL, 'Select All') self.editmenu.AppendSeparator() self.editmenu.Append(self.ID_INSERT_SEPARATOR, 'Insert Separator', True) self.editmenu.Append(self.ID_INSERT_REGEX, 'Insert Regular Expression', True) self.editmenu.AppendSeparator() self.editmenu.Append(self.ID_FIND_AND_COMPLETE, 'Find And Complete') self.editmenu.AppendSeparator() self.editmenu.AppendMenu(self.ID_COMMENT, "&Comments", self.commentmenu) self.editmenu.AppendMenu(self.ID_WHITESPACE, "&Whitespace", self.whitespacemenu) self.editmenu.AppendMenu(self.ID_CASE, "Case", self.casemenu) self.searchmenu = drMenu(self) self.searchmenu.Append(self.ID_FIND, 'Find', True, 0) self.searchmenu.Append(self.ID_FIND_NEXT, 'Find Next', False, 5) self.searchmenu.Append(self.ID_FIND_PREVIOUS, 'Find Previous') self.searchmenu.Append(self.ID_REPLACE, 'Replace', True, 0) self.foldmenu = drMenu(self) self.foldmenu.Append(self.ID_TOGGLE_FOLD, 'Toggle Fold', False, 0) self.foldmenu.Append(self.ID_FOLD_ALL, 'Fold All', False, 0) self.foldmenu.Append(self.ID_EXPAND_ALL, 'Expand All', False, 0) self.highlightmenu = drMenu(self) self.highlightmenu.AppendRadioItem(self.ID_HIGHLIGHT_PYTHON, "Python") self.highlightmenu.AppendRadioItem(self.ID_HIGHLIGHT_CPP, "C/C++") self.highlightmenu.AppendRadioItem(self.ID_HIGHLIGHT_HTML, "HTML") self.highlightmenu.AppendRadioItem(self.ID_HIGHLIGHT_PLAIN_TEXT, "Plain Text") self.highlightmenu.Check(self.ID_HIGHLIGHT_PYTHON, True) self.viewinpanelmenu = drMenu(self) self.viewinpanelmenu.Append(self.ID_VIEW_IN_LEFT_PANEL, 'View In Left Panel') self.viewinpanelmenu.Append(self.ID_VIEW_IN_RIGHT_PANEL, 'View In Right Panel') self.viewinpanelmenu.Append(self.ID_VIEW_IN_TOP_PANEL, 'View In Top Panel') self.gotomenu = drMenu(self) self.gotomenu.Append(self.ID_GOTO_BLOCK_START, 'Go To Block Start', False, -1, 'Block Start') self.gotomenu.Append(self.ID_GOTO_BLOCK_END, 'Go To Block End', False, -1, 'Block End') self.gotomenu.Append(self.ID_GOTO_CLASS_START, 'Go To Class Start', False, -1, 'Class Start') self.gotomenu.Append(self.ID_GOTO_CLASS_END, 'Go To Class End', False, -1, 'Class End') self.gotomenu.Append(self.ID_GOTO_DEF_START, 'Go To Def Start', False, -1, 'Def Start') self.gotomenu.Append(self.ID_GOTO_DEF_END, 'Go To Def End', False, -1, 'Def End') self.viewmenu = drMenu(self) self.viewmenu.Append(self.ID_GOTO, 'Go To', True, 0) self.viewmenu.AppendMenu(self.ID_GOTO_MENU, "Go To", self.gotomenu) self.viewmenu.AppendSeparator() self.viewmenu.Append(self.ID_ZOOM_IN, 'Zoom In', False, 5) self.viewmenu.Append(self.ID_ZOOM_OUT, 'Zoom Out', False, 5) self.viewmenu.AppendSeparator() self.viewmenu.AppendMenu(self.ID_FOLDING, "&Folding", self.foldmenu) self.viewmenu.AppendSeparator() self.viewmenu.AppendMenu(self.ID_VIEW_IN_PANEL, "&View In Panel", self.viewinpanelmenu) self.viewmenu.AppendSeparator() self.viewmenu.AppendMenu(self.ID_HIGHLIGHT, "&Syntax Highlighting", self.highlightmenu) self.viewmenu.AppendSeparator() self.viewmenu.Append(self.ID_TOGGLE_SOURCEBROWSER, 'Toggle Source Browser') self.viewmenu.Append(self.ID_SOURCEBROWSER_GOTO, 'Source Browser Go To', True) self.viewmenu.AppendSeparator() #fix bug someone refered in forum limodou 2004/04/20 self.viewmenu.Append(self.ID_TOGGLE_VIEWWHITESPACE, 'Toggle View Whitespace', False, 12) #end limodou self.viewmenu.Append(self.ID_TOGGLE_PROMPT, 'Toggle Prompt') self.programmenu = drMenu(self) self.programmenu.Append(self.ID_CHECK_SYNTAX, 'Check Syntax') self.programmenu.AppendSeparator() self.programmenu.Append(self.ID_RUN, 'Run') self.programmenu.Append(self.ID_SET_ARGS, 'Set Arguments', True) self.programmenu.Append(self.ID_PYTHON, 'Python', False, -1, 'Open a Python Interpreter') self.programmenu.Append(self.ID_END, 'End') self.programmenu.Append(self.ID_CLOSE_PROMPT, 'Close Prompt') # Feb 17 - adding PyDoc menu items self.programmenu.AppendSeparator() self.programmenu.Append(self.ID_PYDOC_CURR, self.getmenulabel('Pydoc Current File')) self.programmenu.Append(self.ID_PYDOC_ALL, self.getmenulabel('Pydoc All Open Files')) self.programmenu.Append(self.ID_VIEW_PYDOC, self.getmenulabel('Browse PyDoc...')) # End Pydoc changes self.bookmarksmenu = drBookmarksMenu(self) self.drscriptmenu = drScriptMenu(self) self.txtDocument.OnModified(None) #DrScript Shortcuts self.DrScriptShortcutsAction = self.drscriptmenu.OnScript self.pluginsconfiguremenu = drPluginConfigureMenu(self) self.pluginsindexmenu = drPluginIndexMenu(self) self.pluginsprefsmenu = drPluginPreferencesMenu(self) self.documentsmenu = drMenu(self) self.setupdocumentsmenu() self.optionsmenu = drMenu(self) self.optionsmenu.Append(self.ID_PREFS, 'Preferences', True, 0) self.optionsmenu.Append(self.ID_SHORTCUTS, 'Customize Shortcuts', True, 0) self.optionsmenu.Append(self.ID_POPUP, 'Customize Pop Up Menu', True) self.optionsmenu.Append(self.ID_CUSTOMIZE_TOOLBAR, 'Customize ToolBar', True) self.optionsmenu.AppendSeparator() self.optionsmenu.Append(self.ID_EDIT_BOOKMARKS, 'Edit Bookmarks', True, 0) self.optionsmenu.Append(self.ID_EDIT_SCRIPT_MENU, 'Edit &Script Menu', True) self.optionsmenu.AppendSeparator() self.optionsmenu.AppendMenu(self.ID_CONFIGURE_PLUGINS, "C&onfigure Plugins", self.pluginsconfiguremenu) self.optionsmenu.AppendMenu(self.ID_PLUGIN_PREFS, "Pl&ugin Preferences", self.pluginsprefsmenu) self.optionsmenu.AppendMenu(self.ID_LOAD_PLUGIN, "&Load Plugin(s) From Index", self.pluginsindexmenu) self.pluginshelpmenu = drPluginHelpMenu(self) self.pluginsaboutmenu = drPluginAboutMenu(self) self.helpmenu = drMenu(self) self.helpmenu.Append(self.ID_ABOUT, "&About DrPython...") self.helpmenu.AppendMenu(self.ID_PLUGIN_ABOUT, "About Plugin", self.pluginsaboutmenu) self.helpmenu.AppendSeparator() self.helpmenu.Append(self.ID_HELP, 'Help', True, 0, 'DrPython &Help...') self.helpmenu.AppendMenu(self.ID_PLUGIN_HELP, "Plugin Help", self.pluginshelpmenu) self.helpmenu.AppendSeparator() self.helpmenu.Append(self.ID_PYTHON_DOCS, 'View Python Docs', True) self.helpmenu.Append(self.ID_WXWIDGETS_DOCS, 'View WxWidgets Docs', True) self.helpmenu.Append(self.ID_REHOWTO_DOCS, 'View Regular Expression Howto', True) if self.prefs.debugmodus: self.helpmenu.AppendSeparator() self.helpmenu.Append(self.ID_INSPECT_TOOL, self.getmenulabel('&Inspect Tool')) self.menuBar = wx.MenuBar() #ugly hack workaround #in linux, if there is a menu accelerator, the hotkeys are not working anymore. menuBarNamesWin32 = ["&File", "&Edit", "&Search", "&View", "&Program", "&Bookmarks", "D&rScript", "&Documents", "&Options", "&Help"] menuBarNamesGtk = ["File", "Edit", "Search", "View", "Program", "Bookmarks", "DrScript", "Documents", "Options", "Help"] if self.PLATFORM_IS_WIN: menuBarNames = menuBarNamesWin32 else: menuBarNames = menuBarNamesGtk self.menuBar.Append(self.filemenu, menuBarNames[0]) self.menuBar.Append(self.editmenu, menuBarNames[1]) self.menuBar.Append(self.searchmenu, menuBarNames[2]) self.menuBar.Append(self.viewmenu, menuBarNames[3]) self.menuBar.Append(self.programmenu, menuBarNames[4]) self.menuBar.Append(self.bookmarksmenu, menuBarNames[5]) self.menuBar.Append(self.drscriptmenu, menuBarNames[6]) self.menuBar.Append(self.documentsmenu, menuBarNames[7]) self.menuBar.Append(self.optionsmenu, menuBarNames[8]) self.menuBar.Append(self.helpmenu, menuBarNames[9]) self.SetMenuBar(self.menuBar) self.SetToolbar() def SetToolbar(self): if self.hasToolBar: self.DestroyToolBar() self.SetToolBar(None) try: #AB self.ToolBarList = drToolBarFile.getToolBarList(self.datdirectory) except: self.ShowMessage("Error Loading ToolBar List", "DrPython Error") if self.prefs.iconsize > 0: self.hasToolBar = True self.toolbar = wx.ToolBar(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.TB_HORIZONTAL) self.ToolBarIdList = self.SetupToolBar() self.SetToolBar(self.toolbar) # lm - adding helper functions def promptSaveAll(self): """ check if there are any open unsaved files, and prompt the user to save each """ x = 0 while x < len(self.txtDocumentArray): if self.txtDocumentArray[x].GetModify(): if self.Ask('Would you like to save "%s"?' % self.txtDocumentArray[x].GetFilename(), "DrPython"): self.setDocumentTo(x) self.OnSave(None) x += 1 def promptSaveCurrent(self): """ ask the user if they would like to save the current file """ if self.txtDocument.GetModify(): if self.Ask('Would you like to save "%s"?' % self.txtDocument.GetFilename(), "DrPython"): self.OnSave(None) def promptDir(self, msg): """ open a directory browser and return the directory chosen """ d = wx.DirDialog(self, msg, style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON|wx.MAXIMIZE_BOX|wx.THICK_FRAME) dir = '' if d.ShowModal() == wx.ID_OK: dir = d.GetPath() d.Destroy() return dir #/lm helper functions # helper function #Update to DrPython 165 and later. can be removed in the future. def CheckForDrPythonBefore165(self): #code taken from DrPython164 and before #1) get former drpython preferences base path self.udir = os.path.expanduser("~").replace("\\", "/") if self.PLATFORM_IS_WIN: if os.environ.has_key("APPDATA"): self.updir = os.environ["APPDATA"].replace("\\", "/") else: self.updir = self.udir else: self.updir = self.udir if not os.path.exists(self.updir): self.updir = self.programdirectory self.updir = self.updir.rstrip('/') if self.PLATFORM_IS_WIN: self.updir += "/drpython" else: self.updir += "/.drpython" #end code taken from DrPython164 and before #2) check for recent.log file and plugins directory: so there was most probably #a former drpython Installation there if os.path.exists(os.path.join(self.updir, 'recent_files.log')) and \ os.path.isdir(os.path.join(self.updir, 'plugins')): return True else: return False def ProcessUpgradeToDrPython165(self): def getsrcfile(f): return os.path.join(self.updirbackup, f) def getdstfile(f): return os.path.join (self.updir, f) self.updirbackup = self.updir + '164backup' files = os.listdir(self.updirbackup) if "preferences.dat" in files: #f.pop(f.index("preferences.dat")) files.remove('preferences.dat') if "drscripts" in files: os.removedirs(getdstfile('drscripts')) shutil.copytree(getsrcfile('drscripts'), getdstfile('drscripts')) files.remove('drscripts') leftfiles = [] #copy drscript.dat into preferences and remove it for i in files: if i.find("shortcuts.dat") > -1: shutil.copyfile(getsrcfile(i), getdstfile('shortcuts/' + i)) else: leftfiles.append(i) coredatfiles = [ ".separator.favorite.colours.dat", "bookmarks.dat", "bookmarksdialog.sizeandposition.dat", "documentation.bookmarks.dat", "drpython.panel.sizes.dat", "drpython.sizeandposition.dat", "drscriptdialog.sizeandposition.dat", "dynamicdrscriptdialog.sizeandposition.dat", "filedialog.sizeandposition.dat", "findreplacedialog.sizeandposition.dat", "openimportedmoduledialog.sizeandposition.dat", "plugindialog.sizeandposition.dat", "popupmenu.dat", "popupmenudialog.sizeandposition.dat", "preferencesdialog.sizeandposition.dat", "recent_files.log", "shortcutsdialog.sizeandposition.dat", "toolbar.dat", "toolbar.custom.icons.dat", "toolbardialog.sizeandposition.dat" #"windowsize.dat" ] for f in coredatfiles: if os.path.exists(getsrcfile(f)): shutil.copyfile(getsrcfile(f), getdstfile('dat/' + f)) leftfiles.remove(f) f = ['drscript.dat', 'userpreferencesdirectory.dat'] for i in f: if i in leftfiles: shutil.copyfile(getsrcfile(i), getdstfile(i)) leftfiles.remove(i) f = 'default.idx' if os.path.exists (getsrcfile('plugins/' + f)): shutil.copyfile(getsrcfile('plugins/' + f), getdstfile(f)) #rest are probably plugin dat files lfiles = [] for f in leftfiles: if os.path.isfile (getsrcfile(f)): shutil.copyfile(getsrcfile(f), getdstfile('.plugins/dat/' + f)) else: lfiles.append(f) #files from plugins direcory files = os.listdir(getsrcfile('plugins')) for f in files: if f.endswith('.py') or f.endswith('.idx'): #put it into drplugins directory shutil.copyfile(getsrcfile('plugins/' + f), getdstfile('drplugins/' + f)) elif f.endswith('.pyc'): continue #ignore that file elif f.endswith('shortcuts.dat'): shutil.copyfile(getsrcfile('plugins/' + f), getdstfile('.plugins/shortcuts/' + f)) elif f.endswith('preferences.dat'): shutil.copyfile(getsrcfile('plugins/' + f), getdstfile('.plugins/preferences/' + f)) elif os.path.isdir(getsrcfile('plugins/' + f)): shutil.copytree(getsrcfile('plugins/' + f), getdstfile('.plugins/dat/' + f)) else: shutil.copyfile(getsrcfile('plugins/' + f), getdstfile('.plugins/dat/' + f)) wx.MessageBox("Please install later the new plugins from Sourceforge.\nMost old ones are not compatible anymore.", "DrPython updated to 165 and newer", wx.ICON_INFORMATION) wx.MessageBox("Please restart DrPython and download/install the new plugins.", "DrPython Update ready", wx.ICON_INFORMATION) #Update to DrPython 165 and later end. can be removed in the future. #******************************************************************************************************* class DrApp(wx.App): def OnInit(self): #lc = wx.Locale(wx.LANGUAGE_DEFAULT) #_ = wx.GetTranslation #lc.AddCatalogLookupPathPrefix('locale') #lc.AddCatalog('drpython') self.frame = DrFrame(None, 101, "DrPython - Untitled 1") self.frame.Show(True) self.SetTopWindow(self.frame) self.Bind(wx.EVT_ACTIVATE_APP, self.OnActivate) return True def OnActivate(self, event): if event.GetActive(): self.frame.OnActivate() event.Skip() class SysOutListener: def __init__(self): self.first = True def write(self, string): f=open(out_file, 'a') if self.first: self.first = False f.write('\n\n' + time.ctime() + ':\n') f.write(string) f.flush() f.close() #sys.__stdout__.write(string) #evt = wxStdOut(text=string) #wx.PostEvent(wx.GetApp().frame.output_window, evt) class SysErrListener: def __init__(self): self.first = True def write(self, string): did_not_exist = False if not os.path.exists(err_file): did_not_exist = True f=open(err_file, 'a') if self.first: self.first = False if did_not_exist: first = open(firsterr_file, 'w') first.close() f.write('\n\n' + time.ctime() + ':\n') f.write(string) f.flush() f.close() #sys.__stderr__.write(string) #evt = wxStdOut(text=string) #wx.PostEvent(wx.GetApp().frame.output_window, evt) def ShowErrAndRemoveErrFile (end=True): import wx if os.path.exists(err_file): app = wx.App(0) if end: answer = wx.MessageBox("Do you want to see the errors?\n(You can turn off that debug modus in preferences.)", "There were errors: Output is in" + err_file, wx.YES_NO) else: answer = wx.YES if answer == wx.YES: import wx.lib.dialogs f = open (err_file) if not end: wx.MessageBox("There were errors in previous startup!", "Show Errors", wx.ICON_EXCLAMATION) dlg = wx.lib.dialogs.ScrolledMessageDialog(None, f.read(), err_file + " File") dlg.ShowModal() dlg.Destroy() f.close() if end: answer = wx.MessageBox("Delete the error File", "Do you want to delete the error file?", wx.YES_NO) if answer == wx.YES: os.remove (err_file) if os.path.exists(out_file): os.remove (out_file) app.MainLoop() def main(): #print len (sys.argv) #for i in sys.argv: # print i useredirecttofile = 1 if len(sys.argv) > 1: if sys.argv[1].find('--r0') == 0: useredirecttofile = 0 del sys.argv[1] if os.path.exists(firsterr_file): os.remove (firsterr_file) ShowErrAndRemoveErrFile(False) if useredirecttofile: sys.stdout = SysOutListener() sys.stderr = SysErrListener() app = DrApp(0) if useredirecttofile: sys.stdout = SysOutListener() sys.stderr = SysErrListener() #print "test" #test for sysout #6 / 0 #test for syserr # load files from command line parameters #print "hallo"#test print if len(sys.argv) > 1: app.frame.OpenFile(sys.argv[1], False) if len(sys.argv) > 2: for f in sys.argv[2:]: try: app.frame.OpenFile(f, True) except: print "Error opening file %r" % f app.MainLoop() debugmodus = app.debugmodus if debugmodus: ShowErrAndRemoveErrFile() if __name__ == '__main__': main() drpython-3.11.1/drScrolledMessageDialog.py0000644000175000017500000000645311150445514021356 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Scrolled Message Dialog import wx import sys, traceback class ScrolledMessageDialog(wx.Dialog): def __init__(self, parent, message, title, position = wx.DefaultPosition, size = wx.Size(400, 300)): wx.Dialog.__init__(self, parent, -1, title, position, size, wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.THICK_FRAME | wx.RESIZE_BORDER) self.ID_CLOSE = 101 self.theSizer = wx.BoxSizer(wx.VERTICAL) self.cmdSizer = wx.BoxSizer(wx.HORIZONTAL) self.btnClose = wx.Button(self, self.ID_CLOSE, "&Close") self.cmdSizer.Add(self.btnClose, 0, wx.SHAPED | wx.ALIGN_CENTER) self.btnClose.SetDefault() slist = traceback.format_tb(sys.exc_info()[2]) l = len(slist) if l > 0: x = 0 rstring = "" while x < l: rstring = rstring + slist[x] x = x + 1 tracebackstring = "Traceback (most recent call last):\n" + rstring \ + str(sys.exc_info()[0]).lstrip("exceptions.") + ": " + str(sys.exc_info()[1]) message = message + "\n\n\n" + tracebackstring self.txtMessage = wx.TextCtrl(self, -1, message, wx.DefaultPosition, wx.DefaultSize, wx.TE_MULTILINE | wx.TE_READONLY) #[ 1357735 ] Change from Text to Html Messages; don't know wheter to apply or not #self.txtMessage = wx.html.HtmlWindow(self, -1, wx.DefaultPosition, wx.DefaultSize, wx.html.HW_SCROLLBAR_AUTO) #self.txtMessage.AppendToPage(''+message+'') self.theSizer.Add(self.txtMessage, 9, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.theSizer.Add(self.cmdSizer, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.SetAutoLayout(True) self.SetSizer(self.theSizer) self.Bind(wx.EVT_BUTTON, self.OnbtnClose, id=self.ID_CLOSE) self.btnClose.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) def OnbtnClose(self, event): self.Close(1) def OnKeyDown(self, event): if event.GetKeyCode() == wx.WXK_ESCAPE: self.Close(1) def ShowMessage(parent, message, title, position = wx.DefaultPosition, size = wx.Size(400, 300)): d = ScrolledMessageDialog(parent, message, title, position, size) d.ShowModal() d.Destroy()drpython-3.11.1/drNotebook.py0000644000175000017500000007130311150445515016737 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #The Notebook, and Panels. import os.path import wx import wx.stc from drText import DrText import drEncoding #************************************************* #Used in the main panel. class drSashWindow(wx.SashWindow): def __init__(self, parent, id, pos, size, style=0): wx.SashWindow.__init__(self, parent, id, pos, size, style) self.parent = parent.parent self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) def OnKeyDown(self, event): self.parent.RunShortcuts(event) def SetNotebook(self, notebook): '''Can Only be called once''' self.notebook = notebook self.theSizer = wx.BoxSizer(wx.HORIZONTAL) self.theSizer.Add(self.notebook, 1, wx.EXPAND) self.SetAutoLayout(True) self.SetSizer(self.theSizer) #************************************************* #This is the main panel, #Where all the sizing stuff happens. class drMainPanel(wx.Panel): def __init__(self, parent, id): wx.Panel.__init__(self, parent, id) self.panelsizesfile = parent.datdirectory + "/drpython.panel.sizes.dat" self.parent = parent width, height = self.GetSizeTuple() #Variables to Keep Track of what is being used. self.ID_DOCUMENT = 6001 self.ID_PROMPT = 6002 self.ID_LEFT = 6003 self.ID_RIGHT = 6004 self.ID_TOP = 6005 self.PromptIsVisible = self.parent.prefs.promptisvisible self.LeftIsVisible = False self.RightIsVisible = False self.TopIsVisible = False self.documenttuple = (width, height) self.prompttuple = (0, 0) self.lefttuple = (0, 0) self.righttuple = (0, 0) self.toptuple = (0, 0) self.promptsize = self.parent.prefs.promptsize self.prompt = drSashWindow(self, self.ID_PROMPT, wx.DefaultPosition, wx.DefaultSize, wx.SW_3D) self.document = drSashWindow(self, self.ID_DOCUMENT, wx.DefaultPosition, wx.DefaultSize, wx.SW_3D) self.leftsize = self.parent.prefs.sidepanelleftsize self.left = drSashWindow(self, self.ID_LEFT, wx.DefaultPosition, wx.DefaultSize, wx.SW_3D) self.rightsize = self.parent.prefs.sidepanelrightsize self.right = drSashWindow(self, self.ID_RIGHT, wx.DefaultPosition, wx.DefaultSize, wx.SW_3D) self.topsize = self.parent.prefs.sidepaneltopsize self.top = drSashWindow(self, self.ID_TOP, wx.DefaultPosition, wx.DefaultSize, wx.SW_3D) self.oldwidth, self.oldheight = 0, 0 self.leftNotebook = drSidePanelNotebook(self.left, -1, 0) self.rightNotebook = drSidePanelNotebook(self.right, -1, 1) self.topNotebook = drSidePanelNotebook(self.top, -1, 1) self.left.SetNotebook(self.leftNotebook) self.right.SetNotebook(self.rightNotebook) self.top.SetNotebook(self.topNotebook) self.lidx = [] self.ridx = [] self.tidx = [] self.OnSize(None) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_SASH_DRAGGED, self.OnSashDrag, id=self.ID_DOCUMENT) self.Bind(wx.EVT_SASH_DRAGGED, self.OnSashDrag, id=self.ID_PROMPT) if not parent.PLATFORM_IS_GTK: #if 0: self.document.SetSashVisible(wx.SASH_BOTTOM, True) #self.document.SetSashBorder(wx.SASH_BOTTOM, True) self.prompt.SetSashVisible(wx.SASH_TOP, True) #self.prompt.SetSashBorder(wx.SASH_TOP, True) self.document.SetSashVisible(wx.SASH_LEFT, True) #self.document.SetSashBorder(wx.SASH_LEFT, True) self.document.SetSashVisible(wx.SASH_RIGHT, True) #self.document.SetSashBorder(wx.SASH_RIGHT, True) self.document.SetSashVisible(wx.SASH_TOP, True) #self.document.SetSashBorder(wx.SASH_TOP, True) self.prompt.SetSashVisible(wx.SASH_LEFT, True) #self.prompt.SetSashBorder(wx.SASH_LEFT, True) self.prompt.SetSashVisible(wx.SASH_RIGHT, True) #self.prompt.SetSashBorder(wx.SASH_RIGHT, True) def _getindex(self, Position, Index): #Left if Position == 0: if Index in self.lidx: Index = self.lidx.index(Index) #Right elif Position == 1: if Index in self.ridx: Index = self.ridx.index(Index) #Top else: if Index in self.tidx: Index = self.tidx.index(Index) return Index def ClosePanel(self, Position, Index): Index = self._getindex(Position, Index) #Left if Position == 0: self.leftNotebook.DeletePage(Index) self.lidx.pop(Index) if self.leftNotebook.GetPageCount() < 1: self.LeftIsVisible = False #Right elif Position == 1: self.rightNotebook.DeletePage(Index) self.ridx.pop(Index) if self.rightNotebook.GetPageCount() < 1: self.RightIsVisible = False #Top else: self.topNotebook.DeletePage(Index) self.tidx.pop(Index) if self.topNotebook.GetPageCount() < 1: self.TopIsVisible = False wx.Yield() self.OnSize(None) def GetTargetNotebookPage(self, Position=1, Title=' '): #Left if Position == 0: l = self.leftNotebook.GetPageCount() self.lidx.append(l) newpage = drSidePanel(self.leftNotebook, -1) self.leftNotebook.AddPage(newpage, Title, True) self.LeftIsVisible = True #Right elif Position == 1: l = self.rightNotebook.GetPageCount() self.ridx.append(l) newpage = drSidePanel(self.rightNotebook, -1) self.rightNotebook.AddPage(newpage, Title, True) self.RightIsVisible = True #Top else: l = self.topNotebook.GetPageCount() self.tidx.append(l) newpage = drSidePanel(self.topNotebook, -1) self.topNotebook.AddPage(newpage, Title, True) self.TopIsVisible = True return newpage, l def IsVisible(self, Position=1, Index=0): Index = self._getindex(Position, Index) #Left if Position == 0: return (self.leftNotebook.GetSelection() == Index) and self.LeftIsVisible #Right elif Position == 1: return (self.rightNotebook.GetSelection() == Index) and self.RightIsVisible #Top else: return (self.topNotebook.GetSelection() == Index) and self.TopIsVisible def MemorizePanelSizes(self): if self.parent.prefs.rememberpanelsizes: try: f = file(self.panelsizesfile, 'wb') f.write(str(self.promptsize) + '\n' + str(self.leftsize) + '\n' + str(self.rightsize) + '\n' + str(self.topsize)) f.close() except: self.parent.ShowMessage('Error Memorizing Panel Sizes.') def OnSashDrag(self, event): evtheight = event.GetDragRect().height evtwidth = event.GetDragRect().width width, height = self.GetSizeTuple() if evtwidth < 0: evtwidth = 0 elif evtwidth > width: evtwidth = width if event.GetDragStatus() == wx.SASH_STATUS_OUT_OF_RANGE: if (not self.PromptIsVisible) or (evtheight < height): evtheight = 0 else: evtheight = height elif evtheight > height: evtheight = height oldsize = self.promptsize loldsize = self.leftsize roldsize = self.rightsize toldsize = self.topsize #Edge Drag e = event.GetId() edge = event.GetEdge() if edge == wx.SASH_LEFT: self.leftsize = ((width*100) - (evtwidth*100)) / width elif edge == wx.SASH_RIGHT: self.rightsize = ((width*100) - (evtwidth*100)) / width elif e == self.ID_DOCUMENT: if edge == wx.SASH_BOTTOM: self.promptsize = ((height*100) - (evtheight*100)) / height self.documenttuple = (self.documenttuple[0], evtheight) self.prompttuple = (self.prompttuple[0], height-evtheight) elif edge == wx.SASH_TOP: self.topsize = ((height*100) - (evtheight*100)) / height elif e == self.ID_PROMPT: self.promptsize = ((evtheight*100) / height) #Prompt Is Visible if self.promptsize == 0: self.promptsize = oldsize self.PromptIsVisible = False elif not self.PromptIsVisible and self.prompttuple[1] > 0: self.PromptIsVisible = True #Left Is Visible if self.leftsize == 0: self.leftsize = loldsize self.LeftIsVisible = False elif not self.LeftIsVisible and self.lefttuple[0] > 0: self.LeftIsVisible = True #Right Is Visible if self.rightsize == 0: self.rightsize = roldsize self.RightIsVisible = False elif not self.RightIsVisible and self.righttuple[0] > 0: self.RightIsVisible = True #Top Is Visible if self.topsize == 0: self.topsize = toldsize self.TopIsVisible = False elif not self.TopIsVisible and self.toptuple[1] > 0: self.TopIsVisible = True self.OnSize(None) def OnSize(self, event): width, height = self.GetSizeTuple() if (event is not None) and (width == self.oldwidth) and (height == self.oldheight): return self.oldwidth, self.oldheight = width, height #Height heightPrompt = 0 heightTop = 0 if self.TopIsVisible: heightTop = (height * self.topsize) / 100 if self.PromptIsVisible: heightPrompt = (height * self.promptsize) / 100 heightDocument = height - heightTop - heightPrompt if heightPrompt != 100: if heightDocument < 50: if heightTop > 0: heightTop = heightTop / 2 if heightPrompt > 0: heightPrompt = heightPrompt / 2 heightDocument += heightTop + heightPrompt #Width widthLeft = 0 widthRight = 0 if self.LeftIsVisible: widthLeft = (width * self.leftsize) / 100 if self.RightIsVisible: widthRight = (width * self.rightsize) / 100 widthMain = width - widthLeft - widthRight if widthMain < 50: if widthLeft > 0: widthLeft = widthLeft / 2 if widthRight > 0: widthRight = widthRight / 2 widthMain += widthLeft + widthRight #Tuples self.documenttuple = (widthMain, heightDocument) self.prompttuple = (widthMain, heightPrompt) self.lefttuple = (widthLeft, height) self.righttuple = (widthRight, height) self.toptuple = (widthMain, heightTop) #Set Move, Then Set Size self.document.Move((widthLeft, heightTop)) self.prompt.Move((widthLeft, heightDocument+heightTop)) self.left.Move((0, 0)) self.right.Move((widthLeft+widthMain, 0)) self.top.Move((widthLeft, 0)) self.document.SetSize(self.documenttuple) self.prompt.SetSize(self.prompttuple) self.left.SetSize(self.lefttuple) self.right.SetSize(self.righttuple) self.top.SetSize(self.toptuple) def RememberPanelSizes(self): if self.parent.prefs.rememberpanelsizes: if not os.path.exists(self.panelsizesfile): return try: f = file(self.panelsizesfile, 'rb') text = f.read() f.close() p, l, r, t = map(int, text.split('\n')) self.promptsize = p self.leftsize = l self.rightsize = r self.topsize = t except: self.parent.ShowMessage('Error Remembering Panel Sizes.\nThe File: "%s" may be corrupt.\nTry removing it, and restarting DrPython.' % self.panelsizesfile) def SetPanelSize(self, Position, size): if Position == 0: self.leftsize = size elif Position == 1: self.rightsize = size else: self.topsize = size def ShowPanel(self, Position, Index, Show=True): Index = self._getindex(Position, Index) #Left if Position == 0: self.LeftIsVisible = Show if self.LeftIsVisible: self.leftNotebook.SetSelection(Index) self.leftNotebook.GetPage(Index).OnSize(None) #Right elif Position == 1: self.RightIsVisible = Show if self.RightIsVisible: self.rightNotebook.SetSelection(Index) self.rightNotebook.GetPage(Index).OnSize(None) #Top else: self.TopIsVisible = Show if self.TopIsVisible: self.topNotebook.SetSelection(Index) self.topNotebook.GetPage(Index).OnSize(None) self.OnSize(None) def TogglePanel(self, Position=1, Index=0): Index = self._getindex(Position, Index) #Left if Position == 0: if not self.LeftIsVisible: self.LeftIsVisible = True self.leftNotebook.SetSelection(Index) else: self.LeftIsVisible = False #Right elif Position == 1: if not self.RightIsVisible: self.RightIsVisible = True self.rightNotebook.SetSelection(Index) else: self.RightIsVisible = False #Top else: if not self.TopIsVisible: self.TopIsVisible = True self.topNotebook.SetSelection(Index) else: self.TopIsVisible = False self.OnSize(None) #************************************************* def _refresh(x): x.Refresh() #******************************************************************************************************* #Notebook base class class drNotebook(wx.Notebook): def __init__(self, parent, id, images, closefunction): wx.Notebook.__init__(self, parent, id, wx.DefaultPosition, wx.Size(-1, -1), wx.CLIP_CHILDREN) self.parent = parent self.grandparent = parent.parent self.closefunction = closefunction if images: imagesize = (16, 16) self.imagelist = wx.ImageList(imagesize[0], imagesize[1]) self.images = images map(self.imagelist.Add, self.images) self.AssignImageList(self.imagelist) #wxPython bug workaround, OldSelection doesn't work. self.oldselection = 0 def OnLeftDoubleClick(self, event): if self.grandparent.prefs.doubleclicktoclosetab: self.closefunction(None) #************************************************* #Document Notebook class drDocNotebook(drNotebook): def __init__(self, parent, id): grandparent = parent.parent images = [wx.BitmapFromImage(wx.Image(grandparent.bitmapdirectory + "/16/unmodified.png", wx.BITMAP_TYPE_PNG)), wx.BitmapFromImage(wx.Image(grandparent.bitmapdirectory + "/16/modified.png", wx.BITMAP_TYPE_PNG)), wx.BitmapFromImage(wx.Image(grandparent.bitmapdirectory + "/16/active unmodified.png", wx.BITMAP_TYPE_PNG)), wx.BitmapFromImage(wx.Image(grandparent.bitmapdirectory + "/16/active modified.png", wx.BITMAP_TYPE_PNG))] drNotebook.__init__(self, parent, id, images, grandparent.OnClose) self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged) self.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey) self.Bind(wx.EVT_RIGHT_DOWN, self.OnPopUp) self.Bind(wx.EVT_LEFT_UP, self.OnSelectTab) self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDoubleClick) def OnNavigationKey(self, event): #only in windows? on gtk, that is apparantly never called. ignorekey = False if self.grandparent.prefs.docignorectrlpageupdown: if wx.GetKeyState(wx.WXK_CONTROL): if wx.GetKeyState(wx.WXK_PAGEUP) or wx.GetKeyState(wx.WXK_PAGEDOWN): ignorekey = True #if wx.GetKeyState(wx.WXK_TAB): # ignorekey = True if ignorekey: keycode = 0 if wx.GetKeyState(wx.WXK_TAB): keycode = wx.WXK_TAB if wx.GetKeyState(wx.WXK_PAGEUP): keycode = wx.WXK_PAGEUP if wx.GetKeyState(wx.WXK_PAGEDOWN): keycode = wx.WXK_PAGEDOWN evt = wx.KeyEvent() evt.m_controlDown = wx.GetKeyState(wx.WXK_CONTROL) evt.m_keyCode = keycode evt.m_shiftDown = wx.GetKeyState(wx.WXK_SHIFT) evt.SetEventType(wx.wxEVT_KEY_DOWN) self.grandparent.txtDocument.GetEventHandler().ProcessEvent(evt) else: event.Skip() def OnPageChanged(self, event): if self.grandparent.ignoreevents: return if not self.grandparent.txtDocumentArray: if event is not None: event.Skip() return if event is not None: i = event.GetSelection() else: i = self.GetSelection() l = self.GetPageCount() if (i < 0) or (i >= l): if event is not None: event.Skip() return if self.oldselection < l: if len (self.grandparent.txtDocumentArray) > self.oldselection: self.grandparent.txtDocumentArray[self.oldselection].IsActive = False self.grandparent.txtDocumentArray[self.oldselection].OnModified(None) self.oldselection = i self.grandparent.txtDocumentArray[i].IsActive = True self.grandparent.txtDocumentArray[i].OnModified(None) wx.CallAfter (self.SetTab) #bug reported and patch supplied by Tiziano Mueller, which itself was supplied by a user, 25. Feb. 2008, thanks. if event is not None: event.Skip() def OnPopUp(self, event): tabmenu = wx.Menu() tabmenu.Append(self.grandparent.ID_CLOSE, "&Close") tabmenu.Append(self.grandparent.ID_CLOSE_ALL, "Close &All Tabs") tabmenu.Append(self.grandparent.ID_CLOSE_ALL_OTHER_DOCUMENTS, "Close All &Other Tabs") tabmenu.AppendSeparator() tabmenu.Append(self.grandparent.ID_NEXT_DOCUMENT, "Next Tab") tabmenu.Append(self.grandparent.ID_PREVIOUS_DOCUMENT, "Previous Tab") tabmenu.Append(self.grandparent.ID_FIRST_DOCUMENT, "First Tab") tabmenu.Append(self.grandparent.ID_LAST_DOCUMENT, "Last Tab") tabmenu.AppendSeparator() tabmenu.Append(self.grandparent.ID_RELOAD, "&Reload File") tabmenu.Append(self.grandparent.ID_RESTORE_FROM_BACKUP, "&Restore From Backup") tabmenu.AppendSeparator() tabmenu.Append(self.grandparent.ID_SAVE, "&Save") tabmenu.Append(self.grandparent.ID_SAVE_AS, "Save &As...") ht = self.HitTest(event.GetPosition())[0] if ht > -1: self.SetSelection(ht) self.SetTab() tabmenu.Enable(self.grandparent.ID_RELOAD, len(self.grandparent.txtDocument.filename) > 0) tabmenu.Enable(self.grandparent.ID_RESTORE_FROM_BACKUP, len(self.grandparent.txtDocument.filename) > 0) self.PopupMenu(tabmenu, event.GetPosition()) tabmenu.Destroy() def OnSelectTab(self, event): selection = self.GetSelection() if selection != self.grandparent.docPosition: self.SetTab() event.Skip() def SetTab(self): #if not self.IsBeingDeleted(): # is not None: #pydeadobject error selection = self.GetSelection() if selection != -1: self.grandparent.setDocumentTo(selection) #************************************************* #Prompt Notebook class drPromptNotebook(drNotebook): def __init__(self, parent, id): grandparent = parent.parent images = [wx.BitmapFromImage(wx.Image(grandparent.bitmapdirectory + "/16/not running.png", wx.BITMAP_TYPE_PNG)), wx.BitmapFromImage(wx.Image(grandparent.bitmapdirectory + "/16/running.png", wx.BITMAP_TYPE_PNG)), wx.BitmapFromImage(wx.Image(grandparent.bitmapdirectory + "/16/active not running.png", wx.BITMAP_TYPE_PNG)), wx.BitmapFromImage(wx.Image(grandparent.bitmapdirectory + "/16/active running.png", wx.BITMAP_TYPE_PNG))] drNotebook.__init__(self, parent, id, images, grandparent.OnClosePrompt) self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged) self.Bind(wx.EVT_LEFT_UP, self.OnSelectTab) self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDoubleClick) self.Bind(wx.EVT_RIGHT_DOWN, self.OnPopUp) def OnPageChanged(self, event): if not self.grandparent.txtPromptArray: if event is not None: event.Skip() return if event is not None: i = event.GetSelection() else: i = self.GetSelection() l = self.GetPageCount() if (i < 0) or (i >= l): if event is not None: event.Skip() return if self.oldselection < l: if self.grandparent.txtPromptArray[self.oldselection].pid > -1: self.SetPageImage(self.oldselection, 1) else: self.SetPageImage(self.oldselection, 0) self.oldselection = i if self.grandparent.txtPromptArray[i].pid > -1: self.SetPageImage(i, 3) else: self.SetPageImage(i, 2) if event is not None: event.Skip() def OnSelectTab(self, event): selection = self.GetSelection() if selection != self.grandparent.promptPosition: self.SetTab() event.Skip() def SetTab(self): selection = self.GetSelection() if selection != -1: self.grandparent.setPromptTo(selection) def OnPopUp(self, event): tabmenu = wx.Menu() tabmenu.Append(self.grandparent.ID_CLOSE_PROMPT, "&Close Prompt") tabmenu.AppendSeparator() tabmenu.Append(self.grandparent.ID_PYTHON, "&Python") tabmenu.Append(self.grandparent.ID_RUN, "&Run Current Document") tabmenu.Append(self.grandparent.ID_END, "&End") ht = self.HitTest(event.GetPosition())[0] if ht > -1: self.SetSelection(ht) self.SetTab() tabmenu.Enable(self.grandparent.ID_RUN, (len(self.grandparent.txtDocument.filename) > 0)) tabmenu.Enable(self.grandparent.ID_END, (self.grandparent.txtPrompt.pid > -1)) self.PopupMenu(tabmenu, event.GetPosition()) tabmenu.Destroy() #************************************************* #Notebook to be used in the side panels. class drSidePanelNotebook(drNotebook): def __init__(self, parent, id, Position): self.parent = parent.parent self.PanelPosition = Position self.ID_CLOSE = 50 drNotebook.__init__(self, parent, id, [], self.OnClose) self.grandparent = self.GetParent().GetParent() self.Bind(wx.EVT_MENU, self.OnClose, id=self.ID_CLOSE) self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged) self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDoubleClick) self.Bind(wx.EVT_RIGHT_DOWN, self.OnPopUp) self.Bind(wx.EVT_SIZE, self.OnSize) def OnClose(self, event): if self.GetPageCount() > 0: self.grandparent.ClosePanel(self.PanelPosition, self.GetSelection()) self.grandparent.OnSize(None) def OnPageChanged(self, event): sel = self.GetSelection() if sel > -1: self.GetPage(sel).OnSize(None) event.Skip() def OnSize(self, event): if event is not None: if self.GetPageCount() > 0: self.GetPage(self.GetSelection()).SetSize(self.GetSize()) event.Skip() def OnPopUp(self, event): tabmenu = wx.Menu() tabmenu.Append(self.ID_CLOSE, "&Close Panel") ht = self.HitTest(event.GetPosition())[0] if ht > -1: self.SetSelection(ht) self.PopupMenu(tabmenu, event.GetPosition()) tabmenu.Destroy() #************************************************* #Panel class for panels with a single stc. class drPanel(wx.Panel): def __init__(self, parent, id): wx.Panel.__init__(self, parent, id) self.grandparent = parent.GetGrandParent() self.stc = None self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) def OnKeyDown(self, event): self.grandparent.GetParent().RunShortcuts(event) def OnSize(self, event): if self.stc is not None: self.stc.SetSize(self.GetSize()) if event is not None: event.Skip() def SetSTC(self, stc): self.stc = stc #************************************************* #Panel class for side panels. class drSidePanel(wx.Panel): def __init__(self, parent, id): wx.Panel.__init__(self, parent, id) self.panel = None self.parent = parent self.grandparent = parent.GetGrandParent() self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) self.Bind(wx.EVT_SIZE, self.OnSize) def OnSize(self, event): if self.panel is not None: self.panel.SetSize(self.GetSize()) if event is not None: event.Skip() def OnKeyDown(self, event): self.grandparent.GetParent().RunShortcuts(event) def SetPanel(self, panel): self.panel = panel #************************************************* #View In Panel class drSplitTextPanel(wx.Panel): def __init__(self, parent, grandparent, targetstc, position, index): docid = grandparent.txtDocument.GetId() wx.Panel.__init__(self, parent, docid) ID_CLOSE = grandparent.GetNewId() self.position = position self.index = index self.parent = parent self.grandparent = grandparent if docid == targetstc.GetId(): sv = -1 else: sv = 1 self.txtDoc = DrText(self, docid, grandparent, SplitView=sv) self.txtDoc.SetupPrefsDocument() self.txtDoc.SetDocPointer(targetstc.GetDocPointer()) self.txtDoc.GotoPos(targetstc.GetCurrentPos()) self.txtDoc.ScrollToLine(targetstc.GetCurrentLine()) self.label = wx.TextCtrl(self, -1, " Viewing: " + targetstc.GetFilenameTitle(), size=(150, -1), style=wx.TE_READONLY) self.btnClose = wx.Button(self, ID_CLOSE, "Close") self.topSizer = wx.BoxSizer(wx.HORIZONTAL) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.topSizer.Add(self.label, 1, wx.EXPAND) self.topSizer.Add(self.btnClose, 0, wx.SHAPED | wx.ALIGN_RIGHT) self.theSizer.Add(self.topSizer, 0, wx.EXPAND) self.theSizer.Add(self.txtDoc, 1, wx.EXPAND) self.SetAutoLayout(True) self.SetSizer(self.theSizer) text = self.txtDoc.GetText() #Scrolling bufferstring = drEncoding.EncodeText(self.grandparent, '000', self.txtDoc.GetEncoding()) lines = text.split(self.txtDoc.GetEndOfLineCharacter()) spaces = "\t".expandtabs(self.grandparent.prefs.doctabwidth[self.txtDoc.filetype]) line = "" length = 0 for l in lines: if len(l) > length: length = len(l) line = l line = line.replace('\t', spaces) self.txtDoc.SetScrollWidth(self.txtDoc.TextWidth(wx.stc.STC_STYLE_DEFAULT, line + bufferstring)) self.txtDoc.SetXOffset(0) #/End Scrolling self.Bind(wx.EVT_BUTTON, self.OnbtnClose, id=ID_CLOSE) self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) def OnbtnClose(self, event): self.grandparent.mainpanel.ClosePanel(self.position, self.index) def OnKeyDown(self, event): self.grandparent.RunShortcuts(event) drpython-3.11.1/drpython_wx26.py0000644000175000017500000000302011150445515017355 0ustar dktrkranzdktrkranz#!/usr/bin/env python # Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2004 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # To Run: # # Windows Users: Make sure ".pyw" files are associated with the pythonw.exe file in your python-directory. # # Linux/Unix Users: Make sure the first line of this file is the correct path to python: # "/bin/python", "/usr/bin/python", "/usr/local/bin/python" are all suggestions. # Using "/bin/env python" should find it for you though. # ## testfile for older version import wxversion wxversion.select("2.60-msw-ansi") if __name__ == '__main__': import drpython app = drpython.DrApp(0) app.MainLoop() drpython-3.11.1/drShortcutsFile.py0000644000175000017500000001751011235245720017755 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Shortcuts File import drPrefsFile from drShortcuts import BuildShortcutString, GetKeycodeStringFromShortcut, MatchControl, MatchShift, MatchAlt, MatchMeta def GetShortcutList(): #Shortcut List return ["Check Syntax", "Close", "Close All Documents", "Close All Other Documents", "Close Prompt", "Comment", "Customize Shortcuts", "Customize Pop Up Menu", "Customize ToolBar", "Dedent", "Dynamic DrScript", "End", "Exit", "Expand All", "Find", "Find And Complete", "Find Next", "Find Previous", "First Document", "Fold All", "Go To", "Go To Block End", "Go To Block Start", "Go To Class End", "Go To Class Start", "Go To Def End", "Go To Def Start", "Help", "Indent", "Insert Regular Expression", "Insert Separator", "Last Document", "New", "Next Document", "Open", "Open Imported Module", "Preferences", "Previous Document", "Print File", "Print Prompt", "Print Setup", "Python", "Reload File", "Replace", "Restore From Backup", "Run", "Save", "Save All Documents", "Save As", "Save Prompt Output To File", "Set Arguments", "Source Browser Go To", "Toggle Fold", "Toggle Maximize", "Toggle Prompt","Toggle Source Browser", "Toggle View Whitespace", "UnComment", "View In Left Panel", "View In Right Panel", "View In Top Panel", "View Python Docs", "View Regular Expression Howto", "View WxWidgets Docs"] def GetSTCShortcutList(): #STC Shortcuts: return ["Back Tab", "Cancel", "Char Left", "Char Left Extend", "Char Left Rect Extend", "Char Right", "Char Right Extend", "Char Right Rect Extend", "Copy", "Cut", "Delete", "Delete Back", "Delete Back Not Line", "Delete Line Left", "Delete Line Right", "Delete Word Left", "Delete Word Right", "Document End", "Document End Extend", "Document Start", "Document Start Extend", "Form Feed", "Home", "Home Display", "Home Display Extend", "Home Extend", "Home Rect Extend", "Line Cut", "Line Delete", "Line Down", "Line Down Extend", "Line Down Rect Extend", "Line Duplicate", "Line End", "Line End Display", "Line End Display Extend", "Line End Extend", "Line End Rect Extend", "Line Scroll Down", "Line Scroll Up", "Line Transpose", "Line Up", "Line Up Extend", "Line Up Rect Extend", "Lowercase", "New Line", "Page Down", "Page Down Extend", "Page Down Rect Extend", "Page Up", "Page Up Extend", "Page Up Rect Extend", "Paste", "Redo", "Select All", "Tab", "Toggle Overtype", "Undo", "Uppercase", "Visible Character Home", "Visible Character Home Extend", "World Left", "Word Left Extend", "Word Part Left", "Word Part Left Extend", "Word Part Right", "Word Part Right Extend", "Word Right", "Word Right Extend", "Zoom In", "Zoom Out"] def IsBuiltIn(name): return 1 def GetDefaultProgramShortcuts(ShortcutList): shortcutArray = [] l = len(ShortcutList) x = 0 while x < l: shortcutArray.append('') x = x + 1 return shortcutArray def GetDefaultSTCShortcuts(): return GetDefaultProgramShortcuts(GetSTCShortcutList()) def GetDefaultShortcuts(): import sys if sys.platform.find("linux") > -1: ignorestring = "Meta," else: ignorestring = "" sA = GetDefaultProgramShortcuts(GetShortcutList()) return sA, ignorestring def ReadSTCShortcuts(filename): f = open(filename, 'rb') text = f.read() f.close() shortcutArray = [] shortcutNames = [] x = 0 progshortcutlist = GetSTCShortcutList() l = len(progshortcutlist) while x < l: shortcutNames.append(progshortcutlist[x]) shortcuttext = drPrefsFile.ExtractPreferenceFromText(text, progshortcutlist[x]) Keycode = drPrefsFile.ExtractPreferenceFromText(shortcuttext, "keycode") modifiers = drPrefsFile.ExtractPreferenceFromText(shortcuttext, "mod") shortcutArray.append(BuildShortcutString(Keycode, MatchControl(modifiers), MatchShift(modifiers), MatchAlt(modifiers), MatchMeta(modifiers))) x = x + 1 return shortcutArray, shortcutNames, '' def ReadShortcuts(filename, getIgnoreString = 1): shortcutNames = [] if getIgnoreString: f = open(filename, 'rb') text = f.read() f.close() shortcutArray = [] ignorestring = "" ignorestring = drPrefsFile.ExtractPreferenceFromText(text, "ignore") x = 0 progshortcutlist = GetShortcutList() l = len(progshortcutlist) while x < l: shortcutNames.append(progshortcutlist[x]) shortcuttext = drPrefsFile.ExtractPreferenceFromText(text, progshortcutlist[x]) Keycode = drPrefsFile.ExtractPreferenceFromText(shortcuttext, "keycode") modifiers = drPrefsFile.ExtractPreferenceFromText(shortcuttext, "mod") shortcutArray.append(BuildShortcutString(Keycode, MatchControl(modifiers), MatchShift(modifiers), MatchAlt(modifiers), MatchMeta(modifiers))) x = x + 1 else: f = open(filename, 'rb') shortcutArray = [] ignorestring = "" x = 0 line = f.readline() while len(line) > 0: s = line.find("<") e = line.find(">") if (s > -1) and (e > -1): shortcutNames.append(line[s+1:e]) Keycode = drPrefsFile.ExtractPreferenceFromText(line, "keycode") modifiers = drPrefsFile.ExtractPreferenceFromText(line, "mod") shortcutArray.append(BuildShortcutString(Keycode, MatchControl(modifiers), MatchShift(modifiers), MatchAlt(modifiers), MatchMeta(modifiers))) x = x + 1 line = f.readline() f.close() return shortcutArray, shortcutNames, ignorestring def WriteShortcuts(filename, shortcuts, shortcutNames, ignorestring = "", writeIgnoreString = True): f = open(filename, 'wb') if writeIgnoreString: #Ignore String f.write("" + ignorestring + "\n") allowControl = not (ignorestring.find("Control") > -1) allowShift = not (ignorestring.find("Shift") > -1) allowMeta = not (ignorestring.find("Meta") > -1) allowAlt = not (ignorestring.find("Alt") > -1) l = len(shortcuts) x = 0 while x < l: writestring = "<" + shortcutNames[x] + ">" if MatchControl(shortcuts[x]) and allowControl: writestring = writestring + "Control," if MatchShift(shortcuts[x]) and allowShift: writestring = writestring + "Shift," if MatchAlt(shortcuts[x]) and allowAlt: writestring = writestring + "Alt," if MatchMeta(shortcuts[x]) and allowMeta: writestring = writestring + "Meta," writestring = writestring + "" + GetKeycodeStringFromShortcut(shortcuts[x]) + \ "\n" f.write(writestring) x = x + 1 f.close() drpython-3.11.1/drFileDialog.py0000644000175000017500000012143711235243060017155 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #File Dialog import os, re, stat, time, sys, locale import wx import drScrolledMessageDialog import lnkDecoderRing import drEncoding class FileListCtrl(wx.ListView): def __init__(self, parent, id, fsize, fstyle): wx.ListView.__init__(self, parent, id, size=fsize, style=fstyle) bDir = parent.parent.bitmapdirectory + '/16/' self.parent = parent self.grandparent = parent.parent self.IsDetailed = False self.pywfilter = re.compile('.*\.pyw$') self.pyfilter = re.compile('.*\.py$') self.imagelist = wx.ImageList(16, 16) self.images = [wx.BitmapFromImage(wx.Image(bDir+'folder.png', wx.BITMAP_TYPE_PNG)), \ wx.BitmapFromImage(wx.Image(bDir+'py.png', wx.BITMAP_TYPE_PNG)), \ wx.BitmapFromImage(wx.Image(bDir+'pyw.png', wx.BITMAP_TYPE_PNG)), \ wx.BitmapFromImage(wx.Image(bDir+'unknown.png', wx.BITMAP_TYPE_PNG)), \ wx.BitmapFromImage(wx.Image(bDir+'up.png', wx.BITMAP_TYPE_PNG)), \ wx.BitmapFromImage(wx.Image(bDir+'down.png', wx.BITMAP_TYPE_PNG))] map(self.imagelist.Add, self.images) self.AssignImageList(self.imagelist, wx.IMAGE_LIST_SMALL) self.directories = [''] self.dirposition = -1 self.ShowHiddenFiles = False self.DataArray = [] self.currentcolumn = 0 self.direction = [0, -1, -1, -1, -1] self.timeformat = '%m/%d/%Y %H:%M:%S' self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColumnClick) self.Bind(wx.EVT_SIZE, self.OnSize) def GetDirectory(self): try: return self.directories[self.dirposition] except: return self.directories[0] def GoBack(self, filter): self.dirposition = self.dirposition - 1 if self.dirposition < 0: self.dirposition = 0 self.SetDirectoryTo(self.directories[self.dirposition], filter, False) def GoForward(self, filter): self.dirposition = self.dirposition + 1 if self.dirposition >= len(self.directories): self.dirposition = len(self.directories) - 1 self.SetDirectoryTo(self.directories[self.dirposition], filter, False) def IsDirectory(self, index): return self.DataArray[index][2] == '' def OnColumnClick(self, event): oldcol = self.currentcolumn self.currentcolumn = event.GetColumn() self.ClearColumnImage(oldcol) if oldcol != self.currentcolumn: self.direction[oldcol] = -1 if self.direction[self.currentcolumn] == -1: self.direction[self.currentcolumn] = 1 self.SetColumnImage(self.currentcolumn, 5) else: self.direction[self.currentcolumn] = not self.direction[self.currentcolumn] if self.direction[self.currentcolumn]: self.SetColumnImage(self.currentcolumn, 5) else: self.SetColumnImage(self.currentcolumn, 4) self.SortItems(self.SortData) def OnSize(self, event): if self.IsDetailed: width = self.GetSizeTuple()[0] self.SetColumnWidth(0, int(width * .4)) self.SetColumnWidth(1, int(width * .15)) self.SetColumnWidth(2, int(width * .15)) self.SetColumnWidth(3, int(width * .15)) self.SetColumnWidth(4, int(width * .15)) if event is not None: event.Skip() def SetDirectoryTo(self, directory, filter="*", updatedirectories=True): self.parent.cboFile.SetValue('') self.parent.cboFile.Clear() directory = os.path.normpath(directory).replace('\\', '/').replace('//', '/') if not os.path.exists(directory): return self.parent.txtDirectory.SetValue(directory) try: if wx.USE_UNICODE: uthelist = os.listdir(directory) thelist = [] if self.grandparent.prefs.defaultencoding: for u in uthelist: try: thelist.append(u) except: wx.MessageBox ("Cannot show files:\nPlease check in Options=>Preferences=>General=>Default Encoding!", "Error Decoding Directory Entry: Not Ascii.", wx.ICON_INFORMATION, self) return else: for u in uthelist: if not drEncoding.CheckAscii(u): wx.MessageBox ("Cannot show files:\nNo Encoding is set up.\nPlease check in Options=>Preferences=>General=>Default Encoding!", "Error Decoding Directory Entry: Not Ascii.", wx.ICON_INFORMATION, self) return else: thelist.append(u) else: thelist = os.listdir(directory) if updatedirectories: self.directories = self.directories[:self.dirposition+1] self.directories.append(directory) self.dirposition = self.dirposition + 1 dirs = [] l = len(thelist) x = 0 while x < l: if os.path.isdir(directory + '/' + thelist[x]): dirs.append(thelist.pop(x)) x = x - 1 l = l - 1 x = x + 1 self.DeleteAllItems() #franz, 15.03.2005: thelist.sort(lambda x,y: cmp(x.lower(), y.lower())) dirs.sort(lambda x,y: cmp(x.lower(), y.lower())) filter = filter + ";" + self.parent.parent.prefs.constantwildcard filter = filter.replace('.', '\.').replace('*', '.*').replace(';', '$|') + '$' refilter = re.compile(filter) dirs.insert(0, '..') for item in dirs: additem = True if not self.ShowHiddenFiles: if item[0] == '.': if item != '..': additem = False if additem: i = self.GetItemCount() self.InsertStringItem(i, item) self.SetItemImage(i, 0, 0) if self.IsDetailed: self.SetItemData(i, i) st = os.stat(directory + '/' + item) mtime = time.strftime(self.timeformat ,time.localtime(st.st_mtime)) mmode = str(oct(stat.S_IMODE(st.st_mode))) self.DataArray.append((item, '', '', mtime, mmode)) self.SetStringItem(i, 1, '') self.SetStringItem(i, 2, '') self.SetStringItem(i, 3, mtime) self.SetStringItem(i, 4, mmode) for item in thelist: additem = True if not self.ShowHiddenFiles: if item[0] == '.': additem = False if additem: if refilter.match(item): self.parent.cboFile.Append(item) i = self.GetItemCount() self.InsertStringItem(i, item) if self.pywfilter.match(item): self.SetItemImage(i, 2, 2) elif self.pyfilter.match(item): self.SetItemImage(i, 1, 1) else: self.SetItemImage(i, 3, 3) if self.IsDetailed: self.SetItemData(i, i) st = os.stat(directory + '/' + item) size = str(st.st_size) mtime = time.strftime(self.timeformat ,time.localtime(st.st_mtime)) mmode = str(oct(stat.S_IMODE(st.st_mode))) type_ = item.rfind('.') if type > -1: type_ = item[type_+1:] else: type_ = '' self.DataArray.append((item, size, type_, mtime, mmode)) self.SetStringItem(i, 1, str(size)) self.SetStringItem(i, 2, type_) self.SetStringItem(i, 3, mtime) self.SetStringItem(i, 4, mmode) except: self.grandparent.ShowMessage('Error Setting Directory To:' + directory, 'File Dialog Error') def SetShowHiddenFiles(self, showhidden): self.ShowHiddenFiles = showhidden def SetViewDetailed(self, fstyle = 0): self.DeleteAllItems() self.SetWindowStyleFlag(fstyle|wx.LC_REPORT) self.IsDetailed = True self.InsertColumn(0, 'Name') self.InsertColumn(1, 'Size') self.InsertColumn(2, 'Type') self.InsertColumn(3, 'Modified') self.InsertColumn(4, 'Permissions') self.SetColumnImage(0, 5) self.OnSize(None) def SetViewList(self, fstyle = 0): self.DeleteAllItems() self.SetWindowStyleFlag(fstyle|wx.LC_LIST) self.IsDetailed = False def SortData(self, item1, item2): i1 = self.DataArray[item1][self.currentcolumn] i2 = self.DataArray[item2][self.currentcolumn] i1isdir = self.IsDirectory(item1) i2isdir = self.IsDirectory(item2) if i1isdir and not i2isdir: if self.direction[self.currentcolumn]: return 1 else: return -1 elif not i1isdir and i2isdir: if self.direction[self.currentcolumn]: return -1 else: return 1 elif i1isdir and i2isdir: if self.currentcolumn == 1: i1 = self.DataArray[item1][0] i2 = self.DataArray[item2][0] elif self.currentcolumn == 3: it1 = time.strptime(i1, self.timeformat) it2 = time.strptime(i2, self.timeformat) i2 = it1[0] i1 = it2[0] x = 1 while (i1 == i2) and (x < 6): i2 = it1[x] i1 = it2[x] x = x + 1 if self.direction[self.currentcolumn]: if i1 < i2: return 1 if i1 > i2: return -1 else: if i1 < i2: return -1 if i1 > i2: return 1 if self.currentcolumn == 1: try: i1 = int(i1) except: i1 = 0 try: i2 = int(i2) except: i1 = 0 elif self.currentcolumn == 3: it1 = time.strptime(i1, self.timeformat) it2 = time.strptime(i2, self.timeformat) i1 = it1[0] i2 = it2[0] x = 1 while (i1 == i2) and (x < 6): i1 = it1[x] i2 = it2[x] x = x + 1 if self.direction[self.currentcolumn]: if i1 < i2: return -1 if i1 > i2: return 1 else: if i1 < i2: return 1 if i1 > i2: return -1 return 0 class DirPanel(wx.Dialog): def __init__(self, parent, id, pos, size): wx.Dialog.__init__(self, parent, id, 'Look In:', pos, size) self.parent = parent self.ID_CLOSE = 3031 self.dirControl = wx.GenericDirCtrl(self, -1, size=size, style=wx.DIRCTRL_DIR_ONLY) self.btnClose = wx.Button(self, self.ID_CLOSE, 'Close') self.theSizer = wx.BoxSizer(wx.VERTICAL) self.theSizer.Add(self.dirControl, 1, wx.EXPAND) self.theSizer.Add(self.btnClose, 0, wx.SHAPED | wx.ALIGN_CENTER) self.SetAutoLayout(True) self.SetSizerAndFit(self.theSizer) self.Bind(wx.EVT_BUTTON, self.OnClose, id=self.ID_CLOSE) def GetPath(self): return self.dirControl.GetPath() def OnClose(self, event): self.EndModal(0) class drFileDialog(wx.Dialog): def __init__(self, parent, title, wildcard, point=wx.DefaultPosition, size=wx.DefaultSize, IsASaveDialog=0, MultipleSelection=0, ShowRecentFiles=0): wx.Dialog.__init__(self, parent, -1, title, point, size, wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.THICK_FRAME | wx.RESIZE_BORDER) self.parent = parent self.IsASaveDialog = IsASaveDialog self.MultipleSelection = MultipleSelection if IsASaveDialog: self.MultipleSelection = False #Constants: self.ID_BOOKMARKS = 3001 self.ID_DISPLAY_LIST = 3002 self.ID_DISPLAY_DETAILED = 3003 self.ID_BACK = 3004 self.ID_FORWARD = 3005 self.ID_UP = 3006 self.ID_HOME = 3011 self.ID_REFRESH = 3007 self.ID_NEW_DIRECTORY = 3008 self.ID_DELETE_FILE = 3009 self.ID_BROWSE = 3010 self.ID_SHOW_HIDDEN_FILES = 3011 self.ID_LIST_FILES = 3015 self.ID_DIR = 3020 self.ID_FILE = 3030 self.ID_EXTENSION = 3031 self.ID_SHOW_READONLY = 3032 self.ID_ENCODING = 3035 self.ID_OK = 3040 self.ID_CANCEL = 3041 self.ID_BOOKMARK_MENU = 3100 self.ID_BOOKMARK_ADD = 3101 self.ID_BOOKMARK_FILE = 3102 self.ID_EDIT_BOOKMARKS = 3103 self.ID_BOOKMARK_BASE = 3150 #/Constants #Components: #ShowRecentFiles is not used anymore. self.cboFile = wx.ComboBox(self, self.ID_FILE, size=wx.Size(500, -1)) self.btnOk = wx.Button(self, self.ID_OK, " &Ok ") self.cboExtension = wx.ComboBox(self, self.ID_EXTENSION, size=wx.Size(250, -1)) try: defaultlocale = locale.getdefaultlocale()[1] except: defaultlocale = None if defaultlocale is not None: encodings = ['', defaultlocale, 'ascii', 'latin-1', 'cp1252', 'utf-8', 'utf-16'] else: encodings = ['', 'ascii', 'latin-1', 'cp1252', 'utf-8', 'utf-16'] self.cboEncoding = wx.ComboBox(self, self.ID_ENCODING, size=wx.Size(250, -1), choices=encodings) if not self.parent.PLATFORM_IS_WIN: self.chkShowHiddenFiles = wx.CheckBox(self, self.ID_SHOW_HIDDEN_FILES, ' Show Hidden Files ') self.btnCancel = wx.Button(self, self.ID_CANCEL, " &Cancel ") bDir = self.parent.bitmapdirectory + '/24/' self.btnDisplayList = wx.BitmapButton(self, self.ID_DISPLAY_LIST, wx.BitmapFromImage(wx.Image(bDir+'list.png', wx.BITMAP_TYPE_PNG))) self.btnDisplayDetailed = wx.BitmapButton(self, self.ID_DISPLAY_DETAILED, wx.BitmapFromImage(wx.Image(bDir+'detailed.png', wx.BITMAP_TYPE_PNG))) self.btnBack = wx.BitmapButton(self, self.ID_BACK, wx.BitmapFromImage(wx.Image(bDir+'back.png', wx.BITMAP_TYPE_PNG))) self.btnForward = wx.BitmapButton(self, self.ID_FORWARD, wx.BitmapFromImage(wx.Image(bDir+'forward.png', wx.BITMAP_TYPE_PNG))) self.btnUp = wx.BitmapButton(self, self.ID_UP, wx.BitmapFromImage(wx.Image(bDir+'up.png', wx.BITMAP_TYPE_PNG))) self.btnHome = wx.BitmapButton(self, self.ID_HOME, wx.BitmapFromImage(wx.Image(bDir+'home.png', wx.BITMAP_TYPE_PNG))) self.btnRefresh = wx.BitmapButton(self, self.ID_REFRESH, wx.BitmapFromImage(wx.Image(bDir+'Reload File.png', wx.BITMAP_TYPE_PNG))) self.btnBookmarks = wx.BitmapButton(self, self.ID_BOOKMARKS, wx.BitmapFromImage(wx.Image(bDir+'bookmarks.png', wx.BITMAP_TYPE_PNG))) self.btnDir = wx.BitmapButton(self, self.ID_BROWSE, wx.BitmapFromImage(wx.Image(bDir+'folder.png', wx.BITMAP_TYPE_PNG))) self.btnNewDirectory = wx.BitmapButton(self, self.ID_NEW_DIRECTORY, wx.BitmapFromImage(wx.Image(bDir+'new directory.png', wx.BITMAP_TYPE_PNG))) self.btnDeleteFile = wx.BitmapButton(self, self.ID_DELETE_FILE, wx.BitmapFromImage(wx.Image(bDir+'Delete.png', wx.BITMAP_TYPE_PNG))) self.btnDisplayList.SetToolTipString('List View') self.btnDisplayDetailed.SetToolTipString('Detailed View') self.btnBookmarks.SetToolTipString('Bookmarks') self.btnBack.SetToolTipString('Back') self.btnForward.SetToolTipString('Forward') self.btnUp.SetToolTipString('Up') self.btnHome.SetToolTipString('Home') self.btnRefresh.SetToolTipString('Refresh') self.btnDir.SetToolTipString('Look In') self.btnNewDirectory.SetToolTipString('New Directory') self.btnDeleteFile.SetToolTipString('Delete') self.txtDirectory = wx.TextCtrl(self, self.ID_DIR, '', size=wx.Size(350, -1), style=wx.TE_PROCESS_ENTER) if MultipleSelection: self.lstFiles = FileListCtrl(self, self.ID_LIST_FILES, wx.Size(500, 230), wx.LC_LIST) else: self.lstFiles = FileListCtrl(self, self.ID_LIST_FILES, wx.Size(500, 230), wx.LC_LIST | wx.LC_SINGLE_SEL) self.btnOk.SetDefault() self.cboFile.SetFocus() #/Components #Data swildcards = wildcard.split('|') self.wildcards = [] x = 0 l = len(swildcards) - 1 while x < l: self.cboExtension.Append(swildcards[x]) self.wildcards.append(swildcards[x+1]) x = x + 2 self.cboExtension.SetValue(swildcards[0]) wx.CallAfter (self.cboExtension.SetMark, 0, 0) if self.parent.prefs.defaultencoding: if not self.parent.prefs.defaultencoding in encodings: self.cboEncoding.Append(self.parent.prefs.defaultencoding) self.cboEncoding.SetSelection(encodings.index(self.parent.prefs.defaultencoding)) else: self.cboEncoding.SetSelection(0) self.currentextension = 0 self.lstFiles.SetDirectoryTo(self.parent.ddirectory, self.wildcards[self.currentextension]) self.bookmarks = [] #lnk Replace Table: if not self.parent.PLATFORM_IS_WIN: self.lnkReplaceA = [] self.lnkReplaceB = [] replacestrings = self.parent.prefs.windowsshortcutreplacetable.split('#') for rstring in replacestrings: if rstring: a, b = rstring.split(',') self.lnkReplaceA.append(a) self.lnkReplaceB.append(b) #/Data #Sizer: self.theSizer = wx.BoxSizer(wx.VERTICAL) self.commandSizer = wx.BoxSizer(wx.HORIZONTAL) self.commandSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.commandSizer.Add(self.btnDisplayList, 0, wx.SHAPED) self.commandSizer.Add(self.btnDisplayDetailed, 0, wx.SHAPED) self.commandSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.commandSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.commandSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.commandSizer.Add(self.btnBack, 0, wx.SHAPED) self.commandSizer.Add(self.btnForward, 0, wx.SHAPED) self.commandSizer.Add(self.btnUp, 0, wx.SHAPED) self.commandSizer.Add(self.btnHome, 0, wx.SHAPED) self.commandSizer.Add(self.btnRefresh, 0, wx.SHAPED) self.commandSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.commandSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.commandSizer.Add(self.btnBookmarks, 0, wx.SHAPED) self.commandSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.commandSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.commandSizer.Add(self.btnDir, 0, wx.SHAPED) if not self.parent.PLATFORM_IS_WIN: self.commandSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED | wx.ALIGN_RIGHT) self.commandSizer.Add(self.chkShowHiddenFiles, 1, wx.SHAPED | wx.ALIGN_RIGHT) else: self.commandSizer.Add(wx.StaticText(self, -1, ' '), 1, wx.EXPAND) self.commandSizer.Add(self.btnNewDirectory, 0, wx.SHAPED) self.commandSizer.Add(self.btnDeleteFile, 0, wx.SHAPED) self.commandSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.dirSizer = wx.BoxSizer(wx.HORIZONTAL) self.dirSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.EXPAND) self.dirSizer.Add(self.txtDirectory, 9, wx.EXPAND) self.dirSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.EXPAND) self.listSizer = wx.BoxSizer(wx.HORIZONTAL) self.listSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.EXPAND) self.listSizer.Add(self.lstFiles, 9, wx.EXPAND) self.listSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.EXPAND) self.OkSizer = wx.BoxSizer(wx.HORIZONTAL) self.OkSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.EXPAND) self.OkSizer.Add(self.cboFile, 9, wx.EXPAND | wx.ALIGN_LEFT) self.OkSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.EXPAND) self.OkSizer.Add(self.btnOk, 0, wx.ALIGN_RIGHT) self.OkSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.EXPAND) self.CancelSizer = wx.BoxSizer(wx.HORIZONTAL) self.CancelSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.EXPAND) self.CancelSizer.Add(self.cboExtension, 2, wx.EXPAND) self.CancelSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.EXPAND) self.CancelSizer.Add(self.cboEncoding, 2, wx.EXPAND) self.CancelSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.EXPAND) self.CancelSizer.Add(self.btnCancel, 0, wx.ALIGN_RIGHT) self.CancelSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.EXPAND) self.theSizer.Add(self.commandSizer, 0, wx.EXPAND | wx.ALIGN_CENTER) self.theSizer.Add(self.dirSizer, 0, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.EXPAND) self.theSizer.Add(self.listSizer, 9, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.EXPAND) self.theSizer.Add(self.OkSizer, 0, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.EXPAND) self.theSizer.Add(self.CancelSizer, 0, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.EXPAND) self.SetAutoLayout(True) self.SetSizerAndFit(self.theSizer) #/Sizer #Events: self.Bind(wx.EVT_BUTTON, self.OnbtnUp, id=self.ID_UP) self.Bind(wx.EVT_BUTTON, self.OnbtnBack, id=self.ID_BACK) self.Bind(wx.EVT_BUTTON, self.OnbtnForward, id=self.ID_FORWARD) self.Bind(wx.EVT_BUTTON, self.OnbtnHome, id=self.ID_HOME) self.Bind(wx.EVT_BUTTON, self.OnbtnRefresh, id=self.ID_REFRESH) self.Bind(wx.EVT_BUTTON, self.OnbtnBookmarks, id=self.ID_BOOKMARKS) self.Bind(wx.EVT_BUTTON, self.OnbtnNewDirectory, id=self.ID_NEW_DIRECTORY) self.Bind(wx.EVT_BUTTON, self.OnbtnDelete, id=self.ID_DELETE_FILE) self.Bind(wx.EVT_BUTTON, self.OnbtnDisplayList, id=self.ID_DISPLAY_LIST) self.Bind(wx.EVT_BUTTON, self.OnbtnDisplayDetailed, id=self.ID_DISPLAY_DETAILED) self.Bind(wx.EVT_BUTTON, self.OnbtnCancel, id=self.ID_CANCEL) self.Bind(wx.EVT_BUTTON, self.OnbtnOk, id=self.ID_OK) self.Bind(wx.EVT_COMBOBOX, self.OnExtension, id=self.ID_EXTENSION) if not self.parent.PLATFORM_IS_WIN: self.Bind(wx.EVT_CHECKBOX, self.OnShowHiddenFiles, id=self.ID_SHOW_HIDDEN_FILES) self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnFileSelected, id=self.ID_LIST_FILES) self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnFileActivated, id=self.ID_LIST_FILES) self.Bind(wx.EVT_TEXT_ENTER, self.OnDir, id=self.ID_DIR) self.Bind(wx.EVT_TEXT_ENTER, self.OnbtnOk, id=self.ID_FILE) self.Bind(wx.EVT_CHAR, self.OnChar) self.cboFile.Bind(wx.EVT_CHAR, self.OnChar) self.Bind(wx.EVT_BUTTON, self.OnBrowse, id=self.ID_BROWSE) #/Events self.parent.LoadDialogSizeAndPosition(self, 'filedialog.sizeandposition.dat') def OnCloseW(self, event): self.parent.SaveDialogSizeAndPosition(self, 'filedialog.sizeandposition.dat') if event is not None: event.Skip() def EndAndCheck(self, value): if self.IsASaveDialog: filename = self.GetPath() if os.path.exists(filename): msg = 'File "' + filename + '" already exists. Overwrite?' # d = wx.MessageDialog(self, msg, "OverWrite File?", wx.YES_NO | wx.ICON_QUESTION) # answer = d.ShowModal() # d.Destroy() # if answer == wx.ID_NO: # return if not self.parent.Ask(msg, "OverWrite File?"): return self.OnCloseW(None) self.EndModal(value) def GetEncoding(self): return self.cboEncoding.GetValue() def getNormedPath(self, filename): if filename.find(".lnk") > -1: filename = self.HandleLnk(filename) else: filename = filename.replace('\\', '/') return filename def GetPath(self): path = self.getNormedPath(self.cboFile.GetValue()) if self.IsASaveDialog and self.parent.prefs.defaultextension: if path.find('.') == -1: path += '.py' return path def GetPaths(self): i = self.lstFiles.GetFirstSelected() if i == -1: return [self.getNormedPath(self.cboFile.GetValue())] if (self.lstFiles.GetItemText(i) != self.cboFile.GetValue()) and (self.lstFiles.GetNextSelected(i) == -1): return [self.getNormedPath(self.cboFile.GetValue())] dir = self.lstFiles.GetDirectory() filelist = [self.getNormedPath(os.path.join(dir, self.lstFiles.GetItemText(i)).replace('\\', '/'))] y = i y = self.lstFiles.GetNextSelected(y) while y != -1: filelist.append(self.getNormedPath(os.path.join(dir, self.lstFiles.GetItemText(y)).replace('\\', '/'))) y = self.lstFiles.GetNextSelected(y) currentfile = self.getNormedPath(self.cboFile.GetValue().replace('\\', '/')) if not (currentfile in filelist): filelist.insert(0, currentfile) return filelist def HandleLnk(self, filename): filename = lnkDecoderRing.ReadLink(filename) if self.parent.PLATFORM_IS_WIN: return filename else: x = 0 for rA in self.lnkReplaceA: result = re.match(rA + '\:', filename) resultA = re.match(rA, filename) if result is not None: if self.lnkReplaceB[x].find('@') > 0: return filename.replace(result.group(), self.lnkReplaceB[x].replace('@', resultA.group().lower())) elif self.lnkReplaceB[x].find('@') > 0: return filename.replace(result.group(), self.lnkReplaceB[x].replace('@', resultA.group())) else: return filename.replace(result.group(), self.lnkReplaceB[x]) x += 1 self.parent.ShowMessage('Windows Shortcut Error:\n\nCould not Find: "%s".' % (filename), 'Error') return None def HandleDesktop(self, filename): f = file(filename, 'rb') lines = f.read().split() f.close() for line in lines: if line.find('URL=') > -1: return line[4:] return None def OnAddBookmark(self, event): try: bookfile = self.parent.datdirectory + "/bookmarks.dat" f = file(bookfile, 'rb') text = f.read() f.close() text = text.strip() cdir = self.lstFiles.GetDirectory() text = text + '\n\t' + cdir + '\n' f = file(bookfile, 'wb') f.write(text) f.close() self.parent.bookmarksmenu.reloadBookmarks() if self.parent.prefs.enablefeedback: self.parent.ShowMessage('Successfully Added ' + cdir, 'Success') except: self.parent.ShowMessage('Error Adding Bookmark', 'Error') def OnBookmark(self, event): bookmarkindex = event.GetId() - self.ID_BOOKMARK_BASE if not (os.path.exists(self.bookmarks[bookmarkindex])): drScrolledMessageDialog.ShowMessage(self.parent, ("Error with: " + self.bookmarks[bookmarkindex] + "\nBookmark does not actually exist.\n"), "Error") return if os.path.isdir(self.bookmarks[bookmarkindex]): self.lstFiles.SetDirectoryTo(self.bookmarks[bookmarkindex], self.wildcards[self.currentextension]) return self.cboFile.SetValue(self.bookmarks[bookmarkindex]) def OnbtnBack(self, event): self.lstFiles.GoBack(self.wildcards[self.currentextension]) def OnbtnBookmarks(self, event): bookfile = self.parent.datdirectory + "/bookmarks.dat" bookmarksmenu = wx.Menu() bookmarksmenu.Append(self.ID_BOOKMARK_ADD, 'Bookmark Current Directory') bookmarksmenu.Append(self.ID_BOOKMARK_FILE, 'File Current Directory...') bookmarksmenu.Append(self.ID_EDIT_BOOKMARKS, 'Edit Bookmarks...') bookmarksmenu.AppendSeparator() self.Bind(wx.EVT_MENU, self.OnAddBookmark, id=self.ID_BOOKMARK_ADD) self.Bind(wx.EVT_MENU, self.OnFileBookmark, id=self.ID_BOOKMARK_FILE) self.Bind(wx.EVT_MENU, self.parent.OnEditBookmarks, id=self.ID_EDIT_BOOKMARKS) self.bookmarks = [] if os.path.exists(bookfile): try: #Read from the file f = open(bookfile, 'r') folders = [bookmarksmenu] folderindex = 0 menuTitles = [] menuTitleindex = -1 lastCount = 1 bookmarkcount = 0 #Skip the First Line line = f.readline() #Initialize line = f.readline() while line: c = line.count('\t') line = line[c:].rstrip() while lastCount > c: folders[(folderindex - 1)].AppendMenu(self.ID_BOOKMARK_MENU, menuTitles.pop(), folders.pop()) folderindex = folderindex - 1 menuTitleindex = menuTitleindex - 1 lastCount = lastCount - 1 if line[0] == '>': folders.append(wx.Menu()) menuTitles.append(line[1:]) folderindex = folderindex + 1 menuTitleindex = menuTitleindex + 1 c = c + 1 else: self.bookmarks.append(line) self.Bind(wx.EVT_MENU, self.OnBookmark, id=(self.ID_BOOKMARK_BASE + bookmarkcount)) folders[folderindex].Append((self.ID_BOOKMARK_BASE + bookmarkcount), line) bookmarkcount = bookmarkcount + 1 lastCount = c line = f.readline() f.close() #Add any menus not yet added: c = 1 while lastCount > c: folders[(folderindex - 1)].AppendMenu(self.ID_BOOKMARK_MENU, menuTitles.pop(), folders.pop()) folderindex = folderindex - 1 menuTitleindex = menuTitleindex - 1 lastCount = lastCount - 1 except: drScrolledMessageDialog.ShowMessage(self, ("Your bookmarks file is a tad messed up.\n"), "Error") return else: f = file(bookfile, 'wb') f.write('>Bookmarks\n') f.close() posX, posY = self.btnBookmarks.GetPosition() posY = posY + self.btnBookmarks.GetSize()[1] self.PopupMenu(bookmarksmenu, (posX, posY)) bookmarksmenu.Destroy() def OnBrowse(self, event): posX, posY = self.btnDir.GetPosition() posY = posY + self.btnDir.GetSize()[1] d = DirPanel(self, -1, (posX, posY), (250, 300)) d.ShowModal() self.lstFiles.SetDirectoryTo(d.GetPath(), self.wildcards[self.currentextension]) d.Destroy() def OnbtnCancel(self, event): self.EndModal(wx.ID_CANCEL) def OnbtnDelete(self, event): filename = self.cboFile.GetValue() if os.path.exists(filename) and not os.path.isdir(filename): msg = 'Delete "' + filename + '"?' if self.parent.Ask(msg, "Delete File?"): try: os.remove(filename) self.cboFile.SetValue('') self.OnbtnRefresh(None) except: drScrolledMessageDialog.ShowMessage(self, 'Error Removing "' + filename + '".', "Error") def OnbtnDisplayDetailed(self, event): if self.MultipleSelection: self.lstFiles.SetViewDetailed() else: self.lstFiles.SetViewDetailed(wx.LC_SINGLE_SEL) self.lstFiles.SetDirectoryTo(self.lstFiles.GetDirectory(), self.wildcards[self.currentextension]) def OnbtnDisplayList(self, event): if self.MultipleSelection: self.lstFiles.SetViewList() else: self.lstFiles.SetViewList(wx.LC_SINGLE_SEL) self.lstFiles.SetDirectoryTo(self.lstFiles.GetDirectory(), self.wildcards[self.currentextension]) def OnbtnForward(self, event): self.lstFiles.GoForward(self.wildcards[self.currentextension]) def OnbtnHome(self, event): try: self.lstFiles.SetDirectoryTo(os.path.expanduser('~'), self.wildcards[self.currentextension]) except: drScrolledMessageDialog.ShowMessage(self, 'Error Setting Current Directory to Home', "DrPython Error") def OnbtnNewDirectory(self, event): d = wx.TextEntryDialog(self, "Enter New Directory:", "New Directory", "") answer = d.ShowModal() v = d.GetValue() d.Destroy() if answer == wx.ID_OK: if v: os.mkdir(self.lstFiles.GetDirectory() + '/' + v) self.OnbtnRefresh(None) def OnbtnOk(self, event): filename = self.cboFile.GetValue() if not os.path.isabs(filename): fname = self.txtDirectory.GetValue() if not fname.endswith ('/'): fname += '/' filename = fname + filename if filename.find(".lnk") > -1: filename = self.HandleLnk(filename) if filename is None: return elif filename.find('.desktop') > -1: filename = self.HandleDesktop(filename) if filename is None: return if not self.IsASaveDialog: if not os.path.exists(filename): self.parent.ShowMessage('"' + filename + '" does not exist.', 'Error') return if os.path.isdir(filename): self.cboFile.SetValue('') self.lstFiles.SetDirectoryTo(filename, self.wildcards[self.currentextension]) else: self.cboFile.SetValue(filename) self.EndAndCheck(wx.ID_OK) def OnbtnRefresh(self, event): self.lstFiles.SetDirectoryTo(self.lstFiles.GetDirectory(), self.wildcards[self.currentextension]) def OnbtnUp(self, event): cdir = os.path.split(self.lstFiles.GetDirectory())[0] self.lstFiles.SetDirectoryTo(cdir, self.wildcards[self.currentextension]) def OnChar(self, event): if event.GetKeyCode() == wx.WXK_ESCAPE: self.OnbtnCancel(None) elif event.GetKeyCode() == wx.WXK_RETURN: self.OnbtnOk(None) else: event.Skip() def OnDir(self, event): directory = self.txtDirectory.GetValue() if os.path.exists(directory): self.lstFiles.SetDirectoryTo(directory, self.wildcards[self.currentextension]) else: self.parent.ShowMessage('"%s" does not exist.' % (directory), 'Error') def OnExtension(self, event): self.currentextension = self.cboExtension.GetSelection() self.lstFiles.SetDirectoryTo(self.lstFiles.GetDirectory(), self.wildcards[self.currentextension]) def OnFileActivated(self, event): seltext = event.GetLabel() filename = self.lstFiles.GetDirectory() + '/' + seltext if filename.find(".lnk") > -1: filename = self.HandleLnk(filename) if filename is None: return elif filename.find('.desktop') > -1: filename = self.HandleDesktop(filename) if filename is None: return if not self.IsASaveDialog: if not os.path.exists(filename): self.parent.ShowMessage('"' + filename + '" does not exist.', 'Error') return if os.path.isdir(filename): self.lstFiles.SetDirectoryTo(filename, self.wildcards[self.currentextension]) else: self.EndAndCheck(wx.ID_OK) def OnFileBookmark(self, event): try: bookfile = self.parent.datdirectory + "/bookmarks.dat" f = file(bookfile, 'rb') text = f.read() f.close() lines = text.strip().split('\n') x = 0 folders = [] linenumbers = [] for line in lines: c = line.count('\t') pre = line[:c].replace('\t', ' ') line = line[c:].rstrip() if line[0] == '>': folders.append(pre + line[1:]) linenumbers.append(x) x += 1 cdir = self.lstFiles.GetDirectory() d = wx.SingleChoiceDialog(self.parent, 'Select Bookmark Folder:', "File Bookmark", folders, wx.CHOICEDLG_STYLE) answer = d.ShowModal() result = d.GetSelection() if answer == wx.ID_OK: target = linenumbers[result] f = file(bookfile, 'wb') x = 0 for line in lines: f.write(line + '\n') if x == target: c = line.count('\t') istring = '\t' for a in range(c): istring += '\t' f.write(istring + cdir + '\n') x += 1 f.close() self.parent.bookmarksmenu.reloadBookmarks() if self.parent.prefs.enablefeedback: self.parent.ShowMessage('Successfully Added ' + cdir, 'Success') except: self.parent.ShowMessage('Error Filing Bookmark', 'Error') def OnFileSelected(self, event): seltext = event.GetLabel() filename = self.lstFiles.GetDirectory() if not filename.endswith ('/'): filename += '/' filename += seltext if not os.path.isdir(filename): self.cboFile.SetValue(filename) def OnShowHiddenFiles(self, event): showhidden = self.chkShowHiddenFiles.GetValue() self.lstFiles.SetShowHiddenFiles(showhidden) self.OnbtnRefresh(None) def SetDirectory(self, directory): if not os.path.exists(directory): directory = self.parent.userhomedirectory self.lstFiles.SetDirectoryTo(directory, self.wildcards[self.currentextension]) class drWxFileDialog(wx.FileDialog): def __init__(self, parent, title, message, defaultdir, wildcard, style): wx.FileDialog.__init__(self, parent, title, message, defaultdir, wildcard, style) def GetEncoding(self): return '' #Wrapper for drFileDialog def FileDialog(parent, title, wildcard, point=(0, 0), size=wx.DefaultSize, IsASaveDialog=0, MultipleSelection=0, ShowRecentFiles=0): if parent.prefs.usewxfiledialog: if IsASaveDialog: return drWxFileDialog(parent, title, "", "", wildcard, wx.SAVE|wx.HIDE_READONLY|wx.OVERWRITE_PROMPT) else: return drWxFileDialog(parent, title, "", "", wildcard, wx.OPEN|wx.HIDE_READONLY|wx.MULTIPLE) else: return drFileDialog(parent, title, wildcard, point, size, IsASaveDialog, MultipleSelection, ShowRecentFiles) drpython-3.11.1/drDragAndDrop.py0000644000175000017500000000633411150445514017305 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Drag and Drop import wx, wx.stc #******************************************************************************************************* #Submitted by Slim Amamou #Modified by Daniel Pozmanter #Modified again by Dan for 3.7.0 # Reworked to add Text Drag and Drop Support # Thanks to Robin Dunn for the code. class drDropTarget(wx.DropTarget): def __init__(self, window): wx.DropTarget.__init__(self) self.window = window.grandparent window.Bind(wx.stc.EVT_STC_START_DRAG, self.OnStartDrag, id=window.GetId()) self.data = wx.DataObjectComposite() self.dtext = wx.TextDataObject() self.dfilename = wx.FileDataObject() self.data.Add(self.dtext, True) self.data.Add(self.dfilename) self.draginitiatedfromstc = False self.moddown = False self.SetDataObject(self.data) def DropFiles(self, filenames): filenames = map(lambda x: x.replace("\\", "/"), filenames) for fname in filenames: self.window.OpenOrSwitchToFile(fname) def DropText(self, text, point): if self.window.prefs.draganddropmode != 2: if self.draginitiatedfromstc: if ((self.window.prefs.draganddroptextmode == 0) and self.moddown) or \ ((self.window.prefs.draganddroptextmode == 1) and (not self.moddown)): self.window.txtDocument.SetSelectedText('') position = self.window.txtDocument.PositionFromPoint(point) self.window.txtDocument.InsertText(position, text) self.window.txtDocument.GotoPos(position+len(text)) def OnDrop(self, x, y): if self.draginitiatedfromstc==1 and self.window.prefs.draganddropmode==2: return False else: return True def OnData(self, x, y, theData): self.GetData() if self.dtext.GetTextLength() > 1: self.DropText(self.dtext.GetText(), wx.Point(x, y)) self.dtext.SetText('') else: self.DropFiles(self.dfilename.GetFilenames()) self.draginitiatedfromstc = False return theData def OnStartDrag(self, event): self.draginitiatedfromstc = True def SetModifierDown(self, moddown): self.moddown = moddowndrpython-3.11.1/drPDB.py0000644000175000017500000000146311150445514015563 0ustar dktrkranzdktrkranzimport bdb import sys class drPdb(bdb.Bdb): """ Subclass of bdb that sends output to the prompt window """ def __init__(self, drFrame): """ Set up for debugging """ bdb.Bdb.__init__(self) self.save_stdout = sys.stdout self.save_stderr = sys.stderr self.lineno = None self.stack = [] self.curindex = 0 self.curframe = None self.drFrame = drFrame def start(self,debugfile,globals=None,locals=None): """ Start debugging """ # redirect output to prompt window sys.stdout = sys.stderr = self.drFrame.txtPrompt cmd = 'execfile("' + debugfile + '")' self.run(cmd,globals,locals) # get output back to original sys.stdout = self.save_stdout sys.stderr = self.save_stderr drpython-3.11.1/drTreeDialog.py0000644000175000017500000003314111150445514017173 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Tree Dialog Base Class import os.path import wx import drScrolledMessageDialog from drProperty import * def SortBranch(dialog, branch): x = 0 ccount = dialog.datatree.GetChildrenCount(branch, 0) twigs = [] if ccount > 0: b, cookie = dialog.datatree.GetFirstChild(branch) twigs.append([dialog.datatree.GetItemText(b), b]) x = 1 while x < ccount: b, cookie = dialog.datatree.GetNextChild(branch, cookie) twigs.append([dialog.datatree.GetItemText(b), b]) x = x + 1 twigs.sort() x = len(twigs) - 1 while x > -1: dialog.datatree.MoveXToY(twigs[x][1], branch) x -= 1 class drTree(wx.TreeCtrl): def __init__(self, parent, id, targetbitmap, stylestring, point, size, style): wx.TreeCtrl.__init__(self, parent, id, point, size, style) self.parent = parent self.modified = False self.grandparent = self.GetGrandParent() yarrr = convertStyleStringToWXFontArray(stylestring) imagesize = (16,16) self.imagelist = wx.ImageList(imagesize[0], imagesize[1]) self.images = [wx.BitmapFromImage(wx.Image(self.grandparent.bitmapdirectory + "/16/folder.png", wx.BITMAP_TYPE_PNG)), \ wx.BitmapFromImage(wx.Image(self.grandparent.bitmapdirectory + "/16/folder open.png", wx.BITMAP_TYPE_PNG)), \ wx.BitmapFromImage(wx.Image(targetbitmap, wx.BITMAP_TYPE_PNG))] map(self.imagelist.Add, self.images) self.AssignImageList(self.imagelist) w = wx.Font(yarrr[1], wx.NORMAL, wx.NORMAL, wx.NORMAL, yarrr[2]) w.SetFaceName(yarrr[0]) if yarrr[3]: w.SetWeight(wx.BOLD) else: w.SetWeight(wx.NORMAL) if yarrr[4]: w.SetStyle(wx.ITALIC) else: w.SetStyle(wx.NORMAL) self.SetFont(w) f = convertColorPropertyToColorArray(getStyleProperty("fore", stylestring)) b = convertColorPropertyToColorArray(getStyleProperty("back", stylestring)) self.TextColor = wx.Colour(f[0], f[1], f[2]) self.SetForegroundColour(self.TextColor) self.badbranch = 0 self.dragging = 0 self.draggingId = self.GetRootItem() self.SetBackgroundColour(wx.Colour(b[0], b[1], b[2])) self.edittext = "" self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnBeginDrag, id=id) self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnItemActivated, id=id) self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) self.Bind(wx.EVT_MOTION, self.OnMotion) self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnLabelEdited) self.Bind(wx.EVT_LEFT_DOWN, self.OnLabelEdited) def GetBadBranch(self): return self.badbranch def GetModified(self): return self.modified def MoveChildren(self, fromitem, toitem): ccount = self.GetChildrenCount(fromitem, 0) if ccount > 0: b, cookie = self.GetFirstChild(fromitem) newchild = self.InsertItemBefore(toitem, 0, self.GetItemText(b)) self.SetPyData(newchild, self.GetPyData(b)) if self.GetChildrenCount(b, 0) > 0: self.MoveChildren(b, newchild) self.SetIcons(newchild) x = 1 while x < ccount: b, cookie = self.GetNextChild(fromitem, cookie) newchild = self.InsertItemBefore(toitem, x, self.GetItemText(b)) self.SetPyData(newchild, self.GetPyData(b)) if self.GetChildrenCount(b, 0) > 0: self.MoveChildren(b, newchild) self.SetIcons(newchild) x = x + 1 def MoveXToY(self, frombranch, tobranch): tobranchtext = self.GetItemText(tobranch) tobranchparent = self.GetItemParent(tobranch) if tobranchtext[0] == '>': newbranch = self.InsertItemBefore(tobranch, 0, self.GetItemText(frombranch)) else: newbranch = self.InsertItem(tobranchparent, tobranch, self.GetItemText(frombranch)) self.SetPyData(newbranch, self.GetPyData(frombranch)) self.SetIcons(newbranch) self.MoveChildren(frombranch, newbranch) self.Delete(frombranch) return newbranch def OnBeginDrag(self, event): self.draggingId = self.GetSelection() if (self.draggingId == self.GetRootItem()) or (not self.draggingId.IsOk()): return self.SetCursor(wx.StockCursor(wx.CURSOR_HAND)) self.dragging = 1 def OnItemActivated(self, event): sel = self.GetSelection() if not sel.IsOk(): return self.edittext = self.GetItemText(sel) self.EditLabel(sel) def OnLabelEdited(self, event): if self.edittext: self.SetModified() if self.edittext[0] == '>': sel = self.GetSelection() text = self.GetItemText(sel) if not text[0] == '>': self.SetItemText(sel, '>' + text) event.Skip() def OnLeftUp(self, event): self.SetCursor(wx.STANDARD_CURSOR) if self.dragging: self.dragging = 0 item, flags = self.HitTest(event.GetPosition()) if item.IsOk(): if item == self.draggingId: return newbranch = self.MoveXToY(self.draggingId, item) self.SelectItem(newbranch) def OnMotion(self, event): if self.dragging: sel, flags = self.HitTest(event.GetPosition()) if sel.IsOk(): self.SelectItem(sel) event.Skip() def SetBadBranch(self, branch): self.badbranch = branch def SetIcons(self, item): text = self.GetItemText(item) if text[0] == '>': self.SetItemImage(item, 0, wx.TreeItemIcon_Normal) self.SetItemImage(item, 1, wx.TreeItemIcon_Expanded) else: self.SetItemImage(item, 2, wx.TreeItemIcon_Normal) self.SetItemImage(item, 2, wx.TreeItemIcon_Selected) def SetModified(self, mod=True): self.modified = mod if self.modified: self.parent.SetTitle(self.parent.title + ' [Modified]') else: self.parent.SetTitle(self.parent.title) class drTreeDialog(wx.Dialog): def __init__(self, parent, title, rootstring, targetfile, targetstyle, dialogsizefile, bitmapfile, BuildTreeFromString, WriteBranch): wx.Dialog.__init__(self, parent, -1, title, wx.Point(50, 50), wx.Size(-1, -1), wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.THICK_FRAME | wx.RESIZE_BORDER) self.title = title self.ID_ADD_FOLDER = 1002 self.ID_REMOVE = 1003 self.ID_SORT = 1004 self.ID_SAVE = 1005 self.parent = parent self.BuildTreeFromString = BuildTreeFromString self.WriteBranch = WriteBranch self.preferencesdirectory = parent.preferencesdirectory self.wildcard = parent.prefs.wildcard self.targetfile = targetfile self.dialogsizefile = dialogsizefile self.btnAddFolder = wx.Button(self, self.ID_ADD_FOLDER, "Add &Folder") self.btnRemove = wx.Button(self, self.ID_REMOVE, "&Remove") self.btnSort = wx.Button(self, self.ID_SORT, "Sort Folder") self.btnSave = wx.Button(self, self.ID_SAVE, "&Save") self.btnClose = wx.Button(self, 101, "&Close") self.btnClose.SetDefault() self.datatree = drTree(self, -1, bitmapfile, targetstyle, wx.Point(0, 0), wx.Size(500, 350), wx.TR_DEFAULT_STYLE | wx.TR_EDIT_LABELS) root = self.datatree.AddRoot(">"+rootstring) self.datatree.SetItemImage(root, 0, wx.TreeItemIcon_Normal) self.datatree.SetItemImage(root, 1, wx.TreeItemIcon_Expanded) self.initialize() self.datatree.Expand(root) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.cmdSizer = wx.BoxSizer(wx.HORIZONTAL) self.cmdSizer.Add(self.btnAddFolder, 0, wx.SHAPED) self.cmdSizer.Add(self.btnRemove, 0, wx.SHAPED) self.cmdSizer.Add(self.btnSort, 0, wx.SHAPED) self.cmdSizer.Add(self.btnSave, 0, wx.SHAPED) self.theSizer.Add(self.cmdSizer, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.datatree, 9, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.btnClose, 0, wx.SHAPED | wx.ALIGN_CENTER) self.Bind(wx.EVT_BUTTON, self.OnbtnAddFolder, id=self.ID_ADD_FOLDER) self.Bind(wx.EVT_BUTTON, self.OnbtnRemove, id=self.ID_REMOVE) self.Bind(wx.EVT_BUTTON, self.OnbtnSort, id=self.ID_SORT) self.Bind(wx.EVT_BUTTON, self.OnbtnSave, id=self.ID_SAVE) self.Bind(wx.EVT_BUTTON, self.OnbtnClose, id=101) self.parent.LoadDialogSizeAndPosition(self, dialogsizefile) def OnCloseW(self, event): self.parent.SaveDialogSizeAndPosition(self, self.dialogsizefile) if event is not None: event.Skip() def initialize(self): if os.path.exists(self.targetfile): try: f = open(self.targetfile, 'r') self.BuildTreeFromString(self, self.datatree.GetRootItem(), f.read()) f.close() except: drScrolledMessageDialog.ShowMessage(self.parent, ('File Error.\n"'+self.targetfile+'"\n'), "Error") def OnbtnAddFolder(self, event): sel = self.datatree.GetSelection() if not sel.IsOk(): if self.datatree.GetCount() < 2: sel = self.datatree.GetRootItem() else: return if self.datatree.GetItemText(sel)[0] == '>': d = wx.TextEntryDialog(self, 'Enter Tree Folder:', 'Add Folder', '') if d.ShowModal() == wx.ID_OK: v = d.GetValue() item = self.datatree.AppendItem(self.datatree.GetSelection(), ">" + v) self.datatree.SetItemImage(item, 0, wx.TreeItemIcon_Normal) self.datatree.SetItemImage(item, 1, wx.TreeItemIcon_Expanded) self.datatree.SetModified() d.Destroy() else: drScrolledMessageDialog.ShowMessage(self, "You can only add a folder to another folder.", "Bad Folder Location") def OnbtnClose(self, event): if self.datatree.GetModified(): answer = wx.MessageBox('Save Changes?', self.title, wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION) if answer == wx.YES: self.OnbtnSave(event) elif answer == wx.CANCEL: return self.Close(1) def OnbtnRemove(self, event): sel = self.datatree.GetSelection() if not sel.IsOk(): return if sel == self.datatree.GetRootItem(): drScrolledMessageDialog.ShowMessage(self, "You can't remove the Root Item.\n", "Mistake") return t = self.datatree.GetItemText(sel) message = "This will remove the item: " + t if self.datatree.GetItemText(sel)[0] == '>': message = "This will remove all items in folder: " + t + "!" answer = wx.MessageBox((message + "\nAre you sure you want to do this?"), "DrPython", wx.YES_NO | wx.ICON_QUESTION) if answer == wx.NO: return try: self.datatree.Delete(sel) self.datatree.SetModified() except: drScrolledMessageDialog.ShowMessage(self, ("Something went wrong trying to remove that item....\nWhat's it called....\nOh yes: " + t + "\n"), "Error") return def OnbtnSave(self, event): try: root = self.datatree.GetRootItem() f = open(self.targetfile, 'w') self.WriteBranch(self.datatree, root, f, 0) f.close() except IOError: drScrolledMessageDialog.ShowMessage(self, ("There were some problems writing to:\n" + self.targetfile + "\nEither the file is having metaphysical issues, or you do not have permission to write.\nFor metaphysical issues, consult the documentation.\nFor permission issues, change the permissions on the directory to allow yourself write access.\nDrPython will now politely ignore your request to save.\nTry again when you have fixed the problem."), "Write Error") return self.datatree.SetModified(False) if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, ("Succesfully wrote to:\n" + self.targetfile), "Success") def OnbtnSort(self, event): sel = self.datatree.GetSelection() if not sel.IsOk(): return #self.datatree.SortChildren(sel) SortBranch(self, sel) self.datatree.SetModified() def SetupSizer(self): self.SetAutoLayout(True) self.SetSizerAndFit(self.theSizer) drpython-3.11.1/drScriptDialog.py0000644000175000017500000002126211150445515017542 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #drScript Dialog import os.path import wx import drScrolledMessageDialog from drProperty import * from drPrefsFile import ExtractPreferenceFromText import drShortcutsFile from drTreeDialog import * class drTreeItemData(wx.TreeItemData): def __init__(self, Line, Shortcut): wx.TreeItemData.__init__(self) self.Line = Line self.Shortcut = Shortcut def BuildTreeFromString(dialog, branch, thestring): line = " " roots = [branch] rootindex = 0 #Shortcuts Shortcuts = [] ShortcutIndex = 0 map(Shortcuts.append, dialog.parent.DrScriptShortcuts[dialog.parent.drscriptmenu.ExampleScriptCount:]) lastCount = 0 i = 0 lastI = 0 while line: i = thestring.find('\n') if i > -1: line = thestring[0:(i + 1)] lastI = i + 1 thestring = thestring[lastI:] c = line.count('\t') line = line[c:].rstrip() while lastCount > c: roots.pop() rootindex = rootindex - 1 lastCount = lastCount - 1 if line.find("title") > -1: line_title = ExtractPreferenceFromText(line, "title") currentItem = dialog.datatree.AppendItem(roots[rootindex], line_title) dialog.datatree.SetPyData(currentItem, drTreeItemData(line, Shortcuts[ShortcutIndex])) ShortcutIndex = ShortcutIndex + 1 dialog.datatree.SetItemImage(currentItem, 2, wx.TreeItemIcon_Normal) dialog.datatree.SetItemImage(currentItem, 2, wx.TreeItemIcon_Selected) elif line[0] == '>': currentItem = dialog.datatree.AppendItem(roots[rootindex], line) dialog.datatree.SetPyData(currentItem, drTreeItemData(line, None)) dialog.datatree.SetItemImage(currentItem, 0, wx.TreeItemIcon_Normal) dialog.datatree.SetItemImage(currentItem, 1, wx.TreeItemIcon_Expanded) roots.append(currentItem) rootindex = rootindex + 1 lastCount = c + 1 else: line = "" class drScriptDialog(drTreeDialog): def __init__(self, parent): drTreeDialog.__init__(self, parent, 'Edit DrScript Menu', 'DrScript Menu', parent.preferencesdirectory + "/drscript.dat", parent.prefs.drscriptstyle, \ 'drscriptdialog.sizeandposition.dat', parent.bitmapdirectory + '/16/drscript.png', BuildTreeFromString, self.WriteBranch) self.SetupSizer() if parent.PLATFORM_IS_GTK: #does not get initially the focus (bug tracker #1903778, "Open Imported Module: focus problem", 29.02.2008: from Jon White, thanks. self.SetFocus() def GetShortcutArrays(self, tree, branch): Shortcuts = [] t = tree.GetItemText(branch) if not (t[0] == '>'): data = tree.GetPyData(branch) if data.Shortcut is not None: Shortcuts.append(data.Shortcut) else: ccount = tree.GetChildrenCount(branch, 0) if ccount > 0: if (wx.MAJOR_VERSION >= 2) and (wx.MINOR_VERSION >= 5): b, cookie = tree.GetFirstChild(branch) else: b, cookie = tree.GetFirstChild(branch, 1) s = self.GetShortcutArrays(tree, b) Shortcuts.extend(s) x = 1 while x < ccount: b, cookie = tree.GetNextChild(branch, cookie) s = self.GetShortcutArrays(tree, b) Shortcuts.extend(s) x = x + 1 return Shortcuts def WriteBranch(self, tree, branch, filehandle, tablevel): t = tree.GetItemText(branch) if tablevel > -1: data = tree.GetPyData(branch) if data is not None: x = 0 y = "" while x < tablevel: y = y + '\t' x = x + 1 title = ExtractPreferenceFromText(data.Line, "title") if title: self.parent.drscriptmenu.titles.append(title) if title: if not (title == t): data.Line = data.Line[:data.Line.find("")] + "<title>" + t + "" y = y + data.Line + '\n' filehandle.write(y) if t[0] == '>': ccount = tree.GetChildrenCount(branch, 0) if ccount > 0: if (wx.MAJOR_VERSION >= 2) and (wx.MINOR_VERSION >= 5): b, cookie = tree.GetFirstChild(branch) else: b, cookie = tree.GetFirstChild(branch, 1) self.WriteBranch(tree, b, filehandle, (tablevel + 1)) x = 1 while x < ccount: b, cookie = tree.GetNextChild(branch, cookie) self.WriteBranch(tree, b, filehandle, (tablevel + 1)) x = x + 1 def OnbtnAddFolder(self, event): sel = self.datatree.GetSelection() if not sel.IsOk(): if self.datatree.GetCount() < 2: sel = self.datatree.GetRootItem() else: return if self.datatree.GetItemText(sel)[0] == '>': d = wx.TextEntryDialog(self, 'Enter Tree Folder:', 'Add Folder', '') if d.ShowModal() == wx.ID_OK: v = d.GetValue() sel = self.datatree.GetSelection() if sel.IsOk(): item = self.datatree.AppendItem(self.datatree.GetSelection(), ">" + v) self.datatree.SetPyData(item, drTreeItemData(">" + v, None)) self.datatree.SetItemImage(item, 0, wx.TreeItemIcon_Normal) self.datatree.SetItemImage(item, 1, wx.TreeItemIcon_Expanded) self.datatree.SetModified() d.Destroy() else: drScrolledMessageDialog.ShowMessage(self, "You can only add a folder to another folder.", "Bad Folder Location") def OnbtnSave(self, event): try: root = self.datatree.GetRootItem() f = open(self.targetfile, 'w') self.parent.drscriptmenu.titles = self.parent.drscriptmenu.titles[:self.parent.drscriptmenu.ExampleScriptCount] self.WriteBranch(self.datatree, root, f, -1) f.close() except IOError: drScrolledMessageDialog.ShowMessage(self, "There were some problems writing to:\n" + self.targetfile, "Write Error") return self.datatree.SetModified(False) if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, ("Succesfully wrote to:\n" + self.targetfile), "Success") root = self.datatree.GetRootItem() #Sync Shortcuts: s = self.GetShortcutArrays(self.datatree, root) self.parent.DrScriptShortcuts = self.parent.DrScriptShortcuts[:self.parent.drscriptmenu.ExampleScriptCount] map(lambda x: self.parent.DrScriptShortcuts.append(x), s) #Sync the Shortcuts File: shortcutsfile = self.parent.shortcutsdirectory + "/drscript.shortcuts.dat" try: drShortcutsFile.WriteShortcuts(shortcutsfile, self.parent.DrScriptShortcuts, self.parent.drscriptmenu.titles, "", False) except IOError: drScrolledMessageDialog.ShowMessage(self, ("There were some problems writing to:\n" + shortcutsfile + "\nEither the file is having metaphysical issues, or you do not have permission to write.\nFor metaphysical issues, consult the documentation.\nFor permission issues, change the permissions on the directory to allow yourself write access.\nDrPython will now politely ignore your request to save.\nTry again when you have fixed the problem."), "Write Error") return drpython-3.11.1/__init__.py0000644000175000017500000000002611235243545016365 0ustar dktrkranzdktrkranz__version__ = "3.11.1"drpython-3.11.1/drTabNanny.py0000644000175000017500000000636711235237236016704 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public Lisense) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Tab Nanny Check: returns a string on checking. from tabnanny import * #Copied from tabnanny by Tim Peters, then hacked to work the way I want. import os import tokenize __all__ = ["check", "NannyNag", "process_tokens"] verbose = 0 filename_only = 0 def errprint(*args): printstr(args) def printstr(*args): result = '' sep = '' for arg in args: result += sep + str(arg) sep = ' ' return result + '\n' def Check(file): """check(file_or_dir) If file_or_dir is a directory and not a symbolic link, then recursively descend the directory tree named by file_or_dir, checking all .py files along the way. If file_or_dir is an ordinary Python source file, it is checked for whitespace related problems. The diagnostic messages are written to standard output using the print statement. """ result = '' if os.path.isdir(file) and not os.path.islink(file): if verbose: result += printstr("%s: listing directory" % `file`) names = os.listdir(file) for name in names: fullname = os.path.join(file, name) if os.path.isdir(fullname) and not os.path.islink(fullname) or os.path.normcase(name[-3:]) == ".py": check(fullname) return result try: f = open(file) except IOError, msg: result += errprint("%s: I/O Error: %s" % (`file`, str(msg))) return result if verbose > 1: result += printstr("checking", `file`, "...") try: process_tokens(tokenize.generate_tokens(f.readline)) except tokenize.TokenError, msg: result += errprint("%s: Token Error: %s" % (`file`, str(msg))) return result except NannyNag, nag: badline = nag.get_lineno() line = nag.get_line() if verbose: result += printstr("%s: *** Line %d: trouble in tab city! ***" % (`file`, badline)) result += printstr("offending line:", `line`) result += printstr(nag.get_msg()) else: if ' ' in file: file = '"' + file + '"' if filename_only: result += printstr(file) else: result += printstr(file, badline, `line`) return result if verbose: result += printstr("%s: Clean bill of health." % `file`) return resultdrpython-3.11.1/drDynamicDrScriptDialog.py0000644000175000017500000001001211150445514021323 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Dynamic DrScript Dialog import os.path import wx import drScrolledMessageDialog from drText import DrText class drDynamicDrScriptDialog(wx.Dialog): def __init__(self, parent, text): wx.Dialog.__init__(self, parent, -1, ("Dynamic DrScript"), wx.DefaultPosition, wx.Size(600, 400), wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.THICK_FRAME | wx.RESIZE_BORDER) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.parent = parent self.txtScript = DrText(self, -1, self.parent, 1) self.txtScript.SetText(text) self.txtScript.SetupPrefsDocument() self.theSizer.Add(self.txtScript, 9, wx.EXPAND) self.commandSizer = wx.BoxSizer(wx.HORIZONTAL) self.btnClose = wx.Button(self, 101, "&Close") self.btnOk = wx.Button(self, 102, "&Ok") self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.commandSizer.Add(self.btnClose, 0, wx.SHAPED | wx.ALIGN_CENTER) self.commandSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.commandSizer.Add(self.btnOk, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.commandSizer, 0, wx.SHAPED | wx.ALIGN_CENTER) self.btnOk.SetDefault() self.SetAutoLayout(True) self.SetSizer(self.theSizer) self.Bind(wx.EVT_CLOSE, self.OnCloseW) self.Bind(wx.EVT_BUTTON, self.OnbtnClose, id=101) self.Bind(wx.EVT_BUTTON, self.OnbtnOk, id=102) self.parent.LoadDialogSizeAndPosition(self, 'dynamicdrscriptdialog.sizeandposition.dat') def OnCloseW(self, event): self.parent.SaveDialogSizeAndPosition(self, 'dynamicdrscriptdialog.sizeandposition.dat') if event is not None: event.Skip() def OnbtnClose(self, event): self.Close(1) def OnbtnOk(self, event): value = self.txtScript.GetText() if value.find("DrFilename") > -1: value = value.replace("DrFilename", "self.parent.txtDocument.filename") if value.find("DrScript") > -1: value = value.replace("DrScript", "self.parent.DrScript") if value.find("DrDocument") > -1: value = value.replace("DrDocument", "self.parent.txtDocument") if value.find("DrPrompt") > -1: value = value.replace("DrPrompt", "self.parent.txtPrompt") if value.find("DrFrame") > -1: value = value.replace("DrFrame", "self.parent") try: #Bug-Report/Fix (Submitted, Edited) Franz Steinhausier value = value.replace('\r', '\n') code = compile((value + '\n'), "Dynamic DrScript", 'exec') except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error compiling dynamic script."), "Error", wx.DefaultPosition, wx.Size(550,300)) return try: exec(code) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error running dynamic script."), "Error", wx.DefaultPosition, wx.Size(550,300)) return def GetText(self): return self.txtScript.GetText()drpython-3.11.1/Changelog.txt0000644000175000017500000004137611235323633016716 0ustar dktrkranzdktrkranz - add notes from the next release here. - in drtext.py two times wx.CallAfter, else Segmentation fault (3.11.0. wxPython Version: 2.8.4.0, wxGTK, unicode, gtk2, wx-assertions-off, Python Version: 2.5.1.final, Python Platform: linux2) - few changes: - preferences: ignore ctrl-pageupdown key, so it can be used as shortcut. - but in gtk in find and find history. - some code cleaning. - gtk: openimported module didn't work as expected on gtk: keys came twice. - in drtext.py two times wx.CallAfter, else Segmentation fault (3.11.0. wxPython Version: 2.8.4.0, wxGTK, unicode, gtk2, wx-assertions-off, Python Version: 2.5.1.final, Python Platform: linux2) - bug in drPrinter.py, reported by Luca Falavigna; 'DrPrinter' object has no attribute 'log'; fixed. - fixed problems on quitting the app - removed the need of a certain wxpython version - some Code Cleanup (for example AskExitingDrPython()) - Goto Line on Traceback more universal (with pychecker line now also possible). - fixed some issues on gtk with wx.Notebook. - removed unnecessary shebgangs reported by Luca Falavigna, thanks - DrPython sometimes hangs when opening a python interpreter. patch by Luca Falavigna - dktrkranz, 07/04/2008, thanks - DrPython crashes if saved file is not available Step to reproduce the crash: 1) Open a new file and save it 2) Edit the file, but do not save it 3) Delete the file 4) Close drpython and answer Yes when asked5) Program crashes bug reported by Luca Falavigna - dktrkranz, 07/04/2008, thanks. - open python with cp1252 encoding => crash. no solution => workaround Messagebox and disable this - statement in prompt with character above ascii 127 crashes the program; no solution => workaround (check characters) Messagebox and disable this - A wish from Dan to change it to the old version numbering system - New File __init__.py - New File drHtmlBrowser.py for displaying html content, when run a file. - new preferences: intelligent Backspace Key for each filetype (if it is on, it jumps back the indentation setting, for example 4 spaces, else it jumps back 1 space as expected. - some fixes in font adjustment (AB) - fixed bug in sourcebrowser. - applied patch from Cedric Delfosse (Ctrl-q as default for exiting DrPython), thanks. - some fixes in drscriptmenu und drscriptdialog (there were sometimes a mess, when editing the drscriptmenu afterwards). - fixed storing of the size of the Drpython frame (also remembers now the restore frame size, if it was maximized before, and the maximize state.). - Changed the close behaviour (jumps to the tab right instead of the tab left before). - improved OnComment and UnComment (remembers the exact cursor position). - Goto Line shows the line now in the middle of the edit window (patch: [ 1366679 ]) - simplified all openfile operations with OpenOrSwitchToFile and improve AlreadyFileOpen. - OnReload also remembers the old cursor postion and jumps back to it. - Some fixes in OnRun (patch [ 1367222 ]). - Changed some Titles of DrPython Error for easier bug reporting and tracking. - fixed bug in reloadocumentsmenu. - remove trailing whitespaces can now adjusted for the different filetypes in the preferences dialog. - when switching documents, the state of view whitespace/linendings is taken with to the new switched tab. - changed some menu accellerators, which were doubled in one menu. - added a redirect to file for stdout and stderr, for easier bug tracking and reporting. - some fixes in drprompt.py (AB) also patch: [ 1366679 ] - changed some default styles (AB). - #bug reported and patch supplied by Tiziano Mueller, which itself was supplied by a user, 25. Feb. 2008, thanks. when switching tabs, with ctrl-(shift)-tab, the new active tab was not set properly. - changed behaviour when find forward and backward, so the active found text is not displayed on the very top or bottom, but there are about 5 lines lower/higher visible. - fixed bug in search backward, when in the mean time text was added or deleted. - fixed bug in drregularexpressionsdialg (parent window) - fixed bug in drNotebook: (list index out of range if closing the last window) - added command line option for drpyhton.py useredirecttofile (--r0 as option to redirect output not to file, but to console as normal pyhton behaviour). - added patch in drprompt.py Prompt window scrolls to wrong position, thanks Mervin Beng (mervinb) - added inscpect tool in Help Menu (borrowed from wxpython demo) (visible if "debug modus" in preferences is on. also for popup menu - added new drpyhton event (self.EVT_DRPY_PROMPT_GOTO) for drprompt goto (this can be used in plugins for evaluation the output (used in plugin makefile for the output for example)) - hack: AskPlatformDependent: Problem was: default behaviour on linux (gtk) and drpyhton was differnet in messageboxe - hack: the code uncomment for c/c++ files didn't work correctly: removed that complicated query - added patch #patch: [ 1366679 ] Goto Line Should Not Display At Top Of Window and made a function for that in drpython.py thanks Christopher Thoday (cthoday) - added encoding cp1252 (for open files and drFileDialog for opening files) - changed: different messagebox behaviour in find/replace linux/windows: should be the same behavour now (FS) ... Franz Steinhauesler (AB) ... Antonio Barbosa noteable in this release: - changed directory structure: drplugins and drscript dir is by default in preferences, but can be choosen to be somewhere else the structure of the data files: - prefsdir (preferences.dat, default.idx and drscript.dat) - "dat" (drpython.panel.sizes.dat, ...) - "shortcuts" (shortcuts.dat, stcshortcuts.dat, drscript.shortcuts.dat) - "plugins" (default.idx, the list of plugins loaded at startup) - "dat" (Plugins data and remembered state files) - "shortcuts" (plugin shortcut files) - "preferences" (plugin preferences files) please check your paths, if you update to version 165. - new project member (António Barbosa) abbreviated with AB. (contributed already a good fix, see below) (António Barbosa) is abbreviated with AB in changelog: - AB: Sourcebrowser with textfield for fast search. - AB: Sourcebrowser option: display source browser icons, default on (saves space, when turned on). - cleanup and removed some unnecessary code - removed simple/advanced mode. (until) 07. Apr. 2007: - added notes.txt - little text display bug in drToolBarDialog (AB). - fix in StyleDialog (AB). - changed some default shortcuts to be more userfriendly (AB). - Added update function for users changing from 1.64 to 1.65 because of new directory structure (FS). - implemented new simple export/import preferences of drPyhton (AB). - changed some default preferences settings to be more userfriendly (AB). (until) 23. Mar. 2007: - removed simple/advanced mode. - changed by AB: moved Generel Tab in Preferences to first tab. - fix by AB: (eliminate the call of initializing drScriptMenu twice. - fix by AB: on linux, output of prompt didn't appear (evt_idle do not work if the control has no focus; used a timer instead). - fix by AB: in drPrefsDialog.py: removed |wx.DD_NEW_DIR_BUTTON because the style wx.DD_DEFAULT_STYLE already includes wx.DD_NEW_DIR_BUTTON - used sometimes 'u' to open text files with universal newline support (eliminates some problems with different lineendings (dos and linux)) 25. Feb. 2007 - 01. Mar. 2007: - thanks antonio for testing. - plugins tested under windows and linux, wxpython unicode wxPython 2.8.1.1 and above for DrPython 1.65: (only listed plugins, I have in my local plugin directory; still some are missing in this list) - scrolledmessagedialog called with Showmessage only. - revert: revert changes "== None", "!= None" to the former "is None" and "is not None" (many people said, this is not ok) - cleanup: run pychecker over all files, removed unneeded variables or names, unneeded import, fixed one or two bugs directly detected by pychecker. - cleanup: replaces the three lines in drscrolledmessage with a single ShowMessage. - changed: procedure of assigning userpreferences- und pluginsdir (take care, if drpyhton is started with --preferencesbasepath), and some other fixes with writing userpreferencesdirectory.dat and preferences.dat, handling of userpreferencesdirectory. - changed: split default.idx files for getting plugins. It should now work for both linux and windows for the same default.idx file. - fixed: always save and restore the current working directory (os.chdir and os.getcwd) - added: textfield and preference for defaultdirectory and store this in preferences.dat (I have changed it before unawared) - fixed: added fix by AB in EncodeTextWith(text, encoding), which caused problems with unicode in prompt (thanks Antonio). - removed: unnecessary print statements in code. - added tools directory for miscellanous stuff - run pyflakes and corrected/optimized some code. 24. Feb. 2007: - removed default directory in preferences - added user preferences dir: a file with the preferences dir will be created in the home folder - used plugin dir (was ignored until now) - used drscripts dir (was ignored until now); if a script is inside that dir, only relative path- and filename is stored, else the whole filename and path is stored - run pychecker on changed files * removed unneeded variables * detected a few bugs with pychecker - all files should be now with unix lineendings, spaces as indentation and trailing whitespaces are removed now. - new project member (António Barbosa) abbreviated with AB. - AB: fixed problem with PyDeadObjectError, when soure browser was closed by right click on the tab and choose close, and then try to reopen Sourcebrowser (drSourceBrowser.py). - cleanup the code, shortened to make it more clearly-presented: * for example in if no parenthises are needed if (a > b): => if a > b: * compare if string is empty: if len(teststring) > 0: => if teststring: * long lines breaked sometimes * self.scriptcount = self.scriptcount + 1 => self.scriptcount += 1 * MessageDialog replaced by MessageBox (fewer lines) - is there a small bug in wxPython 2.8.1.1 compared to 2.6?: The edit script dialog was not fully visible anymore (no ok and cancel buttons) removed the setsize function therefore. - restriced trimtrailing whitespace only to python files. - removed unnecessary print statements. - drtext and drRegularExpressionDialog.py small bug fixed (which I checked in before) - while parenthesis removed: while (x < y): => while x < y: - AB: changed: in drpluginsdialog: (setnotindex) to keep old selection, which is not in index yet. - applied patch from Steffen (ssteidte), thanks: The following small changes to drpython.py(w) provide the ability to give the names of files to edit as command line arguments. - applied patch from Knut Gerwens in CheckSyntax (drpython.py), many thanks. there was former a problem using unicode version of wxPython with encoding cookie - Patch by Knut Gerwens in drAboutDialog.py: added import of wx.lib.stattext, replaced all occurences of 'wx.StaticText' with 'wx.lib.stattext.GenStaticText' because wx.StaticText displayed some lines truncated when wxPython is run with wxGTK - Set first notebook tab of drAboutDialog to white Background. - added again menu entries: Edit => copy, cut, paste. - fixed bug in editing drscript menu (File: drScriptDialog.py) (shortcuts didn't fit anymore) - extended Encoding Error message in drEncoding.py to give users a hint what to do (Knut Gerwens) - fixed some issues with not valid directory in PyDocAll and OnPyDocCurrent. - fixed bug in OnIndentRegion in drpyhton.py setModEventMask to SetModEventMask. - fixed bug in 'Save All Documents" - added test.but - changed runinterminal script (runs only on linux) - fixed bug in drNotebook.py (caused traceback in drSidePanel) - fixed error in drFileDialog.py (unicode string was not converted in string) and defaultencoding is now also used for linux. - renamed variable type to type_ in drFileDialog.py (type is a reserved keyword) - fixed annoying problem with unicode (added setdefaultencoding and wx.SetDefaultPyEncoding if a default encoding is set. (in drpython.py and if you change the encoding in drPrefsDialog.py). hack in linux reload(sys) otherwise, the setdefaultencoding is not available. - fixed bug in promptDir in DrPython.py: if dialog was cancelled, a traceback appeared (dir was not set). - AB: fixed bug in prompt with unicode: thanks! - split of default.idx (should work with lf and crlf now). - scrolledmessagedialog called with Showmessage only. (Franz Steinhaeusler) - I know there is much to do for linux, I'm looking for a project member (tester or even better bug fixer) for linux. I will request to sourceforge project help in the next few days/weeks anyway for that. There are some or many dialogs with bad layout, so not all texts are displayed, sizers are not fitting, crashes ... If you have interest please send me a mail or post into one of the foren. But nevertheless interesting, whether it runs on linux or are there some critical errors, and possible bug fixes? Best to send me whole files with an annotation, on what drpython release base you made your changes. With minmerge, that should be no problem, that I integrate them. - 1.63 experimental; for careful people, please stay at 1.62 for the time being, for the other, please test - plugin patches are also welcome - there should be more menu icons visible. - drpopup: icons in context menu (changes are older then one year) - applied tab2spaces (for all py files in drpython, because it is python "standard") - test and helper files added: dr.bat and d.bat drpython_wx26.pyw (test for older wxpython version) drpython_wx26_debug.pyw (test for older wxpython version and traceback output to file) drpython_wx26.py (test for older wxpython version) and 2 bat files if you use on of these, please rename then, adapt them to your needs and make a link to them. (because, this files will be overwritten in a newer version). - encoding problems There was a problem in unicode build (for example german umlauts), that files are stored with 0 bytes. This is REALLY bad. I hope, this is resolved now (GetDefaultEncoding added). If there is still an error, the file will not be stored. you could copy/paste it to another editor. But I hope, this will never happen. applied also for decoding files. - some "selfish" hacks integrated, which I want resolve in newer versions 1) trim trailing whitespace only for python files, not for other files (I use the editor also in the company) Later, I want to add trim trailing whitespace to the file types 2) removed copy/cut/paste from edit menu. For my keyboard macro plugin, otherwise, the keystrokes will not be recognised. Every people should know this commands by heart, anyway. :) 3) I laid the ctr-right mouse click to my doclist plugin. - drfiledialog sort "case insenstive". - standard file dialog is standard again, not the drfiledialog (some people mourned about that). - a bug in drNotebook.py fixed (bug report was also longer time ago). - minimum panel size for source browser was restricted to 25 (unnecessary). put the value to 1. thanks for user request, Peter - menu printer setup was not working, fixed. - small fix in drPrompt.py - new "hidden" feature: ctrl-right mouseclick should show the about dialog. - small patch in drscripmenu.py - workaround by Dunderhead, thanks. (self.txtPromptArray[i]._waitforoutput('>>>'), freezes on linux). - small changes in RemoveTrailingWhitespace with status text output. (assisted for Dan by Franz Steinhaeusler) should be running with wxPython 2.7 and 2.8 (Position is now a function; this caused a startup error) added patch from Jean-Pierre MANDON for drToolBarDialog - thanks; there were some errors for plugin icons. Removing the buggy debugger for now. Focus is set in each tab when switching documents. The focus is set to the current document when a program ends. (BugReport/Feature-Request, Thanks schmolch) Added code for Save A Copy (Thanks Stewart Midwinter) SourceBrowser autorefresh is saved again. Changed the location of the mode dialog bitmaps. "Toronto Edition" Huge Thanks to Greg Wilson, Tim Smith, Patrick Smith, and Laurie MacDougall. new features: graphical debugger import all user modes (beginner, advanced) pydoc browser plus other fixes and ui tweaks. drpython-3.11.1/drAboutDialog.py0000644000175000017500000002101411235243552017344 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #About Dialog # Patch by Knut Gerwens, January 2007: added import of wx.lib.stattext, # replaced all occurences of 'wx.StaticText' with 'wx.lib.stattext.GenStaticText' # because wx.StaticText displayed some lines truncated when wxPython is run with wxGTK import wx, wx.html, wx.lib.stattext import sys, string class drStaticLink(wx.Panel): def __init__(self, parent, id, text, target, drframe): wx.Panel.__init__(self, parent, id) self.drframe = drframe self.link = target self.SetBackgroundColour(wx.Colour(255, 255, 255)) self.stText = wx.lib.stattext.GenStaticText(self, id, text) self.stText.SetBackgroundColour(wx.WHITE) self.stText.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.BOLD)) self.stText.SetForegroundColour(wx.Colour(0, 90, 255)) self.theSizer = wx.BoxSizer(wx.HORIZONTAL) self.theSizer.Add(self.stText, 0, wx.SHAPED | wx.ALIGN_CENTER) self.SetAutoLayout(True) self.SetSizer(self.theSizer) self.SetSize(self.stText.GetSize()) self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter) self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave) self.stText.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) self.stText.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) def OnMouseEnter(self, event): self.SetBackgroundColour(wx.Colour(255, 198, 107)) event.Skip() def OnMouseLeave(self, event): self.SetBackgroundColour(wx.Colour(255, 255, 255)) event.Skip() def OnLeftDown(self, event): self.SetBackgroundColour(wx.Colour(255, 156, 0)) event.Skip() def OnLeftUp(self, event): self.SetBackgroundColour(wx.Colour(255, 198, 107)) event.Skip() self.drframe.ViewURLInBrowser(self.link) class drAboutContentPanel(wx.Panel): def __init__(self, parent, id, drframe): wx.Panel.__init__(self, parent, id) self.SetBackgroundColour(wx.Colour(255, 255, 255)) standardfont = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.BOLD) app = wx.lib.stattext.GenStaticText(self, -1, 'DrPython - Python IDE') app.SetBackgroundColour(wx.WHITE) app.SetFont(standardfont) author = wx.lib.stattext.GenStaticText(self, -1, '(c) 2003-2007, Daniel Pozmanter') author.SetBackgroundColour(wx.WHITE) author.SetFont(standardfont) credits = drStaticLink(self, 1, ' Credits ', drframe.programdirectory + "/documentation/credits.html", drframe) website = drStaticLink(self, 2, ' http://drpython.sourceforge.net/ ', 'http://drpython.sourceforge.net/', drframe) self.theSizer = wx.BoxSizer(wx.VERTICAL) tempstat = wx.lib.stattext.GenStaticText(self, -1, ' ') tempstat.SetBackgroundColour(wx.WHITE) self.theSizer.Add(tempstat, 0, wx.SHAPED | wx.ALIGN_CENTER_HORIZONTAL) self.theSizer.Add(app, 0, wx.SHAPED | wx.ALIGN_CENTER_HORIZONTAL) tempstat = wx.lib.stattext.GenStaticText(self, -1, ' ') tempstat.SetBackgroundColour(wx.WHITE) self.theSizer.Add(tempstat, 0, wx.SHAPED | wx.ALIGN_CENTER_HORIZONTAL) self.theSizer.Add(author, 0, wx.SHAPED | wx.ALIGN_CENTER_HORIZONTAL) tempstat = wx.lib.stattext.GenStaticText(self, -1, ' ') tempstat.SetBackgroundColour(wx.WHITE) self.theSizer.Add(tempstat, 0, wx.SHAPED | wx.ALIGN_CENTER_HORIZONTAL) self.theSizer.Add(credits, 0, wx.SHAPED | wx.ALIGN_CENTER_HORIZONTAL) tempstat = wx.lib.stattext.GenStaticText(self, -1, ' ') tempstat.SetBackgroundColour(wx.WHITE) self.theSizer.Add(tempstat, 0, wx.SHAPED | wx.ALIGN_CENTER_HORIZONTAL) self.theSizer.Add(website, 0, wx.SHAPED | wx.ALIGN_CENTER_HORIZONTAL) self.SetAutoLayout(True) self.SetSizer(self.theSizer) class drAboutPanel(wx.Panel): def __init__(self, parent, id, drframe): wx.Panel.__init__(self, parent, id) aboutpanel = drAboutContentPanel(self, id, drframe) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.theSizer.Add(aboutpanel, 1, wx.EXPAND) self.SetAutoLayout(True) self.SetSizer(self.theSizer) class drLicensePanel(wx.Panel): def __init__(self, parent, id, drframe): wx.Panel.__init__(self, parent, id) try: f = file(drframe.programdirectory + "/documentation/gpl.html", 'rb') text = f.read() f.close() except: drframe.ShowMessage('Error Reading the GPL!', 'About Dialog Error') return self.htmlBox = wx.html.HtmlWindow(self, -1) self.htmlBox.SetPage(text) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.theSizer.Add(self.htmlBox, 1, wx.EXPAND) self.SetAutoLayout(True) self.SetSizer(self.theSizer) class drSystemPanel(wx.Panel): def __init__(self, parent, id): wx.Panel.__init__(self, parent, id) version = string.join(map(lambda x: str(x), sys.version_info[:4]), '.') wxplatform = string.join(wx.PlatformInfo[1:], ', ') systeminfo = '''wxPython Version: %s wxPython Platform: %s Python Version: %s Python Platform: %s''' % (wx.VERSION_STRING, wxplatform, version, sys.platform) self.txt = wx.TextCtrl(self, -1, systeminfo, style = wx.TE_READONLY | wx.TE_MULTILINE) self.txt.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD)) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.theSizer.Add(self.txt, 1, wx.EXPAND) self.SetAutoLayout(True) self.SetSizer(self.theSizer) class drAboutDialog(wx.Dialog): def __init__(self, parent): wx.Dialog.__init__(self, parent, -1, ("About DrPython"), wx.DefaultPosition, wx.Size(500, 400), wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.THICK_FRAME | wx.RESIZE_BORDER) self.parent = parent self.notebook = wx.Notebook(self, -1, style=wx.CLIP_CHILDREN) self.notebook.AddPage(drAboutPanel(self.notebook, -1, parent), 'About') self.notebook.AddPage(drLicensePanel(self.notebook, -1, parent), 'License Agreement') self.notebook.AddPage(drSystemPanel(self.notebook, -1), 'System Info') self.btnClose = wx.Button(self, 101, "&Close") stext = wx.lib.stattext.GenStaticText(self, -1, 'DrPython - 3.11.1') stext.SetFont(wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.BOLD)) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.topSizer = wx.BoxSizer(wx.HORIZONTAL) self.topSizer.Add(wx.lib.stattext.GenStaticText(self, -1, ' '), 0, wx.SHAPED | wx.ALIGN_CENTER_VERTICAL) self.topSizer.Add(wx.StaticBitmap(self, -1, wx.BitmapFromImage(wx.Image(parent.programdirectory + "/documentation/drpython.png", wx.BITMAP_TYPE_PNG))), 0, wx.SHAPED | wx.ALIGN_CENTER_VERTICAL) self.topSizer.Add(wx.lib.stattext.GenStaticText(self, -1, ' '), 0, wx.SHAPED | wx.ALIGN_CENTER_VERTICAL) self.topSizer.Add(stext, 0, wx.SHAPED | wx.ALIGN_CENTER_VERTICAL) self.theSizer.Add(wx.lib.stattext.GenStaticText(self, -1, ' '), 0, wx.SHAPED) self.theSizer.Add(self.topSizer, 0, wx.SHAPED) self.theSizer.Add(wx.lib.stattext.GenStaticText(self, -1, ' '), 0, wx.SHAPED) self.theSizer.Add(self.notebook, 1, wx.EXPAND) self.theSizer.Add(wx.lib.stattext.GenStaticText(self, -1, ' '), 0, wx.SHAPED) self.theSizer.Add(self.btnClose, 0, wx.SHAPED | wx.ALIGN_CENTER) self.SetAutoLayout(True) self.SetSizer(self.theSizer) self.Bind(wx.EVT_BUTTON, self.OnbtnClose, id=101) def OnbtnClose(self, event): self.EndModal(0) def Show(parent): d = drAboutDialog(parent) d.ShowModal() d.Destroy() drpython-3.11.1/drHtmlBrowser.py0000644000175000017500000000417111150445515017426 0ustar dktrkranzdktrkranz# drHtmlBrowser.py # Programmer: Eur Ing Christopher Thoday. # Copyright: assigned to the DrPython project import wx, os import wx.html """This module provides a browser for displaying HTML files composed in the DrPython text editor. Links are displayed within separate pages within the browser. The tab name for the page is the HTML title if given, else it is the file name.""" note = None history = {} def _AddPage(href): if href[0:5] != "http:": if not os.path.exists(href): href = os.path.normpath(os.path.join(dir, href)) if not os.path.exists(href): wx.MessageBox("File does not exist: " + href, "DrPython HTML Browser") return if href in history: note.SetSelection(history[href]) return np = note.GetPageCount() history[href] = np page = HtmlPage(note, -1) note.AddPage(page, "", True) page.LoadPage(href) title = page.GetOpenedPageTitle() (fname, ext) = os.path.splitext(title) if ext[0:4] == ".htm" or ext[0:5] == ".html": title = fname.title() note.SetPageText(np, title) class HtmlPage(wx.html.HtmlWindow): def __init__(self, parent, id): wx.html.HtmlWindow.__init__(self, parent, id, style=wx.NO_FULL_REPAINT_ON_RESIZE) if "gtk2" in wx.PlatformInfo: self.SetStandardFonts() def OnLinkClicked(self, link): href = link.GetHref() #print href _AddPage(href) class HtmlBrowser(wx.Dialog): def __init__(self, parent, file, title): global note, dir dir = os.path.dirname(file) wx.Dialog.__init__(self, parent, -1, title, size=(500, 600), style=wx.DEFAULT_DIALOG_STYLE | wx.THICK_FRAME) note = wx.Notebook(self, -1) history.clear() _AddPage(file) note.SetSelection(0) #else nothing is displayed event = wx.SizeEvent() self.GetEventHandler().ProcessEvent(event) def ShowHtmlFile(parent, file, title=""): if title == "": title = file d = HtmlBrowser(parent, file, title) d.ShowModal() d.Destroy() drpython-3.11.1/drStyleDialog.py0000644000175000017500000012346011150445514017400 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import string, os.path import wx import wx.stc from drProperty import * import drScrolledMessageDialog from drPrefsFile import ExtractPreferenceFromText class drColorPanel(wx.Panel): def __init__(self, parent, id, point, size, fg): wx.Panel.__init__(self, parent, id, point, size) self.ID_COLOR = 105 self.ID_RED = 106 self.ID_GREEN = 107 self.ID_BLUE = 108 self.theSizer = wx.BoxSizer(wx.VERTICAL) self.txtColor = wx.TextCtrl(self, self.ID_COLOR, "", wx.Point(0, 10), wx.Size(100, -1)) self.isForeground = fg self.red = wx.Slider(self, self.ID_RED, 0, 0, 255, wx.Point(0, 40), wx.Size(100, 35), wx.SL_HORIZONTAL | wx.SL_LABELS) self.green = wx.Slider(self, self.ID_GREEN, 0, 0, 255, wx.Point(0, 70), wx.Size(100, 35), wx.SL_HORIZONTAL | wx.SL_LABELS) self.blue = wx.Slider(self, self.ID_BLUE, 0, 0, 255, wx.Point(0, 100), wx.Size(100, 35), wx.SL_HORIZONTAL | wx.SL_LABELS) self.theSizer.Add(self.txtColor, 0, wx.SHAPED) self.theSizer.Add(self.red, 0, wx.SHAPED) self.theSizer.Add(self.green, 0, wx.SHAPED) self.theSizer.Add(self.blue, 0, wx.SHAPED) self.SetAutoLayout(True) self.SetSizer(self.theSizer) self.Bind(wx.EVT_SCROLL, self.OnScroll) self.red.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) self.green.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) self.blue.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) self.Bind(wx.EVT_TEXT, self.OnTextChange, id=self.ID_COLOR) def GetValue(self): return self.txtColor.GetValue() def OnLeftUp(self, event): self.txtColor.SetEditable(True) event.Skip() def OnScroll(self, event): self.txtColor.SetEditable(False) i = event.GetId() if i == self.ID_RED: r = self.red.GetValue() sr = '' if r < 16: sr = '0' sr = sr + hex(r)[2:] sr = sr.upper() text = self.txtColor.GetValue() if len(text) != 7: drScrolledMessageDialog.ShowMessage(self, ("The text box above should be formatted as follows:\n#0033AA,\nStart with the # character, followed by 6 characters which can be 0-9 or a-f.\nDrPython will ignore any changes to the color until this is fixed."), "Error") return self.txtColor.SetValue(text[0:1] + sr + text[3:]) elif i == self.ID_GREEN: g = self.green.GetValue() sr = '' if g < 16: sr = '0' sr = sr + hex(g)[2:] sr = sr.upper() text = self.txtColor.GetValue() if len(text) != 7: drScrolledMessageDialog.ShowMessage(self, ("The text box above should be formatted as follows:\n#0033AA,\nStart with the # character, followed by 6 characters which can be 0-9 or a-f.\nDrPython will ignore any changes to the color until this is fixed."), "Error") return self.txtColor.SetValue(text[0:3] + sr + text[5:]) elif i == self.ID_BLUE: b = self.blue.GetValue() sr = '' if b < 16: sr = '0' sr = sr + hex(b)[2:] sr = sr.upper() text = self.txtColor.GetValue() if len(text) != 7: drScrolledMessageDialog.ShowMessage(self, ("The text box above should be formatted as follows:\n#0033AA,\nStart with the # character, followed by 6 characters which can be 0-9 or a-f.\nDrPython will ignore any changes to the color until this is fixed."), "Error") return self.txtColor.SetValue(text[0:5] + sr + text[7:]) event.Skip() def OnTextChange(self, event): v = self.txtColor.GetValue() if self.txtColor.IsEditable(): if not v: self.red.Enable(False) self.green.Enable(False) self.blue.Enable(False) return if (v[0] == "#") and (len(v) == 7): #Update Sliders self.red.Enable(True) self.green.Enable(True) self.blue.Enable(True) try: self.red.SetValue(int(v[1:3], 16)) self.green.SetValue(int(v[3:5], 16)) self.blue.SetValue(int(v[5:7], 16)) except: drScrolledMessageDialog.ShowMessage(self, ("Bad Color Data. Should be in the form #00A3F4\nUse only digits 0-9, characters A-F"), "Error") else: self.red.Enable(False) self.green.Enable(False) self.blue.Enable(False) if len(v) == 7: if v[0] == "#": #Update Parent if self.isForeground: self.GetParent().foreground = v else: self.GetParent().background = v self.GetParent().SetColor() event.Skip() def SetValue(self, colorstring): self.txtColor.SetValue(colorstring) r = int(colorstring[1:3], 16) g = int(colorstring[3:5], 16) b = int(colorstring[5:7], 16) self.red.SetValue(r) self.green.SetValue(g) self.blue.SetValue(b) #***************************************** class drSeparatorDialog(wx.Dialog): def __init__(self, parent, title): wx.Dialog.__init__(self, parent, -1, title, wx.DefaultPosition, wx.Size(-1, -1)) self.parent = parent self.ID_CANCEL = 101 self.ID_OK = 102 self.ID_SAVE = 103 self.favorites = {0:('#000000', '#CAFFFF'), 1:('#000000', '#FFFFC6'), 2:('#000000', '#BEFFC6'), 3:('#000000', '#FFA400'), 4:('#00FF00', '#000000')} self.favoritefile = self.parent.datdirectory + '/.separator.favorite.colours.dat' self.txtLabel = wx.TextCtrl(self, -1, 'Label', size=wx.Size(300, -1), style=wx.TE_PROCESS_ENTER|wx.TE_RICH2) self.txtLabel.SetSelection(0, 5) self.btn0 = wx.Button(self, 0, '&0', style=wx.BU_EXACTFIT) self.btn1 = wx.Button(self, 1, '&1', style=wx.BU_EXACTFIT) self.btn2 = wx.Button(self, 2, '&2', style=wx.BU_EXACTFIT) self.btn3 = wx.Button(self, 3, '&3', style=wx.BU_EXACTFIT) self.btn4 = wx.Button(self, 4, '&4', style=wx.BU_EXACTFIT) self.btnSave = wx.Button(self, self.ID_SAVE, '&Save Favorite') self.fgPanel = drColorPanel(self, -1, wx.Point(10, 200), wx.Size(400, 350), True) self.bgPanel = drColorPanel(self, -1, wx.Point(220, 200), wx.Size(400, 350), False) self.fgPanel.SetValue('#000000') self.bgPanel.SetValue('#FFFFFF') self.btnCancel = wx.Button(self, self.ID_CANCEL, "&Cancel", wx.Point(5, 0), wx.Size(-1, -1)) self.btnOk = wx.Button(self, self.ID_OK, "&Ok", wx.Point(400, 0), wx.Size(-1, -1)) self.LoadFavorites() #Sizer: self.theSizer = wx.BoxSizer(wx.VERTICAL) self.textSizer = wx.BoxSizer(wx.HORIZONTAL) self.favoritesSizer = wx.BoxSizer(wx.HORIZONTAL) self.panelSizer = wx.BoxSizer(wx.HORIZONTAL) self.buttonSizer = wx.BoxSizer(wx.HORIZONTAL) self.favoritesSizer.Add(self.btn0, 0, wx.SHAPED | wx.ALIGN_CENTER) self.favoritesSizer.Add(self.btn1, 0, wx.SHAPED | wx.ALIGN_CENTER) self.favoritesSizer.Add(self.btn2, 0, wx.SHAPED | wx.ALIGN_CENTER) self.favoritesSizer.Add(self.btn3, 0, wx.SHAPED | wx.ALIGN_CENTER) self.favoritesSizer.Add(self.btn4, 0, wx.SHAPED | wx.ALIGN_CENTER) self.favoritesSizer.Add(self.btnSave, 0, wx.SHAPED | wx.ALIGN_CENTER) self.panelSizer.Add(self.fgPanel, 1, wx.SHAPED) self.panelSizer.Add(self.bgPanel, 1, wx.SHAPED | wx.ALIGN_RIGHT) self.buttonSizer.Add(self.btnCancel, 1, wx.SHAPED) self.buttonSizer.Add(self.btnOk, 1, wx.SHAPED | wx.ALIGN_RIGHT) self.textSizer.Add(self.txtLabel, 1, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.textSizer, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, 'Favorite Colours:'), 0, wx.SHAPED) self.theSizer.Add(self.favoritesSizer, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.theSizer.Add(self.panelSizer, 1, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, ' '), 0, wx.SHAPED) self.theSizer.Add(self.buttonSizer, 0, wx.EXPAND) self.SetAutoLayout(True) self.SetSizerAndFit(self.theSizer) #End Sizer self.Bind(wx.EVT_BUTTON, self.OnbtnCancel, id=self.ID_CANCEL) self.Bind(wx.EVT_BUTTON, self.OnbtnOk, id=self.ID_OK) self.Bind(wx.EVT_BUTTON, self.OnFavorite, id=0) self.Bind(wx.EVT_BUTTON, self.OnFavorite, id=1) self.Bind(wx.EVT_BUTTON, self.OnFavorite, id=2) self.Bind(wx.EVT_BUTTON, self.OnFavorite, id=3) self.Bind(wx.EVT_BUTTON, self.OnFavorite, id=4) self.Bind(wx.EVT_BUTTON, self.OnbtnSave, id=self.ID_SAVE) self.Bind(wx.EVT_CHAR, self.OnChar) self.txtLabel.Bind(wx.EVT_CHAR, self.OnChar) if parent.PLATFORM_IS_GTK: #does not get initially the focus (bug tracker #1903778, "Open Imported Module: focus problem", 29.02.2008: from Jon White, thanks. self.SetFocus() def GetLabel(self): return '#---' + self.txtLabel.GetValue() + '---' + self.fgPanel.GetValue() + self.bgPanel.GetValue() + '---------------------------------' def LoadFavorites(self): if os.path.exists(self.favoritefile): try: f = file(self.favoritefile, 'rb') text = f.read() f.close() for fL in range(5): result = ExtractPreferenceFromText(text, str(fL)) if result: results = result.split(',') if len(results) == 2: self.favorites[fL] = results except: self.parent.ShowMessage('Error Loading Favorite Colours', 'Error') def OnbtnCancel(self, event): self.EndModal(wx.ID_CANCEL) def OnbtnOk(self, event): self.EndModal(wx.ID_OK) def OnbtnSave(self, event): d = wx.SingleChoiceDialog(self, "Store Current Colour in Which Slot?", "Save Favorite", ['0', '1', '2', '3', '4'], wx.OK|wx.CANCEL) answer = d.ShowModal() i = d.GetSelection() d.Destroy() if answer == wx.ID_OK: try: self.favorites[i] = (self.fgPanel.GetValue(), self.bgPanel.GetValue()) f = file(self.favoritefile, 'wb') x = 0 l = len(self.favorites) while x < l: f.write('<' + str(x) + '>' + self.favorites[x][0] + ',' + self.favorites[x][1] + '') x += 1 f.close() except: self.parent.ShowMessage('Error Saving Favorite Colours', 'Error') def OnChar(self, event): if event.GetKeyCode() == wx.WXK_ESCAPE: self.OnbtnCancel(event) elif event.GetKeyCode() == wx.WXK_RETURN: self.OnbtnOk(event) else: event.Skip() def OnFavorite(self, event): i = event.GetId() self.fgPanel.SetValue(self.favorites[i][0]) self.bgPanel.SetValue(self.favorites[i][1]) def SetColor(self): self.txtLabel.SetForegroundColour(wx.Colour(self.fgPanel.red.GetValue(), self.fgPanel.green.GetValue(), self.fgPanel.blue.GetValue())) self.txtLabel.SetBackgroundColour(wx.Colour(self.bgPanel.red.GetValue(), self.bgPanel.green.GetValue(), self.bgPanel.blue.GetValue())) #***************************************** class drSimpleStyleDialog(wx.Dialog): def __init__(self, parent, id, title, stylestring, defaultstylestring, ChangeSpec = 0): wx.Dialog.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(-1, -1)) self.ID_CANCEL = 101 self.ID_OK = 102 self.ID_FONTS = 103 self.ID_SIZE = 104 self.ID_BOLD = 109 self.ID_ITALIC = 110 self.ID_UNDERLINE = 111 self.Enum = wx.FontEnumerator() self.Enum.EnumerateFacenames() self.FontList = self.Enum.GetFacenames() self.FontList.sort() self.OK = False self.font = getStyleProperty("face", stylestring) if not self.font: self.font = getStyleProperty("face", defaultstylestring) self.size = getStyleProperty("size", stylestring) if not self.size: self.size = getStyleProperty("size", defaultstylestring) self.foreground = getStyleProperty("fore", stylestring) if not self.foreground: self.foreground = getStyleProperty("fore", defaultstylestring) self.background = getStyleProperty("back", stylestring) if not self.background: self.background = getStyleProperty("back", defaultstylestring) self.bold = getStyleProperty("bold", stylestring) self.italic = getStyleProperty("italic", stylestring) self.underline = getStyleProperty("underline", stylestring) self.txtPreview = wx.stc.StyledTextCtrl(self, id, wx.Point(225, 15), wx.Size(225, 150)) if ChangeSpec > 0: self.font = getStyleProperty("face", defaultstylestring) self.size = getStyleProperty("size", defaultstylestring) if ChangeSpec == 1: self.background = getStyleProperty("back", defaultstylestring) elif ChangeSpec == 3: self.foreground = getStyleProperty("fore", defaultstylestring) if self.font not in self.FontList: old=self.font self.size = '12' options=['Courier','Courier 10 Pitch','Monospace','Sans',''] for font in options: if font in self.FontList: self.font=font break drScrolledMessageDialog.ShowMessage(self, ("Default font [%s] not found! \nChoosed [%s] instead." %(old,self.font)), "Error") self.txtPreview.SetText("Preview\n()[]{}\n0123") self.txtPreview.SetUseHorizontalScrollBar(0) self.txtPreview.SetReadOnly(1) self.txtPreview.SetMarginWidth(0, 0) self.txtPreview.SetMarginWidth(1, 0) self.txtPreview.SetMarginWidth(2, 0) self.txtPreview.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline)) self.txtPreview.StyleClearAll() self.txtPreview.StartStyling(0, 0xff) self.boxFonts = wx.ListBox(self, self.ID_FONTS, wx.Point(10, 10), wx.Size(250, 250), self.FontList) try: #self.boxFonts.SetStringSelection(self.font) i=self.boxFonts.FindString(self.font) if i<0: i=0 self.boxFonts.Select(i) #self.boxFonts.EnsureVisible(i) # Bug: Doesn't work self.boxFonts.SetFirstItem(i) except: drScrolledMessageDialog.ShowMessage(self, ("Something awful happened trying to \nset the font to the default."), "Error") self.boxFonts.SetSelection(0) self.boxSize = wx.ComboBox(self, self.ID_SIZE, self.size, wx.Point(10, 175), wx.Size(150, 50), ['8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30']) self.fgPanel = drColorPanel(self, id, wx.Point(10, 200), wx.Size(400, 225), True) self.fgPanel.SetValue(self.foreground) self.bgPanel = drColorPanel(self, id, wx.Point(220, 200), wx.Size(400, 225), False) self.bgPanel.SetValue(self.background) self.chkBold = wx.CheckBox(self, self.ID_BOLD, "Bold", wx.Point(10, 345)) if self.bold: self.chkBold.SetValue(1) self.chkItalic = wx.CheckBox(self, self.ID_ITALIC, "Italic", wx.Point(110, 345)) if self.italic: self.chkItalic.SetValue(1) self.chkUnderline = wx.CheckBox(self, self.ID_UNDERLINE, "Underline", wx.Point(210, 345)) if self.underline: self.chkUnderline.SetValue(1) if ChangeSpec > 0: self.boxFonts.Enable(False) self.boxSize.Enable(False) self.chkBold.Enable(False) self.chkItalic.Enable(False) self.chkUnderline.Enable(False) if ChangeSpec == 1: self.bgPanel.Enable(False) elif ChangeSpec == 3: self.fgPanel.Enable(False) self.btnCancel = wx.Button(self, self.ID_CANCEL, "&Cancel", wx.Point(5, 0), wx.Size(-1, -1)) self.btnOk = wx.Button(self, self.ID_OK, "&Ok", wx.Point(300, 0), wx.Size(-1, -1)) #Sizer: self.theSizer = wx.FlexGridSizer(2, 2, 5, 1) self.styleSizerLeft = wx.BoxSizer(wx.VERTICAL) self.styleSizerRight = wx.BoxSizer(wx.VERTICAL) self.styleSizerLeft.Add(wx.StaticText(self, -1, "Font:"), 0, wx.ALL|wx.SHAPED,4) self.styleSizerLeft.Add(self.boxFonts, 0, wx.ALL|wx.SHAPED,4) self.styleSizerLeft.Add(wx.StaticText(self, -1, "Size:"), 0, wx.ALL|wx.SHAPED,4) self.styleSizerLeft.Add(self.boxSize, 0, wx.ALL|wx.SHAPED,4) self.styleSizerLeft.Add(self.chkBold, 0, wx.ALL|wx.SHAPED,4) self.styleSizerLeft.Add(wx.StaticText(self, -1, " "), 0, wx.ALL|wx.SHAPED,4) self.styleSizerLeft.Add(self.chkItalic, 0, wx.ALL|wx.SHAPED,4) self.styleSizerLeft.Add(wx.StaticText(self, -1, " "), 0, wx.ALL|wx.SHAPED,4) self.styleSizerLeft.Add(self.chkUnderline, 0, wx.ALL|wx.SHAPED,4) self.styleSizerRight.Add(self.txtPreview, 0, wx.ALL|wx.SHAPED,4) self.styleSizerRight.Add(wx.StaticText(self, -1, 'Foreground:'), 0, wx.ALL|wx.SHAPED,4) self.styleSizerRight.Add(self.fgPanel, 0, wx.ALL|wx.SHAPED,4) self.styleSizerRight.Add(wx.StaticText(self, -1, 'Background:'), 0, wx.ALL|wx.SHAPED,4) self.styleSizerRight.Add(self.bgPanel, 1, wx.ALL|wx.SHAPED,4) self.theSizer.Add(self.styleSizerLeft, 0, wx.ALL|wx.SHAPED,4) self.theSizer.Add(self.styleSizerRight, 0, wx.ALL|wx.SHAPED,4) self.theSizer.Add(self.btnCancel, 0, wx.ALL|wx.SHAPED|wx.ALIGN_RIGHT,4) self.theSizer.Add(self.btnOk, 0, wx.ALL | wx.SHAPED|wx.ALIGN_LEFT ,4) self.SetAutoLayout(True) self.SetSizerAndFit(self.theSizer) self.btnCancel.SetDefault() #End Sizer self.Bind(wx.EVT_LISTBOX, self.OnFontSelect, id=self.ID_FONTS) self.Bind(wx.EVT_COMBOBOX, self.OnSizeSelect, id=self.ID_SIZE) self.Bind(wx.EVT_TEXT, self.OnChangeSize, id=self.ID_SIZE) self.Bind(wx.EVT_CHECKBOX, self.OnBold, id=self.ID_BOLD) self.Bind(wx.EVT_CHECKBOX, self.OnItalic, id=self.ID_ITALIC) self.Bind(wx.EVT_CHECKBOX, self.OnUnderline, id=self.ID_UNDERLINE) self.Bind(wx.EVT_BUTTON, self.OnbtnCancel, id=self.ID_CANCEL) self.Bind(wx.EVT_BUTTON, self.OnbtnOk, id=self.ID_OK) def OnChangeSize(self, event): self.size = self.boxSize.GetValue() self.txtPreview.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline)) self.txtPreview.StyleClearAll() self.txtPreview.StartStyling(0, 0xff) def OnFontSelect(self, event): self.font = self.boxFonts.GetStringSelection() self.txtPreview.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline)) self.txtPreview.StyleClearAll() self.txtPreview.StartStyling(0, 0xff) def OnSizeSelect(self, event): self.size = self.boxSize.GetStringSelection() self.txtPreview.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline)) self.txtPreview.StyleClearAll() self.txtPreview.StartStyling(0, 0xff) def SetColor(self): self.txtPreview.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline)) self.txtPreview.StyleClearAll() self.txtPreview.StartStyling(0, 0xff) def OnBold(self, event): if self.chkBold.IsChecked(): self.bold = "bold" else: self.bold = "" self.txtPreview.StyleResetDefault() self.txtPreview.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline)) self.txtPreview.StyleClearAll() self.txtPreview.StartStyling(0, 0xff) def OnItalic(self, event): if self.chkItalic.IsChecked(): self.italic = "italic" else: self.italic = "" self.txtPreview.StyleResetDefault() self.txtPreview.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline)) self.txtPreview.StyleClearAll() self.txtPreview.StartStyling(0, 0xff) def OnUnderline(self, event): if self.chkUnderline.IsChecked(): self.underline = "underline" else: self.underline = "" self.txtPreview.StyleResetDefault() self.txtPreview.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline)) self.txtPreview.StyleClearAll() self.txtPreview.StartStyling(0, 0xff) def OnbtnCancel(self, event): self.EndModal(0) def OnbtnOk(self, event): self.OK = True self.EndModal(0) def ClickedOk(self): return self.OK def GetBackground(self): return self.background def GetColorString(self): return ("fore:" + self.foreground + ",back:" + self.background) def GetForeground(self): return self.foreground def GetStyleString(self): return ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline) class drStyleDialog(wx.Dialog): def __init__(self, parent, id, title, isPrompt = False): wx.Dialog.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(640, 480)) self.ancestor = parent.grandparent.parent self.ID_CANCEL = 101 self.ID_OK = 102 self.ID_FONTS = 103 self.ID_SIZE = 104 self.ID_BOLD = 109 self.ID_ITALIC = 110 self.ID_UNDERLINE = 111 self.ID_STYLE = 121 self.ID_LANGUAGE = 122 self.last = 0 if isPrompt: self.txtPromptStyleDictionary = self.ancestor.prefs.txtPromptStyleDictionary.copy() else: self.PythonStyleDictionary = self.ancestor.prefs.PythonStyleDictionary.copy() self.CPPStyleDictionary = self.ancestor.prefs.CPPStyleDictionary.copy() self.HTMLStyleDictionary = self.ancestor.prefs.HTMLStyleDictionary.copy() self.targetArray = [] self.ChangeSpec = 0 self.Enum = wx.FontEnumerator() self.Enum.EnumerateFacenames() self.FontList = self.Enum.GetFacenames() self.FontList.sort() self.txtPreview = wx.stc.StyledTextCtrl(self, id, wx.Point(225, 15), wx.Size(225, 125)) self.Ok = False self.isPrompt = isPrompt i = self.ancestor.txtDocument.filetype if i > 2: i = 0 self.boxLanguage = wx.Choice(self, self.ID_LANGUAGE, wx.Point(150, 135), wx.Size(-1, -1), ["Python", "C/C++", "HTML"]) self.boxLanguage.SetSelection(i) if isPrompt: self.boxLanguage.Enable(False) self.txtPreview.SetText("Preview\n()[]{}\n0123") self.txtPreview.SetUseHorizontalScrollBar(0) self.txtPreview.SetMarginWidth(0, 0) self.txtPreview.SetMarginWidth(1, 0) self.txtPreview.SetMarginWidth(2, 0) self.txtPreview.SetReadOnly(1) self.boxFonts = wx.ListBox(self, self.ID_FONTS, wx.DefaultPosition, wx.Size(200, 250), self.FontList) self.boxSize = wx.ComboBox(self, self.ID_SIZE, "10", wx.DefaultPosition, wx.Size(150, 50), ['8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30']) self.fgPanel = drColorPanel(self, id, wx.DefaultPosition, wx.Size(400, 225), True) self.bgPanel = drColorPanel(self, id, wx.DefaultPosition, wx.Size(400, 225), False) self.chkBold = wx.CheckBox(self, self.ID_BOLD, "Bold") self.chkItalic = wx.CheckBox(self, self.ID_ITALIC, "Italic") self.chkUnderline = wx.CheckBox(self, self.ID_UNDERLINE, "Underline") self.btnCancel = wx.Button(self, self.ID_CANCEL, "&Cancel") self.btnCancel.SetDefault() self.btnOk = wx.Button(self, self.ID_OK, "&Ok") self.boxStyle = wx.ListBox(self, self.ID_STYLE, wx.DefaultPosition, wx.Size(150, 350), "") #Sizer: self.theSizer = wx.FlexGridSizer(2, 3, 5, 1) self.selectSizer = wx.FlexGridSizer(3, 3, 5, 10) self.listSizer = wx.BoxSizer(wx.HORIZONTAL) self.styleSizerLeft = wx.BoxSizer(wx.VERTICAL) self.styleSizerRight = wx.BoxSizer(wx.VERTICAL) self.styleSizerLeft.Add(wx.StaticText(self, -1, "Font:"), 0, wx.SHAPED) self.styleSizerLeft.Add(self.boxFonts, 0, wx.SHAPED) self.styleSizerLeft.Add(wx.StaticText(self, -1, "Size:"), 0, wx.SHAPED) self.styleSizerLeft.Add(self.boxSize, 0, wx.SHAPED) self.styleSizerLeft.Add(self.chkBold, 0, wx.SHAPED) self.styleSizerLeft.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.styleSizerLeft.Add(self.chkItalic, 0, wx.SHAPED) self.styleSizerLeft.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.styleSizerLeft.Add(self.chkUnderline, 0, wx.SHAPED) self.styleSizerRight.Add(self.txtPreview, 0, wx.SHAPED) self.styleSizerRight.Add(wx.StaticText(self, -1, 'Foreground:'), 0, wx.SHAPED) self.styleSizerRight.Add(self.fgPanel, 0, wx.SHAPED) self.styleSizerRight.Add(wx.StaticText(self, -1, 'Background:'), 0, wx.SHAPED) self.styleSizerRight.Add(self.bgPanel, 1, wx.SHAPED) self.listSizer.Add(wx.StaticText(self, -1, "Language: "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.listSizer.Add(self.boxLanguage, 0, wx.ALIGN_CENTER | wx.SHAPED) self.selectSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_LEFT | wx.SHAPED) self.selectSizer.Add(self.listSizer, 0, wx.ALIGN_LEFT | wx.SHAPED) self.selectSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_LEFT | wx.SHAPED) self.selectSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_LEFT | wx.SHAPED) self.selectSizer.Add(wx.StaticText(self, -1, "Text Type:"), 0, wx.ALIGN_LEFT | wx.SHAPED) self.selectSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_LEFT | wx.SHAPED) self.selectSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.selectSizer.Add(self.boxStyle, 1, wx.SHAPED | wx.ALIGN_CENTER) self.selectSizer.Add(wx.StaticText(self, -1, ""), 1, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.selectSizer, 0, wx.SHAPED) self.theSizer.Add(self.styleSizerLeft, 0, wx.SHAPED) self.theSizer.Add(self.styleSizerRight, 0, wx.SHAPED) self.theSizer.Add(self.btnCancel, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(wx.StaticText(self, -1, ""), 0, wx.SHAPED) self.theSizer.Add(self.btnOk, 1, wx.SHAPED | wx.ALIGN_CENTER) self.SetAutoLayout(True) self.SetSizer(self.theSizer) #End Sizer self.OnSelectLanguage(None) self.Bind(wx.EVT_LISTBOX, self.OnFontSelect, id=self.ID_FONTS) self.Bind(wx.EVT_LISTBOX, self.OnSelectStyle, id=self.ID_STYLE) self.Bind(wx.EVT_CHOICE, self.OnSelectLanguage, id=self.ID_LANGUAGE) self.Bind(wx.EVT_COMBOBOX, self.OnSizeSelect, id=self.ID_SIZE) self.Bind(wx.EVT_TEXT, self.OnChangeSize, id=self.ID_SIZE) self.Bind(wx.EVT_CHECKBOX, self.OnBold, id=self.ID_BOLD) self.Bind(wx.EVT_CHECKBOX, self.OnItalic, id=self.ID_ITALIC) self.Bind(wx.EVT_CHECKBOX, self.OnUnderline, id=self.ID_UNDERLINE) self.Bind(wx.EVT_BUTTON, self.OnbtnCancel, id=self.ID_CANCEL) self.Bind(wx.EVT_BUTTON, self.OnbtnOk, id=self.ID_OK) def OnChangeSize(self, event): self.size = self.boxSize.GetValue() self.txtPreview.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline)) self.txtPreview.StyleClearAll() self.txtPreview.StartStyling(0, 0xff) def OnFontSelect(self, event): self.font = self.boxFonts.GetStringSelection() self.txtPreview.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline)) self.txtPreview.StyleClearAll() self.txtPreview.StartStyling(0, 0xff) def OnSizeSelect(self, event): self.size = self.boxSize.GetStringSelection() self.txtPreview.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline)) self.txtPreview.StyleClearAll() self.txtPreview.StartStyling(0, 0xff) def SetColor(self): self.txtPreview.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline)) self.txtPreview.StyleClearAll() self.txtPreview.StartStyling(0, 0xff) def OnBold(self, event): if self.chkBold.IsChecked(): self.bold = "bold" else: self.bold = "" self.txtPreview.StyleResetDefault() self.txtPreview.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline)) self.txtPreview.StyleClearAll() self.txtPreview.StartStyling(0, 0xff) def OnItalic(self, event): if self.chkItalic.IsChecked(): self.italic = "italic" else: self.italic = "" self.txtPreview.StyleResetDefault() self.txtPreview.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline)) self.txtPreview.StyleClearAll() self.txtPreview.StartStyling(0, 0xff) def OnUnderline(self, event): if self.chkUnderline.IsChecked(): self.underline = "underline" else: self.underline = "" self.txtPreview.StyleResetDefault() self.txtPreview.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline)) self.txtPreview.StyleClearAll() self.txtPreview.StartStyling(0, 0xff) def OnbtnCancel(self, event): self.EndModal(0) def OnbtnOk(self, event): if self.ChangeSpec == 0: self.targetArray[self.last] = self.GetStyleString() elif self.ChangeSpec == 1: self.targetArray[self.last] = self.GetForeground() elif self.ChangeSpec == 2: self.targetArray[self.last] = self.GetColorString() elif self.ChangeSpec == 3: self.targetArray[self.last] = self.GetBackground() self.Ok = True self.EndModal(0) def ClickedOk(self): return self.Ok def GetArrays(self): if self.isPrompt: return self.txtPromptStyleDictionary return self.PythonStyleDictionary, self.CPPStyleDictionary, self.HTMLStyleDictionary def GetBackground(self): return self.background def GetColorString(self): return ("fore:" + self.foreground + ",back:" + self.background) def GetForeground(self): return self.foreground def GetStyleString(self): return ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline) def OnSelectLanguage(self, event): sel = self.boxLanguage.GetSelection() try: if self.ChangeSpec == 0: self.targetArray[self.last] = self.GetStyleString() elif self.ChangeSpec == 1: self.targetArray[self.last] = self.GetForeground() elif self.ChangeSpec == 2: self.targetArray[self.last] = self.GetColorString() elif self.ChangeSpec == 3: self.targetArray[self.last] = self.GetBackground() except: #This will happen the first time this function is called. pass if self.isPrompt: self.targetArray = self.txtPromptStyleDictionary array = ["Normal", "Line Number (Margin)", "Brace-Selected (Match)", "Brace-Selected (No Match)", "Character (Single Quoted String)", "Class Name", "Comment", "Comment Block", "Function Name", "Keyword", "Number", "Operator", "String", "String EOL", "Triple Quoted String", "Caret Foreground", "Selection"] else: if sel == 1: self.targetArray = self.CPPStyleDictionary array = ["Normal", "Line Number (Margin)", "Brace-Selected (Match)", "Brace-Selected (No Match)", "Character", "Preprocessor", "Comment", "Verbatim", "Keyword", "C Identifier", "Number", "Operator", "String", "String EOL", "Global Class", "Regex", "UUID", "Caret Foreground", "Selection", "Folding", "Long Line Indicator"] elif sel == 2: self.targetArray = self.HTMLStyleDictionary array = ["Normal", "Line Number (Margin)", "Brace-Selected (Match)", "Brace-Selected (No Match)", "Tag", "Unkown Tag", "Atrribute", "Unkown Attribute", "Number", "String", "Character (Single Quoted String)", "Comment", "Entity", "Tag End", "XML Start", "XML End", "Script", "Value", "Caret Foreground", "Selection", "Folding", "Long Line Indicator", "Current Line Highlight"] else: self.targetArray = self.PythonStyleDictionary array = ["Normal", "Line Number (Margin)", "Brace-Selected (Match)", "Brace-Selected (No Match)", "Character (Single Quoted String)", "Class Name", "Comment", "Comment Block", "Function Name", "Keyword", "Number", "Operator", "String", "String EOL", "Triple Quoted String", "Caret Foreground", "Selection", "Folding", "Long Line Indicator", "Current Line Highlight", "Indentation Guide"] self.last = -1 self.boxStyle.Set(array) self.boxStyle.SetSelection(0) self.OnSelectStyle(event) def OnSelectStyle(self, event): current = self.boxStyle.GetSelection() seltext = self.boxStyle.GetStringSelection() if self.last > -1: if self.ChangeSpec == 0: self.targetArray[self.last] = self.GetStyleString() elif self.ChangeSpec == 1: self.targetArray[self.last] = self.GetForeground() elif self.ChangeSpec == 2: self.targetArray[self.last] = self.GetColorString() elif self.ChangeSpec == 3: self.targetArray[self.last] = self.GetBackground() self.ChangeSpec = 0 stylestring = self.targetArray[current] if (seltext == "Caret Foreground") or (seltext == "Long Line Indicator") or (seltext == "Indentation Guide"): self.ChangeSpec = 1 stylestring = "fore:" + stylestring elif (seltext == "Selection") or (seltext == "Folding"): self.ChangeSpec = 2 elif seltext == "Current Line Highlight": self.ChangeSpec = 3 stylestring = "back:" + stylestring self.font = getStyleProperty("face", stylestring) if not self.font: self.font = getStyleProperty("face", self.targetArray[0]) self.size = getStyleProperty("size", stylestring) if not self.size: self.size = getStyleProperty("size", self.targetArray[0]) self.foreground = getStyleProperty("fore", stylestring) if not self.foreground: self.foreground = getStyleProperty("fore", self.targetArray[0]) self.background = getStyleProperty("back", stylestring) if not self.background: self.background = getStyleProperty("back", self.targetArray[0]) self.bold = getStyleProperty("bold", stylestring) self.italic = getStyleProperty("italic", stylestring) self.underline = getStyleProperty("underline", stylestring) if self.ChangeSpec > 0: self.font = getStyleProperty("face", self.targetArray[0]) self.size = getStyleProperty("size", self.targetArray[0]) if self.ChangeSpec == 1: self.background = getStyleProperty("back", self.targetArray[0]) elif self.ChangeSpec == 3: self.foreground = getStyleProperty("fore", self.targetArray[0]) if self.font not in self.FontList: f1 = string.capwords(self.font) f2 = string.lower(self.font) if f1 in self.FontList: self.font = f1 elif f2 in self.FontList: self.font = f2 if self.font not in self.FontList: old=self.font self.size = '12' options=['Courier','Courier 10 Pitch','Monospace','Sans',''] for font in options: if font in self.FontList: self.font=font break #I don't know why this a traceback: no foreground !!! #drScrolledMessageDialog.ShowMessage(self, ("Default font [%s] not found! \nChoosed [%s] instead." %(old,self.font)), "Error") print "Default font [%s] not found! \nChoosed [%s] instead." %(old,self.font) self.txtPreview.StyleResetDefault() self.txtPreview.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, ("fore:" + self.foreground + ",back:" + self.background + ",size:" + self.size + ",face:" + self.font + "," + self.bold + "," + self.italic + "," + self.underline)) self.txtPreview.StyleClearAll() self.txtPreview.StartStyling(0, 0xff) try: #self.boxFonts.SetStringSelection(self.font) i=self.boxFonts.FindString(self.font) if i<0: i=0 self.boxFonts.Select(i) #self.boxFonts.EnsureVisible(i) # Bug: Doesn't work self.boxFonts.SetFirstItem(i) except: drScrolledMessageDialog.ShowMessage(self, ("Something awful happened trying to \nset the font to the default."), "Error") self.boxFonts.SetSelection(0) try: tsizearray = ['8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30'] if not self.size in tsizearray: self.boxSize.SetValue(self.size) else: i = tsizearray.index(self.size) self.boxSize.SetSelection(i) except: drScrolledMessageDialog.ShowMessage(self, ("Something awful happened trying to \nset the font to the default."), "Error") self.boxSize.SetSelection(0) self.OnSizeSelect(event) self.fgPanel.SetValue(self.foreground) self.bgPanel.SetValue(self.background) self.chkBold.SetValue((len(self.bold) > 0)) self.chkItalic.SetValue((len(self.italic) > 0)) self.chkUnderline.SetValue((len(self.underline) > 0)) self.boxFonts.Enable(self.ChangeSpec == 0) self.boxSize.Enable(self.ChangeSpec == 0) self.chkBold.Enable(self.ChangeSpec == 0) self.chkItalic.Enable(self.ChangeSpec == 0) self.chkUnderline.Enable(self.ChangeSpec == 0) if self.ChangeSpec == 1: self.fgPanel.Enable(True) self.bgPanel.Enable(False) elif self.ChangeSpec == 3: self.fgPanel.Enable(False) self.bgPanel.Enable(True) else: self.fgPanel.Enable(True) self.bgPanel.Enable(True) self.last = currentdrpython-3.11.1/tools/0000755000175000017500000000000011246265352015420 5ustar dktrkranzdktrkranzdrpython-3.11.1/tools/dr26prefs.bat0000644000175000017500000000010711150445515017716 0ustar dktrkranzdktrkranzpython ..\drpython_wx26.py --preferencesbasepath=C:/drpython/drpython26drpython-3.11.1/tools/convert_drkeys.py0000644000175000017500000000435411150445515021034 0ustar dktrkranzdktrkranz#!/usr/bin/python # -*- coding: iso-8859-1 -* """ convert_drkeys.py Convert key codes of DrPython Shortcuts Antonio Barbosa 29 Dec 2006 I must be run twice: In first run, creates a file with «old» keycodes In the second run, creates another file with «new» keycodes. And then prompts for conversion of each shortcuts file of DrPython. It should be wise to make backups of those files :) """ import os import wxversion import re fname1="keys_2.6.txt" fname2="keys_2.8.txt" Dict1={} Dict2={} drFiles=["shortcuts.dat","stcshortcuts.dat","drscript.shortcuts.dat"] userpreferencesdirectory = os.environ["APPDATA"].replace("\\", "/") +'/drpython/' def convert(filename): print 'Converting: ',filename text='#version=%s\n' %wx.VERSION_STRING f = open(userpreferencesdirectory +filename, 'rb') line = f.readline() if line.find("version")>0: print '------> allready converted!' f.close() return while len(line) > 0: p0 = line.find("") p1 = line.find("") if p0>=0 and p1>p0: s0=line[:p0+len("")] s1=line[p1:] key=line[p0+len(""):p1] if len(key): #a=int(key) if Dict1.has_key(key): a=Dict1[key] key=Dict2[a] text+=s0+key+s1 else: text+=line line = f.readline() f.close() f = open(userpreferencesdirectory +filename, 'w') f.write(text) f.close() print 'ok' def save_key_codes(fname): print 'saving ',fname fragment = "WXK_" f=open (fname,'w') for elem in dir(wx): if elem.isupper() and fragment in elem: #print elem,eval('wx.'+elem) f.write( '%s\t%s\n' %(elem,eval('wx.'+elem))) f.close() #--------------------------------- if os.path.exists(fname1)==False: #first run wxversion.select("2.6") import wx save_key_codes(fname1) print "please run this script again..." else: #second run wxversion.select("2.8") import wx save_key_codes(fname2) #Creating dicts: f1 = open(fname1, 'r') for line in f1: s=line.strip().split('\t') Dict1[s[1]]=s[0] #Value:Name f1.close() f2 = open(fname2, 'r') for line in f2: s=line.strip().split('\t') Dict2[s[0]]=s[1] #Name:Value f2.close() #And finally, converting shortcuts files for file in drFiles: print "Process %s? (y/n)" %file, s=raw_input() if s=='y': convert(file) drpython-3.11.1/tools/dr.bat0000644000175000017500000000002511150445515016505 0ustar dktrkranzdktrkranzpython ..\drpython.pydrpython-3.11.1/tools/pyc.bat0000644000175000017500000001232211150445515016676 0ustar dktrkranzdktrkranzcd .. call c:\Python24\Scripts\pychecker.bat drAboutDialog.py > tools\pycoutput\drAboutDialog.pyt call c:\Python24\Scripts\pychecker.bat drBookmarksDialog.py > tools\pycoutput\drBookmarksDialog.pyt call c:\Python24\Scripts\pychecker.bat drBookmarksMenu.py > tools\pycoutput\drBookmarksMenu.pyt call c:\Python24\Scripts\pychecker.bat drDragAndDrop.py > tools\pycoutput\drDragAndDrop.pyt call c:\Python24\Scripts\pychecker.bat drDynamicDrScriptDialog.py > tools\pycoutput\drDynamicDrScriptDialog.pyt call c:\Python24\Scripts\pychecker.bat drEncoding.py > tools\pycoutput\drEncoding.pyt call c:\Python24\Scripts\pychecker.bat drFileDialog.py > tools\pycoutput\drFileDialog.pyt call c:\Python24\Scripts\pychecker.bat drFileDialogPrefs.py > tools\pycoutput\drFileDialogPrefs.pyt call c:\Python24\Scripts\pychecker.bat drFindReplaceDialog.py > tools\pycoutput\drFindReplaceDialog.pyt call c:\Python24\Scripts\pychecker.bat drGetBlockInfo.py > tools\pycoutput\drGetBlockInfo.pyt call c:\Python24\Scripts\pychecker.bat drGetKeyDialog.py > tools\pycoutput\drGetKeyDialog.pyt call c:\Python24\Scripts\pychecker.bat drKeywords.py > tools\pycoutput\drKeywords.pyt call c:\Python24\Scripts\pychecker.bat drMenu.py > tools\pycoutput\drMenu.pyt rem call c:\Python24\Scripts\pychecker.bat drModeDialog.py > tools\pycoutput\drModeDialog.pyt call c:\Python24\Scripts\pychecker.bat drOpenImportedModuleDialog.py > tools\pycoutput\drOpenImportedModuleDialog.pyt call c:\Python24\Scripts\pychecker.bat drPDB.py > tools\pycoutput\drPDB.pyt call c:\Python24\Scripts\pychecker.bat drPluginDialog.py > tools\pycoutput\drPluginDialog.pyt call c:\Python24\Scripts\pychecker.bat drPluginMenu.py > tools\pycoutput\drPluginMenu.pyt call c:\Python24\Scripts\pychecker.bat drPopUp.py > tools\pycoutput\drPopUp.pyt call c:\Python24\Scripts\pychecker.bat drPopUpMenuDialog.py > tools\pycoutput\drPopUpMenuDialog.pyt call c:\Python24\Scripts\pychecker.bat drPreferences.py > tools\pycoutput\drPreferences.pyt call c:\Python24\Scripts\pychecker.bat drPrefsDialog.py > tools\pycoutput\drPrefsDialog.pyt call c:\Python24\Scripts\pychecker.bat drPrefsFile.py > tools\pycoutput\drPrefsFile.pyt call c:\Python24\Scripts\pychecker.bat drPrinter.py > tools\pycoutput\drPrinter.pyt call c:\Python24\Scripts\pychecker.bat drPrompt.py > tools\pycoutput\drPrompt.pyt call c:\Python24\Scripts\pychecker.bat drProperty.py > tools\pycoutput\drProperty.pyt call c:\Python24\Scripts\pychecker.bat drRegularExpressionDialog.py > tools\pycoutput\drRegularExpressionDialog.pyt call c:\Python24\Scripts\pychecker.bat drSTC.py > tools\pycoutput\drSTC.pyt call c:\Python24\Scripts\pychecker.bat drScriptDialog.py > tools\pycoutput\drScriptDialog.pyt call c:\Python24\Scripts\pychecker.bat drScriptMenu.py > tools\pycoutput\drScriptMenu.pyt call c:\Python24\Scripts\pychecker.bat drScrolledMessageDialog.py > tools\pycoutput\drScrolledMessageDialog.pyt call c:\Python24\Scripts\pychecker.bat drSetupPreferences.py > tools\pycoutput\drSetupPreferences.pyt call c:\Python24\Scripts\pychecker.bat drShortcuts.py > tools\pycoutput\drShortcuts.pyt call c:\Python24\Scripts\pychecker.bat drShortcutsDialog.py > tools\pycoutput\drShortcutsDialog.pyt call c:\Python24\Scripts\pychecker.bat drShortcutsFile.py > tools\pycoutput\drShortcutsFile.pyt call c:\Python24\Scripts\pychecker.bat drSingleChoiceDialog.py > tools\pycoutput\drSingleChoiceDialog.pyt call c:\Python24\Scripts\pychecker.bat drSourceBrowser.py > tools\pycoutput\drSourceBrowser.pyt call c:\Python24\Scripts\pychecker.bat drSourceBrowserGoTo.py > tools\pycoutput\drSourceBrowserGoTo.pyt call c:\Python24\Scripts\pychecker.bat drStyleDialog.py > tools\pycoutput\drStyleDialog.pyt call c:\Python24\Scripts\pychecker.bat drTabNanny.py > tools\pycoutput\drTabNanny.pyt call c:\Python24\Scripts\pychecker.bat drText.py > tools\pycoutput\drText.pyt call c:\Python24\Scripts\pychecker.bat drToolBarDialog.py > tools\pycoutput\drToolBarDialog.pyt call c:\Python24\Scripts\pychecker.bat drToolBarFile.py > tools\pycoutput\drToolBarFile.pyt call c:\Python24\Scripts\pychecker.bat drTreeDialog.py > tools\pycoutput\drTreeDialog.pyt call c:\Python24\Scripts\pychecker.bat drZip.py > tools\pycoutput\drZip.pyt call c:\Python24\Scripts\pychecker.bat drpython.py > tools\pycoutput\drpython.pyt call c:\Python24\Scripts\pychecker.bat drpython.pyw > tools\pycoutput\drpython.pyw.pyt call c:\Python24\Scripts\pychecker.bat lnkDecoderRing.py > tools\pycoutput\lnkDecoderRing.pyt call c:\Python24\Scripts\pychecker.bat postinst.py > tools\pycoutput\postinst.pyt rem call c:\Python24\Scripts\pychecker.bat setup.py > tools\pycoutput\setup.pyt cd tools drpython-3.11.1/tools/evaluate_pycheckeroutput.py0000644000175000017500000000102411150445515023106 0ustar dktrkranzdktrkranz import os os.chdir('pycoutput') for i in os.listdir('.'): if i.endswith('.pyt'): f = open (i, 'r') for l in f: if l.find('\\wx\\') == -1: if l.find('Parameter (') > -1: if l.find('(event)') > -1: pass else: print l if l.find('No global') > -1: print l f.close() #put to list and call unique #then output the list os.chdir('..') drpython-3.11.1/tools/dr26.bat0000644000175000017500000000003211150445515016653 0ustar dktrkranzdktrkranzpython ..\drpython_wx26.pydrpython-3.11.1/tools/drprefs.bat0000644000175000017500000000010611150445515017545 0ustar dktrkranzdktrkranzpython.exe ..\drpython.py --preferencesbasepath=c:/drpython/drpython28drpython-3.11.1/tools/key_codes.xls0000644000175000017500000006400011150445515020110 0ustar dktrkranzdktrkranzÐÏࡱá>þÿ 2þÿÿÿþÿÿÿ1ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ©ÍÁÀá°Áâ\pSteinhaFBarbosa B°aÀ=œ¯¼=hÌBp58X@"·Ú1´ÿ7Arial1´ÿ7Arial1´ÿ7Arial1´ÿ7Arial1´ÿ¼7Arial3#,##0\ "¬ ";\-#,##0\ "¬ "=#,##0\ "¬ ";[Red]\-#,##0\ "¬ "?#,##0.00\ "¬ ";\-#,##0.00\ "¬ "I"#,##0.00\ "¬ ";[Red]\-#,##0.00\ "¬ "q*6_-* #,##0\ "¬ "_-;\-* #,##0\ "¬ "_-;_-* "-"\ "¬ "_-;_-@_-k)3_-* #,##0\ _¬ _-;\-* #,##0\ _¬ _-;_-* "-"\ _¬ _-;_-@_-,>_-* #,##0.00\ "¬ "_-;\-* #,##0.00\ "¬ "_-;_-* "-"??\ "¬ "_-;_-@_-{+;_-* #,##0.00\ _¬ _-;\-* #,##0.00\ _¬ _-;_-* "-"??\ _¬ _-;_-@_-àõÿ À àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ à À à+õÿ øÀ à)õÿ øÀ à,õÿ øÀ à*õÿ øÀ à õÿ øÀ à À “€ÿ“€ÿ“€ÿ“€ÿ“€ÿ“€ÿ`…ÒSheet1Œ_ÁÁ"¾ü%ƒƒWXK_ADDWXK_ALTWXK_BACK WXK_CANCEL WXK_CAPITAL WXK_CLEAR WXK_COMMAND WXK_CONTROL WXK_DECIMAL WXK_DELETE WXK_DIVIDEWXK_DOWNWXK_END WXK_ESCAPE WXK_EXECUTEWXK_F1WXK_F10WXK_F11WXK_F12WXK_F13WXK_F14WXK_F15WXK_F16WXK_F17WXK_F18WXK_F19WXK_F2WXK_F20WXK_F21WXK_F22WXK_F23WXK_F24WXK_F3WXK_F4WXK_F5WXK_F6WXK_F7WXK_F8WXK_F9WXK_HELPWXK_HOME WXK_INSERT WXK_LBUTTONWXK_LEFT WXK_MBUTTONWXK_MENU WXK_MULTIPLYWXK_NEXT WXK_NUMLOCK WXK_NUMPAD0 WXK_NUMPAD1 WXK_NUMPAD2 WXK_NUMPAD3 WXK_NUMPAD4 WXK_NUMPAD5 WXK_NUMPAD6 WXK_NUMPAD7 WXK_NUMPAD8 WXK_NUMPAD9WXK_NUMPAD_ADDWXK_NUMPAD_BEGINWXK_NUMPAD_DECIMALWXK_NUMPAD_DELETEWXK_NUMPAD_DIVIDEWXK_NUMPAD_DOWNWXK_NUMPAD_ENDWXK_NUMPAD_ENTERWXK_NUMPAD_EQUAL WXK_NUMPAD_F1 WXK_NUMPAD_F2 WXK_NUMPAD_F3 WXK_NUMPAD_F4WXK_NUMPAD_HOMEWXK_NUMPAD_INSERTWXK_NUMPAD_LEFTWXK_NUMPAD_MULTIPLYWXK_NUMPAD_NEXTWXK_NUMPAD_PAGEDOWNWXK_NUMPAD_PAGEUPWXK_NUMPAD_PRIORWXK_NUMPAD_RIGHTWXK_NUMPAD_SEPARATORWXK_NUMPAD_SPACEWXK_NUMPAD_SUBTRACTWXK_NUMPAD_TAB WXK_NUMPAD_UP WXK_PAGEDOWN WXK_PAGEUP WXK_PAUSE WXK_PRINT WXK_PRIOR WXK_RBUTTON WXK_RETURN WXK_RIGHT WXK_SCROLL WXK_SELECT WXK_SEPARATOR WXK_SHIFT WXK_SNAPSHOT WXK_SPACE WXK_SPECIAL1 WXK_SPECIAL10 WXK_SPECIAL11 WXK_SPECIAL12 WXK_SPECIAL13 WXK_SPECIAL14 WXK_SPECIAL15 WXK_SPECIAL16 WXK_SPECIAL17 WXK_SPECIAL18 WXK_SPECIAL19 WXK_SPECIAL2 WXK_SPECIAL20 WXK_SPECIAL3 WXK_SPECIAL4 WXK_SPECIAL5 WXK_SPECIAL6 WXK_SPECIAL7 WXK_SPECIAL8 WXK_SPECIAL9 WXK_START WXK_SUBTRACTWXK_TABWXK_UPWXK_WINDOWS_LEFTWXK_WINDOWS_MENUWXK_WINDOWS_RIGHTkey_namewx2.6wx2.8difÿŠ  lnÍÏln¶¸ Š Œ ž  ; =Ë Í0 2¦ ¨% 'ž  cc: ©ÍÁÀ  €@l”)Õ4ý?  dü©ñÒMbP?_*+‚€%ðÁƒ„M¢QMS 1060 Print SystemÜÄSï ê odXXLetterPRIVâ0''''Ä\KhC>K_ÿ¡" dXXà?à?U} m} I€ð€ðððððððð ð ð ð ð ðððððððððððððððððððý ý €ý ý ‚ý ½u@ðt@!@ ›ý DÀDÀý ½0s@0s@þ¼A@ LþÀLÿÀý ½ @ @ÿý ½ðr@ðr@ÿý ½ps@ps@ÿý ½s@s@ÿý ½y@Àx@@ÿý ½@s@@s@ ÿý ½ @u@ u@ @ ÿý  ½ À_@À_@  ÿý  ½ Pu@0u@ @ ÿý  ½ ðs@Ðs@ @ ÿý  ½  s@€s@ @ÿý  ½;@;@ÿý ½ t@t@@ÿý ½`u@@u@@ÿý ½ðu@Ðu@@ÿý ½v@àu@@ÿý ½v@ðu@@ÿý ½ v@v@@ÿý ½0v@v@@ÿý ½@v@ v@@ÿý ½Pv@0v@@ÿý ½`v@@v@@ÿý ½pv@Pv@@ÿý ½€v@`v@@ÿý ½pu@Pu@@ÿý ½v@pv@@ÿý ½ v@€v@@ÿý ½°v@v@@ÿý ½Àv@ v@@ ÿ×Dô l8I\CCCCCCCCCCCCCCCCCCCCCCCCCCCC ð!ð"ð#ð$ð%ð&ð'ð(ð)ð*ð+ð,ð-ð.ð/ð0ð1ð2ð3ð4ð5ð6ð7ð8ð9ð:ð;ð<ð=ð>ð?ðý ½ Ðv@°v@ @!ÿý ! ½!€u@`u@!@"ÿý "!½"u@pu@"@#ÿý #"½# u@€u@#@$ÿý $#½$°u@u@$@%ÿý %$½%Àu@ u@%@&ÿý &%½&Ðu@°u@&@'ÿý '&½'àu@Àu@'@(ÿý ('½(Pt@0t@(@)ÿý )(½)°s@s@)@*ÿý *)½*@t@ t@*@+ÿý +*½+Ðr@Ðr@+,ÿý ,+½,Às@ s@,@-ÿý -,½-s@s@-.ÿý .-½.Ps@Ps@./ÿý /.½/u@àt@/@0ÿý 0/½0s@ðv@0KÀ1ÿý 10½1àv@Àv@1@2ÿý 21½2`t@@t@2@3ÿý 32½3pt@Pt@3@4ÿý 43½4€t@`t@4@5ÿý 54½5t@pt@5@6ÿý 65½6 t@€t@6@7ÿý 76½7°t@t@7@8ÿý 87½8Àt@ t@8@9ÿý 98½9Ðt@°t@9@:ÿý :9½:àt@Àt@:@;ÿý ;:½;ðt@Ðt@;@<ÿý <;½<€x@@x@<@=ÿý =<½=0x@ðw@=@>ÿý >=½>°x@px@>@?ÿý ?>½?Px@x@?@@ÿ×Dà lCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC@ðAðBðCðDðEðFðGðHðIðJðKðLðMðNðOðPðQðRðSðTðUðVðWðXðYðZð[ð\ð]ð^ð_ðý @?½@Àx@€x@@@Aÿý A@½AÐw@°w@A@Bÿý BA½B x@àw@B@CÿB¼B> LþÀLÿÀý CB½C@w@ w@C@DÿBý DC½D`x@ x@D@EÿBý ED½EPw@0w@E@FÿBý FE½F`w@@w@F@GÿBý GF½Gpw@Pw@G@HÿBý HG½H€w@`w@H@IÿBý IH½Iw@pw@I@JÿBý JI½J@x@x@J@KÿBý KJ½K w@€w@K@LÿBý LK½Lpx@0x@L@MÿBý ML½Mx@Ðw@M@NÿBý NM½Nx@Ðw@N@OÿBý ON½Oðw@Àw@O@PÿBý PO½Pàw@Àw@P@QÿBý QP½QÀw@ w@Q@RÿBý RQ½Rx@Px@R@SÿBý SR½S w@w@S@TÿBý TS½T x@`x@T@UÿBý UT½U0w@w@U@VÿBý VU½V°w@w@V@WÿBý WV½Ww@ðv@W@XÿBý XW½Xw@àv@X@YÿBý YX½Y`s@`s@YZÿBý ZY½Zt@ðs@Z@[ÿBý [Z½[€s@àv@[KÀ\ÿBý \[½\àr@àr@\]ÿBý ]\½]*@*@]^ÿBý ^]½^às@Às@^@_ÿBý _^½_ðv@Ðv@_@`ÿB×Dù lCC\CCCCCCCCCCCCCCCCCCCCCCCCCCCC`ðaðbðcðdðeðfðgðhðiðjðkðlðmðnðoðpðqðrðsðtðuðvðwðxðyðzð{ð|ð}ð~ððý `_½`t@às@`@aÿBý a`½a u@u@a@bÿBý ba½b s@ s@bcÿBý cb½c0t@t@c@dÿBý dc½d@@@@deÿBý ed½e h@ h@efÿBý fe½f@i@@i@fgÿBý gf½g`i@`i@ghÿBý hg½h€i@€i@hiÿBý ih½i i@ i@ijÿBý ji½jÀi@Ài@jkÿBý kj½kài@ài@klÿBý lk½lj@j@lmÿBý ml½m j@ j@mnÿBý nm½n@j@@j@noÿBý on½o`j@`j@opÿBý po½p@h@@h@pqÿBý qp½q€j@€j@qrÿBý rq½r`h@`h@rsÿBý sr½s€h@€h@stÿBý ts½t h@ h@tuÿBý ut½uÀh@Àh@uvÿBý vu½vàh@àh@vwÿBý wv½wi@i@wxÿBý xw½x i@ i@xyÿBý yx½yÀr@Àr@yzÿBý zy½z0u@u@z@{ÿBý {z½{"@"@{|ÿBý |{½|Ðs@°s@|@}ÿBý }|½}Ðx@x@}@~ÿBý ~}½~ðx@°x@~@ÿBý ~½àx@ x@@ÿB×Dà lCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC>¶@  ï7 þÿà…ŸòùOh«‘+'³Ù0°@H`x œ¨äAntonio BarbosaAntonio BarbosaMicrosoft Excel@l[ìÚ*Ç@€5ÊöÛ*ÇþÿÕÍÕœ.“—+,ù®0Ä PXd lt|„ Œ ŸäGN« Sheet1  Worksheets  þÿÿÿ"#$%&'(þÿÿÿ*+,-./0þÿÿÿýÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRoot Entryÿÿÿÿÿÿÿÿ ÀF@/+ÇþÿÿÿWorkbookÿÿÿÿÿÿÿÿÿÿÿÿ|@SummaryInformation(ÿÿÿÿ!DocumentSummaryInformation8ÿÿÿÿÿÿÿÿÿÿÿÿ)drpython-3.11.1/drPrinter.py0000644000175000017500000000634211150445514016602 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Printing. Very simple. No colors. #Takes the font and size from the style given, and uses it to print with. import wx.html class DrPrinter(wx.html.HtmlEasyPrinting): def __init__(self, parent): wx.html.HtmlEasyPrinting.__init__(self) self.parent = parent def HTMLify(self, text, linenumbers): #Prep Special Characters text = text.replace('&', "&").replace('<', "<").replace('>', ">") #Line numbers: if linenumbers: text = "100000" + text.replace(' ', "  ") x = 0 l = len(text) line = 2 n = "" while x < l: if text[x] == '\n': n = n + "\n" + str(line) if line < 10: n = n + "00000" elif line < 100: n = n + "0000" elif line < 1000: n = n + "000" else: n = n + "00" line = line + 1 else: n = n + text[x] x = x + 1 text = n #htmlify the text: thehtml = "" \ + text.replace('\n', "\n
") \ + "" #TabWidth twstring = "".zfill(self.parent.prefs.printtabwidth) twstring = "" + twstring + "" thehtml = thehtml.replace('\t', twstring) return thehtml def Print(self, text, filename, linenumbers = 1): self.SetHeader(filename) self.PrintText(self.HTMLify(text, linenumbers), filename) def PrinterSetup(self, parent): data = wx.PrintDialogData() data.EnableSelection(True) data.EnablePrintToFile(True) data.EnablePageNumbers(True) data.SetMinPage(1) data.SetMaxPage(5) data.SetAllPages(True) dlg = wx.PrintDialog(parent, data) if dlg.ShowModal() == wx.ID_OK: data = dlg.GetPrintDialogData() #self.log.WriteText('GetAllPages: %d\n' % data.GetAllPages()) dlg.Destroy() drpython-3.11.1/drPreferences.py0000644000175000017500000006771611150445515017435 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Preferences #LongLineCol from Chris McDonough #Changed name from longlinecol to doclonglinecol #The idea for using a dictionary for reading/writing preferences #ame from submitted code by limodou that was never incorporated #into DrPython. (It used an array of preferences, #and called modified versions of drPrefsFile functions using #setattr and getattr to read and write preferences). import os.path, re import wx rekey = re.compile('(?<=\[).*(?=\])') def _getkey(target): return int(rekey.search(target).group()) def _stringify(x): return (x, '') def GetPreferencesDictionary(): #Each item in the Dictionary: #(Key, Array) #Each item in the Array: #(Preference, Preferences File String, Function) #Function: 0: (GetPref, Not an Integer,), 1: (GetPref, Integer), 2: (ExtractPref, Not an Integer). return {'General': [('rememberwindowsizeandposition', 'remember.window.size.and.position', 1), ('rememberdialogsizesandpositions', 'remember.dialog.sizes.and.positions', 1), ('rememberpanelsizes', 'remember.panel.sizes', 1), ('autodetectencoding', 'auto.detect.encoding', 1), ('defaultencoding', 'default.encoding', 2), ('saveonrun', 'save.on.run', 1), ('checksyntaxonsave', 'check.syntax.on.save', 1), ('checksyntaxextensions', 'check.syntax.extensions', 0), ('promptonsaveall', 'prompt.on.save.all', 1), ('doubleclicktoclosetab', 'double.click.to.close.tab', 1), ('iconsize', 'icon.size', 1), ('recentfileslimit', 'max.recent.files', 1), ('vieweol', 'view.eol', 1), ('checkeol', 'check.line.ending.type', 1), ('checkindentation', 'check.indentation.type', 1), ('pythonargs', 'python.arguments', 2), ('defaultdirectory', 'default.directory', 2), ('enablefeedback', 'enable.feedback', 1), ('debugmodus', 'debug.modus', 1), ('alwayspromptonexit', 'always.prompt.on.exit', 1), ('backupfileonsave', 'backup.file.on.save', 1)], 'File Types': [('extensions[0]', 'filetypes.extensions.python', 0), ('extensions[1]', 'filetypes.extensions.cpp', 0), ('extensions[2]', 'filetypes.extensions.html', 0), ('extensions[3]', 'filetypes.extensions.text', 0), ('docfolding[0]', 'filetypes.docfolding.python', 1), ('docfolding[1]', 'filetypes.docfolding.cpp', 1), ('docfolding[2]', 'filetypes.docfolding.html', 1), ('docfolding[3]', 'filetypes.docfolding.text', 1), ('doctabwidth[0]', 'filetypes.doctabwidth.python', 1), ('doctabwidth[1]', 'filetypes.doctabwidth.cpp', 1), ('doctabwidth[2]', 'filetypes.doctabwidth.html', 1), ('doctabwidth[3]', 'filetypes.doctabwidth.text', 1), ('docusetabs[0]', 'filetypes.docusetabs.python', 1), ('docusetabs[1]', 'filetypes.docusetabs.cpp', 1), ('docusetabs[2]', 'filetypes.docusetabs.html', 1), ('docusetabs[3]', 'filetypes.docusetabs.text', 1), ('docuseintellibackspace[0]', 'filetypes.docuseintellibackspace.python', 1), ('docuseintellibackspace[1]', 'filetypes.docuseintellibackspace.cpp', 1), ('docuseintellibackspace[2]', 'filetypes.docuseintellibackspace.html', 1), ('docuseintellibackspace[3]', 'filetypes.docuseintellibackspace.text', 1), ('docremovetrailingwhitespace[0]', 'filetypes.docremovetrailingwhitespace.python', 1), ('docremovetrailingwhitespace[1]', 'filetypes.docremovetrailingwhitespace.cpp', 1), ('docremovetrailingwhitespace[2]', 'filetypes.docremovetrailingwhitespace.html', 1), ('docremovetrailingwhitespace[3]', 'filetypes.docremovetrailingwhitespace.text', 1), ('doceolmode[0]', 'filetypes.doceolmode.python', 1), ('doceolmode[1]', 'filetypes.doceolmode.cpp', 1), ('doceolmode[2]', 'filetypes.doceolmode.html', 1), ('doceolmode[3]', 'filetypes.doceolmode.text', 1), ('doccommentstring[0]', 'filetypes.doccommentstring.python', 0), ('doccommentstring[1]', 'filetypes.doccommentstring.cpp', 0), ('doccommentstring[2]', 'filetypes.doccommentstring.html', 0), ('doccommentstring[3]', 'filetypes.doccommentstring.text', 0), ('docwordwrap[0]', 'filetypes.docwordwrap.python', 1), ('docwordwrap[1]', 'filetypes.docwordwrap.cpp', 1), ('docwordwrap[2]', 'filetypes.docwordwrap.html', 1), ('docwordwrap[3]', 'filetypes.docwordwrap.text', 1)], 'File Dialog': [('constantwildcard', 'constant.wildcard', 0), ('wildcard', 'wildcard', 0), ('windowsshortcutreplacetable', 'windows.shortcut.replace.table', 0), ('defaultextension', 'default.extension', 1), ('usewxfiledialog', 'use.wx.filedialog', 1)], 'Drag and Drop': [('draganddropmode', 'drag.and.drop.mode', 1), ('draganddroptextmode', 'drag.and.drop.text.mode', 1)], 'Document': [('docshowlinenumbers', 'doc.show.line.numbers', 1), ('docautoindent', 'doc.autoindent', 1), ('docautoreload', 'doc.autoreload', 1), ('docupdateindentation', 'doc.update.indentation', 1), ('docparenthesismatching', 'doc.parenthesis.matching', 1), ('docusefileindentation', 'doc.use.file.indentation', 1), ('docwhitespaceisvisible', 'doc.whitespace.is.visible.on.startup', 1), ('dochighlightcurrentline', 'doc.highlight.current.line', 1), ('docignorectrlpageupdown', 'doc.ignore.ctrlpageupdown', 1), ('doccaretwidth', 'doc.caret.width', 1), ('doccommentmode', 'doc.comment.mode', 1), ('docusestyles', 'doc.use.styles', 1), ('docuseindentationguides', 'doc.use.indentation.guides', 1), ('doclonglinecol', 'doc.long.line.col', 1), ('docscrollextrapage', 'doc.scroll.extra.page', 1), ('docdefaultsyntaxhighlighting', 'doc.default.syntax.highlighting', 1), ('doconlyusedefaultsyntaxhighlighting', 'doc.only.use.default.syntax.highlighting', 1), ('PythonStyleDictionary[0]', 'doc.style.normal', 0), ('PythonStyleDictionary[1]', 'doc.style.linenumber', 0), ('PythonStyleDictionary[2]', 'doc.style.brace.match', 0), ('PythonStyleDictionary[3]', 'doc.style.brace.nomatch', 0), ('PythonStyleDictionary[4]', 'doc.style.character', 0), ('PythonStyleDictionary[5]', 'doc.style.class', 0), ('PythonStyleDictionary[6]', 'doc.style.comment', 0), ('PythonStyleDictionary[7]', 'doc.style.comment.block', 0), ('PythonStyleDictionary[8]', 'doc.style.definition', 0), ('PythonStyleDictionary[9]', 'doc.style.keyword', 0), ('PythonStyleDictionary[10]', 'doc.style.number', 0), ('PythonStyleDictionary[11]', 'doc.style.operator', 0), ('PythonStyleDictionary[12]', 'doc.style.string', 0), ('PythonStyleDictionary[13]', 'doc.style.string.eol', 0), ('PythonStyleDictionary[14]', 'doc.style.triple.string', 0), ('PythonStyleDictionary[15]', 'doc.style.caret', 0), ('PythonStyleDictionary[16]', 'doc.style.selection', 0), ('PythonStyleDictionary[17]', 'doc.style.folding', 0), ('PythonStyleDictionary[18]', 'doc.style.longlinecol', 0), ('PythonStyleDictionary[19]', 'doc.style.current.line', 0), ('PythonStyleDictionary[20]', 'doc.style.indentation.guide', 0), ('CPPStyleDictionary[0]', 'doc.cstyle.normal', 0), ('CPPStyleDictionary[1]', 'doc.cstyle.linenumber', 0), ('CPPStyleDictionary[2]', 'doc.cstyle.brace.match', 0), ('CPPStyleDictionary[3]', 'doc.cstyle.brace.nomatch', 0), ('CPPStyleDictionary[4]', 'doc.cstyle.character', 0), ('CPPStyleDictionary[5]', 'doc.cstyle.preprocessor', 0), ('CPPStyleDictionary[6]', 'doc.cstyle.comment', 0), ('CPPStyleDictionary[7]', 'doc.cstyle.verbatim', 0), ('CPPStyleDictionary[8]', 'doc.cstyle.keyword', 0), ('CPPStyleDictionary[9]', 'doc.cstyle.c.identifier', 0), ('CPPStyleDictionary[10]', 'doc.cstyle.number', 0), ('CPPStyleDictionary[11]', 'doc.cstyle.operator', 0), ('CPPStyleDictionary[12]', 'doc.cstyle.string', 0), ('CPPStyleDictionary[13]', 'doc.cstyle.string.eol', 0), ('CPPStyleDictionary[14]', 'doc.cstyle.globalclass', 0), ('CPPStyleDictionary[15]', 'doc.cstyle.regex', 0), ('CPPStyleDictionary[16]', 'doc.cstyle.uuid', 0), ('CPPStyleDictionary[17]', 'doc.cstyle.caret', 0), ('CPPStyleDictionary[18]', 'doc.cstyle.selection', 0), ('CPPStyleDictionary[19]', 'doc.cstyle.folding', 0), ('CPPStyleDictionary[20]', 'doc.cstyle.longlinecol', 0), ('CPPStyleDictionary[21]', 'doc.cstyle.current.line', 0), ('HTMLStyleDictionary[0]', 'doc.htmlstyle.normal', 0), ('HTMLStyleDictionary[1]', 'doc.htmlstyle.linenumber', 0), ('HTMLStyleDictionary[2]', 'doc.htmlstyle.brace.match', 0), ('HTMLStyleDictionary[3]', 'doc.htmlstyle.brace.nomatch', 0), ('HTMLStyleDictionary[4]', 'doc.htmlstyle.tag', 0), ('HTMLStyleDictionary[5]', 'doc.htmlstyle.unknown.tag', 0), ('HTMLStyleDictionary[6]', 'doc.htmlstyle.attribute', 0), ('HTMLStyleDictionary[7]', 'doc.htmlstyle.unknown.attribute', 0), ('HTMLStyleDictionary[8]', 'doc.htmlstyle.number', 0), ('HTMLStyleDictionary[9]', 'doc.htmlstyle.string', 0), ('HTMLStyleDictionary[10]', 'doc.htmlstyle.character', 0), ('HTMLStyleDictionary[11]', 'doc.htmlstyle.comment', 0), ('HTMLStyleDictionary[12]', 'doc.htmlstyle.entity', 0), ('HTMLStyleDictionary[13]', 'doc.htmlstyle.tag.end', 0), ('HTMLStyleDictionary[14]', 'doc.htmlstyle.xml.start', 0), ('HTMLStyleDictionary[15]', 'doc.htmlstyle.xml.end', 0), ('HTMLStyleDictionary[16]', 'doc.htmlstyle.script', 0), ('HTMLStyleDictionary[17]', 'doc.htmlstyle.value', 0), ('HTMLStyleDictionary[18]', 'doc.htmlstyle.caret', 0), ('HTMLStyleDictionary[19]', 'doc.htmlstyle.selection', 0), ('HTMLStyleDictionary[20]', 'doc.htmlstyle.folding', 0), ('HTMLStyleDictionary[21]', 'doc.htmlstyle.longlinecol', 0), ('HTMLStyleDictionary[22]', 'doc.htmlstyle.current.line', 0)], 'Prompt': [('promptisvisible', 'prompt.is.visible.on.startup', 1), ('promptmarginwidth', 'prompt.margin.width', 1), ('promptsize', 'prompt.size', 1), ('prompttabwidth', 'prompt.tabwidth', 1), ('prompteolmode', 'prompt.eolmode', 1), ('promptusetabs', 'prompt.use.tabs', 1), ('promptwordwrap', 'prompt.wordwrap', 1), ('promptwhitespaceisvisible', 'prompt.whitespace.is.visible.on.startup', 1), ('promptcaretwidth', 'prompt.caret.width', 1), ('promptusestyles', 'prompt.use.styles', 1), ('promptscrollextrapage', 'prompt.scroll.extra.page', 1), ('promptstartupscript', 'prompt.startup.script', 0), ('txtPromptStyleDictionary[0]', 'prompt.style.normal', 0), ('txtPromptStyleDictionary[1]', 'prompt.style.linenumber', 0), ('txtPromptStyleDictionary[2]', 'prompt.style.brace.match', 0), ('txtPromptStyleDictionary[3]', 'prompt.style.brace.nomatch', 0), ('txtPromptStyleDictionary[4]', 'prompt.style.character', 0), ('txtPromptStyleDictionary[5]', 'prompt.style.class', 0), ('txtPromptStyleDictionary[6]', 'prompt.style.comment', 0), ('txtPromptStyleDictionary[7]', 'prompt.style.comment.block', 0), ('txtPromptStyleDictionary[8]', 'prompt.style.definition', 0), ('txtPromptStyleDictionary[9]', 'prompt.style.keyword', 0), ('txtPromptStyleDictionary[10]', 'prompt.style.number', 0), ('txtPromptStyleDictionary[11]', 'prompt.style.operator', 0), ('txtPromptStyleDictionary[12]', 'prompt.style.string', 0), ('txtPromptStyleDictionary[13]', 'prompt.style.string.eol', 0), ('txtPromptStyleDictionary[14]', 'prompt.style.triple.string', 0), ('txtPromptStyleDictionary[15]', 'prompt.style.caret', 0), ('txtPromptStyleDictionary[16]', 'prompt.style.selection', 0)], 'Side Panels': [('sidepanelleftsize', 'side.panel.left.size', 1), ('sidepanelrightsize', 'side.panel.right.size', 1), ('sidepaneltopsize', 'side.panel.top.size', 1)], 'Find/Replace': [('findreplaceregularexpression', 'find.replace.regular.expression', 1), ('findreplacematchcase', 'find.replace.match.case', 1), ('findreplacefindbackwards', 'find.replace.find.backwards', 1), ('findreplacewholeword', 'find.replace.whole.word', 1), ('findreplaceinselection', 'find.replace.in.selection', 1), ('findreplacefromcursor', 'find.replace.from.cursor', 1), ('findreplacepromptonreplace', 'find.replace.prompt.on.replace', 1), ('findreplaceautowrap', 'find.replace.auto.wrap', 1), ('findreplaceundercursor', 'find.replace.prompt.under.cursor', 1)], 'Source Browser': [('sourcebrowserpanel', 'sourcebrowser.panel', 1), ('sourcebrowsersize', 'sourcebrowser.size', 1), ('sourcebrowserisvisible', 'sourcebrowser.is.visible', 1), ('sourcebrowsercloseonactivate', 'sourcebrowser.close.on.activate', 1), ('sourcebrowserissorted', 'sourcebrowser.is.sorted', 1), ('sourcebrowserautorefreshonsave', 'sourcebrowser.auto.refresh.on.save', 1), ('sourcebrowserautorefresh', 'sourcebrowser.auto.refresh', 1), ('sourcebrowseruseimages', 'sourcebrowser.use.images', 1), ('sourcebrowserstyle', 'sourcebrowser.style', 0)], 'Bookmarks': [('bookmarksstyle', 'bookmarks.style', 0)], 'Plugins': [('pluginsdirectory', 'plugins.directory', 2)], 'DrScript': [('drscriptsdirectory', 'drscripts.directory', 2), ('drscriptstyle', 'drscript.style', 0), ('drscriptloadexamples', 'drscript.load.examples', 1)], 'Printing': [('printdoclinenumbers', 'print.doc.linenumbers', 1), ('printpromptlinenumbers', 'print.prompt.linenumbers', 1), ('printtabwidth', 'print.tab.width', 1)], 'Documentation': [('documentationbrowser', 'documentation.browser', 0), ('documentationpythonlocation', 'documentation.python.location', 0), ('documentationwxwidgetslocation', 'documentation.wx.widgets.location', 0), ('documentationrehowtolocation', 'documentation.rehowto.location', 0)]} class drPreferences: def __init__(self, platform_is_windows, programdirectory = ""): self.platform_is_windows = platform_is_windows self.programdirectory = programdirectory #General Settings self.rememberwindowsizeandposition = 1 self.rememberdialogsizesandpositions = 1 self.rememberpanelsizes = 1 self.autodetectencoding = 1 self.defaultencoding = 'latin-1' self.saveonrun = 1 self.checksyntaxonsave = 1 self.checksyntaxextensions = '' self.promptonsaveall = 1 self.doubleclicktoclosetab = 0 self.iconsize = 16 self.recentfileslimit = 10 self.checkindentation = 0 self.vieweol = 1 self.checkeol = 1 self.pythonargs = "" self.defaultdirectory = programdirectory self.enablefeedback = 1 wx.GetApp().debugmodus = self.debugmodus = 1 self.alwayspromptonexit = 0 self.backupfileonsave = 1 self.save = 0 #File Dialog self.usewxfiledialog = 0 self.defaultextension = 1 self.constantwildcard = '*.lnk' #self.windowsshortcutreplacetable = 'C:,/mnt/win_c#' #@ = replace with lowercase match & = replace with exact match self.windowsshortcutreplacetable = '[A-Z],/mnt/win_@#' if self.platform_is_windows: self.wildcard = "Python Source (*.pyw *.py)|*.pyw;*.py|C/C++ Source (*.c *.cc *.cpp *.cxx *.h *.hh *.hpp *.hxx)|*.c;*.cc;*.cpp;*.cxx;*.h;*.hh;*.hpp;*.hxx|HTML Files (*.htm *.html *.shtm *.shtml *.xml)|*.htm;*.html;*.shtm;*.shtml;*.xml|Backup Files (*.bak)|*.bak|Plain Text (*.txt *.dat *.log)|*.txt;*.dat;*.log|All Files (*)|*" else: self.wildcard = "Python Source (*.py *.pyw)|*.py;*.pyw|C/C++ Source (*.c *.cc *.cpp *.cxx *.h *.hh *.hpp *.hxx)|*.c;*.cc;*.cpp;*.cxx;*.h;*.hh;*.hpp;*.hxx|HTML Files (*.htm *.html *.shtm *.shtml *.xml)|*.htm;*.html;*.shtm;*.shtml;*.xml|Backup Files (*.bak)|*.bak|Plain Text (*.txt *.dat *.log)|*.txt;*.dat;*.log|All Files (*)|*" #Drag and Drop self.draganddropmode = 2 self.draganddroptextmode = 0 #File Types self.extensions = {0: 'py,pyw', 1: 'c,cc,cpp,cxx,h,hh,hpp,hxx', 2: 'htm,shtm,html,shtml,xml', 3: 'txt,dat,log'} self.docfolding = {0: 1, 1: 0, 2: 0, 3: 0} self.doctabwidth = {0: 4, 1: 4, 2: 4, 3: 4} self.docusetabs = {0: 0, 1: 0, 2: 0, 3: 0} self.docuseintellibackspace = {0: 1, 1: 1, 2: 1, 3: 1} self.docremovetrailingwhitespace = {0: 0, 1: 0, 2: 0, 3: 0} self.doceolmode = {0: 0, 1: 0, 2: 0, 3: 0} self.doccommentstring = {0: '#', 1: '//', 2: '', 3: '#'} self.docwordwrap = {0: 0, 1: 0, 2: 0, 3: 0} #Document Settings self.docshowlinenumbers = 1 self.docautoindent = 2 self.docautoreload = 1 self.docupdateindentation = 0 self.docparenthesismatching = 1 self.docusefileindentation = 1 self.docwhitespaceisvisible = 0 self.dochighlightcurrentline = 1 self.docignorectrlpageupdown = 0 self.doccaretwidth = 1 self.doccommentmode = 0 self.docusestyles = 1 self.docuseindentationguides = 1 self.doclonglinecol = 0 self.docscrollextrapage = 0 self.docdefaultsyntaxhighlighting = 0 self.doconlyusedefaultsyntaxhighlighting = 0 self.PythonStyleDictionary = dict(map(_stringify, range(21))) self.CPPStyleDictionary = dict(map(_stringify, range(22))) self.HTMLStyleDictionary = dict(map(_stringify, range(23))) if self.platform_is_windows: defaultfont0="Courier" #monospaced defaultfont1="MS Sans Serif" #proportional else: defaultfont0="Courier 10 Pitch" #monospaced defaultfont1="Sans" #proportional #check if those fonts exists, else use system default FontList = wx.FontEnumerator().GetFacenames() defaultfont = wx.GetApp().GetTopWindow().GetFont().GetFaceName() if defaultfont0 not in FontList: defaultfont0=defaultfont if defaultfont1 not in FontList: defaultfont1=defaultfont self.PythonStyleDictionary[0] = "fore:#000000,back:#FFFFFF,size:10,face:%s" %defaultfont0 self.PythonStyleDictionary[1] = "fore:#000000,back:#82AEE3,size:10,face:%s" %defaultfont1 self.PythonStyleDictionary[2] = "fore:#FF6400,back:#98D3FF,size:10,face:%s" %defaultfont0 self.PythonStyleDictionary[3] = "fore:#FF0000,back:#FFFF00,size:10,face:%s" %defaultfont0 self.PythonStyleDictionary[4] = "fore:#007f08,back:#ffffff,size:10,face:%s" %defaultfont0 self.PythonStyleDictionary[5] = "fore:#b200ac,back:#ffffff,size:10,face:%s" %defaultfont0 self.PythonStyleDictionary[6] = "fore:#7F7F7F,back:#FFFFFF,size:10,face:%s" %defaultfont0 self.PythonStyleDictionary[7] = "fore:#0B5400,back:#BAE8D5,size:10,face:%s" %defaultfont0 self.PythonStyleDictionary[8] = "fore:#e80300,back:#ffffff,size:10,face:%s" %defaultfont0 self.PythonStyleDictionary[9] = "fore:#FF0000,back:#ffffff,size:10,face:%s" %defaultfont0 self.PythonStyleDictionary[10] = "fore:#0027c4,back:#ffffff,size:10,face:%s" %defaultfont0 self.PythonStyleDictionary[11] = "fore:#FF0071,back:#ffffff,size:10,face:%s" %defaultfont0 self.PythonStyleDictionary[12] = "fore:#007f08,back:#ffffff,size:10,face:%s" %defaultfont0 self.PythonStyleDictionary[13] = "fore:#007f08,back:#ffffff,size:10,face:%s" %defaultfont0 self.PythonStyleDictionary[14] = "fore:#7B8184,back:#FFFFFF,size:10,face:%s" %defaultfont0 self.PythonStyleDictionary[15] = "#000000" self.PythonStyleDictionary[16] = "fore:#000000,back:#FF7900" self.PythonStyleDictionary[17] = "fore:#000000,back:#82AEE3" self.PythonStyleDictionary[18] = "#82AEE3" self.PythonStyleDictionary[19] = "#98D3FF" self.PythonStyleDictionary[20] = "#AAAAAA" self.CPPStyleDictionary[0] = "fore:#000000,back:#FFFFFF,size:12,face:%s" %defaultfont0 self.CPPStyleDictionary[1] = "fore:#000000,back:#82AEE3,size:12,face:%s" %defaultfont0 self.CPPStyleDictionary[2] = "fore:#FF6400,back:#98D3FF,bold" self.CPPStyleDictionary[3] = "fore:#FF0000,back:#FFFF00,bold" self.CPPStyleDictionary[4] = "fore:#007f08,back:#ffffff" self.CPPStyleDictionary[5] = "fore:#228D63,back:#ffffff,bold" self.CPPStyleDictionary[6] = "fore:#2D3D9E,back:#DFDFEB,bold" self.CPPStyleDictionary[7] = "fore:#e80300,back:#ffffff" self.CPPStyleDictionary[8] = "fore:#000000,back:#ffffff,bold" self.CPPStyleDictionary[9] = "fore:#000000,back:#ffffff" self.CPPStyleDictionary[10] = "fore:#2050C6,back:#ffffff," self.CPPStyleDictionary[11] = "fore:#003D22,back:#ffffff" self.CPPStyleDictionary[12] = "fore:#008500,back:#FFFFFF" self.CPPStyleDictionary[13] = "fore:#008500,back:#FFFFFF" self.CPPStyleDictionary[14] = "fore:#000000,back:#FFFFFF" self.CPPStyleDictionary[15] = "fore:#338144,back:#5FFFFF,bold" self.CPPStyleDictionary[16] = "fore:#330044,back:#5FFFFF" self.CPPStyleDictionary[17] = "#000000" self.CPPStyleDictionary[18] = "fore:#000000,back:#FF7900" self.CPPStyleDictionary[19] = "fore:#000000,back:#82AEE3" self.CPPStyleDictionary[20] = "#82AEE3" self.CPPStyleDictionary[21] = "#98D3FF" self.HTMLStyleDictionary[0] = "fore:#000000,back:#FFFFFF,size:12,face:%s" %defaultfont0 self.HTMLStyleDictionary[1] = "fore:#000000,back:#82AEE3,size:12,face:%s" %defaultfont0 self.HTMLStyleDictionary[2] = "fore:#FF6400,back:#98D3FF,bold" self.HTMLStyleDictionary[3] = "fore:#FF0000,back:#FFFF00,bold" self.HTMLStyleDictionary[4] = "fore:#000000,back:#ffffff,bold" self.HTMLStyleDictionary[5] = "fore:#0000FF,back:#FFFFFF,bold" self.HTMLStyleDictionary[6] = "fore:#2D3D9E,back:#DFDFEB,bold" self.HTMLStyleDictionary[7] = "fore:#FF0000,back:#ffff00,bold" self.HTMLStyleDictionary[8] = "fore:#0000FF,back:#ffffff" self.HTMLStyleDictionary[9] = "fore:#003100,back:#ffffff" self.HTMLStyleDictionary[10] = "fore:#204D71,back:#ffffff,bold" self.HTMLStyleDictionary[11] = "fore:#2D3D9E,back:#DFDFEB,bold" self.HTMLStyleDictionary[12] = "fore:#7B8184,back:#FFFFFF,bold" self.HTMLStyleDictionary[13] = "fore:#000000,back:#FFF7C2,bold" self.HTMLStyleDictionary[14] = "fore:#000081,back:#FFE48D,bold" self.HTMLStyleDictionary[15] = "fore:#006E00,back:#FFE48D,bold" self.HTMLStyleDictionary[16] = "fore:#00812A,back:#CEF0FF,bold" self.HTMLStyleDictionary[17] = "fore:#000000,back:#C2FFE8,bold" self.HTMLStyleDictionary[18] = "#000000" self.HTMLStyleDictionary[19] = "fore:#000000,back:#FF7900" self.HTMLStyleDictionary[20] = "fore:#000000,back:#82AEE3" self.HTMLStyleDictionary[21] = "#82AEE3" self.HTMLStyleDictionary[22] = "#98D3FF" self.txtDocumentStyleDictionary = self.PythonStyleDictionary #Prompt Settings self.promptisvisible = 0 self.promptmarginwidth = 0 self.prompttabwidth = 4 self.promptsize = 50 self.prompteolmode = 0 self.promptusetabs = 1 self.promptwordwrap = 1 self.promptwhitespaceisvisible = 0 self.promptcaretwidth = 1 self.promptusestyles = 1 self.promptscrollextrapage = 0 self.promptstartupscript = 'import sys, os, wx' self.txtPromptStyleDictionary = dict(map(_stringify, range(17))) # lm - changing default prompt style for increased readability #normal self.txtPromptStyleDictionary[0] = "fore:#000000,back:#FFFFFF,size:8,face:%s" %defaultfont1 # line number (margin) self.txtPromptStyleDictionary[1] = "fore:#000000,back:#82AEE3,size:8" # brace selected (match) self.txtPromptStyleDictionary[2] = "fore:#000000,back:#FFFFFF" # brace selected (no match) self.txtPromptStyleDictionary[3] = "fore:#000000,back:#FFFFFF" # character (single quoted string) self.txtPromptStyleDictionary[4] = "fore:#000000,back:#FFFFFF" #class name self.txtPromptStyleDictionary[5] = "fore:#000000,back:#FFFFFF" #comment self.txtPromptStyleDictionary[6] = "fore:#000000,back:#FFFFFF" #comment block self.txtPromptStyleDictionary[7] = "fore:#000000,back:#FFFFFF" #function name self.txtPromptStyleDictionary[8] = "fore:#000000,back:#FFFFFF" #keyword self.txtPromptStyleDictionary[9] = "fore:#000000,back:#FFFFFF" #number self.txtPromptStyleDictionary[10] = "fore:#000000,back:#FFFFFF" #operator self.txtPromptStyleDictionary[11] = "fore:#000000,back:#FFFFFF" #string self.txtPromptStyleDictionary[12] = "fore:#000000,back:#FFFFFF" #string eol self.txtPromptStyleDictionary[13] = "fore:#000000,back:#FFFFFF" #triple quoted string self.txtPromptStyleDictionary[14] = "fore:#000000,back:#FFFFFF" #caret foreground self.txtPromptStyleDictionary[15] = "#000000" #selection self.txtPromptStyleDictionary[16] = "fore:#000000,back:#FF7900" # /lm #Side Panel Settings self.sidepanelleftsize = 30 self.sidepanelrightsize = 30 self.sidepaneltopsize = 30 #Find/Replace Settings self.findreplaceregularexpression = 0 self.findreplacematchcase = 0 self.findreplacefindbackwards = 0 self.findreplacewholeword = 0 self.findreplaceinselection = 0 self.findreplacefromcursor = 1 self.findreplacepromptonreplace = 1 self.findreplaceautowrap = 0 self.findreplaceundercursor = 1 #Source Browser Settings self.sourcebrowserpanel = 0 self.sourcebrowsersize = 25 self.sourcebrowserisvisible = 1 self.sourcebrowsercloseonactivate = 0 self.sourcebrowserissorted = 0 self.sourcebrowserautorefreshonsave = 1 self.sourcebrowserautorefresh = 0 self.sourcebrowseruseimages = 0 self.sourcebrowserstyle = "fore:#FF0000,back:#FFFFFF,size:10,face:%s" %defaultfont1 #Bookmarks Settings self.bookmarksstyle = "fore:#000000,back:#FFFFFF,size:12,face:%s,bold" %defaultfont1 preferencesdirectory = wx.GetApp().GetTopWindow().preferencesdirectory #Plugins Settings self.pluginsdirectory = os.path.join(preferencesdirectory, 'drplugins').replace ('\\', "/") #DrScript Settings self.drscriptsdirectory = os.path.join(preferencesdirectory, 'drscripts').replace ('\\', "/") self.drscriptstyle = "fore:#000000,back:#FFFFFF,size:12,face:%s,bold" %defaultfont1 self.drscriptloadexamples = 1 #Printing Settings self.printdoclinenumbers = 1 self.printpromptlinenumbers = 0 self.printtabwidth = 4 #Documentation Settings self.documentationbrowser = "mozilla" if self.platform_is_windows: self.documentationbrowser = "" self.documentationpythonlocation = "http://www.python.org/doc/current/" self.documentationwxwidgetslocation = "http://www.wxwidgets.org/docs.htm" self.documentationrehowtolocation = "http://www.amk.ca/python/howto/regex/" def __getitem__(self, key): k = key.find('[') if k > -1: return self.__dict__[key[:k]][_getkey(key)] else: return self.__dict__[key] def __setitem__(self, key, value): k = key.find('[') if k > -1: self.__dict__[key[:k]][_getkey(key)] = value else: self.__dict__[key] = value def reset(self): self.__init__(self.platform_is_windows, self.programdirectory) def resetjust(self, target): defaults = drPreferences(self.platform_is_windows, self.programdirectory) prefsdictionary = GetPreferencesDictionary() if prefsdictionary.has_key(target): for Preference in prefsdictionary[target]: self[Preference[0]] = defaults[Preference[0]] wx.GetApp().debugmodus = self['debugmodus'] def Copy(self, target): self.platform_is_windows = target.platform_is_windows self.programdirectory = target.programdirectory prefsdictionary = GetPreferencesDictionary() for Entry in prefsdictionary: for Preference in prefsdictionary[Entry]: self[Preference[0]] = target[Preference[0]] wx.GetApp().debugmodus = self['debugmodus'] drpython-3.11.1/drpython.pyw0000644000175000017500000000264211150445515016667 0ustar dktrkranzdktrkranz#!/usr/bin/env python # Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # To Run: # # Windows Users: Make sure ".pyw" files are associated with the pythonw.exe file in your python-directory. # # Linux/Unix Users: Make sure the first line of this file is the correct path to python: # "/bin/python", "/usr/bin/python", "/usr/local/bin/python" are all suggestions. # Using "/bin/env python" should find it for you though. # if __name__ == '__main__': import drpython drpython.main() drpython-3.11.1/drScriptMenu.py0000644000175000017500000005565511150445514017263 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #drScript Menu import os.path import wx import drFileDialog import drScrolledMessageDialog from drPrefsFile import ExtractPreferenceFromText import drShortcutsFile import drShortcuts from drMenu import drMenu def updatescripts(scriptfile, paths, titles): l = len(paths) x = 0 f = open(scriptfile, 'w') while x < l: f.write("" + paths[x] + "" + titles[x] + "\n") x = x + 1 f.close() class drNewShellDialog(wx.Dialog): def __init__(self, parent, title): wx.Dialog.__init__(self, parent, -1, title, wx.Point(50, 50), wx.Size(375, 250), wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.THICK_FRAME | wx.RESIZE_BORDER) self.ID_SAVE = 1005 self.theSizer = wx.FlexGridSizer(6, 3, 5, 10) self.btnSave = wx.Button(self, self.ID_SAVE, "&Save") self.parent = parent self.txtTitle = wx.TextCtrl(self, -1, "", wx.Point(15, 325), wx.Size(250, -1)) self.txtCommand = wx.TextCtrl(self, -1, "", wx.Point(15, 325), wx.Size(250, -1)) self.txtArguments = wx.TextCtrl(self, -1, "", wx.Point(15, 325), wx.Size(250, -1)) self.txtDirectory = wx.TextCtrl(self, -1, "", wx.Point(15, 325), wx.Size(250, -1)) self.chkRunInPrompt = wx.CheckBox(self, -1, "") self.chkRunInPrompt.SetValue(True) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Title:"), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.txtTitle, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Command:"), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.txtCommand, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Arguments:"), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.txtArguments, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Directory:"), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.txtDirectory, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, "Run In Prompt:"), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.chkRunInPrompt, 0, wx.SHAPED) self.btnClose = wx.Button(self, 101, "&Close") self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.theSizer.Add(self.btnClose, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.btnSave, 0, wx.SHAPED | wx.ALIGN_RIGHT) self.txtTitle.SetFocus() self.btnSave.SetDefault() self.SetAutoLayout(True) self.SetSizer(self.theSizer) self.exitstatus = 0 self.Bind(wx.EVT_BUTTON, self.OnbtnSave, id=self.ID_SAVE) self.Bind(wx.EVT_BUTTON, self.OnbtnClose, id=101) def GetExitStatus(self): return self.exitstatus def GetShellTuple(self): return self.txtTitle.GetValue(), self.txtCommand.GetValue(), self.txtArguments.GetValue(), self.txtDirectory.GetValue(), int(self.chkRunInPrompt.GetValue()) def OnbtnClose(self, event): self.exitstatus = 0 self.Close(1) def OnbtnSave(self, event): self.exitstatus = 1 self.Close(1) def SetShellTuple(self, title, command, args, dir, inprompt): self.txtTitle.SetValue(title) self.txtCommand.SetValue(command) self.txtArguments.SetValue(args) self.txtDirectory.SetValue(dir) self.chkRunInPrompt.SetValue(inprompt) class drScriptMenu(drMenu): def __init__(self, parent): drMenu.__init__(self, parent) self.dynamicscriptext = "" self.ID_ADD_SCRIPT = 3100 self.ID_NEW_SCRIPT = 3101 self.ID_EXISTING_SCRIPT = 3102 self.ID_SHELL_COMMAND = 3103 self.ID_EDIT_SCRIPT = 3003 self.ID_REMOVE_SCRIPT = 3005 self.ID_DYNAMIC_SCRIPT = 3006 self.ID_EXAMPLE_SCRIPTS = 3010 self.ID_SCRIPT_BASE = parent.ID_SCRIPT_BASE self.ID_SCRIPT_MENU = 3500 self.parent = parent self.preferencesdirectory = parent.preferencesdirectory self.programdirectory = parent.programdirectory self.shortcutsdirectory = parent.shortcutsdirectory self.scriptcount = 0 self.scripts = [] self.titles = [] self.setupMenu() self.ExampleScriptCount = 0 self.loadscripts() def getdrscriptmenulabel(self, label): shortcuttext = '' if not self.parent.DrScriptShortcuts: return label if label in self.titles: i = self.titles.index(label) self.parent.DrScriptShortcuts[i] shortcuttext = drShortcuts.GetShortcutLabel(self.parent.DrScriptShortcuts[i]) if len(shortcuttext) > 1: if shortcuttext == "Tab": shortcuttext += " " return label + '\t' + shortcuttext return label def reloadscripts(self, oldlength = -1, SyncShortcuts = 1): if oldlength < 0: oldlength = len(self.scripts) mnuitems = self.GetMenuItems() num = len(mnuitems) x = 0 while x < num: self.Remove(mnuitems[x].GetId()) #mnuitems[x].Destroy() x = x + 1 self.scripts = [] self.titles = [] self.setupMenu() self.loadscripts(SyncShortcuts) self.parent.DrScriptShortcutNames = [] if self.titles: for l in self.titles: self.parent.DrScriptShortcutNames.append(l) def loadscripts(self, SyncShortcuts = 1): self.scriptcount = 0 if self.parent.prefs.drscriptloadexamples: self.examplemenu = wx.Menu() self.loadscriptsfromfile(self.programdirectory + "/examples/DrScript/drscript.dat", self.examplemenu, 1) self.AppendMenu(self.ID_EXAMPLE_SCRIPTS, "Examples", self.examplemenu) self.AppendSeparator() self.ExampleScriptCount = self.scriptcount self.loadscriptsfromfile(self.preferencesdirectory + "/drscript.dat", self) #Either there is no shortcuts file, or it is out of sync. if SyncShortcuts: l = len(self.titles) if l != len(self.parent.DrScriptShortcuts): self.parent.DrScriptShortcuts = [] self.parent.DrScriptShortcutNames = [] x = 0 while x < l: self.parent.DrScriptShortcuts.append(' #') self.parent.DrScriptShortcutNames.append(self.titles[x]) x = x + 1 def loadscriptsfromfile(self, scriptfile, target, appendprogpath = 0): if os.path.exists(scriptfile): folders = [target] folderindex = 0 menuTitles = [] menuTitleindex = -1 lastCount = 0 try: #Read from the file f = open(scriptfile, 'rb') #Initialize line = f.readline() while len(line) > 0: c = line.count('\t') line = line[c:].rstrip() while lastCount > c: folders[(folderindex - 1)].AppendMenu(self.ID_SCRIPT_MENU, menuTitles.pop(), folders.pop()) folderindex = folderindex - 1 menuTitleindex = menuTitleindex - 1 lastCount = lastCount - 1 if line[0] == '>': folders.append(wx.Menu()) menuTitles.append(line[1:]) folderindex = folderindex + 1 menuTitleindex = menuTitleindex + 1 c = c + 1 else: line_path = ExtractPreferenceFromText(line, "path") if appendprogpath: line_path = self.programdirectory + "/" + line_path.replace('\\', '/') else: if not os.path.isabs(line_path): line_path = os.path.join(self.parent.drscriptsdirectory, line_path) line_title = ExtractPreferenceFromText(line, "title") if os.path.exists(line_path): self.titles.append(line_title) folders[folderindex].Append((self.ID_SCRIPT_BASE + self.scriptcount), self.getdrscriptmenulabel(line_title)) self.parent.Bind(wx.EVT_MENU, self.OnScript, id=(self.ID_SCRIPT_BASE + self.scriptcount)) self.scripts.append(line_path) self.scriptcount = self.scriptcount + 1 lastCount = c line = f.readline() f.close() #Add any menus not yet added: c = 0 while lastCount > c: folders[(folderindex - 1)].AppendMenu(self.ID_SCRIPT_MENU, menuTitles.pop(), folders.pop()) folderindex = folderindex - 1 menuTitleindex = menuTitleindex - 1 lastCount = lastCount - 1 except: drScrolledMessageDialog.ShowMessage(self.parent, ("Your drscript file is a tad messed up.\n"), "Error") def OnAddExistingScript(self, event): scriptfile = self.preferencesdirectory + "/drscript.dat" dlg = drFileDialog.FileDialog(self.parent, "Select Script File", self.parent.prefs.wildcard) if self.parent.drscriptsdirectory: try: dlg.SetDirectory(self.parent.drscriptsdirectory) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error Setting Default Directory To: " + self.parent.drscriptsdirectory), "DrPython Error") if dlg.ShowModal() == wx.ID_OK: filen = dlg.GetPath().replace("\\", "/") p = os.path.basename(filen) #patch by AB (suggests filename as title), 06.03.2007, thanks s = os.path.splitext(p) d = wx.TextEntryDialog(self.parent, 'Enter Script Title:', 'Add DrScript: Title', s[0]) #end patch by AB title = "" if d.ShowModal() == wx.ID_OK: title = d.GetValue() d.Destroy() if not title: drScrolledMessageDialog.ShowMessage(self.parent, ("Bad script title.\nDrPython will politely ignore your request to add this script."), "Error") return self.Append((self.ID_SCRIPT_BASE + self.scriptcount), title, title) self.parent.Bind(wx.EVT_MENU, self.OnScript, id=(self.ID_SCRIPT_BASE + self.scriptcount)) #if directory is relativ, store only filename without path pth = self.parent.drscriptsdirectory.lower() if filen.lower().startswith (pth): filen = filen[len(pth):] if filen[0] == '/': filen = filen[1:] self.scripts.append(filen) self.titles.append(title) self.parent.DrScriptShortcuts.append('') self.parent.DrScriptShortcutNames.append(title) self.scriptcount += 1 try: f = open(scriptfile, 'a') f.write("" + filen + "" + title + "\n") f.close() #Update the shortcuts Too. shortcutsfile = self.shortcutsdirectory + "/drscript.shortcuts.dat" drShortcutsFile.WriteShortcuts(shortcutsfile, self.parent.DrScriptShortcuts, self.parent.DrScriptShortcutNames, "", False) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Problem saving script.\n"), "Error") dlg.Destroy() def OnAddNewScript(self, event): scriptfile = self.preferencesdirectory + "/drscript.dat" dlg = drFileDialog.FileDialog(self.parent, "Save New Script File As", self.parent.prefs.wildcard, IsASaveDialog=True) if self.parent.drscriptsdirectory: try: dlg.SetDirectory(self.parent.drscriptsdirectory) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error Setting Default Directory To: " + self.parent.drscriptsdirectory), "DrPython Error") if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath().replace("\\", "/") if not filename.endswith('.py'): filename += '.py' s = os.path.splitext(filename)[0] s = os.path.basename(s) d = wx.TextEntryDialog(self.parent, "Enter Script Title:", "Add DrScript: Title", s) title = "" if d.ShowModal() == wx.ID_OK: title = d.GetValue() d.Destroy() if not title: drScrolledMessageDialog.ShowMessage(self.parent, ("Bad script title.\nDrPython will politely ignore your request to add this script."), "Error") return cfile = file(filename, 'wb') cfile.write("#drscript\n\n") cfile.close() self.Append((self.ID_SCRIPT_BASE + self.scriptcount), title, title) self.parent.Bind(wx.EVT_MENU, self.OnScript, id=(self.ID_SCRIPT_BASE + self.scriptcount)) #if directory is relativ, store only filename without path pth = self.parent.drscriptsdirectory.lower() fname = filename if filename.lower().startswith (pth): fname = filename[len(pth):] if fname[0] == '/': fname = fname[1:] self.scripts.append(fname) self.titles.append(fname) self.parent.DrScriptShortcuts.append('') self.parent.DrScriptShortcutNames.append(title) self.scriptcount += 1 try: f = open(scriptfile, 'a') f.write("" + fname + "" + title + "\n") f.close() shortcutsfile = self.shortcutsdirectory + "/drscript.shortcuts.dat" drShortcutsFile.WriteShortcuts(shortcutsfile, self.parent.DrScriptShortcuts, self.parent.DrScriptShortcutNames, "", False) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Problem saving script.\n"), "Error") old = self.parent.txtDocument.filename if (len(old) > 0) or (self.parent.txtDocument.GetModify()): self.parent.OpenFile(filename, True) else: self.parent.OpenFile(filename, False) dlg.Destroy() def OnAddShellCommand(self, event): scriptfile = self.preferencesdirectory + "/drscript.dat" dlg = drFileDialog.FileDialog(self.parent, "Save New Shell Command As", self.parent.prefs.wildcard, IsASaveDialog=True) if self.parent.drscriptsdirectory: try: dlg.SetDirectory(self.parent.drscriptsdirectory) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error Setting Default Directory To: " + self.parent.drscriptsdirectory), "DrPython Error") if dlg.ShowModal() == wx.ID_OK: filen = dlg.GetPath().replace("\\", "/") d = drNewShellDialog(self.parent, "New Shell Command") if self.parent.PLATFORM_IS_WIN: d.SetSize(wx.Size(425, 350)) d.ShowModal() if d.GetExitStatus(): title, cmd, args, dir, inprompt = d.GetShellTuple() d.Destroy() else: d.Destroy() return if not title: drScrolledMessageDialog.ShowMessage(self.parent, ("Bad shell title.\nDrPython will politely ignore your request to add this shell command."), "Error") return if args.find("") > -1: args = args.replace("", self.parent.txtDocument.filename) if args.find("") > -1: args = args.replace("", os.path.split(self.parent.txtDocument.filename)[0]) if dir.find("") > -1: dir = dir.replace("", os.path.split(self.parent.txtDocument.filename)[0]) cfile = file(filen, 'wb') scripttext = "#drscript shell command\n\n" if dir: scripttext = scripttext + 'import os\n\nos.chdir("' + dir + '")\n\n' if inprompt: scripttext = scripttext + 'DrFrame.Execute("' + cmd + ' ' + args + '", "Running Shell Command")\n\n' else: scripttext = scripttext + 'wx.Shell("' + cmd + ' ' + args + '")\n\n' cfile.write(scripttext) cfile.close() self.Append((self.ID_SCRIPT_BASE + self.scriptcount), title, title) self.parent.Bind(wx.EVT_MENU, self.OnScript, id=(self.ID_SCRIPT_BASE + self.scriptcount)) self.scripts.append(filen) self.titles.append(title) self.parent.DrScriptShortcuts.append('') self.parent.DrScriptShortcutNames.append(title) self.scriptcount = self.scriptcount + 1 try: f = open(scriptfile, 'a') f.write("" + filen + "" + title + "\n") f.close() shortcutsfile = self.shortcutsdirectory + "/drscript.shortcuts.dat" drShortcutsFile.WriteShortcuts(shortcutsfile, self.parent.DrScriptShortcuts, self.parent.DrScriptShortcutNames, "", False) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Problem saving script.\n"), "Error") dlg.Destroy() def OnDynamicScript(self, event): from drDynamicDrScriptDialog import drDynamicDrScriptDialog d = drDynamicDrScriptDialog(self.parent, self.dynamicscriptext) d.ShowModal() self.dynamicscriptext = d.GetText() d.Destroy() def OnEditScript(self, event): if self.scripts: def tuplify(x, y): return (x, y) def detuplify(x): return x[0] array = map(tuplify, self.titles, self.scripts) array.sort() titles = map(detuplify, array) d = wx.SingleChoiceDialog(self.parent, "Select the Script to Edit:", "Edit Script", titles, wx.CHOICEDLG_STYLE) #d.SetSize(wx.Size(250, 250)) answer = d.ShowModal() d.Destroy() if answer == wx.ID_OK: i = d.GetSelection() filename = array[i][1].replace("\\", "/") self.parent.OpenOrSwitchToFile(filename, editRecentFiles=False) else: drScrolledMessageDialog.ShowMessage(self.parent, ("There aren't any scripts to edit.\nTry \"New Script\" or \"Add Script\" Instead."), "Error") def OnScript(self, event): scriptindex = event.GetId() - self.ID_SCRIPT_BASE scriptfname = self.scripts[scriptindex] #relativ path? => complete script filename if not os.path.isabs(scriptfname): scriptfname = os.path.join(self.parent.drscriptsdirectory, scriptfname) f = open(scriptfname, 'r') scripttext = f.read() f.close() if scripttext.find("DrFilename") > -1: scripttext = scripttext.replace("DrFilename", "self.parent.txtDocument.filename") if scripttext.find("DrScript") > -1: scripttext = scripttext.replace("DrScript", "self.parent.DrScript") if scripttext.find("DrDocument") > -1: scripttext = scripttext.replace("DrDocument", "self.parent.txtDocument") if scripttext.find("DrPrompt") > -1: scripttext = scripttext.replace("DrPrompt", "self.parent.txtPrompt") if scripttext.find("DrFrame") > -1: scripttext = scripttext.replace("DrFrame", "self.parent") try: code = compile((scripttext + '\n'), scriptfname, 'exec') except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error compiling script."), "Error", wx.DefaultPosition, wx.Size(550,300)) return try: exec(code) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error running script."), "Error", wx.DefaultPosition, wx.Size(550,300)) return def setupMenu(self): addscriptmenu = wx.Menu() addscriptmenu.Append(self.ID_NEW_SCRIPT, "&New Script...") addscriptmenu.Append(self.ID_EXISTING_SCRIPT, "&Existing Script...") addscriptmenu.Append(self.ID_SHELL_COMMAND, "&Shell Command...") self.AppendMenu(self.ID_ADD_SCRIPT, "&Add Script", addscriptmenu) self.Append(self.ID_EDIT_SCRIPT, "&Edit Script...") self.Append(self.ID_DYNAMIC_SCRIPT, "&Dynamic DrScript...") self.AppendSeparator() self.parent.Bind(wx.EVT_MENU, self.OnAddExistingScript, id=self.ID_EXISTING_SCRIPT) self.parent.Bind(wx.EVT_MENU, self.OnAddNewScript, id=self.ID_NEW_SCRIPT) self.parent.Bind(wx.EVT_MENU, self.OnAddShellCommand, id=self.ID_SHELL_COMMAND) self.parent.Bind(wx.EVT_MENU, self.OnEditScript, id=self.ID_EDIT_SCRIPT) self.parent.Bind(wx.EVT_MENU, self.OnDynamicScript, id=self.ID_DYNAMIC_SCRIPT) drpython-3.11.1/drBookmarksDialog.py0000644000175000017500000001521711150445514020230 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Bookmarks Dialog import wx import drScrolledMessageDialog import drFileDialog from drProperty import * from drTreeDialog import * def BuildTreeFromString(dialog, branch, thestring): line = " " roots = [branch] rootindex = 0 lastCount = 1 i = 0 lastI = 0 #Skip the First Line i = thestring.find('\n') if i > -1: line = thestring[0:(i + 1)] lastI = i + 1 thestring = thestring[lastI:] #Get On With It! while line: i = thestring.find('\n') if (i > -1): line = thestring[0:(i + 1)] lastI = i + 1 thestring = thestring[lastI:] c = line.count('\t') line = line[c:].rstrip() while lastCount > c: roots.pop() rootindex = rootindex - 1 lastCount = lastCount - 1 currentItem = dialog.datatree.AppendItem(roots[rootindex], line) if line[0] == '>': dialog.datatree.SetItemImage(currentItem, 0, wx.TreeItemIcon_Normal) dialog.datatree.SetItemImage(currentItem, 1, wx.TreeItemIcon_Expanded) roots.append(currentItem) rootindex = rootindex + 1 lastCount = c + 1 else: dialog.datatree.SetItemImage(currentItem, 2, wx.TreeItemIcon_Normal) dialog.datatree.SetItemImage(currentItem, 2, wx.TreeItemIcon_Selected) else: line = "" def WriteBranch(tree, branch, filehandle, tablevel): t = tree.GetItemText(branch) isfolder = (t[0] == '>') x = 0 y = "" while x < tablevel: y = y + '\t' x = x + 1 y = y + t + "\n" filehandle.write(y) if isfolder: ccount = tree.GetChildrenCount(branch, 0) if ccount > 0: if (wx.MAJOR_VERSION >= 2) and (wx.MINOR_VERSION >= 5): b, cookie = tree.GetFirstChild(branch) else: b, cookie = tree.GetFirstChild(branch, 1) WriteBranch(tree, b, filehandle, (tablevel + 1)) x = 1 while x < ccount: b, cookie = tree.GetNextChild(branch, cookie) WriteBranch(tree, b, filehandle, (tablevel + 1)) x = x + 1 class drBookmarksDialog(drTreeDialog): def __init__(self, parent, bookmarksfile): drTreeDialog.__init__(self, parent, 'Edit Bookmarks', 'Bookmarks', bookmarksfile, parent.prefs.bookmarksstyle, \ 'bookmarksdialog.sizeandposition.dat', parent.bitmapdirectory + "/16/bookmark.png", BuildTreeFromString, WriteBranch) self.ID_ADD = 1001 self.btnAdd = wx.Button(self, self.ID_ADD, "&Add") self.cmdSizer.Prepend(self.btnAdd, 0, wx.SHAPED) self.SetupSizer() self.Bind(wx.EVT_BUTTON, self.OnbtnAdd, id=self.ID_ADD) if parent.PLATFORM_IS_GTK: #does not get initially the focus (bug tracker #1903778, "Open Imported Module: focus problem", 29.02.2008: from Jon White, thanks. self.SetFocus() def OnbtnAdd(self, event): sel = self.datatree.GetSelection() if not sel.IsOk(): if self.datatree.GetCount() < 2: sel = self.datatree.GetRootItem() else: return if self.datatree.GetItemText(sel)[0] == '>': d = wx.SingleChoiceDialog(self, "Add Bookmark:", "Add Bookmark", ["Select Directory", "Select File", "Type It In"], wx.OK|wx.CANCEL) d.SetSize(wx.Size(250, 200)) answer = d.ShowModal() d.Destroy() if answer == wx.ID_OK: s = d.GetStringSelection() currentItem = None if s == "Type It In": d = wx.TextEntryDialog(self, 'Enter Bookmark:', 'Add Bookmark', '') if d.ShowModal() == wx.ID_OK: v = d.GetValue() currentItem = self.datatree.AppendItem(sel, v.replace('\\', '/')) d.Destroy() elif s == "Select Directory": d = wx.DirDialog(self, "Select Directory:", style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON|wx.MAXIMIZE_BOX|wx.THICK_FRAME) if self.parent.ddirectory: try: d.SetPath(self.parent.ddirectory) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error Setting Default Directory To: " + self.parent.ddirectory), "DrPython Error") if d.ShowModal() == wx.ID_OK: currentItem = self.datatree.AppendItem(sel, d.GetPath().replace('\\', '/')) d.Destroy() else: dlg = drFileDialog.FileDialog(self.parent, "Select File", self.wildcard) if self.parent.ddirectory: try: dlg.SetDirectory(self.parent.ddirectory) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error Setting Default Directory To: " + self.parent.ddirectory), "DrPython Error") if dlg.ShowModal() == wx.ID_OK: currentItem = self.datatree.AppendItem(sel, dlg.GetPath().replace("\\", "/")) dlg.Destroy() if currentItem is not None: self.datatree.SetItemImage(currentItem, 2, wx.TreeItemIcon_Normal) self.datatree.SetItemImage(currentItem, 2, wx.TreeItemIcon_Selected) self.datatree.SetModified() else: drScrolledMessageDialog.ShowMessage(self, "You can only add a bookmark to a folder.\nSelect either \"Bookmarks\", or a folder.", "Bad Bookmark Folder") drpython-3.11.1/drPrefsDialog.py0000644000175000017500000022704511235243012017354 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import os, locale import sys import wx import drScrolledMessageDialog from drProperty import * import drPrefsFile import drFileDialog from drStyleDialog import drStyleDialog, drSimpleStyleDialog from drPreferences import drPreferences #Cause I want it to work MY way! class drPrefsBook(wx.Panel): def __init__(self, parent, id, size): wx.Panel.__init__(self, parent, id, size=size) x, y = size self.pages = [] self.labels = [] self.ancestor = parent.parent self.listview = wx.ListView(self, id+1, pos=(0, 0), size=(150, y), style=wx.LC_SINGLE_SEL|wx.LC_LIST) self.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.OnSelected, id=id+1) self.Bind(wx.EVT_SIZE, self.OnSize) self.oldpos = -1 def AddPage(self, page, label): page.Show(False) self.pages.append(page) self.labels.append(label) def OnSelected(self, event): if self.oldpos > -1: self.pages[self.oldpos].Show(False) sel = self.listview.GetFocusedItem() self.ancestor.prefdialogposition = sel px, py = self.GetPositionTuple() sx, sy = self.GetSizeTuple() self.pages[sel].Move((px+150, 0)) self.pages[sel].SetSize((sx-150, sy)) self.pages[sel].Show(True) self.oldpos = sel def OnSize(self, event): sel = self.listview.GetFocusedItem() px, py = self.GetPositionTuple() sx, sy = self.GetSizeTuple() self.listview.SetSize((150, sy)) self.pages[sel].Move((px+150, 0)) self.pages[sel].SetSize((sx-150, sy)) def SetSelection(self, selection): self.listview.Select(selection) self.listview.Focus(selection) def ShowPanel(self, selection=0): x = 0 for label in self.labels: self.listview.InsertStringItem(x, label) x += 1 self.listview.Select(selection) self.listview.Focus(selection) self.OnSelected(None) #Cleaned up the sizing code, which was a tad ugly. class PrefsPanel(wx.ScrolledWindow): def __init__(self, parent, id, name, NumberOfItems): wx.ScrolledWindow.__init__(self, parent, id) self.SetName(name) self.grandparent = parent.GetParent() self.drframe = self.grandparent.parent self.EnableScrolling(True, True) self.SetScrollbars(10, NumberOfItems+3, 35, 62) self.btnResetPanel = wx.Button(self, self.grandparent.ID_RESET_PANEL, " Reset Panel ") self.theSizer = wx.FlexGridSizer(NumberOfItems+2, 3, 5, 10) self.AddBuffer() self.Add(self.btnResetPanel, "Reset Just These Preferences:") self.Bind(wx.EVT_BUTTON, self.grandparent.OnbtnResetPanel, id=self.grandparent.ID_RESET_PANEL) self.Show(False) def Add(self, wxitem, label=""): if label: self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, label), 1, wx.EXPAND) self.theSizer.Add(wxitem,1,wx.SHAPED) else: self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wxitem, 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) def AddBuffer(self): self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) def AddLabel(self, label): self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, label), 1, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) def AddTwoItems(self, wxitem1, wxitem2): self.theSizer.Add(wx.StaticText(self, -1, " "), 1, wx.SHAPED) self.theSizer.Add(wxitem1,1,wx.SHAPED) self.theSizer.Add(wxitem2,1,wx.SHAPED) def SetPanelSizer(self): self.SetAutoLayout(True) self.SetSizer(self.theSizer) class BookmarksPanel(PrefsPanel): def __init__(self, parent, id, name): PrefsPanel.__init__(self, parent, id, name, 1) self.btnBStyle = wx.Button(self, self.grandparent.ID_BOOKMARKS_STYLE, " Edit Bookmarks Style ") self.Add(self.btnBStyle) self.SetPanelSizer() self.Bind(wx.EVT_BUTTON, self.OnbtnBStyle, id=self.grandparent.ID_BOOKMARKS_STYLE) def OnbtnBStyle(self, event): d = drSimpleStyleDialog(self, -1, ("Style: Bookmarks"), self.grandparent.prefs.bookmarksstyle, self.grandparent.prefs.bookmarksstyle) d.ShowModal() if d.ClickedOk(): self.grandparent.prefs.bookmarksstyle = d.GetStyleString() d.Destroy() class DocumentPanel(PrefsPanel): def __init__(self, parent, id, name): PrefsPanel.__init__(self, parent, id, name, 10) self.radusestyles = wx.RadioBox(self, -1, "Styles:", wx.DefaultPosition, wx.DefaultSize, ["Don't Use Styles", "Use Styles", "Only Use \"Normal\", \"Caret Foreground\""], 1, wx.RA_SPECIFY_COLS) self.boxdefaultsyntaxhighlighting = wx.Choice(self, -1, wx.Point(225, 135), wx.Size(-1, -1), ["Python", "C/C++", "HTML"]) self.chkonlyusedefaultsyntaxhighlighting = wx.CheckBox(self, -1, "") self.btnStyle = wx.Button(self, self.grandparent.ID_FILE_STYLE, " Edit Text Styles ") self.btnApplyProperty = wx.Button(self, self.grandparent.ID_APPLY_PROPERTY, " Apply Text Property To All Styles ") self.raddocautoindent = wx.RadioBox(self, -1, "Auto Indent:", wx.DefaultPosition, wx.DefaultSize, ["None", "Normal", "Context Sensitive"], 1, wx.RA_SPECIFY_COLS) self.chkdocshowlinenumbers = wx.CheckBox(self, -1, "") #self.chkdocremovetrailingwhitespace = wx.CheckBox(self, -1, "") self.chkdocautoreload = wx.CheckBox(self, -1, "") self.chkdocparenthesismatching = wx.CheckBox(self, -1, "") self.chkdocupdateindentation = wx.CheckBox(self, -1, "") self.chkdocusefileindentation = wx.CheckBox(self, -1, '') self.chkWhitespace = wx.CheckBox(self, -1, "") self.txtcaretwidth = wx.TextCtrl(self, self.grandparent.ID_DOC_CARET_WIDTH, str(self.grandparent.prefs.doccaretwidth), wx.Point(225, 215), wx.Size(35, -1)) self.chkhighlightcurrentline = wx.CheckBox(self, -1, "") self.chkignorectrlpageupdown = wx.CheckBox(self, -1, "") self.chkuseindentationguides = wx.CheckBox(self, -1, "") #Chris McDonough (I added txt prefix, update for local constants) self.txtdoclonglinecol = wx.TextCtrl(self, self.grandparent.ID_LONGLINE_COL, str(self.grandparent.prefs.doclonglinecol), wx.Point(225, 215), wx.Size(35, -1)) #/Chris McDonough self.chkscrollextrapage = wx.CheckBox(self, -1, "") self.raddoccommentmode = wx.RadioBox(self, -1, "Comment Mode:", wx.DefaultPosition, wx.DefaultSize, ["Start of Line", "Start of Word"], 1, wx.RA_SPECIFY_COLS) self.Add(self.btnStyle) self.Add(self.btnApplyProperty) self.Add(self.radusestyles) self.Add(self.boxdefaultsyntaxhighlighting, "Default Syntax Highlighting:") self.Add(self.chkonlyusedefaultsyntaxhighlighting, "Only Use Default Syntax Highlighting:") self.Add(self.chkdocshowlinenumbers, "Show Line Numbers:") #self.Add(self.chkdocremovetrailingwhitespace, "Remove Trailing Whitespace:") self.Add(self.raddocautoindent) self.Add(self.chkdocautoreload, "Auto Reload:") self.Add(self.chkdocparenthesismatching, "Parenthesis Matching:") self.Add(self.chkdocupdateindentation, "Update Indentation:") self.Add(self.chkdocusefileindentation, "Use File's Indentation:") self.Add(self.chkWhitespace, "Whitespace is visible on startup:") self.Add(self.chkuseindentationguides, "Use Indentation guides:") self.Add(self.txtdoclonglinecol, "Long Line Indicator Column:") self.Add(self.chkscrollextrapage, "Scroll Extra Page:") self.Add(self.txtcaretwidth, "Caret Width:") self.Add(self.chkhighlightcurrentline, "Highlight Current Line:") self.Add(self.chkignorectrlpageupdown, "Ignore Ctrl Pageup/down:") self.Add(self.raddoccommentmode) self.SetPanelSizer() self.reset() self.Bind(wx.EVT_BUTTON, self.OnbtnStyle, id=self.grandparent.ID_FILE_STYLE) self.Bind(wx.EVT_BUTTON, self.OnbtnApplyProperty, id=self.grandparent.ID_APPLY_PROPERTY) self.Bind(wx.EVT_TEXT, self.Ontxtcaretwidth, id=self.grandparent.ID_DOC_CARET_WIDTH) self.Bind(wx.EVT_TEXT, self.Ontxtdoclonglinecol, id=self.grandparent.ID_LONGLINE_COL) def reset(self): self.boxdefaultsyntaxhighlighting.SetSelection(self.grandparent.prefs.docdefaultsyntaxhighlighting) self.chkonlyusedefaultsyntaxhighlighting.SetValue(self.grandparent.prefs.doconlyusedefaultsyntaxhighlighting) self.radusestyles.SetSelection(self.grandparent.prefs.docusestyles) self.chkdocshowlinenumbers.SetValue(self.grandparent.prefs.docshowlinenumbers) #self.chkdocremovetrailingwhitespace.SetValue(self.grandparent.prefs.docremovetrailingwhitespace) self.raddocautoindent.SetSelection(self.grandparent.prefs.docautoindent) self.chkdocautoreload.SetValue(self.grandparent.prefs.docautoreload) self.chkdocparenthesismatching.SetValue(self.grandparent.prefs.docparenthesismatching) self.chkdocupdateindentation.SetValue(self.grandparent.prefs.docupdateindentation) self.chkdocusefileindentation.SetValue(self.grandparent.prefs.docusefileindentation) self.chkWhitespace.SetValue(self.grandparent.prefs.docwhitespaceisvisible) self.chkuseindentationguides.SetValue(self.grandparent.prefs.docuseindentationguides) self.chkscrollextrapage.SetValue(self.grandparent.prefs.docscrollextrapage) self.txtcaretwidth.SetValue(str(self.grandparent.prefs.doccaretwidth)) self.chkhighlightcurrentline.SetValue(self.grandparent.prefs.dochighlightcurrentline) self.chkignorectrlpageupdown.SetValue(self.grandparent.prefs.docignorectrlpageupdown) self.raddoccommentmode.SetSelection(self.grandparent.prefs.doccommentmode) def Ontxtdoclonglinecol(self, event): #Chris McDonough (Edited to allow for negative numbers) x = self.txtdoclonglinecol.GetValue() if not x: return try: y = int(x) except ValueError: if not x == "-": drScrolledMessageDialog.ShowMessage(self, ("Whatever you are trying to do... Stop it.\nIt won't work. Actual Numbers only please.\nDrPython will reset to the value last loaded."), "Value Error") self.txtdoclonglinecol.SetValue(str(self.grandparent.prefs.doclonglinecol)) return y = 0 except TypeError: drScrolledMessageDialog.ShowMessage(self, ("\"" + y + "\" is not an integer (a number, eg 2, 4, 568)\nDrPython will reset to the value last loaded."), "Type Error") self.txtdoclonglinecol.SetValue(str(self.grandparent.prefs.doclonglinecol)) return if y > 1024: drScrolledMessageDialog.ShowMessage(self, ("DrPython does not recommend going this high. You can of course..."), "Hmmmm") def Ontxtcaretwidth(self, event): x = self.txtcaretwidth.GetValue() if not x: return try: y = int(x) except ValueError: drScrolledMessageDialog.ShowMessage(self, ("Whatever you are trying to do... Stop it.\nIt won't work. Positive Numbers only please.\nDrPython will reset to the value last loaded."), "Value Error") self.txtcaretwidth.SetValue(str(self.grandparent.prefs.doccaretwidth)) return except TypeError: drScrolledMessageDialog.ShowMessage(self, ("\"" + y + "\" is not an integer (a number, eg 2, 4, 568)\nDrPython will reset to the value last loaded."), "Type Error") self.txtcaretwidth.SetValue(str(self.grandparent.prefs.doccaretwidth)) return if y > 256: drScrolledMessageDialog.ShowMessage(self, ("DrPython does not recommend going this high. You can of course..."), "Hmmmm") def OnbtnStyle(self, event): d = drStyleDialog(self, -1, ("Edit Styles")) d.ShowModal() if d.ClickedOk(): self.grandparent.prefs.PythonStyleDictionary, self.grandparent.prefs.CPPStyleDictionary, self.grandparent.prefs.HTMLStyleDictionary = d.GetArrays() d.Destroy() def OnbtnApplyProperty(self, event): d = wx.SingleChoiceDialog(self, "Select the property you wish to apply to all styles:", "Apply Property To All Styles", ["Font", "Size", "Background", "Foreground"], wx.OK|wx.CANCEL) answer = d.ShowModal() s = d.GetStringSelection() d.Destroy() if answer == wx.ID_OK: self.SetPropertyForStyleArray(self.grandparent.prefs.PythonStyleDictionary, s) self.SetPropertyForStyleArray(self.grandparent.prefs.CPPStyleDictionary, s) self.SetPropertyForStyleArray(self.grandparent.prefs.HTMLStyleDictionary, s) def SetPropertyForStyleArray(self, targetArray, s): #Ignore default text for all, and line number text for bg/fg (first two items) x = 2 if s == "Font": prop = "face" dummy = ",face:terminal" x = 1 elif s == "Size": prop = "size" dummy = ",size:10" x = 1 elif s == "Background": prop = "back" dummy = ",back:#FFFFFF" elif s == "Foreground": prop = "fore" dummy = ",fore:#000000" newstring = getStyleProperty(prop, targetArray[0]) #ignore caret foreground, selection, folding style, long line column, current line #(last five items). l = len(targetArray) - 5 while x < l: tstring = targetArray[x] try: tstring.index(prop) except: tstring = tstring + dummy targetArray[x] = setStyleProperty(prop, tstring, newstring) x = x + 1 class DocumentationPanel(PrefsPanel): def __init__(self, parent, id, name): PrefsPanel.__init__(self, parent, id, name, 8) self.btnBrowse = wx.Button(self, self.grandparent.ID_DOCUMENTATION_BROWSE, " &Browse ") self.btnBrowseP = wx.Button(self, self.grandparent.ID_DOCUMENTATION_BROWSE_P, " &Browse ") self.btnBrowseW = wx.Button(self, self.grandparent.ID_DOCUMENTATION_BROWSE_W, " &Browse ") self.btnBrowseR = wx.Button(self, self.grandparent.ID_DOCUMENTATION_BROWSE_R, " &Browse ") self.txtbrowser = wx.TextCtrl(self, -1, "", wx.Point(225, 215), wx.Size(250, -1)) self.txtpython = wx.TextCtrl(self, -1, "", wx.Point(225, 215), wx.Size(250, -1)) self.txtwxwidgets = wx.TextCtrl(self, -1, "", wx.Point(225, 215), wx.Size(250, -1)) self.txtrehowto = wx.TextCtrl(self, -1, "", wx.Point(225, 215), wx.Size(250, -1)) self.AddLabel("Browser:") self.AddTwoItems(self.txtbrowser, self.btnBrowse) self.AddLabel("Python Docs:") self.AddTwoItems(self.txtpython,self.btnBrowseP) self.AddLabel("WxWidgets Docs:") self.AddTwoItems(self.txtwxwidgets,self.btnBrowseW) self.AddLabel("Regular Expression Howto:") self.AddTwoItems(self.txtrehowto,self.btnBrowseR) self.SetPanelSizer() self.reset() if self.grandparent.prefs.platform_is_windows: self.wildcard = "Program File (*.exe)|*.exe|All files (*)|*" else: self.wildcard = "All files (*)|*" self.Bind(wx.EVT_BUTTON, self.OnbtnBrowse, id=self.grandparent.ID_DOCUMENTATION_BROWSE) self.Bind(wx.EVT_BUTTON, self.OnbtnBrowseDoc, id=self.grandparent.ID_DOCUMENTATION_BROWSE_P) self.Bind(wx.EVT_BUTTON, self.OnbtnBrowseDoc, id=self.grandparent.ID_DOCUMENTATION_BROWSE_W) self.Bind(wx.EVT_BUTTON, self.OnbtnBrowseDoc, id=self.grandparent.ID_DOCUMENTATION_BROWSE_R) def reset(self): self.txtbrowser.SetValue(self.grandparent.prefs.documentationbrowser) self.txtpython.SetValue(self.grandparent.prefs.documentationpythonlocation) self.txtwxwidgets.SetValue(self.grandparent.prefs.documentationwxwidgetslocation) self.txtrehowto.SetValue(self.grandparent.prefs.documentationrehowtolocation) def OnbtnBrowse(self, event): dlg = drFileDialog.FileDialog(self.grandparent.parent, "Select A Browser", self.wildcard) if dlg.ShowModal() == wx.ID_OK: self.txtbrowser.SetValue(dlg.GetPath()) dlg.Destroy() def OnbtnBrowseDoc(self, event): eid = event.GetId() result = "" dlg = drFileDialog.FileDialog(self.grandparent.parent, "Location of Documentation", self.wildcard) if dlg.ShowModal() == wx.ID_OK: result = dlg.GetPath() dlg.Destroy() if result: if eid == self.grandparent.ID_DOCUMENTATION_BROWSE_P: self.txtpython.SetValue(result) elif eid == self.grandparent.ID_DOCUMENTATION_BROWSE_W: self.txtwxwidgets.SetValue(result) elif eid == self.grandparent.ID_DOCUMENTATION_BROWSE_R: self.txtrehowto.SetValue(result) class DragAndDropPanel(PrefsPanel): def __init__(self, parent, id, name): PrefsPanel.__init__(self, parent, id, name, 2) self.raddraganddropmode = wx.RadioBox(self, -1, "Drag and Drop Mode:", wx.DefaultPosition, wx.DefaultSize, ["Drag: Files Only, Drop: Files and Text", "Drag: Files and Text, Drop: Files and Text", "Drag and Drop Files Only"], 1, wx.RA_SPECIFY_COLS) self.raddraganddroptextmode = wx.RadioBox(self, -1, "Drag and Drop Text Mode:", wx.DefaultPosition, wx.DefaultSize, ["Copy by Default, Cut with Control", "Cut by Default, Copy with Control"], 1, wx.RA_SPECIFY_COLS) self.Add(self.raddraganddropmode) self.Add(self.raddraganddroptextmode) self.SetPanelSizer() self.reset() def reset(self): self.raddraganddropmode.SetSelection(self.grandparent.prefs.draganddropmode) self.raddraganddroptextmode.SetSelection(self.grandparent.prefs.draganddroptextmode) class DrScriptPanel(PrefsPanel): def __init__(self, parent, id, name): PrefsPanel.__init__(self, parent, id, name, 2) self.txtdefaultdirectory = wx.TextCtrl(self, -1, self.grandparent.prefs.drscriptsdirectory, wx.Point(15, 325), wx.Size(250, -1)) self.DrScriptbtnBrowse = wx.Button(self, self.grandparent.ID_DRSCRIPT_BROWSE, " &Browse ") self.btnDStyle = wx.Button(self, self.grandparent.ID_DRSCRIPT_STYLE, " Edit DrScript Style ") self.chkloadexamples = wx.CheckBox(self, -1, "") self.Add(self.btnDStyle) self.AddLabel("Default Directory:") self.AddTwoItems(self.txtdefaultdirectory, self.DrScriptbtnBrowse) self.Add(self.chkloadexamples, "Load Example Scripts:") self.SetPanelSizer() self.reset() self.Bind(wx.EVT_BUTTON, self.OnbtnDBrowse, id=self.grandparent.ID_DRSCRIPT_BROWSE) self.Bind(wx.EVT_BUTTON, self.OnbtnDStyle, id=self.grandparent.ID_DRSCRIPT_STYLE) def reset(self): self.txtdefaultdirectory.SetValue(self.grandparent.prefs.drscriptsdirectory) self.chkloadexamples.SetValue(self.grandparent.prefs.drscriptloadexamples) def OnbtnDBrowse(self, event): d = wx.DirDialog(self, "Select Default Directory For DrScript:", style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON|wx.MAXIMIZE_BOX|wx.THICK_FRAME) if d.ShowModal() == wx.ID_OK: self.txtdefaultdirectory.SetValue(d.GetPath()) d.Destroy() def OnbtnDStyle(self, event): d = drSimpleStyleDialog(self, -1, ("Style: DrScript"), self.grandparent.prefs.drscriptstyle, self.grandparent.prefs.drscriptstyle) d.ShowModal() if d.ClickedOk(): self.grandparent.prefs.drscriptstyle = d.GetStyleString() d.Destroy() class FileDialogPanel(PrefsPanel): def __init__(self, parent, id, name): PrefsPanel.__init__(self, parent, id, name, 2) self.chkusewxfiledialog = wx.CheckBox(self, -1, "") self.chkdefaultextension = wx.CheckBox(self, -1, "") self.btnwildcard = wx.Button(self, self.grandparent.ID_BTN_WILDCARD, ' Edit Wildcard ') self.btnlnkreplacetable = wx.Button(self, self.grandparent.ID_BTN_LNK_REPLACE_TABLE, ' Windows Shortcut Replace Table ') self.Add(self.chkdefaultextension, 'Default Extension (".py"):') self.Add(self.chkusewxfiledialog, "Use wx.FileDialog:") self.Add(self.btnwildcard) self.Add(self.btnlnkreplacetable) self.SetPanelSizer() self.reset() self.Bind(wx.EVT_BUTTON, self.OnEditWildcard, id=self.grandparent.ID_BTN_WILDCARD) self.Bind(wx.EVT_BUTTON, self.OnReplaceTable, id=self.grandparent.ID_BTN_LNK_REPLACE_TABLE) def reset(self): self.chkusewxfiledialog.SetValue(self.grandparent.prefs.usewxfiledialog) self.chkdefaultextension.SetValue(self.grandparent.prefs.defaultextension) def OnEditWildcard(self, event): import drFileDialogPrefs d = drFileDialogPrefs.drFilePrefsDialog(self) answer = d.ShowModal() newwc = d.GetWildcard() cwc = d.GetConstantWildcard() d.Destroy() if answer == wx.ID_OK: self.grandparent.prefs.wildcard = newwc self.grandparent.prefs.constantwildcard = cwc def OnReplaceTable(self, event): import drFileDialogPrefs d = drFileDialogPrefs.drReplaceTableDialog(self) answer = d.ShowModal() newrt = d.GetReplaceTable() d.Destroy() if answer == wx.ID_OK: self.grandparent.prefs.windowsshortcutreplacetable = newrt class FileTypesPanel(PrefsPanel): def __init__(self, parent, id, name): PrefsPanel.__init__(self, parent, id, name, 7) self.ID_FILETYPE = 701 self.ID_EXTENSIONS = 702 self.ID_USETABS = 703 self.ID_TABWIDTH = 704 self.ID_FOLDING = 705 self.ID_EOLMODE = 706 self.ID_COMMENTSTRING = 707 self.ID_WORDWRAP = 708 self.ID_USEINTELLIBACKSPACE = 709 self.ID_REMOVETRAILINGWHITESPACE = 710 self.cboFileType = wx.ComboBox(self, self.ID_FILETYPE, choices=['Python', 'C/C++', 'HTML', 'Text']) self.filetype = self.drframe.txtDocument.filetype self.txtExtensions = wx.TextCtrl(self, self.ID_EXTENSIONS, '', wx.Point(225, 215), wx.Size(225, -1)) self.chkdocusetabs = wx.CheckBox(self, self.ID_USETABS, "") self.chkdocuseintellibackspace = wx.CheckBox(self, self.ID_USEINTELLIBACKSPACE, "") self.chkdocremovetrailingwhitespace = wx.CheckBox(self, self.ID_REMOVETRAILINGWHITESPACE, "") self.chkdocwordwrap = wx.CheckBox(self, self.ID_WORDWRAP, "") self.chkfolding = wx.CheckBox(self, self.ID_FOLDING, "") self.txtdoccommentstring = wx.TextCtrl(self, self.ID_COMMENTSTRING, '', wx.Point(225, 215), wx.Size(35, -1)) self.txttabwidth = wx.TextCtrl(self, self.ID_TABWIDTH, '', wx.Point(225, 215), wx.Size(35, -1)) self.radFormat = wx.Choice(self, self.ID_EOLMODE, wx.Point(15, 80), wx.DefaultSize, [" Unix ('\\n') "," DOS/Windows ('\\r\\n') "," Mac ('\\r') "]) self.Add(self.cboFileType, "File Type:") self.Add(self.txtExtensions, "Extensions:") self.Add(self.txtdoccommentstring, "Comment String:") self.Add(self.txttabwidth, "Tab Width:") self.Add(self.chkdocusetabs, "Use Tabs:") self.Add(self.chkdocuseintellibackspace, "Use Intelli Backspace:") self.Add(self.chkdocremovetrailingwhitespace, "Remove trailing Whitespace on Save:") self.Add(self.chkfolding, "Folding:") self.Add(self.chkdocwordwrap, "Word Wrap:") self.Add(self.radFormat, "Line Ending Format:") self.SetPanelSizer() self.Bind(wx.EVT_COMBOBOX, self.OnFileType, id=self.ID_FILETYPE) self.Bind(wx.EVT_TEXT, self.Ontxttabwidth, id=self.ID_TABWIDTH) self.Bind(wx.EVT_TEXT, self.OnExtensions, id=self.ID_EXTENSIONS) self.Bind(wx.EVT_TEXT, self.OnCommentString, id=self.ID_COMMENTSTRING) self.Bind(wx.EVT_CHECKBOX, self.OnUseTabs, id=self.ID_USETABS) self.Bind(wx.EVT_CHECKBOX, self.OnUseIntelliBackspace, id=self.ID_USEINTELLIBACKSPACE) self.Bind(wx.EVT_CHECKBOX, self.OnRemoveTrailingWhitespace, id=self.ID_REMOVETRAILINGWHITESPACE) self.Bind(wx.EVT_CHECKBOX, self.OnFolding, id=self.ID_FOLDING) self.Bind(wx.EVT_CHECKBOX, self.OnWordWrap, id=self.ID_WORDWRAP) self.Bind(wx.EVT_CHOICE, self.OnEolMode, id=self.ID_EOLMODE) self.cboFileType.SetSelection(self.filetype) self.reset() def reset(self): self.extensions = self.grandparent.prefs.extensions.copy() self.docusetabs = self.grandparent.prefs.docusetabs.copy() self.docuseintellibackspace = self.grandparent.prefs.docuseintellibackspace.copy() self.docremovetrailingwhitespace= self.grandparent.prefs.docremovetrailingwhitespace.copy() self.doctabwidth = self.grandparent.prefs.doctabwidth.copy() self.doceolmode = self.grandparent.prefs.doceolmode.copy() self.docfolding = self.grandparent.prefs.docfolding.copy() self.doccommentstring = self.grandparent.prefs.doccommentstring.copy() self.docwordwrap = self.grandparent.prefs.docwordwrap.copy() self.OnFileType(None) def OnCommentString(self, event): self.doccommentstring[self.filetype] = self.txtdoccommentstring.GetValue() def OnEolMode(self, event): self.doceolmode[self.filetype] = self.radFormat.GetSelection() def OnExtensions(self, event): self.extensions[self.filetype] = self.txtExtensions.GetValue() def OnFileType(self, event): self.filetype = self.cboFileType.GetSelection() self.txtExtensions.SetValue(self.extensions[self.filetype]) self.chkdocusetabs.SetValue(self.docusetabs[self.filetype]) self.chkdocuseintellibackspace.SetValue(self.docuseintellibackspace[self.filetype]) self.chkdocremovetrailingwhitespace.SetValue(self.docremovetrailingwhitespace[self.filetype]) self.txttabwidth.SetValue(str(self.doctabwidth[self.filetype])) self.radFormat.SetSelection(self.doceolmode[self.filetype]) self.chkfolding.SetValue(self.docfolding[self.filetype]) self.txtdoccommentstring.SetValue(self.doccommentstring[self.filetype]) self.chkdocwordwrap.SetValue(self.docwordwrap[self.filetype]) def OnFolding(self, event): self.docfolding[self.filetype] = int(self.chkfolding.GetValue()) def Ontxttabwidth(self, event): x = self.txttabwidth.GetValue() if not x: return try: y = int(x) except ValueError: drScrolledMessageDialog.ShowMessage(self, ("Whatever you are trying to do... Stop it.\nIt won't work. Positive Numbers only please.\nDrPython will reset to the value last loaded."), "Value Error") self.txttabwidth.SetValue(str(self.grandparent.prefs.doctabwidth[self.filetype])) return except TypeError: drScrolledMessageDialog.ShowMessage(self, ("\"" + y + "\" is not an integer (a number, eg 2, 4, 568)\nDrPython will reset to the value last loaded."), "Type Error") self.txttabwidth.SetValue(str(self.grandparent.prefs.doctabwidth[self.filetype])) return if y > 1024: drScrolledMessageDialog.ShowMessage(self, ("DrPython does not recommend going this high. You can of course..."), "Hmmmm") return self.doctabwidth[self.filetype] = y def OnWordWrap(self, event): self.docwordwrap[self.filetype] = int(self.chkdocwordwrap.GetValue()) def OnUseTabs(self, event): self.docusetabs[self.filetype] = int(self.chkdocusetabs.GetValue()) def OnUseIntelliBackspace(self, event): self.docuseintellibackspace[self.filetype] = int(self.chkdocuseintellibackspace.GetValue()) def OnRemoveTrailingWhitespace(self, event): self.docremovetrailingwhitespace[self.filetype] = int(self.chkdocremovetrailingwhitespace.GetValue()) class FindReplacePanel(PrefsPanel): def __init__(self, parent, id, name): PrefsPanel.__init__(self, parent, id, name, 8) self.chkregularexpression = wx.CheckBox(self, -1, "") self.chkmatchcase = wx.CheckBox(self, -1, "") self.chkfindbackwards = wx.CheckBox(self, -1, "") self.chkwholeword = wx.CheckBox(self, -1, "") self.chkinselection = wx.CheckBox(self, -1, "") self.chkfromcursor = wx.CheckBox(self, -1, "") self.chkpromptonreplace = wx.CheckBox(self, -1, "") self.chkfindreplaceautowrap = wx.CheckBox(self, -1, "") self.chkundercursor = wx.CheckBox(self, -1, "") self.Add(self.chkregularexpression, "Regular Expression:") self.Add(self.chkmatchcase, "Match Case:") self.Add(self.chkfindbackwards, "Find Backwards:") self.Add(self.chkwholeword, "Whole Word:") self.Add(self.chkinselection, "In Selection:") self.Add(self.chkfromcursor, "From Cursor:") self.Add(self.chkpromptonreplace, "Prompt On Replace:") self.Add(self.chkfindreplaceautowrap, "Auto Wrap:") self.Add(self.chkundercursor, "Under Cursor:") self.SetPanelSizer() self.reset() def reset(self): self.chkregularexpression.SetValue(self.grandparent.prefs.findreplaceregularexpression) self.chkmatchcase.SetValue(self.grandparent.prefs.findreplacematchcase) self.chkfindbackwards.SetValue(self.grandparent.prefs.findreplacefindbackwards) self.chkwholeword.SetValue(self.grandparent.prefs.findreplacewholeword) self.chkinselection.SetValue(self.grandparent.prefs.findreplaceinselection) self.chkfromcursor.SetValue(self.grandparent.prefs.findreplacefromcursor) self.chkpromptonreplace.SetValue(self.grandparent.prefs.findreplacepromptonreplace) self.chkfindreplaceautowrap.SetValue(self.grandparent.prefs.findreplaceautowrap) self.chkundercursor.SetValue(self.grandparent.prefs.findreplaceundercursor) class GeneralPanel(PrefsPanel): def __init__(self, parent, id, name): PrefsPanel.__init__(self, parent, id, name, 8) try: defaultlocale = locale.getdefaultlocale()[1] except: defaultlocale = None if defaultlocale is not None: self.encodings = [defaultlocale, 'ascii', 'latin-1', 'cp1252', 'utf-8', 'utf-16'] else: self.encodings = ['ascii', 'latin-1', 'cp1252', 'utf-8', 'utf-16'] self.chkrememberwindowsizeandposition = wx.CheckBox(self, -1, "") self.chkrememberdialogsizesandpositions = wx.CheckBox(self, -1, "") self.chkrememberpanelsizes = wx.CheckBox(self, -1, "") self.chkautodetectencoding = wx.CheckBox(self, -1, "") self.cboEncoding = wx.ComboBox(self, -1, choices=self.encodings) self.chksaveonrun = wx.CheckBox(self, -1, "") self.chkchecksyntaxonsave = wx.CheckBox(self, -1, "") self.txtchecksyntaxextensions = wx.TextCtrl(self, -1, self.grandparent.prefs.checksyntaxextensions, size=wx.Size(55, -1)) self.chkpromptonsaveall = wx.CheckBox(self, -1, "") self.chkdoubleclicktoclosetab = wx.CheckBox(self, -1, "") self.boxiconsize = wx.Choice(self, self.grandparent.ID_ICON_SIZE, wx.Point(225, 135), wx.Size(-1, -1), ["0", "16", "24"]) self.txtRecentFiles = wx.TextCtrl(self, self.grandparent.ID_TXT_RECENT_FILES, str(self.grandparent.prefs.recentfileslimit), wx.Point(225, 175), wx.Size(35, -1)) self.chkcheckindentation = wx.CheckBox(self, -1, "") self.txtpythonargs = wx.TextCtrl(self, -1, self.grandparent.prefs.pythonargs, wx.Point(225, 255), wx.Size(55, -1)) self.chkenablefeedback = wx.CheckBox(self, -1, "") self.chkdebugmodus = wx.CheckBox(self, -1, "") self.chkalwayspromptonexit = wx.CheckBox(self, -1, "") self.chkbackupfileonsave = wx.CheckBox(self, -1, "") self.chkCheckFormat = wx.CheckBox(self, -1, "") self.chkvieweol = wx.CheckBox(self, -1, "") self.txtdefaultuserprefsdirectory = wx.TextCtrl(self, -1, self.grandparent.GetParent().preferencesdirectory, wx.Point(15, 325), wx.Size(250, -1)) self.btnBrowseUserPrefsDir = wx.Button(self, self.grandparent.ID_FILE_BROWSE_USER_PREFS_DIR, " &Browse ") self.txtdefaultcurdirdirectory = wx.TextCtrl(self, -1, self.grandparent.prefs.defaultdirectory, wx.Point(15, 375), wx.Size(250, -1)) self.btnBrowseCurDir = wx.Button(self, self.grandparent.ID_FILE_BROWSE_CUR_DIR, " &Browse ") self.btnExportSetup = wx.Button(self, self.grandparent.ID_EXPORT_PREFS, " Export Preferences ") self.btnImportSetup = wx.Button(self, self.grandparent.ID_IMPORT_PREFS, " Import Preferences ") self.Add(self.chkrememberwindowsizeandposition, "Remember Window Size And Position:") self.Add(self.chkrememberdialogsizesandpositions, "Remember Dialog Sizes and Positions:") self.Add(self.chkrememberpanelsizes, "Remember Panel Sizes:") self.Add(self.chkautodetectencoding, "Auto Detect Encoding:") self.Add(self.cboEncoding, "Default Encoding") self.Add(self.chksaveonrun, "Save On Run:") self.Add(self.chkchecksyntaxonsave, "Check Syntax On Save:") self.Add(self.txtchecksyntaxextensions, "Check Syntax: Only On Extensions:") self.Add(self.chkpromptonsaveall, "Prompt On Save All:") self.Add(self.chkdoubleclicktoclosetab, "Double Click To Close Tab:") self.Add(self.txtRecentFiles, "Max number of recent files:") self.Add(self.chkvieweol, "View Line Endings With Whitespace:") self.Add(self.chkCheckFormat, "Check Line Ending Format on Open:") self.Add(self.chkcheckindentation, "Check Indentation Type on Open:") self.Add(self.txtpythonargs, "Python arguments (eg \"-i\"):") self.Add(self.boxiconsize, "Toolbar Icon Size:") self.AddBuffer() self.AddLabel("Default Preferences Directory:") self.AddTwoItems(self.txtdefaultuserprefsdirectory, self.btnBrowseUserPrefsDir) self.AddBuffer() self.AddLabel("Default Current Working Directory:") self.AddTwoItems(self.txtdefaultcurdirdirectory, self.btnBrowseCurDir) self.AddBuffer() self.Add(self.chkenablefeedback, "Enable Feedback Messages:") self.Add(self.chkdebugmodus, "Debug Modus:") self.Add(self.chkalwayspromptonexit, "Always Prompt On Exit:") self.Add(self.chkbackupfileonsave, "Backup File On Save:") self.Add(self.btnExportSetup) self.Add(self.btnImportSetup) self.SetPanelSizer() self.reset() self.Bind(wx.EVT_BUTTON, self.OnbtnBrowseUserPrefsDir, id=self.grandparent.ID_FILE_BROWSE_USER_PREFS_DIR) self.Bind(wx.EVT_BUTTON, self.OnbtnBrowseCurDir, id=self.grandparent.ID_FILE_BROWSE_CUR_DIR) self.Bind(wx.EVT_TEXT, self.OntxtRecentFiles, id=self.grandparent.ID_TXT_RECENT_FILES) self.Bind(wx.EVT_BUTTON, self.OnbtnExportPrefs, id=self.grandparent.ID_EXPORT_PREFS) self.Bind(wx.EVT_BUTTON, self.OnbtnImportPrefs, id=self.grandparent.ID_IMPORT_PREFS) def reset(self): self.txtdefaultuserprefsdirectory.SetValue(self.grandparent.GetParent().preferencesdirectory) self.txtdefaultcurdirdirectory.SetValue(self.grandparent.prefs.defaultdirectory) self.chkrememberwindowsizeandposition.SetValue(self.grandparent.prefs.rememberwindowsizeandposition) self.chkrememberdialogsizesandpositions.SetValue(self.grandparent.prefs.rememberdialogsizesandpositions) self.chkrememberpanelsizes.SetValue(self.grandparent.prefs.rememberpanelsizes) self.chkautodetectencoding.SetValue(self.grandparent.prefs.autodetectencoding) self.chksaveonrun.SetValue(self.grandparent.prefs.saveonrun) self.chkchecksyntaxonsave.SetValue(self.grandparent.prefs.checksyntaxonsave) self.txtchecksyntaxextensions.SetValue(self.grandparent.prefs.checksyntaxextensions) self.chkpromptonsaveall.SetValue(self.grandparent.prefs.promptonsaveall) self.chkdoubleclicktoclosetab.SetValue(self.grandparent.prefs.doubleclicktoclosetab) self.txtRecentFiles.SetValue(str(self.grandparent.prefs.recentfileslimit)) if self.grandparent.prefs.defaultencoding not in self.encodings: self.encodings.append(self.grandparent.prefs.defaultencoding) self.cboEncoding.Append(self.grandparent.prefs.defaultencoding) self.cboEncoding.SetSelection(self.encodings.index(self.grandparent.prefs.defaultencoding)) self.chkcheckindentation.SetValue(self.grandparent.prefs.checkindentation) if self.grandparent.prefs.iconsize == 24: self.boxiconsize.SetSelection(2) elif self.grandparent.prefs.iconsize == 16: self.boxiconsize.SetSelection(1) else: self.boxiconsize.SetSelection(0) self.txtpythonargs.SetValue(self.grandparent.prefs.pythonargs) self.chkenablefeedback.SetValue(self.grandparent.prefs.enablefeedback) self.chkdebugmodus.SetValue(self.grandparent.prefs.debugmodus) self.chkalwayspromptonexit.SetValue(self.grandparent.prefs.alwayspromptonexit) self.chkbackupfileonsave.SetValue(self.grandparent.prefs.backupfileonsave) self.chkvieweol.SetValue(self.grandparent.prefs.vieweol) self.chkCheckFormat.SetValue(self.grandparent.prefs.checkeol) def OnbtnBrowseUserPrefsDir(self, event): #bug fix by Antonio, 06.03.2007: (removed |wx.DD_NEW_DIR_BUTTON because the style wx.DD_DEFAULT_STYLE already includes wx.DD_NEW_DIR_BUTTON) d = wx.DirDialog(self, "Select Default User Preferences Directory:", style=wx.DD_DEFAULT_STYLE) if d.ShowModal() == wx.ID_OK: self.txtdefaultuserprefsdirectory.SetValue(d.GetPath()) d.Destroy() def OnbtnBrowseCurDir(self, event): d = wx.DirDialog(self, "Select Default Current Working Directory:", style=wx.DD_DEFAULT_STYLE) if d.ShowModal() == wx.ID_OK: self.txtdefaultcurdirdirectory.SetValue(d.GetPath()) d.Destroy() def OnbtnExportPrefs(self, event): import drZip import zipfile dlg = drFileDialog.FileDialog(self.drframe, "Export Preferences, Plugins, and DrScripts To", 'Zip File (*.zip)|*.zip', IsASaveDialog=True) if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath().replace("\\", "/") if filename.endswith('.zip')==False: #AB: bug of drFileDialog filename=filename.split('.')[0]+'.zip' zf = zipfile.ZipFile(filename, 'w') drZip.AddDirectoryToZipFile(self.drframe.preferencesdirectory,'',zf) zf.close() dlg.Destroy() def OnbtnImportPrefs(self, event): import drZip if self.drframe.Ask('This will permanently overwrite all of your preferences, plugins, and drscript file.\n\nProceed?', 'Warning'): dlg = drFileDialog.FileDialog(self.drframe, "Import Preferences, Plugins, and DrScripts From", 'Zip File (*.zip)|*.zip') if dlg.ShowModal() == wx.ID_OK: filename = dlg.GetPath().replace("\\", "/") drZip.ImportPreferencesFrom(self.drframe.preferencesdirectory, filename) self.drframe.ShowMessage('Successfully imported preferences, plugins, and drscripts.', 'Import Success') dlg.Destroy() def OntxtRecentFiles(self, event): x = self.txtRecentFiles.GetValue() if not x: return try: y = int(x) except ValueError: drScrolledMessageDialog.ShowMessage(self, ("Whatever you are trying to do... Stop it.\nIt won't work. Positive Numbers only please.\nDrPython will reset to the value last loaded."), "Value Error") self.txtRecentFiles.SetValue(str(self.grandparent.prefs.recentfileslimit)) return except TypeError: drScrolledMessageDialog.ShowMessage(self, ("\"" + y + "\" is not an integer (a number, eg 2, 4, 568)\nDrPython will reset to the value last loaded."), "Type Error") self.txtRecentFiles.SetValue(str(self.grandparent.prefs.recentfileslimit)) return if y > 25: drScrolledMessageDialog.ShowMessage(self, ("DrPython does not recommend going this high. You can of course..."), "Hmmmm") class PluginsPanel(PrefsPanel): def __init__(self, parent, id, name): PrefsPanel.__init__(self, parent, id, name, 1) self.txtdefaultdirectory = wx.TextCtrl(self, -1, self.grandparent.prefs.pluginsdirectory, wx.Point(15, 325), wx.Size(250, -1)) self.PluginsbtnBrowse = wx.Button(self, self.grandparent.ID_PLUGINS_BROWSE, " &Browse ") self.AddLabel("Default Directory:") self.AddTwoItems(self.txtdefaultdirectory, self.PluginsbtnBrowse) self.SetPanelSizer() self.reset() self.Bind(wx.EVT_BUTTON, self.OnbtnPBrowse, id=self.grandparent.ID_PLUGINS_BROWSE) def reset(self): self.txtdefaultdirectory.SetValue(self.grandparent.prefs.pluginsdirectory) def OnbtnPBrowse(self, event): d = wx.DirDialog(self, "Select Default Directory For Plugins:", style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON|wx.MAXIMIZE_BOX|wx.THICK_FRAME) if d.ShowModal() == wx.ID_OK: self.txtdefaultdirectory.SetValue(d.GetPath()) d.Destroy() class PrintPanel(PrefsPanel): def __init__(self, parent, id, name): PrefsPanel.__init__(self, parent, id, name, 3) self.chkdoclinenumbers = wx.CheckBox(self, -1, "") self.chkpromptlinenumbers = wx.CheckBox(self, -1, "") self.txttabwidth = wx.TextCtrl(self, self.grandparent.ID_PRINT_TAB_WIDTH, str(self.grandparent.prefs.printtabwidth), wx.Point(225, 215), wx.Size(35, -1)) self.Add(self.chkdoclinenumbers, "Document Line Numbers:") self.Add(self.chkpromptlinenumbers, "Prompt Line Numbers:") self.Add(self.txttabwidth, "Tab Width:") self.SetPanelSizer() self.reset() self.Bind(wx.EVT_TEXT, self.Ontxttabwidth, id=self.grandparent.ID_PRINT_TAB_WIDTH) def reset(self): self.chkdoclinenumbers.SetValue(self.grandparent.prefs.printdoclinenumbers) self.chkpromptlinenumbers.SetValue(self.grandparent.prefs.printpromptlinenumbers) self.txttabwidth.SetValue(str(self.grandparent.prefs.printtabwidth)) def Ontxttabwidth(self, event): x = self.txttabwidth.GetValue() if not x: return try: y = int(x) except ValueError: drScrolledMessageDialog.ShowMessage(self, ("Whatever you are trying to do... Stop it.\nIt won't work. Positive Numbers only please.\nDrPython will reset to the value last loaded."), "Value Error") self.txttabwidth.SetValue(str(self.grandparent.prefs.printtabwidth)) return except TypeError: drScrolledMessageDialog.ShowMessage(self, ("\"" + y + "\" is not an integer (a number, eg 2, 4, 568)\nDrPython will reset to the value last loaded."), "Type Error") self.txttabwidth.SetValue(str(self.grandparent.prefs.printtabwidth)) return if y > 32: drScrolledMessageDialog.ShowMessage(self, ("DrPython does not recommend going this high. You can of course..."), "Hmmmm") class PromptPanel(PrefsPanel): def __init__(self, parent, id, name): PrefsPanel.__init__(self, parent, id, name, 8) self.ID_TABWIDTH = 750 self.radusestyles = wx.RadioBox(self, -1, "Styles:", wx.DefaultPosition, wx.DefaultSize, ["Don't Use Styles", "Use Styles", "Only Use \"Normal\", \"Caret Foreground\""], 1, wx.RA_SPECIFY_COLS) self.btnStyle = wx.Button(self, self.grandparent.ID_PROMPT_STYLE, " Edit Text Styles ") self.btnApplyProperty = wx.Button(self, self.grandparent.ID_PROMPT_APPLY_PROPERTY, " Apply Text Property To All Styles ") self.txtmarginwidth = wx.TextCtrl(self, self.grandparent.ID_PROMPT_MARGIN_WIDTH, str(self.grandparent.prefs.promptmarginwidth), wx.Point(225, 215), wx.Size(35, -1)) self.chkVisible = wx.CheckBox(self, -1, "") self.chkpromptusetabs = wx.CheckBox(self, -1, "") self.chkwordwrap = wx.CheckBox(self, -1, "") self.txtcaretwidth = wx.TextCtrl(self, self.grandparent.ID_PROMPT_CARET_WIDTH, str(self.grandparent.prefs.promptcaretwidth), wx.Point(225, 215), wx.Size(35, -1)) self.chkWhitespace = wx.CheckBox(self, -1, "") self.chkscrollextrapage = wx.CheckBox(self, -1, "") self.sldrSize = wx.Slider(self, -1, self.grandparent.prefs.promptsize, 25, 100, wx.Point(150, 55), wx.Size(75, -1), wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS ) self.sldrSize.SetTickFreq(25, 1) self.txttabwidth = wx.TextCtrl(self, self.ID_TABWIDTH, '', wx.Point(225, 215), wx.Size(35, -1)) self.radFormat = wx.Choice(self, -1, wx.Point(15, 80), wx.DefaultSize, [" Unix ('\\n') "," DOS/Windows ('\\r\\n') "," Mac ('\\r') "]) self.txtStartupScript = wx.TextCtrl(self, -1, self.grandparent.prefs.promptstartupscript, wx.Point(225, 215), wx.Size(250, 150), wx.TE_MULTILINE) self.Add(self.btnStyle) self.Add(self.btnApplyProperty) self.Add(self.radusestyles) self.Add(self.txtmarginwidth, "Line Number Margin Width:") self.Add(self.chkVisible, "Visible By Default:") self.Add(self.txttabwidth, "Tab Width:") self.Add(self.chkpromptusetabs, "Use Tabs:") self.Add(self.radFormat, "Line Ending Format:") self.Add(self.chkwordwrap, "Word Wrap:") self.Add(self.txtcaretwidth, "Caret Width:") self.Add(self.chkWhitespace, "Whitespace is Visible on Startup:") self.Add(self.chkscrollextrapage, "Scroll Extra Page:") self.Add(self.sldrSize, "Vertical Size:") self.AddLabel("Startup Script:") self.Add(self.txtStartupScript) self.SetPanelSizer() self.reset() self.Bind(wx.EVT_BUTTON, self.OnbtnStyle, id=self.grandparent.ID_PROMPT_STYLE) self.Bind(wx.EVT_BUTTON, self.OnbtnApplyProperty, id=self.grandparent.ID_PROMPT_APPLY_PROPERTY) self.Bind(wx.EVT_TEXT, self.Ontxtmarginwidth, id=self.grandparent.ID_PROMPT_MARGIN_WIDTH) self.Bind(wx.EVT_TEXT, self.Ontxtcaretwidth, id=self.grandparent.ID_PROMPT_CARET_WIDTH) self.Bind(wx.EVT_TEXT, self.Ontxttabwidth, id=self.ID_TABWIDTH) def reset(self): self.txttabwidth.SetValue(str(self.grandparent.prefs.prompttabwidth)) self.radFormat.SetSelection(self.grandparent.prefs.prompteolmode) self.radusestyles.SetSelection(self.grandparent.prefs.promptusestyles) self.txtmarginwidth.SetValue(str(self.grandparent.prefs.promptmarginwidth)) self.chkVisible.SetValue(self.grandparent.prefs.promptisvisible) self.chkpromptusetabs.SetValue(self.grandparent.prefs.promptusetabs) self.chkwordwrap.SetValue(self.grandparent.prefs.promptwordwrap) self.txtcaretwidth.SetValue(str(self.grandparent.prefs.promptcaretwidth)) self.chkWhitespace.SetValue(self.grandparent.prefs.promptwhitespaceisvisible) self.sldrSize.SetValue(self.grandparent.prefs.promptsize) self.chkscrollextrapage.SetValue(self.grandparent.prefs.promptscrollextrapage) self.txtStartupScript.SetValue(self.grandparent.prefs.promptstartupscript) def OnbtnStyle(self, event): d = drStyleDialog(self, -1, ("Edit Prompt Styles"), True) d.ShowModal() if d.ClickedOk(): self.grandparent.prefs.txtPromptStyleDictionary = d.GetArrays() d.Destroy() def OnbtnApplyProperty(self, event): d = wx.SingleChoiceDialog(self, "Select the property you wish to apply to all styles:", "Apply Property To All Styles", ["Font", "Size", "Background", "Foreground"], wx.OK|wx.CANCEL) answer = d.ShowModal() s = d.GetStringSelection() d.Destroy() if answer == wx.ID_OK: if s == "Font": prop = "face" dummy = ",face:terminal" elif s == "Size": prop = "size" dummy = ",size:10" elif s == "Background": prop = "back" dummy = ",back:#000000" elif s == "Foreground": prop = "fore" dummy = ",fore:#FFFFFF" l = len(self.grandparent.prefs.txtPromptStyleDictionary) - 3 #ignore caret foreground, selections x = 2 #Ignore default text, and line number text (0, and 1) bstring = getStyleProperty(prop, self.grandparent.prefs.txtPromptStyleDictionary[0]) while x < l: tstring = self.grandparent.prefs.txtPromptStyleDictionary[x] #self.grandparent.prefs.txtPromptStyleDictionary.pop(x) try: tstring.index(prop) except: tstring = tstring + dummy self.grandparent.prefs.txtPromptStyleDictionary[x] = setStyleProperty(prop, tstring, bstring) x = x + 1 def Ontxtcaretwidth(self, event): x = self.txtcaretwidth.GetValue() if not x: return try: y = int(x) except ValueError: drScrolledMessageDialog.ShowMessage(self, ("Whatever you are trying to do... Stop it.\nIt won't work. Positive Numbers only please.\nDrPython will reset to the value last loaded."), "Value Error") self.txtcaretwidth.SetValue(str(self.grandparent.prefs.promptcaretwidth)) return except TypeError: drScrolledMessageDialog.ShowMessage(self, ("\"" + y + "\" is not an integer (a number, eg 2, 4, 568)\nDrPython will reset to the value last loaded."), "Type Error") self.txtcaretwidth.SetValue(str(self.grandparent.prefs.promptcaretwidth)) return if y > 256: drScrolledMessageDialog.ShowMessage(self, ("DrPython does not recommend going this high. You can of course..."), "Hmmmm") def Ontxtmarginwidth(self, event): x = self.txtmarginwidth.GetValue() if not x: return try: y = int(x) except ValueError: drScrolledMessageDialog.ShowMessage(self, ("Whatever you are trying to do... Stop it.\nIt won't work. Positive Numbers only please.\nDrPython will reset to the value last loaded."), "Value Error") self.txtmarginwidth.SetValue(str(self.grandparent.prefs.promptmarginwidth)) return except TypeError: drScrolledMessageDialog.ShowMessage(self, ("\"" + y + "\" is not an integer (a number, eg 2, 4, 568)\nDrPython will reset to the value last loaded."), "Type Error") self.txtmarginwidth.SetValue(str(self.grandparent.prefs.promptmarginwidth)) return if y > 1024: drScrolledMessageDialog.ShowMessage(self, ("DrPython does not recommend going this high. You can of course..."), "Hmmmm") def Ontxttabwidth(self, event): x = self.txttabwidth.GetValue() if not x: return try: y = int(x) except ValueError: drScrolledMessageDialog.ShowMessage(self, ("Whatever you are trying to do... Stop it.\nIt won't work. Positive Numbers only please.\nDrPython will reset to the value last loaded."), "Value Error") self.txttabwidth.SetValue(str(self.grandparent.prefs.prompttabwidth)) return except TypeError: drScrolledMessageDialog.ShowMessage(self, ("\"" + y + "\" is not an integer (a number, eg 2, 4, 568)\nDrPython will reset to the value last loaded."), "Type Error") self.txttabwidth.SetValue(str(self.grandparent.prefs.prompttabwidth)) return if y > 1024: drScrolledMessageDialog.ShowMessage(self, ("DrPython does not recommend going this high. You can of course..."), "Hmmmm") class SidePanelPanel(PrefsPanel): def __init__(self, parent, id, name): PrefsPanel.__init__(self, parent, id, name, 4) self.sldrSizeLeft = wx.Slider(self, -1, self.grandparent.prefs.sidepanelleftsize, 15, 100, wx.Point(150, 55), wx.Size(75, -1), wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS ) self.sldrSizeLeft.SetTickFreq(25, 1) self.sldrSizeRight = wx.Slider(self, -1, self.grandparent.prefs.sidepanelrightsize, 15, 100, wx.Point(150, 55), wx.Size(75, -1), wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS ) self.sldrSizeRight.SetTickFreq(25, 1) self.sldrSizeTop = wx.Slider(self, -1, self.grandparent.prefs.sidepaneltopsize, 15, 100, wx.Point(150, 55), wx.Size(75, -1), wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS ) self.sldrSizeTop.SetTick(15) self.sldrSizeTop.SetTickFreq(25, 1) self.Add(self.sldrSizeLeft, "Left Panel Size:") self.Add(self.sldrSizeRight, "Right Panel Size:") self.Add(self.sldrSizeTop, "Top Panel Size:") self.SetPanelSizer() self.reset() def reset(self): self.sldrSizeLeft.SetValue(self.grandparent.prefs.sidepanelleftsize) self.sldrSizeRight.SetValue(self.grandparent.prefs.sidepanelrightsize) self.sldrSizeTop.SetValue(self.grandparent.prefs.sidepaneltopsize) class SourceBrowserPanel(PrefsPanel): def __init__(self, parent, id, name): PrefsPanel.__init__(self, parent, id, name, 4) self.btnCStyle = wx.Button(self, self.grandparent.ID_CLASS_BROWSER_STYLE, " Edit Source Browser Style ") self.positionchooser = wx.RadioBox(self, -1, "", wx.DefaultPosition, wx.DefaultSize, ['Left', 'Right', 'Top'], 3, wx.RA_SPECIFY_COLS | wx.NO_BORDER) self.sldrSize = wx.Slider(self, -1, self.grandparent.prefs.sourcebrowsersize, 1, 100, wx.Point(150, 55), wx.Size(75, -1), wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS ) self.sldrSize.SetTickFreq(1, 1) self.chkIsVisible = wx.CheckBox(self, -1, "") self.chkcloseonactivate = wx.CheckBox(self, -1, "") self.chkissorted = wx.CheckBox(self, -1, "") self.chkautorefreshonsave = wx.CheckBox(self, -1, "") self.chkautorefresh = wx.CheckBox(self, -1, "") self.chkuseimages = wx.CheckBox(self, -1, "") self.Add(self.btnCStyle) self.AddLabel("") self.AddLabel("Panel Position:") self.Add(self.positionchooser) self.Add(self.sldrSize, "Panel Size:") self.Add(self.chkIsVisible, "Visible By Default:") self.Add(self.chkcloseonactivate, "Close On Activate:") self.Add(self.chkissorted, "Sorted (Alphabetical):") self.Add(self.chkautorefreshonsave, "Auto Refresh On Save:") self.Add(self.chkautorefresh, "Auto Refresh:") self.Add(self.chkuseimages, "Use Images:") self.SetPanelSizer() self.reset() self.Bind(wx.EVT_BUTTON, self.OnbtnCStyle, id=self.grandparent.ID_CLASS_BROWSER_STYLE) def reset(self): self.positionchooser.SetSelection(self.grandparent.prefs.sourcebrowserpanel) self.sldrSize.SetValue(self.grandparent.prefs.sourcebrowsersize) self.chkIsVisible.SetValue(self.grandparent.prefs.sourcebrowserisvisible) self.chkcloseonactivate.SetValue(self.grandparent.prefs.sourcebrowsercloseonactivate) self.chkissorted.SetValue(self.grandparent.prefs.sourcebrowserissorted) self.chkautorefreshonsave.SetValue(self.grandparent.prefs.sourcebrowserautorefreshonsave) self.chkautorefresh.SetValue(self.grandparent.prefs.sourcebrowserautorefresh) self.chkuseimages.SetValue(self.grandparent.prefs.sourcebrowseruseimages) def OnbtnCStyle(self, event): d = drSimpleStyleDialog(self, -1, ("Style: Source Browser"), self.grandparent.prefs.sourcebrowserstyle, self.grandparent.prefs.sourcebrowserstyle) d.ShowModal() if d.ClickedOk(): self.grandparent.prefs.sourcebrowserstyle = d.GetStyleString() d.Destroy() class drPrefsDialog(wx.Dialog): def __init__(self, parent, id, title): wx.Dialog.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(640, 480), wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.THICK_FRAME | wx.RESIZE_BORDER) self.parent = parent self.ID_PAGES = 100 self.ID_CLOSE = 101 self.ID_RESET = 102 self.ID_UPDATE = 103 self.ID_SAVE = 104 self.ID_HELP = 105 self.ID_FILE_BROWSE_USER_PREFS_DIR = 109 self.ID_TEXT_TYPE = 110 self.ID_FILE_STYLE = 111 self.ID_APPLY_PROPERTY = 112 self.ID_DOC_MARGIN_WIDTH = 113 self.ID_FILE_BROWSE_CUR_DIR = 114 self.ID_DOC_CARET_WIDTH = 1235 self.ID_PROMPT_CARET_WIDTH = 1237 self.ID_LONGLINE_COL = 116 self.ID_ICON_SIZE = 350 self.ID_PROMPT_STYLE = 1140 self.ID_PROMPT_MARGIN_WIDTH = 115 self.ID_PROMPT_TEXT_TYPE = 117 self.ID_PROMPT_APPLY_PROPERTY = 118 self.ID_CLASS_BROWSER_STYLE = 201 self.ID_BOOKMARKS_STYLE = 202 self.ID_DRSCRIPT_STYLE = 203 self.ID_DRSCRIPT_BROWSE = 211 self.ID_PLUGINS_BROWSE = 212 self.ID_PRINT_TAB_WIDTH = 251 self.ID_DOCUMENTATION_BROWSE = 231 self.ID_DOCUMENTATION_BROWSE_P = 232 self.ID_DOCUMENTATION_BROWSE_W = 233 self.ID_DOCUMENTATION_BROWSE_R = 234 self.ID_TXT_RECENT_FILES = 301 self.ID_TXT_TAB_WIDTH = 302 self.ID_USE_TABS = 303 self.ID_RESET_PANEL = 405 self.ID_LB_PREFS = 505 self.ID_EXPORT_PREFS = 501 self.ID_IMPORT_PREFS = 502 self.ID_BTN_WILDCARD = 510 self.ID_BTN_LNK_REPLACE_TABLE = 511 self.prefs = drPreferences(parent.PLATFORM_IS_WIN, parent.programdirectory) self.prefs.Copy(parent.prefs) self.oldprefs = drPreferences(parent.PLATFORM_IS_WIN, parent.programdirectory) self.oldprefs.Copy(parent.prefs) self.lbPrefs = drPrefsBook(self, self.ID_LB_PREFS, (600, 400)) self.pnlGeneral = GeneralPanel(self.lbPrefs, -1, "General") self.pnlBookmarks = BookmarksPanel(self.lbPrefs, -1, "Bookmarks") self.pnlDocument = DocumentPanel(self.lbPrefs, -1, "Document") self.pnlDocumentation = DocumentationPanel(self.lbPrefs, -1, "Documentation") self.pnlDragAndDrop = DragAndDropPanel(self.lbPrefs, -1, "Drag and Drop") self.pnlDrScript = DrScriptPanel(self.lbPrefs, -1, "DrScript") self.pnlFileDialog = FileDialogPanel(self.lbPrefs, -1, "File Dialog") self.pnlFileTypes = FileTypesPanel(self.lbPrefs, -1, "File Types") self.pnlFindReplace = FindReplacePanel(self.lbPrefs, -1, "Find/Replace") self.pnlPlugins = PluginsPanel(self.lbPrefs, -1, "Plugins") self.pnlPrint = PrintPanel(self.lbPrefs, -1, "Printing") self.pnlPrompt = PromptPanel(self.lbPrefs, -1, "Prompt") self.pnlSidePanels = SidePanelPanel(self.lbPrefs, -1, "Side Panels") self.pnlSourceBrowser = SourceBrowserPanel(self.lbPrefs, -1, "Source Browser") self.lbPrefs.AddPage(self.pnlGeneral, "General") self.lbPrefs.AddPage(self.pnlBookmarks, "Bookmarks") self.lbPrefs.AddPage(self.pnlDocument, "Document") self.lbPrefs.AddPage(self.pnlDocumentation, "Documentation") self.lbPrefs.AddPage(self.pnlDragAndDrop, "Drag And Drop") self.lbPrefs.AddPage(self.pnlDrScript, "DrScript") self.lbPrefs.AddPage(self.pnlFileDialog, "File Dialog") self.lbPrefs.AddPage(self.pnlFileTypes, "File Types") self.lbPrefs.AddPage(self.pnlFindReplace, "Find/Replace") self.lbPrefs.AddPage(self.pnlPlugins, "Plugins") self.lbPrefs.AddPage(self.pnlPrint, "Printing") self.lbPrefs.AddPage(self.pnlPrompt, "Prompt") self.lbPrefs.AddPage(self.pnlSidePanels, "Side Panels") self.lbPrefs.AddPage(self.pnlSourceBrowser, "Source Browser") self.lbPrefs.ShowPanel(parent.prefdialogposition) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.buttonSizer = wx.BoxSizer(wx.HORIZONTAL) self.btnClose = wx.Button(self, self.ID_CLOSE, " &Close ") self.btnClose.SetDefault() self.btnHelp = wx.Button(self, self.ID_HELP, " &Help ") self.btnReset = wx.Button(self, self.ID_RESET, " &Reset All ") self.btnUpdate = wx.Button(self, self.ID_UPDATE, " &Update ") self.btnSave = wx.Button(self, self.ID_SAVE, " &Save ") self.buttonSizer.Add(self.btnClose, 0, wx.ALL|wx.EXPAND, 4) self.buttonSizer.Add(self.btnHelp, 0, wx.ALL|wx.EXPAND, 4) self.buttonSizer.Add(self.btnReset, 0, wx.ALL|wx.EXPAND, 4) self.buttonSizer.Add(self.btnUpdate, 0, wx.ALL|wx.EXPAND, 4) self.buttonSizer.Add(self.btnSave, 0, wx.ALL|wx.EXPAND, 4) #self.theSizer.Add(self.lbPrefs, 1, wx.ALL|wx.EXPAND,4) #if border is used, the right scrollbar doesn't show entirely (!) self.theSizer.Add(self.lbPrefs, 1, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.buttonSizer, 0, wx.SHAPED | wx.ALIGN_CENTER) self.SetAutoLayout(True) self.SetSizer(self.theSizer) self.Bind(wx.EVT_BUTTON, self.OnbtnClose, id=self.ID_CLOSE) self.Bind(wx.EVT_BUTTON, self.OnbtnHelp, id=self.ID_HELP) self.Bind(wx.EVT_BUTTON, self.OnbtnReset, id=self.ID_RESET) self.Bind(wx.EVT_BUTTON, self.OnbtnUpdate, id=self.ID_UPDATE) self.Bind(wx.EVT_BUTTON, self.OnbtnSave, id=self.ID_SAVE) parent.LoadDialogSizeAndPosition(self, 'preferencesdialog.sizeandposition.dat') if parent.PLATFORM_IS_GTK: #does not get initially the focus (bug tracker #1903778, "Open Imported Module: focus problem", 29.02.2008: from Jon White, thanks. self.SetFocus() def OnCloseW(self, event): self.parent.SaveDialogSizeAndPosition(self, 'preferencesdialog.sizeandposition.dat') if event is not None: event.Skip() def OnbtnClose(self, event): self.OnCloseW(None) self.EndModal(0) def OnbtnHelp(self, event): self.parent.ViewURLInBrowser(self.parent.programdirectory + "/documentation/preferences.html") def OnbtnReset(self, event): answer = wx.MessageBox("This will reset all preferences to the program default.\n(You still need to click update and/or save)\nAre you sure you want to do this?", "Reset Preferences", wx.YES_NO | wx.ICON_QUESTION) if answer == wx.YES: self.prefs.reset() self.pnlSourceBrowser.reset() self.pnlDocument.reset() self.pnlDocumentation.reset() self.pnlDrScript.reset() self.pnlFindReplace.reset() self.pnlFileTypes.reset() self.pnlGeneral.reset() self.pnlPlugins.reset() self.pnlPrint.reset() self.pnlPrompt.reset() self.pnlSidePanels.reset() def OnbtnResetPanel(self, event): answer = wx.MessageBox("This will reset all of this panel's preferences to the program default.\n\ (You still need to click update and/or save)\nAre you sure you want to do this?", "Reset Panel Preferences", wx.YES_NO | wx.ICON_QUESTION) if answer == wx.YES: panel = event.GetEventObject().GetParent() self.prefs.resetjust(panel.GetName()) panel.reset() def OnbtnUpdate(self, event): self.parent.prefs = self.GetPreferences() self.parent.updatePrefs(self.oldprefs) self.oldprefs.Copy(self.prefs) if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, ("Succesfully updated the current instance of DrPython.\nClick Save to make it permanent."), "Updated Preferences") def OnbtnSave(self, event): self.parent.prefs = self.GetPreferences() self.parent.WriteUserPreferencesDirectoryFile() if not os.path.exists(self.parent.preferencesdirectory): drScrolledMessageDialog.ShowMessage(self, "Your userpreferencesdirectory '" + self.parent.preferencesdirectory + "' does not exist.", "DrPython Error") return preffile = self.parent.prefsfile try: drPrefsFile.WritePreferences(self.GetPreferences(), preffile) except IOError: drScrolledMessageDialog.ShowMessage(self, "There were some problems writing to:\n" + preffile, "Write Error") return self.parent.updatePrefs(self.oldprefs) self.oldprefs.Copy(self.prefs) if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, ("Succesfully wrote to:\n" + preffile + "\nand updated the current instance of DrPython."), "Saved Preferences") def GetPreferences(self): #General self.prefs.rememberwindowsizeandposition = int(self.pnlGeneral.chkrememberwindowsizeandposition.GetValue()) self.prefs.rememberdialogsizesandpositions = int(self.pnlGeneral.chkrememberdialogsizesandpositions.GetValue()) self.prefs.rememberpanelsizes = int(self.pnlGeneral.chkrememberpanelsizes.GetValue()) self.prefs.autodetectencoding = int(self.pnlGeneral.chkautodetectencoding.GetValue()) self.prefs.defaultencoding = self.pnlGeneral.cboEncoding.GetValue() self.prefs.saveonrun = int(self.pnlGeneral.chksaveonrun.GetValue()) self.prefs.checksyntaxonsave = int(self.pnlGeneral.chkchecksyntaxonsave.GetValue()) self.prefs.checksyntaxextensions = self.pnlGeneral.txtchecksyntaxextensions.GetValue() self.prefs.promptonsaveall = int(self.pnlGeneral.chkpromptonsaveall.GetValue()) self.prefs.doubleclicktoclosetab = int(self.pnlGeneral.chkdoubleclicktoclosetab.GetValue()) self.prefs.recentfileslimit = self.pnlGeneral.txtRecentFiles.GetValue() if not self.prefs.recentfileslimit: self.prefs.recentfileslimit = self.oldprefs.recentfileslimit self.prefs.recentfileslimit = int(self.prefs.recentfileslimit) self.prefs.iconsize = int(self.pnlGeneral.boxiconsize.GetStringSelection()) self.prefs.pythonargs = self.pnlGeneral.txtpythonargs.GetValue() self.parent.preferencesdirectory = self.pnlGeneral.txtdefaultuserprefsdirectory.GetValue().replace('\\', '/') self.prefs.defaultdirectory = self.pnlGeneral.txtdefaultcurdirdirectory.GetValue().replace('\\', '/') #Plugins self.prefs.pluginsdirectory = self.pnlPlugins.txtdefaultdirectory.GetValue().replace('\\', '/') #DrScript self.prefs.drscriptsdirectory = self.pnlDrScript.txtdefaultdirectory.GetValue().replace('\\', '/') self.parent.SetDrPythonDirectories() self.prefs.drscriptloadexamples = int(self.pnlDrScript.chkloadexamples.GetValue()) self.prefs.enablefeedback = int(self.pnlGeneral.chkenablefeedback.GetValue()) self.prefs.debugmodus = wx.GetApp().debugmodus = int(self.pnlGeneral.chkdebugmodus.GetValue()) self.prefs.alwayspromptonexit = int(self.pnlGeneral.chkalwayspromptonexit.GetValue()) self.prefs.backupfileonsave = int(self.pnlGeneral.chkbackupfileonsave.GetValue()) self.prefs.checkindentation = int(self.pnlGeneral.chkcheckindentation.GetValue()) self.prefs.checkeol = int(self.pnlGeneral.chkCheckFormat.GetValue()) self.prefs.vieweol = int(self.pnlGeneral.chkvieweol.GetValue()) #Drag and Drop self.prefs.draganddropmode = self.pnlDragAndDrop.raddraganddropmode.GetSelection() self.prefs.draganddroptextmode = self.pnlDragAndDrop.raddraganddroptextmode.GetSelection() #File Types: self.prefs.extensions = self.pnlFileTypes.extensions.copy() self.prefs.docusetabs = self.pnlFileTypes.docusetabs.copy() self.prefs.docuseintellibackspace = self.pnlFileTypes.docuseintellibackspace.copy() self.prefs.docremovetrailingwhitespace= self.pnlFileTypes.docremovetrailingwhitespace.copy() self.prefs.doctabwidth = self.pnlFileTypes.doctabwidth.copy() self.prefs.doceolmode = self.pnlFileTypes.doceolmode.copy() self.prefs.docfolding = self.pnlFileTypes.docfolding.copy() self.prefs.doccommentstring = self.pnlFileTypes.doccommentstring.copy() self.prefs.docwordwrap = self.pnlFileTypes.docwordwrap.copy() #File Dialog self.prefs.usewxfiledialog = int(self.pnlFileDialog.chkusewxfiledialog.GetValue()) self.prefs.defaultextension = int(self.pnlFileDialog.chkdefaultextension.GetValue()) #Document self.prefs.docshowlinenumbers = int(self.pnlDocument.chkdocshowlinenumbers.GetValue()) self.prefs.docparenthesismatching = int(self.pnlDocument.chkdocparenthesismatching.GetValue()) self.prefs.docupdateindentation = int(self.pnlDocument.chkdocupdateindentation.GetValue()) self.prefs.docautoindent = self.pnlDocument.raddocautoindent.GetSelection() #self.prefs.docremovetrailingwhitespace = int(self.pnlDocument.chkdocremovetrailingwhitespace.GetValue()) self.prefs.docautoreload = int(self.pnlDocument.chkdocautoreload.GetValue()) self.prefs.docusefileindentation = int(self.pnlDocument.chkdocusefileindentation.GetValue()) self.prefs.docwhitespaceisvisible = int(self.pnlDocument.chkWhitespace.GetValue()) self.prefs.docusestyles = self.pnlDocument.radusestyles.GetSelection() self.prefs.docuseindentationguides = int(self.pnlDocument.chkuseindentationguides.GetValue()) self.prefs.doccommentmode = self.pnlDocument.raddoccommentmode.GetSelection() self.prefs.doccaretwidth = self.pnlDocument.txtcaretwidth.GetValue() if not self.prefs.doccaretwidth: self.prefs.doccaretwidth = self.oldprefs.doccaretwidth self.prefs.doccaretwidth = int(self.prefs.doccaretwidth) self.prefs.dochighlightcurrentline = int(self.pnlDocument.chkhighlightcurrentline.GetValue()) self.prefs.docignorectrlpageupdown = int(self.pnlDocument.chkignorectrlpageupdown.GetValue()) #Chris McDonough (I added the txt prefix) self.prefs.doclonglinecol = self.pnlDocument.txtdoclonglinecol.GetValue() if not self.prefs.doclonglinecol: self.prefs.doclonglinecol = self.oldprefs.doclonglinecol self.prefs.doclonglinecol = int(self.prefs.doclonglinecol) #/Chris McDonough self.prefs.docscrollextrapage = int(self.pnlDocument.chkscrollextrapage.GetValue()) self.prefs.docdefaultsyntaxhighlighting = self.pnlDocument.boxdefaultsyntaxhighlighting.GetSelection() self.prefs.doconlyusedefaultsyntaxhighlighting = self.pnlDocument.chkonlyusedefaultsyntaxhighlighting.GetValue() #Prompt self.prefs.prompttabwidth = self.pnlPrompt.txttabwidth.GetValue() if not self.prefs.prompttabwidth: self.prefs.prompttabwidth = self.oldprefs.prompttabwidth self.prefs.prompttabwidth = int(self.prefs.prompttabwidth) self.prefs.prompteolmode = self.pnlPrompt.radFormat.GetSelection() self.prefs.promptmarginwidth = self.pnlPrompt.txtmarginwidth.GetValue() if not self.prefs.promptmarginwidth: self.prefs.promptmarginwidth = self.oldprefs.promptmarginwidth self.prefs.promptmarginwidth = int(self.prefs.promptmarginwidth) self.prefs.promptusetabs = int(self.pnlPrompt.chkpromptusetabs.GetValue()) self.prefs.promptisvisible = int(self.pnlPrompt.chkVisible.GetValue()) self.prefs.promptsize = int(self.pnlPrompt.sldrSize.GetValue()) self.prefs.promptwordwrap = int(self.pnlPrompt.chkwordwrap.GetValue()) self.prefs.promptcaretwidth = self.pnlPrompt.txtcaretwidth.GetValue() if not self.prefs.promptcaretwidth: self.prefs.promptcaretwidth = self.oldprefs.promptcaretwidth self.prefs.promptcaretwidth = int(self.prefs.promptcaretwidth) self.prefs.promptwhitespaceisvisible = int(self.pnlPrompt.chkWhitespace.GetValue()) self.prefs.promptusestyles = self.pnlPrompt.radusestyles.GetSelection() self.prefs.promptscrollextrapage = int(self.pnlPrompt.chkscrollextrapage.GetValue()) self.prefs.promptstartupscript = self.pnlPrompt.txtStartupScript.GetValue() #Find/Replace self.prefs.findreplaceregularexpression = int(self.pnlFindReplace.chkregularexpression.GetValue()) self.prefs.findreplacematchcase = int(self.pnlFindReplace.chkmatchcase.GetValue()) self.prefs.findreplacefindbackwards = int(self.pnlFindReplace.chkfindbackwards.GetValue()) self.prefs.findreplacewholeword = int(self.pnlFindReplace.chkwholeword.GetValue()) self.prefs.findreplaceinselection = int(self.pnlFindReplace.chkinselection.GetValue()) self.prefs.findreplacefromcursor = int(self.pnlFindReplace.chkfromcursor.GetValue()) self.prefs.findreplacepromptonreplace = int(self.pnlFindReplace.chkpromptonreplace.GetValue()) self.prefs.findreplaceautowrap = int(self.pnlFindReplace.chkfindreplaceautowrap.GetValue()) self.prefs.findreplaceundercursor = int(self.pnlFindReplace.chkundercursor.GetValue()) #Side Panels self.prefs.sidepanelleftsize = int(self.pnlSidePanels.sldrSizeLeft.GetValue()) self.prefs.sidepanelrightsize = int(self.pnlSidePanels.sldrSizeRight.GetValue()) self.prefs.sidepaneltopsize = int(self.pnlSidePanels.sldrSizeTop.GetValue()) #Source Browser self.prefs.sourcebrowserpanel = self.pnlSourceBrowser.positionchooser.GetSelection() self.prefs.sourcebrowsersize = self.pnlSourceBrowser.sldrSize.GetValue() self.prefs.sourcebrowserisvisible = int(self.pnlSourceBrowser.chkIsVisible.GetValue()) self.prefs.sourcebrowsercloseonactivate = int(self.pnlSourceBrowser.chkcloseonactivate.GetValue()) self.prefs.sourcebrowserissorted = int(self.pnlSourceBrowser.chkissorted.GetValue()) self.prefs.sourcebrowserautorefreshonsave = int(self.pnlSourceBrowser.chkautorefreshonsave.GetValue()) self.prefs.sourcebrowserautorefresh = int(self.pnlSourceBrowser.chkautorefresh.GetValue()) self.prefs.sourcebrowseruseimages = int(self.pnlSourceBrowser.chkuseimages.GetValue()) #Printing self.prefs.printdoclinenumbers = int(self.pnlPrint.chkdoclinenumbers.GetValue()) self.prefs.printpromptlinenumbers = int(self.pnlPrint.chkpromptlinenumbers.GetValue()) self.prefs.printtabwidth = self.pnlPrint.txttabwidth.GetValue() if not self.prefs.printtabwidth: self.prefs.printtabwidth = self.oldprefs.printtabwidth self.prefs.printtabwidth = int(self.prefs.printtabwidth) #Documentation self.prefs.documentationbrowser = self.pnlDocumentation.txtbrowser.GetValue() self.prefs.documentationpythonlocation = self.pnlDocumentation.txtpython.GetValue() self.prefs.documentationwxwidgetslocation = self.pnlDocumentation.txtwxwidgets.GetValue() self.prefs.documentationrehowtolocation = self.pnlDocumentation.txtrehowto.GetValue() if self.prefs.defaultencoding: reload(sys) #this is needed because of wine and linux sys.setdefaultencoding(self.prefs.defaultencoding) wx.SetDefaultPyEncoding(str(self.prefs.defaultencoding)) #sys.setappdefaultencoding(self.prefs.defaultencoding) return self.prefs drpython-3.11.1/Notes.txt0000644000175000017500000002055211232063333016103 0ustar dktrkranzdktrkranz----------------------------------------------------- (since DrPython 1.63) (FS) ... Franz Steinhauesler (AB) ... Antonio Barbosa ----------------------------------------------------- When Updating to wxPython 2.8 your previous stored shortcuts may not work anymore. ----------------------------------------------------- For that Antonio has written a shortcuts update script located in tools/convert_drkeys.py ----------------------------------------------------- Changed file and directory structure in DrPyhton 1.65. ----------------------------------------------------- Example for users switched from DrPython 1.64 and before to 1.65: Please copy your files, that it fits your personal directories. A example is shown below: : preferences.dat drscript.dat default.idx /dat recent_files.log findreplacedialog.sizeandposition.dat filedialog.sizeandposition.dat drpython.panel.sizes.dat drpython.sizeandposition.dat preferencesdialog.sizeandposition.dat shortcutsdialog.sizeandposition.dat plugindialog.sizeandposition.dat dynamicdrscriptdialog.sizeandposition.dat openimportedmoduledialog.sizeandposition.dat popupmenudialog.sizeandposition.dat popupmenu.dat drscriptdialog.sizeandposition.dat bookmarksdialog.sizeandposition.dat bookmarks.dat toolbardialog.sizeandposition.dat toolbar.dat toolbar.custom.icons.dat .separator.favorite.colours.dat documentation.bookmarks.dat windowsize.dat /shortcuts stcshortcuts.dat shortcuts.dat drscript.shortcuts.dat /plugins default.idx /plugins/preferences SearchInFiles.preferences.dat Sessions.preferences.dat CodeMarksPlus.preferences.dat CodeCompletion.preferences.dat CleanUpFile.preferences.dat Pycheck.preferences.dat FindAutoComplete.preferences.dat CopyCutPasteExtend.preferences.dat CTags.preferences.dat ToDoList.preferences.dat abbreviations.preferences.dat DocList.preferences.dat CTags.preferences_company.dat CTags.preferences_home.dat FindFiles.preferences.dat FindAll.preferences.dat keyboardmacros.preferences.dat /plugins/shortcuts FindAutoComplete.shortcuts.dat FindFiles.shortcuts.dat FullScreen.shortcuts.dat GetLine.shortcuts.dat IncrementalSearch.shortcuts.dat InsertMenu.shortcuts.dat KeyBoardMacros.shortcuts.dat ListShortCuts.shortcuts.dat myProject.shortcuts.dat PositionMarker.shortcuts.dat PyCheckerSupport.shortcuts.dat QuickMarker.shortcuts.dat RedirectOutput.shortcuts.dat RunFromBuffer.shortcuts.dat RunTab1.shortcuts.dat ScrollFunctions.shortcuts.dat SearchInFiles.shortcuts.dat SessionsLight.shortcuts.dat ShellMenu.shortcuts.dat ShowLineinBrowser.shortcuts.dat Switcheroo.shortcuts.dat TracebackMenu.shortcuts.dat Abbreviations.shortcuts.dat Bombs.shortcuts.dat ChopMenu.shortcuts.dat CleanUpFile.shortcuts.dat CodeCompletion.shortcuts.dat CodemarksPlus.shortcuts.dat CompWord.shortcuts.dat CopyCutPasteExtend.shortcuts.dat CTags.shortcuts.dat DocList.shortcuts.dat EpyDoc.shortcuts.dat FindAll.shortcuts.dat /plugins/dat MultiClip.log SearchInFilesHistory.log searchinfiles.viewstcsizepos.dat FindFilesHistory.log searchinfiles.sizeposcolumn.dat FindFilesSavedFiles.log recent_sessions.log myproject.log DocList.sizepos.dat FindFiles.sizepos.dat /plugins/dat/SessionsLight recent_sessions.log LastSession.ses myzuhause.dsf pycrust.dsf Default.dsf /plugins/dat/abbreviations abbreviations.txt ----------------------------------------------------------- plugins (sorted by creators): Daniel (first), enhanced by Franz: - SearchInFiles: ok...linux...ok (5,4, 11) Daniel: - CodeCompletion:........................ok...linux...ok (7) - DocumentationBookmarksMenu:............ok...linux...ok - FindAll:...............................ok...linux...ok (1) - FullScreen:............................ok...linux...ok - InsertMenu:............................ok...linux...ok - RedirectOutput:........................ok...linux...ok - RunFromBuffer:.........................ok...linux...ok (2) - ShellMenu:............................ ok...linux...ok - Switcheroo:............................ok...linux...ok - TracebackMenu:.........................ok...linux...ok Franz: - Abbreviations:.........................ok...linux...ok - AutoSave:..............................ok...linux...ok - Bombs:.................................ok...linux...ok (9) - CleanUpFile:...........................ok...linux...ok - CompWord:..............................ok...linux...ok - CopyCutPasteExtend:....................ok...linux...ok - CTags:.................................ok...linux...ok - DocList:...............................ok...linux...ok (4) - FindAutoComplete:......................ok...linux...ok (4) (10) - FindFiles:.............................ok...linux...ok (4) - GetLine:...............................ok...linux...ok - IncrementalSearch:.....................ok...linux...ok - KeyBoardMacros:........................ok...linux...ok (8) - ListShortCuts:.........................ok...linux...ok - PositionMarker:........................ok...linux...ok - QuickMarker:...........................ok...linux...ok - ScrollFunctions:.......................ok...linux...ok - SessionsLight:.........................ok...linux...ok - Startup:...............................ok...linux...ok Antonio: - CodeMarksPlus:.........................ok...linux...ok - EpyDoc:................................ok.. Linux...(3) - myProject:.............................ok...linux...ok - RunTab1:...............................ok...linux...ok - ShowLineinBrowser:.....................ok...linux...ok other authors: - bikeplugin:............................ok...linux...ok - PyCheckerSupport:......................ok...linux...ok - ToDoList:..............................ok...linux...ok (6) more plugins: abandoned pugins and therefore hidden on sourceforge: - Codemarks: (will be replaced by CodeMarksPlus) - Sessions: (will be replaced by SessionsLight) - ChopMenu: (Dan already remove it); there are the functions in stc "Delete Line Left" and "Delete Line Right". - ThemeMenu: (outdated, could be "reanimated" probably) - SimpleDebugger: (outdated, could be "reanimated" probably) NOTES: (1) Worked ok but results were truncated. Now shows entire line. Seen on Linux: the marked line is sometimes to long, it reaches up to the next line. (2) RunFromBuffer saves script in a temp file. (3) There are some differences on epydoc in linux. May be diferent versions (s?) (4) could be improved by emulating windows behaviour on gtk with keystrokes (listctrl, listbox, combobox) (5) almost ok sporadical errors (pydeadobject, list index out of range; on linux, only every second time (6) should update itself, when changing the current document (7) should or could improved enormous (like pycrust's autocomplete for instance) (8) only when started automatically (must be in default.idx and if Sessionslight is also loaded, it should be registered in default.idx BEFORE SessionsLight). (9) some funny rest of background and little graphics bugs (also redraw problem(?)). (10) doesn not work as expected (on windows, no problem) EVT_TEXT is fired 2 or more times. It should be somehow suppressed (ask in the mailing list)? should be fixed now (11) some problems on linux, but not easy to duplicate. additional notes: many other differences. I (FS) created for that a wiki page in wxPyhton wiki. (Differences gtk...) for example also ComboBox.SetBackgroundColor is not working... drscrips: =========================================================================================================== ----------------------------------------------------- Next one... (to be continued) ----------------------------------------------------- drpython-3.11.1/drPluginDialog.py0000644000175000017500000017314711150445515017546 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Plugins Dialog import os, shutil, zipfile, tempfile, urllib, thread, sys import wx, wx.wizard, wx.lib.dialogs, wx.html, wx.lib.newevent import drScrolledMessageDialog import drFileDialog from drPrefsFile import ExtractPreferenceFromText #******************************************************************************* #Update Plugin List Dialog (UpdatePluginDialog, EVT_UPDATE_PLUGINDIALOG) = wx.lib.newevent.NewEvent() class drUpdatePluginListDialog(wx.Dialog): def __init__(self, parent): wx.Dialog.__init__(self, parent, -1, "Updating Plugin List", wx.DefaultPosition, wx.Size(300, 200), wx.DEFAULT_DIALOG_STYLE) self.parent = parent.parent self.stxtDownload = wx.StaticText(self, -1, "Downloading...") self.txtStatus = wx.TextCtrl(self, -1, '', size=(250, -1), style=wx.TE_READONLY) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.theSizer.Add(self.stxtDownload, 0, wx.EXPAND) self.theSizer.Add(self.txtStatus, 1, wx.EXPAND) self.SetAutoLayout(True) self.SetSizerAndFit(self.theSizer) self.Bind(EVT_UPDATE_PLUGINDIALOG, self.UpdateUI) self.error = False thread.start_new_thread(self.RunInThread, ()) def RunInThread(self): self.error = False wx.PostEvent(self, UpdatePluginDialog(status = 'Plugin List: Connecting...')) targetfile = self.parent.ancestor.pluginsdirectory + "/drpython.plugin.list.dat" try: u = urllib.urlopen('http://drpython.sourceforge.net/cgi-bin/GetPluginList.py') result = 'Philosophia' data = '' x = 0 while len(result) > 0: result = u.read(1) if (x % 1024) == 0: wx.PostEvent(self, UpdatePluginDialog(status = 'Plugin List: ' + str(x / 1024) + 'kb Read')) x += 1 if result: data += result u.close() except: self.error = True wx.PostEvent(self, UpdatePluginDialog(status = 'Plugin List: Error')) return if data.find('') != 0: self.error = True wx.PostEvent(self, UpdatePluginDialog(status = 'Plugin List: Error')) return try: f = file(targetfile, 'wb') f.write(data) f.close() except: self.error = True wx.PostEvent(self, UpdatePluginDialog(status = 'Plugin List: Error')) return wx.PostEvent(self, UpdatePluginDialog(status = 'Plugin List: Done.')) self.EndModal(0) def UpdateUI(self, event): self.txtStatus.SetValue(event.status) if self.error: errormessage = '''Error Downloading Plugin List From Selected Mirror. If you proceed, DrPython will use the copy which came with this version of the core program. This copy may be out of date. Please try a different mirror.''' drScrolledMessageDialog.ShowMessage(self, errormessage, 'Plugin List Error') self.EndModal(0) #******************************************************************************* #Select Plugins Dialog class drSelectPluginsDialog(wx.Dialog): def __init__(self, parent): wx.Dialog.__init__(self, parent, -1, "Select DrPython Plugin", wx.DefaultPosition, wx.Size(600, 400), wx.DEFAULT_DIALOG_STYLE) ID_CANCEL = 1 ID_OK = 2 ID_PLUGINS = 3 ID_SEARCH = 4 ID_CLEAR = 5 self.Plugins = [] self.parent = parent #Local For Test self.pluginlistfile = parent.pluginsdirectory + "/drpython.plugin.list.dat" if not os.path.exists(self.pluginlistfile): self.pluginlistfile = parent.programdirectory + "/drpython.plugin.list.dat" self.txtSearch = wx.TextCtrl(self, -1, '', size=(150, -1), style=wx.TE_PROCESS_ENTER) self.choType = wx.Choice(self, -1, choices=['Keyword', 'Title', 'Author', 'Description']) self.chkCaseSensitive = wx.CheckBox(self, -1, 'Case Sensitive') self.btnSearch = wx.Button(self, ID_SEARCH, 'Search') self.btnClear = wx.Button(self, ID_CLEAR, 'Clear') self.choType.SetSelection(0) self.lstPlugins = wx.CheckListBox(self, ID_PLUGINS, size=(300, 300)) self.htmlData = wx.html.HtmlWindow(self, size=(300, 300)) self.btnCancel = wx.Button(self, ID_CANCEL, " &Cancel ") self.btnOk = wx.Button(self, ID_OK, " &Ok ") self.theSizer = wx.BoxSizer(wx.VERTICAL) self.mainSizer = wx.FlexGridSizer(3, 2, 10, 10) self.searchSizer = wx.BoxSizer(wx.HORIZONTAL) self.searchSizer.Add(self.txtSearch, 1, wx.EXPAND) self.searchSizer.Add(self.choType, 0, wx.SHAPED) self.searchSizer.Add(self.chkCaseSensitive, 0, wx.SHAPED) self.searchSizer.Add(self.btnSearch, 0, wx.SHAPED) self.searchSizer.Add(self.btnClear, 0, wx.SHAPED) self.mainSizer.Add(self.lstPlugins, 0, wx.SHAPED) self.mainSizer.Add(self.htmlData, 0, wx.SHAPED) self.mainSizer.Add(self.btnCancel, 0, wx.SHAPED) self.mainSizer.Add(self.btnOk, 0, wx.SHAPED | wx.ALIGN_RIGHT) self.theSizer.Add(self.searchSizer, 0, wx.EXPAND) self.theSizer.Add(self.mainSizer, 0, wx.EXPAND) self.SetAutoLayout(True) self.SetSizerAndFit(self.theSizer) self.ReadPluginList() self.Bind(wx.EVT_LISTBOX, self.OnSelectPlugin, id=ID_PLUGINS) self.Bind(wx.EVT_BUTTON, self.OnbtnCancel, id=ID_CANCEL) self.Bind(wx.EVT_BUTTON, self.OnbtnOk, id=ID_OK) self.Bind(wx.EVT_BUTTON, self.OnbtnSearch, id=ID_SEARCH) self.Bind(wx.EVT_BUTTON, self.OnbtnClear, id=ID_CLEAR) self.txtSearch.Bind(wx.EVT_CHAR, self.OnChar) def GetPluginFileText(self, text): #Protects against invalid values in the plugin list file. data = '' for character in text: c = ord(character) if (c < 128) and (c >= 0): data += character return data def GetPluginData(self, pluginindex, dataindex, casesensitive): data = self.PluginDataArray[pluginindex][dataindex] if casesensitive: return data.lower() return data def GetSelectedPlugins(self): selections = [] l = self.lstPlugins.GetCount() x = 0 while x < l: if self.lstPlugins.IsChecked(x): selections.append(x) x += 1 pluginfilenames = [] for selection in selections: pluginfilenames.append(self.lstPlugins.GetString(selection) + '-' + self.PluginDataArray[selection][0] + '.zip') return pluginfilenames def OnbtnCancel(self, event): self.EndModal(wx.ID_CANCEL) def OnbtnClear(self, event): self.txtSearch.SetValue('') self.OnbtnSearch(event) def OnbtnOk(self, event): self.EndModal(wx.ID_OK) def OnbtnSearch(self, event): stext = self.txtSearch.GetValue() if not stext: self.PluginDataArrayForLST = list(self.PluginDataArray) self.lstPlugins.Set(self.Plugins) return t = self.choType.GetSelection() - 1 self.PluginDataArrayForLST = [] pluginlist = [] x = 0 casesensitive = self.chkCaseSensitive.GetValue() for plugin in self.Plugins: if self.SearchPlugin(stext, t, plugin, casesensitive): pluginlist.append(plugin) self.PluginDataArrayForLST.append(self.PluginDataArray[x]) x += 1 self.lstPlugins.Set(pluginlist) def OnChar(self, event): if event.GetKeyCode() == wx.WXK_RETURN: self.OnbtnSearch(None) event.Skip() def OnSelectPlugin(self, event): sel = self.lstPlugins.GetSelection() if sel == -1: return txt = self.lstPlugins.GetStringSelection() htmltxt = '''Name: %s

Version: %s

Author(s): %s

Description:

%s

''' % (txt, self.PluginDataArrayForLST[sel][0], self.PluginDataArrayForLST[sel][1], self.PluginDataArrayForLST[sel][2]) self.htmlData.SetPage(htmltxt) def ReadPluginList(self): try: f = file(self.pluginlistfile, 'r') text = self.GetPluginFileText(f.read()) f.close() self.Plugins = ExtractPreferenceFromText(text, 'Plugins').strip().split('\n') if not self.Plugins: drScrolledMessageDialog.ShowMessage(self, 'Corrupt Plugin List, Trying Default', 'Error') self.pluginlistfile = self.parent.programdirectory + "/drpython.plugin.list.dat" f = file(self.pluginlistfile, 'r') text = f.read() f.close() self.Plugins = ExtractPreferenceFromText(text, 'Plugins').strip().split('\n') self.PluginDataArray = [] for plugin in self.Plugins: plugintext = ExtractPreferenceFromText(text, plugin).strip() version = ExtractPreferenceFromText(plugintext, 'Version').strip() author = ExtractPreferenceFromText(plugintext, 'Author').strip() description = ExtractPreferenceFromText(plugintext, 'Description').strip() self.PluginDataArray.append([version, author, description]) self.PluginDataArrayForLST = list(self.PluginDataArray) self.lstPlugins.Set(self.Plugins) except: drScrolledMessageDialog.ShowMessage(self, 'Error Reading "' + self.pluginlistfile + '".', 'Error Reading Plugin List') def SearchPlugin(self, searchtext, type, pluginname, casesensitive): if casesensitive: if type == 0: return pluginname.find(searchtext) > -1 elif (type < 3) and (type > -1): if pluginname in self.Plugins: i = self.Plugins.index(pluginname) return self.GetPluginData(i, type, 0).find(searchtext) > -1 return False else: if pluginname.find(searchtext) > -1: return True elif pluginname in self.Plugins: i = self.Plugins.index(pluginname) if self.GetPluginData(i, 0, 0).find(searchtext) > -1: return True elif self.GetPluginData(i, 1, 0).find(searchtext) > -1: return True elif self.GetPluginData(i, 2, 0).find(searchtext) > -1: return True else: searchtext = searchtext.lower() if type == 0: return pluginname.lower().find(searchtext) > -1 elif (type < 3) and (type > -1): if pluginname in self.Plugins: i = self.Plugins.index(pluginname) return self.GetPluginData(i, type, 1).find(searchtext) > -1 return False else: if pluginname.lower().find(searchtext) > -1: return True elif pluginname in self.Plugins: i = self.Plugins.index(pluginname) if self.GetPluginData(i, 0, 1).find(searchtext) > -1: return True elif self.GetPluginData(i, 1, 1).find(searchtext) > -1: return True elif self.GetPluginData(i, 2, 1).find(searchtext) > -1: return True return False #******************************************************************************* #Install Wizard class drPluginInstallLocationPage(wx.wizard.WizardPageSimple): def __init__(self, parent): wx.wizard.WizardPageSimple.__init__(self, parent) self.parent = parent ID_LOCATION = 78 ID_MIRROR = 79 title = wx.StaticText(self, -1, "Select Location:") title.SetFont(wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)) self.radLocation = wx.RadioBox(self, ID_LOCATION, "", wx.DefaultPosition, wx.DefaultSize, ["Local", "SourceForge Mirror"], 1, wx.RA_SPECIFY_COLS | wx.NO_BORDER) mirrors = ['Bern, Switzerland (Europe)', 'Brussels, Belgium (Europe)', 'Chapel Hill, NC (North America)', 'Duesseldorf, Germany (Europe)', \ 'Dublin, Ireland (Europe)', 'Minneapolis, MN (North America)', 'New York, New York (North America)', 'Paris, France (Europe)', \ 'Phoenix, AZ (North America)', 'Reston, VA (North America)', 'SourceForge (OSDN)', 'Sydney, Australia (Australia)', 'Zurich, Switzerland (Europe)'] self.mirrorAddresses = ['http://puzzle.dl.sourceforge.net/', 'http://belnet.dl.sourceforge.net/', 'http://unc.dl.sourceforge.net/', 'http://mesh.dl.sourceforge.net/', \ 'http://heanet.dl.sourceforge.net/', 'http://umn.dl.sourceforge.net/', 'http://voxel.dl.sourceforge.net/', 'http://ovh.dl.sourceforge.net/', \ 'http://easynews.dl.sourceforge.net/sourceforge/', 'http://aleron.dl.sourceforge.net/', 'http://osdn.dl.sourceforge.net/', 'http://optusnet.dl.sourceforge.net/', 'http://switch.dl.sourceforge.net/'] self.lstMirrors = wx.ListBox(self, ID_MIRROR, size=(300, 300), choices=mirrors) self.lstMirrors.SetSelection(0) self.lstMirrors.Enable(False) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.theSizer.Add(title, 0, wx.SHAPED) self.theSizer.Add(self.radLocation, 0, wx.SHAPED) self.theSizer.Add(self.lstMirrors, 0, wx.SHAPED) self.SetAutoLayout(True) self.SetSizer(self.theSizer) self.Bind(wx.EVT_RADIOBOX, self.OnLocationChanged, id=ID_LOCATION) self.Bind(wx.EVT_LISTBOX, self.OnMirrorChanged, id=ID_MIRROR) def OnLocationChanged(self, event): isSF = self.radLocation.GetSelection() self.lstMirrors.Enable(isSF) self.parent.Location = isSF if isSF: self.OnMirrorChanged(None) def OnMirrorChanged(self, event): i = self.lstMirrors.GetSelection() if i < 0: i = 0 self.parent.Mirror = self.mirrorAddresses[i] class drPluginInstallSelectPage(wx.wizard.WizardPageSimple): def __init__(self, parent): wx.wizard.WizardPageSimple.__init__(self, parent) self.parent = parent ID_ADD = 77 ID_REMOVE = 78 ID_PLUGINS = 79 title = wx.StaticText(self, -1, "Select Plugins to Install:") title.SetFont(wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)) self.btnAdd = wx.Button(self, ID_ADD, "Add") self.btnRemove = wx.Button(self, ID_REMOVE, "Remove") self.lstPlugins = wx.ListBox(self, ID_PLUGINS, size=(300, 300)) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.bSizer = wx.BoxSizer(wx.HORIZONTAL) self.bSizer.Add(self.btnAdd, 0, wx.SHAPED | wx.ALIGN_LEFT) self.bSizer.Add(self.btnRemove, 0, wx.SHAPED | wx.ALIGN_RIGHT) self.theSizer.Add(title, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.theSizer.Add(self.bSizer, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.theSizer.Add(self.lstPlugins, 0, wx.SHAPED) self.SetAutoLayout(True) self.SetSizer(self.theSizer) self.Bind(wx.EVT_BUTTON, self.OnAdd, id=ID_ADD) self.Bind(wx.EVT_BUTTON, self.OnRemove, id=ID_REMOVE) def OnAdd(self, event): if self.parent.Location: #SourceForge d = drSelectPluginsDialog(self.parent.ancestor) answer = d.ShowModal() self.Raise() self.SetFocus() if answer == wx.ID_OK: selectedplugins = d.GetSelectedPlugins() for plugin in selectedplugins: self.parent.pluginstodownload.append(self.parent.Mirror + 'sourceforge/drpython/' + plugin) labels = map(lambda x: os.path.splitext(x)[0], selectedplugins) self.parent.pluginlabels.extend(labels) self.parent.pluginsinstallmethod.extend(map(lambda x: 0, labels)) self.lstPlugins.Set(self.parent.pluginlabels) d.Destroy() else: #Local dlg = drFileDialog.FileDialog(self.parent.ancestor, "Select DrPython Plugin(s)", self.parent.wildcard, MultipleSelection=True) if self.parent.ancestor.pluginsdirectory: dlg.SetDirectory(self.parent.ancestor.pluginsdirectory) if dlg.ShowModal() == wx.ID_OK: filenames = dlg.GetPaths() filenames = map(lambda x: x.replace("\\", '/'), filenames) self.parent.pluginstoinstall.extend(filenames) labels = map(lambda x: os.path.splitext(os.path.split(x)[1])[0], filenames) self.parent.pluginlabels.extend(labels) self.parent.pluginsinstallmethod.extend(map(lambda x: 0, labels)) self.lstPlugins.Set(self.parent.pluginlabels) dlg.Destroy() def OnRemove(self, event): i = self.lstPlugins.GetSelection() if i < 0: return answer = wx.MessageBox('Remove "%s"?' % self.parent.pluginlabels[i], "Remove Plugin From List", wx.YES_NO | wx.ICON_QUESTION) if answer == wx.YES: self.parent.pluginlabels.pop(i) if self.parent.Location: self.parent.pluginstodownload.pop(i) else: self.parent.pluginstoinstall.pop(i) self.lstPlugins.Set(self.parent.pluginlabels) def Run(self): if self.parent.Location: answer = wx.MessageBox('Update Plugin List?', "Update Plugin List", wx.YES_NO | wx.ICON_QUESTION) if answer == wx.YES: e = drUpdatePluginListDialog(self) e.ShowModal() e.Destroy() #Make sure plugion labels are synced with list: self.lstPlugins.Set(self.parent.pluginlabels) (UpdateDownloadPage, EVT_UPDATE_DOWNLOADPAGE) = wx.lib.newevent.NewEvent() class drPluginInstallDownloadPage(wx.wizard.WizardPageSimple): def __init__(self, parent): wx.wizard.WizardPageSimple.__init__(self, parent) self.parent = parent self.errors = [] title = wx.StaticText(self, -1, "Getting Selected Plugins:") title.SetFont(wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)) self.stxtDownload = wx.StaticText(self, -1, "Downloading...") self.stxtUnPacking = wx.StaticText(self, -1, "UnPacking...") self.stxtDone = wx.StaticText(self, -1, "Done") self.stxtDownload.SetForegroundColour(wx.Colour(175, 175, 175)) self.stxtUnPacking.SetForegroundColour(wx.Colour(175, 175, 175)) self.stxtDone.SetForegroundColour(self.GetBackgroundColour()) self.gDownload = wx.Gauge(self, -1, 0, size=(250, -1)) self.gUnPack = wx.Gauge(self, -1, 0, size=(250, -1)) self.txtStatus = wx.TextCtrl(self, -1, '', size=(250, -1), style=wx.TE_READONLY) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.theSizer.Add(title, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.theSizer.Add(self.stxtDownload, 0, wx.SHAPED) self.theSizer.Add(self.gDownload, 0, wx.SHAPED) self.theSizer.Add(self.txtStatus, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.theSizer.Add(self.stxtUnPacking, 0, wx.SHAPED) self.theSizer.Add(self.gUnPack, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.theSizer.Add(self.stxtDone, 0, wx.SHAPED) self.SetAutoLayout(True) self.SetSizer(self.theSizer) self.Bind(EVT_UPDATE_DOWNLOADPAGE, self.UpdateUI) def CreateDirectories(self, targetdir, zippedfilename): zippedfilename = zippedfilename.replace('\\', '/') d = zippedfilename.find('/') while d > -1: dir = zippedfilename[:d] targetdir = targetdir + '/' + dir if not os.path.exists(targetdir): os.mkdir(targetdir) zippedfilename = zippedfilename[d+1:] d = zippedfilename.find('/') def Download(self, remotefile, label): try: targetfile = self.parent.tempdir + label + '.zip' wx.PostEvent(self, UpdateDownloadPage(step = 0, range = -1, value = -1, done = False, status = label + '.zip: Connecting...')) u = urllib.urlopen(remotefile) mimetype = u.info().gettype() if mimetype != 'application/zip': u.close() self.errors.append([remotefile, 'MimeType Info: "' + mimetype + '"']) return '' result = 'Philosophia' data = '' x = 0 while len(result) > 0: result = u.read(1) if (x % 1024) == 0: wx.PostEvent(self, UpdateDownloadPage(step = 0, range = -1, value = -1, done = False, status = label + '.zip: ' + str(x / 1024) + 'kb Read')) x += 1 if result: data += result u.close() f = file(targetfile, 'wb') f.write(data) f.close() return targetfile except: self.errors.append([remotefile, str(sys.exc_info()[0]).lstrip("exceptions.") + ": " + str(sys.exc_info()[1])]) return '' def Run(self): thread.start_new_thread(self.RunInThread, ()) def RunInThread(self): #Download if self.parent.Location: l = len(self.parent.pluginstodownload) x = 0 wx.PostEvent(self, UpdateDownloadPage(step = 0, range = l, value = x, done = False, status='')) self.parent.pluginstoinstall = [] while x < l: result = self.Download(self.parent.pluginstodownload[x], self.parent.pluginlabels[x]) if result: self.parent.pluginstoinstall.append(result) x = x + 1 wx.PostEvent(self, UpdateDownloadPage(step = 0, range = l, value = x, done = False, status= '')) #Update arrays based on what was downloaded self.parent.pluginlabels = map(lambda x: os.path.splitext(os.path.split(x)[1])[0], self.parent.pluginstoinstall) self.parent.pluginsinstallmethod = (map(lambda x: 0, self.parent.pluginlabels)) wx.PostEvent(self, UpdateDownloadPage(step = 0, range = l, value = x, done = True, status= '')) #UnPack l = len(self.parent.pluginstoinstall) wx.PostEvent(self, UpdateDownloadPage(step = 1, range = l, value = 0, done = False, status= '')) x = 0 while x < l: self.UnPack(self.parent.pluginstoinstall[x], self.parent.pluginlabels[x]) x = x + 1 wx.PostEvent(self, UpdateDownloadPage(step = 1, range = l, value = x, done = False, status= '')) wx.PostEvent(self, UpdateDownloadPage(step = 1, range = l, value = x, done = True, status= '')) def UnPack(self, filename, label): zf = zipfile.ZipFile(filename, 'r') dir = self.parent.tempdir + label if not os.path.exists(dir): os.mkdir(dir) zippedfiles = zf.namelist() self.parent.UnZippedFilesArray.append(zippedfiles) for zippedfile in zippedfiles: l = len(zippedfile) if (zippedfile[l-1] == '/') or (zippedfile[l-1] == '\\'): self.CreateDirectories(dir, zippedfile) else: self.CreateDirectories(dir, zippedfile) data = zf.read(zippedfile) f = file(dir + '/' + zippedfile, 'wb') f.write(data) f.close() zf.close() def UpdateUI(self, event): if event.step == 0: if event.status: self.txtStatus.SetValue(event.status) else: if not event.done: self.stxtDownload.SetForegroundColour(self.GetForegroundColour()) else: self.stxtDownload.SetForegroundColour(wx.Colour(175, 175, 175)) if event.range != self.gDownload.GetRange(): self.gDownload.SetRange(event.range) self.gDownload.SetValue(event.value) elif event.step == 1: if not event.done: self.stxtUnPacking.SetForegroundColour(self.GetForegroundColour()) else: self.stxtUnPacking.SetForegroundColour(wx.Colour(175, 175, 175)) self.stxtDone.SetForegroundColour(self.GetForegroundColour()) if event.range != self.gUnPack.GetRange(): self.gUnPack.SetRange(event.range) self.gUnPack.SetValue(event.value) self.Refresh() if self.errors: error = self.errors.pop(0) drScrolledMessageDialog.ShowMessage(self.parent, 'Error Downloading File "' + error[0] + '".\n\n' + error[1], "Error", wx.DefaultPosition, wx.Size(550,300)) class drPluginInstallIndexPage(wx.wizard.WizardPageSimple): def __init__(self, parent): wx.wizard.WizardPageSimple.__init__(self, parent) self.parent = parent title = wx.StaticText(self, -1, "Set Loading Method:") title.SetFont(wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)) self.chklLoadByDefault = wx.CheckListBox(self, 1, wx.DefaultPosition, (200, 100), self.parent.pluginlabels) self.chklLoadFromIndex = wx.CheckListBox(self, 2, wx.DefaultPosition, (200, 100), self.parent.pluginlabels) self.theSizer = wx.FlexGridSizer(6, 1, 5, 5) self.theSizer.Add(title, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, "Load By Default:"), 0, wx.EXPAND) self.theSizer.Add(self.chklLoadByDefault, 0, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, "Load From Index:"), 0, wx.EXPAND) self.theSizer.Add(self.chklLoadFromIndex, 0, wx.EXPAND) self.SetAutoLayout(True) self.SetSizer(self.theSizer) self.Bind(wx.EVT_CHECKLISTBOX, self.OnLoadByDefault, id=1) self.Bind(wx.EVT_CHECKLISTBOX, self.OnLoadFromIndex, id=2) def GetDefSel(self, IndexSel): txt = self.chklLoadFromIndex.GetString(IndexSel) return self.chklLoadByDefault.FindString(txt) def GetIdxSel(self, DefaultSel): txt = self.chklLoadByDefault.GetString(DefaultSel) return self.chklLoadFromIndex.FindString(txt) def OnLoadByDefault(self, event): sel = event.GetSelection() i = self.GetIdxSel(sel) if sel > -1: if self.chklLoadByDefault.IsChecked(sel) and (i > -1): self.parent.pluginsinstallmethod[sel] = 0 self.chklLoadFromIndex.Check(i, False) elif i > -1: if not self.chklLoadFromIndex.IsChecked(i): self.parent.pluginsinstallmethod[sel] = -1 def OnLoadFromIndex(self, event): sel = event.GetSelection() i = self.GetDefSel(sel) if sel > -1: if self.chklLoadFromIndex.IsChecked(sel) and (i > -1): self.parent.pluginsinstallmethod[i] = 1 self.chklLoadByDefault.Check(i, False) elif not self.chklLoadByDefault.IsChecked(sel) and (i > -1): self.parent.pluginsinstallmethod[i] = -1 def Run(self): if not self.parent.pluginstoinstall: return self.chklLoadByDefault.Set(self.parent.pluginlabels) indexlabels = [] x = 0 for label in self.parent.pluginlabels: pluginname = label if pluginname.find('-') > -1: pluginname = pluginname[:pluginname.find('-')] if pluginname.find('.') > -1: pluginname = pluginname[:pluginname.find('.')] for fn in self.parent.UnZippedFilesArray[x]: if fn.find(pluginname + '.idx') > -1: indexlabels.append(label) break x += 1 self.chklLoadFromIndex.Set(indexlabels) x = 0 l = len(self.parent.pluginlabels) while x < l: self.chklLoadByDefault.Check(x, True) x = x + 1 class drPluginInstallInstallPage(wx.wizard.WizardPageSimple): def __init__(self, parent): wx.wizard.WizardPageSimple.__init__(self, parent) self.parent = parent title = wx.StaticText(self, -1, "Installing Selected Plugins:") title.SetFont(wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)) self.stxtInstalling = wx.StaticText(self, -1, "Installing...") self.stxtIndexing = wx.StaticText(self, -1, "Indexing...") self.stxtDone = wx.StaticText(self, -1, "Done") self.stxtInstalling.SetForegroundColour(wx.Colour(175, 175, 175)) self.stxtIndexing.SetForegroundColour(wx.Colour(175, 175, 175)) self.stxtDone.SetForegroundColour(self.GetBackgroundColour()) self.gInstall = wx.Gauge(self, -1, 0, size=(200, -1)) self.gIndex = wx.Gauge(self, -1, 0, size=(200, -1)) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.theSizer.Add(title, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.theSizer.Add(self.stxtInstalling, 0, wx.SHAPED) self.theSizer.Add(self.gInstall, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.theSizer.Add(self.stxtIndexing, 0, wx.SHAPED) self.theSizer.Add(self.gIndex, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.theSizer.Add(self.stxtDone, 0, wx.SHAPED) self.SetAutoLayout(True) self.SetSizer(self.theSizer) def RemoveTempDir(self, tempdir): entries = os.listdir(tempdir) for entry in entries: fname = tempdir + '/' + entry if os.path.isdir(fname): self.RemoveTempDir(fname) else: os.remove(fname) os.rmdir(tempdir) def Index(self, label, unzippedfiles, installmethod): dir = self.parent.tempdir + label pluginname = label if pluginname.find('-') > -1: pluginname = pluginname[:pluginname.find('-')] if pluginname.find('.') > -1: pluginname = pluginname[:pluginname.find('.')] if installmethod == 0: #indexfile = self.parent.preferencesdirectory + "/default.idx" #AB: #print self.parent.preferencesdirectory #print self.parent.pluginsbasepreferencesdir indexfile = self.parent.GetParent().preferencesdirectory + "/default.idx" if not os.path.exists(indexfile): f = file(indexfile, 'wb') #f.write('\n') f.close() try: f = file(indexfile, 'rU') plugins = [x.strip() for x in f] f.close() f = file(indexfile, 'w') for p in plugins: if p != pluginname: f.write(p + '\n') f.write(pluginname + '\n') f.close() except: drScrolledMessageDialog.ShowMessage(self.parent, 'Error Adding Plugin "' + pluginname + '" to default.idx"', "Error", wx.DefaultPosition, wx.Size(550,300)) return elif installmethod == 1: target = pluginname + '.idx' indexfile = '' for fname in unzippedfiles: if os.path.split(fname)[1] == target: indexfile = dir + '/' + fname if not indexfile: drScrolledMessageDialog.ShowMessage(self.parent, 'Error Installing "' + label + '"', 'Install Index Error') return shutil.copyfile(indexfile, os.path.join(self.parent.pluginsdirectory , target)) def Install(self, filename, label, unzippedfiles): pluginname = label if pluginname.find('-') > -1: pluginname = pluginname[:pluginname.find('-')] if pluginname.find('.') > -1: pluginname = pluginname[:pluginname.find('.')] dir = self.parent.tempdir + label target = pluginname + '.py' pluginfile = '' for fname in unzippedfiles: if os.path.split(fname)[1] == target: pluginfile = dir + '/' + fname if not pluginfile: drScrolledMessageDialog.ShowMessage(self.parent, 'Error Installing "' + label + '"', 'Install Error') else: #Do the Install pluginrfile = os.path.join(self.parent.pluginsdirectory, target) #Install Script plugininstallfile = pluginfile + ".install" continueinstallation = True if os.path.exists(plugininstallfile): f = open(plugininstallfile, 'r') scripttext = f.read() f.close() try: code = compile((scripttext + '\n'), plugininstallfile, 'exec') except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error compiling install script."), "Error", wx.DefaultPosition, wx.Size(550,300)) return try: cwd = os.getcwd() os.chdir(dir + '/' + os.path.commonprefix(unzippedfiles)) exec(code) continueinstallation = Install(self.parent.ancestor) os.chdir(cwd) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error running install script."), "Error", wx.DefaultPosition, wx.Size(550,300)) return #/Install Script if continueinstallation: try: copyf = True if os.path.exists(pluginrfile): answer = wx.MessageBox('Overwrite"' + pluginrfile + '"?', "DrPython", wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION) if answer == wx.NO: copyf = False if copyf: shutil.copyfile(pluginfile, pluginrfile) #there could be an error check: if idx file does not exist in source, simply create one. shutil.copyfile(os.path.splitext(pluginfile)[0] + '.idx', os.path.splitext(pluginrfile)[0] + '.idx') except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error with: " + pluginfile), "Install Error") return def Run(self): l = len(self.parent.pluginstoinstall) if l < 1: self.stxtDone.SetForegroundColour(self.GetForegroundColour()) return #Install self.stxtInstalling.SetForegroundColour(self.GetForegroundColour()) self.gInstall.SetRange(l) x = 0 while x < l: self.Install(self.parent.pluginstoinstall[x], self.parent.pluginlabels[x], self.parent.UnZippedFilesArray[x]) x = x + 1 self.gInstall.SetValue(x) self.stxtInstalling.SetForegroundColour(wx.Colour(175, 175, 175)) #Index self.stxtIndexing.SetForegroundColour(self.GetForegroundColour()) self.gIndex.SetRange(l) x = 0 while x < l: self.Index(self.parent.pluginlabels[x], self.parent.UnZippedFilesArray[x], self.parent.pluginsinstallmethod[x]) x = x + 1 self.gIndex.SetValue(x) self.stxtIndexing.SetForegroundColour(wx.Colour(175, 175, 175)) #Remove All Temporary Files. for label in self.parent.pluginlabels: dir = self.parent.tempdir + label try: self.RemoveTempDir(dir) if self.parent.Location: #Remove the Downloaded File, if it exists. downloadedfile = self.parent.tempdir + label + '.zip' if os.path.exists(downloadedfile): os.remove(downloadedfile) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error removing temporary directory for: " + label), "Post Install Error") return self.stxtDone.SetForegroundColour(self.GetForegroundColour()) class drPluginInstallWizard(wx.wizard.Wizard): def __init__(self, parent, title, bitmap): wx.wizard.Wizard.__init__(self, parent, 303, title, bitmap) self.ancestor = parent self.pluginsdirectory = parent.pluginsdirectory self.wildcard = "DrPython Plugin Archive (*.zip)|*.zip" self.pluginstodownload = [] self.pluginstoinstall = [] self.pluginsinstallmethod = [] self.pluginlabels = [] self.UnZippedFilesArray = [] self.Location = 0 self.Mirror = '' try: #TempDir self.tempdir = os.path.split(tempfile.mktemp())[0].replace('\\', '/') + '/' except: drScrolledMessageDialog.ShowMessage(parent, "Error Getting Temporary Directory.", "Install Error") return self.LocationPage = drPluginInstallLocationPage(self) self.SelectPage = drPluginInstallSelectPage(self) self.DownloadPage = drPluginInstallDownloadPage(self) self.IndexPage = drPluginInstallIndexPage(self) self.InstallPage = drPluginInstallInstallPage(self) wx.wizard.WizardPageSimple_Chain(self.LocationPage, self.SelectPage) wx.wizard.WizardPageSimple_Chain(self.SelectPage, self.DownloadPage) wx.wizard.WizardPageSimple_Chain(self.DownloadPage, self.IndexPage) wx.wizard.WizardPageSimple_Chain(self.IndexPage, self.InstallPage) self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged, id=303) def OnPageChanged(self, event): cp = self.GetCurrentPage() if cp == self.SelectPage: self.SelectPage.Run() elif cp == self.DownloadPage: self.DownloadPage.Run() elif cp == self.IndexPage: self.IndexPage.Run() elif cp == self.InstallPage: self.InstallPage.Run() def Run(self): self.RunWizard(self.LocationPage) #******************************************************************************* #UnInstall Wizard class drPluginUnInstallSelectPage(wx.wizard.WizardPageSimple): def __init__(self, parent): wx.wizard.WizardPageSimple.__init__(self, parent) self.parent = parent ID_ADD = 77 ID_REMOVE = 78 ID_PLUGINS = 79 title = wx.StaticText(self, -1, "Select Plugins to UnInstall:") title.SetFont(wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)) self.btnAdd = wx.Button(self, ID_ADD, "Add") self.btnRemove = wx.Button(self, ID_REMOVE, "Remove") self.lstPlugins = wx.ListBox(self, ID_PLUGINS, size=(300, 300)) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.bSizer = wx.BoxSizer(wx.HORIZONTAL) self.bSizer.Add(self.btnAdd, 0, wx.SHAPED | wx.ALIGN_LEFT) self.bSizer.Add(self.btnRemove, 0, wx.SHAPED | wx.ALIGN_RIGHT) self.theSizer.Add(title, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.theSizer.Add(self.bSizer, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.theSizer.Add(self.lstPlugins, 0, wx.SHAPED) self.SetAutoLayout(True) self.SetSizer(self.theSizer) self.Bind(wx.EVT_BUTTON, self.OnAdd, id=ID_ADD) self.Bind(wx.EVT_BUTTON, self.OnRemove, id=ID_REMOVE) def OnAdd(self, event): plist = os.listdir(self.parent.pluginsdirectory) PluginList = [] for p in plist: i = p.find(".py") l = len(p) if i > -1 and (i + 3 == l): PluginList.append(p[:i]) PluginList.sort() d = wx.lib.dialogs.MultipleChoiceDialog(self, "Select Plugins to Remove:", "Add Plugin(s) to List", PluginList) if d.ShowModal() == wx.ID_OK: selections = d.GetValueString() self.parent.pluginstoremove.extend(selections) self.lstPlugins.Set(self.parent.pluginstoremove) d.Destroy() def OnRemove(self, event): i = self.lstPlugins.GetSelection() if i < 0: return answer = wx.MessageBox('Remove "%s"?' % self.parent.pluginstoremove[i], "Remove Plugin From List", wx.YES_NO | wx.ICON_QUESTION) if answer == wx.YES: self.parent.pluginstoremove.pop(i) self.lstPlugins.Set(self.parent.pluginstoremove) class drPluginUnInstallDataPage(wx.wizard.WizardPageSimple): def __init__(self, parent): wx.wizard.WizardPageSimple.__init__(self, parent) self.parent = parent title = wx.StaticText(self, -1, "Remove Preferences and Shortcuts?:") title.SetFont(wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)) self.chklData = wx.CheckListBox(self, 1, wx.DefaultPosition, (200, 200), self.parent.pluginstoremove) self.theSizer = wx.FlexGridSizer(3, 1, 5, 5) self.theSizer.Add(title, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.EXPAND) self.theSizer.Add(self.chklData, 0, wx.EXPAND) self.SetAutoLayout(True) self.SetSizer(self.theSizer) self.Bind(wx.EVT_CHECKLISTBOX, self.OnData, id=1) def OnData(self, event): sel = event.GetSelection() if sel > -1: self.parent.removealldataforpluginArray[sel] = self.chklData.IsChecked(sel) def Run(self): if not self.parent.pluginstoremove: return self.chklData.Set(self.parent.pluginstoremove) self.parent.removealldataforpluginArray = map(lambda x: True, self.parent.pluginstoremove) x = 0 l = len(self.parent.pluginstoremove) while x < l: self.chklData.Check(x, True) x = x + 1 class drPluginUnInstallUnInstallPage(wx.wizard.WizardPageSimple): def __init__(self, parent): wx.wizard.WizardPageSimple.__init__(self, parent) self.parent = parent title = wx.StaticText(self, -1, "UnInstalling Selected Plugins:") title.SetFont(wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)) self.stxtUnInstalling = wx.StaticText(self, -1, "UnInstalling...") self.stxtUnIndexing = wx.StaticText(self, -1, "Removing From Index Files...") self.stxtDone = wx.StaticText(self, -1, "Done") self.stxtUnInstalling.SetForegroundColour(wx.Colour(175, 175, 175)) self.stxtUnIndexing.SetForegroundColour(wx.Colour(175, 175, 175)) self.stxtDone.SetForegroundColour(self.GetBackgroundColour()) self.gUnInstall = wx.Gauge(self, -1, 0, size=(200, -1)) self.gUnIndex = wx.Gauge(self, -1, 0, size=(200, -1)) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.theSizer.Add(title, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.theSizer.Add(self.stxtUnInstalling, 0, wx.SHAPED) self.theSizer.Add(self.gUnInstall, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.theSizer.Add(self.stxtUnIndexing, 0, wx.SHAPED) self.theSizer.Add(self.gUnIndex, 0, wx.SHAPED) self.theSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.theSizer.Add(self.stxtDone, 0, wx.SHAPED) self.SetAutoLayout(True) self.SetSizer(self.theSizer) def RemoveDatFiles(self, plugin): pluginpreferencesfilebase = os.path.join(self.parent.pluginsdirectory , plugin) pluginshortcutsfilebase = os.path.join(self.parent.pluginsshortcutsdirectory, plugin) try: if os.path.exists(pluginpreferencesfilebase + '.preferences.dat'): os.remove(pluginpreferencesfilebase + '.preferences.dat') if os.path.exists(pluginshortcutsfilebase + '.shortcuts.dat'): os.remove(pluginshortcutsfilebase + '.shortcuts.dat') except: drScrolledMessageDialog.ShowMessage(self.parent, "Error Removing Plugin Preference Files", "Uninstall Error") def RemoveFromIndex(self, idx): idxfile = os.path.join(self.parent.pluginsdirectory , idx) f = file(idxfile, 'r') plugins = f.read().strip().split('\n') f.close() pluginstowrite = [] for plugin in plugins: if not (plugin in self.parent.pluginstoremove): pluginstowrite.append(plugin) if not pluginstowrite: f = file(idxfile, 'w') for plugin in pluginstowrite: f.write(plugin + '\n') f.close() else: if idx != 'default.idx': os.remove(idxfile) def Run(self): #UnInstall Plugins self.stxtUnInstalling.SetForegroundColour(self.GetForegroundColour()) self.gUnInstall.SetRange(len(self.parent.pluginstoremove)) self.gUnInstall.SetValue(0) x = 0 for plugin in self.parent.pluginstoremove: self.UnInstall(plugin) if self.parent.removealldataforpluginArray[x]: self.RemoveDatFiles(plugin) x = x + 1 self.gUnInstall.SetValue(x) self.stxtUnInstalling.SetForegroundColour(self.GetForegroundColour()) #Remove Plugins from any index files. self.stxtUnIndexing.SetForegroundColour(self.GetForegroundColour()) plist = os.listdir(self.parent.pluginsdirectory) IndexList = [] for p in plist: i = p.find(".idx") if i > -1: IndexList.append(p) self.gUnIndex.SetRange(len(IndexList)) self.gUnIndex.SetValue(0) x = 0 for idx in IndexList: try: self.RemoveFromIndex(idx) except: drScrolledMessageDialog.ShowMessage(self.parent, ('Error Removing Plugins From Index: "' + idx + '".'), "Uninstall Error") x = x + 1 self.gUnIndex.SetValue(x) self.stxtUnIndexing.SetForegroundColour(wx.Colour(175, 175, 175)) self.stxtDone.SetForegroundColour(self.GetForegroundColour()) def UnInstall(self, plugin): pluginfile = os.path.join(self.parent.pluginsdirectory, plugin) + ".py" try: continueuninstall = True try: exec(compile("import " + plugin, plugin, 'exec')) exec(compile("continueuninstall = " + plugin + ".UnInstall(self.parent.ancestor)", plugin, 'exec')) except: pass if continueuninstall: os.remove(pluginfile) if os.path.exists(pluginfile + "c"): os.remove(pluginfile + "c") if os.path.exists(pluginfile + ".bak"): os.remove(pluginfile + ".bak") except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error Removing Plugin File: " + pluginfile), "Uninstall Error") class drPluginUnInstallWizard(wx.wizard.Wizard): def __init__(self, parent, title, bitmap): wx.wizard.Wizard.__init__(self, parent, 303, title, bitmap) self.ancestor = parent self.pluginstoremove = [] self.removealldataforpluginArray = [] self.SelectPage = drPluginUnInstallSelectPage(self) self.DataPage = drPluginUnInstallDataPage(self) self.UnInstallPage = drPluginUnInstallUnInstallPage(self) wx.wizard.WizardPageSimple_Chain(self.SelectPage, self.DataPage) wx.wizard.WizardPageSimple_Chain(self.DataPage, self.UnInstallPage) self.Location = 0 self.Mirror = '' self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.OnPageChanged, id=303) def OnPageChanged(self, event): cp = self.GetCurrentPage() if cp == self.DataPage: self.DataPage.Run() elif cp == self.UnInstallPage: self.UnInstallPage.Run() def Run(self): self.RunWizard(self.SelectPage) #******************************************************************************* #Edit Indexes Dialog class drEditIndexDialog(wx.Dialog): def __init__(self, parent): wx.Dialog.__init__(self, parent, -1, "Edit Indexes", wx.DefaultPosition, wx.Size(-1, -1), wx.DEFAULT_DIALOG_STYLE | wx.THICK_FRAME) wx.Yield() self.ID_SAVE = 102 self.ID_DELETE = 103 self.ID_SAVE_AS = 104 self.ID_NEW = 105 self.ID_ADD = 1003 self.ID_REMOVE = 1004 self.ID_INDEX = 1005 self.ID_PROGRAM = 1010 self.ID_POPUP = 1011 self.ID_UP = 1111 self.ID_DOWN = 2222 plist = os.listdir(parent.pluginsdirectory) self.PluginList = [] self.IndexList = [] self.indexname = "" self.indexplugins = [] for p in plist: i = p.find(".py") l = len(p) if i > -1 and (i + 3 == l): self.PluginList.append(p[:i]) pidxlist = os.listdir(parent.pluginsdirectory) for p in pidxlist: i = p.find(".idx") if i > -1: self.IndexList.append(p) ##AB: #if len(self.IndexList)==0: #self.IndexList.append('default.idx') ##FS: 25.03.2007: added again self.IndexList.append('default.idx') self.PluginList.sort() self.IndexList.sort() self.boxNotInIndex = wx.ListBox(self, self.ID_PROGRAM, wx.DefaultPosition, wx.Size(200, 200), self.PluginList) self.boxInIndex = wx.ListBox(self, self.ID_POPUP, wx.DefaultPosition, wx.Size(200, 200)) self.btnAdd = wx.Button(self, self.ID_ADD, " ---> ") self.btnRemove = wx.Button(self, self.ID_REMOVE, " Remove ") self.btnUp = wx.Button(self, self.ID_UP, " Up ") self.btnDown = wx.Button(self, self.ID_DOWN, " Down ") self.cboIndex = wx.Choice(self, self.ID_INDEX, wx.DefaultPosition, (250, -1), self.IndexList) self.cboIndex.SetStringSelection('default.idx') self.btnClose = wx.Button(self, wx.ID_CANCEL, "&Close Dialog") self.btnDelete = wx.Button(self, self.ID_DELETE, "&Delete Index") self.btnNew = wx.Button(self, self.ID_NEW, "&New Index") self.btnSave = wx.Button(self, self.ID_SAVE, "&Save Index") self.btnSaveAs = wx.Button(self, self.ID_SAVE_AS, "&Save Index As") self.theSizer = wx.BoxSizer(wx.VERTICAL) self.indexSizer = wx.BoxSizer(wx.HORIZONTAL) self.topmenuSizer = wx.BoxSizer(wx.HORIZONTAL) self.mainSizer = wx.FlexGridSizer(4, 4, 5, 10) self.menubuttonSizer = wx.BoxSizer(wx.VERTICAL) self.indexSizer.Add(wx.StaticText(self, -1, " Current Index: "), 0, wx.SHAPED) self.indexSizer.Add(self.cboIndex, 0, wx.SHAPED) self.indexSizer.Add(wx.StaticText(self, -1, " "), 0, wx.SHAPED) self.indexSizer.Add(self.btnClose, 0, wx.SHAPED) self.topmenuSizer.Add(self.btnDelete, 1, wx.SHAPED) self.topmenuSizer.Add(self.btnNew, 1, wx.SHAPED) self.topmenuSizer.Add(self.btnSave, 1, wx.SHAPED) self.topmenuSizer.Add(self.btnSaveAs, 1, wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(self.btnAdd, 0, wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(self.btnUp, 0, wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(self.btnDown, 0, wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.menubuttonSizer.Add(self.btnRemove, 0, wx.SHAPED) self.mainSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.mainSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.mainSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.mainSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.mainSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.mainSizer.Add(wx.StaticText(self, -1, "Not In Index:"), 0, wx.ALIGN_CENTER | wx.SHAPED) self.mainSizer.Add(wx.StaticText(self, -1, " "), 0, wx.ALIGN_CENTER | wx.SHAPED) self.mainSizer.Add(wx.StaticText(self, -1, "Plugins In Index:"), 0, wx.ALIGN_CENTER | wx.SHAPED) self.mainSizer.Add(wx.StaticText(self, -1, ""), 0, wx.ALIGN_CENTER | wx.SHAPED) self.mainSizer.Add(self.boxNotInIndex, 0, wx.SHAPED | wx.ALIGN_CENTER) self.mainSizer.Add(self.menubuttonSizer, 0, wx.SHAPED | wx.ALIGN_CENTER) self.mainSizer.Add(self.boxInIndex, 0, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(wx.StaticText(self, -1, ""), 1, wx.SHAPED) self.theSizer.Add(self.indexSizer, 1, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(wx.StaticText(self, -1, ""), 1, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.topmenuSizer, 1, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.mainSizer, 9, wx.EXPAND) self.theSizer.Add(wx.StaticText(self, -1, ""), 1, wx.SHAPED) self.parent = parent self.SetAutoLayout(True) self.SetSizerAndFit(self.theSizer) self.Bind(wx.EVT_BUTTON, self.OnbtnUp, id=self.ID_UP) self.Bind(wx.EVT_BUTTON, self.OnbtnDown, id=self.ID_DOWN) self.Bind(wx.EVT_BUTTON, self.OnbtnAdd, id=self.ID_ADD) self.Bind(wx.EVT_BUTTON, self.OnbtnRemove, id=self.ID_REMOVE) self.Bind(wx.EVT_BUTTON, self.OnbtnSave, id=self.ID_SAVE) self.Bind(wx.EVT_BUTTON, self.OnbtnDelete, id=self.ID_DELETE) self.Bind(wx.EVT_BUTTON, self.OnbtnSaveAs, id=self.ID_SAVE_AS) self.Bind(wx.EVT_BUTTON, self.OnbtnNew, id=self.ID_NEW) self.Bind(wx.EVT_CHOICE, self.OnOpen, id=self.ID_INDEX) self.parent.LoadDialogSizeAndPosition(self, 'editindexdialog.sizeandposition.dat') self.OnOpen(None) def OnCloseW(self, event): self.parent.SaveDialogSizeAndPosition(self, 'plugindialog.sizeandposition.dat') if event is not None: event.Skip() def OnbtnAdd(self, event): tselection = self.boxNotInIndex.GetStringSelection() try: self.indexplugins.index(tselection) drScrolledMessageDialog.ShowMessage(self, 'Plugin "' + tselection + '" has already been added.', "Already Added") except: tsel = self.boxNotInIndex.GetSelection() if tsel == -1: drScrolledMessageDialog.ShowMessage(self, "Nothing Selected to Add", "Mistake") return sel = self.boxInIndex.GetSelection() if sel == -1: sel = 0 self.boxInIndex.Append(tselection) self.boxInIndex.SetSelection(sel) self.indexplugins.append(tselection) self.SetNotInIndex() def OnbtnDelete(self, event): indexname = self.cboIndex.GetStringSelection() if indexname == 'default.idx': drScrolledMessageDialog.ShowMessage(self, 'You Cannot Delete the Default Index', 'Error') return answer = wx.MessageBox('Delete "%s"?' % (indexname), "DrPython", wx.YES_NO | wx.ICON_QUESTION) if answer == wx.YES: indexfile = os.path.join(self.parent.pluginsbasepreferencesdir, indexname) if not os.path.exists(indexfile): drScrolledMessageDialog.ShowMessage(self, '"%s" does not exist.' % (indexfile), 'Error') return try: os.remove(indexfile) except: drScrolledMessageDialog.ShowMessage(self, 'Error Removing "%s".' % (indexfile), 'Error') if indexname in self.IndexList: i = self.IndexList.index(indexname) self.IndexList.pop(i) self.cboIndex.Delete(i) self.cboIndex.SetStringSelection('default.idx') self.OnOpen(None) if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, 'Successfully Removed "%s".' % (indexfile), 'Deleted Index') def OnbtnDown(self, event): sel = self.boxInIndex.GetSelection() if sel < self.boxInIndex.GetCount() - 1 and sel > -1: txt = self.boxInIndex.GetString(sel) self.boxInIndex.Delete(sel) self.boxInIndex.InsertItems([txt], sel+1) self.boxInIndex.SetSelection(sel+1) #franz:swap elements self.indexplugins.insert(sel+1, self.indexplugins.pop(sel)) def OnbtnNew(self, event): d = wx.TextEntryDialog(self, "Enter New Index Name (No .idx):", "New Index", "") answer = d.ShowModal() v = d.GetValue() d.Destroy() if answer == wx.ID_OK: indexname = v + '.idx' indexfile = os.path.join(self.parent.pluginsbasepreferencesdir , indexname) self.IndexList.append(indexname) self.cboIndex.Append(indexname) self.cboIndex.SetStringSelection(indexname) try: f = file(indexfile, 'wb') f.write('\n') f.close() except: drScrolledMessageDialog.ShowMessage(self, 'Error Creating "%s".' % (indexfile), 'Error') return self.OnOpen(None) def OnbtnRemove(self, event): sel = self.boxInIndex.GetSelection() if sel == -1: drScrolledMessageDialog.ShowMessage(self, "Nothing Selected to Remove", "Mistake") return self.indexplugins.pop(sel) self.boxInIndex.Delete(sel) self.boxInIndex.SetSelection(sel-1) self.SetNotInIndex() def OnbtnSave(self, event): f = file(self.indexname, 'w') for plugin in self.indexplugins: f.write(plugin + "\n") f.close() if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, ("Succesfully wrote to:\n" + self.indexname), "Saved Changes to Index File") def OnbtnSaveAs(self, event): idx = self.cboIndex.GetStringSelection() d = wx.TextEntryDialog(self, 'Save "%s" As(No .idx):' % (idx), "Save Index As", "") answer = d.ShowModal() v = d.GetValue() d.Destroy() if answer == wx.ID_OK: indexname = v + '.idx' indexfile = os.path.join(self.parent.pluginsbasepreferencesdir , indexname) self.IndexList.append(indexname) self.cboIndex.Append(indexname) self.cboIndex.SetStringSelection(indexname) try: f = file(indexfile, 'wb') for plugin in self.indexplugins: f.write(plugin + "\n") f.close() if self.parent.prefs.enablefeedback: drScrolledMessageDialog.ShowMessage(self, ("Succesfully wrote to:\n" + indexfile), "Saved Changes to Index File") except: drScrolledMessageDialog.ShowMessage(self, 'Error Saving "%s" As "%s".' % (idx, indexname), 'Error') return def OnbtnUp(self, event): sel = self.boxInIndex.GetSelection() if sel > 0: txt = self.boxInIndex.GetString(sel) self.boxInIndex.Delete(sel) self.boxInIndex.InsertItems([txt], sel-1) self.boxInIndex.SetSelection(sel-1) #franz:swap elements self.indexplugins.insert(sel-1, self.indexplugins.pop(sel)) def OnOpen(self, event): fname = self.cboIndex.GetStringSelection() self.indexname = os.path.join(self.parent.preferencesdirectory, fname) if not os.path.exists(self.indexname): return try: f = file(self.indexname, 'r') self.indexplugins = f.read().rstrip().split('\n') f.close() x = 0 l = len(self.indexplugins) while x < l: if not self.indexplugins[x]: self.indexplugins.pop(x) x = x - 1 l = l - 1 x = x + 1 self.boxInIndex.Set(self.indexplugins) self.SetNotInIndex() except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error Reading Index File: " + self.indexname), "Open Error") def SetNotInIndex (self): #Written By Franz #AB: Modified to keep old selection sel = self.boxNotInIndex.GetSelection() nlist = [] for i in self.PluginList: if i not in self.indexplugins: nlist.append (i) self.boxNotInIndex.Set (nlist) if sel<0: sel=0 if sel>=len(nlist): sel=len(nlist)-1 self.boxNotInIndex.SetSelection(sel)drpython-3.11.1/drPluginMenu.py0000644000175000017500000003212211150445515017236 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #Plugins Menu import os, shutil, sys import wx import drScrolledMessageDialog import drFileDialog from drMenu import drMenu class drPluginConfigureMenu(drMenu): def __init__(self, parent): drMenu.__init__(self, parent) self.parent = parent self.ID_INSTALL = 4300 self.ID_INSTALL_PY = 4301 self.ID_UNINSTALL = 4302 self.ID_INDEX = 4303 self.ID_EDIT = 4304 self.wildcard = "DrPython Plugin (*.py)|*.py" self.Append(self.ID_INSTALL, "&Install...") self.Append(self.ID_INSTALL_PY, "Install From Py...") self.Append(self.ID_UNINSTALL, "&UnInstall...") self.Append(self.ID_INDEX, "&Edit Indexes...") self.Append(self.ID_EDIT, "Edit &Plugin Source...") self.parent.Bind(wx.EVT_MENU, self.OnInstall, id=self.ID_INSTALL) self.parent.Bind(wx.EVT_MENU, self.OnInstallFromPy, id=self.ID_INSTALL_PY) self.parent.Bind(wx.EVT_MENU, self.OnUnInstall, id=self.ID_UNINSTALL) self.parent.Bind(wx.EVT_MENU, self.OnEditIndex, id=self.ID_INDEX) self.parent.Bind(wx.EVT_MENU, self.OnEditPlugin, id=self.ID_EDIT) def EditPlugin(self, plugin): pluginfile = os.path.join(self.parent.pluginsdirectory, plugin) + ".py" #Patch From Franz, Check for already open. #(Slightly edited by Dan, if ... in replaces try ... except. self.parent.OpenOrSwitchToFile(pluginfile) def OnEditIndex(self, event): from drPluginDialog import drEditIndexDialog d = drEditIndexDialog(self.parent) d.ShowModal() d.Destroy() def OnEditPlugin(self, event): plist = os.listdir(self.parent.pluginsdirectory) PluginList = [] for p in plist: i = p.find(".py") l = len(p) if i > -1 and (i + 3 == l): PluginList.append(p[:i]) PluginList.sort() try: d = wx.SingleChoiceDialog(self.parent, "Select the Plugin to Edit:", "Edit Plugin", PluginList, wx.CHOICEDLG_STYLE) d.SetSize(wx.Size(250, 250)) answer = d.ShowModal() d.Destroy() if answer == wx.ID_OK: self.EditPlugin(d.GetStringSelection()) except: drScrolledMessageDialog.ShowMessage(self.parent, "Error Editing Plugin", "Edit Plugin Error") def OnInstall(self, event): from drPluginDialog import drPluginInstallWizard img = wx.Image(self.parent.bitmapdirectory + "/install.wizard.png", wx.BITMAP_TYPE_PNG) installWizard = drPluginInstallWizard(self.parent, "Install DrPython Plugin(s)", wx.BitmapFromImage(img)) installWizard.Run() def OnInstallFromPy (self, event): dlg = drFileDialog.FileDialog(self.parent, "Select Plugin to Install", self.wildcard) if self.parent.pluginsdirectory: try: dlg.SetDirectory(self.parent.pluginsdirectory) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error Setting Default Directory To: " + self.parent.pluginsdirectory), "DrPython Error") if dlg.ShowModal() == wx.ID_OK: if not os.path.exists(self.parent.pluginsdirectory): os.mkdir(self.parent.pluginsdirectory) pluginfile = dlg.GetPath().replace("\\", "/") pluginrfile = os.path.join(self.parent.pluginsdirectory, os.path.split(pluginfile)[1]) pluginpath, plugin = os.path.split(pluginfile) i = plugin.find(".py") if i == -1: drScrolledMessageDialog.ShowMessage(self.parent, ("Plugins must be .py files."), "DrPython Error") plugininstallfile = pluginfile + ".install" continueinstallation = True if os.path.exists(plugininstallfile): f = open(plugininstallfile, 'r') scripttext = f.read() f.close() try: code = compile((scripttext + '\n'), plugininstallfile, 'exec') except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error compiling install script."), "Error", wx.DefaultPosition, wx.Size(550,300)) return try: cwd = os.getcwd() os.chdir(pluginpath) exec(code) continueinstallation = Install(self.parent) os.chdir(cwd) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error running install script."), "Error", wx.DefaultPosition, wx.Size(550,300)) return if not continueinstallation: return plugin = plugin[:i] pluginsfile = self.parent.preferencesdirectory + "/default.idx" if not os.path.exists(pluginsfile): f = file(pluginsfile, 'wb') f.write('\n') f.close() try: copyf = True if os.path.exists(pluginrfile): answer = wx.MessageBox('Overwrite"' + pluginrfile + '"?', "DrPython", wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION) if answer == wx.NO: copyf = False if copyf: shutil.copyfile(pluginfile, pluginrfile) #there could be an error check: if idx file does not exist in source, simply create one. shutil.copyfile(os.path.splitext(pluginfile)[0] + '.idx', os.path.splitext(pluginrfile)[0] + '.idx') try: f = open(pluginsfile, 'rU') pluginstoload = [x.strip() for x in f] f.close() except: pluginstoload = [] try: pluginstoload.index(plugin) except: f = file(pluginsfile, 'w') for p in pluginstoload: f.write(p + "\n") f.write(plugin) f.close() except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error with: " + pluginfile), "Install Error") return def OnUnInstall(self, event): from drPluginDialog import drPluginUnInstallWizard img = wx.Image(self.parent.bitmapdirectory + "/uninstall.wizard.png", wx.BITMAP_TYPE_PNG) uninstallWizard = drPluginUnInstallWizard(self.parent, "UnInstall DrPython Plugin(s)", wx.BitmapFromImage(img)) uninstallWizard.Run() class drPluginIndexMenu(wx.Menu): def __init__(self, parent): wx.Menu.__init__(self) self.ID_LOAD_PLUGIN_BASE = 4505 self.parent = parent self.indexes = [] self.loadedindexes = [self.parent.preferencesdirectory + "/default.idx"] self.setupMenu() def OnLoadPluginsFromIndex(self, event): idnum = event.GetId() i = idnum - self.ID_LOAD_PLUGIN_BASE index = self.indexes[i] try: f = file(index, 'r') pluginstoload = f.read().rstrip().split('\n') f.close() for plugin in pluginstoload: try: self.parent.InitializePlugin(plugin) except: errstring = str(sys.exc_info()[0]).lstrip("exceptions.") + ": " + str(sys.exc_info()[1]) drScrolledMessageDialog.ShowMessage(self.parent, ("Error loading plugin: " + plugin + "\n\n" + errstring), "Load Error") self.loadedindexes.append(self.indexes[i]) self.reloadMenu() except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error loading plugins from: " + index), "Load Error") def setupMenu(self): files = os.listdir(self.parent.pluginsdirectory) self.indexes = [] #Added By Franz pluginsfile = self.parent.preferencesdirectory + "/default.idx" if not os.path.exists(pluginsfile): return pluginstoload = [] try: f = file(pluginsfile, 'rU') pluginstoload = [x.strip() for x in f] f.close() except: #Return added by Dan return #/Franz x = 0 for f in files: if f.find(".idx") > -1 and f != "default.idx": index = os.path.join (self.parent.pluginsdirectory, f) if not (index in self.loadedindexes): if not os.path.splitext(os.path.basename(index))[0] in pluginstoload: self.indexes.append(index) self.Append(self.ID_LOAD_PLUGIN_BASE + x, str(os.path.basename(f))) self.parent.Bind(wx.EVT_MENU, self.OnLoadPluginsFromIndex, id=self.ID_LOAD_PLUGIN_BASE+x) x = x + 1 def reloadMenu(self): mnuitems = self.GetMenuItems() num = len(mnuitems) x = 0 while x < num: self.Remove(mnuitems[x].GetId()) x = x + 1 self.setupMenu() class drPluginFunctionMenu(wx.Menu): def __init__(self, parent, function_id_base, functionstring, function): wx.Menu.__init__(self) self.ID_BASE = function_id_base self.functionstring = functionstring self.function = function self.parent = parent self.pluginsArray = [] self.pluginsMenuArray = [] def GetInsertPosition(self, plugin): x = 0 l = len(self.pluginsMenuArray) while x < l: if plugin > self.pluginsMenuArray[x]: x += 1 else: return x return x def AddItem(self, plugin): try: i = self.parent.LoadedPlugins.index(plugin) exec(compile('self.parent.PluginModules[i]' + self.functionstring, plugin, 'exec')) x = len(self.pluginsArray) i = self.GetInsertPosition(plugin) self.pluginsMenuArray.insert(i, plugin) self.pluginsArray.append(plugin) self.Insert(i, self.ID_BASE + x, plugin) self.parent.Bind(wx.EVT_MENU, self.function, id=self.ID_BASE + x) except: pass class drPluginAboutMenu(drPluginFunctionMenu): def __init__(self, parent): self.ID_LOAD_PLUGIN_ABOUT_BASE = 4305 drPluginFunctionMenu.__init__(self, parent, self.ID_LOAD_PLUGIN_ABOUT_BASE, '.OnAbout', self.OnLoadPluginsAbout) def OnLoadPluginsAbout(self, event): idnum = event.GetId() i = idnum - self.ID_LOAD_PLUGIN_ABOUT_BASE plugin = self.pluginsArray[i] try: i = self.parent.LoadedPlugins.index(plugin) self.parent.PluginModules[i].OnAbout(self.parent) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error With Help."), "Plugin Help Error") class drPluginHelpMenu(drPluginFunctionMenu): def __init__(self, parent): self.ID_LOAD_PLUGIN_HELP_BASE = 4705 drPluginFunctionMenu.__init__(self, parent, self.ID_LOAD_PLUGIN_HELP_BASE, '.OnHelp', self.OnLoadPluginsHelp) def OnLoadPluginsHelp(self, event): idnum = event.GetId() i = idnum - self.ID_LOAD_PLUGIN_HELP_BASE plugin = self.pluginsArray[i] try: i = self.parent.LoadedPlugins.index(plugin) self.parent.PluginModules[i].OnHelp(self.parent) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error With Help."), "Plugin Help Error") class drPluginPreferencesMenu(drPluginFunctionMenu): def __init__(self, parent): self.ID_LOAD_PLUGIN_PREFS_BASE = 4905 drPluginFunctionMenu.__init__(self, parent, self.ID_LOAD_PLUGIN_PREFS_BASE, '.OnPreferences', self.OnLoadPluginsPreferences) def OnLoadPluginsPreferences(self, event): idnum = event.GetId() i = idnum - self.ID_LOAD_PLUGIN_PREFS_BASE plugin = self.pluginsArray[i] try: i = self.parent.LoadedPlugins.index(plugin) self.parent.PluginModules[i].OnPreferences(self.parent) except: drScrolledMessageDialog.ShowMessage(self.parent, ("Error With Help."), "Plugin Help Error") drpython-3.11.1/drGetKeyDialog.py0000644000175000017500000001023611150445515017465 0ustar dktrkranzdktrkranz# Programmer: Daniel Pozmanter # E-mail: drpython@bluebottle.com # Note: You must reply to the verification e-mail to get through. # # Copyright 2003-2007 Daniel Pozmanter # # Distributed under the terms of the GPL (GNU Public License) # # DrPython 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; either version 2 of the License, or # (at your option) any later version. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #GetKey Dialog import drShortcuts import wx class drGetTextCtrl(wx.TextCtrl): def __init__(self, parent, ignorestring, grandparent): #Bug-Report With Fix, Christian Daven. wx.TextCtrl.__init__(self, parent, -1, "Hit A Key", wx.DefaultPosition, wx.DefaultSize, style=wx.TE_PROCESS_TAB|wx.TE_PROCESS_ENTER) self.ancestor = grandparent self.valuestring = '' self.allowControl = not (ignorestring.find("Control") > -1) self.allowShift = not (ignorestring.find("Shift") > -1) self.allowMeta = not (ignorestring.find("Meta") > -1) self.allowAlt = not (ignorestring.find("Alt") > -1) self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) def GetValue(self): return self.valuestring def OnKeyDown(self, event): keystr = "" keycode = event.GetKeyCode() if (keycode == wx.WXK_CONTROL) or (keycode == 309) or (keycode == wx.WXK_SHIFT): return if event.ControlDown() and self.allowControl: keystr = "Control" if event.ShiftDown() and self.allowShift: keystr = keystr + "Shift" if event.AltDown() and self.allowAlt: keystr = keystr + "Alt" if event.MetaDown() and self.allowMeta: keystr = keystr + "Meta" keystr = keystr + str(keycode) self.SetValue(keystr) def SetValue(self, value): self.valuestring = value vstring = '' if drShortcuts.MatchControl(value): vstring += "Control + " if drShortcuts.MatchShift(value): vstring += "Shift + " if drShortcuts.MatchAlt(value): vstring += "Alt + " if drShortcuts.MatchMeta(value): vstring += "Meta + " vstring = vstring + drShortcuts.GetKeycodeStringFromShortcut(value) wx.TextCtrl.SetValue(self, vstring) class drGetKeyDialog(wx.Dialog): def __init__(self, parent, ignorestring, grandparent): wx.Dialog.__init__(self, parent, -1, ("Hit A Key"), wx.DefaultPosition, wx.Size(200, 200), wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.THICK_FRAME | wx.RESIZE_BORDER) self.theSizer = wx.BoxSizer(wx.VERTICAL) self.txtKey = drGetTextCtrl(self, ignorestring, grandparent) self.theSizer.Add(self.txtKey, 1, wx.EXPAND) self.btnClear = wx.Button(self, 102, "Clear") self.btnClose = wx.Button(self, 101, "&Close") self.theSizer.Add(self.btnClear, 1, wx.SHAPED | wx.ALIGN_CENTER) self.theSizer.Add(self.btnClose, 1, wx.SHAPED | wx.ALIGN_CENTER) self.SetAutoLayout(True) self.SetSizer(self.theSizer) self.txtKey.SetFocus() self.Bind(wx.EVT_BUTTON, self.OnbtnClose, id=101) self.Bind(wx.EVT_BUTTON, self.OnbtnClear, id=102) def SetKeyString(self, keystring): if drShortcuts.GetKeycodeFromShortcut(keystring): self.txtKey.SetValue(keystring) else: self.txtKey.SetValue("Hit A Key") def GetKeyString(self): y = self.txtKey.GetValue() if y == "Hit A Key": return "" return y def OnbtnClear(self, event): self.txtKey.SetValue("Hit A Key") def OnbtnClose(self, event): self.EndModal(0)