Browse Source

Merge pull request #119 from Shura1oplot/quoting

Separate boxes used to input command line parts and other data
pull/128/head
Chris 9 years ago
parent
commit
a8ba3c766c
5 changed files with 80 additions and 41 deletions
  1. 4
      gooey/gui/util/quoting.py
  2. 18
      gooey/gui/widgets/components.py
  3. 83
      gooey/gui/widgets/widget_pack.py
  4. 10
      gooey/gui/windows/advanced_config.py
  5. 6
      gooey/gui/windows/layouts.py

4
gooey/gui/util/quoting.py

@ -8,7 +8,3 @@ if sys.platform.startswith("win"):
else: # POSIX shell else: # POSIX shell
def quote(value): def quote(value):
return "'{}'".format('{}'.format(value).replace("'", "'\\''")) return "'{}'".format('{}'.format(value).replace("'", "'\\''"))
def maybe_quote(string):
return '"{}"'.format(string) if not re.match(r'^".*"$', string) else string

18
gooey/gui/widgets/components.py

@ -97,6 +97,9 @@ class BaseGuiComponent(object):
def GetValue(self): def GetValue(self):
return self.widget_pack.getValue() return self.widget_pack.getValue()
def HasOptionString(self):
return bool(self.widget_pack.option_string)
def _GetWidget(self): def _GetWidget(self):
# used only for unittesting # used only for unittesting
return self.widget_pack.widget return self.widget_pack.widget
@ -142,7 +145,7 @@ class CheckBox(BaseGuiComponent):
return self.panel return self.panel
def onSetter(self, evt): def onSetter(self, evt):
self.getValue()
self.GetValue()
def onResize(self, evt): def onResize(self, evt):
msg = self.help_msg msg = self.help_msg
@ -157,6 +160,9 @@ class CheckBox(BaseGuiComponent):
def GetValue(self): def GetValue(self):
return self.option_strings if self.widget.GetValue() else '' return self.option_strings if self.widget.GetValue() else ''
def HasOptionString(self):
return bool(self.option_strings)
def _GetWidget(self): def _GetWidget(self):
return self.widget return self.widget
@ -168,7 +174,7 @@ class RadioGroup(object):
self.data = data self.data = data
self.radio_buttons = [] self.radio_buttons = []
self.option_stings = []
self.option_strings = []
self.help_msgs = [] self.help_msgs = []
self.btn_names = [] self.btn_names = []
@ -181,7 +187,7 @@ class RadioGroup(object):
self.radio_buttons = [wx.RadioButton(self.panel, -1) for _ in self.data] self.radio_buttons = [wx.RadioButton(self.panel, -1) for _ in self.data]
self.btn_names = [wx.StaticText(self.panel, label=btn_data['display_name'].title()) for btn_data in self.data] self.btn_names = [wx.StaticText(self.panel, label=btn_data['display_name'].title()) for btn_data in self.data]
self.help_msgs = [wx.StaticText(self.panel, label=btn_data['help'].title()) for btn_data in self.data] self.help_msgs = [wx.StaticText(self.panel, label=btn_data['help'].title()) for btn_data in self.data]
self.option_stings = [btn_data['commands'] for btn_data in self.data]
self.option_strings = [btn_data['commands'] for btn_data in self.data]
# box = wx.StaticBox(self.panel, -1, label=self.data['group_name']) # box = wx.StaticBox(self.panel, -1, label=self.data['group_name'])
box = wx.StaticBox(self.panel, -1, label='') box = wx.StaticBox(self.panel, -1, label='')
@ -205,7 +211,7 @@ class RadioGroup(object):
return self.panel return self.panel
def onSetter(self, evt): def onSetter(self, evt):
self.getValue()
self.GetValue()
def onResize(self, evt): def onResize(self, evt):
msg = self.help_msgs[0] msg = self.help_msgs[0]
@ -224,6 +230,9 @@ class RadioGroup(object):
except: except:
return '' return ''
def HasOptionString(self):
return bool(self.option_strings)
def _GetWidget(self): def _GetWidget(self):
return self.radio_buttons return self.radio_buttons
@ -234,6 +243,7 @@ DirChooser = lambda data: BaseGuiComponent(data=data, widget_pack=widget_
FileSaver = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.FileSaverPayload()) FileSaver = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.FileSaverPayload())
DateChooser = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.DateChooserPayload()) DateChooser = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.DateChooserPayload())
TextField = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.TextInputPayload()) TextField = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.TextInputPayload())
CommandField = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.TextInputPayload(no_qouting=True))
Dropdown = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.DropdownPayload()) Dropdown = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.DropdownPayload())
Counter = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.CounterPayload()) Counter = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.CounterPayload())
MultiDirChooser = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.MultiDirChooserPayload()) MultiDirChooser = lambda data: BaseGuiComponent(data=data, widget_pack=widget_pack.MultiDirChooserPayload())

