File Coverage

blib/lib/UI/Dialog/Backend/Zenity.pm
Criterion Covered Total %
statement 53 479 11.0
branch 5 142 3.5
condition 19 212 8.9
subroutine 9 42 21.4
pod 22 32 68.7
total 108 907 11.9


line stmt bran cond sub pod time code
1             package UI::Dialog::Backend::Zenity;
2             ###############################################################################
3             # Copyright (C) 2015 Kevin C. Krinke
4             #
5             # This library is free software; you can redistribute it and/or
6             # modify it under the terms of the GNU Lesser General Public
7             # License as published by the Free Software Foundation; either
8             # version 2.1 of the License, or (at your option) any later version.
9             #
10             # This library is distributed in the hope that it will be useful,
11             # but WITHOUT ANY WARRANTY; without even the implied warranty of
12             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13             # Lesser General Public License for more details.
14             #
15             # You should have received a copy of the GNU Lesser General Public
16             # License along with this library; if not, write to the Free Software
17             # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18             ###############################################################################
19 1     1   21595 use 5.006;
  1         4  
20 1     1   6 use strict;
  1         2  
  1         26  
21 1     1   725 use FileHandle;
  1         14628  
  1         6  
22 1     1   408 use Cwd qw( abs_path );
  1         2  
  1         49  
23 1     1   5 use Carp;
  1         2  
  1         51  
24 1     1   710 use UI::Dialog::Backend;
  1         4  
  1         44  
