Class: Yast::CWMClass

Inherits:
Module
  • Object
show all
Defined in:
library/cwm/src/modules/CWM.rb

Constant Summary collapse

CONTAINER_WIDGETS =

UI containers, layout helpers that contain other widgets. Used by functions that recurse through "contents" to decide whether to go deeper.

[
  :Frame,
  :RadioButtonGroup,
  :VBox,
  :HBox,
  :MarginBox,
  :MinWidth,
  :MinHeight,
  :MinSize,
  :Left,
  :Right,
  :Top,
  :Bottom,
  :HCenter,
  :VCenter,
  :HVCenter,
  :HSquash,
  :VSquash,
  :HVSquash,
  :HWeight,
  :VWeight,
  :DumbTab,
  :ReplacePoint
].freeze

Instance Method Summary collapse

Instance Method Details

#AdjustButtons(next_, back, abort, _help) ⇒ Object

Adjust the labels of the bottom buttons of the wizard sequencer

Parameters:

  • next_ (String)

    label of the "Next" button

  • back (String)

    string label of the "Back" button

  • abort (String)

    string label of the "Abort" button

  • _help (String)

    unused parameter since help button cannot be hide anyway


852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
# File 'library/cwm/src/modules/CWM.rb', line 852

def AdjustButtons(next_, back, abort, _help)
  next_ = "" if next_.nil?
  back = "" if back.nil?
  abort = "" if abort.nil?
  if next_ != ""
    Wizard.SetNextButton(:next, next_)
  else
    Wizard.HideNextButton
  end

  if abort != ""
    Wizard.SetAbortButton(:abort, abort)
  else
    Wizard.HideAbortButton
  end

  if back != ""
    Wizard.SetBackButton(:back, back)
  else
    Wizard.HideBackButton
  end

  nil
end

#cleanupWidgets(widgets) ⇒ Object

Cleanup after dialog was finished (independently on what event) global only because of testsuites

Parameters:


384
385
386
387
388
389
390
391
392
393
394
395
396
397
# File 'library/cwm/src/modules/CWM.rb', line 384

def cleanupWidgets(widgets)
  widgets = deep_copy(widgets)
  Builtins.foreach(widgets) do |w|
    self.processed_widget = deep_copy(w)
    toEval = Convert.convert(
      Ops.get(w, "cleanup"),
      from: "any",
      to:   "void (string)"
    )
    toEval&.call(Ops.get_string(w, "_cwm_key", ""))
  end

  nil
end

#CreateWidgets(names, source) ⇒ Array<::CWM::WidgetHash>

Read widgets with listed names

Parameters:

  • names (Array<String>)

    a list of strings/symbols names of widgets

  • Hash (Hash <String, ::CWM::WidgetHash] source a map containing the widgets)

    <String, ::CWM::WidgetHash] source a map containing the widgets

Returns:


690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
# File 'library/cwm/src/modules/CWM.rb', line 690

def CreateWidgets(names, source)
  names = deep_copy(names)
  source = deep_copy(source)
  ValidateMaps(source) # FIXME: find better place
  ret = Builtins.maplist(names) do |w|
    m = Ops.get(source, w, {})    # leave add here in order to make a copy of the structure
    # eval isn't usable because the map may contain terms, that can't
    # be evaluated here

    m = Builtins.add(m, "_cwm_key", w)
    deep_copy(m)
  end
  ret = Builtins.maplist(ret) { |w| prepareWidget(w) }
  deep_copy(ret)
end

#DisableButtons(buttons) ⇒ Object

Disable given bottom buttons of the wizard sequencer

Parameters:

  • buttons (Array<String>)

    list of buttons to be disabled: "back_button", "abort_button", "next_button"


837
838
839
840
841
842
843
844
845
# File 'library/cwm/src/modules/CWM.rb', line 837

def DisableButtons(buttons)
  Builtins.foreach(buttons) do |button|
    Wizard.DisableBackButton if button == "back_button"
    Wizard.DisableAbortButton if button == "abort_button"
    Wizard.DisableNextButton if button == "next_button"
  end

  nil
end

#GetLowestTimeout(widgets) ⇒ Integer

Returns the lowest 'ui_timeout' value, or 0.

Parameters:

Returns:

  • (Integer)

    the lowest 'ui_timeout' value, or 0


270
271
272
273
274
275
276
277
278
279
280
# File 'library/cwm/src/modules/CWM.rb', line 270

def GetLowestTimeout(widgets)
  minimum = 0
  Builtins.foreach(widgets) do |w|
    timeout = Ops.get_integer(w, "ui_timeout", 0)
    if Ops.less_than(timeout, minimum) && Ops.greater_than(timeout, 0) ||
        minimum == 0
      minimum = timeout
    end
  end
  minimum
end

#GetProcessedWidgetHash

Return description map of currently processed widget

Returns:

  • (Hash)

    description map of currently processed widget


403
404
405
# File 'library/cwm/src/modules/CWM.rb', line 403

def GetProcessedWidget
  deep_copy(@processed_widget)
end

#handleDebugObject

A hook to handle Alt-Ctrl-Shift-D


