Mailinglist Archive: yast-devel (105 mails)

< Previous Next >
[yast-devel] Hackweek: Unified Installation Progress
  • From: Stanislav Visnovsky <visnov@xxxxxxx>
  • Date: Mon, 1 Sep 2008 09:29:59 +0200
  • Message-id: <200809010929.59815.visnov@xxxxxxx>
Hi Hackers!

So, Hackweek III is over and here is the result of my work - a grand unified
installation progress.

Global progress
===============
The basic idea is that the progress consists "stages" - during a new install,
there are 3: disk preparation, image deployment and package installation.

Before the first client using the unified progress, the stages need to be set
up, e.g. :

list< map<string,any> > stages = [
$[
"name" : "disk",
"description": _("Preparing disks..."),
"value" : Mode::update() ? 0 : 120, // 2 minutes, who needs more? ;-)
"units" : `sec,
],
$[
"name" : "images",
"description": _("Deploying Images..."),
"value" : ImageInstallation::TotalSize() / 1024, // kilobytes
"units" : `kb,
],
$[
"name" : "packages",
"description": _("Installing Packages..."),
// here, we do a hack, because until images are deployed, we cannot
determine how many
// packages will be really installed additionally
"value" : (PackageSlideShow::total_size_to_install -
ImageInstallation::TotalSize()) / 1024 , // kilobytes
"units" : `kb,
],
];

SlideShow::Setup( stages );

The function will calculate the partitioning of the unified progress based on
estimate of a needed time. A stage can provide the estimate of time or an
amount of data to be transferred (the constants used are based on assumption
of 15 min install time and that the data are downloaded and written to disk).
The logic is no rocket science as the only goal for a progress bar is to have
it move somewhat regularly.

A client using the new unified progress will do basically 2 things:

1) calls SlideShow::MoveToStage( stage-id )
- this will move the global progress to a proper position for start of the
stage and updates also the label ("description" entry in the map)

2) calls regularly SlideShow::StageProgress( new_percent, new_label )
- new_percent is the progress inside of the current stage, the library will
recompute this to get a global progress percents.
- if new_label is nil, label is not updated.

More functionality
==================
The SlideShow dialog contains the following functionality:
- global progress (see above)
- subprogress for the current action (e.g. download a package, format
disk, ...)
- installation log
- slide show support
- optional package table
- release notes viewer

See the SlideShow API how to handle those.

Implementation Notes
====================
During the hacking, I've splitted the old SlideShow module into 3:
- Slides.ycp - handling of slide loading from the installation medium
- SlideShow.ycp - generic API for the unified installation progress
- PackageSlideShow - code specific for handling package installation, e.g.
CDs, summary table, ....

Attached are the complete new modules as diffs do not make much sense.
Next, there is updated control.xml with a new installation client
inst_prepareprogress which sets up the stages for normal installation.
The rest are diffs for adapting to new APIs. Influenced code is in
yast2-installation, yast2-packager and yast2-storage

I've tested the code on modified alpha2 - new installation, update and also on
running system. Qt and ncurses.

Stano
/**
* Module: PackageSlideShow.ycp
*
* Purpose: Module to access slides from installation repository
*
* Author: Stefan Hundhammer <sh@xxxxxxx>
* Stanislav Visnovsky <visnov@xxxxxxx>
*
*/
{
module "PackageSlideShow";

textdomain "packager";

import "Slides";
import "SlideShow";
import "String";

global list<list<integer> > total_sizes_per_cd_per_src = []; //
total sizes per inst-src: [ [42, 43, 44], [12, 13, 14] ]
global list<list<integer> > remaining_sizes_per_cd_per_src = []; //
remaining sizes
global list<list<integer> > remaining_times_per_cd_per_src = []; //
remaining times
global list<string> inst_src_names = []; // a
list of strings identifying each repository
global list<list<integer> > total_pkg_count_per_cd_per_src = []; //
number of pkgs per inst-src: [ [7, 5, 3], [2, 3, 4] ]
global list<list<integer> > remaining_pkg_count_per_cd_per_src = []; //
remaining number of pkgs
global map<integer,integer> srcid_to_current_src_no = $[];
// the string is follwed by a media number, e.g. "Medium 1"
global string media_type = _("Medium");
global integer total_size_installed = 0;
global integer total_size_to_install = 0;
global integer min_time_per_cd = 10; // const - minimum time
displayed per CD if there is something to install
global integer max_time_per_cd = 7200; // const - seconds to
cut off predicted time (it's bogus anyway)
global integer size_column = 1; // const - column
number for remaining size per CD
global integer pkg_count_column = 2; // const - column
number for remaining number of packages per CD
global integer time_column = 3; // const - column
number for remaining time per CD
global integer current_src_no = -1; // 1..n
global integer current_cd_no = -1; // 1..n
global integer next_src_no = -1;
global integer next_cd_no = -1;
global boolean last_cd = false;
global integer total_cd_count = 0;
global boolean unit_is_seconds = false; // begin with
package sizes
global integer bytes_per_second = 1;
global boolean init_pkg_data_complete = false;

boolean debug = false; // more
debugging info
string provide_name = ""; // currently
downlaoded package name
string provide_size = ""; // currently
downlaoded package size


/*****************************************************************************/
/*************** Formatting functions and helpers ***************************/
/*****************************************************************************/

/**
* Get version info for a package (without build no.)
*
* @param pkg_name name of the package without path and ".rpm" extension
* @return version string
**/
global string StripReleaseNo( string pkg_name )
{
integer build_no_pos = findlastof (pkg_name, "-" ); // find
trailing build no.

if ( build_no_pos != nil && build_no_pos > 0 )
{
// cut off trailing build no.
pkg_name = substring( pkg_name , 0, build_no_pos );
}

return pkg_name;
}

/**
* Get package file name from path
*
* @param pkg_name location of the package
* @return string package file name
**/
global string StripPath(string pkg_name)
{
if (pkg_name == nil)
{
return nil;
}

integer file_pos = findlastof(pkg_name, "/");

if (file_pos != nil && file_pos > 0 )
{
// return just the file name
pkg_name = substring(pkg_name, file_pos + 1);
}

return pkg_name;
}


/**
* set media type "CD" or "DVD"
*/
global void SetMediaType (string new_media_type)
{
media_type = new_media_type;
}

/**
* Sum up all list items
**/
integer ListSum( list<integer> sizes )
{
integer sum = 0;

foreach( integer item, sizes, ``{
if ( item != -1 )
sum = sum + item;
});

return sum;
}


/**
* Sum up all positive list items, but cut off individual items at a
maximum value.
* Negative return values indicate overflow of any individual item at
"max_cutoff".
* In this case, the real sum is the absolute value of the return value.
**/
integer ListSumCutOff( list<integer> sizes, integer max_cutoff )
{
boolean overflow = false;
integer sum = 0;

foreach( integer item, sizes, ``{
if ( item > 0 )
{
if ( item > max_cutoff )
{
overflow = true;
sum = sum + max_cutoff;
}
else
sum = sum + item;
}
});

if ( overflow )
sum = -sum;

return sum;
}


integer TotalRemainingSize()
{
return ListSum( flatten( remaining_sizes_per_cd_per_src ) );
}


integer TotalRemainingTime()
{
return ListSumCutOff( flatten( remaining_times_per_cd_per_src ),
max_time_per_cd );
}


integer TotalRemainingPkgCount()
{
return ListSum( flatten( remaining_pkg_count_per_cd_per_src ) );
}


integer TotalInstalledSize()
{
return total_size_to_install - TotalRemainingSize();
}


/**
* Format an integer number as (at least) two digits; use leading zeroes if
* necessary.
* @return number as two-digit string
**/
string FormatTwoDigits( integer x )
{
return x < 10 && x >= 0 ?
sformat( "0%1", x ) :
sformat( "%1", x );
}


/**
* Format an integer seconds value with min:sec or hours:min:sec
**/
string FormatTime( integer seconds )
{
if ( seconds < 0 )
return "";

if ( seconds < 3600 ) // Less than one hour
{
return sformat( "%1:%2", FormatTwoDigits( seconds / 60 ),
FormatTwoDigits( seconds % 60 ) );
}
else // More than one hour - we don't hope this will ever happen,
but who knows?
{
integer hours = seconds / 3600;
seconds = seconds % 3600;
return sformat( "%1:%2:%3", hours, FormatTwoDigits( seconds / 60 ),
FormatTwoDigits( seconds % 60 ) );
}
}


/**
* Format an integer seconds value with min:sec or hours:min:sec
*
* Negative values are interpreted as overflow - ">" is prepended and the
* absolute value is used.
**/
string FormatTimeShowOverflow( integer seconds )
{
string text = "";

if ( seconds < 0 ) // Overflow (indicated by negative value)
{
// When data throughput goes downhill (stalled network connection
etc.),
// cut off the predicted time at a reasonable maximum.
// "%1" is a predefined maximum time.

text = sformat( _(">%1"), FormatTime( -seconds ) );
}
else
{
text = FormatTime( seconds );
}

return text;
}


/**
* Format number of remaining bytes to be installed as string.
* @param remaining bytes remaining, -1 for 'done'
* @return string human readable remaining time or byte /
kB/ MB size
**/
string FormatRemainingSize( integer remaining )
{
if ( remaining < 0 )
{
// Nothing more to install from this CD (very concise - little
space!!)
return _("Done.");
}
if ( remaining == 0 )
{
return "";
}

return String::FormatSize( remaining );
}


/**
* Format number of remaining packages to be installed as string.
* @param remaining bytes remaining, -1 for 'done'
* @return string human readable remaining time or byte /
kB/ MB size
**/
string FormatRemainingCount( integer remaining )
{
if ( remaining < 0 )
{
// Nothing more to install from this CD (very concise - little
space!!)
return _("Done.");
}
if ( remaining == 0 )
{
return "";
}

return sformat( "%1", remaining );
}


string FormatNextMedia()
{
string text = "";

if ( next_src_no >= 0 && next_cd_no >= 0 )
{
string next_media_name = sformat( "%1 %2 %3",
inst_src_names[ next_src_no ]:"",
media_type, next_cd_no+1 );

if ( unit_is_seconds )
{
// Status line informing about the next CD that will be used
// %1: Media type ("CD" / "DVD", ???)
// %2: Media name ("SuSE Linux Professional CD 2" )
// %3: Time remaining until this media will be needed
text = sformat( _("Next %1: %2 -- %3"), media_type,
next_media_name,
FormatTime( remaining_times_per_cd_per_src[
current_src_no-1, current_cd_no-1 ]: 1) );
}
else
{
// Status line informing about the next CD that will be used
// %1: Media type ("CD" / "DVD", ???)
// %2: Media name ("SuSE Linux Professional CD 2" )
text = sformat( _("Next %1: %2"), media_type, next_media_name );
}
}

return text;
}

/*****************************************************************************/
/*********************** Computing Helpers **********************************/
/*****************************************************************************/


/**
* Perform sanity check for correct initialzation etc.
* @param silent don't complain in log file
* @return true if OK, false if any error
**/
boolean SanityCheck( boolean silent )
{
return true; // FIXME!
if ( ! init_pkg_data_complete )
{
if ( ! silent )
{
y2error( "SlideShow::SanityCheck(): Slide show not correctly
initialized: " +
"SlideShow::InitPkgData() never called!" );
}
return false;
}

if ( current_src_no < 1 || current_cd_no < 1 )
{
// nothing to install but something is going to be deleted, so it's
OK
if (Pkg::IsAnyResolvable(`package, `to_remove))
{
return true;
}
else if (!silent)
{
y2error(-1, "SlideShow::SanityCheck(): Illegal values for
current_src (%1) or current_cd (%2)",
current_src_no, current_cd_no );
y2milestone( "total sizes: %1", total_sizes_per_cd_per_src );
}
return false;
}

return true;
}

/**
* Update internal bookkeeping: subtract size of one package from the
* global list of remaining sizes per CD
**/
void SubtractPackageSize( integer pkg_size )
{
integer remaining = remaining_sizes_per_cd_per_src [ current_src_no-1,
current_cd_no-1 ]: 1;
remaining = remaining - pkg_size;
total_size_installed = total_size_installed + pkg_size;

if ( remaining <= 0 )
{
// -1 is the indicator for "done with this CD" - not to be
// confused with 0 for "nothing to install from this CD".
remaining = -1;
}

remaining_sizes_per_cd_per_src [ current_src_no-1, current_cd_no-1 ] =
remaining;
remaining_pkg_count_per_cd_per_src [ current_src_no-1, current_cd_no-1
] =
remaining_pkg_count_per_cd_per_src [ current_src_no-1,
current_cd_no-1 ]:0 -1;

if ( unit_is_seconds )
{
integer seconds = 0;

if ( remaining > 0 && bytes_per_second > 0 )
seconds = remaining / bytes_per_second;

remaining_times_per_cd_per_src [ current_src_no-1, current_cd_no-1
] = seconds;
}

if ( debug )
y2milestone( "SubtractPackageSize( %1 ) -> %2", pkg_size,
remaining_sizes_per_cd_per_src);
}


/**
* Initialize internal pacakge data, such as remaining package sizes and
* times. This may not be called before the pkginfo server is up and
* running, so this cannot be reliably done from the constructor in all
* cases.
* @param force true to force reinitialization
**/
global void InitPkgData(boolean force)
{
if ( init_pkg_data_complete && ! force)
return;

// Reinititalize some globals (in case this is a second run)
total_size_installed = 0;
//total_time_elapsed = 0;
//start_time = -1;
current_src_no = -1; // 1..n
current_cd_no = -1; // 1..n
next_src_no = -1;
next_cd_no = -1;
last_cd = false;
unit_is_seconds = false; // begin with package sizes
bytes_per_second = 1;

list< list > src_list = Pkg::PkgMediaNames();
inst_src_names = maplist( list src, src_list, ``(src[0]:"CD") );

y2milestone ("Media names: %1", inst_src_names);

integer index = 0;

srcid_to_current_src_no = listmap( list src, src_list, {
index = index + 1;
return $[src[1]:-1 : index];
});

y2milestone ("Repository mapping information: %1",
srcid_to_current_src_no );

total_sizes_per_cd_per_src = Pkg::PkgMediaSizes();
total_pkg_count_per_cd_per_src = Pkg::PkgMediaCount();


total_size_to_install = ListSum( flatten(
total_sizes_per_cd_per_src ) );
y2milestone("total_size_to_install: %1", total_size_to_install);
remaining_sizes_per_cd_per_src = (list<list <integer> >) eval
(total_sizes_per_cd_per_src);
remaining_pkg_count_per_cd_per_src = (list<list <integer> >) eval
(total_pkg_count_per_cd_per_src);
total_cd_count = size( flatten(
total_sizes_per_cd_per_src ) );
init_pkg_data_complete = true;

y2milestone( "SlideShow::InitPkgData() done;
total_sizes_per_cd_per_src: %1", total_sizes_per_cd_per_src );
y2milestone( "SlideShow::InitPkgData(): pkg: %1",
total_pkg_count_per_cd_per_src );

// RebuildDialog(true);
}

/**
* Try to figure out what media will be needed next
* and set next_src_no and next_cd_no accordingly.
**/
void FindNextMedia()
{
// Normally we would have to use current_cd_no+1,
// but since this uses 1..n and we need 0..n-1
// for array subscripts anyway, use it as it is.
next_cd_no = current_cd_no;
next_src_no = current_src_no-1;
last_cd = false;

while ( next_src_no < size( remaining_sizes_per_cd_per_src ) )
{
list<integer> remaining_sizes = remaining_sizes_per_cd_per_src[
next_src_no ]: [];

while ( next_cd_no < size( remaining_sizes ) )
{
if ( remaining_sizes[ next_cd_no ]:0 > 0 )
{
if ( debug )
y2milestone( "Next media: src: %1 CD: %2", next_src_no,
next_cd_no );
return;
}
else
{
next_cd_no = next_cd_no + 1;
}
}

next_src_no = next_src_no + 1;
}

if ( debug )
y2milestone( "No next media - all done" );

next_src_no = -1;
next_cd_no = -1;
last_cd = true;
}


/**
* Set the current repository and CD number. Must be called for each CD
change.
* src_no: 1...n
* cd_no: 1...n
**/
global void SetCurrentCdNo( integer src_no, integer cd_no )
{
if (cd_no == 0)
{
y2milestone("medium number 0, using medium number 1");
cd_no = 1;
}

y2milestone("SetCurrentCdNo() - src: %1 , CD: %2", src_no, cd_no);
current_src_no = srcid_to_current_src_no[src_no]:-1;
current_cd_no = cd_no;

SlideShow::CheckForSlides();
FindNextMedia();

if ( Slides::HaveSlides() && Slides::HaveSlideSupport() )
{
if ( ! SlideShow::HaveSlideWidget() )
{
SlideShow::RebuildDialog();

if ( SlideShow::user_switched_to_details )
SlideShow::SwitchToDetailsView();
}

if ( ! SlideShow::user_switched_to_details ) // Don't override
explicit user request!
{
SlideShow::SwitchToSlideView();
}
}
else
{
if ( ! SlideShow::ShowingDetails() )
SlideShow::RebuildDialog();
}
}



/**
* Recalculate remaining times per CD based on package sizes remaining
* and data rate so far. Recalculation is only done each 'recalc_interval'
* seconds unless 'force_recalc' is set to 'true'.
*
* @param force_recalc force recalculation even if timeout not reached yet
* @return true if recalculated, false if not
**/
boolean RecalcRemainingTimes( boolean force_recalc )
{
if ( ! force_recalc
&& time() < SlideShow::next_recalc_time )
{
// Nothing to do (yet) - simply return
return false;
}


// Actually do recalculation

integer elapsed = SlideShow::total_time_elapsed;

if ( SlideShow::start_time >= 0 )
{
elapsed = elapsed + time() - SlideShow::start_time;
}

if ( elapsed == 0 )
{
// Called too early - no calculation possible yet.
// This happens regularly during initialization, so an error
// message wouldn't be a good idea here.

return false;
}

// This is the real thing.

integer real_bytes_per_second = total_size_installed / elapsed;

// But this turns out to be way to optimistic - RPM gets slower and
// slower while installing. So let's add some safety margin to make
// sure initial estimates are on the pessimistic side - the
// installation being faster than initially estimated will be a
// pleasant surprise to the user. Most users don't like it the other
// way round.
//
// The "pessimistic factor" progressively decreases as the installation
// proceeds. It begins with about 1.7, i.e. the data transfer rate is
// halved to what it looks like initially. It decreases to 1.0 towards
// the end.

float pessimistic_factor = 1.0;

if ( total_size_to_install > 0 )
pessimistic_factor = 1.7 - tofloat( total_size_installed ) /
tofloat( total_size_to_install );
bytes_per_second = tointeger( tofloat( real_bytes_per_second ) /
pessimistic_factor + 0.5 );

if ( bytes_per_second < 1 )
bytes_per_second = 1;

remaining_times_per_cd_per_src = [];

// Recalculate remaining times for the individual CDs

foreach ( list<integer> remaining_sizes_list,
remaining_sizes_per_cd_per_src,
``{
list<integer> remaining_times_list = [];
integer remaining_time = -1;

foreach ( integer remaining_size, remaining_sizes_list,
``{
remaining_time = remaining_size;

if ( remaining_size > 0 )
{
remaining_time = remaining_size / bytes_per_second;

if ( remaining_time < min_time_per_cd )
{
// It takes at least this long for the CD drive to spin
up and
// for RPM to do _anything_. Times below this values are
// ridiculously unrealistic.
remaining_time = min_time_per_cd;
}
else if ( remaining_time > max_time_per_cd ) // clip off at
2 hours
{
// When data throughput goes downhill (stalled network
connection etc.),
// cut off the predicted time at a reasonable maximum.
remaining_time = max_time_per_cd;
}
}
remaining_times_list = add( remaining_times_list,
remaining_time );
});

remaining_times_per_cd_per_src = add(
remaining_times_per_cd_per_src, remaining_times_list );
});


// Recalculate slide interval

if ( Slides::HaveSlides() )
{
integer slides_remaining = size( Slides::slides ) -
SlideShow::current_slide_no - 1;

if ( slides_remaining > 0 )
{
// The remaining time for the rest of the slides depends on the
// remaining time for the current CD only: This is where the
// slide images and texts reside. Normally, only CD1 has slides
// at all, i.e. the slide show must be finished when CD1 is
// done.
//
// In addition to that, take elapsed time for current slide
// into account so all slides get about the same time.

integer time_remaining =
remaining_times_per_cd_per_src[current_src_no-1, current_cd_no-1]:1 + time() -
SlideShow::slide_start_time;
SlideShow::slide_interval = time_remaining / slides_remaining;
y2debug( "New slide interval: %1 - slides remaining: %2 -
remaining time: %3",
SlideShow::slide_interval, slides_remaining,
time_remaining );

if ( SlideShow::slide_interval < SlideShow::slide_min_interval )
{
SlideShow::slide_interval = SlideShow::slide_min_interval;
y2debug( "Resetting slide interval to min slide interval:
%1", SlideShow::slide_interval );
}

if ( SlideShow::slide_interval > SlideShow::slide_max_interval )
{
SlideShow::slide_interval = SlideShow::slide_max_interval;
y2debug( "Resetting slide interval to max slide interval:
%1", SlideShow::slide_interval );
}
}
}

SlideShow::next_recalc_time = time() + SlideShow::recalc_interval;

return true;
}

/**
* Switch unit to seconds if necessary and recalc everything accordingly.
* @return true if just switched from sizes to seconds, false otherwise
**/
boolean SwitchToSecondsIfNecessary()
{
if ( unit_is_seconds
|| time() < SlideShow::start_time + SlideShow::initial_recalc_delay
)
{
return false; // no need to switch
}

RecalcRemainingTimes( true ); // force recalculation
unit_is_seconds = true;

return true; // just switched
}



/*****************************************************************************/
/****************** Callbacks and progress bars *****************************/
/*****************************************************************************/



/**
* Update progress widgets for the current CD: Label and ProgressBar.
* Use global statistics variables for that.
**/
global void UpdateCurrentCdProgress(boolean silent_check)
{
if ( ! SanityCheck( silent_check ) ) return;
if ( ! UI::WidgetExists(`cdStatisticsTable) ) return;


