Author: visnov
Date: Tue Sep 2 11:23:10 2008
New Revision: 50558
URL: http://svn.opensuse.org/viewcvs/yast?rev=50558&view=rev
Log:
Unified progress during installation
Added:
trunk/packager/src/modules/PackageSlideShow.ycp
trunk/packager/src/modules/Slides.ycp
Modified:
trunk/packager/package/yast2-packager.changes
trunk/packager/src/clients/inst_rpmcopy.ycp
trunk/packager/src/clients/sw_single.ycp
trunk/packager/src/modules/PackageInstallation.ycp
trunk/packager/src/modules/Packages.ycp
trunk/packager/src/modules/SlideShow.ycp
trunk/packager/src/modules/SlideShowCallbacks.ycp
Modified: trunk/packager/package/yast2-packager.changes
URL: http://svn.opensuse.org/viewcvs/yast/trunk/packager/package/yast2-packager.changes?rev=50558&r1=50557&r2=50558&view=diff
==============================================================================
--- trunk/packager/package/yast2-packager.changes (original)
+++ trunk/packager/package/yast2-packager.changes Tue Sep 2 11:23:10 2008
@@ -1,4 +1,9 @@
-------------------------------------------------------------------
+Tue Sep 2 11:11:56 CEST 2008 - visnov@suse.cz
+
+- Use unified progress bar during installation (FATE #303860)
+
+-------------------------------------------------------------------
Wed Aug 27 13:28:07 CEST 2008 - locilka@suse.cz
- Initializing installation URL got from install.inf (RepoURL)
Modified: trunk/packager/src/clients/inst_rpmcopy.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/packager/src/clients/inst_rpmcopy.ycp?rev=50558&r1=50557&r2=50558&view=diff
==============================================================================
--- trunk/packager/src/clients/inst_rpmcopy.ycp (original)
+++ trunk/packager/src/clients/inst_rpmcopy.ycp Tue Sep 2 11:23:10 2008
@@ -27,6 +27,7 @@
import "PackageInstallation";
import "Packages";
import "SlideShow";
+ import "PackageSlideShow";
import "SlideShowCallbacks";
import "Popup";
import "Report";
@@ -661,7 +662,7 @@
}
list<string> failed = [];
- list<string> patterns = AutoinstData::post_patterns;
+ list<string> patterns = []; // WORKAROUND, REMOVE!!! AutoinstData::post_patterns;
/* set SoftLock to avoid the installation of recommended patterns (#159466) */
foreach( map p, Pkg::ResolvableProperties ("", `pattern, ""), ``{
Pkg::ResolvableSetSoftLock( p["name"]:"", `pattern );
@@ -871,9 +872,10 @@
// initialize the package agent in continue mode
Packages::Init( true );
RestoreDiskCacheSettings ();
- }
- SlideShow::OpenSlideShowDialog ();
+ // in 1st stage, this is opened already
+ SlideShow::OpenDialog ();
+ }
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)
{
Modified: trunk/packager/src/clients/sw_single.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/packager/src/clients/sw_single.ycp?rev=50558&r1=50557&r2=50558&view=diff
==============================================================================
--- trunk/packager/src/clients/sw_single.ycp (original)
+++ trunk/packager/src/clients/sw_single.ycp Tue Sep 2 11:23:10 2008
@@ -528,6 +528,19 @@
SlideShow::InitPkgData(true); // force reinitialization
SlideShow::OpenSlideShowDialog();
+ list< map > 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");
Modified: trunk/packager/src/modules/PackageInstallation.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/packager/src/modules/PackageInstallation.ycp?rev=50558&r1=50557&r2=50558&view=diff
==============================================================================
--- trunk/packager/src/modules/PackageInstallation.ycp (original)
+++ trunk/packager/src/modules/PackageInstallation.ycp Tue Sep 2 11:23:10 2008
@@ -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;
Added: trunk/packager/src/modules/PackageSlideShow.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/packager/src/modules/PackageSlideShow.ycp?rev=50558&view=auto
==============================================================================
--- trunk/packager/src/modules/PackageSlideShow.ycp (added)
+++ trunk/packager/src/modules/PackageSlideShow.ycp Tue Sep 2 11:23:10 2008
@@ -0,0 +1,1113 @@
+/**
+ * Module: PackageSlideShow.ycp
+ *
+ * Purpose: Module to access slides from installation repository
+ *
+ * Author: Stefan Hundhammer
+ * Stanislav Visnovsky
+ *
+ */
+{
+ module "PackageSlideShow";
+
+ textdomain "packager";
+
+ import "Slides";
+ import "SlideShow";
+ import "String";
+
+ global list total_sizes_per_cd_per_src = []; // total sizes per inst-src: [ [42, 43, 44], [12, 13, 14] ]
+ global list remaining_sizes_per_cd_per_src = []; // remaining sizes
+ global list remaining_times_per_cd_per_src = []; // remaining times
+ global list<string> inst_src_names = []; // a list of strings identifying each repository
+ global list total_pkg_count_per_cd_per_src = []; // number of pkgs per inst-src: [ [7, 5, 3], [2, 3, 4] ]
+ global list remaining_pkg_count_per_cd_per_src = []; // remaining number of pkgs
+ global map 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) eval (total_sizes_per_cd_per_src);
+ remaining_pkg_count_per_cd_per_src = (list) 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);
+ }
+
+
+
+}
Modified: trunk/packager/src/modules/Packages.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/packager/src/modules/Packages.ycp?rev=50558&r1=50557&r2=50558&view=diff
==============================================================================
--- trunk/packager/src/modules/Packages.ycp (original)
+++ trunk/packager/src/modules/Packages.ycp Tue Sep 2 11:23:10 2008
@@ -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))
{
Modified: trunk/packager/src/modules/SlideShow.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/packager/src/modules/SlideShow.ycp?rev=50558&r1=50557&r2=50558&view=diff
==============================================================================
--- trunk/packager/src/modules/SlideShow.ycp (original)
+++ trunk/packager/src/modules/SlideShow.ycp Tue Sep 2 11:23:10 2008
@@ -1,9 +1,10 @@
/**
* Module: SlideShow.ycp
*
- * Purpose: Slide show during package installation
+ * Purpose: Slide show during installation
*
* Author: Stefan Hundhammer
+ * Stanislav Visnovsky
*
* $Id$
*
@@ -20,104 +21,60 @@
import "String";
import "Wizard";
import "FileUtils";
+ import "Mode";
+ import "Popup";
+ import "Slides";
- global list total_sizes_per_cd_per_src = []; // total sizes per inst-src: [ [42, 43, 44], [12, 13, 14] ]
- global list remaining_sizes_per_cd_per_src = []; // remaining sizes
- global list remaining_times_per_cd_per_src = []; // remaining times
- global list<string> inst_src_names = []; // a list of strings identifying each repository
- global list total_pkg_count_per_cd_per_src = []; // number of pkgs per inst-src: [ [7, 5, 3], [2, 3, 4] ]
- global list remaining_pkg_count_per_cd_per_src = []; // remaining number of pkgs
- global map 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 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 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 next_recalc_time = -1;
- 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 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 string slide_base_path = Installation::sourcedir + "/suse/setup/slide";
-
- global string slide_txt_path = "";
- global string slide_pic_path = "";
- global string fallback_lang = "en";
global integer slide_interval = slide_min_interval;
- global list<string> slides = [];
global string language = Language::language;
- global boolean init_pkg_data_complete = false;
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;
+ 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
- boolean textmode = nil;
- integer display_width = nil;
+ global boolean textmode = UI::GetDisplayInfo()["TextMode"]:false;
+ global integer display_width = UI::GetDisplayInfo()["Width"]:0;
global string relnotes = nil;
+
+ global void ChangeSlideIfNecessary(); // forward declaration
/**
- * return the value of text_mode (true for ncurses)
- */
- global boolean GetTextMode () {
-
- if (textmode == nil)
- {
- map display_info = UI::GetDisplayInfo ();
- textmode = display_info["TextMode"]:false;
- }
- return textmode;
- }
-
- /**
- * return the value of screen width
+ * Set the flag that user requested abort of the installation
+ * @param abort new state of the abort requested flag (true = abort requested)
*/
- global integer GetDisplayWidth () {
-
- if (display_width == nil)
- {
- map display_info = UI::GetDisplayInfo ();
- display_width = display_info["Width"]:0;
- }
- return display_width;
- }
-
- /**
- * Constructor
- **/
- global void SlideShow()
- {
- y2milestone( "SlideShow constructor" );
- next_recalc_time = time();
- }
-
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;
@@ -161,12 +118,11 @@
total_time_elapsed % 60 ); // sec
}
-
/**
* Check if currently the "Details" page is shown
* @return true if showing details, false otherwise
**/
- boolean ShowingDetails()
+ global boolean ShowingDetails()
{
return widgets_created && UI::WidgetExists(`detailsPage );
}
@@ -176,653 +132,164 @@
* Check if currently the "Slide Show" page is shown
* @return true if showing details, false otherwise
**/
- boolean ShowingSlide()
+ global boolean ShowingSlide()
{
- return widgets_created && UI::WidgetExists(`slidesPage );
+ return widgets_created && UI::WidgetExists(`slideShowPage );
}
/**
* Check if currently the "Release Notes" page is shown
* @return true if showing details, false otherwise
**/
- boolean ShowingRelNotes()
+ global boolean ShowingRelNotes()
{
return widgets_created && UI::WidgetExists(`relNotesPage);
}
-
- /**
- * 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 FormatTotalRemaining()
- {
- // (Short!) headline for the total remaining time or MBs to install
- return sformat( _("Remaining:\n%1"),
- unit_is_seconds ?
- FormatTimeShowOverflow( TotalRemainingTime() ) :
- FormatRemainingSize( TotalRemainingSize() ) );
- }
-
-
- 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;
- }
-
-
- /**
- * Normalize a CD size list like [ [ 111, 0, 333 ], [ 211, 222, 0 ] ]
- * to a flat single list that doesn't contain any 0 items (but -1 if there are any)
- * If the resulting list would be completely empty, use a simple fallback: [ 1 ]
- **/
- list<integer> FlattenNoZeroes( list< list<integer> > sizesPerSourceList )
- {
- list <integer> normalizedList =
- filter( integer item, flatten( sizesPerSourceList ),
- ``{ return item != 0; });
-
- if ( size( normalizedList ) < 1 )
- normalizedList = [ 1 ];
-
- return normalizedList;
- }
-
-
/**
- * Get a list of available slides (images) for the slide show.
- * @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 )
- {
- y2debug( "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.
- **/
- boolean HaveSlideSupport()
+ * 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)
{
- 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
+ if ( UI::WidgetExists(`progressCurrentPackage ) )
{
- return false;
+ UI::ChangeWidget(`progressCurrentPackage, `Value, 0);
+ UI::ChangeWidget(`progressCurrentPackage, `Label, text);
}
+
+ sub_progress_label = text;
}
-
-
- /**
- * Check if slides are available.
- *
- * Not to be confused with HaveSlideSupport() which checks
- * if slides could be displayed if there are any.
- **/
- boolean HaveSlides()
- {
- return size( slides ) > 0;
- }
-
-
- /**
- * Check if the dialog is currently set up so the user could switch to the slide page.
- **/
- 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()
+ * 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)
{
- slides = [];
-
- map tmp = (map) WFM::Read(.local.stat, slide_base_path);
- if (! tmp["isdir"]:false)
+ if( UI::WidgetExists( `progressCurrentPackage ) )
{
- slide_base_path = "/var/adm/YaST/InstSrcManager/tmp/CurrentMedia/suse/setup/slide";
+ UI::ChangeWidget(`progressCurrentPackage, `Value, value );
+ if( text != nil )
+ UI::ChangeWidget(`progressCurrentPackage, `Label, text );
}
-
- if ( debug && false )
- {
- y2milestone( "Debug mode - using faster time recalc values" );
- initial_recalc_delay = 7;
- recalc_interval = 5;
- slide_min_interval = 5;
- }
-
-
- if ( Stage::initial () || Stage::cont () )
- {
- if ( HaveSlideSupport() )
- {
- y2milestone( "Display OK for slide show" );
-
- slides = GetSlideList( language );
- }
- else
- {
- y2warning( "Disabling slide show - insufficient display capabilities" );
- }
- }
- }
-
-
- /**
- * Set the slide show text.
- * @param text
- **/
- void SetSlideText( string 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)
{
- if ( UI::WidgetExists(`slideText ) )
+ total_progress_label = text;
+ if ( UI::WidgetExists(`progressTotal ) )
{
- //
- // 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;
- }
-
- UI::ChangeWidget(`slideText, `Value, text );
+ UI::ChangeWidget(`progressTotal, `Value, 0);
+ UI::ChangeWidget(`progressTotal, `Label, text );
}
+
+ total_progress_label = text;
+ total_progress_value = 0;
}
-
-
+
/**
- * Load one slide from files complete with image and textual description.
- * @param text_file_name file name + path of the text file (rich text / HTML)
- * @return true if OK, false if error
- **/
- boolean LoadSlideFile( string text_file_name )
+ * 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)
{
- string text = (string) SCR::Read( .target.string, [text_file_name, ""] );
+ if( new_text != nil)
+ total_progress_label = new_text;
+ total_progress_value = value;
- if ( text == "" )
+ if ( UI::WidgetExists(`progressTotal ) )
{
- return false;
+ UI::ChangeWidget(`progressTotal, `Value, value);
+ if( new_text != nil )
+ UI::ChangeWidget(`progressTotal, `Label, new_text );
}
else
+ y2milestone( "progressTotal widget missing" );
+
+ // update slide
+ if( ShowingSlide() )
{
- y2debug( "Loading slide show text from %1", text_file_name);
- SetSlideText( text );
- return true;
- }
- }
-
-
- /**
- * 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);
+ ChangeSlideIfNecessary();
}
-
- return pkg_name;
}
+ map > _stages = $[]; // list of the configured stages
+ map _current_stage = nil; // current stage
/**
- * set media type "CD" or "DVD"
+ * Return the description for the current stage.
+ * @return string localized string description
*/
- global void SetMediaType (string new_media_type)
+ global string CurrentStageDescription()
{
- media_type = new_media_type;
+ return _current_stage["description"]:_("Installing...");
}
-
-
+
/**
- * Set the slide show directory
+ * Move the global progress to the beginning of the given stage.
+ * @param stage_name id of the stage to move to
*/
- global void SetSlideDir( string dir )
- {
- slide_base_path = dir;
-
- map tmp = (map) WFM::Read (.local.stat, slide_base_path);
-
- if ( ! tmp["isdir"]:false )
- slide_base_path = "/var/adm/YaST/InstSrcManager/tmp/CurrentMedia/suse/setup/slide";
-
- y2milestone( "SetSlideDir: %1", slide_base_path );
- }
-
-
- /**
- * 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 )
+ global void MoveToStage( string stage_name )
{
- if ( ! init_pkg_data_complete )
+ if( ! haskey( _stages, stage_name ) )
{
- 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;
- }
-
- string provide_name = "";
- string provide_size = "";
-
- global void SlideGenericProvideStart (string pkg_name, integer sz,
- string pattern, boolean remote)
- {
- if ( ! SanityCheck( false ) ) return;
- if ( ! ShowingDetails() ) return;
-
- if ( UI::WidgetExists(`progressCurrentPackage) )
- {
- 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;
- }
-
- UI::ChangeWidget(`progressCurrentPackage, `Label, provide_msg);
- UI::ChangeWidget(`progressCurrentPackage, `Value, 0);
+ y2error( "Unknown progress stage \"%1\"", stage_name );
+ return;
}
- //
- // Update (user visible) installation log
- // for remote download only
- //
- if( ! remote ) return;
-
- y2milestone( "Package '%1' is remote", pkg_name );
+ _current_stage = _stages[stage_name]:nil;
- string strsize = String::FormatSize (sz);
- // message in the installatino log, %1 is package name,
- // %2 is package size
- string msg = sformat (pattern, pkg_name, strsize);
- string log_line = "\n" + msg;
- inst_log = inst_log + log_line;
-
- if ( ShowingDetails() )
- {
- if ( UI::WidgetExists( `instLog ) )
- UI::ChangeWidget(`instLog, `LastLine, log_line );
- }
-
- }
-
- global void SlideDeltaApplyStart (string pkg_name) {
- if ( ! SanityCheck( false ) ) return;
- if ( ! ShowingDetails() ) return;
-
- if ( UI::WidgetExists(`progressCurrentPackage) )
- {
- UI::ChangeWidget(`progressCurrentPackage, `Label, pkg_name);
- UI::ChangeWidget(`progressCurrentPackage, `Value, 0);
- }
-
- string msg = sformat (_("Applying delta RPM: %1"), pkg_name);
- string log_line = "\n" + msg;
- inst_log = inst_log + log_line;
-
- if ( ShowingDetails() )
- {
- if ( UI::WidgetExists( `instLog ) )
- UI::ChangeWidget(`instLog, `LastLine, log_line );
- }
+ 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...") );
}
-
/**
- * Package providal start
- */
- global void SlideProvideStart (string pkg_name, integer sz, boolean remote)
+ * 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 )
{
- // message in the installatino log, %1 is package name,
- // %2 is package size
- SlideGenericProvideStart (pkg_name, sz, _("Downloading %1 (download size %2)"),
- remote);
+ UpdateGlobalProgress( _current_stage["start"]:0 + (value * _current_stage["size"]:1 / 100), text );
}
-
/**
- * Set the curent language. Must be called once during initialization.
- **/
- global void SetLanguage( string new_language )
+ * Return the current global progress label.
+ * @return string current label
+ */
+ global void SetGlobalProgressLabel( string text )
{
- language = new_language;
+ total_progress_label = text;
+ if ( UI::WidgetExists(`progressTotal ) )
+ {
+ UI::ChangeWidget(`progressTotal, `Label, text);
+ }
}
/**
- * Append message to the installation log
+ * Append message to the installation log.
+ * @param msg message to be added, without trailing eoln
*/
global void AppendMessageToInstLog (string msg)
{
@@ -836,480 +303,68 @@
}
}
- /**
- * 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);
- }
-
-
- /**
- * 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 );
- }
/**
- * 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() < next_recalc_time )
- {
- // Nothing to do (yet) - simply return
- return false;
- }
-
-
- // Actually do recalculation
-
- integer elapsed = total_time_elapsed;
-
- if ( start_time >= 0 )
- {
- elapsed = elapsed + time() - 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 ( size( slides ) > 0 )
- {
- integer slides_remaining = size( slides ) - 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() - slide_start_time;
- slide_interval = time_remaining / slides_remaining;
- y2debug( "New slide interval: %1 - slides remaining: %2 - remaining time: %3",
- slide_interval, slides_remaining, time_remaining );
-
- if ( slide_interval < slide_min_interval )
- {
- slide_interval = slide_min_interval;
- y2debug( "Resetting slide interval to min slide interval: %1", slide_interval );
- }
-
- if ( slide_interval > slide_max_interval )
- {
- slide_interval = slide_max_interval;
- y2debug( "Resetting slide interval to max slide interval: %1", slide_interval );
- }
- }
- }
-
- next_recalc_time = time() + recalc_interval;
-
- return true;
- }
-
-
- /**
- * Create one single item for the CD statistics table
- **/
- term TableItem( string id, string col1, string col2, string col3, string col4 )
- {
- return `item(`id( id ), col1, col2, col3, col4 );
- }
-
-
- /**
- * Returns a table widget item list for CD statistics
+ * Check if the dialog is currently set up so the user could switch to the slide page.
**/
- list<term> CdStatisticsTableItems()
+ global boolean HaveSlideWidget()
{
- 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, 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, 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,
- 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;
+ return UI::WidgetExists(`dumbTab);
}
-
/**
- * Progress display update
- * This is called via the packager's progress callbacks.
- *
- * @param pkg_percent package percentage
+ * 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 UpdateCurrentPackageProgress(integer pkg_percent)
+ global void CheckForSlides()
{
- if ( UI::WidgetExists(`progressCurrentPackage ) )
- {
- UI::ChangeWidget(`progressCurrentPackage, `Value, pkg_percent);
- }
- }
+ Slides::CheckBasePath();
- global void UpdateCurrentPackageRateProgress(integer pkg_percent, integer bps_avg, integer bps_current)
- {
- // update the download rate
- if ( UI::WidgetExists(`progressCurrentPackage ) )
+ if ( Stage::initial () || Stage::cont () )
{
- UI::ChangeWidget(`progressCurrentPackage, `Value, pkg_percent);
-
- if (bps_current > 0)
+ if ( Slides::HaveSlideSupport() )
{
- // do not show the average download rate if the space is limited
- if (GetTextMode () && GetDisplayWidth () < 100)
- {
- bps_avg = -1;
- }
-
- string msg_rate = String::FormatRateMessage(provide_name + " - %1", bps_avg, bps_current);
- msg_rate = sformat(_("Downloading %1 (download size %2)"), msg_rate, provide_size);
-
- UI::ChangeWidget(`progressCurrentPackage, `Label, msg_rate);
+ y2milestone( "Display OK for slide show, loading" );
+ Slides::LoadSlides( language );
}
- }
- }
-
-
- /**
- * Update progress widgets for all CDs.
- * Uses global statistics variables.
- **/
- global void UpdateAllCdProgress(boolean silent_check)
- {
- if ( ! SanityCheck( silent_check ) ) return;
- if ( ! widgets_created ) return;
-
- if ( unit_is_seconds )
- RecalcRemainingTimes( true ); // force
-
- if ( UI::WidgetExists(`cdStatisticsTable) )
- UI::ChangeWidget(`cdStatisticsTable, `Items, CdStatisticsTableItems() );
- }
-
-
- /**
- * 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
+ else
{
- // When data throughput goes downhill (stalled network connection etc.),
- // cut off the predicted time at a reasonable maximum.
- remaining = -max_time_per_cd;
+ y2warning( "Disabling slide show - insufficient display capabilities" );
}
-
- 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() ) );
-
}
}
- string GetProgressLabel()
- {
- 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());
-
- return sformat(_("Remaining: %1"), rem_string);
- }
/**
- * Update progress widgets
+ * Set the slide show text.
+ * @param text
**/
- void UpdateTotalProgress(boolean silent_check)
+ void SetSlideText( string text )
{
- if ( UI::WidgetExists(`multiProgressMeter ) )
- UI::ChangeWidget(`multiProgressMeter, `Values, FlattenNoZeroes( remaining_sizes_per_cd_per_src ) );
-
- if ( UI::WidgetExists(`progressTotal ) )
- {
- // progress is in kB
- UI::ChangeWidget(`progressTotal, `Value, TotalInstalledSize() >> 10);
- UI::ChangeWidget(`progressTotal, `Label, GetProgressLabel() );
- }
-
- UpdateCurrentCdProgress(silent_check);
-
- if ( UI::WidgetExists(`nextMedia ) )
+ if ( UI::WidgetExists(`slideText ) )
{
- string nextMedia = FormatNextMedia();
-
- if ( nextMedia != "" || last_cd )
- {
- UI::ChangeWidget(`nextMedia, `Value, nextMedia );
- UI::RecalcLayout();
- last_cd = false;
- }
+ UI::ChangeWidget(`slideText, `Value, text );
}
-
- if ( UI::WidgetExists(`totalRemainingLabel ) )
- UI::ChangeWidget(`totalRemainingLabel, `Value, FormatTotalRemaining() );
-
- if ( UI::WidgetExists(`multiProgressMeter ) ) // Avoid that in NCurses - too much flicker
- UI::RecalcLayout();
}
/**
- * Switch unit to seconds if necessary and recalc everything accordingly.
- * @return true if just switched from sizes to seconds, false otherwise
+ * Set the curent language. Must be called once during initialization.
**/
- boolean SwitchToSecondsIfNecessary()
+ global void SetLanguage( string new_language )
{
- if ( unit_is_seconds
- || time() < start_time + initial_recalc_delay )
- {
- return false; // no need to switch
- }
+ language = new_language;
+ }
- RecalcRemainingTimes( true ); // force recalculation
- unit_is_seconds = true;
- return true; // just switched
+ /**
+ * 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 );
}
@@ -1319,18 +374,17 @@
**/
void LoadSlide( integer slide_no )
{
- if ( slide_no > size( slides ) )
+ if ( slide_no > size( Slides::slides ) )
{
slide_no = 0;
}
current_slide_no = slide_no;
- string slide_name = slides[slide_no]:"";
+ string slide_name = Slides::slides[slide_no]:"";
slide_start_time = time();
- if ( LoadSlideFile( sformat ("%1/%2", slide_txt_path, slide_name ) ) ) return;
- SetSlideText ("");
+ SetSlideText( Slides::LoadSlideFile( slide_name ) );
}
@@ -1338,9 +392,9 @@
* Check if the current slide needs to be changed and do that if
* necessary.
**/
- void ChangeSlideIfNecessary()
+ global void ChangeSlideIfNecessary()
{
- if ( current_slide_no + 1 < size( slides )
+ if ( current_slide_no + 1 < size( Slides::slides )
&& time() > slide_start_time + slide_interval )
{
y2debug( "Loading slide #%1", current_slide_no + 2 );
@@ -1348,151 +402,6 @@
}
}
-
- /**
- * 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.
-
- 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
- //
-
- if ( UI::WidgetExists(`progressCurrentPackage) )
- {
- UI::ChangeWidget(`progressCurrentPackage, `Label, msg );
- UI::ChangeWidget(`progressCurrentPackage, `Value, 0);
- }
-
-
- //
- // Update (user visible) installation log
- //
-
- string log_line = "\n" + msg;
-
- if ( pkg_summary != "" )
- log_line = log_line + " -- " + pkg_summary;
-
- inst_log = inst_log + log_line;
-
- if ( ShowingDetails() )
- {
- if ( UI::WidgetExists( `instLog ) )
- UI::ChangeWidget(`instLog, `LastLine, log_line );
- }
- else
- {
- ChangeSlideIfNecessary();
- }
-
-
- if ( ! deleting )
- {
- // the actions are performed when package installation finishes
-// SubtractPackageSize( pkg_size );
- y2milestone( "Installing %1 -- %2", pkg_name, pkg_summary );
-
-// if (SwitchToSecondsIfNecessary()
-// || RecalcRemainingTimes( false ) ) // no forced recalculation
-// {
-// y2debug( "Updating progress for all CDs" );
-// UpdateAllCdProgress();
-// }
-// else
-// {
-// UpdateCurrentCdProgress();
-// }
-
-// UpdateTotalProgress(false);
-
- } // ! deleting
- }
-
- /**
- * 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
-
- }
-
/**
* 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() )
@@ -1501,14 +410,6 @@
**/
term AddProgressWidgets( symbol page_id, term page_contents )
{
- integer progress_max_kB = total_size_to_install >> 10;
-
- // max value cannot be 0, it means "tick" progress
- if (progress_max_kB <= 0)
- {
- progress_max_kB = 1;
- }
-
term widgets =
`HBox(`id( page_id ),
`HSpacing( 1 ),
@@ -1516,17 +417,13 @@
`VWeight( 1, // lower layout priority
page_contents ),
// Progress bar for overall progress of software package installation
- `ProgressBar(`id(`progressTotal ), GetProgressLabel(),
- // progress is in kB due to 32 bit UI limit
- progress_max_kB, TotalInstalledSize() >> 10)
+ `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 )
);
- y2milestone("total_size_to_install: %1", total_size_to_install);
-
y2debug( "widget term: \n%1", widgets );
return widgets;
}
@@ -1548,18 +445,9 @@
return widgets;
}
-
- /**
- * Construct widgets for the "details" page
- *
- * @return A term describing the widgets
- **/
- term DetailsPageWidgets()
+ term DetailsTableWidget()
{
- term widgets =
- AddProgressWidgets( `detailsPage,
- `VBox(
- `VWeight( 1,
+ return `VWeight( 1,
`Table( `id(`cdStatisticsTable), `opt(`keepSorting),
`header(
// Table headings for CD statistics during installation
@@ -1571,13 +459,25 @@
// Table headings for CD statistics during installation
`Right( _("Time") )
),
- CdStatisticsTableItems()
+ 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 ), "", 6, 0 )
+ `LogView(`id(`instLog ), _("Actions performed:"), 6, 0 )
),
- `ProgressBar(`id(`progressCurrentPackage), " ", 100, 0 )
+ `ProgressBar(`id(`progressCurrentPackage), sub_progress_label, 100, sub_progress_value )
)
);
@@ -1585,6 +485,11 @@
return widgets;
}
+ /**
+ * Construct widgets for the "release notes" page
+ *
+ * @return A term describing the widgets
+ **/
term RelNotesPageWidgets() {
term widgets = AddProgressWidgets (`relNotesPage,
`RichText (relnotes)
@@ -1606,30 +511,37 @@
{
UI::ChangeWidget(`dumbTab, `CurrentItem, `showSlide );
UI::ReplaceWidget(`tabContents, SlidePageWidgets() );
- UpdateTotalProgress(false);
+ // UpdateTotalProgress(false); // FIXME: this breaks other stages!
}
}
-
/**
- * Switch from the 'slide show' view to the 'details' view.
- **/
- global void SwitchToDetailsView(boolean silent_check)
+ * Rebuild the details page.
+ */
+ void RebuildDetailsView()
{
- if ( ShowingDetails() )
- return;
-
if ( UI::WidgetExists(`tabContents ) )
{
UI::ChangeWidget(`dumbTab, `CurrentItem, `showDetails );
UI::ReplaceWidget(`tabContents, DetailsPageWidgets() );
+ y2milestone( "Contents set to details" );
}
- UpdateTotalProgress(silent_check);
- UpdateAllCdProgress(silent_check);
-
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();
}
/**
@@ -1644,11 +556,14 @@
{
UI::ChangeWidget(`dumbTab, `CurrentItem, `showRelNotes );
UI::ReplaceWidget(`tabContents, RelNotesPageWidgets() );
- UpdateTotalProgress(false);
+ // UpdateTotalProgress(false);
}
}
+ /**
+ * Help text for the dialog
+ */
string HelpText()
{
// Help text while software packages are being installed (displayed only in rare cases)
@@ -1658,14 +573,15 @@
}
- void RebuildDialog(boolean silent_check)
+ /**
+ * Rebuild the dialog. Useful if slides become available post-creating the dialog.
+ */
+ global void RebuildDialog()
{
- if (!SanityCheck(silent_check)) return;
-
term contents = `Empty();
- if ( UI::HasSpecialWidget(`DumbTab) && HaveSlideSupport()
- && HaveSlides() )
+ if ( UI::HasSpecialWidget(`DumbTab) && Slides::HaveSlideSupport()
+ && Slides::HaveSlides() )
{
list tabs = [
// tab
@@ -1698,17 +614,19 @@
contents = DetailsPageWidgets();
}
+ y2milestone( "SlideShow contents: %1", contents);
+
Wizard::SetContents(
// Dialog heading while software packages are being installed
- _("Package Installation"),
+ _("Perform Installation"),
contents,
HelpText(),
false, false ); // has_back, has_next
widgets_created = true;
- if ( ! HaveSlides() && ShowingSlide() )
- SwitchToDetailsView(false);
+ if ( ! Slides::HaveSlides() && ShowingSlide() )
+ SwitchToDetailsView();
}
@@ -1738,7 +656,7 @@
HelpText(),
false, false ); // has_back, has_next
- RebuildDialog(true);
+ RebuildDialog();
Wizard::SetTitleIcon("yast-sw_single");
// reset abort status
@@ -1747,153 +665,17 @@
/**
- * 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)
+ * Initialize generic data to default values
+ */
+ global void Reset()
{
- 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;
- next_recalc_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;
current_slide_no = 0;
slide_start_time = 0;
-
- 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) eval (total_sizes_per_cd_per_src);
- remaining_pkg_count_per_cd_per_src = (list) 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;
-
- CheckForSlides();
- FindNextMedia();
-
- if ( HaveSlides() && HaveSlideSupport() )
- {
- if ( ! HaveSlideWidget() )
- {
- RebuildDialog(false);
-
- if ( user_switched_to_details )
- SwitchToDetailsView(false);
- }
-
- if ( ! user_switched_to_details ) // Don't override explicit user request!
- {
- SwitchToSlideView();
- LoadSlide(0);
- }
- }
- else
- {
- if ( ! ShowingDetails() )
- RebuildDialog(false);
- else
- UpdateTotalProgress(false);
-
- current_slide_no = 0;
- }
+ total_time_elapsed = 0;
+ start_time = -1;
+ next_recalc_time = -1;
}
+
/**
@@ -1903,12 +685,13 @@
{
if ( button == `showDetails && ! ShowingDetails() )
{
+ y2milestone( "User asks to switch to details" );
user_switched_to_details = true ;
- SwitchToDetailsView(false);
+ SwitchToDetailsView();
}
else if ( button == `showSlide && ! ShowingSlide() )
{
- if ( HaveSlides() )
+ if ( Slides::HaveSlides() )
{
user_switched_to_details = false;
SwitchToSlideView();
@@ -1934,29 +717,70 @@
/**
+ * 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 OpenSlideShowDialog()
+ global void OpenDialog()
{
// call SlideShowCallbacks::InstallSlideShowCallbacks()
WFM::call("wrapper_slideshow_callbacks", ["InstallSlideShowCallbacks"]);
- OpenSlideShowBaseDialog();
+ // check for slides first, otherwise dialogs will be built without them
CheckForSlides();
- if ( HaveSlides() )
+ OpenSlideShowBaseDialog();
+
+ if ( Slides::HaveSlides() )
LoadSlide(0);
else
- SwitchToDetailsView(true);
-
- UpdateAllCdProgress(true);
+ SwitchToDetailsView();
}
/**
* Close the slide show dialog.
**/
- global void CloseSlideShowDialog()
+ global void CloseDialog()
{
if ( opened_own_wizard )
Wizard::CloseDialog();
@@ -1965,4 +789,110 @@
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 > stages )
+ {
+ // initiliaze the generic counters
+ Reset();
+
+ // gather total amount of time need
+ integer total_time = 0;
+
+ foreach( map 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 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 );
+ }
+
}
Modified: trunk/packager/src/modules/SlideShowCallbacks.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/packager/src/modules/SlideShowCallbacks.ycp?rev=50558&r1=50557&r2=50558&view=diff
==============================================================================
--- trunk/packager/src/modules/SlideShowCallbacks.ycp (original)
+++ trunk/packager/src/modules/SlideShowCallbacks.ycp Tue Sep 2 11:23:10 2008
@@ -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);
}
}
Added: trunk/packager/src/modules/Slides.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/packager/src/modules/Slides.ycp?rev=50558&view=auto
==============================================================================
--- trunk/packager/src/modules/Slides.ycp (added)
+++ trunk/packager/src/modules/Slides.ycp Tue Sep 2 11:23:10 2008
@@ -0,0 +1,205 @@
+/**
+ * Module: Slides.ycp
+ *
+ * Purpose: Module to access slides from installation repository
+ *
+ * Author: Stefan Hundhammer
+ * Stanislav Visnovsky
+ *
+ */
+{
+ 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;
+ }
+}
--
To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org
For additional commands, e-mail: yast-commit+help@opensuse.org