758
759
760
761
762
# File 'library/cwm/src/modules/CWM.rb', line 758

def handleDebug
  Builtins.y2debug("Handling a debugging event")

  nil
end

#handleWidgets(widgets, event_descr) ⇒ Symbol

Handle change of widget after event generated global only because of testsuites

Parameters:

  • widgets (Array<::CWM::WidgetHash>)

    list of maps represenging widgets

  • event_descr (Hash)

    map event that occured

Returns:

  • (Symbol)

    modified action (sometimes may be needed) or nil


338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
# File 'library/cwm/src/modules/CWM.rb', line 338

def handleWidgets(widgets, event_descr)
  event_descr = deep_copy(event_descr)
  ret = nil
  Builtins.foreach(widgets) do |w|
    if ret.nil?
      self.processed_widget = deep_copy(w)
      events = Ops.get_list(w, "handle_events", [])
      toEval = Convert.convert(
        Ops.get(w, "handle"),
        from: "any",
        to:   "symbol (string, map)"
      )
      if !toEval.nil? &&
          (events == [] ||
            Builtins.contains(events, Ops.get(event_descr, "ID")))
        ret = toEval.call(Ops.get_string(w, "_cwm_key", ""), event_descr)
      end
    end
  end
  ret
end

#InitNull(_key) ⇒ Object

Do-nothing replacement for a widget initialization function. Used for push buttons if all the other widgets have a fallback.

Parameters:

  • _key (String)

    id of the widget


1012
1013
1014
# File 'library/cwm/src/modules/CWM.rb', line 1012

def InitNull(_key)
  nil
end

#initWidgets(widgets) ⇒ Object

Set widgets according to internally stored settings global only because of testsuites

Parameters:


308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
# File 'library/cwm/src/modules/CWM.rb', line 308

def initWidgets(widgets)
  widgets = deep_copy(widgets)
  Builtins.foreach(widgets) do |w|
    # set initial properties
    valid_chars = Ops.get_string(w, "valid_chars")
    if !valid_chars.nil?
      UI.ChangeWidget(
        Id(Ops.get_string(w, "_cwm_key", "")),
        :ValidChars,
        valid_chars
      )
    end    # set initial values

    self.processed_widget = deep_copy(w)
    toEval = Convert.convert(
      Ops.get(w, "init"),
      from: "any",
      to:   "void (string)"
    )
    toEval&.call(Ops.get_string(w, "_cwm_key", ""))
  end

  nil
end

#mainObject


35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'library/cwm/src/modules/CWM.rb', line 35

def main
  Yast.import "UI"
  textdomain "base"

  Yast.import "Label"
  Yast.import "Report"
  Yast.import "Wizard"

  # local variables

  # Widget that is being currently processed
  @processed_widget = {}

  # All widgets of the current dialog, in the correct order
  @current_dialog_widgets = []

  # stack of settings of nested calls of CWM
  @settings_stack = []

  # Handler to be called after validation of a dialog fails
  @validation_failed_handler = nil
end

#mergeFunctions(widgets, functions) ⇒ Object

Add fallback functions to a widget global only because of testsuites

Parameters:

  • widgets (Array<::CWM::WidgetHash>)

    a list of widget desctiption maps

  • functions (Hash)

    map of functions

Returns:

  • a list of modified widget description maps


287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'library/cwm/src/modules/CWM.rb', line 287

def mergeFunctions(widgets, functions)
  widgets = deep_copy(widgets)
  functions = deep_copy(functions)
  functions = Builtins.filter(functions) { |k, _v| Ops.is_string?(k) }
  fallback_functions = Convert.convert(
    functions,
    from: "map",
    to:   "map <string, any>"
  )
  Builtins.maplist(widgets) do |w|
    Convert.convert(
      Builtins.union(fallback_functions, w),
      from: "map",
      to:   "map <string, any>"
    )
  end
end

#MergeHelps(widgets) ⇒ String

Merge helps from the widgets

Parameters:

Returns:

  • (String)

    merged helps of the widgets


709
710
711
712
713
714
715
716
717
718
# File 'library/cwm/src/modules/CWM.rb', line 709

def MergeHelps(widgets)
  return "" unless widgets

  helps = widgets.map do |widget|
    help = widget["help"]
    help.respond_to?(:call) ? help.call : help
  end
  helps.compact!
  helps.join("\n")
end

#OkCancelBox::CWM::UITerm

Create a term with OK and Cancel buttons placed horizontally

Returns:


409
410
411
412
413
414
415
416
417
418
419
420
421
422
# File 'library/cwm/src/modules/CWM.rb', line 409

def OkCancelBox
  ButtonBox(
    PushButton(
      Id(:_tp_ok),
      Opt(:key_F10, :default, :okButton),
      Label.OKButton
    ),
    PushButton(
      Id(:_tp_cancel),
      Opt(:key_F9, :cancelButton),
      Label.CancelButton
    )
  )
end

#PopSettingsObject

Pop the settings of the currently run dialog from the stack


99
100
101
102
103
104
105
106
# File 'library/cwm/src/modules/CWM.rb', line 99