//
// Update table entries for current CD
//

integer remaining = remaining_sizes_per_cd_per_src [ current_src_no-1,
current_cd_no-1 ]:0;
UI::ChangeWidget(`id(`cdStatisticsTable ),
`Item( sformat( "cd(%1,%2)", current_src_no-1,
current_cd_no-1), size_column ),
FormatRemainingSize( remaining ) );

UI::ChangeWidget(`id(`cdStatisticsTable ),
`Item( sformat( "cd(%1,%2)", current_src_no-1,
current_cd_no-1), pkg_count_column ),
FormatRemainingCount(
remaining_pkg_count_per_cd_per_src [ current_src_no-1, current_cd_no-1 ]:0 ) );

if ( unit_is_seconds )
{
// Convert 'remaining' from size (bytes) to time (seconds)

remaining = remaining / bytes_per_second;

if ( remaining <= 0 )
remaining = 0;

if ( remaining > max_time_per_cd ) // clip off at 2 hours
{
// When data throughput goes downhill (stalled network
connection etc.),
// cut off the predicted time at a reasonable maximum.
remaining = -max_time_per_cd;
}

UI::ChangeWidget(`id(`cdStatisticsTable ),
`Item( sformat( "cd(%1,%2)", current_src_no-1,
current_cd_no-1), time_column ),
FormatTimeShowOverflow( remaining ) );
}


//
// Update "total" table entries
//

UI::ChangeWidget(`id( `cdStatisticsTable ),
`Item( "total", size_column ),
FormatRemainingSize( TotalRemainingSize() ) );

UI::ChangeWidget(`id( `cdStatisticsTable ),
`Item( "total", pkg_count_column ),
FormatRemainingCount( TotalRemainingPkgCount() ) );

if ( unit_is_seconds )
{
UI::ChangeWidget(`id( `cdStatisticsTable ), `Item( "total",
time_column ),
FormatTimeShowOverflow( TotalRemainingTime() ) );

}
}

