1 |
#!/usr/bin/perl |
#!/usr/bin/perl |
2 |
|
|
3 |
# Postfix |
# isdn_answering |
4 |
|
|
5 |
# Copyright (C) 2003 Brian J. Murrell (brian@interlinx.bc.ca) |
# Copyright (C) 2003 Damien Krotkine (dams@tuxfamily.org) |
|
# (based heavily on Damien's Netconfig) |
|
6 |
# |
# |
7 |
# This program is free software; you can redistribute it and/or modify |
# This program is free software; you can redistribute it and/or modify |
8 |
# it under the terms of the GNU General Public License as published by |
# it under the terms of the GNU General Public License as published by |
37 |
# we dump the content for debugging purpose |
# we dump the content for debugging purpose |
38 |
print Dumper($struct) . "\n"; |
print Dumper($struct) . "\n"; |
39 |
|
|
40 |
# a window |
# the main window |
41 |
my $window = Gtk2::Window->new('toplevel'); |
my $window = Gtk2::Window->new('toplevel'); |
42 |
$window->signal_connect(delete_event => sub { ugtk2->exit(0) }); |
$window->signal_connect(delete_event => sub { ugtk2->exit(0) }); |
43 |
$window->set_border_width(5); |
$window->set_border_width(5); |
44 |
$window->set_position('center'); |
$window->set_position('center'); |
45 |
$window->set_title(N('ISDN answering machine configuration')); |
$window->set_title(N('ISDN answering machine configuration')); |
46 |
|
|
47 |
my $button_box = Gtk2::HButtonBox->new; |
#we create the list model |
|
$button_box->set_spacing_default(5); |
|
48 |
my $users_clist_model = Gtk2::ListStore->new('Glib::String'); |
my $users_clist_model = Gtk2::ListStore->new('Glib::String'); |
49 |
|
|
50 |
|
#we add widget in the main window |
51 |
gtkadd($window, |
gtkadd($window, |
52 |
gtkpack_(Gtk2::VBox->new(0,5), |
gtkpack_(Gtk2::VBox->new(0,5), |
53 |
0, N('ISDN Answering Machine Configurator'), |
0, N('ISDN Answering Machine Configurator'), |
54 |
|
|
55 |
|
#global section |
56 |
1, gtkadd(new Gtk2::Frame(N('General parameters')), |
1, gtkadd(new Gtk2::Frame(N('General parameters')), |
57 |
gtkset_border_width(mycreate_packtable({}, |
gtkset_border_width(create_packtable({}, |
58 |
[ N('Audio snippets directory'), getBestWidget($struct, '{GLOBAL}{audio_dir}') ], |
[ N('Audio snippets directory'), getBestWidget($struct, '{GLOBAL}{audio_dir}') ], |
59 |
[ N('User-specific data directory'), getBestWidget($struct, '{GLOBAL}{voice_user_dir}') ], |
[ N('User-specific data directory'), getBestWidget($struct, '{GLOBAL}{voice_user_dir}') ], |
60 |
# [ getBestWidget($struct->{general}, '{user_audio_files}', N('Search for audio files')) ], |
[ N('Search for audio files'), getBestWidget($struct, '{GLOBAL}{user_audio_files}') ], |
61 |
[ N('Voice delay (in sec.)'), getBestWidget($struct, '{GLOBAL}{voice_delay}') ], |
[ N('Voice delay (in sec.)'), getBestWidget($struct, '{GLOBAL}{voice_delay}') ], |
62 |
[ N('Announcement'), getBestWidget($struct, '{GLOBAL}{annoucement}') ], |
[ N('Announcement'), getBestWidget($struct, '{GLOBAL}{announcement}') ], |
63 |
[ N('Record length (in sec.)'), getBestWidget($struct, '{GLOBAL}{record_length}') ], |
[ N('Record length (in sec.)'), getBestWidget($struct, '{GLOBAL}{record_length}') ], |
64 |
[ N('Record silence timeout (in sec.)'), getBestWidget($struct, '{GLOBAL}{record_silence_timeout}') ], |
[ N('Record silence timeout (in sec.)'), getBestWidget($struct, '{GLOBAL}{record_silence_timeout}') ], |
65 |
), 5), |
), 5), |
66 |
), |
), |
67 |
|
|
68 |
|
#users section |
69 |
1, gtkadd(new Gtk2::Frame(N('Users')), |
1, gtkadd(new Gtk2::Frame(N('Users')), |
70 |
gtkpack_(Gtk2::HBox->new(0,5), |
gtkset_border_width(gtkpack_(Gtk2::HBox->new(0,5), |
71 |
1, my $users_clist = Gtk2::TreeView->new_with_model($users_clist_model), |
1, my $users_clist = Gtk2::TreeView->new_with_model($users_clist_model), |
72 |
0, gtkadd(gtkset_layout(Gtk2::VButtonBox->new, 'start'), |
0, gtkadd(gtkset_layout(Gtk2::VButtonBox->new, 'start'), |
73 |
gtksignal_connect(new Gtk2::Button(N("Add")), clicked => sub { user_add() }), |
gtksignal_connect(new Gtk2::Button(N("Add New...")), clicked => sub { user_add() }), |
74 |
gtksignal_connect(new Gtk2::Button(N("Delete")), clicked => sub { user_delete() }), |
gtksignal_connect(new Gtk2::Button(N("Delete")), clicked => sub { user_del() }), |
75 |
gtksignal_connect(new Gtk2::Button(N("Edit...")), clicked => sub { user_edit() }), |
gtksignal_connect(new Gtk2::Button(N("Edit...")), clicked => sub { user_edit() }), |
76 |
) |
) |
77 |
) |
), 5) |
78 |
), |
), |
79 |
0, gtkadd(gtkset_layout($button_box, 'end'), |
|
80 |
|
#bottom buttons |
81 |
|
0, gtkadd(gtkset_layout(Gtk2::HButtonBox->new, 'end'), |
82 |
gtksignal_connect(new Gtk2::Button(N("Apply")), clicked => sub { save(); }), |
gtksignal_connect(new Gtk2::Button(N("Apply")), clicked => sub { save(); }), |
83 |
gtksignal_connect(new Gtk2::Button(N("Cancel")), clicked => sub { cancel_exit(); }), |
gtksignal_connect(new Gtk2::Button(N("Cancel")), clicked => sub { cancel_exit(); }), |
84 |
gtksignal_connect(new Gtk2::Button(N("OK")), clicked => sub { save_exit(); }), |
gtksignal_connect(new Gtk2::Button(N("OK")), clicked => sub { save_exit(); }), |
86 |
) |
) |
87 |
); |
); |
88 |
|
|
89 |
|
# we set up the column title of the list |
90 |
$users_clist->append_column(Gtk2::TreeViewColumn->new_with_attributes(N('Name'), Gtk2::CellRendererText->new, 'text' => 0)); |
$users_clist->append_column(Gtk2::TreeViewColumn->new_with_attributes(N('Name'), Gtk2::CellRendererText->new, 'text' => 0)); |
|
foreach (keys %$struct) { |
|
|
$_ eq 'GLOBAL' and next; |
|
|
$users_clist_model->append_set(0 => $_); |
|
|
} |
|
91 |
|
|
92 |
|
# we fill the list entries |
93 |
|
build_user_list(); |
94 |
|
|
95 |
# we make everything visible in the window |
# we make everything visible in the window |
96 |
$window->show_all(); |
$window->show_all(); |
105 |
ugtk2->exit(0); |
ugtk2->exit(0); |
106 |
|
|
107 |
|
|
108 |
|
##### subfonctions ##### |
109 |
|
|
110 |
|
# this fonction builds the users list |
111 |
|
sub build_user_list { |
112 |
|
#we clear the list in case it wasn't empty |
113 |
|
$users_clist_model->clear(); |
114 |
|
|
115 |
|
#for each section different from 'GLOBAL', we append a line. |
116 |
|
foreach (keys %$struct) { |
117 |
|
$_ eq 'GLOBAL' and next; |
118 |
|
$users_clist_model->append_set(0 => $_); |
119 |
|
} |
120 |
|
} |
121 |
|
|
122 |
|
# called when we want to add a user |
123 |
|
sub user_add { |
124 |
|
|
125 |
|
# we ask for the name of the new user |
126 |
|
if (create_dialog(N('Enter the name of the user to add'), |
127 |
|
gtkpack_(gtkset_border_width(Gtk2::HBox->new(0,5), 5), |
128 |
|
0, N('Name :'), |
129 |
|
1, my $entry = Gtk2::Entry->new(), |
130 |
|
), |
131 |
|
), |
132 |
|
{ |
133 |
|
stock => 'gtk-dialog-info', |
134 |
|
cancel => 1, |
135 |
|
} |
136 |
|
) { |
137 |
|
|
138 |
|
# we create a new void structure |
139 |
|
my $user_struct = new Libconf::Glueconf::Answering_Machine(); |
140 |
|
|
141 |
|
# we give it to edition |
142 |
|
user_edit($entry->get_text(), $user_struct); |
143 |
|
|
144 |
|
# we rebuild the user list |
145 |
|
build_user_list(); |
146 |
|
} |
147 |
|
} |
148 |
|
|
149 |
|
# called when we want to edit the user settings |
150 |
|
sub user_edit { |
151 |
|
# we may receive a user name and a void user |
152 |
|
my ($user, $user_struct) = @_; |
153 |
|
|
154 |
|
# if we didn't get a username, we pick the name selected from the gtk list |
155 |
|
$user ||= $users_clist_model->get(($users_clist->get_selection->get_selected)[1], 0); |
156 |
|
|
157 |
|
# if we didn't get the user struct, we pick it from $struct |
158 |
|
if (!defined $user_struct) { |
159 |
|
|
160 |
|
# new void struct |
161 |
|
$user_struct= new Libconf::Glueconf::Answering_Machine(); |
162 |
|
|
163 |
|
# we copy the settings (need work, should be easier than that. |
164 |
|
$user_struct->{$user}{$_} = $struct->{$user}{$_} foreach (qw(voice_delay announcement record_length record_silence_timeout voice_numbers pin voice_action))a; |
165 |
|
} |
166 |
|
|
167 |
|
# we create the dialog so that it's possible to edit the settings |
168 |
|
if (create_dialog($user, |
169 |
|
gtkadd(new Gtk2::Frame(N('User parameters')), |
170 |
|
gtkset_border_width(create_packtable({}, |
171 |
|
[ N('Voice delay (in sec.)'), getBestWidget($user_struct, "{$user}{voice_delay}") ], |
172 |
|
[ N('Announcement'), getBestWidget($user_struct, "{$user}{announcement}") ], |
173 |
|
[ N('Record length (in sec.)'), getBestWidget($user_struct, "{$user}{record_length}") ], |
174 |
|
[ N('Record silence timeout (in sec.)'), getBestWidget($user_struct, "{$user}{record_silence_timeout}") ], |
175 |
|
[ N('Voice numbers'), getBestWidget($user_struct, "{$user}{voice_numbers}") ], |
176 |
|
[ N('Pin'), getBestWidget($user_struct, "{$user}{pin}") ], |
177 |
|
[ N('Voice action'), getBestWidget($user_struct, "{$user}{voice_action}") ], |
178 |
|
), 5), |
179 |
|
), |
180 |
|
{ |
181 |
|
stock => 'gtk-dialog-info', |
182 |
|
cancel => 1, |
183 |
|
} |
184 |
|
) |
185 |
|
) { |
186 |
|
|
187 |
|
# if the changes are validated, we copy the user sttings in $struct. |
188 |
|
$struct->{$user}{$_} = $user_struct->{$user}{$_} foreach (qw(voice_delay announcement record_length record_silence_timeout voice_numbers pin voice_action)); |
189 |
|
} |
190 |
|
} |
191 |
|
|
192 |
|
# called when we want to remove a user |
193 |
|
sub user_del { |
194 |
|
|
195 |
sub user_add { } |
# we get the user name from the selected entry of the list |
|
sub user_delete { |
|
196 |
my $user = $users_clist_model->get(($users_clist->get_selection->get_selected)[1], 0); |
my $user = $users_clist_model->get(($users_clist->get_selection->get_selected)[1], 0); |
197 |
print "delete $user\n"; |
|
198 |
|
# we remove the corresponding section of the $struct |
199 |
|
delete $struct->{$user}; |
200 |
|
|
201 |
|
# we rebuild the users list |
202 |
|
build_user_list(); |
203 |
} |
} |
204 |
|
|
205 |
|
|
206 |
# the function called when the user clicks on the OK button |
# the function called when the user clicks on the Apply button |
207 |
sub save_exit { |
sub save { |
208 |
|
|
209 |
# we ask the $sys_network object to write itself back to the real config file |
# we ask the $sys_network object to write itself back to the real config file |
210 |
# he knows everything about himself, so no need to give him any arg. |
# it knows everything about itself, so no need to give him any arg. |
211 |
# the file is rewritten, without loosing any information or comments. |
# the file is rewritten, without loosing any information or comments. |
212 |
$postfix->writeconf(); |
$struct->writeConf(); |
213 |
|
} |
214 |
|
|
215 |
|
# the function called when the user clicks on the OK button |
216 |
|
sub save_exit { |
217 |
|
|
218 |
|
# we save the settings |
219 |
|
save(); |
220 |
|
|
221 |
# we exit the gtk2 main loop |
# we exit the gtk2 main loop |
222 |
Gtk2->main_quit(); |
Gtk2->main_quit(); |
229 |
Gtk2->main_quit(); |
Gtk2->main_quit(); |
230 |
} |
} |
231 |
|
|
|
|
|
|
sub mycreate_packtable { |
|
|
my ($options, @l) = @_; |
|
|
my $w = Gtk2::Table->new(0, 0, $options->{homogeneous} || 0); |
|
|
each_index { |
|
|
my ($i, $l) = ($::i, $_); |
|
|
if (@$l == 1 ) { |
|
|
$w->attach($l->[0], 0, 2, $i, $i + 1, 'fill', 'fill', 5, 0); |
|
|
} else { |
|
|
each_index { |
|
|
my $j = $::i; |
|
|
if ($_) { |
|
|
ref $_ or $_ = gtkpack_(Gtk2::HBox->new(0,0), |
|
|
1, Gtk2::HBox->new(0,0), |
|
|
0, Gtk2::Label->new($_) |
|
|
); |
|
|
$w->attach($_, $j, $j + 1, $i, $i + 1, 'fill', 'fill', 5, 0); |
|
|
$_->show; |
|
|
} |
|
|
} @$l; |
|
|
} |
|
|
} @l; |
|
|
$w->set_col_spacings($options->{col_spacings} || 0); |
|
|
$w->set_row_spacings($options->{row_spacings} || 5); |
|
|
$w |
|
|
} |
|