def PopSettings
  current_dialog = Ops.get(@settings_stack, 0, {})
  Ops.set(@settings_stack, 0, nil)
  @settings_stack = Builtins.filter(@settings_stack) { |e| !e.nil? }
  @current_dialog_widgets = Ops.get_list(current_dialog, "widgets", [])

  nil
end

#PrepareDialog(dialog, widgets) ⇒ ::CWM::UITerm

Prepare the dialog, replace strings in the term with appropriate widgets

Parameters:

Returns:


725
726
727
728
729
730
731
732
733
# File 'library/cwm/src/modules/CWM.rb', line 725

def PrepareDialog(dialog, widgets)
  return dialog.clone if dialog.empty?

  m = widgets.map do |w|
    widget_key = w.fetch("_cwm_key", "")
    [widget_key, w]
  end.to_h
  ProcessTerm(dialog, m)
end

#prepareWidget(widget_descr) ⇒ ::CWM::WidgetHash

Prepare a widget for usage

Parameters:

Returns:


475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
# File 'library/cwm/src/modules/CWM.rb', line 475

def prepareWidget(widget_descr)
  widget_descr = deep_copy(widget_descr)
  w = deep_copy(widget_descr)
  widget = Ops.get_symbol(w, "widget", :inputfield)

  if Ops.get(w, "widget") == :empty
    Ops.set(w, "widget", VBox())
  elsif Ops.get(w, "widget") == :custom &&
      Ops.get(w, "custom_widget")
    Ops.set(w, "widget", Ops.get_term(w, "custom_widget") { VSpacing(0) })
  elsif Ops.get(w, "widget") == :func
    toEval = Convert.convert(
      Ops.get(w, "widget_func"),
      from: "any",
      to:   "term ()"
    )
    if !toEval.nil?
      Ops.set(w, "widget", toEval.call)
    else
      Ops.set(w, "widget", VBox())
    end
  else
    id_term = Id(Ops.get_string(w, "_cwm_key", ""))
    opt_term = Opt()
    Builtins.foreach(Ops.get_list(w, "opt", [])) do |o|
      opt_term = Builtins.add(opt_term, o)
    end
    label = Ops.get_string(w, "label", Ops.get_string(w, "_cwm_key", ""))

    case widget
    when :inputfield, :textentry      # backward compatibility

      opt_term = Builtins.add(opt_term, :hstretch) if !Builtins.contains(Builtins.argsof(opt_term), :hstretch)
      Ops.set(w, "widget", InputField(id_term, opt_term, label))
    when :password
      Ops.set(w, "widget", Password(id_term, opt_term, label))
    when :checkbox
      Ops.set(w, "widget", CheckBox(id_term, opt_term, label))
    when :combobox
      Ops.set(
        w,
        "widget",
        ComboBox(
          id_term,
          opt_term,
          label,
          Builtins.maplist(Ops.get_list(w, "items", [])) do |i|
            Item(Id(Ops.get(i, 0, "")), Ops.get(i, 1, Ops.get(i, 0, "")))
          end
        )
      )
    when :selection_box
      Ops.set(
        w,
        "widget",
        SelectionBox(
          id_term,
          opt_term,
          label,
          Builtins.maplist(Ops.get_list(w, "items", [])) do |i|
            Item(Id(Ops.get(i, 0, "")), Ops.get(i, 1, Ops.get(i, 0, "")))
          end
        )
      )
    when :multi_selection_box
      Ops.set(
        w,
        "widget",
        MultiSelectionBox(
          id_term,
          opt_term,
          label,
          Builtins.maplist(Ops.get_list(w, "items", [])) do |i|
            Item(Id(Ops.get(i, 0, "")), Ops.get(i, 1, Ops.get(i, 0, "")))
          end
        )
      )
    when :intfield
      min = Ops.get_integer(w, "minimum", 0)
      max = Ops.get_integer(w, "maximum", 2**31 - 1) # libyui support only signed int
      Ops.set(
        w,
        "widget",
        IntField(id_term, opt_term, label, min, max, min)
      )
    when :radio_buttons
      hspacing = Ops.get_integer(w, "hspacing", 0)
      vspacing = Ops.get_integer(w, "vspacing", 0)
      buttons = VBox(VSpacing(vspacing))
      Builtins.foreach(Ops.get_list(w, "items", [])) do |i|
        buttons = Builtins.add(
          buttons,
          Left(
            RadioButton(
              Id(Ops.get(i, 0, "")),
              opt_term,
              Ops.get(i, 1, Ops.get(i, 0, ""))
            )
          )
        )
        buttons = Builtins.add(buttons, VSpacing(vspacing))
      end
      Ops.set(
        w,
        "widget",
        Frame(
          label,
          HBox(
            HSpacing(hspacing),
            RadioButtonGroup(id_term, buttons),
            HSpacing(hspacing)
          )
        )
      )
    when :radio_button
      Ops.set(w, "widget", RadioButton(id_term, opt_term, label))
    when :push_button
      Ops.set(w, "widget", PushButton(id_term, opt_term, label))
    when :menu_button
      Ops.set(
        w,
        "widget",
        MenuButton(
          id_term,
          opt_term,
          label,
          Builtins.maplist(Ops.get_list(w, "items", [])) do |i|
            Item(Id(Ops.get(i, 0, "")), Ops.get(i, 1, Ops.get(i, 0, "")))
          end
        )
      )
    when :multi_line_edit
      Ops.set(w, "widget", MultiLineEdit(id_term, opt_term, label))
    when :richtext
      Ops.set(w, "widget", RichText(id_term, opt_term, ""))
    when :date_field
      Ops.set(w, "widget", DateField(id_term, opt_term, label))
    when :time_field
      Ops.set(w, "widget", TimeField(id_term, opt_term, label))
    end
  end
  Ops.set(w, "custom_widget", nil) # not needed any more
  deep_copy(w)