/**
* Update progress widgets
**/
void UpdateTotalProgress(boolean silent_check)
{
SlideShow::StageProgress( ( TotalInstalledSize() >> 10 ) * 100 / (
total_size_to_install >> 10 ), nil /*, SlideShow::GetProgressLabel()*/ );

UpdateCurrentCdProgress(silent_check);

if ( UI::WidgetExists(`nextMedia ) )
{
string nextMedia = FormatNextMedia();

if ( nextMedia != "" || last_cd )
{
UI::ChangeWidget(`nextMedia, `Value, nextMedia );
UI::RecalcLayout();
last_cd = false;
}
}
}


/**
* Returns a table widget item list for CD statistics
**/
list<term> CdStatisticsTableItems()
{
list<term> itemList = [];

//
// Add "Total" item - at the top so it is visible by default even if
there are many items
//

{
// List column header for total remaining MB and time to install
string caption = _("Total");
integer remaining = TotalRemainingSize();
string rem_size = FormatRemainingSize( remaining );
string rem_count = FormatRemainingCount(
TotalRemainingPkgCount() );
string rem_time = "";

if ( unit_is_seconds && bytes_per_second > 0 )
{
rem_time = FormatTimeShowOverflow( TotalRemainingTime() );
}

itemList = add( itemList, SlideShow::TableItem( "total", caption, "
" + rem_size, " " + rem_count, " " + rem_time ) );
}


//
// Now go through all repositories
//

integer src_no = 0;

foreach ( list<integer> inst_src, remaining_sizes_per_cd_per_src, ``{
y2milestone( "src #%1: %2", src_no, inst_src );

if (ListSum(inst_src) > 0) // Ignore repositories from where
there is nothing is to install
{
// Add heading for this repository
itemList = add( itemList, SlideShow::TableItem( sformat(
"src(%1)", src_no ),
inst_src_names[ src_no
]:"", "", "", "" ) );

integer cd_no = 0;

foreach ( integer remaining, inst_src, ``{
if ( remaining > 0
|| ( src_no+1 == current_src_no && cd_no+1 ==
current_cd_no ) ) // suppress current CD
{
string caption = sformat( "%1 %2", media_type, cd_no+1
); // "CD 1" - column #0
string rem_size = FormatRemainingSize( remaining );
// column #1
string rem_count = FormatRemainingCount(
remaining_pkg_count_per_cd_per_src[ src_no, cd_no ]:0 );
string rem_time = "";

if ( unit_is_seconds && bytes_per_second > 0 )
{
remaining = remaining / bytes_per_second;
rem_time = FormatTime( remaining );
// column #2

if ( remaining > max_time_per_cd ) // clip
off at 2 hours
{
// When data throughput goes downhill (stalled
network connection etc.),
// cut off the predicted time at a reasonable
maximum.
// "%1" is a predefined maximum time.
rem_time = FormatTimeShowOverflow(
-max_time_per_cd );
}
}

itemList = add( itemList,
SlideShow::TableItem(
sformat("cd(%1,%2)", src_no, cd_no ), // ID
caption, " " + rem_size, "
" + rem_count, " " + rem_time ) );
}

cd_no = cd_no + 1;
});
}

src_no = src_no + 1;
});

if ( debug )
{
y2milestone( "Remaining: %1", remaining_sizes_per_cd_per_src );
y2milestone( "CD table item list:\n%1", itemList );
}

return itemList;
}



/**
* Progress display update
* This is called via the packager's progress callbacks.
*
* @param pkg_percent package percentage
**/
global void UpdateCurrentPackageProgress(integer pkg_percent)
{
SlideShow::SubProgress( pkg_percent, nil );
}

// update the download rate
global void UpdateCurrentPackageRateProgress(integer pkg_percent, integer
bps_avg, integer bps_current)
{
if( ! SlideShow::ShowingDetails() ) return;

string new_text = nil; // no update of the label
if (bps_current > 0)
{
// do not show the average download rate if the space is limited
if (SlideShow::textmode && SlideShow::display_width < 100)
{
bps_avg = -1;
}
new_text = String::FormatRateMessage(provide_name + " - %1",
bps_avg, bps_current);
new_text = sformat(_("Downloading %1 (download size %2)"),
new_text, provide_size);
}

SlideShow::SubProgress( pkg_percent, new_text );
}


/**
* Update progress widgets for all CDs.
* Uses global statistics variables.
**/
global void UpdateAllCdProgress(boolean silent_check)
{
if ( ! SanityCheck( silent_check ) ) return;

if ( unit_is_seconds )
RecalcRemainingTimes( true ); // force

SlideShow::UpdateTable( CdStatisticsTableItems() );
}


/**
* Return a CD's progress bar ID
* @param src_no number of the repository (from 0 on)
* @param cd_no number of the CD within that repository (from 0 on)
**/
string CdProgressId( integer src_no, integer cd_no )
{
return sformat( "Src %1 CD %2", src_no, cd_no );
}


/**
* package start display update
* - this is called at the end of a new package
*
* @param pkg_name package name
* @param deleting Flag: deleting (true) or installing (false)
package?
**/
global void SlideDisplayDone ( string pkg_name,
integer pkg_size,
boolean deleting )
{
if ( ! deleting )
{
SubtractPackageSize( pkg_size );

if (SwitchToSecondsIfNecessary()
|| RecalcRemainingTimes( false ) ) // no forced
recalculation
{
y2debug( "Updating progress for all CDs" );
UpdateAllCdProgress(false);
}
else
{
UpdateCurrentCdProgress(false);
}

UpdateTotalProgress(false);

} // ! deleting

}



/**
* package start display update
* - this is called at the beginning of a new package
*
* @param pkg_name package name
* @param pkg_summary package summary (short description)
* @param deleting Flag: deleting (true) or installing (false)
package?
**/
global void SlideDisplayStart( string pkg_name,
string pkg_summary,
integer pkg_size,
boolean deleting )
{
if ( ! SanityCheck( false ) ) return;

// remove path
pkg_name = StripPath(pkg_name);

// remove release and .rpm suffix
// pkg_name = StripReleaseNo( pkg_name ); // bug #154872

if ( deleting )
{
pkg_size = -1;

// This is a kind of misuse of insider knowledge: If there are
packages to delete, this
// deletion comes first, and only then packages are installed.
This, however, greatly
// distorts the estimated times based on data throughput so far:
While packages are
// deleted, throughput is zero, and estimated times rise to
infinity (they are cut off
// at max_time_per_cd to hide this). So we make sure the time spent
deleting packages is
// not counted for estimating remaining times - reset the timer.
//
// Note: This will begin to fail when some day packages are deleted
in the middle of the
// installaton process.

SlideShow::ResetTimer();
}

if ( pkg_summary == nil )
pkg_summary = "";

string msg = "";

if ( deleting )
{
// Heading for the progress bar for the current package
// while it is deleted. "%1" is the package name.
msg = sformat( _("Deleting %1"), pkg_name );
}
else
{
// package installation - summary text
// %1 is RPM name, %2 is installed (unpacked) size (e.g. 6.20MB)
msg = sformat( _("%1 (installed size %2)"), pkg_name,
String::FormatSize( pkg_size ) );
}


//
// Update package progress bar
//
SlideShow::SubProgress( 0, msg );

// Update global progress bar
string rem_string = "";
integer tot_rem_t = TotalRemainingTime();

rem_string = ( unit_is_seconds && bytes_per_second > 0 && tot_rem_t >
0) ?
sformat("%1 / %2", FormatRemainingSize(TotalRemainingSize()),
FormatTimeShowOverflow(tot_rem_t))
: FormatRemainingSize(TotalRemainingSize());
SlideShow::SetGlobalProgressLabel( SlideShow::CurrentStageDescription()
+ sformat(_(" (Remaining: %1)"), rem_string));

//
// Update (user visible) installation log
//
SlideShow::AppendMessageToInstLog( sformat( _("Installing %1"), msg) );

//
// Update the current slide if applicable
//
if ( SlideShow::ShowingSlide() )
{
SlideShow::ChangeSlideIfNecessary();
}
}


global void SlideGenericProvideStart (string pkg_name, integer sz,
string pattern, boolean remote)
{
if ( ! SanityCheck( false ) ) return;
if ( ! SlideShow::ShowingDetails() ) return;

string provide_msg = "";

if (remote)
{
provide_name = pkg_name;
provide_size = String::FormatSize(sz);

provide_msg = sformat(_("Downloading %1 (download size %2)"),
provide_name, provide_size);
}
else
{
provide_msg = pkg_name;
}

SlideShow::SubProgress( 0, provide_msg );

//
// Update (user visible) installation log
// for remote download only
//

if( ! remote ) return;

y2milestone( "Package '%1' is remote", pkg_name );

// message in the installatino log, %1 is package name,
// %2 is package size
SlideShow::AppendMessageToInstLog( sformat (pattern, pkg_name,
String::FormatSize (sz)) );
}

global void SlideDeltaApplyStart (string pkg_name) {
if ( ! SanityCheck( false ) ) return;
if ( ! SlideShow::ShowingDetails() ) return;

SlideShow::SubProgress( 0, pkg_name );

SlideShow::AppendMessageToInstLog( sformat (_("Applying delta RPM:
%1"), pkg_name) );
}


/**
* Package providal start
*/
global void SlideProvideStart (string pkg_name, integer sz, boolean remote)
{
// message in the installatino log, %1 is package name,
// %2 is package size
SlideGenericProvideStart (pkg_name, sz, _("Downloading %1 (download
size %2)"),
remote);
}



}
/**
* Module: SlideShow.ycp
*
* Purpose: Slide show during installation
*
* Author: Stefan Hundhammer <sh@xxxxxxx>
* Stanislav Visnovsky <visnov@xxxxxxx>
*
* $Id: SlideShow.ycp 47606 2008-05-16 10:36:24Z lslezak $
*
*/
{
module "SlideShow";

textdomain "packager";

import "Installation";
import "Label";
import "Language";
import "Stage";
import "String";
import "Wizard";
import "FileUtils";
import "Mode";
import "Popup";
import "Slides";

global integer total_time_elapsed = 0;
global integer start_time = -1;
global integer initial_recalc_delay = 60; // const - seconds
before initially calculating remaining times
global integer recalc_interval = 30; // const - seconds
between "remaining time" recalculations
global integer next_recalc_time = time();

global integer current_slide_no = 0;
global integer slide_start_time = 0;
global integer slide_min_interval = 30; // const - minimum
seconds between slide changes
global integer slide_max_interval = 3*60; // const - maximum
seconds between slide changes
global integer slide_interval = slide_min_interval;
global string language = Language::language;
global boolean widgets_created = false;
global boolean user_switched_to_details = false;
global boolean opened_own_wizard = false;
global string inst_log = "";
global boolean debug = false;

boolean user_abort = false;

// we need to remember the values for tab switching
string total_progress_label = _("Installing...");
string sub_progress_label = _("Installing...");
integer total_progress_value = 0;
integer sub_progress_value =0;
list<term> table_items = [];

boolean _show_table = false;

// properties of the current UI
global boolean textmode = UI::GetDisplayInfo()["TextMode"]:false;
global integer display_width = UI::GetDisplayInfo()["Width"]:0;

global string relnotes = nil;

global void ChangeSlideIfNecessary(); // forward declaration

/**
* Set the flag that user requested abort of the installation
* @param abort new state of the abort requested flag (true = abort
requested)
*/
global void SetUserAbort(boolean abort)
{
user_abort = abort;
}

/**
* Get the status of the flag that user requested abort of the installation
* @return boolean state of the abort requested flag (true = abort
requested)
*/
global boolean GetUserAbort()
{
return user_abort;
}

/**
* Start the internal (global) timer.
**/
global void StartTimer()
{
start_time = time();
}


/**
* Reset the internal (global) timer.
**/
global void ResetTimer()
{
start_time = time();
}


/**
* Stop the internal (global) timer and account elapsed time.
**/
global void StopTimer()
{
if ( start_time < 0 )
{
y2error( "StopTimer(): No timer running." );
return;
}

integer elapsed = time() - start_time;
start_time = -1;
total_time_elapsed = total_time_elapsed + elapsed;
y2debug("StopTimer(): Elapsed this time: %1 sec; total: %2 sec (%3:%4)",
elapsed, total_time_elapsed,
total_time_elapsed / 60, // min
total_time_elapsed % 60 ); // sec
}

/**
* Check if currently the "Details" page is shown
* @return true if showing details, false otherwise
**/
global boolean ShowingDetails()
{
return widgets_created && UI::WidgetExists(`detailsPage );
}


/**
* Check if currently the "Slide Show" page is shown
* @return true if showing details, false otherwise
**/
global boolean ShowingSlide()
{
return widgets_created && UI::WidgetExists(`slideShowPage );
}

/**
* Check if currently the "Release Notes" page is shown
* @return true if showing details, false otherwise
**/
global boolean ShowingRelNotes()
{
return widgets_created && UI::WidgetExists(`relNotesPage);
}

/**
* Restart the subprogress of the slideshow. This means the
* label will be set to \param text, value to 0.
* @param text new label for the subprogress
*/
global void SubProgressStart(string text)
{
if ( UI::WidgetExists(`progressCurrentPackage ) )
{
UI::ChangeWidget(`progressCurrentPackage, `Value, 0);
UI::ChangeWidget(`progressCurrentPackage, `Label, text);
}

sub_progress_label = text;
}

/**
* Update status of subprogress of the slideshow. The new value will be set
* to \param value, if the \text is not nil, the label will be updated
* to this text as well. Otherwise label will not change.
* @param value new value for the subprogress
* @param text new label for the subprogress
*/
global void SubProgress(integer value, string text)
{
if( UI::WidgetExists( `progressCurrentPackage ) )
{
UI::ChangeWidget(`progressCurrentPackage, `Value, value );
if( text != nil )
UI::ChangeWidget(`progressCurrentPackage, `Label, text );
}

sub_progress_value = value;
if (text != nil)
sub_progress_label = text;
}

/**
* Restart the global progress of the slideshow. This means the
* label will be set to \param text, value to 0.
* @param text new label for the global progress
*/
global void GlobalProgressStart(string text)
{
total_progress_label = text;
if ( UI::WidgetExists(`progressTotal ) )
{
UI::ChangeWidget(`progressTotal, `Value, 0);
UI::ChangeWidget(`progressTotal, `Label, text );
}

total_progress_label = text;
total_progress_value = 0;
}

/**
* Update status of global progress of the slideshow. The new value will be
set
* to \param value, if the \text is not nil, the label will be updated
* to this text as well. Otherwise label will not change.
* @param value new value for the global progress
* @param text new label for the global progress
*/
void UpdateGlobalProgress(integer value, string new_text)
{
if( new_text != nil)
total_progress_label = new_text;
total_progress_value = value;

if ( UI::WidgetExists(`progressTotal ) )
{
UI::ChangeWidget(`progressTotal, `Value, value);
if( new_text != nil )
UI::ChangeWidget(`progressTotal, `Label, new_text );
}
else
y2milestone( "progressTotal widget missing" );

// update slide
if( ShowingSlide() )
{
ChangeSlideIfNecessary();
}
}

map<string, map<string,any> > _stages = $[]; // list of the
configured stages
map<string, any> _current_stage = nil; // current stage

/**
* Return the description for the current stage.
* @return string localized string description
*/
global string CurrentStageDescription()
{
return _current_stage["description"]:_("Installing...");
}

/**
* Move the global progress to the beginning of the given stage.
* @param stage_name id of the stage to move to
*/
global void MoveToStage( string stage_name )
{
if( ! haskey( _stages, stage_name ) )
{
y2error( "Unknown progress stage \"%1\"", stage_name );
return;
}

_current_stage = _stages[stage_name]:nil;

y2milestone( "Moving to stage %1 (%2)", stage_name, _stages[stage_name,
"start"]:0 );
// translators: default global progress bar label
UpdateGlobalProgress( _stages[stage_name, "start"]:0,
_current_stage["description"]:_("Installing...") );
}

/**
* Update the global progress according to the progress in the current
stage.
* The new value will be set to the per cent of the current stage according
to \param value,
* if the \text is not nil, the label will be updated
* to this text as well. Otherwise label will not change.
* @param value new value for the stage progress
* @param text new label for the global progress
*/
global void StageProgress( integer value, string text )
{
UpdateGlobalProgress( _current_stage["start"]:0 + (value *
_current_stage["size"]:1 / 100), text );
}

/**
* Return the current global progress label.
* @return string current label
*/
global void SetGlobalProgressLabel( string text )
{
total_progress_label = text;
if ( UI::WidgetExists(`progressTotal ) )
{
UI::ChangeWidget(`progressTotal, `Label, text);
}
}

/**
* Append message to the installation log.
* @param msg message to be added, without trailing eoln
*/
global void AppendMessageToInstLog (string msg)
{
string log_line = "\n" + msg;
inst_log = inst_log + log_line;

if ( ShowingDetails() )
{
if ( UI::WidgetExists( `instLog ) )
UI::ChangeWidget(`instLog, `LastLine, log_line );
}
}



/**
* Check if the dialog is currently set up so the user could switch to the
slide page.
**/
global boolean HaveSlideWidget()
{
return UI::WidgetExists(`dumbTab);
}


/**
* Check if the slide show is available. This must be called before trying
* to access any slides; some late initialization is done here.
**/
global void CheckForSlides()
{
Slides::CheckBasePath();

if ( Stage::initial () || Stage::cont () )
{
if ( Slides::HaveSlideSupport() )
{
y2milestone( "Display OK for slide show, loading" );
Slides::LoadSlides( language );
}
else
{
y2warning( "Disabling slide show - insufficient display
capabilities" );
}
}
}


/**
* Set the slide show text.
* @param text
**/
void SetSlideText( string text )
{
if ( UI::WidgetExists(`slideText ) )
{
UI::ChangeWidget(`slideText, `Value, text );
}
}


/**
* Set the curent language. Must be called once during initialization.
**/
global void SetLanguage( string new_language )
{
language = new_language;
}


/**
* Create one single item for the CD statistics table
**/
global term TableItem( string id, string col1, string col2, string col3,
string col4 )
{
return `item(`id( id ), col1, col2, col3, col4 );
}


/**
* Load a slide image + text.
* @param slide_no number of slide to load
**/
void LoadSlide( integer slide_no )
{
if ( slide_no > size( Slides::slides ) )
{
slide_no = 0;
}

current_slide_no = slide_no;

string slide_name = Slides::slides[slide_no]:"";
slide_start_time = time();

SetSlideText( Slides::LoadSlideFile( slide_name ) );
}


/**
* Check if the current slide needs to be changed and do that if
* necessary.
**/
global void ChangeSlideIfNecessary()
{
if ( current_slide_no + 1 < size( Slides::slides )
&& time() > slide_start_time + slide_interval )
{
y2debug( "Loading slide #%1", current_slide_no + 2 );
LoadSlide( current_slide_no + 1 );
}
}

