Module: Dialog::KDialog

Defined in:
lib/dialog/kdialog.rb

Defined Under Namespace

Classes: ProgressBar

Instance Method Summary collapse

Instance Method Details

#checkboxes(choices, label: "", default: nil) ⇒ Array<(String, Boolean)>

Present a set of checkboxes to the user

Using this method may be easier than using #selection, as you don’t need to indicate you want checkboxes.

Examples:

Using a Struct for checkboxes

Foodselection = Struct.new(:salad, :soup, :sandwich, :cookie, :drink)
choices = Foodselection.new(false, false, true, false, true)  # sandwich and drink preselected
checkboxes(choices, label: "What would you like for lunch?")

Parameters:

  • choices (#members)

    An object with an attribute for each choice, and a #members method which returns a list of those attributes to be used.

  • label (String) (defaults to: "")

    The text to display above input fields

  • default (Array<String> String) (defaults to: nil)

    The name of the attribute to be pre-selected for the user, or a list of such names, in the case of checkboxes. If not provided, the attribute’s value is tested, and if true, is selected.

Returns:

  • (Array<(String, Boolean)>)

    the textual output of running kdialog, and whether it exited successfully



178
179
180
# File 'lib/dialog/kdialog.rb', line 178

def checkboxes(choices, label: "", default: nil)
  selection(choices, label: label, type: :check, default: default)
end

#colorArray<Integer> nil

Color Picker

Returns:

  • (Array<Integer> nil)

    An array of [red, green, blue] 8-bit color components, or nil if 'cancel' pressed.



307
308
309
310
311
312
313
314
315
# File 'lib/dialog/kdialog.rb', line 307

def color()
  c = nil
  run(["--getcolor"]) {|out|
    c = [out[1,2].to_i(16),
     out[3,2].to_i(16),
     out[5,2].to_i(16)]
  }
  c
end

#combobox(choices, label: "") ⇒ Object

A dropdown box

This is similar to a radio button selection; only one selection can be made.

Parameters:

  • choices (#members)

    An object with an attribute for each choice, and a #members method which returns a list of those attributes to be used.

  • label (String) (defaults to: "")

    The text to display above input fields



153
154
155
156
157
158
159
160
# File 'lib/dialog/kdialog.rb', line 153

def combobox(choices, label: "")
  cmd = ["--combobox", label] + choices.members.map {|k| k.to_s}
  run(cmd) {|sel|
    selected = (sel + '=').to_sym
    (choices.members - [selected]).each {|c| choices.send((c.to_s + '=').to_sym, false)}
    choices.send(selected, true)
  }
end

#dialogbox(text, yesno: true, cancel: false, continue_btn: false, warning: false) { ... } ⇒ Object

Standard dialog boxes

The valid combinations of boolean parameters specifying the type of buttons available are as follows:

YesNo

Cancel

Warning

Continue

true

true

true

false

true

true

false

false

true

false

false

false

true

false

true

false

false

true

true

true

Parameters:

  • text (String)

    The text presented to the user above buttons.

  • yesno (Boolean) (defaults to: true)

    If true, show "Yes" and "No" buttons.

  • cancel (Boolean) (defaults to: false)

    If true, show a "Cancel" button.

  • continue_btn (Boolean) (defaults to: false)

    If true, show a "Continue" button.

  • warning (Boolean) (defaults to: false)

    If true, the icon shown is a warning icon, not a standard question icon

Yields:

  • [] If the user makes a positive selection (yes or continue), the given block is called. If not, the block is ignored.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/dialog/kdialog.rb', line 51

def dialogbox(text, yesno: true, cancel: false, continue_btn: false, warning: false)
  valid_dialogs = {"warningyesnocancel" => true, "yesnocancel" => true,
                   "yesno" => true, "warningyesno" => true,
                   "warningcontinuecancel" => true}
  cmd = ""
  cmd += "warning" if warning == true
  cmd += "yesno" if yesno == true
  cmd += "continue" if continue_btn == true
  cmd += "cancel" if cancel == true
  unless valid_dialogs.has_key?(cmd)
    raise "Can't make that kind of dialog box"
  end
  cmd = "--#{cmd}"
  out, status = *run([cmd, text])
  if block_given? and status == true
    yield()
  end
end

#filepicker(action: :save, type: :file, dir: , multiple: false, filter: nil) {|path| ... } ⇒ Array<String> String

TODO:

Figure out what kinds of strings are expected of the filter parameter, write code to validate

Present a file-picker box, for getting filenames or URLs from the user, for saving or opening.

Parameters:

  • action (Symbol) (defaults to: :save)

    One of :save or :open

  • type (Symbol) (defaults to: :file)

    One of :url, :file, or :directory, indicating what kind of input is expected from the user

  • dir (String) (defaults to: )

    Directory to start the UI in, defaults to ENV['HOME']

  • multiple (Boolean) (defaults to: false)

    If true, allow the user to select multiple files. Only works when action is :open.

  • filter (String) (defaults to: nil)

    A description of what types of files should be displayed in directory listings

Yield Parameters:

  • path (Array<String> String)

    The path (or paths) selected by the user

Returns:

  • (Array<String> String)

    The path (or paths) selected by the user



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
# File 'lib/dialog/kdialog.rb', line 257

def filepicker(action: :save, type: :file, dir: ENV['HOME'], multiple: false, filter: nil, &blk)
  cmd = ["--separate-output"]
  cmd << "--multiple" if (multiple and action == :open)
  cmd << case [action, type]
  when [:save, :file]
    "--getsavefilename"
  when [:save, :url]
    "--getsaveurl"
  when [:open, :file]
    "--getopenfilename"
  when [:open, :url]
    "--getopenurl"
  else
    if type == :directory
      "--getexistingdirectory"
    end
  end
  cmd << dir
  cmd << filter unless (type == :directory or filter.nil?)
  if block_given?
    run(cmd) do |input|
      if multiple
        param = input.split(/\n/)
      else
        param = input
      end
      yield(param)
    end
  else
    input, status = run(cmd)
    if multiple
      input.split(/\n/)
    else
      input
    end
  end
end

#iconArray<(String, Boolean)>

Icon Picker

Allows the user to choose an icon among those available to KDE.

Returns:

  • (Array<(String, Boolean)>)

    the textual output of running kdialog, and whether it exited successfully



300
301
302
# File 'lib/dialog/kdialog.rb', line 300

def icon()
  run(["--geticon", "--help"])
end

#inputbox(prompt: "Input some text", content: nil, height: 1, width: 40, password: false) {|input| ... } ⇒ Array<(String, Boolean)>

Present an input box. It may be a one-line field, a password field, or a larger text-entry area potentially with scrollbars.

Parameters:

  • prompt (String) (defaults to: "Input some text")

    The text to prompt the user, above the input fields

  • content (String) (defaults to: nil)

    The initial value in the input box

  • height (Integer) (defaults to: 1)

    The height of the input field. If 1, presents a single-line input field. If larger, presents a text box that can potentially scroll vertically and horizontally. Defaults to 1

  • width (Integer) (defaults to: 40)

    The width of the input field. Note that this does not limit the amount of text the user may return, only how much can be seen on the screen at once.

  • password (Boolean) (defaults to: false)

    When true, use a 'key' icon and only show dots in place of input characters. When this is true, the height parameter is required to be 1, otherwise this option has no effect.

Yield Parameters:

  • input (String)

    the text provided by the user

Returns:

  • (Array<(String, Boolean)>)

    the textual output of running kdialog, and whether it exited successfully



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/dialog/kdialog.rb', line 118

def inputbox(prompt: "Input some text", content: nil, height: 1, width: 40, password: false, &blk)
  if height == 1
    if password == true
      cmd = ["--password"]
    else
      cmd = ["--inputbox"]
    end
  elsif height > 1
    cmd = ["--textinputbox"]
  end
  cmd << prompt
  if password == false
    cmd << content if content
    if height > 1
      cmd += ["--height", height]
    end
    cmd += ["--width", 40]
  end

  run(cmd, &blk)
end

#messagebox(text, type: :msgbox) ⇒ Array<(String, Boolean)>

A message box, for displaying a little text to the user. For longer, multi-line text, you may prefer to use #textbox. Contrasting with the standard dialog boxes, the button presented to the user only has the effect of closing the box.

Parameters:

  • type (:msgbox :sorry :error) (defaults to: :msgbox)

    The type of message box, affects the choice of icon shown in the box

Returns:

  • (Array<(String, Boolean)>)

    the textual output of running kdialog, and whether it exited successfully



78
79
80
81
82
83
84
# File 'lib/dialog/kdialog.rb', line 78

def messagebox(text, type: :msgbox)
  unless {:msgbox => 1, :sorry => 1, :error => 1}.has_key?(type)
    raise "Can't make that kind of message box"
  end
  cmdtype = "--#{type}"
  run([cmdtype, text])
end

#notification(text, timeout: 3) ⇒ Object

Raise a notification for the user. This doesn’t bring up a window that takes focus, just a little box (usually above the taskbar) in the notification area that goes away by itself.

Parameters:

  • text (String)

    The text to show in the notification

  • timeout (Integer) (defaults to: 3)

    The number of seconds to show the notification for



243
244
245
# File 'lib/dialog/kdialog.rb', line 243

def notification(text, timeout: 3)
  run(["--passivepopup", text, timeout.to_s])
end

#progressbar(steps: 100, title: "Progress Bar", show_cancel: false, label: "Working...", autoclose: true, &blk) ⇒ ProgressBar

Present a progress bar to the user; returns an object to control its desplay

Parameters:

  • steps (Integer) (defaults to: 100)

    Number of increments in the progress bar.

  • title (String) (defaults to: "Progress Bar")

    Text to display in the titlebar of the window

Returns:

  • (ProgressBar)

    An object for manipulating state of the progress bar



420
421
422
423
424
425
426
427
# File 'lib/dialog/kdialog.rb', line 420

def progressbar(steps: 100, title: "Progress Bar", show_cancel: false, label: "Working...", autoclose: true, &blk)
  out, status = Open3.capture2("kdialog", "--progressbar", title, steps.to_s)
  if status != 0
    raise "kdialog exited unexpectedly"
  end
  servicename, path = *out.split(/\s+/)
  ProgressBar.new(servicename, path, label: label, autoclose: autoclose, &blk)
end

#radiobuttons(choices, label: "", default: nil) ⇒ Array<(String, Boolean)>

Note:

It’s the caller’s responsibility to either specify a default, or make sure only one of the 'choices' attributes is true in the choices parameter.

Present a set of radio buttons to the user

Using this method may be easier than using #selection, as you don’t need to indicate you want radio buttons.

Parameters:

  • choices (#members)

    An object with an attribute for each choice, and a #members method which returns a list of those attributes to be used.

  • label (String) (defaults to: "")

    The text to display above input fields

  • default (Array<String> String) (defaults to: nil)

    The name of the attribute to be pre-selected for the user, or a list of such names, in the case of checkboxes. If not provided, the attribute’s value is tested, and if true, is selected.

Returns:

  • (Array<(String, Boolean)>)

    the textual output of running kdialog, and whether it exited successfully



192
193
194
# File 'lib/dialog/kdialog.rb', line 192

def radiobuttons(choices, label: "", default: nil)
  selection(choices, label: label, type: :radio, default: default)
end

#run(arglist) {|output| ... } ⇒ Array<(String, Boolean)>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the textual output of running kdialog, and whether it exited successfully.

Parameters:

  • arglist (Array<String>)

    List of command-line arguments for kdialog

Yield Parameters:

  • output (String)

    The output of running kdialog

Returns:

  • (Array<(String, Boolean)>)

    the textual output of running kdialog, and whether it exited successfully

Raises:

  • (StandardError)

    Any exception raised by Open3#capture2



434
435
436
437
438
439
440
441
442
443
444
445
446
# File 'lib/dialog/kdialog.rb', line 434

def run(arglist, &blk)
  cmd = ["kdialog"] + arglist
  output, code = Open3.capture2(*cmd)
  status = case code.exitstatus
           when 0 then true
           when 1 then false
           else false
           end
  if block_given? and status == true
    yield(output.chomp)
  end
  return output.chomp, status
end

#selection(choices, label: "", type: :check, default: nil) ⇒ Array<(String, Boolean)>

Note:

If type is :radio, it’s the caller’s responsibility to either specify a default, or make sure only one of the 'choices' attributes is true in the choices parameter.

Implementation of radiobuttons and checkboxes; user selections.

Parameters:

  • choices (#members)

    An object with an attribute for each choice, and a #members method which returns a list of those attributes to be used.

  • label (String) (defaults to: "")

    The text to display above input fields

  • default (Array<String> String) (defaults to: nil)

    The name of the attribute to be pre-selected for the user, or a list of such names, in the case of checkboxes. If not provided, the attribute’s value is tested, and if true, is selected.

  • type (Symbol) (defaults to: :check)

    Either :check (for checkboxes, multiple selections allowed) or :radio, (for radio buttons, only one selection)

Returns:

  • (Array<(String, Boolean)>)

    the textual output of running kdialog, and whether it exited successfully

Raises:

  • UnknownSelectionType If type is something other than :check or :radio



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
# File 'lib/dialog/kdialog.rb', line 207

def selection(choices, label: "", type: :check, default: nil)
  cmd = ["--separate-output"]
  cmd << case type
  when :check
    "--checklist"
  when :radio
    "--radiolist"
  else
    raise UnknownSelectionType, "Unknown selection type", caller
  end
  cmd << label
  choices.members.each_with_index {|c, i|
    if ((default.nil? and choices.send(c)) or (default == c) or (default.include?(c)))
        cmd += [i.to_s, c.to_s, 'on']
    else
      cmd += [i.to_s, c.to_s, 'off']
    end
  }
  run(cmd) do |sel|
    selected = sel.each_line.map{|l| l.chomp.to_i}
    choices.members.each.with_index do |box, i|
      method = (box.to_s + '=').to_sym
      if selected.include?(i)
        choices.send(method, true)
      else
        choices.send(method, false)
      end
    end
  end
end

#textbox(text, height: 10, width: 40) ⇒ Array<(String, Boolean)>

A window for showing the user a large amount of text, potentially using horizontal and vertical scrollbars. For small amounts of text, use #messagebox

Parameters:

  • text (String IO)

    The text to send to the user, or a readable IO object.

  • height (Integer) (defaults to: 10)

    The height of the textbox area, defaults to 10

  • width (Integer) (defaults to: 40)

    The width of the textbox area, defaults to 40

Returns:

  • (Array<(String, Boolean)>)

    the textual output of running kdialog, and whether it exited successfully



93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/dialog/kdialog.rb', line 93

def textbox(text, height: 10, width: 40)
  Tempfile.open('dialogfu') do |tf|
    if text.respond_to?(:read)
      tf.print(text.read)
    else
      tf.print(text)
    end
    tf.close
    run(["--textbox", path, "--height", height, "--width", width])
    tf.unlink
  end
end