summaryrefslogtreecommitdiffstats
path: root/Lib/idlelib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/idlelib')
-rw-r--r--Lib/idlelib/configdialog.py403
-rw-r--r--Lib/idlelib/idle_test/test_configdialog.py14
2 files changed, 216 insertions, 201 deletions
diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py
index 6638c06..9c0153b 100644
--- a/Lib/idlelib/configdialog.py
+++ b/Lib/idlelib/configdialog.py
@@ -112,11 +112,11 @@ class ConfigDialog(Toplevel):
self.frame = frame = Frame(self, padding="5px")
self.frame.grid(sticky="nwes")
self.note = note = Notebook(frame)
- self.highpage = HighPage(note)
+ self.extpage = ExtPage(note)
+ self.highpage = HighPage(note, self.extpage)
self.fontpage = FontPage(note, self.highpage)
- self.keyspage = KeysPage(note)
+ self.keyspage = KeysPage(note, self.extpage)
self.genpage = GenPage(note)
- self.extpage = self.create_page_extensions()
note.add(self.fontpage, text='Fonts/Tabs')
note.add(self.highpage, text='Highlights')
note.add(self.keyspage, text=' Keys ')
@@ -244,198 +244,6 @@ class ConfigDialog(Toplevel):
for klass in reloadables:
klass.reload()
- def create_page_extensions(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 a True/False button.
-
- Methods:
- load_extensions:
- extension_selected: Handle selection from list.
- create_extension_frame: Hold widgets for one extension.
- set_extension_value: Set in userCfg['extensions'].
- save_all_changed_extensions: Call extension page Save().
- """
- 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 = Frame(self.note)
- frame_ext = LabelFrame(frame, borderwidth=2, relief=GROOVE,
- text=' Feature Extensions ')
- frame_ext.rowconfigure(0, weight=1)
- frame_ext.columnconfigure(2, weight=1)
- self.extension_list = Listbox(frame_ext, listvariable=self.extension_names,
- selectmode='browse')
- self.extension_list.bind('<<ListboxSelect>>', self.extension_selected)
- scroll = Scrollbar(frame_ext, command=self.extension_list.yview)
- self.extension_list.yscrollcommand=scroll.set
- self.details_frame = LabelFrame(frame_ext, 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_ext.configure(padding=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)
-
-
- self.frame_help = HelpFrame(frame, borderwidth=2, relief=GROOVE,
- text=' Help Menu Extensions ')
- frame_ext.grid(row=0, column=0, sticky='nsew')
- Label(frame).grid(row=1, column=0)
- self.frame_help.grid(row=2, column=0, sticky='sew')
-
- return frame
-
- 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):
- # Former built-in extensions are already filtered out.
- 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):
- "Handle selection of an extension from the list."
- 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, variable=var,
- onvalue='True', offvalue='False', 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'), width=10
- ).grid(row=row, column=1, sticky=NSEW, padx=7)
-
- else: # type == 'str'
- # Limit size to fit non-expanding space with larger font.
- Entry(entry_area, textvariable=var, width=15
- ).grid(row=row, column=1, sticky=NSEW, padx=7)
- return
-
- def set_extension_value(self, section, opt):
- """Return True if the configuration was added or changed.
-
- If the value is the same as the default, then remove it
- from user config file.
- """
- 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.
-
- Attributes accessed:
- extensions
-
- Methods:
- set_extension_value
- """
- 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()
-
# class TabPage(Frame): # A template for Page classes.
# def __init__(self, master):
@@ -695,8 +503,9 @@ class FontPage(Frame):
class HighPage(Frame):
- def __init__(self, master):
+ def __init__(self, master, extpage):
super().__init__(master)
+ self.extpage = extpage
self.cd = master.winfo_toplevel()
self.style = Style(master)
self.create_page_highlight()
@@ -1347,15 +1156,16 @@ class HighPage(Frame):
self.builtin_name.set(idleConf.defaultCfg['main'].Get('Theme', 'name'))
# User can't back out of these changes, they must be applied now.
changes.save_all()
- self.cd.save_all_changed_extensions()
+ self.extpage.save_all_changed_extensions()
self.cd.activate_config_changes()
self.set_theme_type()
class KeysPage(Frame):
- def __init__(self, master):
+ def __init__(self, master, extpage):
super().__init__(master)
+ self.extpage = extpage
self.cd = master.winfo_toplevel()
self.create_page_keys()
self.load_key_cfg()
@@ -1779,7 +1589,7 @@ class KeysPage(Frame):
or idleConf.default_keys())
# User can't back out of these changes, they must be applied now.
changes.save_all()
- self.cd.save_all_changed_extensions()
+ self.extpage.save_all_changed_extensions()
self.cd.activate_config_changes()
self.set_keys_type()
@@ -2094,6 +1904,201 @@ class GenPage(Frame):
'main', 'PyShell', 'auto-squeeze-min-lines', type='int'))
+class ExtPage(Frame):
+ def __init__(self, master):
+ super().__init__(master)
+ self.ext_defaultCfg = idleConf.defaultCfg['extensions']
+ self.ext_userCfg = idleConf.userCfg['extensions']
+ self.is_int = self.register(is_int)
+ self.load_extensions()
+ self.create_page_extensions() # Requires extension names.
+
+ def create_page_extensions(self):
+ """Configure IDLE feature extensions and help menu extensions.
+
+ List the feature extensions and a configuration box for the
+ selected extension. Help menu extensions are in a HelpFrame.
+
+ This code reads the current configuration using idleConf,
+ supplies a GUI interface to change the configuration values,
+ and saves the changes using idleConf.
+
+ Some changes 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 a
+ True/False button.
+
+ Methods:
+ extension_selected: Handle selection from list.
+ create_extension_frame: Hold widgets for one extension.
+ set_extension_value: Set in userCfg['extensions'].
+ save_all_changed_extensions: Call extension page Save().
+ """
+ self.extension_names = StringVar(self)
+
+ frame_ext = LabelFrame(self, borderwidth=2, relief=GROOVE,
+ text=' Feature Extensions ')
+ self.frame_help = HelpFrame(self, borderwidth=2, relief=GROOVE,
+ text=' Help Menu Extensions ')
+
+ frame_ext.rowconfigure(0, weight=1)
+ frame_ext.columnconfigure(2, weight=1)
+ self.extension_list = Listbox(frame_ext, listvariable=self.extension_names,
+ selectmode='browse')
+ self.extension_list.bind('<<ListboxSelect>>', self.extension_selected)
+ scroll = Scrollbar(frame_ext, command=self.extension_list.yview)
+ self.extension_list.yscrollcommand=scroll.set
+ self.details_frame = LabelFrame(frame_ext, 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_ext.configure(padding=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)
+
+
+ frame_ext.grid(row=0, column=0, sticky='nsew')
+ Label(self).grid(row=1, column=0) # Spacer. Replace with config?
+ self.frame_help.grid(row=2, column=0, sticky='sew')
+
+ 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):
+ # Former built-in extensions are already filtered out.
+ 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):
+ "Handle selection of an extension from the list."
+ 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, variable=var,
+ onvalue='True', offvalue='False', 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'), width=10
+ ).grid(row=row, column=1, sticky=NSEW, padx=7)
+
+ else: # type == 'str'
+ # Limit size to fit non-expanding space with larger font.
+ Entry(entry_area, textvariable=var, width=15
+ ).grid(row=row, column=1, sticky=NSEW, padx=7)
+ return
+
+ def set_extension_value(self, section, opt):
+ """Return True if the configuration was added or changed.
+
+ If the value is the same as the default, then remove it
+ from user config file.
+ """
+ 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.
+
+ Attributes accessed:
+ extensions
+
+ Methods:
+ set_extension_value
+ """
+ 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()
+
+
class HelpFrame(LabelFrame):
def __init__(self, master, **cfg):
diff --git a/Lib/idlelib/idle_test/test_configdialog.py b/Lib/idlelib/idle_test/test_configdialog.py
index 214d1b3..e01aa63 100644
--- a/Lib/idlelib/idle_test/test_configdialog.py
+++ b/Lib/idlelib/idle_test/test_configdialog.py
@@ -1292,12 +1292,22 @@ class GenPageTest(unittest.TestCase):
self.assertEqual(extpage, {'CodeContext': {'maxlines': '1'}})
+#unittest.skip("Nothing here yet TODO")
+class ExtPageTest(unittest.TestCase):
+ """Test that the help source list works correctly."""
+ @classmethod
+ def setUpClass(cls):
+ page = dialog.extpage
+ dialog.note.select(page)
+
+
class HelpSourceTest(unittest.TestCase):
"""Test that the help source list works correctly."""
@classmethod
def setUpClass(cls):
- dialog.note.select(dialog.extpage)
- frame = cls.frame = dialog.frame_help
+ page = dialog.extpage
+ dialog.note.select(page)
+ frame = cls.frame = page.frame_help
frame.set = frame.set_add_delete_state = Func()
frame.upc = frame.update_help_changes = Func()
frame.update()