Merge with 3.4
This commit is contained in:
commit
447169f6da
|
@ -252,17 +252,16 @@ Options menu (Shell and Editor)
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Configure IDLE
|
Configure IDLE
|
||||||
Open a configuration dialog. Fonts, indentation, keybindings, and color
|
Open a configuration dialog and change preferences for the following:
|
||||||
themes may be altered. Startup Preferences may be set, and additional
|
fonts, indentation, keybindings, text color themes, startup windows and
|
||||||
help sources can be specified. Non-default user setting are saved in a
|
size, additional help sources, and extensions (see below). On OS X,
|
||||||
.idlerc directory in the user's home directory. Problems caused by bad user
|
open the configuration dialog by selecting Preferences in the application
|
||||||
configuration files are solved by editing or deleting one or more of the
|
menu. To use a new built-in color theme (IDLE Dark) with older IDLEs,
|
||||||
files in .idlerc. On OS X, open the configuration dialog by selecting
|
save it as a new custom theme.
|
||||||
Preferences in the application menu.
|
|
||||||
|
|
||||||
Configure Extensions
|
Non-default user settings are saved in a .idlerc directory in the user's
|
||||||
Open a configuration dialog for setting preferences for extensions
|
home directory. Problems caused by bad user configuration files are solved
|
||||||
(discussed below). See note above about the location of user settings.
|
by editing or deleting one or more of the files in .idlerc.
|
||||||
|
|
||||||
Code Context (toggle)(Editor Window only)
|
Code Context (toggle)(Editor Window only)
|
||||||
Open a pane at the top of the edit window which shows the block context
|
Open a pane at the top of the edit window which shows the block context
|
||||||
|
|
|
@ -78,7 +78,6 @@ menudefs = [
|
||||||
]),
|
]),
|
||||||
('options', [
|
('options', [
|
||||||
('Configure _IDLE', '<<open-config-dialog>>'),
|
('Configure _IDLE', '<<open-config-dialog>>'),
|
||||||
('Configure _Extensions', '<<open-config-extensions-dialog>>'),
|
|
||||||
None,
|
None,
|
||||||
]),
|
]),
|
||||||
('help', [
|
('help', [
|
||||||
|
|
|
@ -191,8 +191,6 @@ class EditorWindow(object):
|
||||||
text.bind("<<python-docs>>", self.python_docs)
|
text.bind("<<python-docs>>", self.python_docs)
|
||||||
text.bind("<<about-idle>>", self.about_dialog)
|
text.bind("<<about-idle>>", self.about_dialog)
|
||||||
text.bind("<<open-config-dialog>>", self.config_dialog)
|
text.bind("<<open-config-dialog>>", self.config_dialog)
|
||||||
text.bind("<<open-config-extensions-dialog>>",
|
|
||||||
self.config_extensions_dialog)
|
|
||||||
text.bind("<<open-module>>", self.open_module)
|
text.bind("<<open-module>>", self.open_module)
|
||||||
text.bind("<<do-nothing>>", lambda event: "break")
|
text.bind("<<do-nothing>>", lambda event: "break")
|
||||||
text.bind("<<select-all>>", self.select_all)
|
text.bind("<<select-all>>", self.select_all)
|
||||||
|
@ -514,10 +512,6 @@ class EditorWindow(object):
|
||||||
# Synchronize with macosxSupport.overrideRootMenu.config_dialog.
|
# Synchronize with macosxSupport.overrideRootMenu.config_dialog.
|
||||||
configDialog.ConfigDialog(self.top,'Settings')
|
configDialog.ConfigDialog(self.top,'Settings')
|
||||||
|
|
||||||
def config_extensions_dialog(self, event=None):
|
|
||||||
"Handle Options 'Configure Extensions' event."
|
|
||||||
configDialog.ConfigExtensionsDialog(self.top)
|
|
||||||
|
|
||||||
def help_dialog(self, event=None):
|
def help_dialog(self, event=None):
|
||||||
"Handle Help 'IDLE Help' event."
|
"Handle Help 'IDLE Help' event."
|
||||||
# Synchronize with macosxSupport.overrideRootMenu.help_dialog.
|
# Synchronize with macosxSupport.overrideRootMenu.help_dialog.
|
||||||
|
|
|
@ -80,12 +80,14 @@ class ConfigDialog(Toplevel):
|
||||||
|
|
||||||
def CreateWidgets(self):
|
def CreateWidgets(self):
|
||||||
self.tabPages = TabbedPageSet(self,
|
self.tabPages = TabbedPageSet(self,
|
||||||
page_names=['Fonts/Tabs', 'Highlighting', 'Keys', 'General'])
|
page_names=['Fonts/Tabs', 'Highlighting', 'Keys', 'General',
|
||||||
|
'Extensions'])
|
||||||
self.tabPages.pack(side=TOP, expand=TRUE, fill=BOTH)
|
self.tabPages.pack(side=TOP, expand=TRUE, fill=BOTH)
|
||||||
self.CreatePageFontTab()
|
self.CreatePageFontTab()
|
||||||
self.CreatePageHighlight()
|
self.CreatePageHighlight()
|
||||||
self.CreatePageKeys()
|
self.CreatePageKeys()
|
||||||
self.CreatePageGeneral()
|
self.CreatePageGeneral()
|
||||||
|
self.CreatePageExtensions()
|
||||||
self.create_action_buttons().pack(side=BOTTOM)
|
self.create_action_buttons().pack(side=BOTTOM)
|
||||||
|
|
||||||
def create_action_buttons(self):
|
def create_action_buttons(self):
|
||||||
|
@ -1092,6 +1094,7 @@ class ConfigDialog(Toplevel):
|
||||||
self.LoadKeyCfg()
|
self.LoadKeyCfg()
|
||||||
### general page
|
### general page
|
||||||
self.LoadGeneralCfg()
|
self.LoadGeneralCfg()
|
||||||
|
# note: extension page handled separately
|
||||||
|
|
||||||
def SaveNewKeySet(self, keySetName, keySet):
|
def SaveNewKeySet(self, keySetName, keySet):
|
||||||
"""
|
"""
|
||||||
|
@ -1145,6 +1148,7 @@ class ConfigDialog(Toplevel):
|
||||||
# save these even if unchanged!
|
# save these even if unchanged!
|
||||||
idleConf.userCfg[configType].Save()
|
idleConf.userCfg[configType].Save()
|
||||||
self.ResetChangedItems() #clear the changed items dict
|
self.ResetChangedItems() #clear the changed items dict
|
||||||
|
self.save_all_changed_extensions() # uses a different mechanism
|
||||||
|
|
||||||
def DeactivateCurrentConfig(self):
|
def DeactivateCurrentConfig(self):
|
||||||
#Before a config is saved, some cleanup of current
|
#Before a config is saved, some cleanup of current
|
||||||
|
@ -1180,6 +1184,168 @@ class ConfigDialog(Toplevel):
|
||||||
view_text(self, title='Help for IDLE preferences',
|
view_text(self, title='Help for IDLE preferences',
|
||||||
text=help_common+help_pages.get(page, ''))
|
text=help_common+help_pages.get(page, ''))
|
||||||
|
|
||||||
|
def CreatePageExtensions(self):
|
||||||
|
"""Part of the config dialog used for configuring IDLE extensions.
|
||||||
|
|
||||||
|
This code is generic - it works for any and all IDLE extensions.
|
||||||
|
|
||||||
|
IDLE extensions save their configuration options using idleConf.
|
||||||
|
This code reads the current configuration using idleConf, supplies a
|
||||||
|
GUI interface to change the configuration values, and saves the
|
||||||
|
changes using idleConf.
|
||||||
|
|
||||||
|
Not all changes take effect immediately - some may require restarting IDLE.
|
||||||
|
This depends on each extension's implementation.
|
||||||
|
|
||||||
|
All values are treated as text, and it is up to the user to supply
|
||||||
|
reasonable values. The only exception to this are the 'enable*' options,
|
||||||
|
which are boolean, and can be toggled with an True/False button.
|
||||||
|
"""
|
||||||
|
parent = self.parent
|
||||||
|
frame = self.tabPages.pages['Extensions'].frame
|
||||||
|
self.ext_defaultCfg = idleConf.defaultCfg['extensions']
|
||||||
|
self.ext_userCfg = idleConf.userCfg['extensions']
|
||||||
|
self.is_int = self.register(is_int)
|
||||||
|
self.load_extensions()
|
||||||
|
# create widgets - a listbox shows all available extensions, with the
|
||||||
|
# controls for the extension selected in the listbox to the right
|
||||||
|
self.extension_names = StringVar(self)
|
||||||
|
frame.rowconfigure(0, weight=1)
|
||||||
|
frame.columnconfigure(2, weight=1)
|
||||||
|
self.extension_list = Listbox(frame, listvariable=self.extension_names,
|
||||||
|
selectmode='browse')
|
||||||
|
self.extension_list.bind('<<ListboxSelect>>', self.extension_selected)
|
||||||
|
scroll = Scrollbar(frame, command=self.extension_list.yview)
|
||||||
|
self.extension_list.yscrollcommand=scroll.set
|
||||||
|
self.details_frame = LabelFrame(frame, width=250, height=250)
|
||||||
|
self.extension_list.grid(column=0, row=0, sticky='nws')
|
||||||
|
scroll.grid(column=1, row=0, sticky='ns')
|
||||||
|
self.details_frame.grid(column=2, row=0, sticky='nsew', padx=[10, 0])
|
||||||
|
frame.configure(padx=10, pady=10)
|
||||||
|
self.config_frame = {}
|
||||||
|
self.current_extension = None
|
||||||
|
|
||||||
|
self.outerframe = self # TEMPORARY
|
||||||
|
self.tabbed_page_set = self.extension_list # TEMPORARY
|
||||||
|
|
||||||
|
# create the frame holding controls for each extension
|
||||||
|
ext_names = ''
|
||||||
|
for ext_name in sorted(self.extensions):
|
||||||
|
self.create_extension_frame(ext_name)
|
||||||
|
ext_names = ext_names + '{' + ext_name + '} '
|
||||||
|
self.extension_names.set(ext_names)
|
||||||
|
self.extension_list.selection_set(0)
|
||||||
|
self.extension_selected(None)
|
||||||
|
|
||||||
|
def load_extensions(self):
|
||||||
|
"Fill self.extensions with data from the default and user configs."
|
||||||
|
self.extensions = {}
|
||||||
|
for ext_name in idleConf.GetExtensions(active_only=False):
|
||||||
|
self.extensions[ext_name] = []
|
||||||
|
|
||||||
|
for ext_name in self.extensions:
|
||||||
|
opt_list = sorted(self.ext_defaultCfg.GetOptionList(ext_name))
|
||||||
|
|
||||||
|
# bring 'enable' options to the beginning of the list
|
||||||
|
enables = [opt_name for opt_name in opt_list
|
||||||
|
if opt_name.startswith('enable')]
|
||||||
|
for opt_name in enables:
|
||||||
|
opt_list.remove(opt_name)
|
||||||
|
opt_list = enables + opt_list
|
||||||
|
|
||||||
|
for opt_name in opt_list:
|
||||||
|
def_str = self.ext_defaultCfg.Get(
|
||||||
|
ext_name, opt_name, raw=True)
|
||||||
|
try:
|
||||||
|
def_obj = {'True':True, 'False':False}[def_str]
|
||||||
|
opt_type = 'bool'
|
||||||
|
except KeyError:
|
||||||
|
try:
|
||||||
|
def_obj = int(def_str)
|
||||||
|
opt_type = 'int'
|
||||||
|
except ValueError:
|
||||||
|
def_obj = def_str
|
||||||
|
opt_type = None
|
||||||
|
try:
|
||||||
|
value = self.ext_userCfg.Get(
|
||||||
|
ext_name, opt_name, type=opt_type, raw=True,
|
||||||
|
default=def_obj)
|
||||||
|
except ValueError: # Need this until .Get fixed
|
||||||
|
value = def_obj # bad values overwritten by entry
|
||||||
|
var = StringVar(self)
|
||||||
|
var.set(str(value))
|
||||||
|
|
||||||
|
self.extensions[ext_name].append({'name': opt_name,
|
||||||
|
'type': opt_type,
|
||||||
|
'default': def_str,
|
||||||
|
'value': value,
|
||||||
|
'var': var,
|
||||||
|
})
|
||||||
|
|
||||||
|
def extension_selected(self, event):
|
||||||
|
newsel = self.extension_list.curselection()
|
||||||
|
if newsel:
|
||||||
|
newsel = self.extension_list.get(newsel)
|
||||||
|
if newsel is None or newsel != self.current_extension:
|
||||||
|
if self.current_extension:
|
||||||
|
self.details_frame.config(text='')
|
||||||
|
self.config_frame[self.current_extension].grid_forget()
|
||||||
|
self.current_extension = None
|
||||||
|
if newsel:
|
||||||
|
self.details_frame.config(text=newsel)
|
||||||
|
self.config_frame[newsel].grid(column=0, row=0, sticky='nsew')
|
||||||
|
self.current_extension = newsel
|
||||||
|
|
||||||
|
def create_extension_frame(self, ext_name):
|
||||||
|
"""Create a frame holding the widgets to configure one extension"""
|
||||||
|
f = VerticalScrolledFrame(self.details_frame, height=250, width=250)
|
||||||
|
self.config_frame[ext_name] = f
|
||||||
|
entry_area = f.interior
|
||||||
|
# create an entry for each configuration option
|
||||||
|
for row, opt in enumerate(self.extensions[ext_name]):
|
||||||
|
# create a row with a label and entry/checkbutton
|
||||||
|
label = Label(entry_area, text=opt['name'])
|
||||||
|
label.grid(row=row, column=0, sticky=NW)
|
||||||
|
var = opt['var']
|
||||||
|
if opt['type'] == 'bool':
|
||||||
|
Checkbutton(entry_area, textvariable=var, variable=var,
|
||||||
|
onvalue='True', offvalue='False',
|
||||||
|
indicatoron=FALSE, selectcolor='', width=8
|
||||||
|
).grid(row=row, column=1, sticky=W, padx=7)
|
||||||
|
elif opt['type'] == 'int':
|
||||||
|
Entry(entry_area, textvariable=var, validate='key',
|
||||||
|
validatecommand=(self.is_int, '%P')
|
||||||
|
).grid(row=row, column=1, sticky=NSEW, padx=7)
|
||||||
|
|
||||||
|
else:
|
||||||
|
Entry(entry_area, textvariable=var
|
||||||
|
).grid(row=row, column=1, sticky=NSEW, padx=7)
|
||||||
|
return
|
||||||
|
|
||||||
|
def set_extension_value(self, section, opt):
|
||||||
|
name = opt['name']
|
||||||
|
default = opt['default']
|
||||||
|
value = opt['var'].get().strip() or default
|
||||||
|
opt['var'].set(value)
|
||||||
|
# if self.defaultCfg.has_section(section):
|
||||||
|
# Currently, always true; if not, indent to return
|
||||||
|
if (value == default):
|
||||||
|
return self.ext_userCfg.RemoveOption(section, name)
|
||||||
|
# set the option
|
||||||
|
return self.ext_userCfg.SetOption(section, name, value)
|
||||||
|
|
||||||
|
def save_all_changed_extensions(self):
|
||||||
|
"""Save configuration changes to the user config file."""
|
||||||
|
has_changes = False
|
||||||
|
for ext_name in self.extensions:
|
||||||
|
options = self.extensions[ext_name]
|
||||||
|
for opt in options:
|
||||||
|
if self.set_extension_value(ext_name, opt):
|
||||||
|
has_changes = True
|
||||||
|
if has_changes:
|
||||||
|
self.ext_userCfg.Save()
|
||||||
|
|
||||||
|
|
||||||
help_common = '''\
|
help_common = '''\
|
||||||
When you click either the Apply or Ok buttons, settings in this
|
When you click either the Apply or Ok buttons, settings in this
|
||||||
dialog that are different from IDLE's default are saved in
|
dialog that are different from IDLE's default are saved in
|
||||||
|
@ -1198,6 +1364,17 @@ theme, with a different name.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def is_int(s):
|
||||||
|
"Return 's is blank or represents an int'"
|
||||||
|
if not s:
|
||||||
|
return True
|
||||||
|
try:
|
||||||
|
int(s)
|
||||||
|
return True
|
||||||
|
except ValueError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class VerticalScrolledFrame(Frame):
|
class VerticalScrolledFrame(Frame):
|
||||||
"""A pure Tkinter vertically scrollable frame.
|
"""A pure Tkinter vertically scrollable frame.
|
||||||
|
|
||||||
|
@ -1240,221 +1417,6 @@ class VerticalScrolledFrame(Frame):
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def is_int(s):
|
|
||||||
"Return 's is blank or represents an int'"
|
|
||||||
if not s:
|
|
||||||
return True
|
|
||||||
try:
|
|
||||||
int(s)
|
|
||||||
return True
|
|
||||||
except ValueError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# TODO:
|
|
||||||
# * Revert to default(s)? Per option or per extension?
|
|
||||||
# * List options in their original order (possible??)
|
|
||||||
class ConfigExtensionsDialog(Toplevel):
|
|
||||||
"""A dialog for configuring IDLE extensions.
|
|
||||||
|
|
||||||
This dialog is generic - it works for any and all IDLE extensions.
|
|
||||||
|
|
||||||
IDLE extensions save their configuration options using idleConf.
|
|
||||||
ConfigExtensionsDialog reads the current configuration using idleConf,
|
|
||||||
supplies a GUI interface to change the configuration values, and saves the
|
|
||||||
changes using idleConf.
|
|
||||||
|
|
||||||
Not all changes take effect immediately - some may require restarting IDLE.
|
|
||||||
This depends on each extension's implementation.
|
|
||||||
|
|
||||||
All values are treated as text, and it is up to the user to supply
|
|
||||||
reasonable values. The only exception to this are the 'enable*' options,
|
|
||||||
which are boolean, and can be toggled with an True/False button.
|
|
||||||
"""
|
|
||||||
def __init__(self, parent, title=None, _htest=False):
|
|
||||||
Toplevel.__init__(self, parent)
|
|
||||||
self.wm_withdraw()
|
|
||||||
|
|
||||||
self.configure(borderwidth=5)
|
|
||||||
self.geometry(
|
|
||||||
"+%d+%d" % (parent.winfo_rootx() + 20,
|
|
||||||
parent.winfo_rooty() + (30 if not _htest else 150)))
|
|
||||||
self.wm_title(title or 'IDLE Extensions Configuration')
|
|
||||||
|
|
||||||
self.defaultCfg = idleConf.defaultCfg['extensions']
|
|
||||||
self.userCfg = idleConf.userCfg['extensions']
|
|
||||||
self.is_int = self.register(is_int)
|
|
||||||
self.load_extensions()
|
|
||||||
self.create_widgets()
|
|
||||||
|
|
||||||
self.resizable(height=FALSE, width=FALSE) # don't allow resizing yet
|
|
||||||
self.transient(parent)
|
|
||||||
self.protocol("WM_DELETE_WINDOW", self.Cancel)
|
|
||||||
self.tabbed_page_set.focus_set()
|
|
||||||
# wait for window to be generated
|
|
||||||
self.update()
|
|
||||||
# set current width as the minimum width
|
|
||||||
self.wm_minsize(self.winfo_width(), 1)
|
|
||||||
# now allow resizing
|
|
||||||
self.resizable(height=TRUE, width=TRUE)
|
|
||||||
|
|
||||||
self.wm_deiconify()
|
|
||||||
if not _htest:
|
|
||||||
self.grab_set()
|
|
||||||
self.wait_window()
|
|
||||||
|
|
||||||
def load_extensions(self):
|
|
||||||
"Fill self.extensions with data from the default and user configs."
|
|
||||||
self.extensions = {}
|
|
||||||
for ext_name in idleConf.GetExtensions(active_only=False):
|
|
||||||
self.extensions[ext_name] = []
|
|
||||||
|
|
||||||
for ext_name in self.extensions:
|
|
||||||
opt_list = sorted(self.defaultCfg.GetOptionList(ext_name))
|
|
||||||
|
|
||||||
# bring 'enable' options to the beginning of the list
|
|
||||||
enables = [opt_name for opt_name in opt_list
|
|
||||||
if opt_name.startswith('enable')]
|
|
||||||
for opt_name in enables:
|
|
||||||
opt_list.remove(opt_name)
|
|
||||||
opt_list = enables + opt_list
|
|
||||||
|
|
||||||
for opt_name in opt_list:
|
|
||||||
def_str = self.defaultCfg.Get(
|
|
||||||
ext_name, opt_name, raw=True)
|
|
||||||
try:
|
|
||||||
def_obj = {'True':True, 'False':False}[def_str]
|
|
||||||
opt_type = 'bool'
|
|
||||||
except KeyError:
|
|
||||||
try:
|
|
||||||
def_obj = int(def_str)
|
|
||||||
opt_type = 'int'
|
|
||||||
except ValueError:
|
|
||||||
def_obj = def_str
|
|
||||||
opt_type = None
|
|
||||||
try:
|
|
||||||
value = self.userCfg.Get(
|
|
||||||
ext_name, opt_name, type=opt_type, raw=True,
|
|
||||||
default=def_obj)
|
|
||||||
except ValueError: # Need this until .Get fixed
|
|
||||||
value = def_obj # bad values overwritten by entry
|
|
||||||
var = StringVar(self)
|
|
||||||
var.set(str(value))
|
|
||||||
|
|
||||||
self.extensions[ext_name].append({'name': opt_name,
|
|
||||||
'type': opt_type,
|
|
||||||
'default': def_str,
|
|
||||||
'value': value,
|
|
||||||
'var': var,
|
|
||||||
})
|
|
||||||
|
|
||||||
def create_widgets(self):
|
|
||||||
"""Create the dialog's widgets."""
|
|
||||||
self.extension_names = StringVar(self)
|
|
||||||
self.rowconfigure(0, weight=1)
|
|
||||||
self.columnconfigure(2, weight=1)
|
|
||||||
self.extension_list = Listbox(self, listvariable=self.extension_names,
|
|
||||||
selectmode='browse')
|
|
||||||
self.extension_list.bind('<<ListboxSelect>>', self.extension_selected)
|
|
||||||
scroll = Scrollbar(self, command=self.extension_list.yview)
|
|
||||||
self.extension_list.yscrollcommand=scroll.set
|
|
||||||
self.details_frame = LabelFrame(self, width=250, height=250)
|
|
||||||
self.extension_list.grid(column=0, row=0, sticky='nws')
|
|
||||||
scroll.grid(column=1, row=0, sticky='ns')
|
|
||||||
self.details_frame.grid(column=2, row=0, sticky='nsew', padx=[10, 0])
|
|
||||||
self.configure(padx=10, pady=10)
|
|
||||||
self.config_frame = {}
|
|
||||||
self.current_extension = None
|
|
||||||
|
|
||||||
self.outerframe = self # TEMPORARY
|
|
||||||
self.tabbed_page_set = self.extension_list # TEMPORARY
|
|
||||||
|
|
||||||
# create the individual pages
|
|
||||||
ext_names = ''
|
|
||||||
for ext_name in sorted(self.extensions):
|
|
||||||
self.create_extension_frame(ext_name)
|
|
||||||
ext_names = ext_names + '{' + ext_name + '} '
|
|
||||||
self.extension_names.set(ext_names)
|
|
||||||
self.extension_list.selection_set(0)
|
|
||||||
self.extension_selected(None)
|
|
||||||
self.create_action_buttons().grid(row=1, columnspan=3)
|
|
||||||
|
|
||||||
def extension_selected(self, event):
|
|
||||||
newsel = self.extension_list.curselection()
|
|
||||||
if newsel:
|
|
||||||
newsel = self.extension_list.get(newsel)
|
|
||||||
if newsel is None or newsel != self.current_extension:
|
|
||||||
if self.current_extension:
|
|
||||||
self.details_frame.config(text='')
|
|
||||||
self.config_frame[self.current_extension].grid_forget()
|
|
||||||
self.current_extension = None
|
|
||||||
if newsel:
|
|
||||||
self.details_frame.config(text=newsel)
|
|
||||||
self.config_frame[newsel].grid(column=0, row=0, sticky='nsew')
|
|
||||||
self.current_extension = newsel
|
|
||||||
|
|
||||||
create_action_buttons = ConfigDialog.create_action_buttons
|
|
||||||
|
|
||||||
def create_extension_frame(self, ext_name):
|
|
||||||
"""Create a frame holding the widgets to configure one extension"""
|
|
||||||
f = VerticalScrolledFrame(self.details_frame, height=250, width=250)
|
|
||||||
self.config_frame[ext_name] = f
|
|
||||||
entry_area = f.interior
|
|
||||||
# create an entry for each configuration option
|
|
||||||
for row, opt in enumerate(self.extensions[ext_name]):
|
|
||||||
# create a row with a label and entry/checkbutton
|
|
||||||
label = Label(entry_area, text=opt['name'])
|
|
||||||
label.grid(row=row, column=0, sticky=NW)
|
|
||||||
var = opt['var']
|
|
||||||
if opt['type'] == 'bool':
|
|
||||||
Checkbutton(entry_area, textvariable=var, variable=var,
|
|
||||||
onvalue='True', offvalue='False',
|
|
||||||
indicatoron=FALSE, selectcolor='', width=8
|
|
||||||
).grid(row=row, column=1, sticky=W, padx=7)
|
|
||||||
elif opt['type'] == 'int':
|
|
||||||
Entry(entry_area, textvariable=var, validate='key',
|
|
||||||
validatecommand=(self.is_int, '%P')
|
|
||||||
).grid(row=row, column=1, sticky=NSEW, padx=7)
|
|
||||||
|
|
||||||
else:
|
|
||||||
Entry(entry_area, textvariable=var
|
|
||||||
).grid(row=row, column=1, sticky=NSEW, padx=7)
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
Ok = ConfigDialog.Ok
|
|
||||||
|
|
||||||
def Apply(self):
|
|
||||||
self.save_all_changed_configs()
|
|
||||||
pass
|
|
||||||
|
|
||||||
Cancel = ConfigDialog.Cancel
|
|
||||||
|
|
||||||
def Help(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def set_user_value(self, section, opt):
|
|
||||||
name = opt['name']
|
|
||||||
default = opt['default']
|
|
||||||
value = opt['var'].get().strip() or default
|
|
||||||
opt['var'].set(value)
|
|
||||||
# if self.defaultCfg.has_section(section):
|
|
||||||
# Currently, always true; if not, indent to return
|
|
||||||
if (value == default):
|
|
||||||
return self.userCfg.RemoveOption(section, name)
|
|
||||||
# set the option
|
|
||||||
return self.userCfg.SetOption(section, name, value)
|
|
||||||
|
|
||||||
def save_all_changed_configs(self):
|
|
||||||
"""Save configuration changes to the user config file."""
|
|
||||||
has_changes = False
|
|
||||||
for ext_name in self.extensions:
|
|
||||||
options = self.extensions[ext_name]
|
|
||||||
for opt in options:
|
|
||||||
if self.set_user_value(ext_name, opt):
|
|
||||||
has_changes = True
|
|
||||||
if has_changes:
|
|
||||||
self.userCfg.Save()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import unittest
|
import unittest
|
||||||
|
|
|
@ -266,16 +266,16 @@ access to locals and globals.</dd>
|
||||||
<h3>25.5.1.7. Options menu (Shell and Editor)<a class="headerlink" href="#options-menu-shell-and-editor" title="Permalink to this headline">¶</a></h3>
|
<h3>25.5.1.7. Options menu (Shell and Editor)<a class="headerlink" href="#options-menu-shell-and-editor" title="Permalink to this headline">¶</a></h3>
|
||||||
<dl class="docutils">
|
<dl class="docutils">
|
||||||
<dt>Configure IDLE</dt>
|
<dt>Configure IDLE</dt>
|
||||||
<dd>Open a configuration dialog. Fonts, indentation, keybindings, and color
|
<dd><p class="first">Open a configuration dialog and change preferences for the following:
|
||||||
themes may be altered. Startup Preferences may be set, and additional
|
fonts, indentation, keybindings, text color themes, startup windows and
|
||||||
help sources can be specified. Non-default user setting are saved in a
|
size, additional help sources, and extensions (see below). On OS X,
|
||||||
.idlerc directory in the user’s home directory. Problems caused by bad user
|
open the configuration dialog by selecting Preferences in the application
|
||||||
configuration files are solved by editing or deleting one or more of the
|
menu. To use a new built-in color theme (IDLE Dark) with older IDLEs,
|
||||||
files in .idlerc. On OS X, open the configuration dialog by selecting
|
save it as a new custom theme.</p>
|
||||||
Preferences in the application menu.</dd>
|
<p class="last">Non-default user settings are saved in a .idlerc directory in the user’s
|
||||||
<dt>Configure Extensions</dt>
|
home directory. Problems caused by bad user configuration files are solved
|
||||||
<dd>Open a configuration dialog for setting preferences for extensions
|
by editing or deleting one or more of the files in .idlerc.</p>
|
||||||
(discussed below). See note above about the location of user settings.</dd>
|
</dd>
|
||||||
<dt>Code Context (toggle)(Editor Window only)</dt>
|
<dt>Code Context (toggle)(Editor Window only)</dt>
|
||||||
<dd>Open a pane at the top of the edit window which shows the block context
|
<dd>Open a pane at the top of the edit window which shows the block context
|
||||||
of the code which has scrolled above the top of the window.</dd>
|
of the code which has scrolled above the top of the window.</dd>
|
||||||
|
@ -699,7 +699,7 @@ are currently:</p>
|
||||||
The Python Software Foundation is a non-profit corporation.
|
The Python Software Foundation is a non-profit corporation.
|
||||||
<a href="https://www.python.org/psf/donations/">Please donate.</a>
|
<a href="https://www.python.org/psf/donations/">Please donate.</a>
|
||||||
<br />
|
<br />
|
||||||
Last updated on Oct 02, 2015.
|
Last updated on Oct 13, 2015.
|
||||||
<a href="../bugs.html">Found a bug</a>?
|
<a href="../bugs.html">Found a bug</a>?
|
||||||
<br />
|
<br />
|
||||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.2.3.
|
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.2.3.
|
||||||
|
|
|
@ -93,15 +93,6 @@ _class_browser_spec = {
|
||||||
"Double clicking on items prints a traceback for an exception "
|
"Double clicking on items prints a traceback for an exception "
|
||||||
"that is ignored."
|
"that is ignored."
|
||||||
}
|
}
|
||||||
ConfigExtensionsDialog_spec = {
|
|
||||||
'file': 'configDialog',
|
|
||||||
'kwds': {'title': 'Test Extension Configuration',
|
|
||||||
'_htest': True,},
|
|
||||||
'msg': "IDLE extensions dialog.\n"
|
|
||||||
"\n[Ok] to close the dialog.[Apply] to apply the settings and "
|
|
||||||
"and [Cancel] to revert all changes.\nRe-run the test to ensure "
|
|
||||||
"changes made have persisted."
|
|
||||||
}
|
|
||||||
|
|
||||||
_color_delegator_spec = {
|
_color_delegator_spec = {
|
||||||
'file': 'ColorDelegator',
|
'file': 'ColorDelegator',
|
||||||
|
@ -121,7 +112,8 @@ ConfigDialog_spec = {
|
||||||
"font face of the text in the area below it.\nIn the "
|
"font face of the text in the area below it.\nIn the "
|
||||||
"'Highlighting' tab, try different color schemes. Clicking "
|
"'Highlighting' tab, try different color schemes. Clicking "
|
||||||
"items in the sample program should update the choices above it."
|
"items in the sample program should update the choices above it."
|
||||||
"\nIn the 'Keys' and 'General' tab, test settings of interest."
|
"\nIn the 'Keys', 'General' and 'Extensions' tabs, test settings"
|
||||||
|
"of interest."
|
||||||
"\n[Ok] to close the dialog.[Apply] to apply the settings and "
|
"\n[Ok] to close the dialog.[Apply] to apply the settings and "
|
||||||
"and [Cancel] to revert all changes.\nRe-run the test to ensure "
|
"and [Cancel] to revert all changes.\nRe-run the test to ensure "
|
||||||
"changes made have persisted."
|
"changes made have persisted."
|
||||||
|
|
Loading…
Reference in New Issue