Class: Installation::ProposalStore
- Inherits:
-
Object
- Object
- Installation::ProposalStore
- Includes:
- Yast::I18n, Yast::Logger
- Defined in:
- src/lib/installation/proposal_store.rb
Overview
- Provides access to metadata of proposal parts (clients), as defined in the control file elements /productDefines/proposals/proposal: https://github.com/yast/yast-installation-control/blob/master/control/control.rnc
- Handles all calls to the parts (clients).
Constant Summary collapse
- MAX_LOOPS_IN_PROPOSAL =
How many times to maximally (re)run the proposal while some proposal clients try to re-trigger their run again, number includes their initial run and resets before each proposal loop starts
8
Instance Method Summary collapse
- #can_be_skipped? ⇒ Boolean
-
#client_for_link(link) ⇒ String
Returns client name that handles the given link returned by UI, raises exception if link is unknown.
-
#description_for(client) ⇒ Hash
Calls a given client/part to retrieve their description.
-
#descriptions ⇒ Hash
Returns all currently cached client descriptions.
-
#handle_link(link) ⇒ Object
Calls client('AskUser'), to change a setting interactively (if link is the heading for the part) or noninteractively (if it is a "shortcut").
-
#hard_read_only?(client) ⇒ Boolean
Checks if the client's proposal is configured as "hard" read-only.
-
#headline ⇒ String
Translated headline.
-
#help_text(current_tab = nil) ⇒ String
Richtext, the complete help text: a common intro + all individual parts.
-
#id_for(client) ⇒ String
Returns ID for given client.
-
#initialize(proposal_mode) ⇒ ProposalStore
constructor
A new instance of ProposalStore.
-
#make_proposals(force_reset: false, language_changed: false, callback: proc {}) ⇒ Object
Makes proposal for all proposal clients.
-
#presentation_order ⇒ Object
returns single list of modules presentation order or list of tabs with list of modules.
-
#proposal_names ⇒ Array<String>
Proposal names in execution order, including the "_proposal" suffix.
-
#read_only?(client) ⇒ Boolean
Checks if the client's proposal is configured as "hard" or "soft" read-only.
-
#read_only_proposals ⇒ Hash
Reads read-only proposals from the control file.
-
#soft_read_only?(client) ⇒ Boolean
Checks if the client's proposal is configured as "soft" read-only.
-
#tab_labels ⇒ Array<String>
Translated tab labels.
- #tabs? ⇒ Boolean
-
#title_for(client) ⇒ String
Returns UI title for given client.
Constructor Details
#initialize(proposal_mode) ⇒ ProposalStore
Returns a new instance of ProposalStore.
38 39 40 41 42 43 44 45 46 47 |
# File 'src/lib/installation/proposal_store.rb', line 38 def initialize(proposal_mode) Yast.import "Mode" Yast.import "ProductControl" Yast.import "Stage" Yast.import "Report" textdomain "installation" @proposal_mode = proposal_mode end |
Instance Method Details
#can_be_skipped? ⇒ Boolean
87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'src/lib/installation/proposal_store.rb', line 87 def can_be_skipped? return @can_skip unless @can_skip.nil? @can_skip = if properties.key?("enable_skip") log.info "properties skip available #{properties["enable_skip"].inspect}." properties["enable_skip"] == "yes" else !["initial", "uml"].include?(@proposal_mode) end log.info "can skip set to #{@can_skip.inspect}." @can_skip end |
#client_for_link(link) ⇒ String
Returns client name that handles the given link returned by UI, raises exception if link is unknown. Link can be either the client ID or a shortcut link from proposal text.
304 305 306 307 308 309 310 311 312 313 314 315 316 |
# File 'src/lib/installation/proposal_store.rb', line 304 def client_for_link(link) if @proposals.nil? raise "There are no client proposals known, call 'client(MakeProposal)' first" end matching_client = @proposals.find do |_client, proposal| link == proposal["id"] || proposal.fetch("links", []).include?(link) end raise "Unknown user request #{link}. Broken proposal client?" if matching_client.nil? matching_client.first end |
#description_for(client) ⇒ Hash
Calls a given client/part to retrieve their description
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'src/lib/installation/proposal_store.rb', line 190 def description_for(client) @descriptions ||= {} return @descriptions[client] if @descriptions.key?(client) description = Yast::WFM.CallFunction(client, ["Description", {}]) return nil if description.nil? || description.empty? unless description.key?("id") log.warn "proposal client #{client} is missing key 'id' in #{description}" @missing_no ||= 1 description["id"] = "module_#{@missing_no}" @missing_no += 1 end @descriptions[client] = description end |
#descriptions ⇒ Hash
Returns all currently cached client descriptions
211 212 213 |
# File 'src/lib/installation/proposal_store.rb', line 211 def descriptions @descriptions ||= {} end |
#handle_link(link) ⇒ Object
Calls client('AskUser'), to change a setting interactively (if link is the heading for the part) or noninteractively (if it is a "shortcut")
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'src/lib/installation/proposal_store.rb', line 279 def handle_link(link) client = client_for_link(link) if read_only?(client) log.warn "Proposal client #{client.inspect} is read-only, ignoring the user action" # TRANSLATORS: Warning message, can be split to more lines if needed Yast::Report.Warning(_("This proposed setting is marked as read-only\n" \ "and cannot be changed.")) return nil end data = { "has_next" => false, "chosen_id" => link } Yast::WFM.CallFunction(client, ["AskUser", data]) end |
#hard_read_only?(client) ⇒ Boolean
Checks if the client's proposal is configured as "hard" read-only
"hard" read-only means that the proposal is always read-only "soft" read-only means that the proposal is made changeable when an error in proposal is detected.
261 262 263 |
# File 'src/lib/installation/proposal_store.rb', line 261 def hard_read_only?(client) read_only_proposals[:hard].include?(client) end |
#headline ⇒ String
Returns translated headline.
50 51 52 53 54 55 56 57 58 59 |
# File 'src/lib/installation/proposal_store.rb', line 50 def headline if properties["label"] Yast::Builtins.dgettext( Yast::ProductControl.getProposalTextDomain, properties["label"] ) else _("Installation Overview") end end |
#help_text(current_tab = nil) ⇒ String
Returns Richtext, the complete help text: a common intro + all individual parts.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'src/lib/installation/proposal_store.rb', line 63 def help_text(current_tab = nil) # General part of the help text for all types of proposals how_to_change = _( "<p>\n" \ "Change the values by clicking on the respective headline\n" \ "or by using the <b>Change...</b> menu.\n" \ "</p>\n" ) # Help text for installation proposal, continued not_modified = _( "<p>\n" \ "Your hard disk has not been modified yet. You can still safely abort.\n" \ "</p>\n" ) help_text = global_help + how_to_change help_text += not_modified if @proposal_mode == "initial" help_text << modules_help(current_tab) help_text end |
#id_for(client) ⇒ String
Returns ID for given client
218 219 220 |
# File 'src/lib/installation/proposal_store.rb', line 218 def id_for(client) description_for(client).fetch("id", client) end |
#make_proposals(force_reset: false, language_changed: false, callback: proc {}) ⇒ Object
Makes proposal for all proposal clients.
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'src/lib/installation/proposal_store.rb', line 156 def make_proposals(force_reset: false, language_changed: false, callback: proc {}) clear_proposals # At first run, all clients will be called call_proposals = proposal_names log.info "Proposals to call: #{call_proposals}" loop do call_proposals.each do |client| description_map = make_proposal(client, force_reset: force_reset, language_changed: language_changed, callback: callback) break unless parse_description_map(client, description_map, force_reset, callback) end # Second and next runs: only triggered clients will be called call_proposals = proposal_names.select { |client| should_be_called_again?(client) } break if call_proposals.empty? log.info "These proposals want to be called again: #{call_proposals}" unless should_run_proposals_again?(call_proposals) log.warn "Too many loops in proposal, exiting" break end end log.info "Making proposals have finished" end |
#presentation_order ⇒ Object
returns single list of modules presentation order or list of tabs with list of modules
147 148 149 150 151 |
# File 'src/lib/installation/proposal_store.rb', line 147 def presentation_order return @modules_order if @modules_order tabs? ? order_with_tabs : order_without_tabs end |
#proposal_names ⇒ Array<String>
Returns proposal names in execution order, including the "_proposal" suffix.
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 |
# File 'src/lib/installation/proposal_store.rb', line 119 def proposal_names return @proposal_names if @proposal_names @proposal_names = Yast::ProductControl.getProposals( Yast::Stage.stage, Yast::Mode.mode, @proposal_mode ) @proposal_names.map!(&:first) # first element is name of client missing_proposals = @proposal_names.reject { |proposal| Yast::WFM::ClientExists(proposal) } unless missing_proposals.empty? log.warn "These proposals are missing on system: #{missing_proposals}" end # Filter missing proposals out @proposal_names -= missing_proposals unavailable_proposals = @proposal_names.select { |name| description_for(name).nil? } unless unavailable_proposals.empty? log.info "These proposals report itself as unavailable: #{unavailable_proposals}" end @proposal_names -= unavailable_proposals end |
#read_only?(client) ⇒ Boolean
Checks if the client's proposal is configured as "hard" or "soft" read-only
"hard" read-only means that the proposal is always read-only "soft" read-only means that the proposal is made changeable when an error
249 250 251 |
# File 'src/lib/installation/proposal_store.rb', line 249 def read_only?(client) hard_read_only?(client) || soft_read_only?(client) end |
#read_only_proposals ⇒ Hash
Reads read-only proposals from the control file
of proposals with "hard" or "soft" read_only flag set.
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 |
# File 'src/lib/installation/proposal_store.rb', line 322 def read_only_proposals return @read_only_proposals if @read_only_proposals @read_only_proposals = { hard: [], soft: [] } properties.fetch("proposal_modules", []).each do |proposal| next unless proposal["read_only"] name = full_module_name(proposal["name"]) ro_type = proposal["read_only"] case ro_type when "hard" @read_only_proposals[:hard] << name when "soft" @read_only_proposals[:soft] << name else log.info("Uknown value for read_only node: #{ro_type}") end end log.info "Found read-only proposals: #{@read_only_proposals}" @read_only_proposals end |
#soft_read_only?(client) ⇒ Boolean
Checks if the client's proposal is configured as "soft" read-only
"hard" read-only means that the proposal is always read-only "soft" read-only means that the proposal is made changeable when an error in proposal is detected.
273 274 275 |
# File 'src/lib/installation/proposal_store.rb', line 273 def soft_read_only?(client) read_only_proposals[:soft].include?(client) end |
#tab_labels ⇒ Array<String>
Returns translated tab labels.
108 109 110 111 112 113 114 115 |
# File 'src/lib/installation/proposal_store.rb', line 108 def tab_labels return @tab_labels if @tab_labels raise "Invalid call to tab_labels for proposal without tabs" unless tabs? tabs = properties["proposal_tabs"] @tab_labels = tabs.map { |m| m["label"] } end |
#tabs? ⇒ Boolean
102 103 104 |
# File 'src/lib/installation/proposal_store.rb', line 102 def tabs? properties.key?("proposal_tabs") end |
#title_for(client) ⇒ String
Returns UI title for given client
226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'src/lib/installation/proposal_store.rb', line 226 def title_for(client) description = description_for(client) title = description["rich_text_title"] || description["rich_text_raw_title"] || client return title unless read_only?(client) # remove any HTML links if the proposal is read only, # use the non-greedy .*? repetition to handle # the "<a>foo</a> <a>bar</a>" case correctly title.gsub(/<a.*?>(.*?)<\/a>/, "\\1") end |