end

#ProcessTerm(term, widgets) ⇒ ::CWM::UITerm

Process term with the dialog, replace strings in the term with appropriate widgets

Parameters:

Returns:


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
# File 'library/cwm/src/modules/CWM.rb', line 113

def ProcessTerm(term, widgets)
  return term if term.empty?

  ret = Yast::Term.new(term.value)

  is_frame = term.value == :Frame
  is_id_frame = false

  term.each.with_index do |arg, index|
    if is_frame && index == 0 # no action
      # frame can have id and also label, so mark if id is used
      is_id_frame = arg.is_a?(Yast::Term) && arg.value == :id
      Builtins.y2debug("Leaving untouched %1", arg)
    elsif is_frame && index == 1 && is_id_frame && arg.is_a?(::String) # no action
      Builtins.y2debug("Leaving untouched %1", arg)
    elsif Ops.is_term?(arg) # recurse
      arg = ProcessTerm(arg, widgets) if CONTAINER_WIDGETS.include?(arg.value)
    elsif Ops.is_string?(arg) # action
      Builtins.y2error("find string '#{arg}' without associated widget in StringTerm #{term.inspect}") unless widgets[arg]
      Builtins.y2milestone("Known widgets #{widgets.inspect}") unless widgets[arg]

      arg = widgets.fetch(arg, {}).fetch("widget") { VBox() }
      arg = ProcessTerm(arg, widgets) if CONTAINER_WIDGETS.include?(arg.value)
    end
    ret << arg
  end
  ret
end

#PushSettingsObject

Push the settings of the currently run dialog to the stack


89
90
91
92
93
94
95
96
# File 'library/cwm/src/modules/CWM.rb', line 89

def PushSettings
  @settings_stack = Builtins.prepend(
    @settings_stack,
    "widgets" => @current_dialog_widgets
  )

  nil
end

#ReplaceWidgetHelp(widget = nil, help = "") ⇒ Object

Replace help for a particular widget if nil is passed, then just regenerate help. Useful for refresh dynamic help content.

Examples:

change help content for widget w which had static help

Yast::CWM.ReplaceWidgetHelp("my_widget", "my new free-cool-in help")

refresh help for widget with dynamic content

Yast::CWM.ReplaceWidgetHelp

Parameters:

  • widget (String) (defaults to: nil)

    string widget ID of widget to replace help,

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

    string new help to the widget. If widget is nil, then this argument is ignored


744
745
746
747
748
749
750
751
752
753
754
755
# File 'library/cwm/src/modules/CWM.rb', line 744

def ReplaceWidgetHelp(widget = nil, help = "")
  if widget
    @current_dialog_widgets = Builtins.maplist(@current_dialog_widgets) do |w|
      Ops.set(w, "help", help) if Ops.get_string(w, "_cwm_key", "") == widget
      deep_copy(w)
    end
  end
  help = MergeHelps(@current_dialog_widgets)
  Wizard.RestoreHelp(help)

  nil
end

#Run(widgets, functions, skip_store_for: []) ⇒ Symbol

Generic function to create dialog and handle it's events

Parameters:

  • widgets (Array<::CWM::WidgetHash>)

    list of widget maps

  • functions (Hash)

    map initialize/save/handle fallbacks if not specified with the widgets.

  • skip_store_for (Array<Object>) (defaults to: [])

    list of events for which the value of the widget will not be stored Useful mainly for non-standard redraw of widgets, like :reset or :redraw. It will skip also validation, because it is not needed as nothing is stored.

Returns:

  • (Symbol)

    wizard sequencer symbol


772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
# File 'library/cwm/src/modules/CWM.rb', line 772

