1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
|
#!/usr/bin/perl -w
=head1 NAME
Debconf::FrontEnd - base FrontEnd
=cut
package Debconf::FrontEnd;
use strict;
use Debconf::Gettext;
use Debconf::Priority;
use Debconf::Log ':all';
use base qw(Debconf::Base);
=head1 DESCRIPTION
This is the base of the FrontEnd class. Each FrontEnd presents a
user interface of some kind to the user, and handles generating and
communicating with Elements to form that FrontEnd.
=head1 FIELDS
=over 4
=item elements
A reference to an array that contains all the elements that the FrontEnd
needs to show to the user.
=item interactive
Is this an interactive FrontEnd?
=item capb
Holds any special capabilities the FrontEnd supports.
=item title
The title of the FrontEnd.
=item requested_title
The title last explicitly requested for the FrontEnd. May be temporarily
overridden by another title, e.g. for progress bars.
=item info
A question containing an informative message to be displayed, without
requiring any acknowledgement from the user. FrontEnds may choose not to
implement this. If they do implement it, they should display the info
persistently until some other info comes along.
=item backup
A flag that Elements can set when they are displayed, to tell the FrontEnd
that the user has indicated they want to back up.
=item capb_backup
This will be set if the confmodule states it has the backup capability.
=item progress_bar
The element used for the currently running progress bar, if any.
=item need_tty
Set to true if the frontend needs a tty. Defaults to true.
Note that setting this to true does not ensure that the frontend actually
gets a tty. It does let debconf abort in cases where the selected frontend
cannot work due to it being impossible to get a tty for it.
=back
=head1 METHODS
=over 4
=item init
Sets several of the fields to defaults.
=cut
sub init {
my $this=shift;
$this->elements([]);
$this->interactive('');
$this->capb('');
$this->title('');
$this->requested_title('');
$this->info(undef);
$this->need_tty(1);
}
=item elementtype
What type of elements this frontend uses. Defaults to returning the same
name as the frontend, but tightly-linked frontends might want to share
elements; if so, one can override this with a method that returns the name
of the other.
This may be called as either a class or an object method.
=cut
sub elementtype {
my $this=shift;
my $ret;
if (ref $this) {
# Called as object method.
($ret) = ref($this) =~ m/Debconf::FrontEnd::(.*)/;
}
else {
# Called as class method.
($ret) = $this =~ m/Debconf::FrontEnd::(.*)/;
}
return $ret;
}
my %nouse;
sub _loadelementclass {
my $this=shift;
my $type=shift;
my $nodebug=shift;
# See if we need to load up the object class.. The eval
# inside here is leak-prone if run multiple times on a
# given type, so make sure to only ever do it once per type.
if (! UNIVERSAL::can("Debconf::Element::$type", 'new')) {
return if $nouse{$type};
eval qq{use Debconf::Element::$type};
if ($@ || ! UNIVERSAL::can("Debconf::Element::$type", 'new')) {
warn sprintf(gettext("Unable to load Debconf::Element::%s. Failed because: %s"), $type, $@) if ! $nodebug;
$nouse{$type}=1;
return;
}
}
}
=item makeelement
Creates an Element of the type used by this FrontEnd. Pass in the question
that will be bound to the Element. It returns the generated Element, or false
if it was unable to make an Element of the given ype.
This may be called as either a class or an object method.
Normally, it outputs debug codes if creating the Element fails. If failure
is expected, a second parameter can be passed with a true value to turn
off those debug messages.
=cut
sub makeelement {
my $this=shift;
my $question=shift;
my $nodebug=shift;
# Figure out what type of frontend this is.
my $type=$this->elementtype.'::'.ucfirst($question->type);
$type=~s/::$//; # in case the question has no type..
$this->_loadelementclass($type, $nodebug);
my $element="Debconf::Element::$type"->new(question => $question);
return if ! ref $element;
return $element;
}
=item add
Adds an Element to the list to be displayed to the user. Just pass the
Element to add. Note that it detects multiple Elements that point to the
same Question and only adds the first.
=cut
sub add {
my $this=shift;
my $element=shift;
foreach (@{$this->elements}) {
return if $element->question == $_->question;
}
$element->frontend($this);
push @{$this->elements}, $element;
}
=item go
Display accumulated Elements to the user.
This will normally return true, but if the user indicates they want to
back up, it returns false.
=cut
sub go {
my $this=shift;
$this->backup('');
foreach my $element (@{$this->elements}) {
$element->show;
return if $this->backup && $this->capb_backup;
}
return 1;
}
=item progress_start
Start a progress bar.
=cut
sub progress_start {
my $this=shift;
my $min=shift;
my $max=shift;
my $question=shift;
my $type = $this->elementtype.'::Progress';
$this->_loadelementclass($type);
my $element="Debconf::Element::$type"->new(question => $question);
unless (ref $element) {
# TODO: error somehow
return;
}
$element->frontend($this);
$element->progress_min($min);
$element->progress_max($max);
$element->progress_cur($min);
$element->start;
$this->progress_bar($element);
}
=item progress_set
Set the value of a progress bar, within the minimum and maximum values
passed when starting it.
=cut
sub progress_set {
my $this=shift;
my $value=shift;
$this->progress_bar->set($value);
}
=item progress_step
Step a progress bar by the given amount.
=cut
sub progress_step {
my $this=shift;
my $inc=shift;
$this->progress_set($this->progress_bar->progress_cur + $inc);
}
=item progress_info
Set an informational message to be displayed along with the progress bar.
=cut
sub progress_info {
my $this=shift;
my $question=shift;
$this->progress_bar->info($question);
}
=item progress_stop
Tear down a progress bar.
=cut
sub progress_stop {
my $this=shift;
$this->progress_bar->stop;
$this->progress_bar(undef);
}
=item clear
Clear out the accumulated Elements.
=cut
sub clear {
my $this=shift;
$this->elements([]);
}
=item default_title
This sets the title field to a default. Pass in the name of the
package that is being configured.
=cut
sub default_title {
my $this=shift;
$this->title(sprintf(gettext("Configuring %s"), shift));
$this->requested_title($this->title);
}
=item shutdown
This method should be called before a frontend is shut down.
=cut
sub shutdown {}
=back
=head1 AUTHOR
Joey Hess <joeyh@debian.org>
=cut
1
|