diff --git a/.editorconfig b/.editorconfig
index 0a0e808bb..585e7fdd4 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,12 +1,12 @@
[*]
charset=utf-8
end_of_line=lf
-trim_trailing_whitespace=false
+trim_trailing_whitespace=true
insert_final_newline=false
indent_style=space
indent_size=4
-[{.babelrc,.stylelintrc,.eslintrc,jest.config,*.bowerrc,*.jsb3,*.jsb2,*.json}]
+[{.babelrc,.stylelintrc,.eslintrc,jest.config,*.uplugin,*.bowerrc,*.jsb3,*.jsb2,*.json}]
indent_style=space
indent_size=2
diff --git a/.idea/.idea.DiscImageChef/.idea/contentModel.xml b/.idea/.idea.DiscImageChef/.idea/contentModel.xml
index 24c28fc19..d52253f6b 100644
--- a/.idea/.idea.DiscImageChef/.idea/contentModel.xml
+++ b/.idea/.idea.DiscImageChef/.idea/contentModel.xml
@@ -56,6 +56,7 @@
+
@@ -1247,8 +1248,11 @@
+
+
+
diff --git a/DiscImageChef.Console/DicConsole.cs b/DiscImageChef.Console/DicConsole.cs
index 3c0c82be8..5fdabb613 100644
--- a/DiscImageChef.Console/DicConsole.cs
+++ b/DiscImageChef.Console/DicConsole.cs
@@ -48,16 +48,19 @@ namespace DiscImageChef.Console
public delegate void DebugWriteHandler(string format, params object[] arg);
+ public delegate void DebugWithModuleWriteLineHandler(string module, string format, params object[] arg);
+
///
/// Implements a console abstraction that defines four level of messages that can be routed to different consoles:
/// standard, error, verbose and debug.
///
public static class DicConsole
{
- public static event WriteLineHandler WriteLineEvent;
- public static event ErrorWriteLineHandler ErrorWriteLineEvent;
- public static event VerboseWriteLineHandler VerboseWriteLineEvent;
- public static event DebugWriteLineHandler DebugWriteLineEvent;
+ public static event WriteLineHandler WriteLineEvent;
+ public static event ErrorWriteLineHandler ErrorWriteLineEvent;
+ public static event VerboseWriteLineHandler VerboseWriteLineEvent;
+ public static event DebugWriteLineHandler DebugWriteLineEvent;
+ public static event DebugWithModuleWriteLineHandler DebugWithModuleWriteLineEvent;
public static event WriteHandler WriteEvent;
public static event ErrorWriteHandler ErrorWriteEvent;
@@ -82,6 +85,7 @@ namespace DiscImageChef.Console
public static void DebugWriteLine(string module, string format, params object[] arg)
{
DebugWriteLineEvent?.Invoke("DEBUG (" + module + "): " + format, arg);
+ DebugWithModuleWriteLineEvent?.Invoke(module, format, arg);
}
public static void WriteLine()
diff --git a/DiscImageChef.Gui/ConsoleHandler.cs b/DiscImageChef.Gui/ConsoleHandler.cs
new file mode 100644
index 000000000..27262fdd5
--- /dev/null
+++ b/DiscImageChef.Gui/ConsoleHandler.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.ObjectModel;
+using DiscImageChef.Console;
+
+namespace DiscImageChef.Gui
+{
+ static class ConsoleHandler
+ {
+ static bool _debug;
+ static bool _verbose;
+
+ public static bool Debug
+ {
+ get => _debug;
+ set
+ {
+ if(_debug == value) return;
+
+ _debug = value;
+
+ if(_debug) DicConsole.DebugWithModuleWriteLineEvent += OnDebugWriteHandler;
+ else DicConsole.DebugWithModuleWriteLineEvent -= OnDebugWriteHandler;
+ }
+ }
+ public static bool Verbose
+ {
+ get => _verbose;
+ set
+ {
+ if(_verbose == value) return;
+
+ _verbose = value;
+
+ if(_verbose) DicConsole.VerboseWriteLineEvent += OnVerboseWriteHandler;
+ else DicConsole.VerboseWriteLineEvent -= OnVerboseWriteHandler;
+ }
+ }
+
+ public static ObservableCollection Entries { get; } = new ObservableCollection();
+
+ internal static void Init()
+ {
+ DicConsole.WriteLineEvent += OnWriteHandler;
+ DicConsole.ErrorWriteLineEvent += OnErrorWriteHandler;
+ }
+
+ static void OnWriteHandler(string format, params object[] arg)
+ {
+ Entries.Add(new LogEntry
+ {
+ Message = string.Format(format, arg),
+ Module = null,
+ Timestamp = DateTime.Now,
+ Type = "Info"
+ });
+ }
+
+ static void OnErrorWriteHandler(string format, params object[] arg)
+ {
+ Entries.Add(new LogEntry
+ {
+ Message = string.Format(format, arg),
+ Module = null,
+ Timestamp = DateTime.Now,
+ Type = "Error"
+ });
+ }
+
+ static void OnVerboseWriteHandler(string format, params object[] arg)
+ {
+ Entries.Add(new LogEntry
+ {
+ Message = string.Format(format, arg),
+ Module = null,
+ Timestamp = DateTime.Now,
+ Type = "Verbose"
+ });
+ }
+
+ static void OnDebugWriteHandler(string module, string format, params object[] arg)
+ {
+ Entries.Add(new LogEntry
+ {
+ Message = string.Format(format, arg),
+ Module = module,
+ Timestamp = DateTime.Now,
+ Type = "Debug"
+ });
+ }
+ }
+
+ class LogEntry
+ {
+ public string Message { get; set; }
+ public string Module { get; set; }
+ public DateTime Timestamp { get; set; }
+ public string Type { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/DiscImageChef.Gui/DiscImageChef.Gui.csproj b/DiscImageChef.Gui/DiscImageChef.Gui.csproj
index d00e57abe..85e732a52 100644
--- a/DiscImageChef.Gui/DiscImageChef.Gui.csproj
+++ b/DiscImageChef.Gui/DiscImageChef.Gui.csproj
@@ -6,6 +6,7 @@
DiscImageChef.Gui
Copyright © 2018
Description of DiscImageChef.Gui
+ 7.2
diff --git a/DiscImageChef.Gui/frmConsole.xeto b/DiscImageChef.Gui/frmConsole.xeto
new file mode 100644
index 000000000..b3715b17d
--- /dev/null
+++ b/DiscImageChef.Gui/frmConsole.xeto
@@ -0,0 +1,22 @@
+
+
\ No newline at end of file
diff --git a/DiscImageChef.Gui/frmConsole.xeto.cs b/DiscImageChef.Gui/frmConsole.xeto.cs
new file mode 100644
index 000000000..d897d6d97
--- /dev/null
+++ b/DiscImageChef.Gui/frmConsole.xeto.cs
@@ -0,0 +1,142 @@
+using System;
+using System.ComponentModel;
+using System.IO;
+using System.Reflection;
+using DiscImageChef.CommonTypes.Interop;
+using DiscImageChef.Console;
+using Eto.Drawing;
+using Eto.Forms;
+using Eto.Serialization.Xaml;
+using PlatformID = DiscImageChef.CommonTypes.Interop.PlatformID;
+using Version = DiscImageChef.CommonTypes.Interop.Version;
+
+namespace DiscImageChef.Gui
+{
+ public class frmConsole : Form
+ {
+ public frmConsole()
+ {
+ XamlReader.Load(this);
+
+ grdMessages.DataStore = ConsoleHandler.Entries;
+ grdMessages.Columns.Add(new GridColumn
+ {
+ DataCell = new TextBoxCell {Binding = Binding.Property(r => $"{r.Timestamp}")},
+ HeaderText = "Time",
+ Sortable = true
+ });
+ grdMessages.Columns.Add(new GridColumn
+ {
+ DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Type)},
+ HeaderText = "Type",
+ Sortable = true
+ });
+ grdMessages.Columns.Add(new GridColumn
+ {
+ DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Module)},
+ HeaderText = "Module",
+ Sortable = true
+ });
+ grdMessages.Columns.Add(new GridColumn
+ {
+ DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Message)},
+ HeaderText = "Message",
+ Sortable = true
+ });
+
+ grdMessages.AllowMultipleSelection = false;
+ grdMessages.CellFormatting += (sender, e) =>
+ {
+ if(((LogEntry)e.Item).Type.ToLower() != "error") return;
+
+ e.BackgroundColor = Colors.Red;
+ e.ForegroundColor = Colors.Black;
+ };
+ grdMessages.AllowColumnReordering = true;
+
+ chkDebug.Checked = ConsoleHandler.Debug;
+ Closing += OnClosing;
+ }
+
+ void OnClosing(object sender, CancelEventArgs e)
+ {
+ // Otherwise if this closes it does not stop hearing events from collection, preventing console to keep working.
+ grdMessages.DataStore = null;
+ }
+
+ protected void OnChkDebugChecked(object sender, EventArgs e)
+ {
+ ConsoleHandler.Debug = chkDebug.Checked.Value;
+ }
+
+ protected void OnBtnClearClicked(object sender, EventArgs e)
+ {
+ ConsoleHandler.Entries.Clear();
+ }
+
+ protected void OnBtnSaveClicked(object sender, EventArgs e)
+ {
+ SaveFileDialog dlgSave = new SaveFileDialog {CheckFileExists = true};
+ dlgSave.Filters.Add(new FileFilter {Extensions = new[] {"log"}, Name = "Log files"});
+ DialogResult result = dlgSave.ShowDialog(this);
+ if(result != DialogResult.Ok) return;
+
+ try
+ {
+ FileStream logFs = new FileStream(dlgSave.FileName, FileMode.Create, FileAccess.ReadWrite);
+ StreamWriter logSw = new StreamWriter(logFs);
+
+ logSw.WriteLine("Log saved at {0}", DateTime.Now);
+
+ PlatformID platId = DetectOS.GetRealPlatformID();
+ string platVer = DetectOS.GetVersion();
+ AssemblyInformationalVersionAttribute assemblyVersion =
+ Attribute.GetCustomAttribute(typeof(DicConsole).Assembly,
+ typeof(AssemblyInformationalVersionAttribute)) as
+ AssemblyInformationalVersionAttribute;
+
+ logSw.WriteLine("################# System information #################");
+ logSw.WriteLine("{0} {1} ({2}-bit)", DetectOS.GetPlatformName(platId, platVer), platVer,
+ Environment.Is64BitOperatingSystem ? 64 : 32);
+ if(DetectOS.IsMono) logSw.WriteLine("Mono {0}", Version.GetMonoVersion());
+ else logSw.WriteLine(".NET Framework {0}", Environment.Version);
+
+ logSw.WriteLine();
+
+ logSw.WriteLine("################# Program information ################");
+ logSw.WriteLine("DiscImageChef {0}", assemblyVersion?.InformationalVersion);
+ logSw.WriteLine("Running in {0}-bit", Environment.Is64BitProcess ? 64 : 32);
+ logSw.WriteLine("Running GUI mode using {0}", Application.Instance.Platform.ID);
+ #if DEBUG
+ logSw.WriteLine("DEBUG version");
+ #endif
+ logSw.WriteLine("Command line: {0}", Environment.CommandLine);
+ logSw.WriteLine();
+
+ logSw.WriteLine("################# Console ################");
+ foreach(LogEntry entry in ConsoleHandler.Entries)
+ if(entry.Type != "Info")
+ logSw.WriteLine("{0}: ({1}) {2}", entry.Timestamp, entry.Type.ToLower(), entry.Message);
+ else
+ logSw.WriteLine("{0}: {1}", entry.Timestamp, entry.Message);
+
+ logSw.Close();
+ logFs.Close();
+ }
+ catch(Exception exception)
+ {
+ MessageBox.Show("Exception {0} trying to save logfile, details has been sent to console.",
+ exception.Message);
+ DicConsole.ErrorWriteLine("Console", exception.Message);
+ DicConsole.ErrorWriteLine("Console", exception.StackTrace);
+ }
+ }
+
+ #region XAML controls
+ GridView grdMessages;
+ CheckBox chkDebug;
+ Button btnClear;
+ Button btnSave;
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/DiscImageChef.Gui/frmMain.xeto b/DiscImageChef.Gui/frmMain.xeto
index 8fb6dcfd4..1103534ea 100644
--- a/DiscImageChef.Gui/frmMain.xeto
+++ b/DiscImageChef.Gui/frmMain.xeto
@@ -12,11 +12,14 @@
-
+
+
+
+
diff --git a/DiscImageChef.Gui/frmMain.xeto.cs b/DiscImageChef.Gui/frmMain.xeto.cs
index d39575ba6..66cf17637 100644
--- a/DiscImageChef.Gui/frmMain.xeto.cs
+++ b/DiscImageChef.Gui/frmMain.xeto.cs
@@ -1,5 +1,7 @@
using System;
+using System.ComponentModel;
using System.Linq;
+using DiscImageChef.Console;
using DiscImageChef.Devices;
using Eto.Forms;
using Eto.Serialization.Xaml;
@@ -8,14 +10,19 @@ namespace DiscImageChef.Gui
{
public class frmMain : Form
{
+ bool closing;
Splitter splMain;
TreeGridView treeImages;
TreeGridItemCollection treeImagesItems;
- public frmMain()
+ public frmMain(bool debug, bool verbose)
{
XamlReader.Load(this);
+ ConsoleHandler.Init();
+ ConsoleHandler.Debug = debug;
+ ConsoleHandler.Verbose = verbose;
+
treeImagesItems = new TreeGridItemCollection();
treeImages.Columns.Add(new GridColumn {HeaderText = "Name", DataCell = new TextBoxCell(0)});
@@ -24,11 +31,22 @@ namespace DiscImageChef.Gui
treeImages.ShowHeader = false;
treeImages.DataStore = treeImagesItems;
- imagesRoot = new TreeGridItem {Values = new object[] {"Images"}};
+ imagesRoot = new TreeGridItem {Values = new object[] {"Images"}};
devicesRoot = new TreeGridItem {Values = new object[] {"Devices"}};
treeImagesItems.Add(imagesRoot);
treeImagesItems.Add(devicesRoot);
+
+ Closing += OnClosing;
+ }
+
+ void OnClosing(object sender, CancelEventArgs e)
+ {
+ // This prevents an infinite loop of crashes :p
+ if(closing) return;
+
+ closing = true;
+ Application.Instance.Quit();
}
protected void OnMenuOpen(object sender, EventArgs e)
@@ -60,11 +78,15 @@ namespace DiscImageChef.Gui
void RefreshDevices()
{
+ DicConsole.WriteLine("Refreshing devices");
devicesRoot.Children.Clear();
foreach(DeviceInfo device in Device.ListDevices().Where(d => d.Supported).OrderBy(d => d.Vendor)
.ThenBy(d => d.Model))
{
+ DicConsole.DebugWriteLine("Main window",
+ "Found support device model {0} by manufacturer {1} on bus {2} and path {3}",
+ device.Model, device.Vendor, device.Bus, device.Path);
devicesRoot.Children.Add(new TreeGridItem
{
Values = new object[] {$"{device.Vendor} {device.Model} ({device.Bus})", device.Path}
@@ -74,6 +96,11 @@ namespace DiscImageChef.Gui
treeImages.ReloadData();
}
+ protected void OnMenuConsole(object sender, EventArgs e)
+ {
+ new frmConsole().Show();
+ }
+
#region XAML IDs
TreeGridItem devicesRoot;
GridView grdFiles;
diff --git a/DiscImageChef/Main.cs b/DiscImageChef/Main.cs
index 80d2c3a4a..5f523b0e3 100644
--- a/DiscImageChef/Main.cs
+++ b/DiscImageChef/Main.cs
@@ -37,6 +37,7 @@ using DiscImageChef.Commands;
using DiscImageChef.Console;
using DiscImageChef.Gui;
using DiscImageChef.Settings;
+using Eto;
using Eto.Forms;
using Statistics = DiscImageChef.Core.Statistics;
@@ -208,9 +209,10 @@ namespace DiscImageChef
Commands.Statistics.ShowStats();
}).WithParsed(opts =>
{
- if (opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
- if (opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
- new Application(Eto.Platform.Detect).Run(new frmMain());
+ if(opts.Debug) DicConsole.DebugWriteLineEvent += System.Console.Error.WriteLine;
+ if(opts.Verbose) DicConsole.VerboseWriteLineEvent += System.Console.WriteLine;
+
+ new Application(Platform.Detect).Run(new frmMain(opts.Debug, opts.Verbose));
}).WithNotParsed(errs => Environment.Exit(1));
Statistics.SaveStats();