def Run(widgets, functions, skip_store_for: [])
  widgets = deep_copy(widgets)
  functions = deep_copy(functions)
  widgets = mergeFunctions(widgets, functions)
  PushSettings()
  @current_dialog_widgets = deep_copy(widgets)
  initWidgets(widgets)

  # allow a handler to enable/disable widgets before the first real
  # UserInput takes place
  UI.FakeUserInput("ID" => "_cwm_wakeup")

  ret = nil
  save_exits = [:next, :ok]
  save = false
  event_descr = {}
  timeout = GetLowestTimeout(widgets)
  while ret != :back && ret != :abort && !save
    event_descr = if Ops.greater_than(timeout, 0)
      UI.WaitForEvent(timeout)
    else
      UI.WaitForEvent
    end
    ret = Ops.get(event_descr, "ID")
    handleDebug if Ops.get_string(event_descr, "EventType", "") == "DebugEvent"
    handle_ret = handleWidgets(widgets, event_descr)
    if !handle_ret.nil? ||
        Ops.is_symbol?(ret) && Builtins.contains(save_exits, ret)
      save = true
      if !handle_ret.nil?
        ret = handle_ret
        Ops.set(event_descr, "ID", ret)
      end
    end

    ret = :abort if ret == :cancel

    if ret == :next && functions[:next]
      ret = nil unless functions[:next].call
      save = false if ret.nil?
    elsif ret == :back && functions[:back]
      ret = nil unless functions[:back].call
    elsif ret == :abort && functions[:abort]
      ret = nil unless functions[:abort].call
    end

    next if ret.nil?

    # ok, so what happens here? event want to save widgets, so check that there is no explicit
    # skip of  storing for this event and there is a widget containing invalid value.
    # In such case do not save and clear ret, so we are still in loop
    if save && !skip_store_for.include?(ret) && !validateWidgets(widgets, event_descr)
      ret = nil
      save = false
    end
  end
  saveWidgets(widgets, event_descr) if save && !skip_store_for.include?(ret)
  cleanupWidgets(widgets)
  PopSettings()
  Convert.to_symbol(ret)
end

#save_current_widgets(event) ⇒ Object

Saves changes of all the widgets in the current dialog

Parameters:

  • event (Hash)

    map event that triggered the saving


1027
1028
1029
# File 'library/cwm/src/modules/CWM.rb', line 1027

def save_current_widgets(event)
  saveWidgets(@current_dialog_widgets, event)
end

#saveWidgets(widgets, event) ⇒ Object

Save changes of widget after event generated global only because of testsuites CWMTab uses it too

Parameters:

  • widgets (Array<::CWM::WidgetHash>)

    list of maps represenging widgets

  • event (Hash)

    map event that occured


365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
# File 'library/cwm/src/modules/CWM.rb', line 365

def saveWidgets(widgets, event)
  widgets = deep_copy(widgets)
  event = deep_copy(event)
  Builtins.foreach(widgets) do |w|
    self.processed_widget = deep_copy(w)
    toEval = Convert.convert(
      Ops.get(w, "store"),
      from: "any",
      to:   "void (string, map)"
    )
    toEval&.call(Ops.get_string(w, "_cwm_key", ""), event)
  end

  nil
end

#SetValidationFailedHandler(handler) ⇒ Object

Set handler to be called after validation of a dialog failed

Parameters:

  • handler (void ())

    a function reference to be caled. If nil, nothing is called


879
880
881
882
883
# File 'library/cwm/src/modules/CWM.rb', line 879

def SetValidationFailedHandler(handler)
  @validation_failed_handler = deep_copy(handler)

  nil
end

#show(contents, caption: nil, back_button: nil, next_button: nil, abort_button: nil, skip_store_for: [], disable_buttons: [], next_handler: nil, back_handler: nil, abort_handler: nil) ⇒ Symbol

Display the dialog and run its event loop using new widget API

Parameters:

  • contents (::CWM::WidgetTerm)

    UI term including instances of CWM::AbstractWidget

  • caption (String) (defaults to: nil)

    caption of dialog

  • back_button (String, nil) (defaults to: nil)

    label for dialog back button, nil to use the default label, "" to omit the button

  • next_button (String, nil) (defaults to: nil)

    label for dialog next button, nil to use the default label, "" to omit the button

  • abort_button (String, nil) (defaults to: nil)

    label for dialog abort button, nil to use the default label, "" to omit the button

  • skip_store_for (Array) (defaults to: [])

    list of events for which the value of the widget will not be stored. Useful mainly when some widget returns an event that should not trigger the storing, like a reset button or a redrawing. It will skip also validation, because it is not needed as nothing is stored.

  • disable_buttons (Array<String>) (defaults to: [])

    buttons to disable: "back_button", "abort_button", "next_button"

  • next_handler (Proc) (defaults to: nil)

    handler that is called after clicking on next. If it returns false, then it does not go next. If it returns true, then :next symbol is returned. If handler is not defined, then it acts like if it returns true.

  • back_handler (Proc) (defaults to: nil)

    handler that is called after clicking on back. If it returns false, then it does not go back. If it returns true, then :back symbol is returned. If handler is not defined, then it acts like if it returns true.

  • abort_handler (Proc) (defaults to: nil)

    handler that is called after clicking on abort. If it returns false, then it stops abort. If it returns true, then :abort symbol is returned. If handler is not defined, then it acts like if it returns true.

Returns:

  • (Symbol)

    wizard sequencer symbol


911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
# File 'library/cwm/src/modules/CWM.rb', line 911

