# Copyright (C) 2003, 2004 Konstantin Korikov
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# 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. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import gtk
import gtk.glade
import gobject
try: import pango
except ImportError: pass
import glob
import os
import re
import sys
import chestnut_dialer
import chestnut_dialer.config
import chestnut_dialer.gtk2_ui.box
from chestnut_dialer import _
from chestnut_dialer.account_set import NoAccountException
config_glade_file = os.path.dirname(__file__) + "/config.glade"
class EditAccountBaseControl:
acc = None
attr_name = None
glxml = None
control_name = None
clr = None
clear_radio = None
nclear_radio = None
def_acc = None
def_toggle = None
def __init__(self, acc, glxml, control_name, attr_name,
clr = 0, def_acc = None):
self.acc = acc
self.glxml = glxml
self.control_name = control_name
self.attr_name = attr_name
self.clr = clr
if self.clr:
self.clear_radio = self.glxml.get_widget(self.control_name + 'Clr')
self.nclear_radio = self.glxml.get_widget(self.control_name + 'NotClr')
self.clear_radio.connect("toggled", self.clear_event)
self.nclear_radio.connect("toggled", self.notclear_event)
self.def_acc = def_acc
if self.def_acc != None:
self.def_toggle = self.glxml.get_widget(self.control_name + 'DefToggle')
self.def_toggle.connect("toggled", self.def_toggled_event)
def acc_get_value(self):
return self.acc[self.attr_name]
def acc_set_value(self, value):
self.acc[self.attr_name] = value
def wid_get_value(self):
pass
def wid_set_value(self, value):
pass
def load_value(self):
v = self.acc_get_value()
if v == None:
if self.def_acc != None:
self.def_toggle.set_active(1)
self.def_toggled_event()
else:
self.wid_set_value(self.get_clear_value())
if self.clr: self.clear_radio.set_active(1)
else:
if self.clr and v == self.get_clear_value():
self.clear_event()
self.clear_radio.set_active(1)
else:
self.wid_set_value(v)
if self.clr: self.nclear_radio.set_active(1)
def save_value(self):
if self.def_acc != None and self.def_toggle.get_active():
self.acc_set_value(None)
else:
self.acc_set_value(self.wid_get_value())
def get_clear_value(self):
return 0
def clear_event(self, *args):
if self.clear_radio.get_active():
self.wid_set_value(self.get_clear_value())
self.set_sensitive(0)
def notclear_event(self, *args):
if self.nclear_radio.get_active():
self.set_sensitive(1)
def def_toggled_event(self, *args):
if self.def_toggle.get_active():
def_v = self.def_acc[self.attr_name]
self.wid_set_value(def_v)
if self.clr:
if def_v == self.get_clear_value():
self.clear_radio.set_active(1)
else:
self.nclear_radio.set_active(1)
self.clear_radio.set_sensitive(0)
self.nclear_radio.set_sensitive(0)
self.set_sensitive(0)
else:
if self.clr:
self.clear_radio.set_sensitive(1)
self.nclear_radio.set_sensitive(1)
self.set_sensitive(not (self.clr and self.clear_radio.get_active()))
class EditAccountEntryControl(EditAccountBaseControl):
entry = None
def __init__(self, acc, glxml, control_name, attr_name,
clr = 0, def_acc = None):
EditAccountBaseControl.__init__(self, acc, glxml,
control_name, attr_name, clr, def_acc)
self.entry = glxml.get_widget(control_name + 'Entry')
def set_sensitive(self, sens):
self.entry.set_sensitive(sens)
def wid_set_value(self, value):
self.entry.set_text(value)
def wid_get_value(self):
return unicode(self.entry.get_text(), "UTF-8")
def get_clear_value(self):
return ""
class EditAccountComboControl(EditAccountBaseControl):
combo = None
def __init__(self, acc, glxml, control_name, attr_name,
clr = 0, def_acc = None):
EditAccountBaseControl.__init__(self, acc, glxml,
control_name, attr_name, clr, def_acc)
self.combo = glxml.get_widget(control_name + 'Combo')
def set_sensitive(self, sens):
self.combo.set_sensitive(sens)
def wid_set_value(self, value):
self.combo.entry.set_text(value)
def wid_get_value(self):
return unicode(self.combo.entry.get_text(), "UTF-8")
def get_clear_value(self):
return ""
class EditAccountSpinControl(EditAccountBaseControl):
spin = None
def __init__(self, acc, glxml, control_name, attr_name,
clr = 0, def_acc = None):
EditAccountBaseControl.__init__(self, acc, glxml,
control_name, attr_name, clr, def_acc)
self.spin = glxml.get_widget(control_name + 'Spin')
def set_sensitive(self, sens):
self.spin.set_sensitive(sens)
def wid_set_value(self, value):
self.spin.set_value(int(value))
def wid_get_value(self):
return int(self.spin.get_value())
def get_clear_value(self):
return 0
class EditAccountListControl(EditAccountBaseControl):
lst = None
entry = None
add_btn = None
del_btn = None
up_btn = None
down_btn = None
def __init__(self, acc, glxml, control_name, attr_name,
clr = 0, def_acc = None):
EditAccountBaseControl.__init__(self, acc, glxml,
control_name, attr_name, clr, def_acc)
self.lst = glxml.get_widget(control_name + 'List')
self.lst.set_model(gtk.ListStore(gobject.TYPE_STRING))
self.lst.append_column(gtk.TreeViewColumn(
"", gtk.CellRendererText(), text=0))
self.lst.get_selection().connect("changed", self.select_event)
self.entry = glxml.get_widget(control_name + 'Entry')
self.add_btn = glxml.get_widget(control_name + 'AddButton')
self.del_btn = glxml.get_widget(control_name + 'RemoveButton')
self.up_btn = glxml.get_widget(control_name + 'Up')
self.down_btn = glxml.get_widget(control_name + 'Down')
self.add_btn.connect("clicked", self.add_action)
self.del_btn.connect("clicked", self.remove_action)
if self.up_btn and self.down_btn:
self.up_btn.connect("clicked", self.up_action)
self.down_btn.connect("clicked", self.down_action)
def select_event(self, sel):
l = []
sel.selected_foreach(
lambda m, p, i, l: l.append(m.get_value(i, 0)), l)
if len(l): self.entry.set_text(l[0])
def add_action(self, *args):
store = self.lst.get_model()
store.set(store.append(), 0, self.entry.get_text())
self.entry.set_text("")
def remove_action(self, *args):
l = []
self.lst.get_selection().selected_foreach(
lambda m, p, i, l: l.append(m.get_value(i, 0)), l)
m = self.lst.get_model()
i = m.get_iter_first()
while i:
j = m.iter_next(i)
if m.get_value(i, 0) in l: m.remove(i)
i = j
def up_action(self, *args):
l = []
self.lst.get_selection().selected_foreach(
lambda m, p, i, l: l.append(p), l)
m = self.lst.get_model()
if len(l) == 1 and l[0][0] > 0:
i = m.get_iter(l[0])
j = m.get_iter((l[0][0] - 1,))
m.set(m.insert_before(j), 0, m.get_value(i, 0))
m.remove(i)
def down_action(self, *args):
l = []
self.lst.get_selection().selected_foreach(
lambda m, p, i, l: l.append(i), l)
m = self.lst.get_model()
if len(l) == 1:
i = l[0]; j = m.iter_next(i)
if j:
m.set(m.insert_after(j), 0, m.get_value(i, 0))
m.remove(i)
def wid_set_value(self, value):
self.entry.set_text("")
store = self.lst.get_model()
store.clear()
for v in value:
store.set(store.append(), 0, v)
def wid_get_value(self):
items = []
def read_item(model, path, iter, items):
items.append(unicode(model.get_value(iter, 0), "UTF-8"))
self.lst.get_model().foreach(read_item, items)
return tuple(items)
def set_sensitive(self, sens):
self.lst.set_sensitive(sens)
self.add_btn.set_sensitive(sens)
self.del_btn.set_sensitive(sens)
if self.up_btn and self.down_btn:
self.up_btn.set_sensitive(sens)
self.down_btn.set_sensitive(sens)
self.entry.set_sensitive(sens)
if not sens: self.entry.set_text("")
def get_clear_value(self):
return ()
class EditAccountOptionControl(EditAccountBaseControl):
option = None
value = None
items = None
def __init__(self, acc, glxml, control_name, attr_name, items,
clr = 0, def_acc = None):
EditAccountBaseControl.__init__(self, acc, glxml,
control_name, attr_name, clr, def_acc)
self.option = glxml.get_widget(control_name + 'Option')
self.items = items
self.value = self.acc_get_value()
num = 0
for mi in self.option.get_menu().get_children():
mi.connect("activate", self.activate_event, items[num])
num += 1
def activate_event(self, mi, v):
self.value = v
def wid_set_value(self, value):
try: self.option.set_history(self.items.index(value))
except ValueError: pass
def wid_get_value(self):
return self.value
def set_sensitive(self, sens):
self.option.set_sensitive(sens)
def get_clear_value(self):
return self.items[0]
class EditAccountCheckControl(EditAccountBaseControl):
check = None
def __init__(self, acc, glxml, control_name, attr_name,
clr = 0, def_acc = None):
EditAccountBaseControl.__init__(self, acc, glxml,
control_name, attr_name, clr, def_acc)
self.check = glxml.get_widget(control_name + 'Check')
def set_sensitive(self, sens):
self.check.set_sensitive(sens)
def wid_set_value(self, value):
self.check.set_active(value)
def wid_get_value(self):
return self.check.get_active()
class EditAccountCheckGroupControl(EditAccountBaseControl):
items = None
group = None
def __init__(self, acc, glxml, control_name, attr_name,
items, clr = 0, def_acc = None):
EditAccountBaseControl.__init__(self, acc, glxml,
control_name, attr_name, clr, def_acc)
self.items = items
self.group = []
for i in range(0, len(items)):
self.group.append(glxml.get_widget(control_name + 'Check' + str(i)))
def set_sensitive(self, sens):
for w in self.group: w.set_sensitive(sens)
def wid_set_value(self, value):
for i in range(0, len(self.items)):
self.group[i].set_active(self.items[i] in value)
def wid_get_value(self):
value = []
for i in range(0, len(self.items)):
if self.group[i].get_active():
value.append(self.items[i])
return tuple(value)
class EditAccountScaleControl(EditAccountBaseControl):
scale = None
def __init__(self, acc, glxml, control_name, attr_name,
clr = 0, def_acc = None):
EditAccountBaseControl.__init__(self, acc, glxml,
control_name, attr_name, clr, def_acc)
self.scale = glxml.get_widget(control_name + 'Scale')
def set_sensitive(self, sens):
self.scale.set_sensitive(sens)
def wid_set_value(self, value):
self.scale.get_adjustment().set_value(value)
def wid_get_value(self):
return int(self.scale.get_adjustment().value)
class EditAccountTextControl(EditAccountBaseControl):
text = None
def __init__(self, acc, glxml, control_name, attr_name,
clr = 0, def_acc = None):
EditAccountBaseControl.__init__(self, acc, glxml,
control_name, attr_name, clr, def_acc)
self.text = glxml.get_widget(control_name + 'Text')
def set_sensitive(self, sens):
self.text.set_sensitive(sens)
def wid_set_value(self, value):
self.text.get_buffer().set_text(value)
def wid_get_value(self):
buf = self.text.get_buffer()
return unicode(buf.get_text(buf.get_start_iter(),
buf.get_end_iter(), True), "UTF-8")
def get_clear_value(self):
return ""
class EditAccountWindow:
window = None
glxml = None
acc = None
acc_real = None
def_acc = None
controls = None
update_list_action = None
def __init__(self, acc, def_acc, update_list_action, show_help_action):
self.acc = acc.copy()
self.acc_real = acc
self.def_acc = def_acc.copy()
self.update_list_action = update_list_action
self.glxml = gtk.glade.XML(config_glade_file, "EditAccountWindow",
chestnut_dialer.domain)
self.window = self.glxml.get_widget("EditAccountWindow")
self.window.set_title("%s - %s" % (_("Account"), acc['name']))
self.controls = [
EditAccountEntryControl( self.acc, self.glxml, 'AccountName', 'name'),
EditAccountSpinControl( self.acc, self.glxml, 'Redial', 'redial_attempts', 1, self.def_acc),
EditAccountCheckControl( self.acc, self.glxml, 'RedialAuto', 'redial_auto', 0, self.def_acc),
EditAccountSpinControl( self.acc, self.glxml, 'MinSpeed', 'min_speed', 0, self.def_acc),
EditAccountCheckGroupControl(self.acc,self.glxml,'RedialIf', 'redial_if',
['no-dialtone', 'auth-fail'], 0, self.def_acc),
EditAccountListControl( self.acc, self.glxml, 'PhoneNumber', 'phone_numbers'),
EditAccountEntryControl( self.acc, self.glxml, 'DialPrefix', 'dial_prefix', 0, self.def_acc),
EditAccountSpinControl( self.acc, self.glxml, 'ModemTimeout', 'modem_timeout', 0, self.def_acc),
EditAccountSpinControl( self.acc, self.glxml, 'Timeout', 'dial_timeout', 0, self.def_acc),
EditAccountSpinControl( self.acc, self.glxml, 'PPPTimeout', 'ppp_timeout', 0, self.def_acc),
EditAccountSpinControl( self.acc, self.glxml, 'PromptTimeout', 'prompt_timeout', 0, self.def_acc),
EditAccountTextControl( self.acc, self.glxml, 'Comment', 'comment'),
EditAccountOptionControl( self.acc, self.glxml, 'AuthType', 'auth_type',
['pap/chap', 'term']),
EditAccountOptionControl( self.acc, self.glxml, 'UseScript', 'use_script',
['predef-noterm', 'predef-term', 'predef-auto', 'dialin', 'custom', 'none']),
EditAccountEntryControl( self.acc, self.glxml, 'Login', 'user'),
EditAccountEntryControl( self.acc, self.glxml, 'Password', 'passwd'),
EditAccountCheckControl( self.acc, self.glxml, 'AskPassword', 'ask_passwd', 0, self.def_acc),
EditAccountCheckControl( self.acc, self.glxml, 'UsePasswordfd', 'use_passwordfd', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'RemoteName', 'remotename', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'ChatLoginPrompt', 'chat_login_prompt', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'ChatPasswordPrompt','chat_passwd_prompt', 0, self.def_acc),
EditAccountTextControl( self.acc, self.glxml, 'ChatScript', 'chat_script', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'LocalIP', 'ip', 1, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'NetMask', 'mask', 1, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'RemoteIP', 'remote', 1, self.def_acc),
EditAccountListControl( self.acc, self.glxml, 'DNSServer', 'dns_servers', 1, self.def_acc),
EditAccountComboControl( self.acc, self.glxml, 'Device', 'device', 0, self.def_acc),
EditAccountOptionControl( self.acc, self.glxml, 'Speed', 'speed',
['115200', '57600', '38400', '19200', '9600', '4800', '2400', '1200'], 0, self.def_acc),
EditAccountCheckControl( self.acc, self.glxml, 'Modem', 'modem', 0, self.def_acc),
EditAccountOptionControl( self.acc, self.glxml, 'FlowControl', 'flow_control',
['crtscts', 'cdtrcts', 'xonxoff', 'no-change'], 0, self.def_acc),
EditAccountOptionControl( self.acc, self.glxml, 'ModemTerm', 'modem_term',
['\\r\\n', '\\r', '\\n'], 0, self.def_acc),
EditAccountScaleControl( self.acc, self.glxml, 'Volume', 'volume_setting', 0, self.def_acc),
EditAccountCheckControl( self.acc, self.glxml, 'DefaultRoute', 'default_route', 0, self.def_acc),
EditAccountCheckControl( self.acc, self.glxml, 'LockDevice', 'lock_device', 0, self.def_acc),
EditAccountSpinControl( self.acc, self.glxml, 'MTU', 'mtu', 0, self.def_acc),
EditAccountSpinControl( self.acc, self.glxml, 'MRU', 'mru', 0, self.def_acc),
EditAccountCheckControl( self.acc, self.glxml, 'Callback', 'callback', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'CallbackPhoneNumber','callback_phone_number',0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'PPPOptions','ppp_options',0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'ConnectProg', 'connect_program', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'DisconnectProg', 'disconnect_program', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'ErrorResp', 'error_resp', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'InitCmd', 'init_cmd', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'Init2Cmd', 'init2_cmd', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'InitResp', 'init_resp', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'VolumeMuteCmd', 'mute_cmd', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'VolumeLowCmd', 'low_vol_cmd', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'VolumeMaxCmd', 'max_vol_cmd', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'VolumeResp', 'vol_resp', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'DialCmd', 'dial_cmd', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'ConnectResp', 'connect_resp', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'BusyResp', 'busy_resp', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'NoAnswerResp', 'noanswer_resp', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'NoCarrierResp', 'nocarrier_resp', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'NoDialtoneResp', 'nodialtone_resp', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'CallbackInitCmd', 'callback_init_cmd', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'CallbackInit2Cmd', 'callback_init2_cmd', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'RingResp', 'ring_resp', 0, self.def_acc),
EditAccountEntryControl( self.acc, self.glxml, 'AnswerCmd', 'answer_cmd', 0, self.def_acc)
]
for c in self.controls: c.load_value()
if not chestnut_dialer.config.disable_show_passwd_button:
self.glxml.get_widget("ShowPasswordButton").connect("toggled",
lambda t, e: e.set_visibility(t.get_active()),
self.glxml.get_widget("PasswordEntry"))
else:
self.glxml.get_widget("ShowPasswordButton").set_sensitive(0)
self.glxml.signal_connect("chat_script_help",
show_help_action, "Chat Scripts")
self.window.connect("destroy",
self.window_destroyed_event)
self.glxml.signal_connect("ok", self.ok_action)
self.glxml.signal_connect("cancel", self.cancel_action)
def destroy(self):
if self.window:
self.window.destroy()
self.window = None
self.controls = None
self.acc = None
self.acc_real = None
self.def_acc = None
self.update_list_action = None
def window_destroyed_event(self, *args):
self.destroy()
def show(self):
self.window.show_all()
def set_modal(self, modal):
self.window.set_modal(modal)
def ok_action(self, *args):
phone_numbers = None
use_script = None
for c in self.controls:
if c.attr_name == 'phone_numbers':
phone_numbers = c.wid_get_value()
elif c.attr_name == 'use_script':
use_script = c.wid_get_value()
if (len(phone_numbers) == 0 and
use_script not in ('dialin', 'custom', 'none')):
msgbox = gtk.MessageDialog(self.window,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO,
_("No phone numbers specified. Continue?"))
r = msgbox.run()
msgbox.destroy()
if r == gtk.RESPONSE_NO: return
for c in self.controls: c.save_value()
self.acc_real.update(self.acc)
self.update_list_action()
self.destroy()
def cancel_action(self, *args):
self.destroy()
class EditDefAccountWindow:
window = None
glxml = None
acc = None
controls = None
def __init__(self, acc, show_help_action):
self.acc = acc
self.glxml = gtk.glade.XML(config_glade_file, "EditDefAccountWindow",
chestnut_dialer.domain)
self.window = self.glxml.get_widget("EditDefAccountWindow")
self.controls = [
EditAccountEntryControl(self.acc, self.glxml, 'DialPrefix', 'dial_prefix'),
EditAccountSpinControl(self.acc, self.glxml, 'Redial', 'redial_attempts', 1),
EditAccountCheckControl(self.acc, self.glxml, 'RedialAuto', 'redial_auto'),
EditAccountSpinControl(self.acc, self.glxml, 'MinSpeed', 'min_speed'),
EditAccountCheckGroupControl(self.acc, self.glxml, 'RedialIf', 'redial_if',
['no-dialtone', 'auth-fail']),
EditAccountSpinControl(self.acc, self.glxml, 'ModemTimeout', 'modem_timeout'),
EditAccountSpinControl(self.acc, self.glxml, 'Timeout', 'dial_timeout'),
EditAccountSpinControl(self.acc, self.glxml, 'PPPTimeout', 'ppp_timeout'),
EditAccountSpinControl(self.acc, self.glxml, 'PromptTimeout', 'prompt_timeout'),
EditAccountCheckControl(self.acc, self.glxml, 'AskPassword', 'ask_passwd'),
EditAccountCheckControl(self.acc, self.glxml, 'UsePasswordfd', 'use_passwordfd'),
EditAccountEntryControl(self.acc, self.glxml, 'RemoteName', 'remotename'),
EditAccountEntryControl(self.acc, self.glxml, 'ChatLoginPrompt', 'chat_login_prompt'),
EditAccountEntryControl(self.acc, self.glxml, 'ChatPasswordPrompt', 'chat_passwd_prompt'),
EditAccountTextControl(self.acc, self.glxml, 'ChatScript', 'chat_script'),
EditAccountEntryControl(self.acc, self.glxml, 'LocalIP', 'ip', 1),
EditAccountEntryControl(self.acc, self.glxml, 'NetMask', 'mask', 1),
EditAccountEntryControl(self.acc, self.glxml, 'RemoteIP', 'remote', 1),
EditAccountListControl(self.acc, self.glxml, 'DNSServer', 'dns_servers', 1),
EditAccountComboControl(self.acc, self.glxml, 'Device', 'device'),
EditAccountOptionControl(self.acc, self.glxml, 'Speed', 'speed',
['115200', '57600', '38400', '19200', '9600', '4800', '2400', '1200']),
EditAccountCheckControl(self.acc, self.glxml, 'Modem', 'modem'),
EditAccountOptionControl(self.acc, self.glxml, 'FlowControl', 'flow_control',
['crtscts', 'cdtrcts', 'xonxoff', 'no-change']),
EditAccountOptionControl(self.acc, self.glxml, 'ModemTerm', 'modem_term',
['\\r\\n', '\\r', '\\n']),
EditAccountScaleControl(self.acc, self.glxml, 'Volume', 'volume_setting'),
EditAccountCheckControl(self.acc, self.glxml, 'DefaultRoute', 'default_route'),
EditAccountCheckControl(self.acc, self.glxml, 'LockDevice', 'lock_device'),
EditAccountSpinControl(self.acc, self.glxml, 'MTU', 'mtu'),
EditAccountSpinControl(self.acc, self.glxml, 'MRU', 'mru'),
EditAccountCheckControl(self.acc, self.glxml, 'Callback', 'callback'),
EditAccountEntryControl(self.acc, self.glxml, 'CallbackPhoneNumber', 'callback_phone_number'),
EditAccountEntryControl(self.acc, self.glxml, 'PPPOptions', 'ppp_options'),
EditAccountEntryControl(self.acc, self.glxml, 'ConnectProg', 'connect_program'),
EditAccountEntryControl(self.acc, self.glxml, 'DisconnectProg', 'disconnect_program'),
EditAccountEntryControl(self.acc, self.glxml, 'ErrorResp', 'error_resp'),
EditAccountEntryControl(self.acc, self.glxml, 'InitCmd', 'init_cmd'),
EditAccountEntryControl(self.acc, self.glxml, 'Init2Cmd', 'init2_cmd'),
EditAccountEntryControl(self.acc, self.glxml, 'InitResp', 'init_resp'),
EditAccountEntryControl(self.acc, self.glxml, 'VolumeMuteCmd', 'mute_cmd'),
EditAccountEntryControl(self.acc, self.glxml, 'VolumeLowCmd', 'low_vol_cmd'),
EditAccountEntryControl(self.acc, self.glxml, 'VolumeMaxCmd', 'max_vol_cmd'),
EditAccountEntryControl(self.acc, self.glxml, 'VolumeResp', 'vol_resp'),
EditAccountEntryControl(self.acc, self.glxml, 'DialCmd', 'dial_cmd'),
EditAccountEntryControl(self.acc, self.glxml, 'ConnectResp', 'connect_resp'),
EditAccountEntryControl(self.acc, self.glxml, 'BusyResp', 'busy_resp'),
EditAccountEntryControl(self.acc, self.glxml, 'NoAnswerResp', 'noanswer_resp'),
EditAccountEntryControl(self.acc, self.glxml, 'NoCarrierResp', 'nocarrier_resp'),
EditAccountEntryControl(self.acc, self.glxml, 'NoDialtoneResp', 'nodialtone_resp'),
EditAccountEntryControl(self.acc, self.glxml, 'CallbackInitCmd', 'callback_init_cmd'),
EditAccountEntryControl(self.acc, self.glxml, 'CallbackInit2Cmd', 'callback_init2_cmd'),
EditAccountEntryControl(self.acc, self.glxml, 'RingResp', 'ring_resp'),
EditAccountEntryControl(self.acc, self.glxml, 'AnswerCmd', 'answer_cmd')
]
for c in self.controls: c.load_value()
self.glxml.signal_connect("chat_script_help",
show_help_action, "Chat Scripts")
self.glxml.signal_connect("ok", self.ok_action)
self.glxml.signal_connect("cancel", self.cancel_action)
self.window.connect("destroy",
self.window_destroyed_event)
def destroy(self):
if self.window:
self.window.destroy()
self.window = None
self.controls = None
self.acc = None
def window_destroyed_event(self, *args):
self.destroy()
def show(self):
self.window.show_all()
def set_modal(self, modal):
self.window.set_modal(modal)
def ok_action(self, *args):
for c in self.controls: c.save_value()
self.destroy()
def cancel_action(self, *args):
self.destroy()
class KeyBindingControl:
entry = None
button = None
def __init__(self, glxml, name):
self.entry = glxml.get_widget(name + "Entry")
self.button = glxml.get_widget(name + "Button")
self.button.connect("clicked", self.button_clicked)
def destroy(self):
self.entry = None
self.button = None
def get_value(self):
return unicode(self.entry.get_text(), "UTF-8")
def set_value(self, value):
self.entry.set_text(value)
def button_clicked(self, *args):
glxml = gtk.glade.XML(config_glade_file, "KeyDialog",
chestnut_dialer.domain)
dialog = glxml.get_widget("KeyDialog")
dialog.connect("key-press-event", self.key_pressed)
dialog.set_response_sensitive(gtk.RESPONSE_OK, True)
dialog.run()
dialog.destroy()
def key_pressed(self, widget, event):
if gtk.accelerator_valid(event.keyval, event.state):
self.entry.set_text(gtk.accelerator_name(
event.keyval, event.state))
widget.response(gtk.RESPONSE_OK)
return False
class OptionsWindow:
window = None
config = None
glxml = None
dockicons_dir = None
accel_controls = None
accel_map = None
def __init__(self, config, show_help_action):
self.config = config
self.glxml = gtk.glade.XML(config_glade_file, "OptionsWindow",
chestnut_dialer.domain)
self.window = self.glxml.get_widget("OptionsWindow")
self.glxml.get_widget("MonitorPeriod").set_value(
self.config.monitor_period)
self.glxml.get_widget("StatusRefreshPeriod").set_value(
self.config.status_refresh_period)
self.dockicons_dir = self.config.dockicons_dir
j = None; i = 0
menu = gtk.Menu()
for d in chestnut_dialer.get_dockicons_dir_list():
menuitem = gtk.MenuItem(d)
menu.append(menuitem)
menuitem.show()
menuitem.connect("activate", self.icons_activate, d)
if d == self.dockicons_dir: j = i
i += 1
self.glxml.get_widget("Icons").set_menu(menu)
if j != None:
self.glxml.get_widget("Icons").set_history(j)
self.icons_activate(None, self.dockicons_dir)
on_connect_actions = self.get_on_connect_actions()
text_dict = self.get_on_connect_text_dict()
menu = gtk.Menu()
for a in on_connect_actions:
menuitem = gtk.MenuItem(text_dict[a])
menu.append(menuitem)
menuitem.show()
self.glxml.get_widget("WhenConnect").set_menu(menu)
try:
self.glxml.get_widget("WhenConnect").set_history(
on_connect_actions.index(self.config.gtk2_ui.on_connect))
except AttributeError: pass
except ValueError: pass
self.glxml.get_widget("WndTitleFmtDisconnected").set_text(
self.config.wnd_title_fmt_disconnected)
self.glxml.get_widget("WndTitleFmtConnecting").set_text(
self.config.wnd_title_fmt_connecting)
self.glxml.get_widget("WndTitleFmtConnected").set_text(
self.config.wnd_title_fmt_connected)
self.glxml.signal_connect("wnd_title_fmt_help",
show_help_action, "Custom Window Title")
self.accel_controls = [
("<ChestnutDialer-Main>/Dial",
KeyBindingControl(self.glxml, "DialKey")),
("<ChestnutDialer-Main>/AccountsConf",
KeyBindingControl(self.glxml, "AccountsConfKey")),
("<ChestnutDialer-Main>/Config",
KeyBindingControl(self.glxml, "ConfigKey")),
("<ChestnutDialer-Main>/Connecting",
KeyBindingControl(self.glxml, "ConnectingKey")),
("<ChestnutDialer-Main>/Connecting/Stop",
KeyBindingControl(self.glxml, "ConnectingStopKey")),
("<ChestnutDialer-Main>/Status",
KeyBindingControl(self.glxml, "StatusKey")),
("<ChestnutDialer-Main>/Status/Disconnect",
KeyBindingControl(self.glxml, "StatusDisconnectKey")),
("<ChestnutDialer-Main>/Quit",
KeyBindingControl(self.glxml, "QuitKey"))]
self.accel_map = {}
for path, accel in map(lambda e: e.split(':'),
self.config.gtk2_ui.accel_map.split(';')):
self.accel_map[path] = accel
for path, control in self.accel_controls:
control.set_value(self.accel_map[path])
self.glxml.get_widget("ConfirmExit").set_active(
self.config.confirm_exit)
self.glxml.get_widget("ConfirmDeleteAccount").set_active(
self.config.confirm_delete_account)
self.glxml.get_widget("PppdCbcpWithAutoAnswer").set_active(
self.config.pppd_cbcp_with_auto_answer)
self.glxml.get_widget("WriteDnsToResolvConf").set_active(
self.config.write_dns_to_resolv_conf)
try:
self.glxml.get_widget("Browser").set_text(
self.config.gtk2_ui.browser)
except AttributeError:
self.glxml.get_widget("Browser").set_text("")
try:
self.glxml.get_widget("PlainTextViewer").set_text(
self.config.gtk2_ui.plain_text_viewer)
except AttributeError:
self.glxml.get_widget("PlainTextViewer").set_text("")
self.glxml.signal_connect("ok", self.ok_action)
self.glxml.signal_connect("cancel", self.cancel_action)
self.window.connect("destroy",
self.window_destroyed_event)
def destroy(self):
if self.window:
self.window.destroy()
self.window = None
if self.accel_controls != None:
for path, control in self.accel_controls:
control.destroy()
self.accel_controls = None
self.accel_map = None
config = None
def window_destroyed_event(self, *args):
self.destroy()
def show(self):
self.window.show_all()
def set_modal(self, modal):
self.window.set_modal(modal)
def icons_activate(self, widget, dockicons_dir):
self.glxml.get_widget("DisconnectedIcon").set_from_file(
chestnut_dialer.get_dockicon_file(dockicons_dir, "disconnected"))
self.glxml.get_widget("ConnectingIcon").set_from_file(
chestnut_dialer.get_dockicon_file(dockicons_dir, "connecting"))
self.glxml.get_widget("ConnectedIcon").set_from_file(
chestnut_dialer.get_dockicon_file(dockicons_dir, "connected"))
self.dockicons_dir = dockicons_dir
def ok_action(self, *args):
self.config.monitor_period = self.glxml.get_widget("MonitorPeriod").get_value()
self.config.status_refresh_period = self.glxml.get_widget("StatusRefreshPeriod").get_value()
self.config.dockicons_dir = self.dockicons_dir
self.config.gtk2_ui.on_connect = self.get_on_connect_actions()[
self.glxml.get_widget("WhenConnect").get_history()]
self.config.wnd_title_fmt_disconnected = unicode(
self.glxml.get_widget("WndTitleFmtDisconnected").get_text(), "UTF-8")
self.config.wnd_title_fmt_connecting = unicode(
self.glxml.get_widget("WndTitleFmtConnecting").get_text(), "UTF-8")
self.config.wnd_title_fmt_connected = unicode(
self.glxml.get_widget("WndTitleFmtConnected").get_text(), "UTF-8")
for path, control in self.accel_controls:
key, mods = gtk.accelerator_parse(control.get_value())
if gtk.accelerator_valid(key, mods):
self.accel_map[path] = control.get_value()
self.config.gtk2_ui.accel_map = ';'.join(
map(lambda p: "%s:%s" % (p, self.accel_map[p]), self.accel_map.keys()))
self.config.confirm_exit = self.glxml.get_widget("ConfirmExit").get_active()
self.config.confirm_delete_account = self.glxml.get_widget("ConfirmDeleteAccount").get_active()
self.config.pppd_cbcp_with_auto_answer = self.glxml.get_widget("PppdCbcpWithAutoAnswer").get_active()
self.config.write_dns_to_resolv_conf = self.glxml.get_widget("WriteDnsToResolvConf").get_active()
self.config.gtk2_ui.browser = unicode(
self.glxml.get_widget("Browser").get_text(), "UTF-8")
self.config.gtk2_ui.plain_text_viewer = unicode(
self.glxml.get_widget("PlainTextViewer").get_text(), "UTF-8")
self.destroy()
def cancel_action(self, *args):
self.destroy()
def get_on_connect_actions(self):
return ["nothing", "iconify"]
def get_on_connect_text_dict(self):
return {"nothing": _("Nothing"), "iconify": _("Minimize Window")}
class AccountsConfBox(chestnut_dialer.gtk2_ui.box.BaseBox):
app = None
clist = None
list_vadj_value = 0
list_selection = []
remove_btn = None
edit_btn = None
duplicate_btn = None
dial_btn = None
def __init__(self, app):
self.app = app
self.list_selection = AccountsConfBox.list_selection
xml = gtk.glade.XML(config_glade_file, "AccountsConfBox",
chestnut_dialer.domain)
self.widget = xml.get_widget("AccountsConfBox")
self.remove_btn = xml.get_widget("RemoveButton")
self.edit_btn = xml.get_widget("EditButton")
self.duplicate_btn = xml.get_widget("DuplicateButton")
self.dial_btn = xml.get_widget("DialButton")
self.remove_btn.set_sensitive(0)
self.edit_btn.set_sensitive(0)
self.duplicate_btn.set_sensitive(0)
self.dial_btn.set_sensitive(0)
xml.signal_connect("add", self.add_action)
xml.signal_connect("remove", self.remove_action)
xml.signal_connect("edit", self.edit_action)
xml.signal_connect("duplicate", self.duplicate_action)
xml.signal_connect("import", self.import_action)
xml.signal_connect("dial", self.dial_action)
self.clist = xml.get_widget("List")
self.clist.set_model(gtk.ListStore(
gobject.TYPE_UINT, gobject.TYPE_STRING))
column = gtk.TreeViewColumn(_("Id"), gtk.CellRendererText(), text=0)
column.set_sort_column_id(0)
column.set_sort_indicator(True)
self.clist.append_column(column)
column = gtk.TreeViewColumn(_("Name"), gtk.CellRendererText(), text=1)
column.set_sort_column_id(1)
column.set_sort_indicator(True)
self.clist.append_column(column)
self.clist.get_selection().set_mode(3)
self.clist.get_model().set_sort_column_id(1, gtk.SORT_ASCENDING)
self.clist.connect("row_activated",
self.row_activated_event)
self.clist.get_selection().connect("changed",
self.selection_changed_event)
self.refresh()
self.widget.connect("size-allocate", self.size_allocate_event)
def destroy(self):
AccountsConfBox.list_vadj_value = self.clist.get_vadjustment().get_value()
self.app = None
self.clist = None
def size_allocate_event(self, *args):
if self.list_vadj_value != None:
self.clist.get_vadjustment().set_value(AccountsConfBox.list_vadj_value)
self.list_vadj_value = None
def row_activated_event(self, tree, path, column):
model = tree.get_model()
self.edit(model.get_value(model.get_iter(path), 0))
def get_selection(self):
return self.list_selection[:]
def selection_changed_event(self, sel):
def getsel(model, path, iter, aid):
aid.append(model.get_value(iter, 0))
self.list_selection[:] = []
sel.selected_foreach(getsel, self.list_selection)
has_selection = len(self.list_selection) > 0
self.remove_btn.set_sensitive(has_selection)
self.edit_btn.set_sensitive(has_selection)
self.duplicate_btn.set_sensitive(has_selection)
self.dial_btn.set_sensitive(has_selection and
not self.app.is_connection_init())
def refresh(self):
if self.clist == None: return
selection = self.get_selection()
store = self.clist.get_model()
accounts = self.app.accounts.ls_accounts()
s = self.clist.get_selection()
store.clear()
for name, aid in accounts:
i = store.append()
store.set(i, 0, aid, 1, name)
if aid in selection: s.select_iter(i)
def edit(self, acc_id):
try: acc = self.app.accounts.get_account(acc_id)
except NoAccountException:
self.refresh()
return
window = EditAccountWindow(self.app.accounts.get_account(acc_id),
self.app.config.default_account, self.refresh,
self.app.show_help_action)
window.set_modal(1)
window.show()
def edit_action(self, *args):
selection = self.get_selection()
if len(selection) == 0: return
self.edit(selection[0])
def add_action(self, *args):
acc = self.app.accounts.new_account()
self.refresh()
window = EditAccountWindow(acc,
self.app.config.default_account, self.refresh,
self.app.show_help_action)
window.set_modal(1)
window.show()
def remove_action(self, *args):
selection = self.get_selection()
if len(selection) == 0: return
r = gtk.RESPONSE_YES
if self.app.config.confirm_delete_account:
msgbox = gtk.MessageDialog(None,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO,
len(selection) == 1 and (_("Delete account %s?") %
self.app.accounts.get_account(selection[0]).name) or
(_("Delete %d accounts?") % len(selection)))
r = msgbox.run()
msgbox.destroy()
if r == gtk.RESPONSE_YES:
self.app.accounts.remove_accounts(selection)
m = self.clist.get_model()
i = m.get_iter_first()
while i:
j = m.iter_next(i)
if m.get_value(i, 0) in selection: m.remove(i)
i = j
def duplicate_action(self, *args):
selection = self.get_selection()
if len(selection) == 0: return
aid = selection[0]
try: acc = self.app.accounts.duplicate_account(aid)
except NoAccountException:
self.refresh()
return
self.refresh()
window = EditAccountWindow(acc,
self.app.config.default_account, self.refresh,
self.app.show_help_action)
window.set_modal(1)
window.show()
def import_action(self, *args):
import chestnut_dialer.gtk2_ui.accimport
window = chestnut_dialer.gtk2_ui.accimport.ImportWindow(
self.app.accounts, self.refresh)
window.set_modal(1)
window.show()
def dial_action(self, *args):
selection = self.get_selection()
if len(selection) == 0: return
try: acc = self.app.accounts.get_account(selection[0])
except NoAccountException:
self.refresh()
return
self.app.connect(acc)
class ConfigBox(chestnut_dialer.gtk2_ui.box.BaseBox):
app = None
def __init__(self, app):
self.app = app
xml = gtk.glade.XML(config_glade_file, "ConfigBox",
chestnut_dialer.domain)
self.widget = xml.get_widget("ConfigBox")
self.init_buttons(xml.get_widget("ButtonBox"))
def destroy(self):
self.app = None
def init_buttons(self, cont):
btn = gtk.Button(_("Options"))
btn.connect("clicked", self.options_action)
cont.pack_start(btn, fill = 1, expand = 0)
btn = gtk.Button(_("Default Account"))
btn.connect("clicked", self.default_account_action)
cont.pack_start(btn, fill = 1, expand = 0)
btn = gtk.Button(_("View Connecting Log"))
btn.connect("clicked", self.view_connecting_log_action)
cont.pack_start(btn, fill = 1, expand = 0)
def default_account_action(self, *args):
window = EditDefAccountWindow(
self.app.config.default_account, self.app.show_help_action)
window.set_modal(1)
window.show()
def options_action(self, *args):
window = OptionsWindow(self.app.config, self.app.show_help_action)
window.set_modal(1)
window.show()
def view_connecting_log_action(self, *args):
dialog = gtk.Dialog(_("Connecting Log"),
self.app.main_window,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CLOSE, gtk.RESPONSE_NONE))
dialog.set_default_size(400, 300)
b = gtk.TextBuffer()
b.set_text(self.app.connecting_log)
t = gtk.TextView(b)
t.set_editable(False)
try: t.modify_font(pango.FontDescription("Monospace 9"))
except NameError: pass
s = gtk.ScrolledWindow()
s.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
s.add_with_viewport(t)
dialog.vbox.add(s)
dialog.show_all()
dialog.run()
dialog.destroy()
|