83
gooey/gui/widgets/widget_pack.py

@ -1,8 +1,7 @@
from functools import partial from functools import partial
import re
from gooey.gui.lang import i18n from gooey.gui.lang import i18n
from gooey.gui.util.filedrop import FileDrop from gooey.gui.util.filedrop import FileDrop
from gooey.gui.util.quoting import maybe_quote
from gooey.gui.util.quoting import quote
__author__ = 'Chris' __author__ = 'Chris'
@ -37,7 +36,12 @@ class WidgetPack(object):
def get_command(data): def get_command(data):
return data['commands'][0] if data['commands'] else '' return data['commands'][0] if data['commands'] else ''
@staticmethod
def disable_quoting(data):
nargs = data.get('nargs', None)
if not nargs:
return False
return nargs not in (1, '?')
class BaseChooser(WidgetPack): class BaseChooser(WidgetPack):
@ -48,9 +52,9 @@ class BaseChooser(WidgetPack):
self.text_box = None self.text_box = None
self.button = None self.button = None
def build(self, parent, data=None):
def build(self, parent, data):
self.parent = parent self.parent = parent
self.option_string = data['commands'][0] if data['commands'] else ''
self.option_string = self.get_command(data)
self.text_box = wx.TextCtrl(self.parent) self.text_box = wx.TextCtrl(self.parent)
self.text_box.AppendText(safe_default(data, '')) self.text_box.AppendText(safe_default(data, ''))
self.text_box.SetMinSize((0, -1)) self.text_box.SetMinSize((0, -1))
@ -69,14 +73,13 @@ class BaseChooser(WidgetPack):
def getValue(self): def getValue(self):
value = self.text_box.GetValue() value = self.text_box.GetValue()
if self.option_string and value: if self.option_string and value:
return '{0} {1}'.format(self.option_string, maybe_quote(value))
return '{0} {1}'.format(self.option_string, quote(value))
else: else:
return maybe_quote(value) if value else ''
return quote(value) if value else ''
def onButton(self, evt): def onButton(self, evt):
raise NotImplementedError raise NotImplementedError
def __repr__(self): def __repr__(self):
return self.__class__.__name__ return self.__class__.__name__
@ -95,15 +98,26 @@ class BaseFileChooser(BaseChooser):
self.text_box.SetValue(result) self.text_box.SetValue(result)
def get_path(self, dlg): def get_path(self, dlg):
if isinstance(dlg, wx.DirDialog) or isinstance(dlg, CalendarDlg):
return maybe_quote(dlg.GetPath())
else:
paths = dlg.GetPaths()
return maybe_quote(paths[0]) if len(paths) < 2 else ' '.join(map(maybe_quote, paths))
return dlg.GetPath()
class BaseMultiFileChooser(BaseFileChooser):
def __init__(self, dialog):
BaseFileChooser.__init__(self, dialog)
def getValue(self):
value = ' '.join(quote(x) for x in self.text_box.GetValue().split(os.pathsep) if x)
if self.option_string and value:
return '{} {}'.format(self.option_string, value)
return value or ''
def get_path(self, dlg):
return os.pathsep.join(dlg.GetPaths())
class MyMultiDirChooser(MDD.MultiDirDialog): class MyMultiDirChooser(MDD.MultiDirDialog):
def __init(self, *args, **kwargs):
super(MyMultiDirChooser,self).__init__(*args, **kwargs)
def __init__(self, *args, **kwargs):
super(MyMultiDirChooser, self).__init__(*args, **kwargs)
def GetPaths(self): def GetPaths(self):
return self.dirCtrl.GetPaths() return self.dirCtrl.GetPaths()
@ -117,18 +131,21 @@ def build_dialog(style, exist_constraint=True, **kwargs):
FileChooserPayload = partial(BaseFileChooser, dialog=build_dialog(wx.FD_OPEN)) FileChooserPayload = partial(BaseFileChooser, dialog=build_dialog(wx.FD_OPEN))
FileSaverPayload = partial(BaseFileChooser, dialog=build_dialog(wx.FD_SAVE, False, defaultFile="Enter Filename")) FileSaverPayload = partial(BaseFileChooser, dialog=build_dialog(wx.FD_SAVE, False, defaultFile="Enter Filename"))
MultiFileSaverPayload = partial(BaseFileChooser, dialog=build_dialog(wx.FD_MULTIPLE, False))
MultiFileSaverPayload = partial(BaseMultiFileChooser, dialog=build_dialog(wx.FD_MULTIPLE, False))
DirChooserPayload = partial(BaseFileChooser, dialog=lambda parent: wx.DirDialog(parent, 'Select Directory', style=wx.DD_DEFAULT_STYLE)) DirChooserPayload = partial(BaseFileChooser, dialog=lambda parent: wx.DirDialog(parent, 'Select Directory', style=wx.DD_DEFAULT_STYLE))
DateChooserPayload = partial(BaseFileChooser, dialog=CalendarDlg) DateChooserPayload = partial(BaseFileChooser, dialog=CalendarDlg)
MultiDirChooserPayload = partial(BaseFileChooser, dialog=lambda parent: MyMultiDirChooser(parent, title="Select Directories", defaultPath=os.getcwd(), agwStyle=MDD.DD_MULTIPLE|MDD.DD_DIR_MUST_EXIST))
MultiDirChooserPayload = partial(BaseMultiFileChooser, dialog=lambda parent: MyMultiDirChooser(parent, title="Select Directories", defaultPath=os.getcwd(), agwStyle=MDD.DD_MULTIPLE|MDD.DD_DIR_MUST_EXIST))
class TextInputPayload(WidgetPack): class TextInputPayload(WidgetPack):
def __init__(self):
def __init__(self, no_quoting=False):
self.widget = None self.widget = None
self.option_string = None self.option_string = None
self.no_quoting = no_quoting
def build(self, parent, data): def build(self, parent, data):
self.option_string = self.get_command(data) self.option_string = self.get_command(data)
if self.disable_quoting(data):
self.no_quoting = True
self.widget = wx.TextCtrl(parent) self.widget = wx.TextCtrl(parent)
dt = FileDrop(self.widget) dt = FileDrop(self.widget)
self.widget.SetDropTarget(dt) self.widget.SetDropTarget(dt)
@ -138,11 +155,15 @@ class TextInputPayload(WidgetPack):
return self.widget return self.widget
def getValue(self): def getValue(self):
if self.no_quoting:
_quote = lambda value: value
else:
_quote = quote
value = self.widget.GetValue() value = self.widget.GetValue()
if value and self.option_string: if value and self.option_string:
return '{} {}'.format(self.option_string, value)
return '{} {}'.format(self.option_string, _quote(value))
else: else:
return '"{}"'.format(value) if value else ''
return _quote(value) if value else ''
def _SetValue(self, text): def _SetValue(self, text):
# used for testing # used for testing
@ -152,12 +173,15 @@ class TextInputPayload(WidgetPack):
class DropdownPayload(WidgetPack): class DropdownPayload(WidgetPack):
default_value = 'Select Option' default_value = 'Select Option'
def __init__(self):
self.option_string = None
def __init__(self, no_quoting=False):
self.widget = None self.widget = None
self.option_string = None
self.no_quoting = no_quoting
def build(self, parent, data): def build(self, parent, data):
self.option_string = self.get_command(data) self.option_string = self.get_command(data)
if self.disable_quoting(data):
self.no_quoting = True
self.widget = wx.ComboBox( self.widget = wx.ComboBox(
parent=parent, parent=parent,
id=-1, id=-1,
@ -168,12 +192,17 @@ class DropdownPayload(WidgetPack):
return self.widget return self.widget
def getValue(self): def getValue(self):
if self.widget.GetValue() == self.default_value:
if self.no_quoting:
_quote = lambda value: value
else:
_quote = quote
value = self.widget.GetValue()
if value == self.default_value:
return '' return ''
elif self.widget.GetValue() and self.option_string:
return '{} {}'.format(self.option_string, self.widget.GetValue())
elif value and self.option_string:
return '{} {}'.format(self.option_string, _quote(value))
else: else:
return self.widget.GetValue()
return _quote(value) if value else ''
def _SetValue(self, text): def _SetValue(self, text):
# used for testing # used for testing
@ -212,4 +241,4 @@ class CounterPayload(WidgetPack):
def safe_default(data, default): def safe_default(data, default):
# str(None) is 'None'!? Whaaaaat...? # str(None) is 'None'!? Whaaaaat...?
return str(data['default']) if data['default'] else ''
return str(data['default']) if data['default'] else default

10
gooey/gui/windows/advanced_config.py

@ -93,10 +93,12 @@ class ConfigPanel(ScrolledPanel, OptionReader):
""" """
returns the collective values from all of the returns the collective values from all of the
widgets contained in the panel""" widgets contained in the panel"""
values = [c.GetValue()
for c in chain(*self.widgets)
if c.GetValue() is not None]
return ' '.join(values)
_f = lambda lst: [x for x in lst if x is not None]
optional_args = _f([c.GetValue() for c in self.widgets.optional_args])
required_args = _f([c.GetValue() for c in self.widgets.required_args if c.HasOptionString()])
position_args = _f([c.GetValue() for c in self.widgets.required_args if not c.HasOptionString()])
if position_args: position_args.insert(0, "--")
return ' '.join(chain(required_args, optional_args, position_args))
def GetRequiredArgs(self): def GetRequiredArgs(self):
return [arg.GetValue() for arg in self.widgets.required_args] return [arg.GetValue() for arg in self.widgets.required_args]

6
gooey/gui/windows/layouts.py

@ -6,10 +6,12 @@ from gooey.gui import events
from gooey.gui.windows.advanced_config import ConfigPanel from gooey.gui.windows.advanced_config import ConfigPanel
from gooey.gui.windows.sidebar import Sidebar from gooey.gui.windows.sidebar import Sidebar
from gooey.gui.util import wx_util from gooey.gui.util import wx_util
from gooey.gui.util.quoting import quote
basic_config = { basic_config = {
'required': [{ 'required': [{
'type': 'TextField',
'type': 'CommandField',
'data': { 'data': {
'display_name': 'Enter Commands', 'display_name': 'Enter Commands',
'help': 'Enter command line arguments', 'help': 'Enter command line arguments',
@ -77,7 +79,7 @@ class ColumnLayout(wx.Panel):
return panels return panels
def GetOptions(self): def GetOptions(self):
return '{} {}'.format(self.active_panel, self.config_panels[self.active_panel].GetOptions())
return '{} {}'.format(quote(self.active_panel), self.config_panels[self.active_panel].GetOptions())
def GetRequiredArgs(self): def GetRequiredArgs(self):
return self.config_panels[self.active_panel].GetRequiredArgs() return self.config_panels[self.active_panel].GetRequiredArgs()

Loading…
Cancel
Save