def show(contents, caption: nil, back_button: nil, next_button: nil, abort_button: nil, skip_store_for: [],
  disable_buttons: [], next_handler: nil, back_handler: nil, abort_handler: nil)
  widgets = widgets_in_contents(contents)
  options = {
    "contents"     => widgets_contents(contents),
    "widget_names" => widgets.map(&:widget_id),
    "widget_descr" => Hash[widgets.map { |w| [w.widget_id, w.cwm_definition] }]
  }
  options["caption"] = caption if caption
  options["back_button"] = back_button if back_button
  options["next_button"] = next_button if next_button
  options["abort_button"] = abort_button if abort_button
  options["skip_store_for"] = skip_store_for
  options["disable_buttons"] = disable_buttons
  options["fallback_functions"] = {}
  options["fallback_functions"][:next] = Yast.fun_ref(next_handler, "boolean ()") if next_handler
  options["fallback_functions"][:back] = Yast.fun_ref(back_handler, "boolean ()") if back_handler
  options["fallback_functions"][:abort] = Yast.fun_ref(abort_handler, "boolean ()") if abort_handler

  ShowAndRun(options)
end

#ShowAndRun(settings) ⇒ Object

Display the dialog and run its event loop

Parameters:

  • settings (Hash<String, Object>)

    a map of all settings needed to run the dialog

Options Hash (settings):

  • "widgets" (Array<CWM::AbstractWidget>)

    list of widgets used in CWM, it is auto added to "widget_names" and "widget_descr"


937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
# File 'library/cwm/src/modules/CWM.rb', line 937

def ShowAndRun(settings)
  settings = deep_copy(settings)
  if settings["widgets"]
    widgets = settings["widgets"]
    settings["widget_names"] ||= []
    settings["widget_names"] += widgets.map(&:widget_id)
    settings["widget_descr"] ||= {}
    settings["widget_descr"] = Hash[widgets.map { |w| [w.widget_id, w.cwm_definition] }]
  end
  widget_descr = Ops.get_map(settings, "widget_descr", {})
  contents = Ops.get_term(settings, "contents", VBox())
  widget_names = Convert.convert(
    Ops.get(settings, "widget_names") { StringsOfTerm(contents) },
    from: "any",
    to:   "list <string>"
  )
  caption = Ops.get_string(settings, "caption", "")
  back_button = Ops.get_string(settings, "back_button") { Label.BackButton }
  next_button = Ops.get_string(settings, "next_button") { Label.NextButton }
  abort_button = Ops.get_string(settings, "abort_button") do
    Label.AbortButton
  end
  fallback = Ops.get_map(settings, "fallback_functions", {})

  w = CreateWidgets(widget_names, widget_descr)
  help = MergeHelps(w)
  contents = PrepareDialog(contents, w)
  Wizard.SetContentsButtons(
    caption,
    contents,
    help,
    back_button,
    next_button
  )
  AdjustButtons(next_button, back_button, abort_button, nil)
  DisableButtons(Ops.get_list(settings, "disable_buttons", []))

  skip_store_for = settings["skip_store_for"] || []
  Run(w, fallback, skip_store_for: skip_store_for)
end

#ShowAndRunOrig(widget_names, widget_descr, contents, caption, back_button, next_button, fallback) ⇒ Symbol

Deprecated.

Display the dialog and run its event loop

Parameters:

  • widget_names (Array<String>)

    list of names of widgets that will be used in the dialog

  • widget_descr (Hash{String => ::CWM::WidgetHash})

    map description map of all widgets

  • contents (::CWM::StringTerm)

    contents of the dialog, identifiers instead of widgets

  • caption (String)

    string dialog caption

  • back_button (String)

    string label of the back button

  • next_button (String)

    string label of the next button

  • fallback (Hash)

    map initialize/save/handle fallbacks if not specified with the widgets.

Returns:

  • (Symbol)

    wizard sequencer symbol


991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
# File 'library/cwm/src/modules/CWM.rb', line 991

def ShowAndRunOrig(widget_names, widget_descr, contents, caption, back_button, next_button, fallback)
  widget_names = deep_copy(widget_names)
  widget_descr = deep_copy(widget_descr)
  contents = deep_copy(contents)
  fallback = deep_copy(fallback)
  ShowAndRun(
    "widget_names"       => widget_names,
    "widget_descr"       => widget_descr,
    "contents"           => contents,
    "caption"            => caption,
    "back_button"        => back_button,
    "next_button"        => next_button,
    "fallback_functions" => fallback
  )
end

#StoreNull(_key, _event) ⇒ Object

Do-nothing replacement for a widget storing function. Used for push buttons if all the other widgets have a fallback.

Parameters:

  • _key (String)

    id of the widget

  • _event (Hash)

    the event being handled


1020
1021
1022
# File 'library/cwm/src/modules/CWM.rb', line 1020

def StoreNull(_key, _event)
  nil
end

#StringsOfTerm(term) ⇒ Array<String>

Process term with the dialog, return all strings. To be used as an argument for widget_names until they are obsoleted.

Parameters:

Returns:

  • (Array<String>)

    found in the term


146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'library/cwm/src/modules/CWM.rb', line 146

