ACC SHELL

Path : /usr/share/YaST2/clients/
File Upload :
Current File : //usr/share/YaST2/clients/inst_resize_dialog.ycp

/**
 * 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