25              
26             BEGIN {
27 1     1   8 use vars qw( $VERSION @ISA );
  1         2  
  1         59  
28 1     1   10 @ISA = qw( UI::Dialog::Backend );
29 1         5617 $VERSION = '1.11';
30             }
31              
32             #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
33             #: Constructor Method
34             #:
35              
36             sub new {
37 1     1 1 824 my $proto = shift();
38 1   33     9 my $class = ref($proto) || $proto;
39 1 50       10 my $cfg = ((ref($_[0]) eq "HASH") ? $_[0] : (@_) ? { @_ } : {});
    50          
40 1         2 my $self = {};
41 1         3 bless($self, $class);
42 1         13 $self->{'_state'} = {};
43 1         4 $self->{'_opts'} = {};
44              
45             #: Dynamic path discovery...
46 1         20 my $CFG_PATH = $cfg->{'PATH'};
47 1 50       8 if ($CFG_PATH) {
    50          
48 0 0       0 if (ref($CFG_PATH) eq "ARRAY") {
    0          
    0          
49 0         0 $self->{'PATHS'} = $CFG_PATH;
50             }
51             elsif ($CFG_PATH =~ m!:!) {
52 0         0 $self->{'PATHS'} = [ split(/:/,$CFG_PATH) ];
53             }
54             elsif (-d $CFG_PATH) {
55 0         0 $self->{'PATHS'} = [ $CFG_PATH ];
56             }
57             }
58             elsif ($ENV{'PATH'}) {
59 1         8 $self->{'PATHS'} = [ split(/:/,$ENV{'PATH'}) ];
60             }
61             else {
62 0         0 $self->{'PATHS'} = '';
63             }
64              
65 1   50     8 $self->{'_opts'}->{'literal'} = $cfg->{'literal'} || 0;
66 1   50     9 $self->{'_opts'}->{'debug'} = $cfg->{'debug'} || undef();
67 1   50     7 $self->{'_opts'}->{'window-icon'} = $cfg->{'window-icon'} || undef();
68 1   50     6 $self->{'_opts'}->{'title'} = $cfg->{'title'} || undef();
69 1   50     8 $self->{'_opts'}->{'width'} = $cfg->{'width'} || 65;
70 1   50     7 $self->{'_opts'}->{'height'} = $cfg->{'height'} || 10;
71 1   50     6 $self->{'_opts'}->{'display'} = $cfg->{'display'} || undef();
72 1   50     7 $self->{'_opts'}->{'name'} = $cfg->{'name'} || undef();
73 1   50     6 $self->{'_opts'}->{'class'} = $cfg->{'class'} || undef();
74 1         11 $self->{'_opts'}->{'bin'} = $self->_find_bin('zenity');
75 1   50     8 $self->{'_opts'}->{'autoclear'} = $cfg->{'autoclear'} || 0;
76 1   50     6 $self->{'_opts'}->{'clearbefore'} = $cfg->{'clearbefore'} || 0;
77 1   50     6 $self->{'_opts'}->{'clearafter'} = $cfg->{'clearafter'} || 0;
78 1   50     8 $self->{'_opts'}->{'beepbin'} = $cfg->{'beepbin'} || $self->_find_bin('beep') || '/usr/bin/beep';
79 1   50     8 $self->{'_opts'}->{'beepbefore'} = $cfg->{'beepbefore'} || 0;
80 1   50     11 $self->{'_opts'}->{'beepafter'} = $cfg->{'beepafter'} || 0;
81 1   50     9 $self->{'_opts'}->{'callbacks'} = $cfg->{'callbacks'} || undef();
82 1   50     5 $self->{'_opts'}->{'timeout'} = $cfg->{'timeout'} || 0;
83 1   50     6 $self->{'_opts'}->{'wait'} = $cfg->{'wait'} || 0;
84 1 50       14 unless (-x $self->{'_opts'}->{'bin'}) {
85 1         343 croak("the zenity binary could not be found at: ".$self->{'_opts'}->{'bin'});
86             }
87              
88 0   0       $self->{'_opts'}->{'trust-input'} = $cfg->{'trust-input'} || 0;
89              
90 0           my $command = $self->{'_opts'}->{'bin'}." --version";
91 0           my $version = `$command 2>&1`;
92 0           chomp( $version );
93 0   0       $self->{'ZENITY_VERSION'} = $version || '1';
94              
95 0 0         $self->{'test_mode'} = $cfg->{'test_mode'} if exists $cfg->{'test_mode'};
96 0           $self->{'test_mode_result'} = '';
97              
98 0           return($self);
99             }
100              
101             #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
102             #: Private Methods
103             #:
104              
105             my $SIG_CODE = {};
106             sub _del_gauge {
107             #: this is beyond self...
108 0     0     my $CODE = $SIG_CODE->{$$};
109 0 0         unless (not ref($CODE)) {
110 0           delete($CODE->{'_GAUGE'});
111 0           $CODE->rv('1');
112 0           $CODE->rs('null');
113 0           $CODE->ra('null');
114 0           $SIG_CODE->{$$} = "";
115             }
116             }
117             sub append_format_base {
118 0     0 0   my ($self,$args,$fmt) = @_;
119 0           $ENV{'ZENITY_CANCEL'} = '1';
120 0           $ENV{'ZENITY_ERROR'} = '254';
121 0           $ENV{'ZENITY_ESC'} = '255';
122 0           $ENV{'ZENITY_EXTRA'} = '3';
123 0           $ENV{'ZENITY_HELP'} = '2';
124 0           $ENV{'ZENITY_OK'} = '0';
125 0           $fmt = $self->append_format_check($args,$fmt,'window-icon','--window-icon {{window-icon}}');
126 0           $fmt = $self->append_format_check($args,$fmt,'width','--width {{width}}');
127 0           $fmt = $self->append_format_check($args,$fmt,'height','--height {{height}}');
128 0           $fmt = $self->append_format_check($args,$fmt,'display','--display {{display}}');
129 0           $fmt = $self->append_format_check($args,$fmt,'name','--name {{name}}');
130 0           $fmt = $self->append_format_check($args,$fmt,'class','--class {{class}}');
131              
132 0           return $fmt;
133             }
134              
135             sub _is_bad_version {
136             # my $self = shift();
137             # my ($d_maj, $d_min, $d_mac) = ( 1, 4, 0 );
138             # my ($z_maj, $z_min, $z_mac) = ( 0, 0, 0 );
139             # my $zenity_version = $self->{'ZENITY_VERSION'} || '0.0.0';
140             # if ( $zenity_version =~ m!^(\d+)\.(\d+)\.(\d+)$! ) {
141             # ($z_maj, $z_min, $z_mac) = ( $1, $2, $3 );
142             # }
143             # if ( ( $d_maj < $z_maj ) ||
144             # ( $d_maj == $z_maj && $d_min < $z_min ) ||
145             # ( $d_maj == $z_maj && $d_min == $z_min && $d_mac < $z_mac )
146             # ) {
147             # return(0);
148             # }
149 0     0     return(1);
150             }
151              
152             #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
153             #: Override Inherited Methods
154             #:
155              
156             #: execute a simple command (return the exit code only);
157             sub command_state {
158 0     0 1   my $self = $_[0];
159 0           my $cmnd = $_[1];
160 0 0         if ($self->is_unit_test_mode()) {
161 0           $self->{'test_mode_result'} = $cmnd;
162 0           return 0;
163             }
164 0           $self->_debug("command: ".$cmnd,1);
165 0           system($cmnd . "> /dev/null 2> /dev/null");
166 0           my $rv = $? >> 8;
167 0           $self->_debug("command rv: ".$rv,2);
168 0           return($rv);
169             }
170              
171             #: execute a command and return the exit code and one-line SCALAR
172             sub command_string {
173 0     0 1   my $self = $_[0];
174 0           my $cmnd = $_[1];
175 0 0         if ($self->is_unit_test_mode()) {
176 0           $self->{'test_mode_result'} = $cmnd;
177 0 0         return (wantarray) ? (0,'') : '';
178             }
179 0           $self->_debug("command: ".$cmnd,1);
180 0           my $text;
181 0 0         if ($self->_is_bad_version()) {
182             #we should ignore STDERR...
183 0           chomp($text = `$cmnd 2> /dev/null`);
184             }
185             else {
186 0           chomp($text = `$cmnd 2>&1`);
187             }
188 0           my $rv = $? >> 8;
189 0           $self->_debug("command rs: ".$rv." '".$text."'",2);
190 0 0         return($text) unless defined wantarray;
191 0 0         return (wantarray) ? ($rv,$text) : $text;
192             }
193              
194             #: execute a command and return the exit code and ARRAY of data
195             sub command_array {
196 0     0 1   my $self = $_[0];
197 0           my $cmnd = $_[1];
198 0 0         if ($self->is_unit_test_mode()) {
199 0           $self->{'test_mode_result'} = $cmnd;
200 0 0         return (wantarray) ? (0,[]) : [];
201             }
202 0           $self->_debug("command: ".$cmnd,1);
203 0           my $text;
204 0 0         if ($self->_is_bad_version()) {
205             #we should ignore STDERR...
206 0           chomp($text = `$cmnd 2> /dev/null`);
207             }
208             else {
209 0           chomp($text = `$cmnd 2>&1`);
210             }
211 0           my $rv = $? >> 8;
212 0           $self->_debug("command ra: ".$rv." '".$text."'",2);
213 0 0         return([split(/\n/,$text)]) unless defined wantarray;
214 0 0         return (wantarray) ? ($rv,[split(/\n/,$text)]) : [split(/\n/,$text)];
215             }
216              
217             #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
218             #: Public Methods
219             #:
220              
221             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
222             #: Ask a binary question (Yes/No)
223             sub question {
224 0     0 1   my $self = shift();
225 0   0       my $caller = (caller(1))[3] || 'main';
226 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
227 0 0 0       if ($_[0] && $_[0] eq 'caller') {
228 0           shift(); $caller = shift();
  0            
229             }
230 0           my $args = $self->_pre($caller,@_);
231              
232 0           my $fmt = $self->prepare_format($args);
233 0           $fmt = $self->append_format_base($args,$fmt);
234 0           $fmt = $self->append_format($fmt,'--question --text {{text}}');
235             my $command = $self->prepare_command
236             ( $args, $fmt,
237 0           text => $self->make_kvt($args,$args->{'text'}),
238             );
239              
240 0           my $rv = $self->command_state($command);
241 0   0       $self->rv($rv||'null');
242 0           $self->ra('null');
243 0           $self->rs('null');
244 0           my $this_rv;
245 0 0 0       if ($rv && $rv >= 1) {
246 0           $self->ra("NO");
247 0           $self->rs("NO");
248 0           $this_rv = 0;
249             }
250             else {
251 0           $self->ra("YES");
252 0           $self->rs("YES");
253 0           $this_rv = 1;
254             }
255 0           $self->_post($args);
256 0           return($this_rv);
257             }
258             #: Zenity doesn't support alternation of the buttons like gdialog et al.
259             #: so here we just wrap for compliance.
260             sub yesno {
261 0     0 1   my $self = shift();
262 0   0       return($self->question('caller',((caller(1))[3]||'main'),@_));
263             }
264             sub noyes {
265 0     0 0   my $self = shift();
266 0   0       return($self->question('caller',((caller(1))[3]||'main'),@_));
267             }
268              
269             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
270             #: Text entry
271             sub entry {
272 0     0 0   my $self = shift();
273 0   0       my $caller = (caller(1))[3] || 'main';
274 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
275 0 0 0       if ($_[0] && $_[0] eq 'caller') {
276 0           shift(); $caller = shift();
  0            
277             }
278 0           my $args = $self->_pre($caller,@_);
279              
280 0   0       $args->{'entry'} ||= ($args->{'init'} || $args->{'entry'});
      0        
281              
282 0           my $fmt = $self->prepare_format($args);
283 0           $fmt = $self->append_format_base($args,$fmt);
284 0           $fmt = $self->append_format($fmt,'--entry');
285 0           $fmt = $self->append_format_check($args,$fmt,'hide-text','--hide-text');
286 0           $fmt = $self->append_format_check($args,$fmt,'entry','--entry-text {{entry}}');
287 0           $fmt = $self->append_format($fmt,'--text {{text}}');
288             my $command = $self->prepare_command
289             ( $args, $fmt,
290 0           text => $self->make_kvt($args,$args->{'text'}),
291             );
292              
293 0           my ($rv,$text) = $self->command_string($command);
294 0   0       $self->rv($rv||'null');
295 0           $self->ra('null');
296 0           my $this_rv;
297 0 0 0       if ($rv && $rv >= 1) {
298 0           $self->rs('null');
299 0           $this_rv = 0;
300             }
301             else {
302 0           $self->ra($text);
303 0           $self->rs($text);
304 0           $this_rv = $text;
305             }
306 0           $self->_post($args);
307 0           return($this_rv);
308             }
309             sub inputbox {
310 0     0 1   my $self = shift();
311 0   0       return($self->entry('caller',((caller(1))[3]||'main'),@_));
312             }
313             sub password {
314 0     0 1   my $self = shift();
315 0   0       return($self->entry('caller',((caller(1))[3]||'main'),@_,'hide-text',1));
316             }
317              
318             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
319             #: Text box
320             sub info {
321 0     0 0   my $self = shift();
322 0   0       my $caller = (caller(1))[3] || 'main';
323 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
324 0 0 0       if ($_[0] && $_[0] eq 'caller') {
325 0           shift(); $caller = shift();
  0            
326             }
327 0           my $args = $self->_pre($caller,@_);
328              
329 0           my $fmt = $self->prepare_format($args);
330 0           $fmt = $self->append_format_base($args,$fmt);
331 0 0         if ($args->{'error'}) {
    0          
332 0           $fmt = $self->append_format($fmt,'--error');
333             }
334             elsif ($args->{'warning'}) {
335 0           $fmt = $self->append_format($fmt,'--warning');
336             }
337             else {
338 0           $fmt = $self->append_format($fmt,'--info');
339             }
340 0           $fmt = $self->append_format($fmt,'--text {{text}}');
341             my $command = $self->prepare_command
342             ( $args, $fmt,
343 0           text => $self->make_kvt($args,$args->{'text'}),
344             );
345              
346 0           my $rv = $self->command_state($command);
347 0   0       $self->rv($rv||'null');
348 0           $self->ra('null');
349 0           $self->rs('null');
350 0           my $this_rv;
351 0 0 0       if ($rv && $rv >= 1) {
352 0           $this_rv = 0;
353             }
354             else {
355 0           $this_rv = 1;
356             }
357 0           $self->_post($args);
358 0           return($this_rv);
359             }
360             sub infobox {
361 0     0 0   my $self = shift();
362 0   0       return($self->info('caller',((caller(1))[3]||'main'),@_));
363             }
364             sub msgbox {
365 0     0 1   my $self = shift();
366 0   0       return($self->info('caller',((caller(1))[3]||'main'),@_));
367             }
368             sub error {
369 0     0 0   my $self = shift();
370 0   0       return($self->info('caller',((caller(1))[3]||'main'),@_,'error',1));
371             }
372             sub warning {
373 0     0 0   my $self = shift();
374 0   0       return($self->info('caller',((caller(1))[3]||'main'),@_,'warning',1));
375             }
376              
377             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
378             #: File box
379             sub text_info {
380 0     0 0   my $self = shift();
381 0   0       my $caller = (caller(1))[3] || 'main';
382 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
383 0 0 0       if ($_[0] && $_[0] eq 'caller') {
384 0           shift(); $caller = shift();
  0            
385             }
386 0           my $args = $self->_pre($caller,@_);
387              
388 0   0       my $filename = $args->{'path'} || $args->{'filename'};
389 0           my $fmt = $self->prepare_format($args);
390 0           $fmt = $self->append_format_base($args,$fmt);
391 0           $fmt = $self->append_format($fmt,'--text-info');
392 0           $fmt = $self->append_format_check($args,$fmt,'editable','--editable');
393 0           $fmt = $self->append_format($fmt,'--filename {{filename}}');
394             my $command = $self->prepare_command
395             ( $args, $fmt,
396 0           text => $self->make_kvt($args,$args->{'text'}),
397             filename => $self->make_kvl($args,$filename)
398             );
399              
400 0           my ($rv,$text) = $self->command_string($command);
401 0   0       $self->rv($rv||'null');
402 0           $self->ra('null');
403 0           $self->rs('null');
404 0           my $this_rv = 0;
405 0 0 0       if ($rv && $rv >= 1) {
    0          
406 0           $self->rs('null');
407             }
408             elsif ($args->{'editable'}) {
409 0           $self->ra($text);
410 0           $self->rs($text);
411 0           $this_rv = $text;
412             }
413             else {
414 0           $this_rv = 1;
415             }
416 0           $self->_post($args);
417 0           return($this_rv);
418             }
419             sub textbox {
420 0     0 1   my $self = shift();
421 0   0       return($self->text_info('caller',((caller(1))[3]||'main'),@_));
422             }
423             sub editbox {
424 0     0 1   my $self = shift();
425 0   0       return($self->text_info('caller',((caller(1))[3]||'main'),@_,'editable',1));
426             }
427              
428             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
429             #: Lists
430             sub list {
431 0     0 0   my $self = shift();
432 0   0       my $caller = (caller(1))[3] || 'main';
433 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
434 0 0 0       if ($_[0] && $_[0] eq 'caller') {
435 0           shift(); $caller = shift();
  0            
436             }
437 0           my $args = $self->_pre($caller,@_);
438              
439 0           my $fmt = $self->prepare_format($args);
440 0           $fmt = $self->append_format_base($args,$fmt);
441 0           $fmt = $self->append_format($fmt,'--list');
442 0 0         if ($args->{'checklist'}) {
    0          
443 0           $fmt = $self->append_format($fmt,'--checklist');
444             }
445             elsif ($args->{'radiolist'}) {
446 0           $fmt = $self->append_format($fmt,'--radiolist');
447             }
448 0           $fmt = $self->append_format($fmt,"--separator \$'\\n'");
449              
450 0 0         if (ref($args->{'list'}) eq "ARRAY") {
451 0 0 0       if ($args->{'checklist'}||$args->{'radiolist'}) {
452 0           $fmt = $self->append_format($fmt,'--column " " --column " " --column " "');
453             } else {
454 0           $fmt = $self->append_format($fmt,'--column " " --column " "');
455             }
456 0           while (@{$args->{'list'}}) {
  0            
457 0           my $item = shift(@{$args->{'list'}});
  0            
458 0           $self->clean_format($args->{'trust-input'},\$item);
459 0           my $info = shift(@{$args->{'list'}});
  0            
460 0 0         if (ref($info) eq "ARRAY") {
461 0           $self->clean_format($args->{'trust-input'},\$info->[0]);
462 0 0         $fmt = $self->append_format($fmt,'"'.(($info->[1]) ? 'TRUE' : 'FALSE').'"');
463 0           $fmt = $self->append_format($fmt,'"'.$item.'"');
464 0           $fmt = $self->append_format($fmt,'"'.$info->[0].'"');
465             }
466             else {
467 0           $self->clean_format($args->{'trust-input'},\$info);
468 0           $fmt = $self->append_format($fmt,'"'.$item.'"');
469 0           $fmt = $self->append_format($fmt,'"'.$info.'"');
470             }
471             }
472             } else {
473 0           croak("Programmer error. list argument missing or not an array.")
474             }
475              
476 0           my $command = $self->prepare_command( $args, $fmt );
477              
478 0           my ($rv,$selected) = $self->command_array($command);
479 0   0       $self->rv($rv||'null');
480 0           $self->ra('null');
481 0           $self->rs('null');
482 0 0 0       if ($rv && $rv >= 1) {
483 0           $self->_post($args);
484 0           return(0);
485             }
486             else {
487 0 0         if ($args->{'checklist'}) {
488 0           $self->ra(@$selected);
489 0           $self->rs(join("\n",@$selected));
490 0           $self->_post($args);
491 0           return(@{$selected});
  0            
492             }
493             else {
494 0           $self->ra($selected->[0]);
495 0           $self->rs($selected->[0]);
496 0           $self->_post($args);
497 0           return($selected->[0]);
498             }
499             }
500             }
501             sub menu {
502 0     0 1   my $self = shift();
503 0   0       return($self->list('caller',((caller(1))[3]||'main'),@_));
504             }
505             sub checklist {
506 0     0 1   my $self = shift();
507 0   0       return($self->list('caller',((caller(1))[3]||'main'),@_,'checklist',1));
508             }
509             sub radiolist {
510 0     0 1   my $self = shift();
511 0   0       return($self->list('caller',((caller(1))[3]||'main'),@_,'radiolist',1));
512             }
513              
514             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
515             #: file select
516             sub fselect {
517 0     0 1   my $self = shift();
518 0   0       my $caller = (caller(1))[3] || 'main';
519 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
520 0 0 0       if ($_[0] && $_[0] eq 'caller') {
521 0           shift(); $caller = shift();
  0            
522             }
523 0           my $args = $self->_pre($caller,@_);
524              
525 0   0       my $filename = $args->{'path'} || $args->{'filename'} || abs_path();
526 0           $args->{'path'} = $filename;
527 0 0         $args->{'path'} = (-d $args->{'path'}) ? $args->{'path'}."/" : $args->{'path'};
528 0           $args->{'path'} =~ s!/+!/!g;
529              
530 0           my $fmt = $self->prepare_format($args);
531 0           $fmt = $self->append_format_base($args,$fmt);
532 0           $fmt = $self->append_format($fmt,'--file-selection');
533 0           $fmt = $self->append_format($fmt,'--filename {{filename}}');
534 0           my $command = $self->prepare_command
535             ( $args, $fmt,
536             filename => $self->make_kvl($args,$filename)
537             );
538              
539 0           $self->_debug("fselect: ".$args->{'path'});
540 0           my ($rv,$file) = $self->command_string($command);
541 0   0       $self->rv($rv||'null');
542 0           $self->ra('null');
543 0           $self->rs('null');
544 0           my $this_rv;
545 0 0 0       if ($rv && $rv >= 1) {
546 0           $this_rv = 0;
547             }
548             else {
549 0           $self->ra($file);
550 0           $self->rs($file);
551 0           $this_rv = $file;
552             }
553 0           $self->_post($args);
554 0           return($this_rv);
555             }
556              
557             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
558             #: directory select
559             sub dselect {
560 0     0 1   my $self = shift();
561 0   0       my $caller = (caller(1))[3] || 'main';
562 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
563 0 0 0       if ($_[0] && $_[0] eq 'caller') {
564 0           shift(); $caller = shift();
  0            
565             }
566 0           my $args = $self->_pre($caller,@_);
567              
568 0   0       my $filename = $args->{'path'} || $args->{'filename'} || abs_path();
569 0           $args->{'path'} = $filename;
570 0 0         $args->{'path'} = (-d $args->{'path'}) ? $args->{'path'}."/" : $args->{'path'};
571 0           $args->{'path'} =~ s!/+!/!g;
572              
573 0           my $fmt = $self->prepare_format($args);
574 0           $fmt = $self->append_format_base($args,$fmt);
575 0           $fmt = $self->append_format($fmt,'--file-selection --directory');
576 0           $fmt = $self->append_format($fmt,'--filename {{filename}}');
577 0           my $command = $self->prepare_command
578             ( $args, $fmt,
579             filename => $self->make_kvl($args,$filename)
580             );
581              
582 0           $self->_debug("fselect: ".$args->{'path'});
583 0           my ($rv,$file) = $self->command_string($command);
584 0   0       $self->rv($rv||'null');
585 0           $self->ra('null');
586 0           $self->rs('null');
587 0           my $this_rv;
588 0 0 0       if ($rv && $rv >= 1) {
589 0           $this_rv = 0;
590             }
591             else {
592 0           $self->ra($file);
593 0           $self->rs($file);
594 0           $this_rv = $file;
595             }
596 0           $self->_post($args);
597 0           return($this_rv);
598             }
599              
600             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
601             #: calendar
602             sub calendar {
603 0     0 1   my $self = shift();
604 0   0       my $caller = (caller(1))[3] || 'main';
605 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
606 0 0 0       if ($_[0] && $_[0] eq 'caller') {
607 0           shift(); $caller = shift();
  0            
608             }
609 0           my $args = $self->_pre($caller,@_);
610              
611 0           my $fmt = $self->prepare_format($args);
612 0           $fmt = $self->append_format_base($args,$fmt);
613 0           $fmt = $self->append_format($fmt,'--calendar');
614 0           $fmt = $self->append_format_check($args,$fmt,'text','--text {{text}}');
615 0           $fmt = $self->append_format_check($args,$fmt,'date-format','--date-format {{date-format}}');
616 0           $fmt = $self->append_format_check($args,$fmt,'day','--day {{day}}');
617 0           $fmt = $self->append_format_check($args,$fmt,'month','--month {{month}}');
618 0           $fmt = $self->append_format_check($args,$fmt,'year','--year {{year}}');
619             my $command = $self->prepare_command
620             ( $args, $fmt,
621 0           text => $self->make_kvt($args,$args->{'text'}),
622             );
623              
624 0           my ($rv,$date) = $self->command_string($command);
625 0   0       $self->rv($rv||'null');
626 0           $self->ra('null');
627 0           $self->rs('null');
628 0           my $this_rv;
629 0 0 0       if ($rv && $rv >= 1) {
630 0           $this_rv = 0;
631             }
632             else {
633 0           chomp($date);
634             # the end programmer can alter the date format
635 0 0         $self->ra(split(/\//,$date)) if $date =~ /^\d+\/\d+\/\d+$/;
636 0           $self->rs($date);
637 0           $this_rv = $date;
638             }
639 0           $self->_post($args);
640 0           return($this_rv);
641             }
642              
643             #:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
644             #: progress
645              
646             sub gauge_start {
647 0     0 1   my $self = shift();
648 0   0       my $caller = (caller(1))[3] || 'main';
649 0 0 0       $caller = ($caller =~ /^UI\:\:Dialog\:\:Backend\:\:/) ? ((caller(2))[3]||'main') : $caller;
650 0 0 0       if ($_[0] && $_[0] eq 'caller') {
651 0           shift(); $caller = shift();
  0            
652             }
653 0           my $args = $self->_pre($caller,@_);
654              
655 0   0       $self->{'_GAUGE'} ||= {};
656 0           $self->{'_GAUGE'}->{'ARGS'} = $args;
657              
658 0 0         if (defined $self->{'_GAUGE'}->{'FH'}) {
659 0           $self->rv(129);
660 0           $self->_post($args);
661 0           return(0);
662             }
663              
664 0           my $fmt = $self->prepare_format($args);
665 0           $fmt = $self->append_format_base($args,$fmt);
666 0           $fmt = $self->append_format($fmt,'--progress');
667 0           $fmt = $self->append_format_check($args,$fmt,'pulsate','--pulsate');
668 0           $fmt = $self->append_format_check($args,$fmt,'text','--text {{text}}');
669 0           $fmt = $self->append_format($fmt,'--percentage {{percentage}}');
670             my $command = $self->prepare_command
671             ( $args, $fmt,
672             text => $self->make_kvt($args,$args->{'text'}),
673 0   0       percentage => $self->make_kvl($args,$args->{'percentage'}||'0'),
674             );
675              
676 0   0       $self->{'_GAUGE'}->{'PERCENT'} = ($args->{'percentage'} || '0');
677 0           $self->{'_GAUGE'}->{'FH'} = new FileHandle;
678 0           $self->{'_GAUGE'}->{'FH'}->open("| $command");
679 0           my $rv = ($? >> 8);
680 0           $self->{'_GAUGE'}->{'FH'}->autoflush(1);
681 0   0       $self->rv($rv||'null');
682 0           $self->ra('null');
683 0           $self->rs('null');
684 0           my $this_rv;
685 0 0 0       if ($rv && $rv >= 1) {
686 0           $this_rv = 0;
687             }
688             else {
689 0           $this_rv = 1;
690             }
691 0           return($this_rv);
692             }
693             sub gauge_inc {
694 0     0 1   my $self = $_[0];
695 0   0       my $incr = $_[1] || 1;
696              
697 0 0         return(0) unless defined $self->{'_GAUGE'}->{'FH'};
698              
699 0           my $fh = $self->{'_GAUGE'}->{'FH'};
700 0           $self->{'_GAUGE'}->{'PERCENT'} += $incr;
701 0           $SIG_CODE->{$$} = $self; local $SIG{'PIPE'} = \&_del_gauge;
  0            
702 0           print $fh $self->{'_GAUGE'}->{'PERCENT'}."\n";
703 0 0         return(((defined $self->{'_GAUGE'}->{'FH'}) ? 1 : 0));
704             }
705             sub gauge_dec {
706 0     0 1   my $self = $_[0];
707 0   0       my $decr = $_[1] || 1;
708              
709 0 0         return(0) unless defined $self->{'_GAUGE'}->{'FH'};
710              
711 0           my $fh = $self->{'_GAUGE'}->{'FH'};
712 0           $self->{'_GAUGE'}->{'PERCENT'} -= $decr;
713 0           $SIG_CODE->{$$} = $self; local $SIG{'PIPE'} = \&_del_gauge;
  0            
714 0           print $fh $self->{'_GAUGE'}->{'PERCENT'}."\n";
715 0 0         return(((defined $self->{'_GAUGE'}->{'FH'}) ? 1 : 0));
716             }
717             sub gauge_set {
718 0     0 1   my $self = $_[0];
719 0   0       my $perc = $_[1] || $self->{'_GAUGE'}->{'PERCENT'} || 1;
720              
721 0 0         return(0) unless $self->{'_GAUGE'}->{'FH'};
722              
723 0           my $fh = $self->{'_GAUGE'}->{'FH'};
724 0           $self->{'_GAUGE'}->{'PERCENT'} = $perc;
725 0           $SIG_CODE->{$$} = $self; local $SIG{'PIPE'} = \&_del_gauge;
  0            
726 0           print $fh $self->{'_GAUGE'}->{'PERCENT'}."\n";
727 0 0         return(((defined $self->{'_GAUGE'}->{'FH'}) ? 1 : 0));
728             }
729             #: Textual updates are not supported by Zenity...
730             sub gauge_text {
731 0     0 0   my $self = $_[0];
732 0   0       my $mesg = $_[1] || return(0);
733              
734 0           my $fh = $self->{'_GAUGE'};
735 0 0         return(0) unless $self->{'_GAUGE'};
736              
737             # $SIG_CODE->{$$} = $self; local $SIG{'PIPE'} = \&_del_gauge;
738             # print $fh "\nXXX\n\n".$mesg."\n\nXXX\n\n".$self->{'_GAUGE'}->{'PERCENT'}."\n";
739 0 0         return(((defined $self->{'_GAUGE'}) ? 1 : 0));
740             }
741             sub gauge_stop {
742 0     0 1   my $self = $_[0];
743 0   0       my $args = $self->{'_GUAGE'}->{'ARGS'} ||
744             $self->_merge_attrs( title => 'gauge_stop',
745             'caller' => ((caller(1))[3]||'main') );
746              
747 0 0         unless ($self->{'_GAUGE'}->{'FH'}) {
748 0           $self->rv(129);
749 0           $self->_post($args);
750 0           return(0);
751             }
752              
753 0           my $fh = $self->{'_GAUGE'}->{'FH'};
754 0           $SIG_CODE->{$$} = $self; local $SIG{'PIPE'} = \&_del_gauge;
  0            
755 0           $self->{'_GAUGE'}->{'FH'}->close();
756 0           delete($self->{'_GAUGE'}->{'ARGS'});
757 0           delete($self->{'_GAUGE'}->{'FH'});
758 0           delete($self->{'_GAUGE'}->{'PERCENT'});
759 0           delete($self->{'_GAUGE'});
760 0           $self->rv('null');
761 0           $self->rs('null');
762 0           $self->ra('null');
763 0           $self->_post($args);
764 0           return(1);
765             }
766              
767             1;
768