def StringsOfTerm(term)
  term = deep_copy(term)
  rets = []
  args = Builtins.size(term)
  index = 0
  while Ops.less_than(index, args)
    arg = Ops.get(term, index)
    current = Builtins.symbolof(term)
    if current == :Frame && index == 0 # no action
      Builtins.y2debug("Leaving untouched %1", arg)
    elsif Ops.is_term?(arg)
      rets = Ops.add(rets, StringsOfTerm(Convert.to_term(arg))) if CONTAINER_WIDGETS.include?(arg.value)
    elsif Ops.is_string?(arg) # action
      rets = Builtins.add(rets, Convert.to_string(arg))
    end
    index = Ops.add(index, 1)
  end
  deep_copy(rets)
end

#validate_current_widgets(event) ⇒ Boolean

Validates all the widgets in the current dialog

Parameters:

  • event (Hash)

    map event that caused validation

Returns:

  • (Boolean)

    true if everything is OK, false if something is wrong


1035
1036
1037
# File 'library/cwm/src/modules/CWM.rb', line 1035

def validate_current_widgets(event)
  validateWidgets(@current_dialog_widgets, event)
end

#ValidateBasicType(value, type) ⇒ Boolean

Validate the value against the basic type

Parameters:

  • value (Object)

    any a value to validate

  • type (String)

    string type information

Returns:

  • (Boolean)

    true on success or if do not know how to validate


170
171
172
173
174
175
176
177
178
179
180
181
# File 'library/cwm/src/modules/CWM.rb', line 170

def ValidateBasicType(value, type)
  return Ops.is_term?(value) if type == "term"
  return Ops.is_string?(value) if type == "string"
  return Ops.is_symbol?(value) if type == "symbol"
  return Ops.is_list?(value) if type == "list"
  return Ops.is_map?(value) if type == "map"
  return Ops.is_boolean?(value) if type == "boolean"
  return Ops.is_integer?(value) if type == "integer"

  Builtins.y2error("Unknown value type %1", type)
  true
end

#ValidateMaps(widgets) ⇒ Boolean

Validate widget description map, check for maps structure Also checks option description maps if present

Parameters:

Returns:

  • (Boolean)

    true on success


428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
# File 'library/cwm/src/modules/CWM.rb', line 428

def ValidateMaps(widgets)
  widgets = deep_copy(widgets)
  ret = true
  Builtins.foreach(widgets) do |k, v|
    Builtins.foreach(v) do |kk, vv|
      ret = ValidateValueType(kk, vv, k) && ret
    end
    to_check = if Ops.get(v, "widget") == :custom
      ["custom_widget"]
    elsif Ops.get(v, "widget") == :empty
      []
    else
      ["label", "widget"]
    end
    Builtins.foreach(to_check) do |key|
      if key != "label" ||
          Ops.get(v, "widget") != :radio_buttons &&
              Ops.get(v, "widget") != :custom &&
              Ops.get(v, "widget") != :rich_text &&
              Ops.get(v, "widget") != :func
        ret = ValidateValueContents(key, Ops.get(v, key), k) && ret
      end
    end
    if Ops.get(v, "widget") == :custom
      ret = ValidateValueContents(
        "custom_widget",
        Ops.get(v, "custom_widget"),
        k
      ) && ret
    end    # validate widget-specific entries

    if Builtins.haskey(v, "_cwm_do_validate")
      val_func = Convert.convert(
        Ops.get(v, "_cwm_do_validate"),
        from: "any",
        to:   "boolean (string, map <string, any>)"
      )
      ret = val_func.call(k, v) && ret if !val_func.nil?
    end
  end
  ret
end

#ValidateValueContents(key, value, widget) ⇒ Boolean

Validate value of entry of the widget/option description map Also checks option description maps if present

Parameters:

  • key (String)

    string key of the map entry

  • value (Object)

    any value of the map entry

  • widget (String)

    any name of the widget/option

Returns:

  • (Boolean)

    true if validation succeeded


245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'library/cwm/src/modules/CWM.rb', line 245

def ValidateValueContents(key, value, widget)
  error = ""
  if key == "label"
    s = Convert.to_string(value)
    if s.nil? || Builtins.size(s) == 0
      error = "Empty label"
    elsif Builtins.size(Builtins.filterchars(s, "&")) != 1
      error = "Label has no shortcut or more than 1 shortcuts"
    end
  elsif key == "widget"
    s = Convert.to_symbol(value)
    error = "No widget specified" if s.nil?
  elsif key == "custom_widget"
    s = Convert.to_term(value)
    error = "No custom widget specified" if s.nil?
  end

  return true if error == ""

  Builtins.y2error("Error on key %1 of widget %2: %3", key, widget, error)
  false
end

#ValidateValueType(key, value, widget) ⇒ Boolean

Validate type of entry of the widget/option description map Also checks option description maps if present

Parameters:

  • key (String)

    string key of the map entry

  • value (Object)

    any value of the map entry

  • widget (String)

    any name of the widget/option

Returns:

  • (Boolean)

    true if validation succeeded


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
# File 'library/cwm/src/modules/CWM.rb', line 189

