From 3d493d3acedd9fdbc2484fe2695482cf8a0d8fb4 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Tue, 10 May 2011 09:39:38 +1200 Subject: [PATCH] Package download works. Download error messages need polish. --- OpenRA.FileFormats/InstallUtils.cs | 74 +++++++++----- OpenRA.Mods.Cnc/Widgets/CncInstallLogic.cs | 93 +++++++++++++++++- .../Widgets/Delegates/GameInitDelegate.cs | 45 ++------- mods/cnc/chrome/install.yaml | 96 +++++++++---------- 4 files changed, 200 insertions(+), 108 deletions(-) diff --git a/OpenRA.FileFormats/InstallUtils.cs b/OpenRA.FileFormats/InstallUtils.cs index d86f38a2ef..36ab2de35e 100644 --- a/OpenRA.FileFormats/InstallUtils.cs +++ b/OpenRA.FileFormats/InstallUtils.cs @@ -26,30 +26,7 @@ namespace OpenRA.FileFormats if (e != null) yield return e; else break; } } - - public static void ExtractZip(this ZipInputStream z, string destPath, List extracted, Action Extracting) - { - foreach (var entry in z.GetEntries()) - { - if (!entry.IsFile) continue; - Extracting(entry.Name); - Directory.CreateDirectory(Path.Combine(destPath, Path.GetDirectoryName(entry.Name))); - var path = Path.Combine(destPath, entry.Name); - extracted.Add(path); - - using (var f = File.Create(path)) - { - int bufSize = 2048; - byte[] buf = new byte[bufSize]; - while ((bufSize = z.Read(buf, 0, buf.Length)) > 0) - f.Write(buf, 0, bufSize); - } - } - - z.Close(); - } - // TODO: The package should be mounted into its own context to avoid name collisions with installed files public static bool ExtractFromPackage(string srcPath, string package, string[] files, string destPath, Action onProgress, Action onError) { @@ -93,5 +70,56 @@ namespace OpenRA.FileFormats onProgress("Extraction complete"); return true; } + + public static bool ExtractZip(string zipFile, string dest, Action onProgress, Action onError) + { + if (!File.Exists(zipFile)) + { + onError("Invalid path: "+zipFile); + return false; + } + + List extracted = new List(); + try + { + var z = new ZipInputStream(File.OpenRead(zipFile)); + z.ExtractZip(dest, extracted, s => onProgress("Extracting "+s)); + onProgress("Extraction complete"); + } + catch (SharpZipBaseException) + { + foreach(var f in extracted) + File.Delete(f); + + onError("Archive corrupt"); + return false; + } + return true; + } + + // TODO: this belongs in FileSystem/ZipFile + static void ExtractZip(this ZipInputStream z, string destPath, List extracted, Action onProgress) + { + foreach (var entry in z.GetEntries()) + { + if (!entry.IsFile) continue; + + onProgress(entry.Name); + + Directory.CreateDirectory(Path.Combine(destPath, Path.GetDirectoryName(entry.Name))); + var path = Path.Combine(destPath, entry.Name); + extracted.Add(path); + + using (var f = File.Create(path)) + { + int bufSize = 2048; + byte[] buf = new byte[bufSize]; + while ((bufSize = z.Read(buf, 0, buf.Length)) > 0) + f.Write(buf, 0, bufSize); + } + } + + z.Close(); + } } } \ No newline at end of file diff --git a/OpenRA.Mods.Cnc/Widgets/CncInstallLogic.cs b/OpenRA.Mods.Cnc/Widgets/CncInstallLogic.cs index b5efe7b740..d5c1b57628 100755 --- a/OpenRA.Mods.Cnc/Widgets/CncInstallLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/CncInstallLogic.cs @@ -10,11 +10,14 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.IO; using System.Linq; +using System.Net; using System.Threading; using OpenRA.FileFormats; using OpenRA.Widgets; +using OpenRA.Mods.RA.Widgets.Delegates; namespace OpenRA.Mods.Cnc.Widgets { @@ -41,7 +44,6 @@ namespace OpenRA.Mods.Cnc.Widgets panel.GetWidget("QUIT_BUTTON").OnClick = Game.Exit; // TODO: - panel.GetWidget("DOWNLOAD_BUTTON").IsDisabled = () => true; panel.GetWidget("MODS_BUTTON").IsDisabled = () => true; } } @@ -136,4 +138,93 @@ namespace OpenRA.Mods.Cnc.Widgets t.Start(); } } + + public class CncDownloadPackagesLogic : IWidgetDelegate + { + Widget panel; + Dictionary installData; + ProgressBarWidget progressBar; + LabelWidget statusLabel; + Action continueLoading; + + [ObjectCreator.UseCtor] + public CncDownloadPackagesLogic([ObjectCreator.Param] Widget widget, + [ObjectCreator.Param] Dictionary installData, + [ObjectCreator.Param] Action continueLoading) + { + this.installData = installData; + this.continueLoading = continueLoading; + + panel = widget.GetWidget("INSTALL_DOWNLOAD_PANEL"); + progressBar = panel.GetWidget("PROGRESS_BAR"); + statusLabel = panel.GetWidget("STATUS_LABEL"); + + ShowDownloadDialog(); + } + + + void ShowDownloadDialog() + { + statusLabel.GetText = () => "Initializing..."; + progressBar.SetIndeterminate(false); + + var retryButton = panel.GetWidget("RETRY_BUTTON"); + retryButton.IsVisible = () => false; + + var cancelButton = panel.GetWidget("CANCEL_BUTTON"); + + // Save the package to a temp file + var file = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + var dest = new string[] { Platform.SupportDir, "Content", "cnc" }.Aggregate(Path.Combine); + + Action onDownloadProgress = i => + { + progressBar.Percentage = i.ProgressPercentage; + statusLabel.GetText = () => "Downloading {1}/{2} kB ({0}%)".F(i.ProgressPercentage, i.BytesReceived / 1024, i.TotalBytesToReceive / 1024); + }; + + Action onExtractProgress = s => + { + statusLabel.GetText = () => s; + }; + + Action onError = s => + { + statusLabel.GetText = () => "Error: "+s; + retryButton.IsVisible = () => true; + }; + + Action onDownloadComplete = (i, cancelled) => + { + if (i.Error != null) + { + onError(i.Error.Message); + return; + } + else if (cancelled) + { + onError("Download cancelled"); + return; + } + + // Automatically extract + statusLabel.GetText = () => "Extracting..."; + progressBar.SetIndeterminate(true); + if (InstallUtils.ExtractZip(file, dest, onExtractProgress, onError)) + { + Game.RunAfterTick(() => + { + Widget.CloseWindow(); // Progress panel + Widget.CloseWindow(); // Install choice panel + continueLoading(); + }); + } + }; + + var dl = new Download(installData["PackageURL"], file, onDownloadProgress, onDownloadComplete); + + cancelButton.OnClick = () => { dl.Cancel(); Widget.CloseWindow(); }; + retryButton.OnClick = () => { dl.Cancel(); ShowDownloadDialog(); }; + } + } } diff --git a/OpenRA.Mods.RA/Widgets/Delegates/GameInitDelegate.cs b/OpenRA.Mods.RA/Widgets/Delegates/GameInitDelegate.cs index 2de78b7aef..9a0b3442c1 100755 --- a/OpenRA.Mods.RA/Widgets/Delegates/GameInitDelegate.cs +++ b/OpenRA.Mods.RA/Widgets/Delegates/GameInitDelegate.cs @@ -142,10 +142,10 @@ namespace OpenRA.Mods.RA.Widgets.Delegates var progress = window.GetWidget("PROGRESS"); // Save the package to a temp file - var file = Path.GetTempPath() + Path.DirectorySeparatorChar + Path.GetRandomFileName(); + var file = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); Action onDownloadChange = i => { - status.GetText = () => "Downloading {1}/{2} kB ({0}%)".F(i.ProgressPercentage, i.BytesReceived/1024, i.TotalBytesToReceive/1024); + status.GetText = () => "Downloading {1}/{2} kB ({0}%)".F(i.ProgressPercentage, i.BytesReceived / 1024, i.TotalBytesToReceive / 1024); progress.Percentage = i.ProgressPercentage; }; @@ -180,28 +180,11 @@ namespace OpenRA.Mods.RA.Widgets.Delegates } bool ExtractZip(Widget window, string zipFile, string dest) - { - if (!File.Exists(zipFile)) - { - ShowError(window, "Invalid path: "+zipFile); - return false; - } - + { var status = window.GetWidget("STATUS"); - List extracted = new List(); - try - { - new ZipInputStream(File.OpenRead(zipFile)).ExtractZip(dest, extracted, s => status.GetText = () => "Extracting "+s); - } - catch (SharpZipBaseException) - { - foreach(var f in extracted) - File.Delete(f); - ShowError(window, "Archive corrupt"); - return false; - } - status.GetText = () => "Extraction complete"; - return true; + return InstallUtils.ExtractZip( zipFile, dest, + s => status.GetText = () => s, + e => ShowError(window, e)); } bool ExtractFromPackage(Widget window, string srcPath, string package, string[] files, string destPath) @@ -216,19 +199,9 @@ namespace OpenRA.Mods.RA.Widgets.Delegates bool CopyFiles(Widget window, string srcPath, string[] files, string destPath) { var status = window.GetWidget("STATUS"); - - foreach (var file in files) - { - var fromPath = Path.Combine(srcPath, file); - if (!File.Exists(fromPath)) - { - ShowError(window, "Cannot find "+file); - return false; - } - status.GetText = () => "Extracting "+file.ToLowerInvariant(); - File.Copy(fromPath, Path.Combine(destPath, Path.GetFileName(file).ToLowerInvariant()), true); - } - return true; + return InstallUtils.CopyFiles(srcPath, files, destPath, + s => status.GetText = () => s, + e => ShowError(window, e)); } bool InstallRAPackages(Widget window, string source, string dest) diff --git a/mods/cnc/chrome/install.yaml b/mods/cnc/chrome/install.yaml index 6445517204..f1111b26c3 100644 --- a/mods/cnc/chrome/install.yaml +++ b/mods/cnc/chrome/install.yaml @@ -71,6 +71,7 @@ Container@INSTALL_PANEL: Width:140 Height:35 Text:Use CD + Container@INSTALL_FROMCD_PANEL: Id:INSTALL_FROMCD_PANEL Delegate:CncInstallFromCDLogic @@ -123,57 +124,56 @@ Container@INSTALL_FROMCD_PANEL: Width:140 Height:35 Text:Retry -Background@INIT_DOWNLOAD: - Id:INIT_DOWNLOAD + +Container@INSTALL_DOWNLOAD_PANEL: + Id:INSTALL_DOWNLOAD_PANEL + Delegate:CncDownloadPackagesLogic X:(WINDOW_RIGHT - WIDTH)/2 - Y:(WINDOW_BOTTOM - HEIGHT)/2 - Width:500 - Height:160 + Y:(WINDOW_BOTTOM - 150)/2 + Width:640 + Height:150 Children: Label@TITLE: - X:0 - Y:20 Width:PARENT_RIGHT - Height:25 - Text:Downloading C&C Content + Y:0-25 + Font:BigBold + Contrast:true Align:Center - Bold:True - ProgressBar@PROGRESS: - Id:PROGRESS - X:50 - Y:55 - Width:PARENT_RIGHT - 100 - Height:25 - Label@STATUS: - Id:STATUS - X:50 - Y:80 - Width:PARENT_RIGHT - 100 - Height:25 - Align:Left - Button@RETRY: - Id:RETRY - X:PARENT_RIGHT - 280 - Y:PARENT_BOTTOM - 45 - Width:120 - Height:25 - Visible: false - Text:Retry - Bold:True - Button@CANCEL: - Id:CANCEL - X:PARENT_RIGHT - 140 - Y:PARENT_BOTTOM - 45 - Width:120 - Height:25 + Text:Downloading Content + Background@bg: + Width:640 + Height:150 + Background:panel-black + Children: + Image@INSTALL: + X:11 + Y:11 + ImageCollection: install + ImageName: logo + ProgressBar@PROGRESS_BAR: + Id:PROGRESS_BAR + X:170 + Y:45 + Width:PARENT_RIGHT - 185 + Height:35 + Label@STATUS_LABEL: + Id:STATUS_LABEL + X:170 + Y:85 + Width:PARENT_RIGHT - 185 + Height:25 + Align:Left + Text:Initialising... + CncMenuButton@CANCEL_BUTTON: + Id:CANCEL_BUTTON + Y:149 + Width:140 + Height:35 Text:Cancel - Bold:True - Button@EXTRACT: - Id:EXTRACT - X:PARENT_RIGHT - 140 - Y:PARENT_BOTTOM - 45 - Width:120 - Height:25 - Visible: false - Text:Extract - Bold:True \ No newline at end of file + CncMenuButton@RETRY_BUTTON: + Id:RETRY_BUTTON + X:500 + Y:149 + Width:140 + Height:35 + Text:Retry \ No newline at end of file