diff --git a/CreateArchive.xaml.cs b/CreateArchive.xaml.cs
index b31cd94a..98d25107 100644
--- a/CreateArchive.xaml.cs
+++ b/CreateArchive.xaml.cs
@@ -1,12 +1,12 @@
using System.IO;
using System.Windows;
+using System.Windows.Controls;
using System.Windows.Input;
using System.Text;
using System.Linq;
using Microsoft.Win32;
using GARbro.GUI.Strings;
using GameRes;
-using System.Windows.Controls;
namespace GARbro.GUI
{
@@ -15,17 +15,31 @@ namespace GARbro.GUI
///
public partial class CreateArchiveDialog : Window
{
- public CreateArchiveDialog ()
+ public CreateArchiveDialog (string initial_name = "")
{
InitializeComponent ();
- this.ArchiveFormat.ItemsSource = FormatCatalog.Instance.ArcFormats;
+ if (!string.IsNullOrEmpty (initial_name))
+ {
+ var format = this.ArchiveFormat.SelectedItem as ArchiveFormat;
+ if (null != format)
+ ArchiveName.Text = Path.ChangeExtension (initial_name, format.Extensions.First());
+ }
}
public ResourceOptions ArchiveOptions { get; private set; }
void Button_Click (object sender, RoutedEventArgs e)
{
+ string arc_name = Path.GetFullPath (ArchiveName.Text);
+ if (File.Exists (arc_name))
+ {
+ string text = string.Format (guiStrings.MsgOverwrite, arc_name);
+ var rc = MessageBox.Show (this, text, guiStrings.TextConfirmOverwrite, MessageBoxButton.YesNo,
+ MessageBoxImage.Question);
+ if (MessageBoxResult.Yes != rc)
+ return;
+ }
DialogResult = true;
}
@@ -92,11 +106,21 @@ namespace GARbro.GUI
}
OptionsWidget.Content = widget;
OptionsWidget.Visibility = null != widget ? Visibility.Visible : Visibility.Hidden;
+
+ if (!string.IsNullOrEmpty (ArchiveName.Text))
+ {
+ ArchiveName.Text = Path.ChangeExtension (ArchiveName.Text, format.Extensions.First());
+ }
}
void CanExecuteAlways (object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
+
+ private void ArchiveName_TextChanged (object sender, RoutedEventArgs e)
+ {
+ this.ButtonOk.IsEnabled = ArchiveName.Text.Length > 0;
+ }
}
}
diff --git a/GARbro.GUI.csproj b/GARbro.GUI.csproj
index c443c9c8..d69a7023 100644
--- a/GARbro.GUI.csproj
+++ b/GARbro.GUI.csproj
@@ -69,7 +69,7 @@
LocalIntranet
- Properties\app.manifest
+ app.manifest
true
@@ -130,11 +130,14 @@
ExtractFile.xaml
+
+
-
+
+
True
True
@@ -198,6 +201,7 @@
guiStrings.Designer.cs
+
diff --git a/GameRes/GameRes.cs b/GameRes/GameRes.cs
index e5ffe475..c5bd4335 100644
--- a/GameRes/GameRes.cs
+++ b/GameRes/GameRes.cs
@@ -144,10 +144,10 @@ namespace GameRes
}
///
- /// Create resource archive named containing entries from the
+ /// Create resource wihin stream containing entries from the
/// supplied and applying necessary .
///
- public virtual void Create (string filename, IEnumerable list, ResourceOptions options = null)
+ public virtual void Create (Stream file, IEnumerable list, ResourceOptions options = null)
{
throw new NotImplementedException ("ArchiveFormat.Create is not implemented");
}
@@ -329,7 +329,7 @@ namespace GameRes
}
}
- public class InvalidFormatException : Exception
+ public class InvalidFormatException : FileFormatException
{
public InvalidFormatException() : base(garStrings.MsgInvalidFormat) { }
public InvalidFormatException (string msg) : base (msg) { }
@@ -346,4 +346,37 @@ namespace GameRes
public InvalidEncryptionScheme() : base(garStrings.MsgInvalidEncryption) { }
public InvalidEncryptionScheme (string msg) : base (msg) { }
}
+
+ public class FileSizeException : Exception
+ {
+ public FileSizeException () : base (garStrings.MsgFileTooLarge) { }
+ public FileSizeException (string msg) : base (msg) { }
+ }
+
+ public class InvalidFileName : Exception
+ {
+ public string FileName { get; set; }
+
+ public InvalidFileName (string filename)
+ : this (filename, garStrings.MsgInvalidFileName)
+ {
+ }
+
+ public InvalidFileName (string filename, string message)
+ : base (message)
+ {
+ FileName = filename;
+ }
+
+ public InvalidFileName (string filename, Exception X)
+ : this (filename, garStrings.MsgInvalidFileName, X)
+ {
+ }
+
+ public InvalidFileName (string filename, string message, Exception X)
+ : base (message, X)
+ {
+ FileName = filename;
+ }
+ }
}
diff --git a/GameRes/Strings/garStrings.Designer.cs b/GameRes/Strings/garStrings.Designer.cs
index 7b972b7c..7cdce5cd 100644
--- a/GameRes/Strings/garStrings.Designer.cs
+++ b/GameRes/Strings/garStrings.Designer.cs
@@ -60,6 +60,15 @@ namespace GameRes.Strings {
}
}
+ ///
+ /// Looks up a localized string similar to File is too large.
+ ///
+ public static string MsgFileTooLarge {
+ get {
+ return ResourceManager.GetString("MsgFileTooLarge", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Inappropriate encryption scheme.
///
@@ -69,6 +78,15 @@ namespace GameRes.Strings {
}
}
+ ///
+ /// Looks up a localized string similar to Invalid file name.
+ ///
+ public static string MsgInvalidFileName {
+ get {
+ return ResourceManager.GetString("MsgInvalidFileName", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Invalid file format.
///
diff --git a/GameRes/Strings/garStrings.resx b/GameRes/Strings/garStrings.resx
index 6314d2b3..480912c6 100644
--- a/GameRes/Strings/garStrings.resx
+++ b/GameRes/Strings/garStrings.resx
@@ -117,9 +117,15 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ File is too large
+
Inappropriate encryption scheme
+
+ Invalid file name
+
Invalid file format
diff --git a/GameRes/Strings/garStrings.ru-RU.resx b/GameRes/Strings/garStrings.ru-RU.resx
index 6a772f39..c8040a17 100644
--- a/GameRes/Strings/garStrings.ru-RU.resx
+++ b/GameRes/Strings/garStrings.ru-RU.resx
@@ -117,9 +117,15 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ Слишком большой размер файла
+
Неподходящий метод шифрования
+
+ Недопустимое имя файла
+
Некорректный формат файла
diff --git a/GarCreate.cs b/GarCreate.cs
new file mode 100644
index 00000000..791ec931
--- /dev/null
+++ b/GarCreate.cs
@@ -0,0 +1,140 @@
+//! \file GarCreate.cs
+//! \date Fri Jul 25 05:56:29 2014
+//! \brief Create archive frontend.
+//
+// Copyright (C) 2014 by morkt
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Linq;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Windows;
+using System.Windows.Input;
+using GameRes;
+using GARbro.GUI.Strings;
+
+namespace GARbro.GUI
+{
+ public partial class MainWindow : Window
+ {
+ private void CreateArchiveExec (object sender, ExecutedRoutedEventArgs e)
+ {
+ try
+ {
+ Directory.SetCurrentDirectory (CurrentPath);
+ var items = CurrentDirectory.SelectedItems.Cast();
+ string arc_name = Path.GetFileName (CurrentPath);
+ if (!items.Skip (1).Any()) // items.Count() == 1
+ {
+ var item = items.First();
+ if (item.IsDirectory)
+ arc_name = Path.GetFileNameWithoutExtension (item.Name);
+ }
+
+ var dialog = new CreateArchiveDialog (arc_name);
+ dialog.Owner = this;
+ if (!dialog.ShowDialog().Value)
+ return;
+ if (string.IsNullOrEmpty (dialog.ArchiveName.Text))
+ {
+ SetStatusText ("Archive name is empty");
+ return;
+ }
+ var format = dialog.ArchiveFormat.SelectedItem as ArchiveFormat;
+ if (null == format)
+ {
+ SetStatusText ("Format is not selected");
+ return;
+ }
+
+ IEnumerable file_list;
+ if (format.IsHierarchic)
+ file_list = BuildFileList (items, AddFilesRecursive);
+ else
+ file_list = BuildFileList (items, AddFilesFromDir);
+
+ arc_name = Path.GetFullPath (dialog.ArchiveName.Text);
+ using (var tmp_file = new GARbro.Shell.TemporaryFile (Path.GetDirectoryName (arc_name),
+ Path.GetRandomFileName()))
+ {
+ using (var file = File.Create (tmp_file.Name))
+ format.Create (file, file_list, dialog.ArchiveOptions);
+ GARbro.Shell.File.Rename (tmp_file.Name, arc_name);
+ }
+ }
+ catch (Exception X)
+ {
+ PopupError (X.Message, guiStrings.TextCreateArchiveError);
+ }
+ }
+
+ delegate void AddFilesEnumerator (IList list, string path, DirectoryInfo path_info);
+
+ IEnumerable BuildFileList (IEnumerable files, AddFilesEnumerator add_files)
+ {
+ var list = new List();
+ foreach (var entry in files)
+ {
+ if (entry.IsDirectory)
+ {
+ if (".." != entry.Name)
+ {
+ var dir = new DirectoryInfo (entry.Name);
+ add_files (list, entry.Name, dir);
+ }
+ }
+ else if (entry.Size < uint.MaxValue)
+ {
+ list.Add (entry.Source);
+ }
+ }
+ return list;
+ }
+
+ void AddFilesFromDir (IList list, string path, DirectoryInfo dir)
+ {
+ foreach (var file in dir.EnumerateFiles())
+ {
+ if (0 != (file.Attributes & (FileAttributes.Hidden | FileAttributes.System)))
+ continue;
+ if (file.Length >= uint.MaxValue)
+ continue;
+ string name = Path.Combine (path, file.Name);
+ var e = FormatCatalog.Instance.CreateEntry (name);
+ e.Size = (uint)file.Length;
+ list.Add (e);
+ }
+ }
+
+ void AddFilesRecursive (IList list, string path, DirectoryInfo info)
+ {
+ foreach (var dir in info.EnumerateDirectories())
+ {
+ string subdir = Path.Combine (path, dir.Name);
+ var subdir_info = new DirectoryInfo (subdir);
+ AddFilesRecursive (list, subdir, subdir_info);
+ }
+ AddFilesFromDir (list, path, info);
+ }
+ }
+}
diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs
index 9395c5ed..40fbff63 100644
--- a/MainWindow.xaml.cs
+++ b/MainWindow.xaml.cs
@@ -36,7 +36,6 @@ using System.Windows.Media;
using System.Windows.Threading;
using System.Threading;
using Microsoft.VisualBasic.FileIO;
-using Ookii.Dialogs.Wpf;
using GARbro.GUI.Properties;
using GARbro.GUI.Strings;
using GameRes;
@@ -772,220 +771,6 @@ namespace GARbro.GUI
*/
}
- ///
- /// Handle "Extract item" command.
- ///
- private void ExtractItemExec (object sender, ExecutedRoutedEventArgs e)
- {
- var entry = CurrentDirectory.SelectedItem as EntryViewModel;
- if (null == entry)
- return;
- try
- {
- if (!ViewModel.IsArchive)
- {
- if (!entry.IsDirectory)
- {
- var arc_dir = CurrentPath;
- var source = Path.Combine (arc_dir, entry.Name);
- string destination = arc_dir;
- // extract into directory named after archive
- if (!string.IsNullOrEmpty (Path.GetExtension (entry.Name)))
- destination = Path.GetFileNameWithoutExtension (source);
- ExtractArchive (source, destination);
- }
- }
- else if (null != m_app.CurrentArchive)
- {
- var vm = ViewModel as ArchiveViewModel;
- string destination = Path.GetDirectoryName (vm.Path);
- string arc_name = Path.GetFileName (vm.Path);
- if (entry.Name == ".." && vm.SubDir == "") // root entry
- {
- ExtractArchive (m_app.CurrentArchive, arc_name, destination);
- }
- else
- {
- ExtractFileFromArchive (entry, destination);
- }
- }
- }
- catch (Exception X)
- {
- PopupError (X.Message, guiStrings.MsgErrorExtracting);
- }
- }
-
- private void ExtractArchive (string path, string destination)
- {
- string arc_name = Path.GetFileName (path);
- FormatCatalog.Instance.LastError = null;
- var arc = ArcFile.TryOpen (path);
- if (null != arc)
- {
- ExtractArchive (arc, arc_name, destination);
- }
- else
- {
- string error_message;
- if (FormatCatalog.Instance.LastError != null)
- error_message = FormatCatalog.Instance.LastError.Message;
- else
- error_message = guiStrings.MsgUnknownFormat;
- SetStatusText (string.Format ("{1}: {0}", error_message, arc_name));
- }
- }
-
- private void ExtractArchive (ArcFile arc, string arc_name, string destination)
- {
- if (0 == arc.Dir.Count)
- {
- SetStatusText (string.Format ("{1}: {0}", guiStrings.MsgEmptyArchive, arc_name));
- return;
- }
- var extractDialog = new ExtractArchiveDialog (arc_name, destination);
- extractDialog.Owner = this;
- var result = extractDialog.ShowDialog();
- if (!result.Value)
- return;
-
- destination = extractDialog.DestinationDir.Text;
- if (!string.IsNullOrEmpty (destination))
- {
- destination = Path.GetFullPath (destination);
- Trace.WriteLine (destination, "Extract destination");
- StopWatchDirectoryChanges();
- try
- {
- Directory.CreateDirectory (destination);
- Directory.SetCurrentDirectory (destination);
- }
- finally
- {
- m_watcher.EnableRaisingEvents = true;
- }
- }
- IEnumerable file_list = arc.Dir;
- bool skip_images = !extractDialog.ExtractImages.IsChecked.Value;
- bool skip_script = !extractDialog.ExtractText.IsChecked.Value;
- if (skip_images || skip_script)
- file_list = file_list.Where (f => !(skip_images && f.Type == "image") && !(skip_script && f.Type == "script"));
-
- if (!file_list.Any())
- {
- SetStatusText (string.Format ("{1}: {0}", guiStrings.MsgNoFiles, arc_name));
- return;
- }
- ImageFormat image_format = null;
- if (!skip_images)
- image_format = extractDialog.GetImageFormat (extractDialog.ImageConversionFormat);
-
- SetStatusText (string.Format(guiStrings.MsgExtractingTo, arc_name, destination));
- ExtractFilesFromArchive (string.Format (guiStrings.MsgExtractingArchive, arc_name),
- arc, file_list, image_format);
- }
-
- private void ExtractFileFromArchive (EntryViewModel entry, string destination)
- {
- var extractDialog = new ExtractFile (entry, destination);
- extractDialog.Owner = this;
- var result = extractDialog.ShowDialog();
- if (!result.Value)
- return;
-
- var file_list = (ViewModel as ArchiveViewModel).GetFiles (entry);
-
- destination = extractDialog.DestinationDir.Text;
- if (!string.IsNullOrEmpty (destination))
- {
- destination = Path.GetFullPath (destination);
- Directory.CreateDirectory (destination);
- Directory.SetCurrentDirectory (destination);
- }
- ImageFormat format = null;
- if (entry.Type == "image")
- format = extractDialog.GetImageFormat (extractDialog.ImageConversionFormat);
-
- string arc_name = Path.GetFileName (CurrentPath);
- ExtractFilesFromArchive (string.Format (guiStrings.MsgExtractingFile, arc_name),
- m_app.CurrentArchive, file_list, format);
- }
-
- private void ExtractFilesFromArchive (string text, ArcFile arc, IEnumerable file_list,
- ImageFormat image_format = null)
- {
- file_list = file_list.OrderBy (e => e.Offset);
- var extractProgressDialog = new ProgressDialog ()
- {
- WindowTitle = guiStrings.TextTitle,
- Text = text,
- Description = "",
- MinimizeBox = true,
- };
- if (!file_list.Skip (1).Any()) // 1 == file_list.Count()
- {
- extractProgressDialog.Description = file_list.First().Name;
- extractProgressDialog.ProgressBarStyle = ProgressBarStyle.MarqueeProgressBar;
- }
- extractProgressDialog.DoWork += (s, e) =>
- {
- try
- {
- int total = file_list.Count();
- int i = 0;
- foreach (var entry in file_list)
- {
- if (extractProgressDialog.CancellationPending)
- break;
- if (total > 1)
- extractProgressDialog.ReportProgress (i*100/total, null, entry.Name);
- if (null != image_format && entry.Type == "image")
- ExtractImage (arc, entry, image_format);
- else
- arc.Extract (entry);
- ++i;
- }
- SetStatusText (string.Format (guiStrings.MsgExtractCompletePlural, i,
- Localization.Plural (i, "file")));
- }
- catch (Exception X)
- {
- SetStatusText (X.Message);
- }
- };
- extractProgressDialog.RunWorkerCompleted += (s, e) => {
- extractProgressDialog.Dispose();
- if (!ViewModel.IsArchive)
- {
- arc.Dispose();
- Dispatcher.Invoke (RefreshView);
- }
- };
- extractProgressDialog.ShowDialog (this);
- }
-
- private void CreateArchiveExec (object sender, ExecutedRoutedEventArgs e)
- {
- try
- {
- var dialog = new CreateArchiveDialog();
- dialog.Owner = this;
- if (!dialog.ShowDialog().Value || string.IsNullOrEmpty (dialog.ArchiveName.Text))
- return;
- var format = dialog.ArchiveFormat.SelectedItem as ArchiveFormat;
- if (null == format)
- return;
-
- string arc_name = Path.GetFullPath (dialog.ArchiveName.Text);
- var items = CurrentDirectory.SelectedItems.Cast();
- format.Create (arc_name, items.Select (entry => entry.Source), dialog.ArchiveOptions);
- }
- catch (Exception X)
- {
- PopupError (X.Message, guiStrings.TextCreateArchiveError);
- }
- }
-
///
/// Handle "Exit" command.
///
diff --git a/Strings/guiStrings.Designer.cs b/Strings/guiStrings.Designer.cs
index c09c3516..6aada000 100644
--- a/Strings/guiStrings.Designer.cs
+++ b/Strings/guiStrings.Designer.cs
@@ -438,6 +438,18 @@ namespace GARbro.GUI.Strings {
}
}
+ ///
+ /// Looks up a localized string similar to File {0}
+ ///already exists.
+ ///
+ ///Overwrite?.
+ ///
+ public static string MsgOverwrite {
+ get {
+ return ResourceManager.GetString("MsgOverwrite", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Ready.
///
@@ -546,6 +558,15 @@ namespace GARbro.GUI.Strings {
}
}
+ ///
+ /// Looks up a localized string similar to Confirm overwrite.
+ ///
+ public static string TextConfirmOverwrite {
+ get {
+ return ResourceManager.GetString("TextConfirmOverwrite", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Create archive.
///
diff --git a/Strings/guiStrings.resx b/Strings/guiStrings.resx
index 493ce39c..0d73d843 100644
--- a/Strings/guiStrings.resx
+++ b/Strings/guiStrings.resx
@@ -318,4 +318,13 @@
Forward
+
+ File {0}
+already exists.
+
+Overwrite?
+
+
+ Confirm overwrite
+
\ No newline at end of file
diff --git a/Strings/guiStrings.ru-RU.resx b/Strings/guiStrings.ru-RU.resx
index 6fafdeb5..46572e07 100644
--- a/Strings/guiStrings.ru-RU.resx
+++ b/Strings/guiStrings.ru-RU.resx
@@ -321,4 +321,13 @@
Вперёд
+
+ Файл под именем '{0}'
+уже существует.
+
+Перезаписать?
+
+
+ Подтвердите перезапись
+
\ No newline at end of file