ShowDialog() public method

public ShowDialog ( IWin32Window owner, ExtractionProcedure extractionProcedure, object state = null ) : DialogResult
owner IWin32Window
extractionProcedure ExtractionProcedure
state object
return DialogResult
Ejemplo n.º 1
0
        private void InteractiveExtractNodes(TreeNode[] nodes)
        {
            extractionSettingsDialog.AllowRecurse = true;

            if (extractionSettingsDialog.ShowDialog(this) != DialogResult.OK)
            {
                return;
            }

            // Save the settings now…
            Settings.Default.ExtractionDirectory      = extractionSettingsDialog.DestinationDirectory;
            Settings.Default.ExtractionRecurse        = extractionSettingsDialog.Recurse;
            Settings.Default.ExtractionOverwriteFiles = extractionSettingsDialog.OverwriteFiles;

            Settings.Default.Save();

            var   directoryInfo  = new DirectoryInfo(extractionSettingsDialog.DestinationDirectory);
            ulong totalSize      = 0;
            int   totalFileCount = 0;

            // Initialize the stack.
            extractionStack = extractionStack ?? new Stack <TreeNode>();
            extractionStack.Clear();

            // Proceed to a tree walk for each requested node, in order to compute total file count and total size
            {
                foreach (var node in nodes)
                {
                    var currentNode = node;
                    do
                    {
                        if (currentNode.Nodes.Count > 0 && (extractionSettingsDialog.Recurse || extractionStack.Count == 0))
                        {
                            extractionStack.Push(currentNode);
                            currentNode = currentNode.FirstNode;
                        }
                        else
                        {
                            var file = currentNode.Tag as MpqFile;

                            if (file != null)
                            {
                                totalSize += unchecked ((ulong)file.Size);
                                checked { totalFileCount++; }                                 // Maybe this will fail someday, but I don't think the current Win32 ListView can handle more than 2^31 nodes…
                            }

                            while (currentNode == null || (currentNode != node && (currentNode = currentNode.NextNode) == null) && extractionStack.Count > 0)
                            {
                                if ((currentNode = extractionStack.Pop()) != node)
                                {
                                    currentNode = currentNode.NextNode;
                                }
                            }
                        }
                    } while (currentNode != node);
                }
            }

            // TODO: Make something a little better…
            if (totalFileCount == 0)
            {
                return;
            }

            // Initialize the extraction progress dialog
            extractionProgressionDialog.TotalSize     = totalSize;
            extractionProgressionDialog.ProcessedSize = 0;

            extractionProgressionDialog.TotalFileCount     = totalFileCount;
            extractionProgressionDialog.ProcessedFileCount = 0;

            extractionProgressionDialog.CurrentFileName = null;

            // Proceed to a tree walk for each requested node, but this time for doing real work
            // The extraction will be done on a separate thread, with progress displayed by the modal dialog
            extractionProgressionDialog.ShowDialog
            (
                this,
                (dialog, state) =>
            {
                var buffer             = new byte[4096];
                int extractedFileCount = 0;

                foreach (var node in nodes)
                {
                    string directoryPhysicalPath = directoryInfo.FullName;
                    var currentNode = node;
                    do
                    {
                        if (currentNode.Nodes.Count > 0 && (extractionSettingsDialog.Recurse || extractionStack.Count == 0))
                        {
                            // Store the relative path into the tag, which should be null for directories…
                            currentNode.Tag       = directoryPhysicalPath;
                            directoryPhysicalPath = Path.Combine(directoryPhysicalPath, currentNode.Text);

                            if (!Directory.Exists(directoryPhysicalPath))
                            {
                                try { Directory.CreateDirectory(directoryPhysicalPath); }
                                catch (Exception ex)
                                {
                                    dialog.ErrorDialog(ex.Message);
                                    return;
                                }
                            }

                            extractionStack.Push(currentNode);
                            currentNode = currentNode.FirstNode;
                        }
                        else
                        {
                            var file = currentNode.Tag as MpqFile;

                            if (file != null)
                            {
                                string filePhysicalPath = Path.Combine(directoryPhysicalPath, currentNode.Text);
                                bool canExtract         = false;

                                dialog.UpdateFileInformation(extractedFileCount + 1, file.Name);

                                if (extractionSettingsDialog.OverwriteFiles || !File.Exists(filePhysicalPath))
                                {
                                    canExtract = true;
                                }
                                else
                                {
                                    switch (dialog.AskForOverwrite(currentNode.Text, directoryPhysicalPath, unchecked ((ulong)file.Size)))
                                    {
                                    case DialogResult.Yes: canExtract = true; break;

                                    case DialogResult.No: canExtract = false; break;

                                    case DialogResult.Cancel: return;
                                    }
                                }

                                if (canExtract)
                                {
                                    try
                                    {
                                        using (var inputStream = file.Open())
                                            using (var outputStream = File.OpenWrite(filePhysicalPath))
                                            {
                                                int byteCounter = 0;
                                                int length;

                                                do
                                                {
                                                    length = inputStream.Read(buffer, 0, 4096);
                                                    outputStream.Write(buffer, 0, length);
                                                    if ((byteCounter += length) >= 0x100000)
                                                    {
                                                        dialog.ProcessedSize += 0x100000UL;
                                                        byteCounter          -= 0x100000;
                                                    }
                                                }while (length == 4096);

                                                if (byteCounter > 0)
                                                {
                                                    dialog.ProcessedSize += unchecked ((ulong)byteCounter);
                                                }
                                                extractedFileCount++;
                                            }
                                    }
                                    catch (Exception ex)
                                    {
                                        ErrorDialog(ex.ToString());
                                        return;
                                    }
                                }
                                else
                                {
                                    dialog.TotalSize      = totalSize -= unchecked ((ulong)file.Size);
                                    dialog.TotalFileCount = totalFileCount--;
                                }
                            }

                            while (currentNode == null || (currentNode != node && (currentNode = currentNode.NextNode) == null) && extractionStack.Count > 0)
                            {
                                currentNode           = extractionStack.Pop();
                                directoryPhysicalPath = currentNode.Tag as string;
                                currentNode.Tag       = null;                                   // Clean the tag when no longer needed

                                if (currentNode != node)
                                {
                                    currentNode = currentNode.NextNode;
                                }
                            }
                        }
                    } while (currentNode != node);
                }
            }
            );
        }