src/lib/y2storage/dialogs/guided_setup/select_disks.rb
# Copyright (c) [2017] SUSE LLC
#
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, contact SUSE LLC.
#
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.
require "yast"
require "y2storage"
require "y2storage/dialogs/guided_setup/base"
module Y2Storage
module Dialogs
class GuidedSetup
# Dialog for disks selection for the proposal.
class SelectDisks < Base
def initialize(*params)
textdomain "storage"
super
end
# This dialog has to be skipped when there is only
# one candidate disk for installing.
def skip?
analyzer.candidate_disks.size == 1
end
# Before skipping, settings should be assigned.
def before_skip
settings.candidate_devices = analyzer.candidate_disks.map(&:name)
end
protected
# Maximum number of disks the user is allowed to select
MAX_DISKS = 3
# Maximum number of disks that can be displayed at the same time with
# the default interface. If that number is exceeded an alternative
# interface with scroll is displayed.
DISKS_WITHOUT_SCROLL = 10
def dialog_title
_("Select Hard Disk(s)")
end
def dialog_content
items = all_disks.map { |d| [d.name, disk_label(d)] }
label = _("Select one or more (max %d) hard disks") % MAX_DISKS
disks_widget.content(label, items)
end
def initialize_widgets
default_selected = settings.candidate_devices || []
default_selected = default_selected.map { |d| analyzer.device_by_name(d) }
default_selected = all_disks if default_selected.empty?
disks_widget.select(default_selected.first(MAX_DISKS).map(&:name))
end
def update_settings!
settings.candidate_devices = selected_disks.map(&:name)
end
def help_text
# TRANSLATORS: Help text for guided storage setup
_(
"<p>" \
"Select the disks to install on." \
"</p><p>" \
"In later dialogs, you can select which of those disks " \
"will be used for the root filesystem and what to do with " \
"any existing Linux, Windows or other partitions (keep, " \
"remove, sometimes resize)." \
"</p><p>" \
"How many of the disks you select here will actually be used " \
"depends on the exact scenario you choose (LVM, with or " \
"without separate home partition etc.)." \
"</p><p>" \
"Disks that are not selected here remain completely untouched." \
"</p>"
)
end
private
def valid?
any_selected_disk? && !many_selected_disks?
end
def any_selected_disk?
return true unless selected_disks.empty?
Yast::Report.Warning(_("At least one disk must be selected"))
false
end
def many_selected_disks?
return false if selected_disks.size <= MAX_DISKS
Yast::Report.Warning(_("At most %d disks can be selected") % MAX_DISKS)
true
end
def selected_disks
all_disks.select { |d| disks_widget.selected?(d.name) }
end
def all_disks
# Let's place the boot-optimized disks at the top of the list
@all_disks ||= analyzer.candidate_disks.partition(&:boss?).flatten
end
# Widget used to display and select the list of disks
#
# @return [DisksWidget, ScrollableDisksWidget]
def disks_widget
@disks_widget ||=
if all_disks.size > DISKS_WITHOUT_SCROLL
ScrollableDisksWidget.new
else
DisksWidget.new
end
end
# Auxiliary internal class to draw and query the list of disks in the
# default case
class DisksWidget
include Yast::UIShortcuts
# @see SelectDisks#dialog_content
#
# @param label [String] heading of the widget
# @param items [Array<Array<String>>] list of pairs (id, description)
def content(label, items)
HSquash(
VBox(
Left(Label(label)),
VSpacing(0.3),
*items.map { |item| disk_widget(item) }
)
)
end
# @see SelectDisks#initialize_widgets
def select(ids)
ids.each { |id| Yast::UI.ChangeWidget(Id(id), :Value, true) }
end
# @see SelectDisks#selected_disks
def selected?(id)
Yast::UI.QueryWidget(Id(id), :Value)
end
protected
# @see #content
def disk_widget(item)
Left(CheckBox(Id(item.first), item.last))
end
end
# Auxiliary internal class to draw and query the list of disks when
# there are so many disks that the default widget cannot deal with it
class ScrollableDisksWidget
include Yast::UIShortcuts
# @see SelectDisks#dialog_content
#
# @param label [String] heading of the widget
# @param items [Array<Array<String>>] list of pairs (id, description)
def content(label, items)
MarginBox(
2, 1,
MultiSelectionBox(
Id(:disks),
label,
items.map { |item| Item(Id(item.first), item.last) }
)
)
end
# @see SelectDisks#initialize_widgets
def select(ids)
Yast::UI.ChangeWidget(Id(:disks), :SelectedItems, ids)
end
# @see SelectDisks#selected_disks
def selected?(id)
Yast::UI.QueryWidget(Id(:disks), :SelectedItems).include?(id)
end
end
end
end
end
end