"""
FtpCube
Copyright (C) Michael Gilfix
This file is part of FtpCube.
You should have received a file COPYING containing license terms
along with this program; if not, write to Michael Gilfix
(mgilfix@eecs.tufts.edu) for a copy.
This version of FtpCube is open source; you can redistribute it and/or
modify it under the terms listed in the file COPYING.
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.
"""
import dialog
import utils
import wx
import wx.lib.colourchooser
class OptionWindow(dialog.DialogWindow):
"""Application options window.
This window allows the user to configure options for the application. Options are returned
in a dictionary, which can be used to update the application global configuration object.
The option window features three tabs: a connections options tab, logging options, and
logging color selection."""
def __init__(self, parent, opts=None):
"""Creates the options window."""
if __debug__:
print "Making option window."
dialog.DialogWindow.__init__(self, parent, _("Ftpcube - Options"))
self.SetIcon(utils.getAppIcon())
panel = self.getDialogPanel()
notebook = wx.Notebook(panel, -1)
self.connection_tab = ConnectionTab(notebook, opts)
notebook.AddPage(self.connection_tab, _("Connections"))
self.logging_tab = LoggingTab(notebook, opts)
notebook.AddPage(self.logging_tab, _("Logging"))
self.colors_tab = ColorsTab(notebook, opts)
notebook.AddPage(self.colors_tab, _("Colors"))
esizer = wx.BoxSizer(wx.VERTICAL)
esizer.Add(notebook, 1, wx.EXPAND)
panel.SetAutoLayout(True)
panel.SetSizer(esizer)
esizer.Fit(panel)
esizer.SetSizeHints(panel)
self.SetSizeHints(450, -1)
self.renderDialog()
def getOptions(self):
"""Returns a dictionary of configuration options that result from the options
window."""
opts = { }
try:
opts.update(self.connection_tab.getOptions())
opts.update(self.logging_tab.getOptions())
opts.update(self.colors_tab.getOptions())
except:
return opts
class ConnectionTab(wx.Panel):
"""Connections options tab."""
def __init__(self, parent, opts=None):
"""Creates the connection tab."""
wx.Panel.__init__(self, parent, -1)
ctimeout_label = wx.StaticText(self, -1, _("Connection Timeout:"))
idle_label = wx.StaticText(self, -1, _("Idle Timeout:"))
delay_label = wx.StaticText(self, -1, _("Delay Between Retries:"))
attempts_label = wx.StaticText(self, -1, _("Number of Attempts:"))
self.ctimeout_entry = wx.TextCtrl(self, -1)
if opts and opts['timeout']:
self.ctimeout_entry.SetValue(str(opts['timeout']))
self.idle_entry = wx.TextCtrl(self, -1)
if opts and opts['main_idle']:
self.idle_entry.SetValue(str(opts['main_idle']))
self.delay_entry = wx.TextCtrl(self, -1)
if opts and opts['delay']:
self.delay_entry.SetValue(str(opts['delay']))
self.attempts_entry = wx.TextCtrl(self, -1)
if opts and opts['retries']:
self.attempts_entry.SetValue(str(opts['retries']))
slabel1 = wx.StaticText(self, -1, _("(seconds)"))
slabel2 = wx.StaticText(self, -1, _("(seconds)"))
slabel3 = wx.StaticText(self, -1, _("(seconds)"))
self.passive_box = wx.CheckBox(self, -1, _("Default to Passive Transfers"))
if opts and opts['passive']:
self.passive_box.SetValue(True)
tsizer = wx.FlexGridSizer(5, 5)
tsizer.AddMany([
((5, 1)),
(ctimeout_label, 0, wx.ALIGN_CENTER_VERTICAL),
(self.ctimeout_entry, 0, wx.EXPAND),
(slabel1, 0, wx.ALIGN_CENTER_VERTICAL),
((5, 1)),
((5, 1)),
(idle_label, 0, wx.ALIGN_CENTER_VERTICAL),
(self.idle_entry, 0, wx.EXPAND),
(slabel2, 0, wx.ALIGN_CENTER_VERTICAL),
((5, 1)),
((5, 1)),
(delay_label, 0, wx.ALIGN_CENTER_VERTICAL),
(self.delay_entry, 0, wx.EXPAND),
(slabel3, 0, wx.ALIGN_CENTER_VERTICAL),
((5, 1)),
((5, 1)),
(attempts_label, 0, wx.ALIGN_CENTER_VERTICAL),
(self.attempts_entry, 0, wx.EXPAND),
((1, 1)),
((5, 1)),
])
tsizer.AddGrowableCol(2)
tsizer.SetHGap(10)
tsizer.SetVGap(7)
box = wx.StaticBox(self, -1, _("Connection Parameters"))
bsizer1 = wx.StaticBoxSizer(box, wx.VERTICAL)
bsizer1.Add((5, 7))
bsizer1.Add(tsizer, 1, wx.EXPAND)
bsizer1.Add((5, 10))
bsizer1.Add(self.passive_box, 0, wx.ALIGN_CENTER_HORIZONTAL)
bsizer1.Add((5, 7))
fsizer1 = wx.FlexGridSizer(3, 3)
fsizer1.AddMany([
((10, 10)), ((10, 10)), ((10, 10)),
((10, 10)), (bsizer1, 1, wx.EXPAND), ((10, 10)),
((10, 10)), ((10, 10)), ((10, 10)),
])
fsizer1.AddGrowableCol(1)
fsizer1.AddGrowableRow(1)
tidle_label = wx.StaticText(self, -1, _("Thread Idle Timeout:"))
self.tidle_entry = wx.TextCtrl(self, -1)
if opts and opts['thread_idle']:
self.tidle_entry.SetValue(str(opts['thread_idle']))
self.tidle_entry.SetSize((100, -1))
slabel4 = wx.StaticText(self, -1, _("(seconds)"))
hsizer = wx.BoxSizer(wx.HORIZONTAL)
hsizer.Add((25, 1))
hsizer.Add(tidle_label, 0, wx.ALIGN_CENTER_VERTICAL)
hsizer.Add((10, 1), 1, wx.EXPAND)
hsizer.Add(self.tidle_entry, 0, wx.EXPAND)
hsizer.Add((10, 1), 1, wx.EXPAND)
hsizer.Add(slabel4, 0, wx.ALIGN_CENTER_VERTICAL)
hsizer.Add((15, 1))
box = wx.StaticBox(self, -1, _("Thread Options"))
bsizer2 = wx.StaticBoxSizer(box, wx.VERTICAL)
bsizer2.Add((5, 7))
bsizer2.Add(hsizer, 1, wx.EXPAND)
bsizer2.Add((5, 7))
fsizer2 = wx.FlexGridSizer(3, 3)
fsizer2.AddMany([
((10, 10)), ((10, 10)), ((10, 10)),
((10, 10)), (bsizer2, 1, wx.EXPAND), ((10, 10)),
((10, 10)), ((10, 10)), ((10, 10)),
])
fsizer2.AddGrowableCol(1)
fsizer2.AddGrowableRow(1)
box = wx.StaticBox(self, -1, _("Default Connection Settings"))
boxsizer = wx.StaticBoxSizer(box, wx.VERTICAL)
boxsizer.Add(fsizer1, 0, wx.EXPAND)
boxsizer.Add(fsizer2, 0, wx.EXPAND)
sizer = wx.FlexGridSizer(3, 3)
sizer.AddMany([
((10, 10)), ((10, 10)), ((10, 10)),
((10, 10)), (boxsizer, 1, wx.EXPAND), ((10, 10)),
((10, 10)), ((10, 10)), ((10, 10)),
])
sizer.AddGrowableCol(1)
sizer.AddGrowableRow(1)
self.SetAutoLayout(True)
self.SetSizer(sizer)
sizer.Fit(self)
sizer.SetSizeHints(self)
def getOptions(self):
"""Returns a dictionary containing the configuration options for this tab."""
opts = { }
if self.ctimeout_entry.GetValue():
opts['timeout'] = int(self.ctimeout_entry.GetValue())
if self.idle_entry.GetValue():
opts['main_idle'] = int(self.idle_entry.GetValue())
if self.delay_entry.GetValue():
opts['delay'] = int(self.delay_entry.GetValue())
if self.attempts_entry.GetValue():
opts['retries'] = int(self.attempts_entry.GetValue())
if self.tidle_entry.GetValue():
opts['thread_idle'] = int(self.tidle_entry.GetValue())
opts['passive'] = bool(self.passive_box.GetValue())
return opts
class LoggingTab(wx.Panel):
"""Logging configuration tab.
This tab allows for configuration of whether to enable logging for commands, downloads,
and uploads. The tab also allows for the specification of the file names for the
logs. The logs are stored in the configuration directory for Ftpcube."""
idRADIO_ACTIVATE = wx.NewId()
idRADIO_DEACTIVATE = wx.NewId()
def __init__(self, parent, opts=None):
"""Create logging tab."""
wx.Panel.__init__(self, parent, -1)
self.activate_button = wx.RadioButton(self, self.idRADIO_ACTIVATE,
_("Turn ON Logging"))
self.deactivate_button = wx.RadioButton(self, self.idRADIO_DEACTIVATE,
_("Turn OFF Logging"))
self.deactivate_button.SetValue(True)
self.log = False
if opts and int(opts['logging']):
self.activate_button.SetValue(True)
self.log = True
self.Bind(wx.EVT_RADIOBUTTON, self.onActivate, id=self.idRADIO_ACTIVATE)
self.Bind(wx.EVT_RADIOBUTTON, self.onDeactivate, id=self.idRADIO_DEACTIVATE)
hsizer1 = wx.BoxSizer(wx.HORIZONTAL)
hsizer1.Add((1, 1), 1, wx.EXPAND)
hsizer1.Add(self.activate_button, 0, wx.EXPAND)
hsizer1.Add((1, 1), 1, wx.EXPAND)
hsizer1.Add(self.deactivate_button, 0, wx.EXPAND)
hsizer1.Add((1, 1), 1, wx.EXPAND)
box = wx.StaticBox(self, -1, _("Activate Logging"))
bsizer1 = wx.StaticBoxSizer(box, wx.VERTICAL)
bsizer1.Add((5, 7))
bsizer1.Add(hsizer1, 1, wx.EXPAND)
bsizer1.Add((5, 7))
fsizer1 = wx.FlexGridSizer(3, 3)
fsizer1.AddMany([
((10, 10)), ((10, 10)), ((10, 10)),
((10, 10)), (bsizer1, 1, wx.EXPAND), ((10, 10)),
((10, 10)), ((10, 10)), ((10, 10)),
])
fsizer1.AddGrowableCol(1)
fsizer1.AddGrowableRow(1)
cmd_label = wx.StaticText(self, -1, _("Command Log:"))
download_label = wx.StaticText(self, -1, _("Download Log:"))
upload_label = wx.StaticText(self, -1, _("Upload Log:"))
self.cmd_entry = wx.TextCtrl(self, -1)
if opts and opts['cmd_log']:
self.cmd_entry.SetValue(opts['cmd_log'])
self.download_entry = wx.TextCtrl(self, -1)
if opts and opts['download_log']:
self.download_entry.SetValue(opts['download_log'])
self.upload_entry = wx.TextCtrl(self, -1)
if opts and opts['upload_log']:
self.upload_entry.SetValue(opts['upload_log'])
tsizer = wx.GridSizer(3, 2)
tsizer.AddMany([
(cmd_label, 0, wx.ALIGN_CENTER_VERTICAL),
(self.cmd_entry, 1, wx.EXPAND),
(download_label, 0, wx.ALIGN_CENTER_VERTICAL),
(self.download_entry, 1, wx.EXPAND),
(upload_label, 0, wx.ALIGN_CENTER_VERTICAL),
(self.upload_entry, 1, wx.EXPAND),
])
tsizer.SetVGap(7)
fsizer2 = wx.FlexGridSizer(3, 3)
fsizer2.AddMany([
((20, 10)), ((10, 10)), ((20, 10)),
((20, 10)), (tsizer, 1, wx.EXPAND), ((20, 10)),
((20, 10)), ((10, 10)), ((20, 10)),
])
fsizer2.AddGrowableCol(1)
fsizer2.AddGrowableRow(1)
box = wx.StaticBox(self, -1, _("Log Files"))
bsizer2 = wx.StaticBoxSizer(box, wx.VERTICAL)
bsizer2.Add(fsizer2, 1, wx.EXPAND)
fsizer3 = wx.FlexGridSizer(3, 3)
fsizer3.AddMany([
((10, 10)), ((10, 10)), ((10, 10)),
((10, 10)), (bsizer2, 1, wx.EXPAND), ((10, 10)),
((10, 10)), ((10, 10)), ((10, 10)),
])
fsizer3.AddGrowableCol(1)
fsizer3.AddGrowableRow(1)
box = wx.StaticBox(self, -1, _("File Transfer Logging"))
boxsizer = wx.StaticBoxSizer(box, wx.VERTICAL)
boxsizer.Add(fsizer1, 0, wx.EXPAND)
boxsizer.Add(fsizer3, 0, wx.EXPAND)
sizer = wx.FlexGridSizer(3, 3)
sizer.AddMany([
((10, 10)), ((10, 10)), ((10, 10)),
((10, 10)), (boxsizer, 1, wx.EXPAND), ((10, 10)),
((10, 10)), ((10, 10)), ((10, 10)),
])
sizer.AddGrowableCol(1)
sizer.AddGrowableRow(1)
self.SetAutoLayout(True)
self.SetSizer(sizer)
sizer.Fit(self)
sizer.SetSizeHints(self)
def onActivate(self, event):
"""Processes an activate logging event."""
self.log = True
self.activate_button.SetValue(True)
def onDeactivate(self, event):
"""Processes a deactivate logging event."""
self.log = False
self.deactivate_button.SetValue(True)
def getOptions(self):
"""Returns a dictionary containing the logging window options."""
opts = { }
opts['logging'] = self.log
if self.cmd_entry.GetValue():
opts['cmd_log'] = self.cmd_entry.GetValue()
if self.download_entry.GetValue():
opts['download_log'] = self.download_entry.GetValue()
if self.upload_entry.GetValue():
opts['upload_log'] = self.upload_entry.GetValue()
return opts
class ColorsTab(wx.Panel):
"""Colors tab.
Allows for the selection of the colors used for logging to the console. This displays
a color chooser to allow for color selection."""
idLOCAL_TEXT = wx.NewId()
idREMOTE_TEXT = wx.NewId()
idERROR_TEXT = wx.NewId()
def __init__(self, parent, opts=None):
"""Creates the color tab."""
wx.Panel.__init__(self, parent, -1)
self.color_chooser = wx.lib.colourchooser.PyColorChooser(self, -1)
csizer = wx.FlexGridSizer(3, 3)
csizer.AddMany([
((10, 10)), ((10, 10)), ((10, 10)),
((10, 10)),
(self.color_chooser, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL),
((10, 10)),
((10, 10)), ((10, 10)), ((10, 10)),
])
self.local_button = wx.RadioButton(self, self.idLOCAL_TEXT, _("Local Text"))
self.remote_button = wx.RadioButton(self, self.idREMOTE_TEXT, _("Remote Text"))
self.error_button = wx.RadioButton(self, self.idERROR_TEXT, _("Error Text"))
self.Bind(wx.EVT_RADIOBUTTON, self.onLocalClick, id=self.idLOCAL_TEXT)
self.Bind(wx.EVT_RADIOBUTTON, self.onRemoteClick, id=self.idREMOTE_TEXT)
self.Bind(wx.EVT_RADIOBUTTON, self.onErrorClick, id=self.idERROR_TEXT)
hsizer = wx.BoxSizer(wx.HORIZONTAL)
hsizer.Add((10, 1))
hsizer.Add(self.local_button, 0, wx.ALIGN_CENTER_VERTICAL)
hsizer.Add((15, 1))
hsizer.Add(self.remote_button, 0, wx.ALIGN_CENTER_VERTICAL)
hsizer.Add((15, 1))
hsizer.Add(self.error_button, 0, wx.ALIGN_CENTER_VERTICAL)
hsizer.Add((10, 1))
box = wx.StaticBox(self, -1, _("Text Type"))
bsizer = wx.StaticBoxSizer(box, wx.VERTICAL)
bsizer.Add(hsizer, 1, wx.EXPAND)
box = wx.StaticBox(self, -1, _("Colors"))
boxsizer = wx.StaticBoxSizer(box, wx.VERTICAL)
boxsizer.Add(csizer, 0, wx.EXPAND)
boxsizer.Add((1, 5))
boxsizer.Add(bsizer, 0, wx.ALIGN_CENTER_HORIZONTAL)
sizer = wx.FlexGridSizer(3, 3)
sizer.AddMany([
((10, 10)), ((10, 10)), ((10, 10)),
((10, 10)), (boxsizer, 1, wx.EXPAND), ((10, 10)),
((10, 10)), ((10, 10)), ((10, 10)),
])
sizer.AddGrowableCol(1)
sizer.AddGrowableRow(1)
self.SetAutoLayout(True)
self.SetSizer(sizer)
sizer.Fit(self)
sizer.SetSizeHints(self)
# Set the current values and load the local text color as default
self.local_color = (0, 0, 0)
if opts and opts['local_color']:
self.local_color = opts['local_color']
self.remote_color = (0, 0, 0)
if opts and opts['remote_color']:
self.remote_color = opts['remote_color']
self.error_color = (0, 0, 0)
if opts and opts['error_color']:
self.error_color = opts['error_color']
self.local_button.SetValue(True)
self.setColor(self.local_color)
def setColor(self, color):
"""Sets the color chooser to the specified color.
The 'color' can be either an RGB tuple or a wx Color object."""
if isinstance(color, wx.Color):
self.color_chooser.SetValue(color)
elif isinstance(color, tuple):
color = apply(wx.Color, color)
self.color_chooser.SetValue(color)
def onLocalClick(self, event):
"""Processes a selection of the local logging color button."""
if self.local_button.GetValue():
self.setColor(self.local_color)
else:
self.local_color = utils.colorToTuple(self.color_chooser.GetValue())
self.local_button.SetValue(True)
def onRemoteClick(self, event):
"""Processes a selection of the remote logging color button."""
if self.remote_button.GetValue():
self.setColor(self.remote_color)
else:
self.remote_color = utils.colorToTuple(self.color_chooser.GetValue())
self.remote_button.SetValue(True)
def onErrorClick(self, event):
"""Processes a selection of the error logging color button."""
if self.error_button.GetValue():
self.setColor(self.error_color)
else:
self.error_color = utils.colorToTuple(self.color_chooser.GetValue())
self.error_button.SetValue(True)
def getOptions(self):
"""Returns a dictionary containing the configuration options for this panel."""
# Update the colors to reflect any current changes
if self.local_button.GetValue():
self.local_color = utils.colorToTuple(self.color_chooser.GetValue())
elif self.remote_button.GetValue():
self.remote_color = utils.colorToTuple(self.color_chooser.GetValue())
elif self.error_button.GetValue():
self.error_color = utils.colorToTuple(self.color_chooser.GetValue())
opts = {
'local_color' : self.local_color,
'remote_color' : self.remote_color,
'error_color' : self.error_color,
}
return opts
|