SHA256
-Progress Bar implemented
- Copy Speed Limit implemented
This commit is contained in:
1 parent
7550cab2c5
commit
c8211fa7ae
2 files changed
+164
-54
No files matched your search
+108
-3
@@ -17,6 +17,9 @@ using System.IO;
|
||||
using XML;
|
||||
using TapeCatalog.Methods;
|
||||
using System.Windows.Threading;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Globalization;
|
||||
|
||||
|
||||
|
||||
@@ -360,7 +363,7 @@ namespace TapeCatalog
|
||||
Copy.PopulateTree(CopyTreeView, SourceTextBox.Text);
|
||||
}
|
||||
|
||||
private void COPY_SELECTED_TO_ARCHIVE(object sender, RoutedEventArgs e)
|
||||
private async void COPY_SELECTED_TO_ARCHIVE(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var archivePath = ArchiveTextBox.Text?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(archivePath) || !Directory.Exists(archivePath))
|
||||
@@ -376,8 +379,104 @@ namespace TapeCatalog
|
||||
return;
|
||||
}
|
||||
|
||||
var result = Copy.CopySelectedToArchive(CopyTreeView, sourceRoot, archivePath);
|
||||
MessageBox.Show(this, $"Copy finished. Success: {result.Item1}, Failed: {result.Item2}", "Copy completed", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
var files = Copy.GetCheckedFiles(CopyTreeView);
|
||||
if (files.Count == 0)
|
||||
{
|
||||
MessageBox.Show(this, "No files selected.", "Nothing to copy", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
// prepare progress UI based on bytes
|
||||
long totalBytes = 0;
|
||||
foreach (var f in files)
|
||||
{
|
||||
try { totalBytes += new FileInfo(f).Length; } catch { }
|
||||
}
|
||||
|
||||
if (totalBytes <= 0) totalBytes = 1; // avoid zero maximum
|
||||
|
||||
CopyProgressBar.Minimum = 0;
|
||||
CopyProgressBar.Maximum = (double)totalBytes;
|
||||
CopyProgressBar.Value = 0;
|
||||
CopyProgressText.Text = "Starting...";
|
||||
|
||||
long bytesCopied = 0;
|
||||
int copied = 0, failed = 0;
|
||||
|
||||
// parse speed limit (MB/s) from settings; 0 or invalid = unlimited
|
||||
double speedMb = 0;
|
||||
var speedText = CopySpeedTextBox?.Text?.Trim();
|
||||
if (!string.IsNullOrWhiteSpace(speedText))
|
||||
double.TryParse(speedText, NumberStyles.Float, CultureInfo.InvariantCulture, out speedMb);
|
||||
|
||||
double speedBytesPerSec = speedMb > 0 ? speedMb * 1024.0 * 1024.0 : 0;
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
const int bufferSize = 64 * 1024; // 64KB
|
||||
var buffer = new byte[bufferSize];
|
||||
|
||||
for (int i = 0; i < files.Count; i++)
|
||||
{
|
||||
var src = files[i];
|
||||
try
|
||||
{
|
||||
var fileDir = System.IO.Path.GetDirectoryName(src) ?? string.Empty;
|
||||
string relative;
|
||||
if (!string.IsNullOrWhiteSpace(sourceRoot) && fileDir.StartsWith(sourceRoot, StringComparison.OrdinalIgnoreCase))
|
||||
relative = fileDir.Substring(sourceRoot.Length).TrimStart(System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar);
|
||||
else
|
||||
relative = System.IO.Path.GetFileName(fileDir);
|
||||
|
||||
var destDir = System.IO.Path.Combine(archivePath, relative);
|
||||
Directory.CreateDirectory(destDir);
|
||||
var destFile = System.IO.Path.Combine(destDir, System.IO.Path.GetFileName(src));
|
||||
|
||||
using (var inStream = new FileStream(src, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var outStream = new FileStream(destFile, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
long fileBytesCopied = 0;
|
||||
var sw = Stopwatch.StartNew();
|
||||
int read;
|
||||
while ((read = inStream.Read(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
outStream.Write(buffer, 0, read);
|
||||
fileBytesCopied += read;
|
||||
Interlocked.Add(ref bytesCopied, read);
|
||||
|
||||
// throttling per file
|
||||
if (speedBytesPerSec > 0)
|
||||
{
|
||||
double desiredMs = (fileBytesCopied / speedBytesPerSec) * 1000.0;
|
||||
double actualMs = sw.Elapsed.TotalMilliseconds;
|
||||
if (desiredMs > actualMs)
|
||||
{
|
||||
int sleep = (int)Math.Ceiling(desiredMs - actualMs);
|
||||
if (sleep > 0) Thread.Sleep(sleep);
|
||||
}
|
||||
}
|
||||
|
||||
// update UI progress
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
CopyProgressBar.Value = Math.Min((double)bytesCopied, CopyProgressBar.Maximum);
|
||||
double pct = (CopyProgressBar.Value / CopyProgressBar.Maximum) * 100.0;
|
||||
CopyProgressText.Text = $"{FormatBytes(bytesCopied)} / {FormatBytes(totalBytes)} ({pct:F1}%)";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
copied++;
|
||||
}
|
||||
catch
|
||||
{
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
CopyProgressText.Text = $"Done. Success: {copied}, Failed: {failed}. {FormatBytes(bytesCopied)} copied.";
|
||||
MessageBox.Show(this, $"Copy finished. Success: {copied}, Failed: {failed}", "Copy completed", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
|
||||
private void UpdateCopySummary()
|
||||
@@ -435,6 +534,12 @@ namespace TapeCatalog
|
||||
// swallow periodic update errors; avoid UI disruptions
|
||||
}
|
||||
}
|
||||
|
||||
private static string FormatBytes(long bytes)
|
||||
{
|
||||
double mb = bytes / 1024.0 / 1024.0;
|
||||
return mb.ToString("F2") + " MB";
|
||||
}
|
||||
}
|
||||
#endregion (VERIFY_SIZES)
|
||||
public class FileEntry : System.ComponentModel.INotifyPropertyChanged
|
||||
|
||||
Reference in new issue
Block a user