This commit is contained in:
law%netscape.com 2000-01-19 00:12:15 +00:00
Родитель 782a39ee6a
Коммит f9dafb59ba
4 изменённых файлов: 232 добавлений и 61 удалений

Просмотреть файл

@ -38,7 +38,11 @@ var observer = {
onProgress( words[0], words[1] );
break;
case progId+";onStatus":
onStatus( data );
// Ignore useless "Transferring data..." messages
// after download has started.
if ( !started ) {
onStatus( data );
}
break;
case progId+";onCompletion":
onCompletion( data );
@ -54,6 +58,29 @@ var observer = {
}
}
function getString( stringId ) {
// Check if we've fetched this string already.
if ( !dialog.strings[ stringId ] ) {
// Try to get it.
var elem = document.getElementById( "dialog.strings."+stringId );
if ( elem ) {
dialog.strings[ stringId ] = elem.childNodes[0].nodeValue;
}
// If missing, use "?" instead.
if ( !dialog.strings[ stringId ] ) {
dialogs.strings[ stringId ] = "?";
}
}
return dialog.strings[ stringId ];
}
function replaceInsert( text, index, value ) {
var result = text;
var regExp = eval( "/#"+index+"/" );
result = result.replace( regExp, value );
return result;
}
function onLoad() {
// Set global variables.
data = window.arguments[0];
@ -64,6 +91,7 @@ function onLoad() {
}
dialog = new Object;
dialog.strings = new Array;
dialog.location = document.getElementById("dialog.location");
dialog.contentType = document.getElementById("dialog.contentType");
dialog.fileName = document.getElementById("dialog.fileName");
@ -71,6 +99,7 @@ function onLoad() {
dialog.progress = document.getElementById("dialog.progress");
dialog.progressPercent = document.getElementById("dialog.progressPercent");
dialog.timeLeft = document.getElementById("dialog.timeLeft");
dialog.timeElapsed = document.getElementById("dialog.timeElapsed");
dialog.cancel = document.getElementById("dialog.cancel");
// Fill dialog.
@ -99,12 +128,33 @@ var elapsed;
var interval = 1000; // Update every 1000 milliseconds.
var lastUpdate = -interval; // Update initially.
function stop() {
// Stop the transfer.
data.Stop();
// These are to throttle down the updating of the download rate figure.
var priorRate = 0;
var rateChanges = 0;
var rateChangeLimit = 2;
// Close the window.
window.close();
var warningLimit = 30000; // Warn on Cancel after 30 sec (30000 milleseconds).
function stop() {
// If too much time has elapsed, make sure it's OK to quit.
if ( started ) {
// Get current time.
var now = ( new Date() ).getTime();
// See if sufficient time has elapsed to warrant dialog.
if ( now - startTime > warningLimit ) {
// XXX - Disabled for now since confirm call doesn't work.
if ( 0 && !window.confirm( getString( "confirmCancel" ) ) ) {
return;
}
}
}
// Stop the transfer.
data.Stop();
// Close the window.
window.close();
}
function onProgress( bytes, max ) {
@ -138,10 +188,16 @@ function onProgress( bytes, max ) {
rate = 0;
}
// Update elapsed time display.
dialog.timeElapsed.childNodes[0].nodeValue = formatSeconds( elapsed / 1000 );
// Calculate percentage.
var percent;
if ( max != "-1" ) {
percent = Math.round( (bytes*100)/max );
percent = parseInt( (bytes*100)/max + .5 );
if ( percent > 100 ) {
percent = 100;
}
// Advance progress meter.
dialog.progress.setAttribute( "value", percent );
@ -154,37 +210,61 @@ function onProgress( bytes, max ) {
// Check if download complete.
if ( !completed ) {
// Update status (nnn of mmm)
var status = "( ";
status += Math.round( bytes/1024 );
status += "K of ";
// Update status (nnK of mmK bytes at xx.xK bytes/sec)
var status = getString( "progressMsg" );
// Insert 1 is the number of kilobytes downloaded so far.
status = replaceInsert( status, 1, parseInt( bytes/1024 + .5 ) );
// Insert 2 is the total number of kilobytes to be downloaded (if known).
if ( max != "-1" ) {
status += Math.round( max/1024 );
status += "K bytes ";
status = replaceInsert( status, 2, parseInt( max/1024 + .5 ) );
} else {
status += "??.?K bytes ";
status = replaceInsert( status, 2, "??" );
}
if ( rate ) {
status += "at ";
status += Math.round( (rate*10)/1024 ) / 10;
status += "K bytes/sec )";
// rate is bytes/sec
var kRate = rate / 1024; // K bytes/sec;
kRate = parseInt( kRate * 10 + .5 ); // xxx (3 digits)
// Don't update too often!
if ( kRate != priorRate ) {
if ( rateChanges++ == rateChangeLimit ) {
// Time to update download rate.
priorRate = kRate;
rateChanges = 0;
} else {
// Stick with old rate for a bit longer.
kRate = priorRate;
}
} else {
rateChanges = 0;
}
var fraction = kRate % 10;
kRate = parseInt( ( kRate - fraction ) / 10 );
// Insert 3 is the download rate (in kilobytes/sec).
status = replaceInsert( status, 3, kRate + "." + fraction );
} else {
status += ")";
status = replaceInsert( status, 3, "??.?" );
}
// Update status msg.
onStatus( status );
}
// Update percentage label on progress meter.
dialog.progressPercent.childNodes[0].nodeValue = percent + "%";
var percentMsg = getString( "percentMsg" );
percentMsg = replaceInsert( percentMsg, 1, percent );
dialog.progressPercent.childNodes[0].nodeValue = percentMsg;
if ( !completed ) {
// Update time remaining.
if ( rate && max != "-1" ) {
var rem = Math.round( ( max - bytes ) / rate ); // In seconds.
var rem = ( max - bytes ) / rate;
rem = parseInt( rem + .5 );
dialog.timeLeft.childNodes[0].nodeValue = formatSeconds( rem );
} else {
dialog.timeLeft.childNodes[0].nodeValue = "??:??:??";
dialog.timeLeft.childNodes[0].nodeValue = getString( "unknownTime" );
}
} else {
// Clear time remaining field.
@ -192,43 +272,53 @@ function onProgress( bytes, max ) {
}
}
function formatSeconds( nSecs ) {
status = "";
if ( nSecs >= 3600 ) {
status += Math.round( nSecs/3600 ) + ":";
nSecs = nSecs % 3600;
function formatSeconds( secs ) {
// Round the number of seconds to remove fractions.
secs = parseInt( secs + .5 );
var hours = parseInt( secs/3600 );
secs -= hours*3600;
var mins = parseInt( secs/60 );
secs -= mins*60;
var result;
if ( hours ) {
result = getString( "longTimeFormat" );
} else {
result = getString( "shortTimeFormat" );
}
status += Math.round( nSecs/60 ) + ":";
nSecs = nSecs % 60;
status += nSecs;
return status;
if ( hours < 10 ) {
hours = "0" + hours;
}
if ( mins < 10 ) {
mins = "0" + mins;
}
if ( secs < 10 ) {
secs = "0" + secs;
}
// Insert hours, minutes, and seconds into result string.
result = replaceInsert( result, 1, hours );
result = replaceInsert( result, 2, mins );
result = replaceInsert( result, 3, secs );
return result;
}
function onCompletion( status ) {
// Note that we're done (and can ignore subsequent progress notifications).
completed = true;
// Indicate completion in status area.
onStatus( "Download completed in " + formatSeconds( elapsed/1000 ) );
var msg = getString( "completeMsg" );
msg = replaceInsert( msg, 1, formatSeconds( elapsed/1000 ) );
onStatus( msg );
// Put progress meter at 100%.
dialog.progress.setAttribute( "value", 100 );
dialog.progress.setAttribute( "mode", "normal" );
try {
// Close the window in 2 seconds (to ensure user sees we're done).
//window.setTimeout( "window.close();", 2000 );
// The above line causes crash on Mac (see bugzilla bug #10613).
// As a workaround, change button text to "Close" and try a
// simple close(). Note that the "close()" is also failing (silently)
// thus the need for the fail-safe mechanism (changing the button
// text).
dialog.cancel.childNodes[0].nodeValue = "Close";
window.close();
dump( "Close still not working right!\n" );
window.setTimeout( "window.close();", 2000 );
} catch ( exception ) {
dump( "Error setting close timeout\n" );
for ( prop in exception ) {
dump( "exception." + prop + "=" + exception[ prop ] + "\n" );
}
// Bug prevents that from working, just close the window.
// OK, try to just close the window immediately.
window.close();
// If that's not working either, change button text to give user a clue.
dialog.cancel.childNodes[0].nodeValue = "Close";
@ -236,8 +326,12 @@ function onCompletion( status ) {
}
function onStatus( status ) {
// Update status text in dialog.
dialog.status.childNodes[0].nodeValue = status;
// Update status text in dialog.
// Ignore if status text is less than 10 characters (we're getting some
// bogus onStatus notifications.
if ( status.length > 9 ) {
dialog.status.childNodes[0].nodeValue = status;
}
}
function onError( errorCode ) {

Просмотреть файл

@ -1,15 +1,31 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://navigator/skin/" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://global/locale/downloadProgress.dtd">
<window xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
class="dialog"
title="Saving file"
onload="onLoad()"
onunload="onUnload()">
<html:script src="chrome://global/content/downloadProgress.js"/>
<!-- This is non-visible content that simply adds translatable string
into the document so that it is accessible to JS code.
-->
<html:div style="display:none">
<html:div id="dialog.strings.confirmCancel">&confirmCancel;</html:div>
<html:div id="dialog.strings.progressMsg">&progressMsg;</html:div>
<html:div id="dialog.strings.completeMsg">&completeMsg;</html:div>
<html:div id="dialog.strings.percentMsg">&percentMsg;</html:div>
<html:div id="dialog.strings.shortTimeFormat">&shortTimeFormat;</html:div>
<html:div id="dialog.strings.longTimeFormat">&longTimeFormat;</html:div>
<html:div id="dialog.strings.unknownTime">&unknownTime;</html:div>
</html:div>
<html:table style="width:100%;">
<html:tr>
@ -36,7 +52,18 @@
</html:td>
<html:td align="left">
<html:span id="dialog.status">
&dialogStatus.label;
&progressMsg;
</html:span>
</html:td>
</html:tr>
<html:tr>
<html:td align="right">
&timeElapsed;
</html:td>
<html:td align="left">
<html:span id="dialog.timeElapsed">
00:00:00
</html:span>
</html:td>
</html:tr>
@ -47,7 +74,7 @@
</html:td>
<html:td align="left">
<html:span id="dialog.timeLeft">
&dialogTimeLeft.label;
00:00:00
</html:span>
</html:td>
</html:tr>
@ -57,7 +84,7 @@
<progressmeter id="dialog.progress" mode="normal" value="0"
style="width:300px;height:16px;"/>
<html:span id="dialog.progressPercent" style="border-left:5px solid lightgray;">
0%
&percentMsg;
</html:span>
</html:td>
</html:tr>

Просмотреть файл

@ -1,12 +1,67 @@
<!-- extracted from downloadProgress.xul -->
<!ENTITY downloadWindow.title "Saving file">
<!ENTITY location "Location">
<!ENTITY saving "Saving">
<!ENTITY status "Status:">
<!-- LOCALIZATION NOTE (dialogStatus.label): Do NOT translate "nn.n" and "mm.m" -->
<!ENTITY dialogStatus.label "( nn.nK of mm.mK bytes )">
<!ENTITY timeLeft "Time Left:">
<!ENTITY dialogTimeLeft.label "?">
<!ENTITY location "Location">
<!ENTITY saving "Saving">
<!ENTITY status "Status:">
<!ENTITY timeElapsed "Elapsed Time:">
<!ENTITY timeLeft "Time Left:">
<!ENTITY dialogCancel.label "Cancel">
<!ENTITY confirmCancel "Are you sure you want to cancel the saving of this file?">
<!-- LOCALIZATION NOTE
This string is used to generate the status message used during
file download.
#1 will be replaced by the number of bytes downloaded thus far
#2 will be replaced by the total number of bytes to be downloaded
#3 will be replaced by the download rate (in Kbytes per second) -->
<!ENTITY progressMsg "#1K of #2K bytes (at #3K bytes/sec)">
<!-- LOCALIZATION NOTE
This string is used when the time remaining is unknown. -->
<!ENTITY unknownTime "">
<!-- LOCALIZATION NOTE
This string is used to format elapsed/remaining times when the
time exceeds 1 hour in length.
#1 will be replaced by the number of hours
#2 will be replaced by the number of minutes
#3 will be replaced by the number of seconds -->
<!ENTITY longTimeFormat "#1:#2:#3">
<!-- LOCALIZATION NOTE
This string is used to format elapsed/remaining times when the
time is less than 1 hour in length. Note that you can leave
"#1" out of this string to omit the leading "00:" if you so choose.
#1 will be replaced by the number of hours
#2 will be replaced by the number of minutes
#3 will be replaced by the number of seconds -->
<!ENTITY shortTimeFormat "#2:#3">
<!-- LOCALIZATION NOTE
This string is displayed when the download is complete. The insert
"#1" is replaced by the elapsed time, formatted according to the
xxxTimeFormat strings defined above). You can omit "#1" if you don't
want the elapsed time in the message.
#1 will be replaced by the elapsed time -->
<!ENTITY completeMsg "Download complete (elapsed time was #1)">
<!-- LOCALIZATION NOTE
This string is used to format the text to the right of the progress
meter.
#1 will be replaced by the percentage of the file that has been saved -->
<!ENTITY percentMsg "#1&#037;">

Просмотреть файл

@ -332,11 +332,6 @@ nsStreamXferOp::OnStopRequest( nsIChannel *channel,
const PRUnichar *aMsg ) {
nsresult rv = NS_OK;
#ifdef DEBUG_law
DEBUG_PRINTF( PR_STDOUT, "nsStreamXferOp::OnStopRequest notified of input completion, status=0x%08X\n",
(int)aStatus );
#endif
// Close the output stream.
if ( mOutputStream ) {
rv = mOutputStream->Close();