ACC SHELL
/**
* Module: inst_resize_dialog.ycp
*
* Authors: Thomas Roelz <tom@suse.de>
* Stefan Hundhammer <sh@suse.de>
* Jiri Srain
*
* Purpose: UI for setting how to split the disk between existing Windows and Linux
*
* FIXME: Get rid of code duplication between here and inst_resize_ui (resizing partition from a proposal)
*
*
* $Id: inst_resize_dialog.ycp 52739 2008-10-30 13:59:13Z aschnell $
*/
{
textdomain "storage";
import "Mode";
import "Storage";
import "Popup";
import "Partitions";
import "Wizard";
import "Installation";
import "StorageProposal";
include "partitioning/partition_defines.ycp";
list<integer> DiskUsage (string win_device) {
integer win_used = -1;
integer win_free = -1;
boolean mount_result = (boolean)SCR::Execute( .target.mount,
[ win_device, Installation::scr_destdir,
Installation::mountlog ]);
if( !mount_result ) {
y2error( "Current Windows device <%1> could not be mounted. Canceled", win_device );
}
else
{
y2milestone( "Current Windows device <%1> mounted on %2.", win_device, Installation::scr_destdir );
}
// get usage information for the partition via df
list<map> df_result = (list<map>)SCR::Read(.run.df);
SCR::Execute(.target.umount, win_device);
y2debug( ".run.df: %1", df_result );
// filter out headline and other invalid entries
df_result = filter( map part, df_result,
``( substring( part["spec"]:"", 0, 1 ) == "/" ));
foreach( map part, df_result, {
if( part["spec"]:"" == win_device ) // find right entry
{
// get the usage values
//
win_used = tointeger(part["used"]:"-1");
win_free = tointeger(part["free"]:"-1");
if( win_used != -1 && win_free != -1 ) {
win_used = win_used / 1024; // MB
win_free = win_free / 1024; // MB
y2milestone( ".run.df: win_used: <%1> win_free:<%2>", win_used, win_free );
}
}
});
return [ win_used, win_free ];
}
map _resize_result = nil;
map ResizeResult() {
return _resize_result;
}
symbol ResizeDialog (string win_device, integer cyl_size, map win_partition) {
/////////////////////////////////////////////////////////////////////////
// START: Initialize
/////////////////////////////////////////////////////////////////////////
boolean test_mode = Mode::test ();
boolean demo_mode = Mode::test ();
// store
//
integer win_used = -1;
integer win_free = -1;
integer min_win_free = -1;
integer new_win_size = -1;
integer linux_size = -1;
integer linux_min = 400; // this is the base value for space calculations (minimum installation)
if ( test_mode ) // not just in demo mode! no HW probe in test mode!
{
win_used = 350;
win_free = 1500;
min_win_free = 50;
linux_size = 800;
linux_min = 400;
}
/////////////////////////////////////////////////////////////////////////
// END: Initialize
/////////////////////////////////////////////////////////////////////////
y2milestone( "Cylinder size of target: <%1>", cyl_size );
// Get region from win partition
//
list<integer> region = win_partition["region"]:[];
if( size( region ) != 2 ) {
y2error( "Invalid region <%1> in Windows partition data struct.", region );
return nil;
} else
y2milestone( "Old region <%1> OK in Windows partition data struct.", region );
// mount the partition to execute some checks
//
list<integer> usage = DiskUsage (win_device);
win_used = usage[0]:-1;
win_free = usage[1]:-1;
if( win_used == -1 || win_free == -1 ) {
y2error( "The sizes for device <%1> could not be examined.", win_device );
return nil;
} else {
// Apply some checks to determine if installing Linux is feasible at all.
//
boolean feasible = true;
// Set minimal free Windows size to 200 MB. Running Windows with
// less disk space is no fun.
//
if ( min_win_free < 200 ) min_win_free = 200;
// If this is more than the free space on the device Windows is already
// overcrowded and Linux shouldn't be installed.
//
if ( min_win_free > win_free ) return nil;
if( win_free - min_win_free < linux_min ) return nil;
// Try to reserve 1.5 GB for linux (default installation).
// Otherwise get as much as possible
//
if ( win_free - min_win_free > 1500 )
linux_size = 1500;
else
linux_size = win_free - min_win_free;
}
if (Storage::resize_partition != nil) // already resized
{
integer win_size = Storage::resize_partition_data["region",1]:-1;
y2internal ("Win size read: %1", win_size);
y2internal ("Part info: %1", Storage::resize_partition_data);
y2internal ("Cyl size: %1", Storage::resize_cyl_size);
if (win_size != -1)
{
win_size = win_size * Storage::resize_cyl_size / (1024*1024);
linux_size = win_used + win_free - win_size;
}
}
/////////////////////////////////////////////////////////////////////////
// END: Preliminary action
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
// START: GUI
/////////////////////////////////////////////////////////////////////////
boolean test_simple_ui = false; // set to "true" to test non-graphical version
// Unit for parition resizing - currently Megabytes
string unit = _("MB");
// Labels for bar graph. "%1" will be replace with a numeric value.
string bargraph_label_win_used = _("Windows\nUsed\n%1 ") + unit;
// Labels for bar graph. "%1" will be replace with a numeric value.
string bargraph_label_win_free = _("Windows\nFree\n%1 ") + unit;
// Labels for bar graph. "%1" will be replace with a numeric value.
string bargraph_label_linux = _("Linux\n%1 ") + unit;
// Labels for input fields. "%1" will be replaced with the current unit (MB).
string field_label_win_free = sformat( _("Windows Free (%1)"), unit);
// Labels for input fields. "%1" will be replaced with the current unit (MB).
string field_label_linux = sformat( _("Linux (%1)"), unit);
term contents = `Empty();
// Help text for Windows partition resizing -
// common part for both graphical mode (with bar graphs)
// and non-graphical mode (text only).
string helptext = _("<p>
Choose the new size for your Windows partition.
</p>");
// help text (common to both modes), continued
helptext = helptext + _("
<p>
The actual resizing will be performed only after you confirm all your
settings in the last installation dialog. Until then, your Windows
partition will remain untouched.
</p>");
// help text (common to both modes), continued
helptext = helptext + _("
<p>
To skip resizing your Windows partition, press
<b>Back</b>.
</p>
");
if ( UI::HasSpecialWidget(`Slider ) &&
UI::HasSpecialWidget(`BarGraph ) &&
! test_simple_ui )
{
contents = `VBox(
`VStretch(),
// Headline above bar graph that displays current windows partition size
`Left( `Label( _("Now")) ),
`BarGraph(
[ win_used, win_free ],
[
bargraph_label_win_used,
bargraph_label_win_free
]
),
`VStretch(),
// Headline above bar graph that displays future windows and linux partitions
`Left( `Label( _("After Installation") ) ),
`PartitionSplitter( `id(`linux_size),
win_used, win_free,
linux_size, linux_min, min_win_free,
bargraph_label_win_used,
bargraph_label_win_free,
bargraph_label_linux,
field_label_win_free,
field_label_linux
),
`VStretch()
);
// help text, continued - graphical mode only
// this help text will be appended to the help text common to both modes.
helptext = helptext + _("
<p>
The upper bar graph displays the current situation.
The lower bar graph displays the situation after the installation (after
the partition resize).
</p>
");
// help text (graphical mode), continued
helptext = helptext + _("
<p>
Drag the slider or enter a numeric value in either
input field to adjust the suggested value.
</p>");
// help text (graphical mode), continued
helptext = helptext + _("
<p>
Within the space you reserve for Linux, partitions will automatically be
created as necessary.
</p>");
}
else // no special widgets -> simple fallback UI
{
contents = `HVSquash(
`VBox(
`HBox(
// Label for used part of the Windows partition in non-graphical mode
`HWeight(3, `Right(`Label(_("Windows Used")))),
`HWeight(2, `Label(`opt(`outputField), sformat("%1", win_used ))),
`HWeight(3, `Left(`Label( unit )))
),
`VSpacing(0.5),
`HBox(
// Label for free part of the Windows partition in non-graphical mode
`HWeight(3, `Right(`Label(_("Free")))),
`HWeight(2, `Label(`opt(`outputField), sformat("%1", win_free ))),
`HWeight(3, `Left(`Label( unit )))
),
`VSpacing(0.5),
`HBox(
// Edit field label for linux partition size in non-graphical mode
`HWeight(3, `Right(`Bottom(`Label(_("Linux"))))),
`HWeight(2, `IntField( `id(`linux_size),
"", // label (above)
linux_min, // min
win_free - min_win_free, // max
linux_size // initial
)
),
`HWeight(3, `Left(`Bottom(`Label( unit ))))
)
)
);
// help text, continued - non-graphical mode only
// this help text will be appended to the help text common to both modes.
helptext = helptext + _("
<p>Enter a value for the size of your <b>Linux</b> installation.
The partitions will automatically be created within this range
as required for &product;.
</p>
");
// help text (non-graphical mode), continued
helptext = helptext + _("
<p>
<b>Windows Used</b> is the size of the used part of your Windows partition.
</p>");
// help text (non-graphical mode), continued
helptext = helptext + _("
<p><b>Free</b> indicates the current free space (before the Linux
installation) on the partition.
</p>");
}
y2internal ("Opening dialog");
Wizard::SetContents( // Set the dialog header
_("Resizing the Windows Partition"),
contents, helptext, true, true);
/////////////////////////////////////////////////////////////////////////
// END: GUI
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
// START: Main loop
/////////////////////////////////////////////////////////////////////////
symbol ret = nil;
repeat {
ret = (symbol)Wizard::UserInput();
if( ret == `abort && Popup::ReallyAbort(true) )
return `abort;
if( ret == `next )
{
// Get the value the user adjusted. If s/he entered a value
// too big or too small this is automatically adjusted to the
// biggest/smallest value possible (by Qt).
//
linux_size = (integer)UI::QueryWidget(`id(`linux_size), `Value);
new_win_size = win_used + win_free - linux_size;
y2milestone( "Linux size: <%1> - New Win size: <%2>",
linux_size, new_win_size);
}
if( ret == `back )
{
return `back;
}
} until ( ret == `next || ret == `back || ret == `cancel );
/////////////////////////////////////////////////////////////////////////
// END: Main loop
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
// START: Final action
/////////////////////////////////////////////////////////////////////////
// Now update the target map to the new situation
//
if( !test_mode ) {
// adjust the partition entry in the target map to reflect the new size
// add flag and new size to the windows partition
//
win_partition = add( win_partition, "resize", true );
// adjust the region list in the windows partition to reflect the new size
//
integer win_start = region[0]:0; // same as before resize
y2internal ("Win size: %1", new_win_size);
y2internal ("Cylinder: %1", cyl_size);
integer new_length_i = PartedSizeToCly( (tofloat(new_win_size) * 1024.0 * 1024.0), cyl_size );
region = [win_start, new_length_i];
win_partition = add( win_partition, "region", region);
y2milestone( "New region of Windows partition after resize: <%1>", region );
_resize_result = win_partition;
return `next;
}
/////////////////////////////////////////////////////////////////////////
// END: final action
/////////////////////////////////////////////////////////////////////////
return ret;
}
// main function
if (Storage::resize_partition == nil) {
Storage::ResetOndiskTarget();
Storage::AddMountPointsForWin(Storage::GetTargetMap());
StorageProposal::get_inst_prop(Storage::GetTargetMap());
if (Storage::resize_partition == nil) // no resize
{
Storage::ResetOndiskTarget();
Storage::resize_partition = "";
return `auto;
}
}
if (Storage::resize_partition == "") {
return `auto;
}
symbol ret = ResizeDialog (Storage::resize_partition, Storage::resize_cyl_size, Storage::resize_partition_data);
if (ret == `next)
{
// store info about partition resize needed for the proposal
Storage::resize_partition_data = ResizeResult();
// reset proposal, recreate it
Storage::ResetOndiskTarget();
Storage::AddMountPointsForWin(Storage::GetTargetMap());
map prop = $[];
prop = StorageProposal::get_inst_prop(Storage::GetTargetMap());
y2milestone( "prop ok:%1", prop["ok"]:false );
if( prop["ok"]:false ) {
Storage::SetTargetMap( prop["target"]:$[] );
Storage::SetPartProposalMode( "accept" );
y2milestone( "PROPOSAL: %1", Storage::ChangeText());
} else {
Storage::SetPartProposalMode( "impossible" );
}
Storage::SetPartProposalFirst( false );
Storage::SetPartProposalActive( true );
y2milestone( "prop=%1", prop );
}
return ret;
}
ACC SHELL 2018