mrdialog 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1245 @@
1
+
2
+ # vim:ts=4:sw=4:
3
+ # = rdialog - A dialog gem for Ruby
4
+ #
5
+ # Homepage:: http://built-it.net/ruby/rdialog/
6
+ # Author:: Aleks Clark (http://built-it.net)
7
+ # Copyright:: (cc) 2004 Aleks Clark
8
+ # License:: BSD
9
+ #
10
+ # class RDialog::Dialog.new( array, str, array)
11
+ #
12
+
13
+ #=================================================
14
+ # I did the following:
15
+ # - renamed the class to MRDialog
16
+ # - removed tabs
17
+ # - added support for the follwoing:
18
+ # - form
19
+ # -
20
+ #
21
+ # muquit@muquit.com, Apr-05-2014
22
+ #=================================================
23
+
24
+ require 'logger'
25
+ require 'tempfile'
26
+ require 'date'
27
+ require 'time'
28
+ require 'shellwords'
29
+ class MRDialog
30
+ DIALOG_OK = 0
31
+ DIALOG_CANCEL = 1
32
+ DIALOG_HELP = 2
33
+ DIALOG_EXTRA = 3
34
+ DIALOG_ITEM_HELP = 4
35
+ DIALOG_ESC = 255
36
+ #MRDialog - Interface to ncurses dialog program
37
+
38
+ #
39
+ # All accessors are boolean unless otherwise noted.
40
+ #
41
+
42
+ #
43
+ # This gives you some control over the box dimensions when
44
+ # using auto sizing (specifying 0 for height and width).
45
+ # It represents width / height. The default is 9,
46
+ # which means 9 characters wide to every 1 line high.
47
+ #
48
+ attr_accessor :aspect
49
+
50
+ #
51
+ # Specifies a backtitle string to be displayed on the backdrop,
52
+ # at the top of the screen.
53
+ #
54
+ attr_accessor :backtitle
55
+
56
+ #
57
+ # Sound the audible alarm each time the screen is refreshed.
58
+ #
59
+ attr_accessor :beep
60
+
61
+ #
62
+ # Specify the position of the upper left corner of a dialog box
63
+ # on the screen, as an array containing two integers.
64
+ #
65
+ attr_accessor :begin
66
+
67
+ #
68
+ # Interpret embedded newlines in the dialog text as a newline
69
+ # on the screen. Otherwise, dialog will only wrap lines where
70
+ # needed to fit inside the text box. Even though you can control
71
+ # line breaks with this, dialog will still wrap any lines that are
72
+ # too long for the width of the box. Without cr-wrap, the layout
73
+ # of your text may be formatted to look nice in the source code of
74
+ # your script without affecting the way it will look in the dialog.
75
+ #
76
+ attr_accessor :crwrap
77
+
78
+ #
79
+ # Interpret the tags data for checklist, radiolist and menuboxes
80
+ # adding a column which is displayed in the bottom line of the
81
+ # screen, for the currently selected item.
82
+ #
83
+ attr_accessor :itemhelp
84
+
85
+ #
86
+ # Suppress the "Cancel" button in checklist, inputbox and menubox
87
+ # modes. A script can still test if the user pressed the ESC key to
88
+ # cancel to quit.
89
+ #
90
+ attr_accessor :nocancel
91
+
92
+ #
93
+ # Draw a shadow to the right and bottom of each dialog box.
94
+ #
95
+ attr_accessor :shadow
96
+
97
+ #
98
+ # Sleep (delay) for the given integer of seconds after processing
99
+ # a dialog box.
100
+ #
101
+ attr_accessor :sleep
102
+
103
+ #
104
+ # Convert each tab character to one or more spaces.
105
+ # Otherwise, tabs are rendered according to the curses library's
106
+ # interpretation.
107
+ #
108
+ attr_accessor :tabcorrect
109
+
110
+ #
111
+ # Specify the number(int) of spaces that a tab character occupies
112
+ # if the tabcorrect option is set true. The default is 8.
113
+ #
114
+ attr_accessor :tablen
115
+
116
+ #
117
+ # Title string to be displayed at the top of the dialog box.
118
+ #
119
+ attr_accessor :title
120
+
121
+ #
122
+ # Alternate path to dialog. If this is not set, environment path
123
+ # is used.
124
+ attr_accessor :path_to_dialog
125
+
126
+ # -- muquit@muquit.com mod starts---
127
+
128
+ # exit codes
129
+ attr_accessor :dialog_ok
130
+ attr_accessor :dialog_cancel
131
+ attr_accessor :dialog_help
132
+ attr_accessor :dialog_extra
133
+ attr_accessor :dialog_item_help
134
+ attr_accessor :dialog_esc
135
+
136
+ #
137
+ # ruby logger
138
+ attr_accessor :logger
139
+
140
+ # Override the label used for "OK" buttons
141
+ attr_accessor :ok_label
142
+
143
+ # clear screen
144
+ attr_accessor :clear
145
+
146
+ # make the password widget friendlier but less secure, by echoing
147
+ # asterisks for each character.
148
+ attr_accessor :insecure
149
+
150
+ # rather than draw graphics lines around boxes, draw ASCII + and -
151
+ attr_accessor :ascii_lines
152
+
153
+ attr_accessor :separator
154
+
155
+ # set it to true for passwordform.
156
+ attr_accessor :password_form
157
+
158
+ # For widgets holding a scrollable set of data, draw a scrollbar
159
+ # on its right-margin. This does not respond to the mouse.
160
+ attr_accessor :scrollbar
161
+ # -- muquit@muquit.com mod ends---
162
+
163
+ # Returns a new RDialog Object
164
+
165
+ def initialize
166
+ # muquit@muquit.com mod starts--
167
+ $stdout.sync = true
168
+ $stderr.sync = true
169
+ @dialog_ok = DIALOG_OK
170
+ @dialog_cancel = DIALOG_CANCEL
171
+ @dialog_help = DIALOG_HELP
172
+ @dialog_extra = DIALOG_EXTRA
173
+ @dialog_item_help = DIALOG_ITEM_HELP
174
+ @dialog_esc = DIALOG_ESC
175
+ @exit_code = 0
176
+ # muquit@muquit.com mod ends--
177
+ end
178
+
179
+ ##---- muquit@muquit.com mod starts---
180
+
181
+ ##---------------------------------------------------
182
+ # if @logger is set, log
183
+ ##---------------------------------------------------
184
+ def log_debug(msg)
185
+ if @logger
186
+ @logger.debug("#{msg}")
187
+ end
188
+ end
189
+
190
+ # return the exit code of the dialog
191
+ def exit_code
192
+ return @exit_code
193
+ end
194
+
195
+ ##---------------------------------------------------
196
+ # return the path of the executable which exists
197
+ # in the PATH env variable
198
+ # return nil otherwise
199
+ # arg is the name of the program without extensin
200
+ # muquit@muquit.com
201
+ ##---------------------------------------------------
202
+ def which(prog)
203
+ path_ext = ENV['PATHEXT']
204
+ exts = ['']
205
+ if path_ext # WINDOW$
206
+ exts = path_ext.split(';')
207
+ end
208
+ path = ENV['PATH']
209
+ path.split(File::PATH_SEPARATOR).each do |dir|
210
+ exts.each do |ext|
211
+ candidate = File.join(dir, "#{prog}#{ext}")
212
+ return candidate if File.executable?(candidate)
213
+ end
214
+ end
215
+ return nil
216
+ end
217
+
218
+
219
+ # A gauge box displays a meter along the bottom of the box. The
220
+ # meter indicates the percentage. New percentages are read from
221
+ # standard input, one integer per line. The meter is updated to
222
+ # reflect each new percentage. If the standard input reads the
223
+ # string "XXX", then the first line following is taken as an
224
+ # integer percentage, then subsequent lines up to another "XXX" are
225
+ # used for a new prompt. The gauge exits when EOF is reached on
226
+ # the standard input.
227
+ #
228
+ # The percent value denotes the initial percentage shown in the
229
+ # meter. If not speciied, it is zero.
230
+ #
231
+ # On exit, no text is written to dialog's output. The widget
232
+ # accepts no input, so the exit status is always OK.
233
+ #
234
+ # The caller will write the text markers to stdout
235
+ # as described above inside a block and will pass the block to the
236
+ # method. Look at samples/gauge for
237
+ # an example on how the method is called. Thanks to Mike Morgan
238
+ # for the idea to use a block.
239
+ #
240
+ # Author:: muquit@muquit.com Apr-02-2014
241
+ ##---------------------------------------------------
242
+ def gauge(text, height=0, width=0, percent=0)
243
+ cmd = ""
244
+ cmd << option_string()
245
+ cmd << " "
246
+ cmd << "--gauge"
247
+ cmd << " "
248
+ cmd << '"'
249
+ cmd << text
250
+ cmd << '"'
251
+ cmd << " "
252
+ cmd << height.to_s
253
+ cmd << " "
254
+ cmd << width.to_s
255
+ cmd << " "
256
+ cmd << percent.to_s
257
+
258
+ log_debug "Command:\n#{cmd}"
259
+ IO.popen(cmd, "w") {|fh| yield fh}
260
+ end
261
+
262
+
263
+ # Progressbox is used to display the piped output of a command.
264
+ # After the command completes, the user can press the ENTER key so
265
+ # that dialog will exit and the calling shell script can continue its operation.
266
+ # If three parameters are given, it displays the text under the title,
267
+ # delineated from the scrolling file's contents. If only two
268
+ # parameters are given, this text is omitted.
269
+ #
270
+ # The caller will write the progress string on stdout in a block
271
+ # and will pass the block to the method. Please look at samples/
272
+ # progress.rb for an example.
273
+ # Author: muquit@muquit.com Apr-02-2014
274
+ def progressbox(description='', height=0, width=0)
275
+ cmd = ""
276
+ cmd << option_string()
277
+ cmd << " "
278
+ cmd << "--progressbox"
279
+ cmd << " "
280
+ if description.length > 0
281
+ cmd << '"'
282
+ cmd << description
283
+ cmd << '"'
284
+ end
285
+ cmd << " "
286
+ cmd << height.to_s
287
+ cmd << " "
288
+ cmd << width.to_s
289
+
290
+ log_debug("Command\n#{cmd}")
291
+ IO.popen(cmd, "w") {|fh| yield fh}
292
+ end
293
+
294
+ # same as progressbox but displays OK button at the end
295
+ def programbox(description='', height=0, width=0)
296
+ cmd = ""
297
+ cmd << option_string()
298
+ cmd << " "
299
+ cmd << "--programbox"
300
+ cmd << " "
301
+ if description.length > 0
302
+ cmd << '"'
303
+ cmd << description
304
+ cmd << '"'
305
+ end
306
+ cmd << " "
307
+ cmd << height.to_s
308
+ cmd << " "
309
+ cmd << width.to_s
310
+
311
+ log_debug("Command\n#{cmd}")
312
+ IO.popen(cmd, "w") {|fh| yield fh}
313
+ end
314
+
315
+ #
316
+ # A prgbox is very similar to a programbox.
317
+ #
318
+ # This dialog box is used to display the output of a command that
319
+ # is specified as an argument to prgbox.
320
+ #
321
+ # After the command completes, the user can press the ENTER key so
322
+ # that dialog will exit and the calling shell script can continue
323
+ # its operation.
324
+ #
325
+ # If three parameters are given, it displays the text under the
326
+ # title, delineated from the scrolling file's contents. If only
327
+ # two parameters are given, this text is omitted.
328
+ #
329
+ def prgbox(command, height=0, width=0, text='')
330
+ cmd = ""
331
+ cmd << option_string()
332
+ cmd << " "
333
+ cmd << "--prgbox"
334
+ cmd << " "
335
+ if text.length > 0
336
+ cmd << '"'
337
+ cmd << text
338
+ cmd << '"'
339
+ end
340
+ cmd << " "
341
+ cmd << '"'
342
+ cmd << command
343
+ cmd << '"'
344
+ cmd << " "
345
+ cmd << height.to_s
346
+ cmd << " "
347
+ cmd << width.to_s
348
+ system(cmd)
349
+ @exit_code = $?.exitstatus
350
+ end
351
+
352
+ #
353
+ # Display data organized as a tree. Each group of data contains a
354
+ # tag, the text to display for the item, its status ("on" or
355
+ # "off") and the depth of the item in the tree.
356
+ #
357
+ # Only one item can be selected (like the radiolist). The tag is
358
+ # not displayed.
359
+ #
360
+ # On exit, the tag of the selected item is written to dialog's
361
+ # output.
362
+ def treeview(text="Text Goes Here", items=nil, height=0, width=0, listheight=0)
363
+ tmp = Tempfile.new('dialog')
364
+ itemlist = ''
365
+ items.each do |item|
366
+ itemlist << '"'
367
+ itemlist << item[0].to_s
368
+ itemlist << '"'
369
+ itemlist << " "
370
+ itemlist << '"'
371
+ itemlist << item[1].to_s
372
+ itemlist << '"'
373
+ itemlist << " "
374
+ itemlist << '"'
375
+ if item[2]
376
+ item[2] = "on"
377
+ else
378
+ item[2] = "off"
379
+ end
380
+ itemlist << item[2]
381
+ itemlist << '"'
382
+ itemlist << " "
383
+ itemlist << item[3].to_s
384
+ itemlist << " "
385
+ end
386
+ itemlist << "2>"
387
+ itemlist << tmp.path
388
+
389
+ cmd = ""
390
+ cmd << option_string()
391
+ cmd << " "
392
+ cmd << "--treeview"
393
+ cmd << " "
394
+ cmd << '"'
395
+ cmd << " "
396
+ cmd << text
397
+ cmd << '"'
398
+ cmd << " "
399
+ cmd << height.to_s
400
+ cmd << " "
401
+ cmd << width.to_s
402
+ cmd << " "
403
+ cmd << listheight.to_s
404
+ cmd << " "
405
+ cmd << itemlist
406
+
407
+ log_debug "Number of items: #{items.size}"
408
+ log_debug "Command:\n#{cmd}"
409
+
410
+ system(cmd)
411
+ @exit_code = $?.exitstatus
412
+ log_debug "Exit code: #{exit_code}"
413
+ tag = ''
414
+ if @exit_code == 0
415
+ tag = tmp.read
416
+ end
417
+ tmp.close!
418
+ return tag
419
+ end
420
+
421
+ #
422
+ # A buildlist dialog displays two lists, side-by-side. The list
423
+ # on the left shows unselected items. The list on the right shows
424
+ # selected items. As items are selected or unselected, they move
425
+ # between the lists. Use SPACE bar to select/unselect an item.
426
+ #
427
+ # Use a carriage return or the "OK" button to accept the current
428
+ # value in the selected-window and exit. The results are written
429
+ # using the order displayed in the selected-window.
430
+ #
431
+ # The caller is responsile to create the items properly. Please
432
+ # look at samples/buildlist.rb for an example.
433
+ #
434
+ # return an array of selected tags
435
+ # Author:: muquit@muquit.com
436
+ def buildlist(text="Text Goes Here", items = nil, height=0, width=0, listheight=0)
437
+ tmp = Tempfile.new('dialog')
438
+ selected_tags = []
439
+ itemlist = ''
440
+
441
+ items.each do |item|
442
+ itemlist << '"'
443
+ itemlist << item[0].to_s
444
+ itemlist << '"'
445
+ itemlist << " "
446
+ itemlist << '"'
447
+ itemlist << item[1].to_s
448
+ itemlist << '"'
449
+ itemlist << " "
450
+ itemlist << '"'
451
+ if item[2]
452
+ item[2] = "on"
453
+ else
454
+ item[2] = "off"
455
+ end
456
+ itemlist << item[2]
457
+ itemlist << '"'
458
+ itemlist << " "
459
+ end
460
+ itemlist << "2>"
461
+ itemlist << tmp.path
462
+
463
+ cmd = ""
464
+
465
+ cmd << option_string()
466
+ if !@separator
467
+ @separator = "|"
468
+ cmd << " "
469
+ cmd << "--separator"
470
+ cmd << " "
471
+ cmd << '"'
472
+ cmd << @separator
473
+ cmd << '"'
474
+ end
475
+ cmd << " "
476
+ cmd << "--buildlist"
477
+ cmd << " "
478
+ cmd << '"'
479
+ cmd << " "
480
+ cmd << text
481
+ cmd << '"'
482
+ cmd << " "
483
+ cmd << height.to_s
484
+ cmd << " "
485
+ cmd << width.to_s
486
+ cmd << " "
487
+ cmd << listheight.to_s
488
+ cmd << " "
489
+ cmd << itemlist
490
+
491
+ log_debug "Number of items: #{items.size}"
492
+ log_debug "Command:\n#{cmd}"
493
+
494
+ system(cmd)
495
+ @exit_code = $?.exitstatus
496
+ log_debug "Exit code: #{exit_code}"
497
+ if @exit_code == 0
498
+ lines = tmp.read
499
+ log_debug "lines: #{lines} #{lines.class}"
500
+ sep = Shellwords.escape(@separator)
501
+ a = lines.split(/#{sep}/)
502
+ a.each do |tag|
503
+ log_debug "tag: '#{tag}'"
504
+ selected_tags << tag if tag.to_s.length > 0
505
+ end
506
+ end
507
+ tmp.close!
508
+ return selected_tags
509
+ end
510
+
511
+ # A pause box displays a meter along the bottom of the box. The
512
+ # meter indicates how many seconds remain until the end of the
513
+ # pause. The pause exits when timeout is reached or the user
514
+ # presses the OK button (status OK) or the user presses the CANCEL
515
+ # button or Esc key.
516
+ def pause(text="Text Goes Here", height=0, width=0, secs=10)
517
+ cmd = ""
518
+ cmd << option_string()
519
+ cmd << " "
520
+ cmd << "--pause"
521
+ cmd << " "
522
+ cmd << '"'
523
+ cmd << text
524
+ cmd << '"'
525
+ cmd << " "
526
+ cmd << height.to_s
527
+ cmd << " "
528
+ cmd << width.to_s
529
+ cmd << " "
530
+ cmd << secs.to_s
531
+ log_debug "Command:\n#{cmd}"
532
+
533
+ system(cmd)
534
+ result = ''
535
+ @exit_code = $?.exitstatus
536
+ log_debug "Exit code: #{exit_code}"
537
+ end
538
+
539
+ # The edit-box dialog displays a copy of the file. You may edit
540
+ # it using the backspace, delete and cursor keys to correct typing
541
+ # errors. It also recognizes pageup/pagedown. Unlike the --in-
542
+ # putbox, you must tab to the "OK" or "Cancel" buttons to close
543
+ # the dialog. Pressing the "Enter" key within the box will split
544
+ # the corresponding line.
545
+ #
546
+ # On exit, the contents of the edit window are written to dialog's
547
+ # output.
548
+ def editbox(filepath, height=0, width=0)
549
+ tmp = Tempfile.new('dialog')
550
+
551
+ cmd = ""
552
+ cmd << option_string()
553
+ cmd << " "
554
+ cmd << "--editbox"
555
+ cmd << " "
556
+ cmd << '"'
557
+ cmd << filepath
558
+ cmd << '"'
559
+ cmd << " "
560
+ cmd << height.to_s
561
+ cmd << " "
562
+ cmd << width.to_s
563
+ cmd << " "
564
+ cmd << "2>"
565
+ cmd << tmp.path
566
+
567
+ log_debug "Command:\n#{cmd}"
568
+
569
+ system(cmd)
570
+ result = ''
571
+ @exit_code = $?.exitstatus
572
+ log_debug "Exit code: #{exit_code}"
573
+ if @exit_code == 0
574
+ result = tmp.read
575
+ end
576
+ tmp.close!
577
+ return result
578
+ end
579
+
580
+ #
581
+ # form/mixedform dialog
582
+ # A form dialog displays a form consisting of labels and fields,
583
+ # which are positioned on a scrollable window by coordinates given in
584
+ # the script. The field length flen and input-length ilen tell how
585
+ # long the field can be. The former defines the length shown for a
586
+ # selected field, while the latter defines the permissible length of
587
+ # the data entered in the field.
588
+ # The caller is responsile to create the items properly. Please
589
+ # look at samples/form.rb for an example
590
+ #
591
+ # return a hash. keys are the labels
592
+ # Author:: muquit@muquit.com
593
+ def form(text, items, height=0, width=0, formheight=0)
594
+ res_hash = {}
595
+ tmp = Tempfile.new('dialog')
596
+ itemlist = ''
597
+ mixed_form = false
598
+ item_size = items[0].size
599
+ log_debug "Item size:#{item_size}"
600
+ # if there are 9 elements, it's a mixedform
601
+ if item_size == 9
602
+ mixed_form = true
603
+ end
604
+ items.each do |item|
605
+ itemlist << '"'
606
+ itemlist << item[0].to_s
607
+ itemlist << '"'
608
+ itemlist << " "
609
+ itemlist << item[1].to_s
610
+ itemlist << " "
611
+ itemlist << item[2].to_s
612
+ itemlist << " "
613
+ itemlist << '"'
614
+ itemlist << item[3].to_s
615
+ itemlist << '"'
616
+ itemlist << " "
617
+ itemlist << item[4].to_s
618
+ itemlist << " "
619
+ itemlist << item[5].to_s
620
+ itemlist << " "
621
+ itemlist << item[6].to_s
622
+ itemlist << " "
623
+ itemlist << item[7].to_s
624
+ itemlist << " "
625
+ if mixed_form
626
+ itemlist << item[8].to_s
627
+ itemlist << " "
628
+ end
629
+ end
630
+ itemlist << " "
631
+ itemlist << "2>"
632
+ itemlist << tmp.path
633
+
634
+ cmd = ""
635
+ cmd << option_string()
636
+ cmd << " "
637
+ if mixed_form
638
+ cmd << "--mixedform"
639
+ else
640
+ if @password_form
641
+ cmd << "--passwordform"
642
+ else
643
+ cmd << "--form"
644
+ end
645
+ end
646
+ cmd << " "
647
+ cmd << '"'
648
+ cmd << text
649
+ cmd << '"'
650
+ cmd << " "
651
+ cmd << height.to_s
652
+ cmd << " "
653
+ cmd << width.to_s
654
+ cmd << " "
655
+ cmd << formheight.to_s
656
+ cmd << " "
657
+ cmd << itemlist
658
+
659
+ log_debug("Number of items: #{items.size}")
660
+ log_debug("Command:\n#{cmd}")
661
+ system(cmd)
662
+ @exit_code = $?.exitstatus
663
+ log_debug "Exit code: #{exit_code}"
664
+
665
+ if @exit_code == 0
666
+ lines = tmp.readlines
667
+ lines.each_with_index do |val, idx|
668
+ key = items[idx][0]
669
+ res_hash[key] = val.chomp
670
+ end
671
+ end
672
+
673
+ tmp.close!
674
+ return res_hash
675
+ end
676
+
677
+ #
678
+ # A mixedform dialog displays a form consisting of labels and fields,
679
+ # much like the --form dialog. It differs by adding a field-type
680
+ # parameter to each field's description. Each bit in the type denotes
681
+ # an attribute of the field:
682
+ # * 1 hidden, e.g., a password field.
683
+ # * 2 readonly, e.g., a label.#
684
+ # Author:: muquit@muquit.com
685
+ def mixedform(text, items, height=0, width=0, formheight=0)
686
+ item_size = items[0].size
687
+ log_debug "Item size:#{item_size}"
688
+ if item_size == 9
689
+ return form(text, items, height, width, formheight)
690
+ end
691
+ return nil
692
+ end
693
+
694
+ #
695
+ # This is identical to --form except that all text fields are
696
+ # treated as password widgets rather than inputbox widgets.
697
+ def passwordform(text, items, height=0, width=0, formheight=0)
698
+ @password_form = true
699
+ return form(text, items, height, width, formheight)
700
+ end
701
+
702
+ ##---- muquit@muquit.com mod ends---
703
+
704
+
705
+ # A calendar box displays month, day and year in separately
706
+ # adjustable windows. If the values for day, month or year are
707
+ # missing or negative, the current date's corresponding values
708
+ # are used. You can increment or decrement any of those using
709
+ # the left-, up-, right- and down-arrows. Use vi-style h, j, k
710
+ # and l for moving around the array of days in a month. Use tab
711
+ # or backtab to move between windows. If the year is given as
712
+ # zero, the current date is used as an initial value.
713
+ #
714
+ # Returns a Date object with the selected date
715
+
716
+ def calendar(text="Select a Date", height=0, width=0, day=Date.today.mday(), month=Date.today.mon(), year=Date.today.year())
717
+
718
+ tmp = Tempfile.new('tmp')
719
+
720
+ command = option_string() + "--calendar \"" + text.to_s +
721
+ "\" " + height.to_i.to_s + " " + width.to_i.to_s + " " +
722
+ day.to_i.to_s + " " + month.to_i.to_s + " " + year.to_i.to_s +
723
+ " 2> " + tmp.path
724
+ success = system(command)
725
+ if success
726
+ date = Date::civil(*tmp.readline.split('/').collect {|i| i.to_i}.reverse)
727
+ tmp.close!
728
+ return date
729
+ else
730
+ tmp.close!
731
+ return success
732
+ end
733
+
734
+ end
735
+
736
+ # A checklist box is similar to a menu box; there are multiple
737
+ # entries presented in the form of a menu. Instead of choosing
738
+ # one entry among the entries, each entry can be turned on or off
739
+ # by the user. The initial on/off state of each entry is speci-
740
+ # fied by status.
741
+ # return an array of selected items
742
+ def checklist(text, items, height=0, width=0, listheight=0)
743
+
744
+ tmp = Tempfile.new('tmp')
745
+
746
+ itemlist = String.new
747
+
748
+ for item in items
749
+ if item[2]
750
+ item[2] = "on"
751
+ else
752
+ item[2] = "off"
753
+ end
754
+ itemlist += "\"" + item[0].to_s + "\" \"" + item[1].to_s +
755
+ "\" " + item[2] + " "
756
+
757
+ if @itemhelp
758
+ itemlist += "\"" + item[3].to_s + "\" "
759
+ end
760
+ end
761
+
762
+ sep = "|"
763
+ command = option_string() + "--checklist \"" + text.to_s +
764
+ "\" " + height.to_i.to_s + " " + width.to_i.to_s +
765
+ " " + listheight.to_i.to_s + " " + itemlist + "2> " +
766
+ tmp.path
767
+ log_debug "Command:\n#{command}"
768
+ success = system(command)
769
+ selected_array = []
770
+ if success
771
+ selected_string = tmp.readline
772
+ tmp.close!
773
+ log_debug "Separator: #{@separator}"
774
+
775
+ sep = Shellwords.escape(@separator)
776
+ a = selected_string.split(/#{sep}/)
777
+ a.each do |item|
778
+ log_debug ">> #{item}"
779
+ selected_array << item if item && item.to_s.length > 0
780
+ end
781
+ return selected_array
782
+ else
783
+ tmp.close!
784
+ return success
785
+ end
786
+
787
+ end
788
+
789
+ # The file-selection dialog displays a text-entry window in which
790
+ # you can type a filename (or directory), and above that two win-
791
+ # dows with directory names and filenames.
792
+
793
+ # Here filepath can be a filepath in which case the file and
794
+ # directory windows will display the contents of the path and the
795
+ # text-entry window will contain the preselected filename.
796
+ #
797
+ # Use tab or arrow keys to move between the windows. Within the
798
+ # directory or filename windows, use the up/down arrow keys to
799
+ # scroll the current selection. Use the space-bar to copy the
800
+ # current selection into the text-entry window.
801
+ #
802
+ # Typing any printable characters switches focus to the text-
803
+ # entry window, entering that character as well as scrolling the
804
+ # directory and filename windows to the closest match.
805
+ #
806
+ # Use a carriage return or the "OK" button to accept the current
807
+ # value in the text-entry window and exit.
808
+
809
+ def fselect(path, height=0, width=0)
810
+ tmp = Tempfile.new('tmp')
811
+
812
+ command = option_string() + "--fselect \"" + path.to_s +
813
+ "\" " + height.to_i.to_s + " " + width.to_i.to_s + " "
814
+
815
+ command += "2> " + tmp.path
816
+
817
+ success = system(command)
818
+
819
+ if success
820
+ begin
821
+ selected_string = tmp.readline
822
+ rescue EOFError
823
+ selected_string = ""
824
+ end
825
+ tmp.close!
826
+ return selected_string
827
+ else
828
+ tmp.close!
829
+ return success
830
+ end
831
+ end
832
+
833
+
834
+ #
835
+ # An info box is basically a message box. However, in this case,
836
+ # dialog will exit immediately after displaying the message to
837
+ # the user. The screen is not cleared when dialog exits, so that
838
+ # the message will remain on the screen until the calling shell
839
+ # script clears it later. This is useful when you want to inform
840
+ # the user that some operations are carrying on that may require
841
+ # some time to finish.
842
+ #
843
+ # Returns false if esc was pushed
844
+ def infobox(text, height=0, width=0)
845
+ command = option_string() + "--infobox \"" + text.to_s +
846
+ "\" " + height.to_i.to_s + " " + width.to_i.to_s + " "
847
+ success = system(command)
848
+ return success
849
+ end
850
+
851
+ # A radiolist box is similar to a menu box. The only difference
852
+ # is that you can indicate which entry is currently selected, by
853
+ # setting its status to true.
854
+
855
+ def radiolist(text, items, height=0, width=0, listheight=0)
856
+
857
+ tmp = Tempfile.new('tmp')
858
+
859
+ itemlist = String.new
860
+
861
+ for item in items
862
+ if item[2]
863
+ item[2] = "on"
864
+ else
865
+ item[2] = "off"
866
+ end
867
+ itemlist += "\"" + item[0].to_s + "\" \"" + item[1].to_s +
868
+ "\" " + item[2] + " "
869
+
870
+ if @itemhelp
871
+ itemlist += "\"" + item[3].to_s + "\" "
872
+ end
873
+ end
874
+
875
+ command = option_string() + "--radiolist \"" + text.to_s +
876
+ "\" " + height.to_i.to_s + " " + width.to_i.to_s +
877
+ " " + listheight.to_i.to_s + " " + itemlist + "2> " +
878
+ tmp.path
879
+ log_debug("Command:\n#{command}")
880
+ success = system(command)
881
+
882
+ if success
883
+ selected_string = tmp.readline
884
+ tmp.close!
885
+ return selected_string
886
+ else
887
+ tmp.close!
888
+ return success
889
+ end
890
+
891
+ end
892
+
893
+ # As its name suggests, a menu box is a dialog box that can be
894
+ # used to present a list of choices in the form of a menu for the
895
+ # user to choose. Choices are displayed in the order given.
896
+ # Each menu entry consists of a tag string and an item string.
897
+ # The tag gives the entry a name to distinguish it from the other
898
+ # entries in the menu. The item is a short description of the
899
+ # option that the entry represents. The user can move between
900
+ # the menu entries by pressing the cursor keys, the first letter
901
+ # of the tag as a hot-key, or the number keys 1-9. There are
902
+ # menu-height entries displayed in the menu at one time, but the
903
+ # menu will be scrolled if there are more entries than that.
904
+ #
905
+ # Returns a string containing the tag of the chosen menu entry.
906
+
907
+ def menu(text="Text Goes Here", items=nil, height=0, width=0, listheight=0)
908
+ tmp = Tempfile.new('tmp')
909
+
910
+ itemlist = String.new
911
+
912
+ for item in items
913
+ itemlist += "\"" + item[0].to_s + "\" \"" + item[1].to_s + "\" "
914
+
915
+ if @itemhelp
916
+ itemlist += "\"" + item[2].to_s + "\" "
917
+ end
918
+ end
919
+
920
+ command = option_string() + "--menu \"" + text.to_s +
921
+ "\" " + height.to_i.to_s + " " + width.to_i.to_s +
922
+ " " + listheight.to_i.to_s + " " + itemlist + "2> " +
923
+ tmp.path
924
+
925
+ log_debug("Command:\n#{command}")
926
+ success = system(command)
927
+
928
+ if success
929
+ selected_string = tmp.readline
930
+ tmp.close!
931
+ return selected_string
932
+ else
933
+ tmp.close!
934
+ return success
935
+ end
936
+
937
+ end
938
+
939
+ # A message box is very similar to a yes/no box. The only dif-
940
+ # ference between a message box and a yes/no box is that a mes-
941
+ # sage box has only a single OK button. You can use this dialog
942
+ # box to display any message you like. After reading the mes-
943
+ # sage, the user can press the ENTER key so that dialog will exit
944
+ # and the calling shell script can continue its operation.
945
+
946
+ def msgbox(text="Text Goes Here", height=0, width=0)
947
+ command = option_string() + "--msgbox \"" + text.to_s +
948
+ "\" " + height.to_i.to_s + " " + width.to_i.to_s + " "
949
+
950
+ log_debug "Command\n#{command}"
951
+ success = system(command)
952
+ return success
953
+ end
954
+
955
+ # A password box is similar to an input box, except that the text
956
+ # the user enters is not displayed. This is useful when prompt-
957
+ # ing for passwords or other sensitive information. Be aware
958
+ # that if anything is passed in "init", it will be visible in the
959
+ # system's process table to casual snoopers. Also, it is very
960
+ # confusing to the user to provide them with a default password
961
+ # they cannot see. For these reasons, using "init" is highly
962
+ # discouraged.
963
+
964
+ def passwordbox(text="Please enter some text", height=0, width=0, init="")
965
+ tmp = Tempfile.new('tmp')
966
+ command = option_string() + "--passwordbox \"" + text.to_s +
967
+ "\" " + height.to_i.to_s + " " + width.to_i.to_s + " "
968
+
969
+ unless init.empty?
970
+ command += init.to_s + " "
971
+ end
972
+
973
+ command += "2> " + tmp.path
974
+ log_debug(command)
975
+ success = system(command)
976
+
977
+ if success
978
+ begin
979
+ selected_string = tmp.readline
980
+ rescue EOFError
981
+ selected_string = ""
982
+ end
983
+ tmp.close!
984
+ return selected_string
985
+ else
986
+ tmp.close!
987
+ return success
988
+ end
989
+ end
990
+
991
+ # The textbox method handles three similar dialog functions, textbox,
992
+ # tailbox, and tailboxbg. They are activated by setting type to
993
+ # "text", "tail", and "bg" respectively
994
+ #
995
+ # Textbox mode:
996
+ # A text box lets you display the contents of a text file in a
997
+ # dialog box. It is like a simple text file viewer. The user
998
+ # can move through the file by using the cursor, PGUP/PGDN and
999
+ # HOME/END keys available on most keyboards. If the lines are
1000
+ # too long to be displayed in the box, the LEFT/RIGHT keys can be
1001
+ # used to scroll the text region horizontally. You may also use
1002
+ # vi-style keys h, j, k, l in place of the cursor keys, and B or
1003
+ # N in place of the pageup/pagedown keys. Scroll up/down using
1004
+ # vi-style 'k' and 'j', or arrow-keys. Scroll left/right using
1005
+ # vi-style 'h' and 'l', or arrow-keys. A '0' resets the
1006
+ # left/right scrolling. For more convenience, vi-style forward
1007
+ # and backward searching functions are also provided.
1008
+ #
1009
+ # Tailbox mode:
1010
+ # Display text from a file in a dialog box, as in a "tail -f"
1011
+ # command. Scroll left/right using vi-style 'h' and 'l', or
1012
+ # arrow-keys. A '0' resets the scrolling.
1013
+ #
1014
+ # Tailboxbg mode:
1015
+ # Display text from a file in a dialog box as a background task,
1016
+ # as in a "tail -f &" command. Scroll left/right using vi-style
1017
+ # 'h' and 'l', or arrow-keys. A '0' resets the scrolling.
1018
+
1019
+ def textbox(file, type="text", height=0, width=0)
1020
+ case type
1021
+ when "text"
1022
+ opt = "--textbox"
1023
+ when "tail"
1024
+ opt = "--tailbox"
1025
+ when "bg"
1026
+ opt = "--textboxbg"
1027
+ end
1028
+
1029
+ command = option_string() + opt +" \"" + file.to_s +
1030
+ "\" " + height.to_i.to_s + " " + width.to_i.to_s + " "
1031
+
1032
+ success = system(command)
1033
+
1034
+ return success
1035
+ end
1036
+
1037
+ # A dialog is displayed which allows you to select hour, minute
1038
+ # and second. If the values for hour, minute or second are miss-
1039
+ # ing or negative, the current date's corresponding values are
1040
+ # used. You can increment or decrement any of those using the
1041
+ # left-, up-, right- and down-arrows. Use tab or backtab to move
1042
+ # between windows.
1043
+ #
1044
+ # On exit, a Time object is returned.
1045
+
1046
+ ##- def timebox(file, type="text", height=0, width=0, time=Time.now)
1047
+ def timebox(text, height=0, width=0, time=Time.now)
1048
+ tmp = Tempfile.new('tmp')
1049
+
1050
+ command = option_string() + "--timebox \"" + text.to_s +
1051
+ "\" " + height.to_i.to_s + " " + width.to_i.to_s + " " +
1052
+ time.hour.to_s + " " + time.min.to_s + " " +
1053
+ time.sec.to_s + " 2> " + tmp.path
1054
+ log_debug("Command:\n#{command}")
1055
+ success = system(command)
1056
+ if success
1057
+ time = Time.parse(tmp.readline)
1058
+ tmp.close!
1059
+ return time
1060
+ else
1061
+ tmp.close!
1062
+ return success
1063
+ end
1064
+
1065
+ end
1066
+
1067
+ # An input box is useful when you want to ask questions that
1068
+ # require the user to input a string as the answer. If init is
1069
+ # supplied it is used to initialize the input string. When
1070
+ # entering the string, the backspace, delete and cursor keys can
1071
+ # be used to correct typing errors. If the input string is
1072
+ # longer than can fit in the dialog box, the input field will be
1073
+ # scrolled.
1074
+ #
1075
+ # On exit, the input string will be returned.
1076
+ def inputbox(text="Please enter some text", height=0, width=0, init="")
1077
+ tmp = Tempfile.new('tmp')
1078
+
1079
+ command = option_string() + "--inputbox \"" + text.to_s +
1080
+ "\" " + height.to_i.to_s + " " + width.to_i.to_s + " "
1081
+
1082
+ unless init.empty?
1083
+ command += init.to_s + " "
1084
+ end
1085
+
1086
+ command += "2> " + tmp.path
1087
+
1088
+ log_debug(command)
1089
+ success = system(command)
1090
+
1091
+ if success
1092
+ begin
1093
+ selected_string = tmp.readline
1094
+ rescue EOFError
1095
+ selected_string = ""
1096
+ end
1097
+ tmp.close!
1098
+ return selected_string
1099
+ else
1100
+ tmp.close!
1101
+ return success
1102
+ end
1103
+ end
1104
+
1105
+ # A yes/no dialog box of size height rows by width columns will
1106
+ # be displayed. The string specified by text is displayed inside
1107
+ # the dialog box. If this string is too long to fit in one line,
1108
+ # it will be automatically divided into multiple lines at appro-
1109
+ # priate places. The text string can also contain the sub-string
1110
+ # "\n" or newline characters '\n' to control line breaking
1111
+ # explicitly. This dialog box is useful for asking questions
1112
+ # that require the user to answer either yes or no. The dialog
1113
+ # box has a Yes button and a No button, in which the user can
1114
+ # switch between by pressing the TAB key.
1115
+
1116
+ # changing --inputbox to --yesno
1117
+ # muquit@muquit.com Apr-01-2014
1118
+ def yesno(text="Please enter some text", height=0, width=0)
1119
+ # command = option_string() + "--inputbox \"" + text.to_s +
1120
+ # "\" " + height.to_i.to_s + " " + width.to_i.to_s
1121
+
1122
+ command = ""
1123
+ command << option_string();
1124
+ command << " "
1125
+ command << '"'
1126
+ command << "--yesno"
1127
+ command << '"'
1128
+ command << " "
1129
+ command << '"'
1130
+ command << text
1131
+ command << '"'
1132
+ command << " "
1133
+ command << height.to_s
1134
+ command << " "
1135
+ command << width.to_s
1136
+
1137
+
1138
+ log_debug("Command:\n#{command}")
1139
+ success = system(command)
1140
+ return success
1141
+ end
1142
+
1143
+ private
1144
+
1145
+ def option_string
1146
+ # make sure 'dialog' is installed
1147
+ # muquit@muquit.com
1148
+ exe_loc = ''
1149
+ unless @path_to_dialog
1150
+ exe_loc = which("dialog")
1151
+ ostring = exe_loc
1152
+ else
1153
+ exe_loc = @path_to_dialog
1154
+ if !File.exists?(exe_loc)
1155
+ raise "Specified path of dialog '#{exe_loc}' does not exist"
1156
+ end
1157
+ if !File.executable?(exe_loc)
1158
+ raise "The program #{exe_loc} is not executable"
1159
+ end
1160
+ end
1161
+ raise "'dialog' executable not found in path" unless exe_loc
1162
+ ostring = exe_loc + " "
1163
+
1164
+ if @aspect
1165
+ ostring += "--aspect " + aspect + " "
1166
+ end
1167
+
1168
+ if @beep
1169
+ ostring += "--beep "
1170
+ end
1171
+
1172
+ if @boxbegin
1173
+ ostring += "--begin " + @boxbegin[0] + @boxbegin[1] + " "
1174
+ end
1175
+
1176
+ if @backtitle
1177
+ ostring += "--backtitle \"" + @backtitle + "\" "
1178
+ end
1179
+
1180
+ if @itemhelp
1181
+ ostring += "--item-help "
1182
+ end
1183
+
1184
+ unless @shadow == nil
1185
+ if @shadow == true
1186
+ ostring += "--shadow "
1187
+ else
1188
+ ostring += "--no-shadow "
1189
+ end
1190
+ end
1191
+
1192
+ if @sleep
1193
+ ostring += "--sleep " + @sleep.to_s + " "
1194
+ end
1195
+
1196
+ if @tabcorrect
1197
+ ostring += "--tab-correct "
1198
+ end
1199
+
1200
+ if @tablen
1201
+ ostring += "--tab-len " + @tablen.to_s + " "
1202
+ end
1203
+
1204
+ if @title
1205
+ # ostring += "--title " + "\"" + @title.to_s "\"" + " "
1206
+ # muquit@muquit.com Apr-01-2014
1207
+ ostring += "--title \"" + @title.to_s + "\" "
1208
+ end
1209
+
1210
+ # muquit@muquit.com mod starts--
1211
+ if @clear
1212
+ ostring += "--clear "
1213
+ end
1214
+
1215
+ if @insecure
1216
+ ostring += "--insecure "
1217
+ end
1218
+
1219
+ if @ascii_lines
1220
+ ostring += "--ascii-lines "
1221
+ end
1222
+
1223
+ if @ok_label
1224
+ ostring += "--ok-label #{@ok_label} "
1225
+ end
1226
+
1227
+ if @separator
1228
+ ostring += "--separator \"#{@separator}\" "
1229
+ end
1230
+ if @scrollbar
1231
+ ostring += "--scrollbar "
1232
+ end
1233
+ # muquit@muquit.com mod ends--
1234
+
1235
+ if @nocancel
1236
+ ostring += "--nocancel "
1237
+ end
1238
+
1239
+ return ostring
1240
+ end
1241
+ end
1242
+
1243
+
1244
+
1245
+ #Dir[File.join(File.dirname(__FILE__), 'rdialog/**/*.rb')].sort.each { |lib| require lib }