-
Notifications
You must be signed in to change notification settings - Fork 11
/
CustomStatusItemSelector1.rb
156 lines (128 loc) · 5.57 KB
/
CustomStatusItemSelector1.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# encoding: utf-8
module Yast
class ExampleClient < Client
Yast.import "UI"
include Yast::Logger
def main
UI.OpenDialog(main_dialog)
set_visible_items
handle_events
UI.CloseDialog
end
protected
VISIBLE_ITEMS = 6
# Some constants to make handling the numeric status values better readable.
# Those constants correspond to the index of the status in the status
# definition (see custom_states).
MOD_DONT_INSTALL = 0
MOD_INSTALL = 1
MOD_AUTOINSTALL = 2
# The custom status values. Each one has an icon name, a text equivalent to
# indicate that status in the NCurses UI, and an optional next status.
#
# If a next status is specified, a click on that item will automatically
# cycle to that next status. If not specified (or -1), the application
# needs to handle status transitions from that status to another one.
def custom_states
[
# icon, NCurses indicator, next status (optional)
["checkbox-off", "[ ]", MOD_INSTALL ],
["checkbox-on", "[ +]", MOD_DONT_INSTALL],
["checkbox-auto-selected", "[a+]", MOD_DONT_INSTALL]
]
end
def items
[
# item ID, heading label , description text (optional)
Item(Id(:mod_kde ), "KDE Plasma", "Full-fledged desktop" ),
Item(Id(:mod_xfce ), "Xfce", "Lightweight desktop" ),
Item(Id(:mod_x11 ), "X Window System", "X11, simple window manager, xterm"),
Item(Id(:mod_office), "LibreOffice", "Office suite" ),
Item(Id(:mod_server), "Server Tools", "Web server, database, file server"),
Item(Id(:mod_sdk ), "SDK", "Development tools" )
]
end
def main_dialog
MarginBox(2, 0.4,
VBox(
Heading("Add-on Software"),
VSpacing(0.2),
CustomStatusItemSelector(Id(:modules), Opt(:notify), custom_states, items),
VSpacing(0.4),
Label(Id(:result_field), Opt(:outputField, :hstretch), "\n\n\n\n\n"),
VSpacing(0.3),
Right(
PushButton(Id(:close), "&Close")
)
)
)
end
def set_visible_items
UI.ChangeWidget(:modules, :VisibleItems, VISIBLE_ITEMS)
UI.RecalcLayout # needed for the change to have an effect
end
def handle_events
while true
event = UI.WaitForEvent
log.info("Event: #{event}")
break if event["WidgetID"] == :close
break if event["EventType"] == "CancelEvent" # WM_CLOSE (Alt-F4)
# If Opt(:notify) is set, the CustomStatusItemSelector sends MenuEvents
# with the ID of the item the user clicked or activated via keyboard.
handle_item_click(event["ID"]) if event["EventType"] == "MenuEvent"
end
nil
end
# Handle an item click (or a keyboard action on an item).
def handle_item_click(item_id)
return if item_id.nil?
log.info("Item #{item_id} clicked")
# The ItemSelector already handled the common status transitions that we
# defined in the status definition: 0 -> 1, 1 -> 0, 2 -> 0.
#
# Now check if we need to change the status of other items because of
# dependencies to demonstrate sample business logic.
handle_dependencies
update_result
end
# Example business logic: Change the status of some of the example software
# modules based on dependencies of other modules.
def handle_dependencies
# ItemStatus return a hash ov IDs (in our case symbols) to integers (the status):
# { :mod_kde => 1, :mod_xfce => 0, :mod_x11 = 2, ... }
status = UI.QueryWidget(:modules, :ItemStatus) # Fetch current status of all items
log.info("Old status values: #{status}")
need_office = true if status[:mod_kde] == MOD_INSTALL
need_x11 = true if status[:mod_kde] == MOD_INSTALL
need_x11 = true if status[:mod_xfce] == MOD_INSTALL
need_x11 = true if status[:mod_office] == MOD_INSTALL
need_x11 = false if status[:mod_x11] == MOD_INSTALL # manually selected
need_office = false if status[:mod_office] == MOD_INSTALL # manually selected
old_status = status.select { |k, v| [:mod_x11, :mod_office].include?(k) }
new_status = old_status.dup
new_status[:mod_x11] = auto_select_status(new_status, :mod_x11, need_x11)
new_status[:mod_office] = auto_select_status(new_status, :mod_office, need_office)
log.info("Auto-modules old status: #{old_status}")
log.info("Auto-modules new status: #{new_status}")
UI.ChangeWidget(:modules, :ItemStatus, new_status) unless new_status == old_status
end
# Example business logic: Return a module's effective status based on its
# old status and a flag indicating if it is needed because of dependencies
def auto_select_status(status_map, mod, needed)
old_status = status_map[mod]
return MOD_AUTOINSTALL if needed && old_status == MOD_DONT_INSTALL
return MOD_DONT_INSTALL if !needed && old_status == MOD_AUTOINSTALL
old_status
end
# Update the "Result" field
def update_result
status = UI.QueryWidget(:modules, :ItemStatus)
status.reject! { |k, v| v == MOD_DONT_INSTALL }
actions = [ "", "Install", "Auto-install"]
result = status.collect{ |mod, stat| actions[stat] + " " + mod.to_s }
log.info("Result: #{result}")
UI.ChangeWidget(:result_field, :Value, result.join("\n"))
end
end
end
Yast::ExampleClient.new.main