/**
* Add widgets for progress bar etc. around a slide show page
* @param page_id ID to use for this page (for checking with
UI::WidgetExists() )
* @param page_contents The inner widgets (the page contents)
* @return A term describing the widgets
**/
term AddProgressWidgets( symbol page_id, term page_contents )
{
term widgets =
`HBox(`id( page_id ),
`HSpacing( 1 ),
`VBox(
`VWeight( 1, // lower layout priority
page_contents ),
// Progress bar for overall progress of software
package installation
`ProgressBar(`id(`progressTotal ),
total_progress_label, 100, total_progress_value)
// intentionally omitting `Label(`nextMedia) -
// too much flicker upon update (UI::RecalcLayout() )
on NCurses
),
`HSpacing( 0.5 )
);

y2debug( "widget term: \n%1", widgets );
return widgets;
}


/**
* Construct widgets describing a page with the real slide show
* (the RichText / HTML page)
*
* @return A term describing the widgets
**/
term SlidePageWidgets()
{
term widgets =
AddProgressWidgets( `slideShowPage,
`RichText(`id(`slideText), "" )
);
y2debug( "widget term: \n%1", widgets );
return widgets;
}

term DetailsTableWidget()
{
return `VWeight( 1,
`Table(
`id(`cdStatisticsTable), `opt(`keepSorting),
`header(
// Table
headings for CD statistics during installation
_("Media"),
// Table
headings for CD statistics during installation
`Right(
_("Size") ),
// Table
headings for CD statistics during installation
`Right(
_("Packages") ),
// Table
headings for CD statistics during installation
`Right(
_("Time") )
),
table_items
)
);
}

/**
* Construct widgets for the "details" page
*
* @return A term describing the widgets
**/
term DetailsPageWidgets()
{
term widgets =
AddProgressWidgets( `detailsPage,
`VBox( _show_table ? DetailsTableWidget() :
`Empty(),
`VWeight( 1,
`LogView(`id(`instLog ),
_("Actions performed:"), 6, 0 )
),

`ProgressBar(`id(`progressCurrentPackage), sub_progress_label, 100,
sub_progress_value )
)
);

y2debug( "widget term: \n%1", widgets );
return widgets;
}

/**
* Construct widgets for the "release notes" page
*
* @return A term describing the widgets
**/
term RelNotesPageWidgets() {
term widgets = AddProgressWidgets (`relNotesPage,
`RichText (relnotes)
);
y2debug( "widget term: \n%1", widgets );
return widgets;
}


/**
* Switch from the 'details' view to the 'slide show' view.
**/
global void SwitchToSlideView()
{
if ( ShowingSlide() )
return;

if ( UI::WidgetExists(`tabContents ) )
{
UI::ChangeWidget(`dumbTab, `CurrentItem, `showSlide );
UI::ReplaceWidget(`tabContents, SlidePageWidgets() );
// UpdateTotalProgress(false); // FIXME: this breaks
other stages!
}
}

/**
* Rebuild the details page.
*/
void RebuildDetailsView()
{
if ( UI::WidgetExists(`tabContents ) )
{
UI::ChangeWidget(`dumbTab, `CurrentItem, `showDetails );
UI::ReplaceWidget(`tabContents, DetailsPageWidgets() );
y2milestone( "Contents set to details" );
}

if ( UI::WidgetExists( `instLog ) && inst_log != "" )
UI::ChangeWidget(`instLog, `Value, inst_log );
}

/**
* Switch from the 'slide show' view to the 'details' view.
**/
global void SwitchToDetailsView()
{
if ( ShowingDetails() )
{
y2milestone( "Already showing details" );
return;
}
RebuildDetailsView();
}

/**
* Switch to the 'release notes' view.
**/
global void SwitchToReleaseNotesView()
{
if ( ShowingRelNotes() )
return;

if ( UI::WidgetExists(`tabContents ) )
{
UI::ChangeWidget(`dumbTab, `CurrentItem, `showRelNotes );
UI::ReplaceWidget(`tabContents, RelNotesPageWidgets() );
// UpdateTotalProgress(false);
}
}


/**
* Help text for the dialog
*/
string HelpText()
{
// Help text while software packages are being installed (displayed
only in rare cases)
string help_text = _("<p>Please wait while packages are being
installed.</p>");

return help_text;
}


/**
* Rebuild the dialog. Useful if slides become available post-creating the
dialog.
*/
global void RebuildDialog()
{
term contents = `Empty();

if ( UI::HasSpecialWidget(`DumbTab) && Slides::HaveSlideSupport()
&& Slides::HaveSlides() )
{
list tabs = [
// tab
`item(`id(`showSlide ), _("Slide Sho&w") ),
// tab
`item(`id(`showDetails ), _("&Details") )
];
if (relnotes != nil && relnotes != "")
// tab
tabs = add (tabs, `item (`id (`showRelNotes), _("Release
&Notes")));

contents =
`DumbTab(`id(`dumbTab ), tabs,
`VBox(
`VSpacing( 0.4 ),
`VWeight( 1, // lower layout priority
`HBox(
`HSpacing( 1 ),

`ReplacePoint(`id(`tabContents), SlidePageWidgets() ),
`HSpacing( 0.5 )
)
),
`VSpacing( 0.4 )
)
);

}
else
{
contents = DetailsPageWidgets();
}

y2milestone( "SlideShow contents: %1", contents);

Wizard::SetContents(
// Dialog heading while software packages are being
installed
_("Perform Installation"),
contents,
HelpText(),
false, false ); // has_back, has_next

widgets_created = true;

if ( ! Slides::HaveSlides() && ShowingSlide() )
SwitchToDetailsView();
}



/**
* Open the slide show base dialog with empty work area (placeholder for
* the image) and CD statistics.
**/
void OpenSlideShowBaseDialog()
{
if ( ! Wizard::IsWizardDialog() ) // If there is no Wizard dialog open
already, open one
{
Wizard::OpenNextBackDialog();
opened_own_wizard = true;
}

UI::WizardCommand(`ProtectNextButton( false ) );
Wizard::RestoreBackButton();
Wizard::RestoreAbortButton();
Wizard::EnableAbortButton();
Wizard::RestoreNextButton();

Wizard::SetContents(
// Dialog heading while software packages are being
installed
_("Package Installation"),
`Empty(), // Wait until InitPkgData() is
called from outside
HelpText(),
false, false ); // has_back, has_next

RebuildDialog();
Wizard::SetTitleIcon("yast-sw_single");

// reset abort status
SetUserAbort(false);
}


/**
* Initialize generic data to default values
*/
global void Reset()
{
current_slide_no = 0;
slide_start_time = 0;
total_time_elapsed = 0;
start_time = -1;
next_recalc_time = -1;
}



/**
* Process (slide show) input (button press).
**/
global void HandleInput( any button )
{
if ( button == `showDetails && ! ShowingDetails() )
{
y2milestone( "User asks to switch to details" );
user_switched_to_details = true ;
SwitchToDetailsView();
}
else if ( button == `showSlide && ! ShowingSlide() )
{
if ( Slides::HaveSlides() )
{
user_switched_to_details = false;
SwitchToSlideView();
LoadSlide( current_slide_no );
}
else
{
UI::ChangeWidget(`dumbTab, `CurrentItem, `showDetails );
}
}
else if ( button == `showRelNotes && ! ShowingRelNotes() )
{
user_switched_to_details = false;
SwitchToReleaseNotesView();
}
else if ( button == `debugHotkey )
{
debug = ! debug;
y2milestone( "Debug mode: %1", debug );
}
// note: `abort is handled in SlideShowCallbacks::HandleInput()
}


/**
* Check for user button presses and handle them. Generic handling to be
used in the
* progress handlers.
**/
global void GenericHandleInput()
{
// any button = SlideShow::debug ? UI::PollInput() :
UI::TimeoutUserInput( 10 );
any button = UI::PollInput();

// in case of cancel ask user if he really wants to quit installation
if ( button == `abort || button == `cancel )
{
if ( Mode::normal () )
{
SlideShow::SetUserAbort(Popup::AnyQuestion( Popup::NoHeadline(),
// popup yes-no
_("Do you really want\nto quit
the installation?"),
Label::YesButton(),
Label::NoButton(),
`focus_no ));
}
else if ( Stage::initial () )
{
SlideShow::SetUserAbort(Popup::ConfirmAbort( `unusable ));
}
else // Mode::update (), Stage::cont ()
{
SlideShow::SetUserAbort(Popup::ConfirmAbort( `incomplete ));
}

if (SlideShow::GetUserAbort())
{
SlideShow::AppendMessageToInstLog (_("Aborted"));
}
}
else
{
SlideShow::HandleInput( button );
}
}

/**
* Open the slide show dialog.
**/
global void OpenDialog()
{
// call SlideShowCallbacks::InstallSlideShowCallbacks()
WFM::call("wrapper_slideshow_callbacks", ["InstallSlideShowCallbacks"]);

// check for slides first, otherwise dialogs will be built without them
CheckForSlides();

OpenSlideShowBaseDialog();

if ( Slides::HaveSlides() )
LoadSlide(0);
else
SwitchToDetailsView();
}


/**
* Close the slide show dialog.
**/
global void CloseDialog()
{
if ( opened_own_wizard )
Wizard::CloseDialog();

// call SlideShowCallbacks::RemoveSlideShowCallbacks()
WFM::call("wrapper_slideshow_callbacks", ["RemoveSlideShowCallbacks"]);
}

global void ShowTable()
{
if ( ShowingDetails() && ! _show_table )
{
_show_table = true;
RebuildDetailsView();
}
_show_table = true;
}

global void HideTable()
{
if ( ShowingDetails() && _show_table )
{
_show_table = false;
RebuildDetailsView();
}
_show_table = false;
}

global void UpdateTable( list<term> items )
{
table_items = items;
if( ShowingDetails() && _show_table )
{
UI::ChangeWidget( `id(`cdStatisticsTable), `Items, items );
}
}

/**
* Prepare the stages for the global progressbar. Will compute the total
estimate of time and
* partition the global 100% to given stages based on their estimates. Can
compute out of
* time and size to download.
*
* The stages description list example:
* [
* $[
* "name" : "disk",
* "description" : "Prepare disk...",
* "value" : 85, // disk speed can be guessed by the
storage, thus passing time
* "units" : `sec
* ],
* $[
* "name" : "images";
* "description" : "Deploying images...",
* "value" : 204800, // amount of kb to be
downloaded/installed
* "units" : `kb
* ],
* ]
*/
global void Setup( list< map<string,any> > stages )
{
// initiliaze the generic counters
Reset();

// gather total amount of time need
integer total_time = 0;

foreach( map<string,any> stage, stages, {
if( stage["units"]:`sec == `sec )
{
total_time = total_time + stage["value"]:0;
}
else // assume kilobytes
{
// assume 15 minutes for installation of openSUSE 11.0, giving
3495 as the constant for kb/s
total_time = total_time + (stage["value"]:0 / 3495);
}
});

y2milestone( "Total estimated time: %1", total_time );

integer start = 0; // value where the current stage starts

_stages = $[]; // prepare a new stages description

// distribute the total time to stages as per cents
foreach( map<string,any> stage, stages, {
if( stage["units"]:`sec == `sec )
{
stage["size"] = stage["value"]:0 * 100 / total_time;
stage["start"] = start;

start = start + stage["size"]:0;
}
else // assume kilobytes
{
// assume 15 minutes for installation of openSUSE 11.0, giving
3495 as the constant
stage["size"] = ( stage["value"]:0 * 100 ) / 3495 / total_time;
stage["start"] = start;
if( stage["size"]:0 + start > 100 )
stage["size"] = 100 - start;

start = start + stage["size"]:0;
}

_stages[ stage["name"]:"" ] = stage;

// setup first stage
if( _current_stage == nil )
_current_stage = stage;
});

y2milestone( "Global progress bar: %1", _stages );
}

}
/**
* Module: Slides.ycp
*
* Purpose: Module to access slides from installation repository
*
* Author: Stefan Hundhammer <sh@xxxxxxx>
* Stanislav Visnovsky <visnov@xxxxxxx>
*
*/
{
module "Slides";

textdomain "packager";

import "FileUtils";
import "Installation";

// list of currently known slides, in the order they should be shown
global list<string> slides = [];
// base path to look for slides
global string slide_base_path = Installation::sourcedir +
"/suse/setup/slide";
// path to look for texts of slides
global string slide_txt_path = "";
// path to look for images of slides
global string slide_pic_path = "";
// if no other language is configured, use this fallback
global string fallback_lang = "en";



/**
* Get a list of available slides (images) for the slide show.
* @param lang language of slides to load
* @return list slides
**/
list<string> GetSlideList( string lang )
{
list<string> slide_list = nil;

string txt_path = sformat( "%1/txt/%2", slide_base_path, lang );
if (FileUtils::Exists (txt_path)) {
slide_list = (list<string>) SCR::Read (.target.dir, txt_path );
}

if ( slide_list == nil )
{
y2error( "Directory %1 does not exist", txt_path );
if ( size( lang ) > 2 )
{
lang = substring( lang, 0, 2 );
txt_path = sformat( "%1/txt/%2", slide_base_path, lang );

if (FileUtils::Exists (txt_path)) {
slide_list = (list<string>) SCR::Read (.target.dir,
txt_path );
}
}
}

if ( slide_list == nil )
{
y2milestone( "Slideshow directory %1 does not exist", txt_path );
}
else
{
y2milestone ("Using slides from '%1' (%2 slides)", txt_path, size
(slide_list));

slide_list = sort( filter( string filename, slide_list, ``{
// Check for valid extensions - ignore editor save files and
other leftover stuff
return regexpmatch( filename,
".*\.(rtf|RTF|html|HTML|htm|HTM)$" );
} ) );

y2debug( "GetSlideList(): Slides at %1: %2", txt_path, slide_list );
}

if ( slide_list != nil && size( slide_list ) > 0 ) // Slide texts
found
{
slide_txt_path = txt_path;
slide_pic_path = slide_base_path + "/pic";

y2milestone ("Using TXT: %1, PIC: %2", slide_txt_path,
slide_pic_path);
}
else // No slide
texts found
{
y2debug( "No slides found at %1", txt_path );

// function calls itself!
if ( lang != fallback_lang )
{
y2debug( "Trying to load slides from fallback: %1",
fallback_lang );
slide_list = GetSlideList( fallback_lang );
}
}

return slide_list;
}


/**
* Check if showing slides is supported.
*
* Not to be confused with HaveSlides() which checks if there are slides
available.
* @return boolean if the current UI is capable of showing slides
**/
global boolean HaveSlideSupport()
{
map disp = UI::GetDisplayInfo();

if (disp != nil // This shouldn't happen, but who knows?
&& disp["HasImageSupport"]:false
&& disp["DefaultWidth"]:-1 >= 800
&& disp["DefaultHeight"]:-1 >= 600
&& disp["Depth"]:-1 >= 8 )
{
return true;
}
else
{
return false;
}
}


/**
* Check if slides are available.
*
* Not to be confused with HaveSlideSupport() which checks
* if slides could be displayed if there are any.
* @return boolean if the loaded list of slides contains any slides
**/
global boolean HaveSlides()
{
return size( slides ) > 0;
}

/**
* Load one slide from files complete with image and textual description.
* Also adapt img links
* @param slide_name name of the slide
* @return true if OK, false if error
**/
global string LoadSlideFile( string slide_name )
{
string text_file_name = sformat ("%1/%2", slide_txt_path, slide_name );
// returns empty string if not found
string text = (string) SCR::Read( .target.string, [text_file_name, ""]
);

//
// Fix <img src> tags: Replace image path with current slide_pic_path
//
while (true)
{
string replaced = regexpsub( text, "(.*)&imagedir;(.*)",
sformat("\\1%1\\2", slide_pic_path
) );
if ( replaced == nil ) break;
text = replaced;
}

return text;
}


/**
* Set the slide show directory
*/
global void SetSlideDir( string dir )
{
slide_base_path = dir;

map tmp = (map) WFM::Read (.local.stat, slide_base_path);

if ( ! tmp["isdir"]:false )
{
y2error( "Using default path instead of %1", tmp );
slide_base_path =
"/var/adm/YaST/InstSrcManager/tmp/CurrentMedia/suse/setup/slide";
}

y2milestone( "SetSlideDir: %1", slide_base_path );
}

/**
* Load slides for the given language and store them in the internal
variables.
* @param language requested language of the slides
*/
global void LoadSlides( string language )
{
slides = GetSlideList( language );
}

/**
* Check, if the base path set up for slides is valid (it exists and
contains slides)
* @return boolean true, if it is possible to load the slides
*/
global boolean CheckBasePath()
{
map tmp = (map) WFM::Read(.local.stat, slide_base_path);
if (! tmp["isdir"]:false)
{
y2error( "Using default path instead of %1", slide_base_path );
slide_base_path =
"/var/adm/YaST/InstSrcManager/tmp/CurrentMedia/suse/setup/slide";

return false;
}
return true;
}
}
<?xml version="1.0"?>
<productDefines xmlns="http://www.suse.com/1.0/yast2ns";
xmlns:config="http://www.suse.com/1.0/configns";>

<!--
Work around for the text domain
textdomain="control"
-->

<textdomain>control</textdomain>

<globals>
<additional_kernel_parameters></additional_kernel_parameters>
<enable_autologin config:type="boolean">true</enable_autologin>
<enable_firewall config:type="boolean">true</enable_firewall>
<firewall_enable_ssh config:type="boolean">false</firewall_enable_ssh>

<!-- FATE #303875, see
/etc/sysconfig/network/dhcp:WRITE_HOSTNAME_TO_HOSTS -->
<write_hostname_to_hosts
config:type="boolean">true</write_hostname_to_hosts>

<incomplete_translation_treshold>95</incomplete_translation_treshold>
<inform_about_suboptimal_distribution
config:type="boolean">true</inform_about_suboptimal_distribution>
<skip_language_dialog config:type="boolean">true</skip_language_dialog>
<ui_mode>simple</ui_mode>
<enable_clone config:type="boolean">false</enable_clone>
<enable_register_hwdata
config:type="boolean">true</enable_register_hwdata>
<enable_register_optional
config:type="boolean">true</enable_register_optional>
<display_register_forcereg
config:type="boolean">true</display_register_forcereg>
<disable_register_w3m config:type="boolean">true</disable_register_w3m>
<register_monthly config:type="boolean">false</register_monthly>
<manual_online_update config:type="boolean">true</manual_online_update>

<!-- bnc #359115 comment #14 -->
<root_password_as_first_user
config:type="boolean">true</root_password_as_first_user>
<root_password_ca_check
config:type="boolean">false</root_password_ca_check>

<!-- Offer online repositories feature in the installation -->
<show_online_repositories
config:type="boolean">false</show_online_repositories>
<online_repositories_default
config:type="boolean">true</online_repositories_default>

<!-- Offer add-ons in the installation -->
<show_addons config:type="boolean">true</show_addons>
<addons_default config:type="boolean">false</addons_default>

<!-- FATE #301937, Save /root content from the installation system to
the installed system -->
<save_instsys_content config:type="list">
<save_instsys_item>
<instsys_directory>/root/</instsys_directory>
<system_directory>/root/inst-sys/</system_directory>
</save_instsys_item>
</save_instsys_content>

<!-- FATE #305019: configure the files to copy from a previous
installation -->
<copy_to_system config:type="list">
<!-- FATE #300421: Import ssh keys from previous installations -->
<copy_to_system_item>
<copy_to_dir>/</copy_to_dir>
<!-- Files that must be all present on the previous system -->
<mandatory_files config:type="list">
<file_item>/etc/ssh/ssh_host_key</file_item>
<file_item>/etc/ssh/ssh_host_key.pub</file_item>
</mandatory_files>
<!-- Files thay may be present -->
<optional_files config:type="list">
<file_item>/etc/ssh/ssh_host_dsa_key</file_item>
<file_item>/etc/ssh/ssh_host_dsa_key.pub</file_item>
<file_item>/etc/ssh/ssh_host_rsa_key</file_item>
<file_item>/etc/ssh/ssh_host_rsa_key.pub</file_item>
</optional_files>
</copy_to_system_item>

<!-- FATE #120103: Import Users From Existing Partition -->
<copy_to_system_item>
<copy_to_dir>/var/lib/YaST2/imported/userdata/</copy_to_dir>
<!-- Files that must be all present on the previous system -->
<mandatory_files config:type="list">
<file_item>/etc/shadow</file_item>
<file_item>/etc/passwd</file_item>
<file_item>/etc/login.defs</file_item>
<file_item>/etc/group</file_item>
</mandatory_files>
</copy_to_system_item>
</copy_to_system>

<!-- FATE #303396, Make second stage non-interactive -->
<enable_autoconfiguration
config:type="boolean">true</enable_autoconfiguration>
<autoconfiguration_default
config:type="boolean">true</autoconfiguration_default>

<!-- FATE #303395, Kexec instead of reboot (default 'false') -->
<kexec_reboot config:type="boolean">true</kexec_reboot>

<!-- Configuration for inst_automatic_configuration script -->
<automatic_configuration config:type="list">
<!--
Adding inst_hostname client here, needed to generate random
hostname in automatic config (and for 127.0.0.2 hack) (#383336)
Must be called before inst_netprobe however, it cannot override
it later on
-->
<ac_step>
<text_id>ac_1</text_id>
<icon>yast-sw_single</icon>
<type>scripts</type>
<ac_items config:type="list">
<ac_item>initialization</ac_item>
<ac_item>hostname</ac_item>
<ac_item>netprobe</ac_item>
<ac_item>rpmcopy_secondstage</ac_item>
</ac_items>
</ac_step>
<!-- network proposal -->
<ac_step>
<text_id>ac_2</text_id>
<icon>yast-network</icon>
<type>proposals</type>
<ac_items config:type="list">
<ac_item>lan</ac_item>
<ac_item>general</ac_item>
<ac_item>dsl</ac_item>
<ac_item>isdn</ac_item>
<ac_item>modem</ac_item>
<ac_item>remote</ac_item>
<ac_item>firewall</ac_item>
</ac_items>
</ac_step>
<!-- hardware proposal -->
<ac_step>
<text_id>ac_3</text_id>
<icon>yast-hwinfo</icon>
<type>proposals</type>
<ac_items config:type="list">
<ac_item>x11</ac_item>
<ac_item>printer</ac_item>
<ac_item>sound</ac_item>
<ac_item>tv</ac_item>
</ac_items>
</ac_step>
<!-- finishing configuration -->
<ac_step>
<text_id>ac_4</text_id>
<icon>yast-sysconfig</icon>
<type>scripts</type>
<ac_items config:type="list">
<ac_item>addon_update_sources</ac_item>
<ac_item>extrasources</ac_item>
<ac_item>suseconfig</ac_item>
<ac_item>save_hardware_status</ac_item>
</ac_items>
</ac_step>
</automatic_configuration>

<!-- FATE: #304865: Enhance YaST Modules to cooperate better handling
the product licenses -->

<base_product_license_directory>/etc/YaST2/licenses/base/</base_product_license_directory>

<!-- #303798: YaST2 runlevel editor: offer easy enablement and
configuration of runlevel 4 -->
<rle_offer_rulevel_4 config:type="boolean">false</rle_offer_rulevel_4>
</globals>

<software>
<delete_old_packages config:type="boolean">true</delete_old_packages>
<selection_type config:type="symbol">auto</selection_type>

<!-- Bugzilla #327791, if not set, default is true -->
<online_repos_preselected
config:type="boolean">false</online_repos_preselected>

<!-- FATE #300898, List of external sources accesible during the
installation time -->

<external_sources_link>http://download.opensuse.org/YaST/Repos/openSUSE_111_Servers.xml</external_sources_link>

<!-- Dropped packages, bnc #300540 -->
<dropped_packages>ant-jai art-sharp asterisk asterisk-alsa
asterisk-capi asterisk-spandsp asterisk-zaptel astools avalon-framework
avalon-framework-manual avalon-logkit avalon-logkit-javadoc avmailgate bbtools
bitchx blackbox colorgcc compat-curl2 cpp41 cpp42 cups-SUSE-ppds-dat db42
dbus-1-gtk devs dockutils dragonegg ejb-javadoc gal2 gcc41 gcc41-32bit
gcc41-ada gcc41-c++ gcc41-fortran gcc41-fortran-32bit gcc41-gij gcc41-gij-32bit
gcc41-java gcc41-locale gcc41-objc gcc41-obj-c++ gcc41-objc-32bit gcc42
gcc42-32bit gcc42-c++ gcc42-fortran gcc42-fortran-32bit gcc42-gij gcc42-info
gcc42-java gcc42-objc gcc42-objc-32bit gconf-sharp gecko-sharp glade-sharp
glib-sharp gnome-keyring-manager gnome-sharp gtk-engines gtkglarea
gtkhtml-sharp2 gtk-qt-engine gtk-sharp gtk-sharp-complete gtk-sharp-gapi hermes
ial indeview ipgrab ipw3945d ircd jaf-demo jaf-javadoc jaf-manual jai
java-1_4_2-cacao java-1_4_2-cacao-devel java-1_4_2-sun java-1_4_2-sun-devel
java-1_4_2-sun-plugin javamail-manual jms-javadoc jmx jmx-javadoc jta
jta-javadoc kbilliards kfs kino knx kssh libcurl2 libexiv2 libgcc41
libgcc41-32bit libgcj41 libgcj41-32bit libgcj41-devel libgcj42 libgcj42-devel
libgfortran42 libgfortran42-32bit libgmime-2_0-2 libgpod libgpod2 libipoddevice
libkdcraw1 libkexiv2 libMagick10 libmudflap41 libmudflap41-32bit libpri
libqtpod libsoprano3 libsoprano3-32bit libstdc++41 libstdc++41-32bit
libstdc++41-devel libstdc++42-devel libWand10 libzypp-zmd-backend
limal-bootloader openbox perl-Xmms planmaker qjackconnect radiusclient rsaref
rsvg-sharp2 rug samba-pdb sax2-libsax-csharp simutrans sqlite-zmd synce
synce-kde tei_3 textmaker tomcat5 tomcat55 tomcat55-common-lib tomcat55-jasper
tomcat55-jsp-2_0-api tomcat55-server-lib tomcat55-servlet-2_4-api tpb varmon
vte-sharp vte-sharp2 websh wlan-kmp-xen xen-doc-ps xmms xmms-jack xmms-lib
yast2-bluetooth yast2-bootfloppy yast2-power-management yast2-powertweak zaptel
zaptel-kmp-default zen-updater zmd zope</dropped_packages>
<extra_urls config:type="list">
<!-- Default update repository, bnc #381360 -->
<extra_url>
<baseurl>http://download.opensuse.org/update/11.1/</baseurl>
<name>Updates for 11.1</name>
<alias>openSUSE-11.1-Updates</alias>
<prod_dir>/</prod_dir>
<enabled config:type="boolean">true</enabled>
<autorefresh config:type="boolean">true</autorefresh>
<priority config:type="integer">20</priority>
</extra_url>

<!-- Replacement for EXTRAURLS and OPTIONALURLS -->
<extra_url>

<baseurl>http://download.opensuse.org/distribution/11.1/repo/oss/</baseurl>
<name>openSUSE-11.1-Oss</name>
<alias>repo-oss</alias>
<prod_dir>/</prod_dir>
<enabled config:type="boolean">true</enabled>
<autorefresh config:type="boolean">true</autorefresh>
<priority config:type="integer">100</priority>
</extra_url>
<extra_url>

<baseurl>http://download.opensuse.org/distribution/11.1/repo/non-oss/</baseurl>
<alias>repo-non-oss</alias>
<name>openSUSE-11.1-Non-Oss</name>
<prod_dir>/</prod_dir>
<enabled config:type="boolean">true</enabled>
<autorefresh config:type="boolean">true</autorefresh>
<priority config:type="integer">100</priority>
</extra_url>
<extra_url>

<baseurl>http://download.opensuse.org/distribution/11.1/repo/debug/</baseurl>
<alias>repo-debug</alias>
<name>openSUSE-11.1-Debug</name>
<prod_dir>/</prod_dir>
<enabled config:type="boolean">false</enabled>
<autorefresh config:type="boolean">true</autorefresh>
<priority config:type="integer">100</priority>
</extra_url>
</extra_urls>
</software>

<partitioning>
<evms_config config:type="boolean">false</evms_config>
<try_separate_home config:type="boolean">true</try_separate_home>
<limit_try_home>7G</limit_try_home>
<root_space_percent>40</root_space_percent>
<root_base_size>5G</root_base_size>
<root_max_size>20G</root_max_size>
<proposal_lvm config:type="boolean">false</proposal_lvm>
<proposal_evms config:type="boolean">false</proposal_evms>
<vm_desired_size>15G</vm_desired_size>
<vm_home_max_size>25G</vm_home_max_size>
<boot_evms config:type="boolean">false</boot_evms>
</partitioning>

<network>
<force_static_ip config:type="boolean">false</force_static_ip>
<network_manager>laptop</network_manager>
<startmode>ifplugd</startmode>
</network>

<clone_modules config:type="list">
<clone_module>language</clone_module>
<clone_module>keyboard</clone_module>
<clone_module>timezone</clone_module>
<clone_module>users</clone_module>
<clone_module>networking</clone_module>
<clone_module>firewall</clone_module>
<clone_module>host</clone_module>
<clone_module>routing</clone_module>
<clone_module>proxy</clone_module>
<clone_module>runlevel</clone_module>
<clone_module>x11</clone_module>
<clone_module>nis</clone_module>
<clone_module>ldap</clone_module>
<clone_module>printer</clone_module>
<clone_module>add-on</clone_module>
<clone_module>iscsi-client</clone_module>
</clone_modules>

<texts>
<congratulate>
<label>
&lt;p&gt;&lt;b&gt;Congratulations!&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The installation of openSUSE on your machine is complete.
After clicking &lt;b&gt;Finish&lt;/b&gt;, you can log in to the
system.&lt;/p&gt;
&lt;p&gt;Visit us at %1.&lt;/p&gt;
&lt;p&gt;Have a lot of fun!&lt;br&gt;Your openSUSE Development Team&lt;/p&gt;
</label>
</congratulate>

<ac_1><label>Initialization...</label></ac_1>
<ac_2><label>Configuring network...</label></ac_2>
<ac_3><label>Configuring hardware...</label></ac_3>
<ac_4><label>Finishing configuration...</label></ac_4>
</texts>

<proposals config:type="list">
<proposal>
<label>Installation Settings</label>
<mode>installation,demo,autoinstallation</mode>
<stage>initial</stage>
<name>initial</name>
<enable_skip>no</enable_skip>
<proposal_modules config:type="list">
<proposal_module>
<name>partitions</name>
<presentation_order>10</presentation_order>
</proposal_module>
<proposal_module>
<name>bootloader</name>
<presentation_order>20</presentation_order>
</proposal_module>
<proposal_module>
<name>country_simple</name>
<presentation_order>40</presentation_order>
</proposal_module>
<proposal_module>
<name>timezone</name>
<presentation_order>50</presentation_order>
</proposal_module>
<!-- FATE #302980 -->
<proposal_module>
<name>users</name>
<presentation_order>60</presentation_order>
</proposal_module>
<proposal_module>
<name>hwinfo</name>
<presentation_order>80</presentation_order>
</proposal_module>
<proposal_module>
<name>mouse</name>
<presentation_order>90</presentation_order>
</proposal_module>
<!-- software proposal should be computed almost at the end -->
<proposal_module>
<name>software</name>
<presentation_order>30</presentation_order>
</proposal_module>
<!-- propose the default runlevel after software is selected,
bnc #380141 -->
<proposal_module>
<name>runlevel</name>
<presentation_order>70</presentation_order>
</proposal_module>
<!-- finds images to deploy -->
<proposal_module>
<name>deploying</name>
<presentation_order>95</presentation_order>
</proposal_module>
</proposal_modules>
<!--
<proposal_tabs config:type="list">
<proposal_tab>
<label>Overview</label>
<proposal_modules config:type="list">
<proposal_module>partitions</proposal_module>
<proposal_module>software_simple</proposal_module>
<proposal_module>country_simple</proposal_module>
</proposal_modules>
</proposal_tab>
<proposal_tab>
<label>Expert</label>
<proposal_modules config:type="list">
<proposal_module>hwinfo</proposal_module>
<proposal_module>keyboard</proposal_module>
<proposal_module>mouse</proposal_module>
<proposal_module>partitions</proposal_module>
<proposal_module>software</proposal_module>
<proposal_module>bootloader</proposal_module>
<proposal_module>timezone</proposal_module>
<proposal_module>language</proposal_module>
<proposal_module>users</proposal_module>
<proposal_module>runlevel</proposal_module>
</proposal_modules>
</proposal_tab>
</proposal_tabs>
-->
</proposal>

<proposal>
<label>Live Installation Settings</label>
<mode>live_installation</mode>
<stage>initial</stage>
<name>initial</name>
<enable_skip>no</enable_skip>
<proposal_modules config:type="list">
<proposal_module>hwinfo</proposal_module>
<proposal_module>partitions</proposal_module>
<proposal_module>bootloader</proposal_module>
<proposal_module>keyboard</proposal_module>
<proposal_module>timezone</proposal_module>
<proposal_module>runlevel</proposal_module>
</proposal_modules>
</proposal>

<proposal>
<label>Update Settings</label>
<mode>update</mode>
<name>initial</name>
<stage>normal</stage>
<enable_skip>no</enable_skip>
<proposal_modules config:type="list">
<proposal_module>update</proposal_module>
<proposal_module>packages</proposal_module>
<proposal_module>backup</proposal_module>
<proposal_module>language</proposal_module>
</proposal_modules>
</proposal>

<proposal>
<label>Installation Settings</label>
<mode>update</mode>
<stage>initial</stage>
<name>initial</name>
<enable_skip>no</enable_skip>
<proposal_modules config:type="list">
<proposal_module>hwinfo</proposal_module>
<proposal_module>media</proposal_module>
<!-- disabled due to bug 165832
<proposal_module>rootpart</proposal_module>
-->
<proposal_module>update</proposal_module>
<proposal_module>packages</proposal_module>
<proposal_module>backup</proposal_module>
<proposal_module>language</proposal_module>
<proposal_module>keyboard</proposal_module>
</proposal_modules>
</proposal>

<proposal>
<label>Network Configuration</label>
<name>network</name>
<stage>continue,normal</stage>
<enable_skip>yes</enable_skip>
<proposal_modules config:type="list">
<proposal_module>
<name>lan</name>
<presentation_order>20</presentation_order>
</proposal_module>
<proposal_module>
<name>general</name>
<presentation_order>5</presentation_order>
</proposal_module>
<proposal_module>
<name>dsl</name>
<presentation_order>30</presentation_order>
</proposal_module>
<proposal_module>
<name>isdn</name>
<presentation_order>40</presentation_order>
</proposal_module>
<proposal_module>
<name>modem</name>
<presentation_order>50</presentation_order>
</proposal_module>
<proposal_module>
<name>remote</name>
<presentation_order>60</presentation_order>
</proposal_module>
<proposal_module>
<name>firewall</name>
<presentation_order>10</presentation_order>
</proposal_module>
<proposal_module>
<name>proxy</name>
<presentation_order>70</presentation_order>
</proposal_module>
</proposal_modules>
</proposal>

<proposal>
<label>Hardware Configuration</label>
<name>hardware</name>
<stage>continue</stage>
<enable_skip>yes</enable_skip>
<proposal_modules config:type="list">
<proposal_module>x11</proposal_module>
<proposal_module>printer</proposal_module>
<proposal_module>sound</proposal_module>
<proposal_module>tv</proposal_module>
<proposal_module>bluetooth</proposal_module>
</proposal_modules>
</proposal>
</proposals>

<!-- Stage: Initial, Mode: Installation -->
<workflows config:type="list">
<workflow>
<defaults>
<archs>all</archs>
<enable_back>yes</enable_back>
<enable_next>yes</enable_next>
</defaults>
<label>Preparation</label>
<mode>installation</mode>
<stage>initial</stage>
<modules config:type="list">
<module>
<label>Welcome</label>
<name>complex_welcome</name>
<enable_back>no</enable_back>
<enable_next>yes</enable_next>
<arguments>
<first_run>yes</first_run>
</arguments>
<retranslate config:type="boolean">true</retranslate>
</module>
<module>
<label>Disk Activation</label>
<name>disks_activate</name>
</module>
<module>
<label>System Analysis</label>
<name>system_analysis</name>
</module>
<module>
<label>System Analysis</label>
<name>mode</name>
</module>
<!-- Here, user selects whether to perform New Installation or
Upgrade -->
<module>
<label>Online Repositories</label>
<name>productsources</name>
<enable_back>yes</enable_back>
</module>
<module>
<label>Add-On Products</label>
<name>add-on</name>
<enable_back>yes</enable_back>
</module>
<module>
<label>Time Zone</label>
<name>timezone</name>
<arguments>
<first_run>yes</first_run>
</arguments>
<enable_back>yes</enable_back>
</module>
<module>
<label>Desktop Selection</label>
<name>new_desktop</name>
</module>
<module>
<label>Disk</label>
<name>disk_proposal</name>
<enable_back>yes</enable_back>
<enable_next>yes</enable_next>
</module>
<module>
<label>User Settings</label>
<name>user_first</name>
</module>
<module>
<label>User Settings</label>
<name>root_first</name>
</module>
<module>
<heading>yes</heading>
<label>Installation</label>
</module>
<module>
<label>Installation Overview</label>
<name>proposal</name>
<proposal>initial</proposal>
</module>
<module>
<label>Perform Installation (my!)</label>
<name>prepareprogress</name>
</module>
<module>
<label>Perform Installation</label>
<name>do_resize</name>
<update config:type="boolean">false</update>
<archs>i386,x86_64,ia64</archs>
</module>
<module>
<label>Perform Installation</label>
<name>prepdisk</name>
</module>
<!-- Installation from images -->
<module>
<label>Perform Installation</label>
<name>deploy_image</name>
</module>
<!-- Installation from image -->
<!-- kickoff moved here in order not to replace files it writes
with files from the image -->
<module>
<label>Perform Installation</label>
<name>kickoff</name>
</module>
<module>
<label>Perform Installation</label>
<name>rpmcopy</name>
<enable_next>no</enable_next>
<enable_back>no</enable_back>
</module>
<module>
<label>Perform Installation</label>
<name>finish</name>
<enable_back>no</enable_back>
</module>
</modules>
</workflow>

<!-- Stage: Initial, Mode: Live Installation -->
<workflow>
<defaults>
<archs>all</archs>
<enable_back>yes</enable_back>
<enable_next>yes</enable_next>
</defaults>
<label>Installation</label>
<mode>live_installation</mode>
<stage>initial</stage>
<modules config:type="list">
<module>
<label>Welcome</label>
<name>complex_welcome</name>
<enable_back>no</enable_back>
<enable_next>yes</enable_next>
<arguments>
<first_run>yes</first_run>
</arguments>
<retranslate config:type="boolean">true</retranslate>
</module>
<!--
<module>
<label>Welcome</label>
<name>inst_live_welcome</name>
</module>
<module>
<label>License Agreement</label>
<name>inst_license</name>
</module>
-->
<module>
<label>Time Zone</label>
<name>timezone</name>
<arguments>
<first_run>yes</first_run>
</arguments>
<enable_back>yes</enable_back>
</module>
<module>
<label>Disk</label>
<name>disk_proposal</name>
<enable_back>yes</enable_back>
<enable_next>yes</enable_next>
</module>
<module>
<label>User Settings</label>
<name>user_first</name>
</module>
<module>
<label>User Settings</label>
<name>root_first</name>
</module>
<!--
<module>
<label>Installation Settings</label>
<name>inst_live_simple_proposal</name>
<proposal>initial</proposal>
</module>
<module>
<label>Installation Settings</label>
<name>inst_live_full_proposal</name>
<proposal>initial</proposal>
</module>
-->
<module>
<label>Installation Settings</label>
<name>inst_live_pre-proposal</name>
</module>
<module>
<label>Installation Settings</label>
<name>inst_proposal</name>
<proposal>initial</proposal>
</module>
<module>
<label>Perform Installation (my!)</label>
<name>inst_prepareprogress</name>
</module>
<module>
<label>Perform Installation</label>
<name>inst_do_resize</name>
<update config:type="boolean">false</update>
<archs>i386,x86_64,ia64</archs>
</module>
<module>
<label>Perform Installation</label>
<name>inst_prepdisk</name>
</module>
<module>
<label>Perform Installation</label>
<name>inst_kickoff</name>
</module>
<module>
<label>Perform Installation</label>
<name>inst_live_doit</name>
<enable_next>no</enable_next>
<enable_back>no</enable_back>
</module>
<module>
<label>Perform Installation</label>
<name>inst_finish</name>
<enable_back>no</enable_back>
</module>
</modules>
</workflow>

<!-- Stage: Initial, Mode: Update -->
<workflow>
<defaults>
<archs>all</archs>
<enable_back>yes</enable_back>
<enable_next>yes</enable_next>
</defaults>
<label>Preparation</label>
<mode>update</mode>
<stage>initial</stage>
<modules config:type="list">
<module>
<name>complex_welcome</name>
<label>Welcome</label>
<enable_back>no</enable_back>
<arguments>
<first_run>yes</first_run>
</arguments>
<retranslate config:type="boolean">true</retranslate>
</module>
<module>
<label>Disk Activation</label>
<name>disks_activate</name>
</module>
<module>
<label>System Analysis</label>
<name>system_analysis</name>
</module>
<module>
<label>System Analysis</label>
<name>mode</name>
</module>
<module>
<label>System for Update</label>
<name>update_partition</name>
</module>
<module>
<name>upgrade_urls</name>
</module>
<module>
<label>Online Repositories</label>
<name>productsources</name>
<enable_back>yes</enable_back>
</module>
<module>
<label>Add-On Products</label>
<name>add-on</name>
<enable_back>yes</enable_back>
</module>
<module>
<heading>yes</heading>
<label>Update</label>
</module>
<module>
<label>Update Settings</label>
<name>proposal</name>
<proposal>initial</proposal>
</module>
<module>
<label>Perform Installation (my!)</label>
<name>inst_prepareprogress</name>
</module>
<module>
<label>Perform Update</label>
<name>do_resize</name>
<update config:type="boolean">false</update>
<archs>i386,x86_64,ia64</archs>
</module>
<module>
<label>Perform Update</label>
<name>prepdisk</name>
</module>
<module>
<label>Perform Update</label>
<name>kickoff</name>
</module>
<module>
<label>Perform Update</label>
<name>rpmcopy</name>
<enable_back>no</enable_back>
<enable_next>no</enable_next>
</module>
<module>
<label>Perform Update</label>
<name>finish</name>
<enable_back>no</enable_back>
</module>
</modules>
</workflow>

<workflow>
<defaults>
<archs>all</archs>
</defaults>
<stage>initial</stage>
<label>Preparation</label>
<mode>repair</mode>
<modules config:type="list">
<module>
<label>System Information</label>
<name>info</name>
</module>
<module>
<label>Perform Repair</label>
<name>repair</name>
</module>
</modules>
</workflow>

<!-- Stage: Initial, Mode: ScreenShot -->
<workflow>
<defaults>
<archs>all</archs>
<enable_back>yes</enable_back>
<enable_next>yes</enable_next>
</defaults>
<stage>initial</stage>
<label>Base Installation</label>
<mode>screen_shot</mode>
<modules config:type="list">
<module>
<enable_back>no</enable_back>
<enable_next>yes</enable_next>
<label>Welcome</label>
<name>complex_welcome</name>
<retranslate config:type="boolean">true</retranslate>
</module>
<module>
<label>Installation Settings</label>
<name>proposal</name>
<proposal>initial</proposal>
</module>
<module>
<label>Perform Installation (my!)</label>
<name>prepareprogress</name>
</module>
<module>
<label>Perform Installation</label>
<name>do_resize</name>
<update config:type="boolean">false</update>
<archs>i386,x86_64,ia64</archs>
</module>
<module>
<label>Perform Installation</label>
<name>prepdisk</name>
</module>
<module>
<label>Perform Installation</label>
<name>kickoff</name>
</module>
<module>
<label>Perform Installation</label>
<name>rpmcopy</name>
<enable_back>no</enable_back>
<enable_next>yes</enable_next>
</module>
</modules>
</workflow>

<!-- Stage: Initial, Mode: Demo -->
<workflow>
<defaults>
<archs>all</archs>
<enable_back>yes</enable_back>
<enable_next>yes</enable_next>
</defaults>
<stage>initial</stage>
<label>Base Installation</label>
<mode>demo</mode>
<modules config:type="list">
<module>
<enable_back>no</enable_back>
<label>Welcome</label>
<name>complex_welcome</name>
<retranslate config:type="boolean">true</retranslate>
</module>
<module>
<label>Installation Settings</label>
<name>proposal</name>
<proposal>initial</proposal>
</module>
<module>
<label>Perform Installation (my!)</label>
<name>prepareprogress</name>
</module>
<module>
<label>Perform Installation</label>
<name>do_resize</name>
<update config:type="boolean">false</update>
<archs>i386,x86_64,ia64</archs>
</module>
<module>
<label>Perform Installation</label>
<name>prepdisk</name>
</module>
<module>
<label>Perform Installation</label>
<name>kickoff</name>
</module>
<module>
<label>Perform Installation</label>
<name>rpmcopy</name>
<enable_back>no</enable_back>
<enable_next>no</enable_next>
</module>
</modules>
</workflow>

<!-- Stage: Continue, Mode: Update -->
<!--
Second stage for update has been disabled by FATE #303396
<workflow>
<stage>continue</stage>
<mode>update</mode>
<defaults>
<archs>all</archs>
<enable_back>yes</enable_back>
<enable_next>yes</enable_next>
</defaults>
<modules config:type="list">
<module>
<label>Perform Update</label>
<name>rpmcopy_secondstage</name>
<enable_back>no</enable_back>
<enable_next>no</enable_next>
</module>
<module>
<heading>yes</heading>
<label>Configuration</label>
</module>
<module>
<label>Network</label>
<name>ask_net_test</name>
<enable_back>no</enable_back>
</module>
<module>
<label>Network</label>
<name>do_net_test</name>
</module>
<module>
<label>Registration</label>
<name>addon_update_sources</name>
</module>
<module>
<label>Registration</label>
<name>suse_register</name>
</module>
<module>
<label>Online Update</label>
<name>ask_online_update</name>
</module>
<module>
<label>Online Update</label>
<name>you</name>
</module>
<module>
<label>Online Update</label>
<name>restore_settings</name>
</module>
<module>
<name>suseconfig</name>
<enable_back>no</enable_back>
<enable_next>no</enable_next>
</module>
<module>
<label>Release Notes</label>
<name>release_notes</name>
</module>
<module>
<name>congratulate</name>
</module>
</modules>
</workflow>
-->

<!-- Stage: Continue, Mode: Installation -->
<workflow>
<stage>continue</stage>
<mode>installation</mode>
<defaults>
<enable_back>yes</enable_back>
<enable_next>yes</enable_next>
<archs>all</archs>
</defaults>
<modules config:type="list">
<module>
<heading>yes</heading>
<label>Configuration</label>
</module>
<!--
Automatic configuration: disabled in manual configuration,
FATE #303396
Non-interactive second stage
-->
<module>
<label>Automatic Configuration</label>
<name>automatic_configuration</name>
<enable_back>no</enable_back>
<enable_next>no</enable_next>
</module>
<module>
<label>root Password</label>
<name>root</name>
<enable_back>no</enable_back>
</module>
<module>
<label>Check Installation</label>
<name>initialization</name>
<enable_back>no</enable_back>
<enable_next>no</enable_next>
</module>
<module>
<label>Check Installation</label>
<name>netprobe</name>
<enable_back>no</enable_back>
<enable_next>no</enable_next>
</module>
<module>
<label>Check Installation</label>
<name>rpmcopy_secondstage</name>
<enable_back>no</enable_back>
<enable_next>no</enable_next>
</module>
<module>
<label>Hostname</label>
<name>hostname</name>
</module>
<module>
<label>Network</label>
<name>proposal</name>
<proposal>network</proposal>
</module>
<module>
<label>Network</label>
<name>ask_net_test</name>
</module>
<module>
<label>Network</label>
<name>do_net_test</name>
</module>
<module>
<label>Registration</label>
<name>addon_update_sources</name>
</module>
<module>
<label>Registration</label>
<name>suse_register</name>
</module>
<module>
<label>Online Update</label>
<name>ask_online_update</name>
</module>
<module>
<label>Online Update</label>
<name>you</name>
</module>
<module>
<label>Online Update</label>
<name>extrasources</name>
</module>
<module>
<label>Online Update</label>
<name>restore_settings</name>
</module>
<module>
<label>Users</label>
<name>auth</name>
</module>
<module>
<label>Users</label>
<name>user</name>
</module>
<module>
<name>suseconfig</name>
<enable_back>no</enable_back>
<enable_next>no</enable_next>
</module>
<module>
<label>Release Notes</label>
<name>release_notes</name>
</module>
<module>
<label>Hardware Configuration</label>
<name>proposal</name>
<proposal>hardware</proposal>
</module>
<module>
<label>Hardware Configuration</label>
<name>save_hardware_status</name>
</module>
<module>
<name>congratulate</name>
</module>
</modules>
</workflow>

<!-- Stage: Continue, Mode: Live Installation -->
<workflow>
<stage>continue</stage>
<mode>live_installation</mode>
<defaults>
<enable_back>yes</enable_back>
<enable_next>yes</enable_next>
<archs>all</archs>
</defaults>
<modules config:type="list">
<module>
<heading>yes</heading>
<label>Configuration</label>
</module>
<module>
<label>Automatic Configuration</label>
<name>automatic_configuration</name>
<enable_back>no</enable_back>
<enable_next>no</enable_next>
</module>
<module>
<label>Users</label>
<name>auth</name>
</module>
<module>
<label>Users</label>
<name>user</name>
</module>
<module>
<label>Users</label>
<name>live_cleanup</name>
<enable_back>no</enable_back>
</module>

</modules>
</workflow>

<!-- Stage: Initial, Mode: AutoInstallation -->
<workflow>
<stage>initial</stage>
<label>Base Installation</label>
<mode>autoinstallation</mode>
<defaults>
<archs>all</archs>
<enable_back>no</enable_back>
<enable_next>no</enable_next>
</defaults>
<modules config:type="list">
<module>
<label>AutoYaST Settings</label>
<name>autoinit</name>
<archs>all</archs>
<retranslate config:type="boolean">true</retranslate>
</module>
<module>
<label>AutoYaST Settings</label>
<name>autosetup</name>
</module>
<module>
<label>AutoYaST Settings</label>
<name>proposal</name>
<proposal>initial</proposal>
<enable_back>no</enable_back>
<enable_next>yes</enable_next>
</module>
<module>
<label>Perform Installation (my!)</label>
<name>prepareprogres</name>
</module>
<module>
<label>Perform Installation</label>
<name>prepdisk</name>
</module>
<module>
<label>Perform Installation</label>
<name>kickoff</name>
</module>
<module>
<label>Perform Installation</label>
<name>autoimage</name>
</module>
<module>
<label>Perform Installation</label>
<name>rpmcopy</name>
</module>
<module>
<label>Perform Installation</label>
<name>finish</name>
</module>
</modules>
</workflow>

<!-- Stage: Continue, Mode: AutoInstallation -->
<workflow>
<defaults>
<archs>all</archs>
<enable_back>no</enable_back>
<enable_next>no</enable_next>
</defaults>
<stage>continue</stage>
<mode>autoinstallation</mode>
<modules config:type="list">
<module>
<label>Perform Installation</label>
<name>netprobe</name>
</module>
<module>
<label>Perform Installation</label>
<name>autopost</name>
</module>
<module>
<label>Perform Installation</label>
<name>rpmcopy_secondstage</name>
</module>
<module>
<heading>yes</heading>
<label>Configuration</label>
</module>
<module>
<label>System Configuration</label>
<name>autoconfigure</name>
</module>
<module>
<name>suseconfig</name>
</module>
</modules>
</workflow>

</workflows>
</productDefines>
/**
* Module: inst_prepareprogress.ycp
*
* Authors: Stanislav Visnovsky (visnov@xxxxxxx)
*
* Purpose:
* Set up the global progress for the installation.
*
* possible return values: `back, `abort `next
*/

{
textdomain "installation";
import "Installation";
import "Mode";
import "Packages";
import "Language";
import "SlideShow";
import "ImageInstallation";
import "StorageClients";
import "PackageSlideShow";

y2milestone("BEGIN of inst_prepareprogress.ycp");

Packages::SlideShowSetUp (Language::language);

SlideShow::OpenDialog();
PackageSlideShow::InitPkgData(true); // FIXME: this is odd!

ImageInstallation::FillUpImagesDetails();

list< map<string,any> > stages = [
$[
"name" : "disk",
"description": _("Preparing disks..."),
"value" : Mode::update() ? 0 : 120, // FIXME: 2 minutes
"units" : `sec,
],
$[
"name" : "images",
"description": _("Deploying Images..."),
"value" : ImageInstallation::TotalSize() / 1024, // kilobytes
"units" : `kb,
],
$[
"name" : "packages",
"description": _("Installing Packages..."),
// here, we do a hack, because until images are deployed, we cannot
determine how many
// packages will be really installed additionally
"value" : (PackageSlideShow::total_size_to_install -
ImageInstallation::TotalSize()) / 1024 , // kilobytes
"units" : `kb,
],
];

SlideShow::Setup( stages );

symbol ret_val = `auto;

y2milestone("END of inst_prepareprogress.ycp");

return ret_val;
}
Index: src/clients/inst_deploy_image.ycp
===================================================================
--- src/clients/inst_deploy_image.ycp (revision 50507)
+++ src/clients/inst_deploy_image.ycp (working copy)
@@ -6,6 +6,7 @@
import "SourceManager";
import "String";
import "PackageCallbacks";
+import "SlideShow";

textdomain "installation";

@@ -20,6 +21,8 @@

y2milestone ("Deploying images");

+SlideShow::MoveToStage( "images" );
+
list<string> images = ImageInstallation::ImageOrder ();

integer last_image = nil;
@@ -39,7 +42,7 @@

void SetProgress () {
integer percent = 100 * _current_step_in_subprogress /
_current_subprogress_total;
- UI::ChangeWidget (`id ("one_image"), `Value, percent);
+ SlideShow::SubProgress( percent, nil );
}

void OverallProgressHandler (string id, integer current_step) {
@@ -67,7 +70,8 @@
// when deploying images, label is handled separately
if (id != "deploying_images") {
string new_label = ImageInstallation::GetProgressLayoutLabel (id);
- UI::ChangeWidget (`id ("one_image"), `Label, new_label);
+ SlideShow::SubProgressStart( new_label );
+ SlideShow::AppendMessageToInstLog( new_label );
}

_previous_id = id;
@@ -91,7 +95,7 @@
// update UI only if nr% has changed
if (_current_overall_progress > _last_overall_progress) {
_last_overall_progress = _current_overall_progress;
- UI::ChangeWidget (`id ("deploying_progress"), `Value,
_current_overall_progress);
+ SlideShow::StageProgress(_current_overall_progress, nil);
}
}

@@ -111,21 +115,15 @@
map <string, any> current_image =
ImageInstallation::GetCurrentImageDetails();

if (_last_download_progress < percent) {
- string current_image_name = current_image["name"]:"";
- if (current_image_name == "") {
- UI::ChangeWidget (
- `id ("one_image"), `Label,
- sformat (_("Downloading image at speed %1/s"),
String::FormatSize (bps_current))
- );
+ string image_info = current_image["name"]:"";
+ if (image_info == "") {
+ image_info = sformat (_("Downloading image at speed %1/s"),
String::FormatSize (bps_current));
} else {
- UI::ChangeWidget (
- `id ("one_image"), `Label,
- sformat (_("Downloading image %1 at speed %2/s"),
current_image_name, String::FormatSize (bps_current))
- );
+ image_info = sformat (_("Downloading image %1 at speed %2/s"),
image_info, String::FormatSize (bps_current));
}
+
+ SlideShow::SubProgress( percent, image_info );

- UI::ChangeWidget (`id ("one_image"), `Value, percent);
-
integer current_image_nr = current_image["image_nr"]:0;
integer current_steps = 0;

@@ -170,18 +168,18 @@
if (x_progress == 0) {
string current_image_name = current_image["name"]:"";
if (current_image_name == "") {
- UI::ChangeWidget (`id ("one_image"), `Label, _("Deploying
image..."));
+ current_image_name = _("Deploying image...");
} else {
- UI::ChangeWidget (`id ("one_image"), `Label, sformat (_("Deploying
image %1..."), current_image_name));
+ current_image_name = sformat (_("Deploying image %1..."),
current_image_name);
}
- // one image done
- } else if (x_progress == 100) {
- UI::ChangeWidget (`id ("one_image"), `Label, _("Image deployed"));
+ // one image done
+ SlideShow::SubProgressStart( current_image_name );
+ SlideShow::AppendMessageToInstLog( current_image_name );
}

// set current step
if (x_progress > _last_progress) {
- UI::ChangeWidget (`id ("one_image"), `Value, x_progress);
+ SlideShow::SubProgress( x_progress, nil );
_last_progress = x_progress;
integer current_image_nr = current_image["image_nr"]:0;
integer current_steps = 0;
@@ -202,6 +200,7 @@

ImageInstallation::AdjustProgressLayout ("deploying_images",
(_steps_for_one_image * size (images)), _("Deploying Images..."));

+/*
Wizard::SetContents (
_("Deploying Installation Images"),
`VBox (
@@ -234,6 +233,7 @@
installation program has to download them first before they are
deployed.</p>"),
false, false
);
+*/

ImageInstallation::StoreAllChanges();

Index: src/modules/ImageInstallation.ycp
===================================================================
--- src/modules/ImageInstallation.ycp (revision 50507)
+++ src/modules/ImageInstallation.ycp (working copy)
@@ -25,6 +25,7 @@
import "Arch";
import "PackageCallbacks";
import "Popup";
+import "SlideShow";

textdomain "installation";

@@ -263,6 +264,7 @@
break;
}
} else {
+ SlideShow::HandleInput( ret );
sleep (200);
}
}
@@ -360,6 +362,19 @@

integer _current_image_from_imageset = -1;

+global integer TotalSize()
+{
+ integer sum = 0;
+
+ y2milestone( "Computing total images size from [%1], data %2",
_image_order, images_details );
+ foreach( string image, _image_order, {
+ sum = sum + images_details[image,"size"]:0;
+ });
+
+ y2milestone( "Total images size: %1", sum );
+ return sum;
+}
+
void SetCurrentImageDetails (map <string,any> img) {
_current_image_from_imageset = _current_image_from_imageset + 1;

Index: src/clients/inst_rpmcopy.ycp
===================================================================
--- src/clients/inst_rpmcopy.ycp (revision 50507)
+++ src/clients/inst_rpmcopy.ycp (working copy)
@@ -27,6 +27,7 @@
import "PackageInstallation";
import "Packages";
import "SlideShow";
+ import "PackageSlideShow";
import "SlideShowCallbacks";
import "Popup";
import "Report";
@@ -871,10 +872,11 @@
// initialize the package agent in continue mode
Packages::Init( true );
RestoreDiskCacheSettings ();
+
+ // in 1st stage, this is opened already
+ SlideShow::OpenDialog ();
}

- SlideShow::OpenSlideShowDialog ();
-
Pkg::TargetLogfile (Installation::destdir + Directory::logdir +
"/y2logRPM");


@@ -899,6 +901,13 @@
integer maxnumbercds = cdnumbers["maxnumbercds"]:10;
integer current_cd_no = cdnumbers["current_cd_no"]:1;

+ // re-initialize package information
+ PackageSlideShow::InitPkgData(true);
+ // we want the table
+ SlideShow::ShowTable();
+ // move the progress to the packages stage
+ SlideShow::MoveToStage("packages");
+
// install packages from CD current_cd_no to CD maxnumbercds
symbol result = InstallPackagesFromMedia (current_cd_no, maxnumbercds);

@@ -909,7 +918,7 @@
Pkg::PkgCommit (9999);
}

- SlideShow::CloseSlideShowDialog();
+ SlideShow::CloseDialog();

if (result != `abort)
{
Index: src/clients/sw_single.ycp
===================================================================
--- src/clients/sw_single.ycp (revision 50507)
+++ src/clients/sw_single.ycp (working copy)
@@ -528,6 +528,19 @@
SlideShow::InitPkgData(true); // force reinitialization
SlideShow::OpenSlideShowDialog();

+ list< map<string,any> > stages = [
+ $[
+ "name" : "packages",
+ "description": _("Installing Packages..."),
+ "value" : SlideShow::total_size_to_install / 1024 , //
kilobytes
+ "units" : `kb,
+ ],
+ ];
+
+ SlideShow::Setup( stages );
+
+ SlideShow::MoveToStage( "packages" );
+
import "PackageInstallation";
Pkg::TargetLogfile (Installation::destdir + Directory::logdir +
"/y2logRPM");
integer oldvmlinuzsize = (integer) SCR::Read(.target.size,
"/boot/vmlinuz");
Index: src/modules/SlideShowCallbacks.ycp
===================================================================
--- src/modules/SlideShowCallbacks.ycp (revision 50507)
+++ src/modules/SlideShowCallbacks.ycp (working copy)
@@ -22,6 +22,7 @@
import "PackageCallbacks";
import "Popup";
import "SlideShow";
+ import "PackageSlideShow";
import "Message";
import "Directory";
import "URL";
@@ -82,7 +83,7 @@

if ( remote )
{
- SlideShow::SlideProvideStart (name , archivesize, remote);
+ PackageSlideShow::SlideProvideStart (name , archivesize, remote);
_remote_provide = true;
}
}
@@ -95,7 +96,7 @@
{
if (_remote_provide)
{
- SlideShow::UpdateCurrentPackageProgress( percent );
+ PackageSlideShow::UpdateCurrentPackageProgress( percent );
}
HandleInput();
return ! SlideShow::GetUserAbort();
@@ -103,7 +104,7 @@

global boolean ProgressDownload(integer percent, integer bps_avg, integer
bps_current)
{
- SlideShow::UpdateCurrentPackageRateProgress(percent, bps_avg,
bps_current);
+ PackageSlideShow::UpdateCurrentPackageRateProgress(percent, bps_avg,
bps_current);

HandleInput();
return ! SlideShow::GetUserAbort();
@@ -117,7 +118,7 @@
{
if ( _remote_provide )
{
- SlideShow::UpdateCurrentPackageProgress( 100 );
+ PackageSlideShow::UpdateCurrentPackageProgress( 100 );
_remote_provide = false;
}
if (SlideShow::GetUserAbort())
@@ -291,7 +292,7 @@
**/
global void DisplayStartInstall(string pkg_name, string pkg_description,
integer pkg_size, boolean deleting )
{
- SlideShow::SlideDisplayStart( pkg_name, pkg_description, pkg_size,
deleting );
+ PackageSlideShow::SlideDisplayStart( pkg_name, pkg_description,
pkg_size, deleting );
HandleInput();

// warn user about exhausted diskspace during installation (not if
deleting packages)
@@ -395,7 +396,7 @@

if (!SlideShow::GetUserAbort())
{
- SlideShow::UpdateCurrentPackageProgress ( pkg_percent );
+ PackageSlideShow::UpdateCurrentPackageProgress ( pkg_percent );
}

if (SlideShow::GetUserAbort())
@@ -414,7 +415,7 @@
{
if (SlideShow::GetUserAbort())
return "I";
- SlideShow::UpdateCurrentPackageProgress (100);
+ PackageSlideShow::UpdateCurrentPackageProgress (100);

string ret = "";
if (error != 0)
@@ -423,7 +424,7 @@
}
if (size (ret) == 0 || tolower (substring (ret, 0, 1)) != "r")
{
- SlideShow::SlideDisplayDone(
+ PackageSlideShow::SlideDisplayDone(
PackageCallbacks::_package_name,
PackageCallbacks::_package_size,
PackageCallbacks::_deleting_package);
@@ -437,7 +438,7 @@
*/
global void StartDeltaProvide( string name, integer archivesize )
{
- SlideShow::SlideGenericProvideStart (name , archivesize, _("Downloading
delta RPM %1 (download size %2)"), true /*remote*/);
+ PackageSlideShow::SlideGenericProvideStart (name , archivesize,
_("Downloading delta RPM %1 (download size %2)"), true /*remote*/);
_remote_provide = true;
}

@@ -446,7 +447,7 @@
*/
global void StartDeltaApply( string name )
{
- SlideShow::SlideDeltaApplyStart (name);
+ PackageSlideShow::SlideDeltaApplyStart (name);
_remote_provide = true;
}
/**
@@ -454,7 +455,7 @@
*/
global void StartPatchProvide( string name, integer archivesize )
{
- SlideShow::SlideGenericProvideStart (name , archivesize, _("Downloading
patch RPM %1 (download size %2)"), true /*remote*/);
+ PackageSlideShow::SlideGenericProvideStart (name , archivesize,
_("Downloading patch RPM %1 (download size %2)"), true /*remote*/);
_remote_provide = true;
}

@@ -463,7 +464,7 @@
*/
global void ProgressDeltaApply( integer percent )
{
- SlideShow::UpdateCurrentPackageProgress ( percent );
+ PackageSlideShow::UpdateCurrentPackageProgress ( percent );
}

/**
@@ -500,9 +501,9 @@
global void CallbackSourceChange( integer source, integer media)
{
PackageCallbacks::SourceChange( source, media ); //
inform PackageCallbacks about the change
- SlideShow::SetCurrentCdNo( source, media );
- SlideShow::UpdateCurrentPackageProgress(0);
- SlideShow::UpdateAllCdProgress(false);
+ PackageSlideShow::SetCurrentCdNo( source, media );
+ PackageSlideShow::UpdateCurrentPackageProgress(0);
+ PackageSlideShow::UpdateAllCdProgress(false);
};

global string MediaChange (string error_code, string error, string url,
string product,
@@ -525,7 +526,7 @@
// moved from PackageCallbacks
if (ret == "" || URL::Check(ret))
{
- SlideShow::SetCurrentCdNo (PackageCallbacks::_current_source,
wanted);
+ PackageSlideShow::SetCurrentCdNo
(PackageCallbacks::_current_source, wanted);
}
}

Index: src/modules/PackageInstallation.ycp
===================================================================
--- src/modules/PackageInstallation.ycp (revision 50507)
+++ src/modules/PackageInstallation.ycp (working copy)
@@ -16,6 +16,7 @@
import "Directory";
import "Packages";
import "SlideShow";
+ import "PackageSlideShow";

import "Label";

@@ -100,7 +101,7 @@
list <integer> sources = Pkg::SourceGetCurrent (false);
integer source_id = sources[0]:0;

- SlideShow::InitPkgData(false);
+ PackageSlideShow::InitPkgData(false);

// structure: [ ["source_name", id] ]
list< list > src_list = Pkg::PkgMediaNames();
@@ -112,13 +113,13 @@

if (media_number == 0)
{
- SlideShow::SetCurrentCdNo (first_source, 1);
+ PackageSlideShow::SetCurrentCdNo (first_source, 1);
}
else
{
- SlideShow::SetCurrentCdNo (first_source, media_number);
+ PackageSlideShow::SetCurrentCdNo (first_source, media_number);
}
- SlideShow::UpdateAllCdProgress (false);
+ PackageSlideShow::UpdateAllCdProgress (false);
SlideShow::StartTimer();

boolean do_commit = true;
Index: src/modules/Packages.ycp
===================================================================
--- src/modules/Packages.ycp (revision 50507)
+++ src/modules/Packages.ycp (working copy)
@@ -25,6 +25,7 @@
import "ProductFeatures";
import "ProductControl";
import "Report";
+import "Slides";
import "SlideShow";
import "SpaceCalculation";
import "String";
@@ -1070,7 +1071,7 @@
// try to download only slides that are needed (by selected language)
// no images are cached
string search_for_dir = sformat ("/%1/setup/slide/", datadir);
- FindAndCopySlideDirWithoutCallbacks(our_slidedir, source, search_for_dir,
lang_long, lang_short, SlideShow::fallback_lang);
+ FindAndCopySlideDirWithoutCallbacks(our_slidedir, source, search_for_dir,
lang_long, lang_short, Slides::fallback_lang);

// fallback solution disabled
/*
@@ -1090,7 +1091,7 @@
*/

y2milestone ("Setting up the slide directory local copy: %1",
our_slidedir);
- SlideShow::SetSlideDir (our_slidedir);
+ Slides::SetSlideDir (our_slidedir);

if (load_release_notes (source))
{
Index: storage/src/inst_prepdisk.ycp
===================================================================
--- storage/src/inst_prepdisk.ycp (revision 50507)
+++ storage/src/inst_prepdisk.ycp (working copy)
@@ -36,6 +36,8 @@
import "Storage";
import "Hotplug";
import "String";
+ import "SlideShow";
+ import "StorageClients";

if (Mode::update ())
return `auto;
@@ -51,6 +53,7 @@
// Define macro that creates a dialog with progressbar
define void MakefsDialog()
``{
+ return;

if (!Wizard::IsWizardDialog())
return;
@@ -93,8 +96,10 @@
// check for ppc-PReP/CHRP system, they need a special boot partition
// todo -> put this in a lib, we need it also in inst_custom_part ...

- MakefsDialog();
+ StorageClients::total_actions = Storage::ActionsCount();

+ SlideShow::MoveToStage( "disk" );
+
y2milestone( "installation=%1", Stage::initial() );
symbol ret_val = `next;

Index: storage/src/modules/StorageClients.ycp
===================================================================
--- storage/src/modules/StorageClients.ycp (revision 50507)
+++ storage/src/modules/StorageClients.ycp (working copy)
@@ -15,6 +15,7 @@
import "Label";
import "Popup";
import "Report";
+ import "SlideShow";
import "StorageCallbacks";

textdomain "storage";
@@ -22,11 +23,14 @@
boolean enable_popup = false;
list<string> texts = [];

+global integer total_actions = 0;
+integer current_action = 0;

global void ProgressBar (string id, integer cur, integer max)
{
integer f = 100 * cur / max;
- UI::ChangeWidget (`id(`progress), `Value, f);
+ SlideShow::SubProgress( f, nil );
+ SlideShow::GenericHandleInput();
}

global void EnablePopup()
@@ -47,7 +51,14 @@

global void ShowInstallInfo (string text)
{
- UI::ChangeWidget (`id(`progress), `Label, text);
+ SlideShow::SubProgressStart( text );
+ SlideShow::AppendMessageToInstLog(text);
+
+ current_action = current_action + 1;
+
+ // hack: assume every text change means another action
+ y2milestone( "Current action: %1, total stage progress: %2",
current_action, current_action * 100 / total_actions );
+ SlideShow::StageProgress( current_action * 100 / total_actions, nil );
}


@@ -77,4 +88,5 @@
StorageCallbacks::YesNoPopup ("StorageClients::YesNoPopup");
}

-}
+} // module StorageClients
+
Index: storage/src/modules/Storage.ycp
===================================================================
--- storage/src/modules/Storage.ycp (revision 50507)
+++ storage/src/modules/Storage.ycp (working copy)
@@ -6424,4 +6424,10 @@
return( ret );
}

+global integer ActionsCount()
+ {
+ return size(LibStorage::StorageInterface::getCommitActions( sint, true
));
+ }
+
}
+
< Previous Next >
List Navigation