2018-08-27 18:29:55 +01:00
|
|
|
// /***************************************************************************
|
|
|
|
|
// The Disc Image Chef
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Filename : frmMain.xeto.cs
|
|
|
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
|
|
|
|
//
|
|
|
|
|
// Component : Main window.
|
|
|
|
|
//
|
|
|
|
|
// --[ Description ] ----------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Implements main GUI window.
|
|
|
|
|
//
|
|
|
|
|
// --[ License ] --------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
|
// it under the terms of the GNU General public License as
|
|
|
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
|
//
|
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
// GNU General public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU General public License
|
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
//
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
// Copyright © 2011-2018 Natalia Portillo
|
|
|
|
|
// ****************************************************************************/
|
2018-08-28 23:29:06 +01:00
|
|
|
|
2018-08-27 15:07:51 +01:00
|
|
|
using System;
|
2018-08-27 18:25:11 +01:00
|
|
|
using System.ComponentModel;
|
2018-08-27 15:07:51 +01:00
|
|
|
using System.Linq;
|
2018-08-27 18:25:11 +01:00
|
|
|
using DiscImageChef.Console;
|
2018-09-09 01:00:54 +01:00
|
|
|
using DiscImageChef.Core.Media.Info;
|
2018-08-27 15:07:51 +01:00
|
|
|
using DiscImageChef.Devices;
|
2018-09-09 01:07:46 +01:00
|
|
|
using DiscImageChef.Gui.Dialogs;
|
|
|
|
|
using DiscImageChef.Gui.Panels;
|
2018-08-27 15:07:51 +01:00
|
|
|
using Eto.Forms;
|
|
|
|
|
using Eto.Serialization.Xaml;
|
|
|
|
|
|
2018-09-09 01:07:46 +01:00
|
|
|
namespace DiscImageChef.Gui.Forms
|
2018-08-27 15:07:51 +01:00
|
|
|
{
|
|
|
|
|
public class frmMain : Form
|
|
|
|
|
{
|
2018-08-27 18:25:11 +01:00
|
|
|
bool closing;
|
2018-09-02 01:41:03 +01:00
|
|
|
GridView grdFiles;
|
|
|
|
|
Label lblError;
|
2018-09-06 22:27:58 +01:00
|
|
|
TreeGridItem placeholderItem;
|
2018-08-27 15:07:51 +01:00
|
|
|
TreeGridView treeImages;
|
|
|
|
|
TreeGridItemCollection treeImagesItems;
|
|
|
|
|
|
2018-08-27 18:25:11 +01:00
|
|
|
public frmMain(bool debug, bool verbose)
|
2018-08-27 15:07:51 +01:00
|
|
|
{
|
|
|
|
|
XamlReader.Load(this);
|
|
|
|
|
|
2018-09-02 01:41:03 +01:00
|
|
|
lblError = new Label();
|
|
|
|
|
grdFiles = new GridView();
|
|
|
|
|
|
2018-08-27 18:25:11 +01:00
|
|
|
ConsoleHandler.Init();
|
|
|
|
|
ConsoleHandler.Debug = debug;
|
|
|
|
|
ConsoleHandler.Verbose = verbose;
|
|
|
|
|
|
2018-08-27 15:07:51 +01:00
|
|
|
treeImagesItems = new TreeGridItemCollection();
|
|
|
|
|
|
|
|
|
|
treeImages.Columns.Add(new GridColumn {HeaderText = "Name", DataCell = new TextBoxCell(0)});
|
|
|
|
|
|
|
|
|
|
treeImages.AllowMultipleSelection = false;
|
|
|
|
|
treeImages.ShowHeader = false;
|
|
|
|
|
treeImages.DataStore = treeImagesItems;
|
|
|
|
|
|
2018-08-27 18:25:11 +01:00
|
|
|
imagesRoot = new TreeGridItem {Values = new object[] {"Images"}};
|
2018-08-27 15:07:51 +01:00
|
|
|
devicesRoot = new TreeGridItem {Values = new object[] {"Devices"}};
|
|
|
|
|
|
|
|
|
|
treeImagesItems.Add(imagesRoot);
|
|
|
|
|
treeImagesItems.Add(devicesRoot);
|
2018-08-27 18:25:11 +01:00
|
|
|
|
2018-09-06 22:27:58 +01:00
|
|
|
placeholderItem = new TreeGridItem {Values = new object[] {"You should not be seeing this"}};
|
|
|
|
|
|
2018-08-27 18:25:11 +01:00
|
|
|
Closing += OnClosing;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OnClosing(object sender, CancelEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
// This prevents an infinite loop of crashes :p
|
|
|
|
|
if(closing) return;
|
|
|
|
|
|
|
|
|
|
closing = true;
|
|
|
|
|
Application.Instance.Quit();
|
2018-08-27 15:07:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void OnMenuOpen(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
MessageBox.Show("Not yet implemented");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void OnMenuAbout(object sender, EventArgs e)
|
|
|
|
|
{
|
2018-08-27 18:43:18 +01:00
|
|
|
AboutDialog dlgAbout = new AboutDialog
|
|
|
|
|
{
|
|
|
|
|
Developers = new[] {"Natalia Portillo", "Michael Drüing"},
|
|
|
|
|
License = "This program is free software: you can redistribute it and/or modify\n" +
|
|
|
|
|
"it under the terms of the GNU General public License as\n" +
|
|
|
|
|
"published by the Free Software Foundation, either version 3 of the\n" +
|
|
|
|
|
"License, or (at your option) any later version.\n\n" +
|
|
|
|
|
"This program is distributed in the hope that it will be useful,\n" +
|
|
|
|
|
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
|
|
|
|
|
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +
|
|
|
|
|
"GNU General public License for more details.\n\n" +
|
|
|
|
|
"You should have received a copy of the GNU General public License\n" +
|
|
|
|
|
"along with this program. If not, see <http://www.gnu.org/licenses/>.",
|
|
|
|
|
ProgramName = "The Disc Image Chef",
|
|
|
|
|
Website = new Uri("https://github.com/claunia"),
|
|
|
|
|
WebsiteLabel = "Source code on..."
|
|
|
|
|
};
|
|
|
|
|
dlgAbout.ShowDialog(this);
|
2018-08-27 15:07:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void OnMenuQuit(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Application.Instance.Quit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void OnDeviceRefresh(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
RefreshDevices();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnLoadComplete(EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
base.OnLoadComplete(e);
|
|
|
|
|
|
|
|
|
|
RefreshDevices();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RefreshDevices()
|
|
|
|
|
{
|
2018-08-27 22:03:20 +01:00
|
|
|
try
|
2018-08-27 15:07:51 +01:00
|
|
|
{
|
2018-08-27 22:03:20 +01:00
|
|
|
DicConsole.WriteLine("Refreshing devices");
|
|
|
|
|
devicesRoot.Children.Clear();
|
|
|
|
|
|
2018-08-28 23:29:06 +01:00
|
|
|
foreach(DeviceInfo device in Device.ListDevices().Where(d => d.Supported).OrderBy(d => d.Vendor)
|
|
|
|
|
.ThenBy(d => d.Model))
|
2018-08-27 15:07:51 +01:00
|
|
|
{
|
2018-08-27 22:03:20 +01:00
|
|
|
DicConsole.DebugWriteLine("Main window",
|
2018-08-28 23:29:06 +01:00
|
|
|
"Found supported device model {0} by manufacturer {1} on bus {2} and path {3}",
|
|
|
|
|
device.Model, device.Vendor, device.Bus, device.Path);
|
2018-09-06 22:27:58 +01:00
|
|
|
|
|
|
|
|
TreeGridItem devItem = new TreeGridItem
|
2018-08-27 22:03:20 +01:00
|
|
|
{
|
2018-09-06 22:27:58 +01:00
|
|
|
Values = new object[] {$"{device.Vendor} {device.Model} ({device.Bus})", device.Path, null}
|
|
|
|
|
};
|
|
|
|
|
devItem.Children.Add(placeholderItem);
|
|
|
|
|
devicesRoot.Children.Add(devItem);
|
2018-08-27 22:03:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
treeImages.ReloadData();
|
|
|
|
|
}
|
2018-08-28 23:29:06 +01:00
|
|
|
catch(InvalidOperationException ex) { DicConsole.ErrorWriteLine(ex.Message); }
|
2018-08-27 15:07:51 +01:00
|
|
|
}
|
|
|
|
|
|
2018-08-27 18:25:11 +01:00
|
|
|
protected void OnMenuConsole(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
new frmConsole().Show();
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-28 23:29:06 +01:00
|
|
|
protected void OnMenuPlugins(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
new dlgPlugins().ShowModal(this);
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-30 22:51:29 +01:00
|
|
|
protected void OnMenuEncodings(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
new dlgEncodings().ShowModal(this);
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-02 01:41:03 +01:00
|
|
|
protected void OnTreeImagesSelectedItemChanged(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if(!(sender is TreeGridView tree)) return;
|
|
|
|
|
|
|
|
|
|
if(!(tree.SelectedItem is TreeGridItem selectedItem)) return;
|
|
|
|
|
|
|
|
|
|
splMain.Panel2 = null;
|
|
|
|
|
|
2018-09-09 01:00:54 +01:00
|
|
|
if(selectedItem.Values.Length >= 3 && selectedItem.Values[2] is Panel infoPanel)
|
|
|
|
|
{
|
|
|
|
|
splMain.Panel2 = infoPanel;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-02 01:41:03 +01:00
|
|
|
if(selectedItem.Parent != devicesRoot) return;
|
|
|
|
|
|
|
|
|
|
switch(selectedItem.Values[2])
|
|
|
|
|
{
|
|
|
|
|
case null:
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Device dev = new Device((string)selectedItem.Values[1]);
|
|
|
|
|
if(dev.Error)
|
|
|
|
|
{
|
|
|
|
|
selectedItem.Values[2] = $"Error {dev.LastError} opening device";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Core.Devices.Info.DeviceInfo devInfo = new Core.Devices.Info.DeviceInfo(dev);
|
|
|
|
|
|
|
|
|
|
selectedItem.Values[2] = new pnlDeviceInfo(devInfo);
|
|
|
|
|
splMain.Panel2 = (Panel)selectedItem.Values[2];
|
|
|
|
|
|
|
|
|
|
dev.Close();
|
|
|
|
|
}
|
|
|
|
|
catch(SystemException ex)
|
|
|
|
|
{
|
|
|
|
|
selectedItem.Values[2] = ex.Message;
|
|
|
|
|
lblError.Text = ex.Message;
|
|
|
|
|
splMain.Panel2 = lblError;
|
|
|
|
|
DicConsole.ErrorWriteLine(ex.Message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case string devErrorMessage:
|
|
|
|
|
lblError.Text = devErrorMessage;
|
|
|
|
|
splMain.Panel2 = lblError;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-06 22:27:58 +01:00
|
|
|
protected void OnTreeImagesItemExpanding(object sender, TreeGridViewItemCancelEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
// First expansion of a device
|
|
|
|
|
if((e.Item as TreeGridItem)?.Children?.Count == 1 &&
|
|
|
|
|
((TreeGridItem)e.Item).Children[0] == placeholderItem &&
|
|
|
|
|
((TreeGridItem)e.Item).Parent == devicesRoot)
|
|
|
|
|
{
|
|
|
|
|
TreeGridItem deviceItem = (TreeGridItem)e.Item;
|
|
|
|
|
|
|
|
|
|
deviceItem.Children.Clear();
|
|
|
|
|
Device dev;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
dev = new Device((string)deviceItem.Values[1]);
|
|
|
|
|
if(dev.Error)
|
|
|
|
|
{
|
|
|
|
|
deviceItem.Values[2] = $"Error {dev.LastError} opening device";
|
|
|
|
|
e.Cancel = true;
|
|
|
|
|
treeImages.ReloadData();
|
|
|
|
|
treeImages.SelectedItem = deviceItem;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch(SystemException ex)
|
|
|
|
|
{
|
|
|
|
|
deviceItem.Values[2] = ex.Message;
|
|
|
|
|
e.Cancel = true;
|
|
|
|
|
treeImages.ReloadData();
|
|
|
|
|
DicConsole.ErrorWriteLine(ex.Message);
|
|
|
|
|
treeImages.SelectedItem = deviceItem;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!dev.IsRemovable)
|
|
|
|
|
deviceItem.Children.Add(new TreeGridItem
|
|
|
|
|
{
|
|
|
|
|
Values = new object[]
|
|
|
|
|
{
|
|
|
|
|
"Non-removable device commands not yet implemented"
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
else
|
2018-09-09 01:00:54 +01:00
|
|
|
{
|
|
|
|
|
// TODO: Removable non-SCSI?
|
|
|
|
|
ScsiInfo scsiInfo = new ScsiInfo(dev);
|
|
|
|
|
|
|
|
|
|
if(!scsiInfo.MediaInserted)
|
|
|
|
|
deviceItem.Children.Add(new TreeGridItem {Values = new object[] {"No media inserted"}});
|
|
|
|
|
else
|
|
|
|
|
deviceItem.Children.Add(new TreeGridItem
|
2018-09-06 22:27:58 +01:00
|
|
|
{
|
2018-09-09 01:00:54 +01:00
|
|
|
Values = new[]
|
|
|
|
|
{
|
|
|
|
|
scsiInfo.MediaType, deviceItem.Values[1],
|
|
|
|
|
new pnlScsiInfo(scsiInfo)
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2018-09-06 22:27:58 +01:00
|
|
|
|
|
|
|
|
dev.Close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-27 15:07:51 +01:00
|
|
|
#region XAML IDs
|
|
|
|
|
TreeGridItem devicesRoot;
|
|
|
|
|
TreeGridItem imagesRoot;
|
2018-09-02 01:41:03 +01:00
|
|
|
Splitter splMain;
|
2018-08-27 15:07:51 +01:00
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
}
|