def ValidateValueType(key, value, widget)
  types = {
    # general
    "widget"        => "symbol",
    "custom_widget" => "term",
    "handle_events" => "list",
    "label"         => "string",
    "opt"           => "list",
    "ui_timeout"    => "integer",
    "validate_type" => "symbol",
    # int field
    "minimum"       => "integer",
    "maximum"       => "integer",
    "_cwm_attrib"   => "map",
    "fallback"      => "map"
  }
  type = Ops.get(types, key)
  success = if type.nil?
    case key
    when "widget_func" then Ops.is(value, "term ()")
    when "init" then Ops.is(value, "void (string)")
    when "handle" then Ops.is(value, "symbol (string, map)")
    when "store" then Ops.is(value, "void (string, map)")
    when "cleanup" then Ops.is(value, "void (string)")
    when "validate_function" then Ops.is(value, "boolean (string, map)")
    when "items" then Ops.is(value, "list <list <string>>")
    when "_cwm_do_validate" then Ops.is(value, "boolean (string, map <string, any>)")
    when "help"      # help can be static string or dynamic callback, that allows to recompute help for
      # widgets with dynamic contents like replace_point

      Ops.is(value, "string") || Ops.is(value, "string ()")
    else
      # unknown key, always valid
      true
    end
  else
    ValidateBasicType(value, type)
  end

  if !success
    Builtins.y2error(
      "Wrong type of option %1 in description map of %2",
      key,
      widget
    )
  end

  success
end

#validateWidget(widget, event, key) ⇒ Object

Validate single widget

Parameters:

  • widget (::CWM::WidgetHash)

    widget description map

  • event (Hash)

    map event that caused validation

  • key (String)

    widget key for validation by function

Returns:

  • true if validation succeeded


625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
# File 'library/cwm/src/modules/CWM.rb', line 625

def validateWidget(widget, event, key)
  widget = deep_copy(widget)
  event = deep_copy(event)
  self.processed_widget = deep_copy(widget)
  failed = false
  val_type = Ops.get_symbol(widget, "validate_type")
  case val_type
  when :function, :function_no_popup
    toEval = Convert.convert(
      Ops.get(widget, "validate_function"),
      from: "any",
      to:   "boolean (string, map)"
    )
    failed = !toEval.call(key, event) if !toEval.nil?
  when :regexp
    regexp = Ops.get_string(widget, "validate_condition", "")
    if !Builtins.regexpmatch(
      Convert.to_string(UI.QueryWidget(Id(:_tp_value), :Value)),
      regexp
    )
      failed = true
    end
  when :list
    possible = Ops.get_list(widget, "validate_condition", [])
    failed = true if !Builtins.contains(possible, UI.QueryWidget(Id(:_tp_value), :Value))
  end

  if failed && val_type != :function
    error = Ops.get_string(widget, "validate_help", "")
    if error == ""
      wname = Ops.get_string(
        widget,
        "label",
        Ops.get_string(widget, "_cwm_key", "")
      )
      wname = Builtins.deletechars(wname, "&")      # message popup, %1 is a label of some widget

      error = Builtins.sformat(_("The value of %1 is invalid."), wname)
    end
    UI.SetFocus(Id(Ops.get_string(widget, "_cwm_key", "")))
    Report.Error(error)
  end
  !failed
end

#validateWidgets(widgets, event) ⇒ Boolean

Validate dialog contents for allow it to be saved

Parameters:

  • widgets (Array<::CWM::WidgetHash>)

    list of widgets to validate

  • event (Hash)

    map event that caused validation

Returns:

  • (Boolean)

    true if everything is OK, false if something is wrong


674
675
676
677
678
679
680
681
682
683
684
# File 'library/cwm/src/modules/CWM.rb', line 674

def validateWidgets(widgets, event)
  widgets = deep_copy(widgets)
  event = deep_copy(event)
  result = true
  Builtins.foreach(widgets) do |w|
    widget_key = Ops.get_string(w, "_cwm_key", "")
    result &&= validateWidget(w, event, widget_key)
  end
  @validation_failed_handler.call if !result && !@validation_failed_handler.nil?
  result
end

#widgets_contents(contents) ⇒ ::CWM::StringTerm

Parameters:

Returns:


1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
# File 'library/cwm/src/modules/CWM.rb', line 1081

def widgets_contents(contents)
  res = contents.clone

  (0..(res.size - 1)).each do |index|
    case contents[index]
    when ::CWM::AbstractWidget then res[index] = res[index].widget_id
    when Yast::Term then res[index] = widgets_contents(res[index])
    end
  end

  res
end

#widgets_in_contents(contents) ⇒ Array<::CWM::AbstractWidget>

Returns:


1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
# File 'library/cwm/src/modules/CWM.rb', line 1067

def widgets_in_contents(contents)
  contents.each_with_object([]) do |arg, res|
    case arg
    when ::CWM::AbstractWidget
      res << arg      # if widget have its own content, also search it

      res.concat(widgets_in_contents(arg.contents)) if arg.respond_to?(:contents)
    when Yast::Term then res.concat(widgets_in_contents(arg))
    end
  end
end