diff options
-rw-r--r-- | Lib/idlelib/Bindings.py | 10 | ||||
-rw-r--r-- | Lib/idlelib/EditorWindow.py | 52 | ||||
-rw-r--r-- | Lib/idlelib/NEWS.txt | 21 | ||||
-rw-r--r-- | Lib/idlelib/config-main.def | 33 | ||||
-rw-r--r-- | Lib/idlelib/configDialog.py | 26 | ||||
-rw-r--r-- | Lib/idlelib/configHandler.py | 61 | ||||
-rw-r--r-- | Lib/idlelib/configHelpSourceEdit.py | 47 | ||||
-rw-r--r-- | Lib/idlelib/configSectionNameDialog.py | 6 |
8 files changed, 164 insertions, 92 deletions
diff --git a/Lib/idlelib/Bindings.py b/Lib/idlelib/Bindings.py index b177a5e..abce56b 100644 --- a/Lib/idlelib/Bindings.py +++ b/Lib/idlelib/Bindings.py @@ -65,16 +65,16 @@ menudefs = [ ('!_Auto-open Stack Viewer', '<<toggle-jit-stack-viewer>>' ), ]), ('options', [ - ('_Configure Idle...', '<<open-config-dialog>>'), + ('_Configure IDLE...', '<<open-config-dialog>>'), None, ('Revert to _Default Settings', '<<revert-all-settings>>'), ]), ('help', [ - ('_IDLE Help...', '<<help>>'), - ('Python _Documentation...', '<<python-docs>>'), - ('View IDLE _Readme...', '<<view-readme>>'), + ('_About IDLE', '<<about-idle>>'), + ('IDLE _Readme', '<<view-readme>>'), None, - ('_About IDLE...', '<<about-idle>>'), + ('_IDLE Help', '<<help>>'), + ('Python _Docs', '<<python-docs>>'), ]), ] diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py index b940c3b..b9522fc 100644 --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -247,8 +247,8 @@ class EditorWindow: menudict[name] = menu = Menu(mbar, name=name) mbar.add_cascade(label=label, menu=menu, underline=underline) self.fill_menus() - #create the ExtraHelp menu, if required - self.ResetExtraHelpMenu() + self.base_helpmenu_length = self.menudict['help'].index(END) + self.reset_help_menu_entries() def postwindowsmenu(self): # Only called when Windows menu exists @@ -315,7 +315,8 @@ class EditorWindow: return "break" def display_docs(self, url): - url = os.path.normpath(url) + if not (url.startswith('www') or url.startswith('http')): + url = os.path.normpath(url) if sys.platform.count('win') or sys.platform.count('nt'): os.startfile(url) else: @@ -530,29 +531,28 @@ class EditorWindow: menu.entryconfig(index,accelerator=accel) #print 'accel now:',accel,'\n' - def ResetExtraHelpMenu(self): - "Load or update the Extra Help menu if required" - menuList=idleConf.GetAllExtraHelpSourcesList() - helpMenu=self.menudict['help'] - cascadeIndex=helpMenu.index(END)-1 - if menuList: - if not hasattr(self,'menuExtraHelp'): - self.menuExtraHelp=Menu(self.menubar) - helpMenu.insert_cascade(cascadeIndex,label='Extra Help', - underline=1,menu=self.menuExtraHelp) - self.menuExtraHelp.delete(1,END) - for menuItem in menuList: - self.menuExtraHelp.add_command(label=menuItem[0], - command=self.__DisplayExtraHelpCallback(menuItem[1])) - else: #no extra help items - if hasattr(self,'menuExtraHelp'): - helpMenu.delete(cascadeIndex-1) - del(self.menuExtraHelp) - - def __DisplayExtraHelpCallback(self,helpFile): - def DisplayExtraHelp(helpFile=helpFile): - self.display_docs(helpFile) - return DisplayExtraHelp + def reset_help_menu_entries(self): + "Update the additional help entries on the Help menu" + help_list = idleConf.GetAllExtraHelpSourcesList() + helpmenu = self.menudict['help'] + # first delete the extra help entries, if any + helpmenu_length = helpmenu.index(END) + if helpmenu_length > self.base_helpmenu_length: + helpmenu.delete((self.base_helpmenu_length + 1), helpmenu_length) + # then rebuild them + if help_list: + helpmenu.add_separator() + for entry in help_list: + cmd = self.__extra_help_callback(entry[1]) + helpmenu.add_command(label=entry[0], command=cmd) + # and update the menu dictionary + self.menudict['help'] = helpmenu + + def __extra_help_callback(self, helpfile): + "Create a callback with the helpfile value frozen at definition time" + def display_extra_help(helpfile=helpfile): + self.display_docs(helpfile) + return display_extra_help def UpdateRecentFilesList(self,newFile=None): "Load or update the recent files list, and menu if required" diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index de72ea4..f6ed853 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -7,6 +7,27 @@ What's New in IDLEfork 0.9 Alpha 2? *Release date: XX-XXX-2003* +- Change default: IDLE now starts with Python Shell. + +- Removed the File Path from the Additional Help Sources scrolled list. + +- Add capability to access Additional Help Sources on the web if the + Help File Path begins with //http or www. (Otherwise local path is + validated, as before.) + +- Additional Help Sources were not being posted on the Help menu in the + order entered. Implement sorting the list by [HelpFiles] 'option' + number. + +- Add Browse button to New Help Source dialog. Arrange to start in + Python/Doc if platform is Windows, otherwise start in current directory. + +- Put the Additional Help Sources directly on the Help menu instead of in + an Extra Help cascade menu. Rearrange the Help menu so the Additional + Help Sources come last. Update help.txt appropriately. + +- Fix Tk root pop-ups in configSectionNameDialog.py and configDialog.py + - Uniform capitalization in General tab of ConfigDialog, update the doc string. - Fix bug in ConfigDialog where SaveAllChangedConfig() was unexpectedly diff --git a/Lib/idlelib/config-main.def b/Lib/idlelib/config-main.def index cd52b21..9d520c1 100644 --- a/Lib/idlelib/config-main.def +++ b/Lib/idlelib/config-main.def @@ -25,9 +25,21 @@ # retained unless specifically deleted within the config dialog. Choosing # one of the default themes or keysets just applies the relevant settings # from the default file. +# +# Additional help sources are listed in the [HelpFiles] section and must be +# viewable by a web browser (or the Windows Help viewer in the case of .chm +# files). These sources will be listed on the Help menu. The pattern is +# <sequence_number = menu item;/path/to/help/source> +# You can't use a semi-colon in a menu item or path. The path will be platform +# specific because of path separators, drive specs etc. +# +# It is best to use the Configuration GUI to set up additional help sources! +# Example: +#1 = My Extra Help Source;/usr/share/doc/foo/index.html +#2 = Another Help Source;/path/to/another.pdf [General] -editor-on-startup= 1 +editor-on-startup= 0 print-command-posix=lpr %s print-command-win=start /min notepad /p %s @@ -51,22 +63,3 @@ default= 1 name= IDLE Classic Windows [HelpFiles] -#additional help sources, must be viewable by an html browser -#will be listed on the Help/Other Help menu -#option names are the sequence number of the option -#values take the form: menu item;/path/to/help/source -#obviously you can't use a semi-colon in a menu item or path and the path will -#be platform specific because of path separators, drive specs etc. -#eg.: -#1= My Extra Help Source;/usr/share/doc/foo/index.html -#2= Another Help Source;/path/to/another.html - -#[RecentFiles] -#this section will only be present in the user config file idle-main.cfg -#where it will record the most recently openned files in the form -#IndexNum= /full/path/of/file , for display on the File/Recent Files menu -#it is present here for reference only -#eg.: -#1=/most/recently/openned/file -#2=/next/most/recently/openned/file -#etc. diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py index f8db74d..814689c 100644 --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -677,7 +677,8 @@ class ConfigDialog(Toplevel): def DeleteCustomKeys(self): keySetName=self.customKeys.get() if not tkMessageBox.askyesno('Delete Key Set','Are you sure you wish '+ - 'to delete the key set '+`keySetName`+' ?'): + 'to delete the key set '+`keySetName`+' ?', + parent=self): return #remove key set from config idleConf.userCfg['keys'].remove_section(keySetName) @@ -703,7 +704,8 @@ class ConfigDialog(Toplevel): def DeleteCustomTheme(self): themeName=self.customTheme.get() if not tkMessageBox.askyesno('Delete Theme','Are you sure you wish '+ - 'to delete the theme '+`themeName`+' ?'): + 'to delete the theme '+`themeName`+' ?', + parent=self): return #remove theme from config idleConf.userCfg['highlight'].remove_section(themeName) @@ -874,7 +876,7 @@ class ConfigDialog(Toplevel): helpSource=GetHelpSourceDialog(self,'New Help Source').result if helpSource: self.userHelpList.append( (helpSource[0],helpSource[1]) ) - self.listHelp.insert(END,helpSource[0]+' '+helpSource[1]) + self.listHelp.insert(END,helpSource[0]) self.UpdateUserHelpChangedItems() self.SetHelpListButtonStates() @@ -887,7 +889,7 @@ class ConfigDialog(Toplevel): return #no changes self.userHelpList[itemIndex]=newHelpSource self.listHelp.delete(itemIndex) - self.listHelp.insert(itemIndex,newHelpSource[0]+' '+newHelpSource[1]) + self.listHelp.insert(itemIndex,newHelpSource[0]) self.UpdateUserHelpChangedItems() self.SetHelpListButtonStates() @@ -899,12 +901,11 @@ class ConfigDialog(Toplevel): self.SetHelpListButtonStates() def UpdateUserHelpChangedItems(self): - #clear and rebuild the HelpFiles section in self.changedItems - if self.changedItems['main'].has_key('HelpFiles'): - del(self.changedItems['main']['HelpFiles']) + "Clear and rebuild the HelpFiles section in self.changedItems" + self.changedItems['main']['HelpFiles'] = {} for num in range(1,len(self.userHelpList)+1): self.AddChangedItem('main','HelpFiles',str(num), - string.join(self.userHelpList[num-1],';')) + string.join(self.userHelpList[num-1][:2],';')) def LoadFontCfg(self): ##base editor font selection list @@ -1019,10 +1020,10 @@ class ConfigDialog(Toplevel): #initial window size self.winWidth.set(idleConf.GetOption('main','EditorWindow','width')) self.winHeight.set(idleConf.GetOption('main','EditorWindow','height')) - #help browsing - self.userHelpList=idleConf.GetExtraHelpSourceList('user') + # additional help sources + self.userHelpList = idleConf.GetAllExtraHelpSourcesList() for helpItem in self.userHelpList: - self.listHelp.insert(END,helpItem[0]+' '+helpItem[1]) + self.listHelp.insert(END,helpItem[0]) self.SetHelpListButtonStates() #self.userHelpBrowser.set(idleConf.GetOption('main','General', # 'user-help-browser',default=0,type='bool')) @@ -1086,6 +1087,7 @@ class ConfigDialog(Toplevel): if section == 'HelpFiles': #this section gets completely replaced idleConf.userCfg['main'].remove_section('HelpFiles') + cfgTypeHasChanges = True for item in self.changedItems[configType][section].keys(): value = self.changedItems[configType][section][item] if self.SetUserValue(configType,section,item,value): @@ -1107,7 +1109,7 @@ class ConfigDialog(Toplevel): instance.ResetColorizer() instance.ResetFont() instance.ResetKeybindings() - instance.ResetExtraHelpMenu() + instance.reset_help_menu_entries() def Cancel(self): self.destroy() diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py index cf2b6db..22e83a6 100644 --- a/Lib/idlelib/configHandler.py +++ b/Lib/idlelib/configHandler.py @@ -1,14 +1,25 @@ +"""Provides access to stored IDLE configuration information. + +Refer to the comments at the beginning of config-main.def for a description of +the available configuration files and the design implemented to update user +configuration information. In particular, user configuration choices which +duplicate the defaults will be removed from the user's configuration files, +and if a file becomes empty, it will be deleted. + +The contents of the user files may be altered using the Options/Configure IDLE +menu to access the configuration GUI (configDialog.py), or manually. + +Throughout this module there is an emphasis on returning useable defaults +when a problem occurs in returning a requested configuration value back to +idle. This is to allow IDLE to continue to function in spite of errors in +the retrieval of config information. When a default is returned instead of +a requested config value, a message is printed to stderr to aid in +configuration problem notification and resolution. + """ -Provides access to stored idle configuration information. -""" -# Throughout this module there is an emphasis on returning useable defaults -# when a problem occurs in returning a requested configuration value back to -# idle. This is to allow idle to continue to function in spite of errors in -# the retrieval of config information. When a default is returned instead of -# a requested config value, a message is printed to stderr to aid in -# configuration problem notification and resolution. - -import os, sys, string +import os +import sys +import string from ConfigParser import ConfigParser, NoOptionError, NoSectionError class InvalidConfigType(Exception): pass @@ -123,9 +134,11 @@ class IdleUserConfParser(IdleConfParser): os.remove(self.file) def Save(self): - """ - If config isn't empty, write file to disk. If config is empty, - remove the file from disk if it exists. + """Update user configuration file. + + Remove empty sections. If resulting config isn't empty, write the file + to disk. If config is empty, remove the file from disk if it exists. + """ if not self.IsEmpty(): cfgFile=open(self.file,'w') @@ -555,11 +568,14 @@ class IdleConf: return keyBindings def GetExtraHelpSourceList(self,configSet): - """ - Returns a list of tuples containing the details of any additional - help sources configured in the requested configSet ('user' or 'default') - , or an empty list if there are none. Returned tuples are of the form - form (menu_item , path_to_help_file , option). + """Fetch list of extra help sources from a given configSet. + + Valid configSets are 'user' or 'default'. Return a list of tuples of + the form (menu_item , path_to_help_file , option), or return the empty + list. 'option' is the sequence number of the help resource. 'option' + values determine the position of the menu items on the Help menu, + therefore the returned list must be sorted by 'option'. + """ helpSources=[] if configSet=='user': @@ -580,8 +596,17 @@ class IdleConf: helpPath=value[1].strip() if menuItem and helpPath: #neither are empty strings helpSources.append( (menuItem,helpPath,option) ) + helpSources.sort(self.__helpsort) return helpSources + def __helpsort(self, h1, h2): + if int(h1[2]) < int(h2[2]): + return -1 + elif int(h1[2]) > int(h2[2]): + return 1 + else: + return 0 + def GetAllExtraHelpSourcesList(self): """ Returns a list of tuples containing the details of all additional help diff --git a/Lib/idlelib/configHelpSourceEdit.py b/Lib/idlelib/configHelpSourceEdit.py index bd799da..25569ca 100644 --- a/Lib/idlelib/configHelpSourceEdit.py +++ b/Lib/idlelib/configHelpSourceEdit.py @@ -1,14 +1,19 @@ "Dialog to specify or edit the parameters for a user configured help source." +import os + from Tkinter import * import tkMessageBox -import os +import tkFileDialog class GetHelpSourceDialog(Toplevel): def __init__(self, parent, title, menuItem='', filePath=''): - """ - menuItem - string, the menu item to edit, if any - filePath - string, the help file path to edit, if any + """Get menu entry and url/ local file location for Additional Help + + User selects a name for the Help resource and provides a web url + or a local file as its source. The user can enter a url or browse + for the file. + """ Toplevel.__init__(self, parent) self.configure(borderwidth=5) @@ -39,7 +44,7 @@ class GetHelpSourceDialog(Toplevel): self.menu = StringVar(self) self.path = StringVar(self) self.fontSize = StringVar(self) - self.frameMain = Frame(self, borderwidth=2, relief=SUNKEN) + self.frameMain = Frame(self, borderwidth=2, relief=GROOVE) self.frameMain.pack(side=TOP, expand=TRUE, fill=BOTH) labelMenu = Label(self.frameMain, anchor=W, justify=LEFT, text='Menu Item:') @@ -47,7 +52,7 @@ class GetHelpSourceDialog(Toplevel): width=30) self.entryMenu.focus_set() labelPath = Label(self.frameMain, anchor=W, justify=LEFT, - text='Help File Path:') + text='Help File Path: Enter URL or browse for file') self.entryPath = Entry(self.frameMain, textvariable=self.path, width=40) self.entryMenu.focus_set() @@ -55,17 +60,41 @@ class GetHelpSourceDialog(Toplevel): self.entryMenu.pack(anchor=W, padx=5, pady=3) labelPath.pack(anchor=W, padx=5, pady=3) self.entryPath.pack(anchor=W, padx=5, pady=3) + browseButton = Button(self.frameMain, text='Browse', width=8, + command=self.browseFile) + browseButton.pack(pady=3) frameButtons = Frame(self) frameButtons.pack(side=BOTTOM, fill=X) self.buttonOk = Button(frameButtons, text='OK', width=8, default=ACTIVE, command=self.Ok) self.buttonOk.grid(row=0, column=0, padx=5,pady=5) - self.buttonOk.bind('<Return>', self.Ok) - #self.buttonOk.focus() self.buttonCancel = Button(frameButtons, text='Cancel', width=8, command=self.Cancel) self.buttonCancel.grid(row=0, column=1, padx=5, pady=5) + def browseFile(self): + filetypes = [ + ("HTML Files", "*.htm *.html", "TEXT"), + ("PDF Files", "*.pdf", "TEXT"), + ("Windows Help Files", "*.chm"), + ("Text Files", "*.txt", "TEXT"), + ("All Files", "*")] + path = self.path.get() + if path: + dir, base = os.path.split(path) + else: + base = None + if sys.platform.count('win') or sys.platform.count('nt'): + dir = os.path.join(os.path.dirname(sys.executable), 'Doc') + if not os.path.isdir(dir): + dir = os.getcwd() + else: + dir = os.getcwd() + opendialog = tkFileDialog.Open(parent=self, filetypes=filetypes) + file = opendialog.show(initialdir=dir, initialfile=base) + if file: + self.path.set(file) + def MenuOk(self): "Simple validity check for a sensible menu item name" menuOk = True @@ -97,6 +126,8 @@ class GetHelpSourceDialog(Toplevel): parent=self) self.entryPath.focus_set() pathOk = False + elif path.startswith('www.') or path.startswith('http'): + pathOk = True elif not os.path.exists(path): tkMessageBox.showerror(title='File Path Error', message='Help file path does not exist.', diff --git a/Lib/idlelib/configSectionNameDialog.py b/Lib/idlelib/configSectionNameDialog.py index 7b768f1..4f1b002 100644 --- a/Lib/idlelib/configSectionNameDialog.py +++ b/Lib/idlelib/configSectionNameDialog.py @@ -63,16 +63,16 @@ class GetCfgSectionNameDialog(Toplevel): name.strip() if not name: #no name specified tkMessageBox.showerror(title='Name Error', - message='No name specified.') + message='No name specified.', parent=self) nameOk=0 elif len(name)>30: #name too long tkMessageBox.showerror(title='Name Error', message='Name too long. It should be no more than '+ - '30 characters.') + '30 characters.', parent=self) nameOk=0 elif name in self.usedNames: tkMessageBox.showerror(title='Name Error', - message='This name is already in use.') + message='This name is already in use.', parent=self) nameOk=0 return nameOk |