summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsr55 <[email protected]>2013-08-27 19:11:43 +0000
committersr55 <[email protected]>2013-08-27 19:11:43 +0000
commitbfd79c7ca947ec205a238a334bfe7f37fd40bb21 (patch)
treedb4ab10a1ba566ae468786d8cf1fb761b808be48
parent09130a3f2991ffaddd7fda7bf6758266e8143d2b (diff)
WinGui: Some more work on the Instant HandBrake prototype.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@5756 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r--win/CS/HandBrakeWPF/Commands/CancelScanCommand.cs16
-rw-r--r--win/CS/HandBrakeWPF/HandBrakeWPF.csproj8
-rw-r--r--win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs2
-rw-r--r--win/CS/HandBrakeWPF/ViewModels/InstantViewModel.cs1014
-rw-r--r--win/CS/HandBrakeWPF/ViewModels/Interfaces/IInstantViewModel.cs18
-rw-r--r--win/CS/HandBrakeWPF/ViewModels/ShellViewModel.cs8
-rw-r--r--win/CS/HandBrakeWPF/Views/InstantMainView.xaml.cs15
-rw-r--r--win/CS/HandBrakeWPF/Views/InstantView.xaml (renamed from win/CS/HandBrakeWPF/Views/InstantMainView.xaml)92
-rw-r--r--win/CS/HandBrakeWPF/Views/InstantView.xaml.cs27
-rw-r--r--win/CS/HandBrakeWPF/Views/ShellView.xaml2
10 files changed, 1142 insertions, 60 deletions
diff --git a/win/CS/HandBrakeWPF/Commands/CancelScanCommand.cs b/win/CS/HandBrakeWPF/Commands/CancelScanCommand.cs
index 617778b08..e9ec9966a 100644
--- a/win/CS/HandBrakeWPF/Commands/CancelScanCommand.cs
+++ b/win/CS/HandBrakeWPF/Commands/CancelScanCommand.cs
@@ -49,7 +49,7 @@ namespace HandBrakeWPF.Commands
/// </param>
private void ScanServiceWrapperScanCompleted(object sender, HandBrake.ApplicationServices.EventArgs.ScanCompletedEventArgs e)
{
- Caliburn.Micro.Execute.OnUIThread(() => this.CanExecuteChanged(sender, EventArgs.Empty));
+ Caliburn.Micro.Execute.OnUIThread(this.OnCanExecuteChanged);
}
/// <summary>
@@ -64,7 +64,7 @@ namespace HandBrakeWPF.Commands
/// </param>
private void ScanServiceWrapperScanStared(object sender, EventArgs e)
{
- Caliburn.Micro.Execute.OnUIThread(() => this.CanExecuteChanged(sender, EventArgs.Empty));
+ Caliburn.Micro.Execute.OnUIThread(this.OnCanExecuteChanged);
}
#region Implementation of ICommand
@@ -100,6 +100,18 @@ namespace HandBrakeWPF.Commands
/// </summary>
public event EventHandler CanExecuteChanged;
+ /// <summary>
+ /// The on can execute changed.
+ /// </summary>
+ protected virtual void OnCanExecuteChanged()
+ {
+ EventHandler handler = this.CanExecuteChanged;
+ if (handler != null)
+ {
+ handler(this, EventArgs.Empty);
+ }
+ }
+
#endregion
}
}
diff --git a/win/CS/HandBrakeWPF/HandBrakeWPF.csproj b/win/CS/HandBrakeWPF/HandBrakeWPF.csproj
index 204774d82..b0094ce23 100644
--- a/win/CS/HandBrakeWPF/HandBrakeWPF.csproj
+++ b/win/CS/HandBrakeWPF/HandBrakeWPF.csproj
@@ -184,7 +184,9 @@
<Compile Include="Services\PrePostActionService.cs" />
<Compile Include="ViewModels\AdvancedViewModel.cs" />
<Compile Include="ViewModels\EncoderOptionsViewModel.cs" />
+ <Compile Include="ViewModels\InstantViewModel.cs" />
<Compile Include="ViewModels\Interfaces\IEncoderOptionsViewModel.cs" />
+ <Compile Include="ViewModels\Interfaces\IInstantViewModel.cs" />
<Compile Include="ViewModels\Interfaces\IX264ViewModel.cs" />
<Compile Include="ViewModels\Interfaces\IQueueSelectionViewModel.cs" />
<Compile Include="ViewModels\QueueSelectionViewModel.cs" />
@@ -194,8 +196,8 @@
<Compile Include="Views\EncoderOptionsView.xaml.cs">
<DependentUpon>EncoderOptionsView.xaml</DependentUpon>
</Compile>
- <Compile Include="Views\InstantMainView.xaml.cs">
- <DependentUpon>InstantMainView.xaml</DependentUpon>
+ <Compile Include="Views\InstantView.xaml.cs">
+ <DependentUpon>InstantView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\QueueSelectionView.xaml.cs">
<DependentUpon>QueueSelectionView.xaml</DependentUpon>
@@ -374,7 +376,7 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
- <Page Include="Views\InstantMainView.xaml">
+ <Page Include="Views\InstantView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
diff --git a/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs b/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs
index aee06213c..0debbbcce 100644
--- a/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs
+++ b/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs
@@ -80,6 +80,8 @@ namespace HandBrakeWPF.Startup
this.windsorContainer.Register(Component.For<IQueueSelectionViewModel>().ImplementedBy<QueueSelectionViewModel>().LifeStyle.Is(LifestyleType.Singleton));
this.windsorContainer.Register(Component.For<ICountdownAlertViewModel>().ImplementedBy<CountdownAlertViewModel>().LifeStyle.Is(LifestyleType.Singleton));
+ this.windsorContainer.Register(Component.For<IInstantViewModel>().ImplementedBy<InstantViewModel>().LifeStyle.Is(LifestyleType.Singleton));
+
// Tab Components
this.windsorContainer.Register(Component.For<IAudioViewModel>().ImplementedBy<AudioViewModel>().LifeStyle.Is(LifestyleType.Singleton));
this.windsorContainer.Register(Component.For<IX264ViewModel>().ImplementedBy<X264ViewModel>().LifeStyle.Is(LifestyleType.Singleton));
diff --git a/win/CS/HandBrakeWPF/ViewModels/InstantViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/InstantViewModel.cs
new file mode 100644
index 000000000..8edfb3a87
--- /dev/null
+++ b/win/CS/HandBrakeWPF/ViewModels/InstantViewModel.cs
@@ -0,0 +1,1014 @@
+// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="InstantViewModel.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+// The instant view model.
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrakeWPF.ViewModels
+{
+ using System;
+ using System.Collections.Generic;
+ using System.ComponentModel;
+ using System.Diagnostics;
+ using System.Globalization;
+ using System.IO;
+ using System.Linq;
+ using System.Threading;
+ using System.Windows;
+
+ using Caliburn.Micro;
+
+ using HandBrake.ApplicationServices;
+ using HandBrake.ApplicationServices.EventArgs;
+ using HandBrake.ApplicationServices.Model;
+ using HandBrake.ApplicationServices.Parsing;
+ using HandBrake.ApplicationServices.Services.Interfaces;
+ using HandBrake.ApplicationServices.Utilities;
+
+ using HandBrakeWPF.Commands;
+ using HandBrakeWPF.Helpers;
+ using HandBrakeWPF.Model;
+ using HandBrakeWPF.Services.Interfaces;
+ using HandBrakeWPF.ViewModels.Interfaces;
+ using HandBrakeWPF.Views;
+
+ using Microsoft.Win32;
+
+ using Ookii.Dialogs.Wpf;
+
+ /// <summary>
+ /// The instant view model.
+ /// </summary>
+ public class InstantViewModel : ViewModelBase, IInstantViewModel
+ {
+ #region Constants and Fields
+
+ /// <summary>
+ /// The encode service.
+ /// </summary>
+ private readonly IEncodeServiceWrapper encodeService;
+
+ /// <summary>
+ /// The error service.
+ /// </summary>
+ private readonly IErrorService errorService;
+
+ /// <summary>
+ /// The preset service.
+ /// </summary>
+ private readonly IPresetService presetService;
+
+ /// <summary>
+ /// The queue processor.
+ /// </summary>
+ private readonly IQueueProcessor queueProcessor;
+
+ /// <summary>
+ /// The scan service.
+ /// </summary>
+ private readonly IScanServiceWrapper scanService;
+
+ /// <summary>
+ /// The shell view model.
+ /// </summary>
+ private readonly IShellViewModel shellViewModel;
+
+ /// <summary>
+ /// The update service.
+ /// </summary>
+ private readonly IUpdateService updateService;
+
+ /// <summary>
+ /// The user setting service.
+ /// </summary>
+ private readonly IUserSettingService userSettingService;
+
+ /// <summary>
+ /// Windows 7 API Pack wrapper
+ /// </summary>
+ private readonly Win7 windowsSeven = new Win7();
+
+ /// <summary>
+ /// The is encoding.
+ /// </summary>
+ private bool isEncoding;
+
+ /// <summary>
+ /// The last percentage complete value.
+ /// </summary>
+ private int lastEncodePercentage;
+
+ /// <summary>
+ /// The ordered by duration.
+ /// </summary>
+ private bool orderedByDuration;
+
+ /// <summary>
+ /// The ordered by title.
+ /// </summary>
+ private bool orderedByTitle;
+
+ /// <summary>
+ /// The output directory.
+ /// </summary>
+ private string outputDirectory;
+
+ /// <summary>
+ /// The program status label.
+ /// </summary>
+ private string programStatusLabel;
+
+ /// <summary>
+ /// The scanned source.
+ /// </summary>
+ private Source scannedSource;
+
+ /// <summary>
+ /// The selected preset.
+ /// </summary>
+ private Preset selectedPreset;
+
+ /// <summary>
+ /// The show status window.
+ /// </summary>
+ private bool showStatusWindow;
+
+ /// <summary>
+ /// The source label.
+ /// </summary>
+ private string sourceLabel;
+
+ /// <summary>
+ /// The status label.
+ /// </summary>
+ private string statusLabel;
+
+ #endregion
+
+ #region Constructors and Destructors
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="InstantViewModel"/> class.
+ /// </summary>
+ /// <param name="userSettingService">
+ /// The user setting service.
+ /// </param>
+ /// <param name="scanService">
+ /// The scan service.
+ /// </param>
+ /// <param name="encodeService">
+ /// The encode service.
+ /// </param>
+ /// <param name="presetService">
+ /// The preset service.
+ /// </param>
+ /// <param name="errorService">
+ /// The error service.
+ /// </param>
+ /// <param name="shellViewModel">
+ /// The shell view model.
+ /// </param>
+ /// <param name="updateService">
+ /// The update service.
+ /// </param>
+ /// <param name="notificationService">
+ /// The notification service.
+ /// </param>
+ /// <param name="whenDoneService">
+ /// The when done service.
+ /// </param>
+ public InstantViewModel(
+ IUserSettingService userSettingService,
+ IScanServiceWrapper scanService,
+ IEncodeServiceWrapper encodeService,
+ IPresetService presetService,
+ IErrorService errorService,
+ IShellViewModel shellViewModel,
+ IUpdateService updateService,
+ INotificationService notificationService,
+ IPrePostActionService whenDoneService)
+ {
+ this.userSettingService = userSettingService;
+ this.scanService = scanService;
+ this.encodeService = encodeService;
+ this.presetService = presetService;
+ this.errorService = errorService;
+ this.shellViewModel = shellViewModel;
+ this.updateService = updateService;
+
+ this.queueProcessor = IoC.Get<IQueueProcessor>();
+
+ // Setup Properties
+ this.TitleList = new BindingList<SelectionTitle>();
+ this.ScannedSource = new Source();
+
+ // Setup Events
+ this.scanService.ScanStared += this.ScanStared;
+ this.scanService.ScanCompleted += this.ScanCompleted;
+ this.scanService.ScanStatusChanged += this.ScanStatusChanged;
+ this.queueProcessor.JobProcessingStarted += this.QueueProcessorJobProcessingStarted;
+ this.queueProcessor.QueueCompleted += this.QueueCompleted;
+ this.queueProcessor.QueueChanged += this.QueueChanged;
+ this.queueProcessor.EncodeService.EncodeStatusChanged += this.EncodeStatusChanged;
+
+ this.Presets = this.presetService.Presets;
+ this.CancelScanCommand = new CancelScanCommand(this.scanService);
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets the cancel scan command.
+ /// </summary>
+ public CancelScanCommand CancelScanCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether IsEncoding.
+ /// </summary>
+ public bool IsEncoding
+ {
+ get
+ {
+ return this.isEncoding;
+ }
+
+ set
+ {
+ this.isEncoding = value;
+ this.NotifyOfPropertyChange(() => this.IsEncoding);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether ordered by duration.
+ /// </summary>
+ public bool OrderedByDuration
+ {
+ get
+ {
+ return this.orderedByDuration;
+ }
+
+ set
+ {
+ this.orderedByDuration = value;
+ this.NotifyOfPropertyChange(() => this.OrderedByDuration);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether ordered by title.
+ /// </summary>
+ public bool OrderedByTitle
+ {
+ get
+ {
+ return this.orderedByTitle;
+ }
+
+ set
+ {
+ this.orderedByTitle = value;
+ this.NotifyOfPropertyChange(() => this.OrderedByTitle);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the output directory.
+ /// </summary>
+ public string OutputDirectory
+ {
+ get
+ {
+ return this.outputDirectory;
+ }
+ set
+ {
+ this.outputDirectory = value;
+ this.NotifyOfPropertyChange(() => this.OutputDirectory);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets Presets.
+ /// </summary>
+ public IEnumerable<Preset> Presets { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Program Status Toolbar Label
+ /// This indicates the status of HandBrake
+ /// </summary>
+ public string ProgramStatusLabel
+ {
+ get
+ {
+ return string.IsNullOrEmpty(this.programStatusLabel) ? "Ready" : this.programStatusLabel;
+ }
+
+ set
+ {
+ if (!Equals(this.programStatusLabel, value))
+ {
+ this.programStatusLabel = value;
+ this.NotifyOfPropertyChange(() => this.ProgramStatusLabel);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating progress percentage.
+ /// </summary>
+ public int ProgressPercentage { get; set; }
+
+ /// <summary>
+ /// Gets or sets the Last Scanned Source
+ /// This object contains information about the scanned source.
+ /// </summary>
+ public Source ScannedSource
+ {
+ get
+ {
+ return this.scannedSource;
+ }
+
+ set
+ {
+ this.scannedSource = value;
+
+ this.NotifyOfPropertyChange("ScannedSource");
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets SelectedPreset.
+ /// </summary>
+ public Preset SelectedPreset
+ {
+ get
+ {
+ return this.selectedPreset;
+ }
+ set
+ {
+ this.selectedPreset = value;
+ this.NotifyOfPropertyChange(() => this.SelectedPreset);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether ShowStatusWindow.
+ /// </summary>
+ public bool ShowStatusWindow
+ {
+ get
+ {
+ return this.showStatusWindow;
+ }
+
+ set
+ {
+ this.showStatusWindow = value;
+ this.NotifyOfPropertyChange(() => this.ShowStatusWindow);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the Source Label
+ /// This indicates the status of scans.
+ /// </summary>
+ public string SourceLabel
+ {
+ get
+ {
+ return string.IsNullOrEmpty(this.sourceLabel) ? "Select 'Source' to continue" : this.sourceLabel;
+ }
+
+ set
+ {
+ if (!Equals(this.sourceLabel, value))
+ {
+ this.sourceLabel = value;
+ this.NotifyOfPropertyChange("SourceLabel");
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets SourceName.
+ /// </summary>
+ public string SourceName
+ {
+ get
+ {
+ // Sanity Check
+ if (this.ScannedSource == null || this.ScannedSource.ScanPath == null)
+ {
+ return string.Empty;
+ }
+
+ // The title that is selected has a source name. This means it's part of a batch scan.
+ // if (selectedTitle != null && !string.IsNullOrEmpty(selectedTitle.SourceName))
+ // {
+ // return Path.GetFileNameWithoutExtension(selectedTitle.SourceName);
+ // }
+
+ // Check if we have a Folder, if so, check if it's a DVD / Bluray drive and get the label.
+ if (this.ScannedSource.ScanPath.EndsWith("\\"))
+ {
+ foreach (DriveInformation item in GeneralUtilities.GetDrives())
+ {
+ if (item.RootDirectory.Contains(this.ScannedSource.ScanPath))
+ {
+ return item.VolumeLabel;
+ }
+ }
+ }
+
+ if (Path.GetFileNameWithoutExtension(this.ScannedSource.ScanPath) != "VIDEO_TS")
+ {
+ return Path.GetFileNameWithoutExtension(this.ScannedSource.ScanPath);
+ }
+
+ return Path.GetFileNameWithoutExtension(Path.GetDirectoryName(this.ScannedSource.ScanPath));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the Program Status Toolbar Label
+ /// This indicates the status of HandBrake
+ /// </summary>
+ public string StatusLabel
+ {
+ get
+ {
+ return string.IsNullOrEmpty(this.statusLabel) ? "Ready" : this.statusLabel;
+ }
+
+ set
+ {
+ if (!Equals(this.statusLabel, value))
+ {
+ this.statusLabel = value;
+ this.NotifyOfPropertyChange(() => this.StatusLabel);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the selected titles.
+ /// </summary>
+ public BindingList<SelectionTitle> TitleList { get; set; }
+
+ #endregion
+
+ #region Public Methods
+
+ /// <summary>
+ /// The Destination Path
+ /// </summary>
+ public void BrowseDestination()
+ {
+ var saveFileDialog = new SaveFileDialog
+ {
+ Filter = "mp4|*.mp4;*.m4v|mkv|*.mkv",
+ CheckPathExists = true,
+ AddExtension = true,
+ DefaultExt = ".mp4",
+ OverwritePrompt = true,
+ };
+
+ saveFileDialog.ShowDialog();
+ this.OutputDirectory = Path.GetDirectoryName(saveFileDialog.FileName);
+ }
+
+ /// <summary>
+ /// Cancel a Scan
+ /// </summary>
+ public void CancelScan()
+ {
+ this.scanService.Stop();
+ }
+
+ /// <summary>
+ /// File Scan
+ /// </summary>
+ public void FileScan()
+ {
+ var dialog = new VistaOpenFileDialog { Filter = "All files (*.*)|*.*" };
+ dialog.ShowDialog();
+ this.StartScan(dialog.FileName, 0);
+ }
+
+ /// <summary>
+ /// Support dropping a file onto the main window to scan.
+ /// </summary>
+ /// <param name="e">
+ /// The DragEventArgs.
+ /// </param>
+ public void FilesDroppedOnWindow(DragEventArgs e)
+ {
+ if (e.Data.GetDataPresent(DataFormats.FileDrop))
+ {
+ var fileNames = e.Data.GetData(DataFormats.FileDrop, true) as string[];
+ if (fileNames != null && fileNames.Any() &&
+ (File.Exists(fileNames[0]) || Directory.Exists(fileNames[0])))
+ {
+ this.StartScan(fileNames[0], 0);
+ }
+ }
+
+ e.Handled = true;
+ }
+
+ /// <summary>
+ /// Folder Scan
+ /// </summary>
+ public void FolderScan()
+ {
+ var dialog = new VistaFolderBrowserDialog
+ {
+ Description = "Please select a folder.",
+ UseDescriptionForTitle = true
+ };
+ dialog.ShowDialog();
+ this.StartScan(dialog.SelectedPath, 0);
+ }
+
+ /// <summary>
+ /// Launch the Help pages.
+ /// </summary>
+ public void LaunchHelp()
+ {
+ Process.Start("https://trac.handbrake.fr/wiki/HandBrakeGuide");
+ }
+
+ /// <summary>
+ /// The on load.
+ /// </summary>
+ public override void OnLoad()
+ {
+ // Check the CLI Executable.
+ CliCheckHelper.CheckCLIVersion();
+
+ // Perform an update check if required
+ // this.updateService.PerformStartupUpdateCheck(this.HandleUpdateCheckResults);
+
+ // Setup the presets.
+ this.presetService.Load();
+ if (this.presetService.CheckIfPresetsAreOutOfDate())
+ {
+ if (!this.userSettingService.GetUserSetting<bool>(UserSettingConstants.PresetNotification))
+ {
+ this.errorService.ShowMessageBox(
+ "HandBrake has determined your built-in presets are out of date... These presets will now be updated." +
+ Environment.NewLine +
+ "Your custom presets have not been updated so you may have to re-create these by deleting and re-adding them.",
+ "Preset Update",
+ MessageBoxButton.OK,
+ MessageBoxImage.Information);
+ }
+ }
+
+ this.SelectedPreset = this.presetService.DefaultPreset;
+
+ // Log Cleaning
+ if (this.userSettingService.GetUserSetting<bool>(UserSettingConstants.ClearOldLogs))
+ {
+ var clearLog = new Thread(() => GeneralUtilities.ClearLogFiles(30));
+ clearLog.Start();
+ }
+ base.OnLoad();
+ }
+
+ /// <summary>
+ /// Open the About Window
+ /// </summary>
+ public void OpenAboutApplication()
+ {
+ var command = new OpenOptionsScreenCommand();
+ command.Execute(OptionsTab.About);
+ }
+
+ /// <summary>
+ /// Open the Log Window
+ /// </summary>
+ public void OpenLogWindow()
+ {
+ Window window =
+ Application.Current.Windows.Cast<Window>().FirstOrDefault(x => x.GetType() == typeof(LogView));
+
+ if (window != null)
+ {
+ var logvm = (ILogViewModel)window.DataContext;
+ logvm.SelectedTab = this.IsEncoding ? 0 : 1;
+ window.Activate();
+ }
+ else
+ {
+ var logvm = IoC.Get<ILogViewModel>();
+ logvm.SelectedTab = this.IsEncoding ? 0 : 1;
+ this.WindowManager.ShowWindow(logvm);
+ }
+ }
+
+ /// <summary>
+ /// Open the Options Window
+ /// </summary>
+ public void OpenOptionsWindow()
+ {
+ this.shellViewModel.DisplayWindow(ShellWindow.OptionsWindow);
+ }
+
+ /// <summary>
+ /// The order by duration.
+ /// </summary>
+ public void OrderByDuration()
+ {
+ this.TitleList =
+ new BindingList<SelectionTitle>(this.TitleList.OrderByDescending(o => o.Title.Duration).ToList());
+ this.NotifyOfPropertyChange(() => this.TitleList);
+ this.OrderedByTitle = false;
+ this.OrderedByDuration = true;
+ }
+
+ /// <summary>
+ /// The order by title.
+ /// </summary>
+ public void OrderByTitle()
+ {
+ this.TitleList = new BindingList<SelectionTitle>(this.TitleList.OrderBy(o => o.Title.TitleNumber).ToList());
+ this.NotifyOfPropertyChange(() => this.TitleList);
+ this.OrderedByTitle = true;
+ this.OrderedByDuration = false;
+ }
+
+ /// <summary>
+ /// Pause an Encode
+ /// </summary>
+ public void PauseEncode()
+ {
+ this.queueProcessor.Pause();
+ }
+
+ /// <summary>
+ /// The select all.
+ /// </summary>
+ public void SelectAll()
+ {
+ foreach (SelectionTitle item in this.TitleList)
+ {
+ item.IsSelected = true;
+ }
+ }
+
+ /// <summary>
+ /// The setup.
+ /// </summary>
+ /// <param name="scannedSource">
+ /// The scanned source.
+ /// </param>
+ public void Setup(Source scannedSource)
+ {
+ this.TitleList.Clear();
+
+ if (scannedSource != null)
+ {
+ IEnumerable<Title> titles = this.orderedByTitle
+ ? scannedSource.Titles
+ : scannedSource.Titles.OrderByDescending(o => o.Duration).ToList();
+
+ foreach (Title item in titles)
+ {
+ var title = new SelectionTitle(item, item.SourceName) { IsSelected = true };
+ this.TitleList.Add(title);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Shutdown this View
+ /// </summary>
+ public void Shutdown()
+ {
+ // Shutdown Service
+ this.encodeService.Shutdown();
+
+ // Unsubscribe from Events.
+ this.scanService.ScanStared -= this.ScanStared;
+ this.scanService.ScanCompleted -= this.ScanCompleted;
+ this.scanService.ScanStatusChanged -= this.ScanStatusChanged;
+
+ this.queueProcessor.QueueCompleted -= this.QueueCompleted;
+ this.queueProcessor.QueueChanged -= this.QueueChanged;
+ this.queueProcessor.JobProcessingStarted -= this.QueueProcessorJobProcessingStarted;
+ this.queueProcessor.EncodeService.EncodeStatusChanged -= this.EncodeStatusChanged;
+ }
+
+ /// <summary>
+ /// Start an Encode
+ /// </summary>
+ public void StartEncode()
+ {
+ // if (this.queueProcessor.IsProcessing)
+ // {
+ // this.errorService.ShowMessageBox("HandBrake is already encoding.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
+ // return;
+ // }
+
+ //// Check if we already have jobs, and if we do, just start the queue.
+ // if (this.queueProcessor.Count != 0)
+ // {
+ // this.queueProcessor.Start();
+ // return;
+ // }
+
+ //// Otherwise, perform Santiy Checking then add to the queue and start if everything is ok.
+ // if (this.SelectedTitle == null)
+ // {
+ // this.errorService.ShowMessageBox("You must first scan a source.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
+ // return;
+ // }
+
+ // if (string.IsNullOrEmpty(this.Destination))
+ // {
+ // this.errorService.ShowMessageBox("The Destination field was empty.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
+ // return;
+ // }
+
+ // if (File.Exists(this.Destination))
+ // {
+ // MessageBoxResult result = this.errorService.ShowMessageBox("The current file already exists, do you wish to overwrite it?", "Question", MessageBoxButton.YesNo, MessageBoxImage.Question);
+ // if (result == MessageBoxResult.No)
+ // {
+ // return;
+ // }
+ // }
+
+ //// Create the Queue Task and Start Processing
+ // QueueTask task = new QueueTask
+ // {
+ // Task = new EncodeTask(this.CurrentTask),
+ // CustomQuery = false
+ // };
+ // this.queueProcessor.Add(task);
+ // this.queueProcessor.Start();
+ // this.IsEncoding = true;
+ }
+
+ /// <summary>
+ /// Start a Scan
+ /// </summary>
+ /// <param name="filename">
+ /// The filename.
+ /// </param>
+ /// <param name="title">
+ /// The title.
+ /// </param>
+ public void StartScan(string filename, int title)
+ {
+ if (!string.IsNullOrEmpty(filename))
+ {
+ this.scanService.Scan(
+ filename,
+ title,
+ this.UserSettingService.GetUserSetting<int>(ASUserSettingConstants.PreviewScanCount),
+ null);
+ }
+ }
+
+ /// <summary>
+ /// Stop an Encode.
+ /// </summary>
+ public void StopEncode()
+ {
+ this.queueProcessor.Pause();
+ this.encodeService.Stop();
+ }
+
+ /// <summary>
+ /// The select all.
+ /// </summary>
+ public void UnSelectAll()
+ {
+ foreach (SelectionTitle item in this.TitleList)
+ {
+ item.IsSelected = false;
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// The Encode Status has changed Handler
+ /// </summary>
+ /// <param name="sender">
+ /// The Sender
+ /// </param>
+ /// <param name="e">
+ /// The Encode Progress Event Args
+ /// </param>
+ private void EncodeStatusChanged(object sender, EncodeProgressEventArgs e)
+ {
+ int percent;
+ int.TryParse(Math.Round(e.PercentComplete).ToString(CultureInfo.InvariantCulture), out percent);
+
+ Execute.OnUIThread(
+ () =>
+ {
+ if (this.queueProcessor.EncodeService.IsEncoding)
+ {
+ string josPending = string.Empty;
+ if (!AppArguments.IsInstantHandBrake)
+ {
+ josPending = ", Pending Jobs {5}";
+ }
+
+ this.ProgramStatusLabel =
+ string.Format(
+ "{0:00.00}%, FPS: {1:000.0}, Avg FPS: {2:000.0}, Time Remaining: {3}, Elapsed: {4:hh\\:mm\\:ss}" +
+ josPending,
+ e.PercentComplete,
+ e.CurrentFrameRate,
+ e.AverageFrameRate,
+ e.EstimatedTimeLeft,
+ e.ElapsedTime,
+ this.queueProcessor.Count);
+
+ if (this.lastEncodePercentage != percent && this.windowsSeven.IsWindowsSeven)
+ {
+ this.windowsSeven.SetTaskBarProgress(percent);
+ }
+
+ this.lastEncodePercentage = percent;
+ this.ProgressPercentage = percent;
+ this.NotifyOfPropertyChange(() => this.ProgressPercentage);
+ }
+ else
+ {
+ this.ProgramStatusLabel = "Queue Finished";
+ this.IsEncoding = false;
+
+ if (this.windowsSeven.IsWindowsSeven)
+ {
+ this.windowsSeven.SetTaskBarProgressToNoProgress();
+ }
+ }
+ });
+ }
+
+ /// <summary>
+ /// The queue changed.
+ /// </summary>
+ /// <param name="sender">
+ /// The sender.
+ /// </param>
+ /// <param name="e">
+ /// The EventArgs.
+ /// </param>
+ private void QueueChanged(object sender, EventArgs e)
+ {
+ Execute.OnUIThread(
+ () => { this.ProgramStatusLabel = string.Format("{0} Encodes Pending", this.queueProcessor.Count); });
+ }
+
+ /// <summary>
+ /// The Queue has completed handler
+ /// </summary>
+ /// <param name="sender">
+ /// The Sender
+ /// </param>
+ /// <param name="e">
+ /// The EventArgs
+ /// </param>
+ private void QueueCompleted(object sender, EventArgs e)
+ {
+ this.IsEncoding = false;
+
+ Execute.OnUIThread(
+ () =>
+ {
+ this.ProgramStatusLabel = "Queue Finished";
+ this.IsEncoding = false;
+
+ if (this.windowsSeven.IsWindowsSeven)
+ {
+ this.windowsSeven.SetTaskBarProgressToNoProgress();
+ }
+ });
+ }
+
+ /// <summary>
+ /// Handle the Queue Starting Event
+ /// </summary>
+ /// <param name="sender">
+ /// The sender.
+ /// </param>
+ /// <param name="e">
+ /// The e.
+ /// </param>
+ private void QueueProcessorJobProcessingStarted(object sender, QueueProgressEventArgs e)
+ {
+ Execute.OnUIThread(
+ () =>
+ {
+ this.ProgramStatusLabel = "Preparing to encode ...";
+ this.IsEncoding = true;
+ });
+ }
+
+ /// <summary>
+ /// Handle the Scan Completed Event
+ /// </summary>
+ /// <param name="sender">
+ /// The Sender
+ /// </param>
+ /// <param name="e">
+ /// The EventArgs
+ /// </param>
+ private void ScanCompleted(object sender, ScanCompletedEventArgs e)
+ {
+ this.scanService.SouceData.CopyTo(this.ScannedSource);
+ this.NotifyOfPropertyChange(() => this.ScannedSource);
+
+ Execute.OnUIThread(
+ () =>
+ {
+ if (this.scannedSource != null)
+ {
+ this.Setup(this.scannedSource);
+ }
+
+ if (e.Successful)
+ {
+ this.NotifyOfPropertyChange(() => this.ScannedSource);
+ this.NotifyOfPropertyChange(() => this.ScannedSource.Titles);
+ }
+
+ this.ShowStatusWindow = false;
+ if (e.Successful)
+ {
+ this.SourceLabel = this.SourceName;
+ this.StatusLabel = "Scan Completed";
+ }
+ else if (e.Cancelled)
+ {
+ this.SourceLabel = "Scan Cancelled.";
+ this.StatusLabel = "Scan Cancelled.";
+ }
+ else if (e.Exception == null && e.ErrorInformation != null)
+ {
+ this.SourceLabel = "Scan failed: " + e.ErrorInformation;
+ this.StatusLabel = "Scan failed: " + e.ErrorInformation;
+ }
+ else
+ {
+ this.SourceLabel = "Scan Failed... See Activity Log for details.";
+ this.StatusLabel = "Scan Failed... See Activity Log for details.";
+ }
+ });
+ }
+
+ /// <summary>
+ /// Handle the Scan Started Event
+ /// </summary>
+ /// <param name="sender">
+ /// The Sender
+ /// </param>
+ /// <param name="e">
+ /// The EventArgs
+ /// </param>
+ private void ScanStared(object sender, EventArgs e)
+ {
+ Execute.OnUIThread(
+ () =>
+ {
+ this.StatusLabel = "Scanning source, please wait...";
+ this.ShowStatusWindow = true;
+ });
+ }
+
+ /// <summary>
+ /// Handle the Scan Status Changed Event.
+ /// </summary>
+ /// <param name="sender">
+ /// The Sender
+ /// </param>
+ /// <param name="e">
+ /// The EventArgs
+ /// </param>
+ private void ScanStatusChanged(object sender, ScanProgressEventArgs e)
+ {
+ this.SourceLabel = string.Format("Scanning Title {0} of {1} ({2}%)", e.CurrentTitle, e.Titles, e.Percentage);
+ this.StatusLabel = string.Format("Scanning Title {0} of {1} ({2}%)", e.CurrentTitle, e.Titles, e.Percentage);
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrakeWPF/ViewModels/Interfaces/IInstantViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/Interfaces/IInstantViewModel.cs
new file mode 100644
index 000000000..5481865b8
--- /dev/null
+++ b/win/CS/HandBrakeWPF/ViewModels/Interfaces/IInstantViewModel.cs
@@ -0,0 +1,18 @@
+// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="IInstantViewModel.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+// Defines the IInstantViewModel type.
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrakeWPF.ViewModels.Interfaces
+{
+ /// <summary>
+ /// The InstantViewModel interface.
+ /// </summary>
+ public interface IInstantViewModel
+ {
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrakeWPF/ViewModels/ShellViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/ShellViewModel.cs
index 565dfda76..162898f68 100644
--- a/win/CS/HandBrakeWPF/ViewModels/ShellViewModel.cs
+++ b/win/CS/HandBrakeWPF/ViewModels/ShellViewModel.cs
@@ -13,11 +13,8 @@ namespace HandBrakeWPF.ViewModels
using Caliburn.Micro;
- using Castle.Facilities.FactorySupport;
-
using HandBrake.ApplicationServices.Services.Interfaces;
- using HandBrakeWPF.Helpers;
using HandBrakeWPF.Model;
using HandBrakeWPF.Services.Interfaces;
using HandBrakeWPF.ViewModels.Interfaces;
@@ -122,6 +119,11 @@ namespace HandBrakeWPF.ViewModels
public IOptionsViewModel OptionsViewModel { get; set; }
/// <summary>
+ /// Gets or sets the instant view model.
+ /// </summary>
+ public IInstantViewModel InstantViewModel { get; set; }
+
+ /// <summary>
/// Gets or sets a value indicating whether ShowMainWindow.
/// </summary>
public bool ShowMainWindow
diff --git a/win/CS/HandBrakeWPF/Views/InstantMainView.xaml.cs b/win/CS/HandBrakeWPF/Views/InstantMainView.xaml.cs
deleted file mode 100644
index 4a74deba4..000000000
--- a/win/CS/HandBrakeWPF/Views/InstantMainView.xaml.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace HandBrakeWPF.Views
-{
- using System.Windows.Controls;
-
- /// <summary>
- /// Interaction logic for InstantMainView.xaml
- /// </summary>
- public partial class InstantMainView : UserControl
- {
- public InstantMainView()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/win/CS/HandBrakeWPF/Views/InstantMainView.xaml b/win/CS/HandBrakeWPF/Views/InstantView.xaml
index 29d8f1b4e..bb9bc1971 100644
--- a/win/CS/HandBrakeWPF/Views/InstantMainView.xaml
+++ b/win/CS/HandBrakeWPF/Views/InstantView.xaml
@@ -1,4 +1,4 @@
-<UserControl x:Class="HandBrakeWPF.Views.InstantMainView"
+<UserControl x:Class="HandBrakeWPF.Views.InstantView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -43,7 +43,6 @@
>
<StackPanel Orientation="Horizontal">
<Label Content="Source" FontWeight="Bold" />
- <Label Content="{Binding Path=SourceLabel}" />
</StackPanel>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="8,10,0,10">
@@ -59,39 +58,60 @@
</StackPanel>
-
- <StackPanel Orientation="Horizontal">
- <Label Margin="8,0,0,0" Content="Title" />
- <ComboBox Name="Titles"
- MinWidth="100"
- Margin="8,0,0,0"
- ItemsSource="{Binding ScannedSource.Titles}"
- SelectedItem="{Binding Path=SelectedTitle}"
- />
- <!--<Label Margin="8,0,0,0" Content="Angle" />
- <ComboBox Name="Angles"
- MinWidth="60"
- Margin="8,0,0,0"
- ItemsSource="{Binding Angles}"
- SelectedItem="{Binding SelectedAngle}"/>-->
-
- <Label Margin="8,0,0,0" Content="Chapters" />
- <ComboBox Name="StartPoint"
- MinWidth="60"
- Margin="8,0,0,0"
- ItemsSource="{Binding StartEndRangeItems}"
- SelectedItem="{Binding SelectedStartPoint}"/>
-
- <Label Margin="8,0,0,0" Content="through" />
- <ComboBox Name="EndPoint"
- MinWidth="60"
- Margin="8,0,0,0"
- ItemsSource="{Binding StartEndRangeItems}"
- SelectedItem="{Binding SelectedEndPoint}"/>
-
- <Label Margin="8,0,0,0" Content="Duration" />
- <Label Margin="8,0,0,0" Content="{Binding Duration}" />
- </StackPanel>
+ <ListBox Grid.Row="2"
+ Margin="10,10,10,10"
+ MinHeight="150" MaxHeight="150"
+ VerticalAlignment="Stretch"
+ Background="LightGray"
+ ItemsSource="{Binding TitleList}"
+ SelectionMode="Single">
+ <ListBox.ItemContainerStyle>
+ <Style TargetType="ListBoxItem">
+ <Setter Property="HorizontalContentAlignment" Value="Stretch" />
+ <Setter Property="Background" Value="WhiteSmoke" />
+ <Setter Property="Margin" Value="0,0,0,1" />
+ </Style>
+ </ListBox.ItemContainerStyle>
+
+ <ListBox.ContextMenu>
+ <ContextMenu>
+ <MenuItem Header="Select All" cal:Message.Attach="[Event Click] = [Action SelectAll]" />
+ <MenuItem Header="Deselect All" cal:Message.Attach="[Event Click] = [Action UnSelectAll]" />
+ <Separator />
+ <MenuItem Header="Order by Title" IsChecked="{Binding OrderedByTitle}" cal:Message.Attach="[Event Click] = [Action OrderByTitle]" />
+ <MenuItem Header="Order by Duration" IsChecked="{Binding OrderedByDuration}" cal:Message.Attach="[Event Click] = [Action OrderByDuration]" />
+ </ContextMenu>
+ </ListBox.ContextMenu>
+
+ <ListBox.ItemTemplate>
+ <DataTemplate>
+ <Grid HorizontalAlignment="Stretch" MinHeight="28">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="Auto" />
+ </Grid.ColumnDefinitions>
+
+ <CheckBox IsChecked="{Binding IsSelected}" Grid.RowSpan="2" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" />
+
+ <StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal" Margin="10,0,0,0" >
+ <TextBlock Text="Title:" Margin="0,0,5,0" FontWeight="Bold" />
+ <TextBlock Text="{Binding Title}" Margin="5,0,5,0" />
+ </StackPanel>
+
+ <StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal" Margin="10,0,0,0" >
+ <TextBlock Text="Source:" Margin="0,0,5,0" FontWeight="Bold" />
+ <TextBlock Text="{Binding SourceName}" Margin="5,0,5,0" />
+ </StackPanel>
+ </Grid>
+
+ </DataTemplate>
+ </ListBox.ItemTemplate>
+ </ListBox>
</StackPanel>
</StackPanel>
@@ -113,7 +133,7 @@
<TextBox Name="Destination"
Grid.Column="1"
Margin="8,0,0,0"
- Text="{Binding Destination,
+ Text="{Binding OutputDirectory,
UpdateSourceTrigger=PropertyChanged}"
/>
<Button Name="DestinationBrowser"
diff --git a/win/CS/HandBrakeWPF/Views/InstantView.xaml.cs b/win/CS/HandBrakeWPF/Views/InstantView.xaml.cs
new file mode 100644
index 000000000..8ca18aa87
--- /dev/null
+++ b/win/CS/HandBrakeWPF/Views/InstantView.xaml.cs
@@ -0,0 +1,27 @@
+// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="InstantView.xaml.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+// Interaction logic for InstantMainView.xaml
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrakeWPF.Views
+{
+ using System.Windows.Controls;
+
+ /// <summary>
+ /// Interaction logic for InstantMainView.xaml
+ /// </summary>
+ public partial class InstantView : UserControl
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="InstantView"/> class.
+ /// </summary>
+ public InstantView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/win/CS/HandBrakeWPF/Views/ShellView.xaml b/win/CS/HandBrakeWPF/Views/ShellView.xaml
index 49b7c94dc..84411cdca 100644
--- a/win/CS/HandBrakeWPF/Views/ShellView.xaml
+++ b/win/CS/HandBrakeWPF/Views/ShellView.xaml
@@ -25,7 +25,7 @@
<ContentControl x:Name="MainViewModel" Visibility="{Binding ShowMainWindow, Converter={StaticResource boolToVisConverter}, ConverterParameter=false}" />
<ContentControl x:Name="OptionsViewModel" Visibility="{Binding ShowOptions, Converter={StaticResource boolToVisConverter}, ConverterParameter=false}" />
- <views:InstantMainView DataContext="{Binding MainViewModel}"
+ <views:InstantView DataContext="{Binding InstantViewModel}"
Visibility="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.ShowInstant, Converter={StaticResource boolToVisConverter}, ConverterParameter=false}" />
</Grid>
</Window>