From aea2c5f0a32428671182a5e9d680ab4c016fce2c Mon Sep 17 00:00:00 2001 From: sr55 Date: Sun, 8 Jul 2012 15:57:58 +0000 Subject: WinGui: Initial work to restore queue editing functionality. (Note, it's not complete yet) git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4821 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- .../Converters/Audio/AudioQueueDisplayConverter.cs | 2 +- .../Subtitles/SubtitlesQueueDisplayConverter.cs | 67 ++++++++++++++++++ win/CS/HandBrakeWPF/HandBrakeWPF.csproj | 3 +- .../Services/Interfaces/IJobContextService.cs | 30 -------- win/CS/HandBrakeWPF/Services/JobContextService.cs | 32 --------- win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs | 1 - .../HandBrakeWPF/ViewModels/AdvancedViewModel.cs | 13 ++++ win/CS/HandBrakeWPF/ViewModels/AudioViewModel.cs | 13 ++++ .../HandBrakeWPF/ViewModels/ChaptersViewModel.cs | 14 ++++ win/CS/HandBrakeWPF/ViewModels/FiltersViewModel.cs | 23 ++++++ .../ViewModels/Interfaces/IMainViewModel.cs | 8 +++ .../ViewModels/Interfaces/ITabInterface.cs | 8 +++ win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs | 60 +++++++++++++++- .../ViewModels/PictureSettingsViewModel.cs | 18 +++++ win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs | 27 ++++++++ .../HandBrakeWPF/ViewModels/SubtitlesViewModel.cs | 12 ++++ win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs | 21 ++++++ win/CS/HandBrakeWPF/ViewModels/ViewModelBase.cs | 4 -- win/CS/HandBrakeWPF/Views/QueueView.xaml | 81 +++++++++++++++------- 19 files changed, 340 insertions(+), 97 deletions(-) create mode 100644 win/CS/HandBrakeWPF/Converters/Subtitles/SubtitlesQueueDisplayConverter.cs delete mode 100644 win/CS/HandBrakeWPF/Services/Interfaces/IJobContextService.cs delete mode 100644 win/CS/HandBrakeWPF/Services/JobContextService.cs (limited to 'win/CS/HandBrakeWPF') diff --git a/win/CS/HandBrakeWPF/Converters/Audio/AudioQueueDisplayConverter.cs b/win/CS/HandBrakeWPF/Converters/Audio/AudioQueueDisplayConverter.cs index d3440e265..624e40a57 100644 --- a/win/CS/HandBrakeWPF/Converters/Audio/AudioQueueDisplayConverter.cs +++ b/win/CS/HandBrakeWPF/Converters/Audio/AudioQueueDisplayConverter.cs @@ -45,7 +45,7 @@ namespace HandBrakeWPF.Converters.Audio } else { - audioTracks.Append( "," + EnumHelper.GetDisplay(track.Encoder)); + audioTracks.Append(", " + EnumHelper.GetDisplay(track.Encoder)); } } } diff --git a/win/CS/HandBrakeWPF/Converters/Subtitles/SubtitlesQueueDisplayConverter.cs b/win/CS/HandBrakeWPF/Converters/Subtitles/SubtitlesQueueDisplayConverter.cs new file mode 100644 index 000000000..e30967ae3 --- /dev/null +++ b/win/CS/HandBrakeWPF/Converters/Subtitles/SubtitlesQueueDisplayConverter.cs @@ -0,0 +1,67 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// +// +// Subtitle Queue Display Converter +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Converters.Subtitles +{ + using System; + using System.Collections.ObjectModel; + using System.Globalization; + using System.Text; + using System.Windows.Data; + + using HandBrake.ApplicationServices.Model.Encoding; + + /// + /// Subtitle Queue Display Converter + /// + public class SubtitlesQueueDisplayConverter : IValueConverter + { + /// + /// Converts a value. + /// + /// + /// A converted value. If the method returns null, the valid null value is used. + /// + /// The value produced by the binding source.The type of the binding target property.The converter parameter to use.The culture to use in the converter. + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + ObservableCollection tracks = value as ObservableCollection; + StringBuilder audioTracks = new StringBuilder(); + if (tracks != null) + { + foreach (SubtitleTrack track in tracks) + { + string text = track.SourceTrack != null ? track.SourceTrack.ToString() : (track.SrtFileName + ".srt"); + if (string.IsNullOrEmpty(audioTracks.ToString())) + { + audioTracks.Append(text); + } + else + { + audioTracks.Append(", " + text); + } + } + } + + return string.IsNullOrEmpty(audioTracks.ToString()) ? "None" : audioTracks.ToString(); + } + + /// + /// Converts a value. + /// + /// + /// A converted value. If the method returns null, the valid null value is used. + /// + /// The value that is produced by the binding target.The type to convert to.The converter parameter to use.The culture to use in the converter. + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/win/CS/HandBrakeWPF/HandBrakeWPF.csproj b/win/CS/HandBrakeWPF/HandBrakeWPF.csproj index 7ef57cd74..2a10df83a 100644 --- a/win/CS/HandBrakeWPF/HandBrakeWPF.csproj +++ b/win/CS/HandBrakeWPF/HandBrakeWPF.csproj @@ -123,6 +123,7 @@ + @@ -152,10 +153,8 @@ - - diff --git a/win/CS/HandBrakeWPF/Services/Interfaces/IJobContextService.cs b/win/CS/HandBrakeWPF/Services/Interfaces/IJobContextService.cs deleted file mode 100644 index d1301026b..000000000 --- a/win/CS/HandBrakeWPF/Services/Interfaces/IJobContextService.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. -// -// -// Defines the IJobContextService type. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace HandBrakeWPF.Services.Interfaces -{ - using HandBrake.ApplicationServices.Model; - using HandBrake.ApplicationServices.Parsing; - - /// - /// A Context service for the current Job Information - /// - public interface IJobContextService - { - /// - /// Gets or sets CurrentTask. - /// - EncodeTask CurrentTask { get; set; } - - /// - /// Gets or sets CurrentSource. - /// - Source CurrentSource { get; set; } - } -} \ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/JobContextService.cs b/win/CS/HandBrakeWPF/Services/JobContextService.cs deleted file mode 100644 index b5f3060a5..000000000 --- a/win/CS/HandBrakeWPF/Services/JobContextService.cs +++ /dev/null @@ -1,32 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. -// -// -// Defines the JobContextService type. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace HandBrakeWPF.Services -{ - using HandBrake.ApplicationServices.Model; - using HandBrake.ApplicationServices.Parsing; - - using HandBrakeWPF.Services.Interfaces; - - /// - /// A Context service for the current Job Information. - /// - public class JobContextService : IJobContextService - { - /// - /// Gets or sets CurrentTask. - /// - public EncodeTask CurrentTask { get; set; } - - /// - /// Gets or sets CurrentSource. - /// - public Source CurrentSource { get; set; } - } -} diff --git a/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs b/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs index e929047ea..632b93877 100644 --- a/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs +++ b/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs @@ -66,7 +66,6 @@ namespace HandBrakeWPF.Startup this.windsorContainer.Register(Component.For().ImplementedBy().LifeStyle.Is(LifestyleType.Singleton)); this.windsorContainer.Register(Component.For().ImplementedBy().LifeStyle.Is(LifestyleType.Singleton)); this.windsorContainer.Register(Component.For().ImplementedBy().LifeStyle.Is(LifestyleType.Singleton)); - this.windsorContainer.Register(Component.For().ImplementedBy().LifeStyle.Is(LifestyleType.Singleton)); this.windsorContainer.Register(Component.For().ImplementedBy().LifeStyle.Is(LifestyleType.Singleton)); // Tab Components diff --git a/win/CS/HandBrakeWPF/ViewModels/AdvancedViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/AdvancedViewModel.cs index 39861bce7..2a0425114 100644 --- a/win/CS/HandBrakeWPF/ViewModels/AdvancedViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/AdvancedViewModel.cs @@ -953,6 +953,19 @@ namespace HandBrakeWPF.ViewModels this.AdvancedOptionsString = preset.Task.AdvancedEncoderOptions; } + /// + /// Update all the UI controls based on the encode task passed in. + /// + /// + /// The task. + /// + public void UpdateTask(EncodeTask task) + { + this.Task = task; + this.SetEncoder(task.VideoEncoder); + this.AdvancedOptionsString = task.AdvancedEncoderOptions; + } + /// /// Setup this window for a new source /// diff --git a/win/CS/HandBrakeWPF/ViewModels/AudioViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/AudioViewModel.cs index 06bd20326..03e779665 100644 --- a/win/CS/HandBrakeWPF/ViewModels/AudioViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/AudioViewModel.cs @@ -184,6 +184,19 @@ namespace HandBrakeWPF.ViewModels this.UserSettingService.GetUserSetting(UserSettingConstants.ShowAdvancedAudioPassthruOpts); } + /// + /// Update all the UI controls based on the encode task passed in. + /// + /// + /// The task. + /// + public void UpdateTask(EncodeTask task) + { + this.Task = task; + this.NotifyOfPropertyChange(() => Task.AudioTracks); + this.NotifyOfPropertyChange(() => this.Task); + } + /// /// Set the Source Title /// diff --git a/win/CS/HandBrakeWPF/ViewModels/ChaptersViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/ChaptersViewModel.cs index cbd6e8441..586167840 100644 --- a/win/CS/HandBrakeWPF/ViewModels/ChaptersViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/ChaptersViewModel.cs @@ -226,6 +226,20 @@ namespace HandBrakeWPF.ViewModels this.NotifyOfPropertyChange(() => this.Task); } + /// + /// Update all the UI controls based on the encode task passed in. + /// + /// + /// The task. + /// + public void UpdateTask(EncodeTask task) + { + this.Task = task; + + this.NotifyOfPropertyChange(() => this.Task.IncludeChapterMarkers); + this.NotifyOfPropertyChange(() => this.Task.ChapterNames); + } + /// /// Set the Source Chapters List /// diff --git a/win/CS/HandBrakeWPF/ViewModels/FiltersViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/FiltersViewModel.cs index 92d069698..e6a93a41b 100644 --- a/win/CS/HandBrakeWPF/ViewModels/FiltersViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/FiltersViewModel.cs @@ -372,6 +372,29 @@ namespace HandBrakeWPF.ViewModels } } + /// + /// Update all the UI controls based on the encode task passed in. + /// + /// + /// The task. + /// + public void UpdateTask(EncodeTask task) + { + this.CurrentTask = task; + + this.NotifyOfPropertyChange(() => this.SelectedDenoise); + this.NotifyOfPropertyChange(() => this.SelectedDecomb); + this.NotifyOfPropertyChange(() => this.SelectedDeInterlace); + this.NotifyOfPropertyChange(() => this.SelectedDetelecine); + this.NotifyOfPropertyChange(() => this.Grayscale); + this.NotifyOfPropertyChange(() => this.DeblockValue); + + this.NotifyOfPropertyChange(() => this.CustomDecomb); + this.NotifyOfPropertyChange(() => this.CustomDeinterlace); + this.NotifyOfPropertyChange(() => this.CustomDetelecine); + this.NotifyOfPropertyChange(() => this.CustomDenoise); + } + /// /// Setup this window for a new source /// diff --git a/win/CS/HandBrakeWPF/ViewModels/Interfaces/IMainViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/Interfaces/IMainViewModel.cs index 8f1f6e5a6..079ce3ad5 100644 --- a/win/CS/HandBrakeWPF/ViewModels/Interfaces/IMainViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/Interfaces/IMainViewModel.cs @@ -60,5 +60,13 @@ namespace HandBrakeWPF.ViewModels.Interfaces /// Start an Encode /// void StartEncode(); + + /// + /// Edit a Queue Task + /// + /// + /// The task. + /// + void EditQueueJob(EncodeTask task); } } \ No newline at end of file diff --git a/win/CS/HandBrakeWPF/ViewModels/Interfaces/ITabInterface.cs b/win/CS/HandBrakeWPF/ViewModels/Interfaces/ITabInterface.cs index b583fba86..42ca560f4 100644 --- a/win/CS/HandBrakeWPF/ViewModels/Interfaces/ITabInterface.cs +++ b/win/CS/HandBrakeWPF/ViewModels/Interfaces/ITabInterface.cs @@ -41,5 +41,13 @@ namespace HandBrakeWPF.ViewModels.Interfaces /// The task. /// void SetPreset(Preset preset, EncodeTask task); + + /// + /// Update all the UI controls based on the encode task passed in. + /// + /// + /// The task. + /// + void UpdateTask(EncodeTask task); } } diff --git a/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs index d63915624..36a1a0e11 100644 --- a/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs @@ -147,6 +147,11 @@ namespace HandBrakeWPF.ViewModels /// private Preset selectedPreset; + /// + /// Queue Edit Task + /// + private EncodeTask queueEditTask; + #endregion /// @@ -1114,6 +1119,19 @@ namespace HandBrakeWPF.ViewModels this.IsEncoding = true; } + /// + /// Edit a Queue Task + /// + /// + /// The task. + /// + public void EditQueueJob(EncodeTask task) + { + // Rescan the source to make sure it's still valid + this.queueEditTask = task; + this.scanService.Scan(task.Source, task.Title, this.UserSettingService.GetUserSetting(ASUserSettingConstants.PreviewScanCount), QueueEditAction); + } + /// /// Pause an Encode /// @@ -1368,6 +1386,44 @@ namespace HandBrakeWPF.ViewModels #region Private Methods + /// + /// Update all the UI Components to allow the user to edit their previous settings. + /// + /// + /// The successful. + /// + private void QueueEditAction(bool successful) + { + Execute.OnUIThread(() => + { + // Copy all the Scan data into the UI + this.scanService.SouceData.CopyTo(this.ScannedSource); + this.NotifyOfPropertyChange(() => this.ScannedSource); + this.NotifyOfPropertyChange(() => this.ScannedSource.Titles); + + // Select the Users Title + this.CurrentTask = new EncodeTask(queueEditTask); + this.NotifyOfPropertyChange(() => this.CurrentTask); + this.SelectedTitle = this.ScannedSource.Titles.FirstOrDefault(t => t.TitleNumber == this.CurrentTask.Title); + + // Update the Main UI control Area (TODO) + this.CurrentTask = new EncodeTask(queueEditTask); + this.NotifyOfPropertyChange(() => this.CurrentTask); + + // Update the Tab Controls (TODO) + this.PictureSettingsViewModel.UpdateTask(this.CurrentTask); + this.VideoViewModel.UpdateTask(this.CurrentTask); + this.FiltersViewModel.UpdateTask(this.CurrentTask); + this.AudioViewModel.UpdateTask(this.CurrentTask); + this.SubtitleViewModel.UpdateTask(this.CurrentTask); + this.ChaptersViewModel.UpdateTask(this.CurrentTask); + this.AdvancedViewModel.UpdateTask(this.CurrentTask); + + // Cleanup + this.ShowStatusWindow = false; + }); + } + /// /// Start a Scan /// @@ -1381,7 +1437,7 @@ namespace HandBrakeWPF.ViewModels { // TODO // 1. Disable GUI. - this.scanService.Scan(filename, title, this.UserSettingService.GetUserSetting(ASUserSettingConstants.PreviewScanCount)); + this.scanService.Scan(filename, title, this.UserSettingService.GetUserSetting(ASUserSettingConstants.PreviewScanCount), null); } /// @@ -1548,8 +1604,6 @@ namespace HandBrakeWPF.ViewModels this.NotifyOfPropertyChange("ScannedSource.Titles"); this.SelectedTitle = this.ScannedSource.Titles.FirstOrDefault(t => t.MainTitle) ?? this.ScannedSource.Titles.FirstOrDefault(); - this.JobContextService.CurrentSource = this.ScannedSource; - this.JobContextService.CurrentTask = this.CurrentTask; this.SetupTabs(); this.ShowStatusWindow = false; } diff --git a/win/CS/HandBrakeWPF/ViewModels/PictureSettingsViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/PictureSettingsViewModel.cs index b052a4ba7..e911905d2 100644 --- a/win/CS/HandBrakeWPF/ViewModels/PictureSettingsViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/PictureSettingsViewModel.cs @@ -639,6 +639,24 @@ namespace HandBrakeWPF.ViewModels this.NotifyOfPropertyChange(() => this.Task); } + /// + /// Update all the UI controls based on the encode task passed in. + /// + /// + /// The task. + /// + public void UpdateTask(EncodeTask task) + { + this.Task = task; + this.NotifyOfPropertyChange(() => this.Width); + this.NotifyOfPropertyChange(() => this.Height); + this.NotifyOfPropertyChange(() => this.SelectedAnamorphicMode); + this.NotifyOfPropertyChange(() => this.SelectedModulus); + this.NotifyOfPropertyChange(() => this.DisplayWidth); + this.NotifyOfPropertyChange(() => this.ParHeight); + this.NotifyOfPropertyChange(() => this.ParWidth); + } + /// /// Setup this window for a new source /// diff --git a/win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs index abcf289e5..badb64e17 100644 --- a/win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs @@ -331,6 +331,33 @@ namespace HandBrakeWPF.ViewModels this.queueProcessor.QueueManager.RestoreQueue(dialog.FileName); } + /// + /// Edit this Job + /// + /// + /// The task. + /// + public void EditJob(QueueTask task) + { + MessageBoxResult result = this.errorService.ShowMessageBox( + "Are you sure you wish to edit this job?\nWARNING!!! This feature is not finished YET! Only part of the job will be copied back!!!", + "Modify Job?", + MessageBoxButton.YesNo, + MessageBoxImage.Question); + + if (result != MessageBoxResult.Yes) + { + return; + } + + // Remove the job if it is not already encoding. Let the user decide if they want to cancel or not. + this.RemoveJob(task); + + // Pass a copy of the job back to the Main Screen + IMainViewModel mvm = IoC.Get(); + mvm.EditQueueJob(new EncodeTask(task.Task)); + } + #endregion #region Methods diff --git a/win/CS/HandBrakeWPF/ViewModels/SubtitlesViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/SubtitlesViewModel.cs index aaf6fa43e..5950bc448 100644 --- a/win/CS/HandBrakeWPF/ViewModels/SubtitlesViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/SubtitlesViewModel.cs @@ -252,6 +252,18 @@ namespace HandBrakeWPF.ViewModels this.NotifyOfPropertyChange(() => this.Task); } + /// + /// Update all the UI controls based on the encode task passed in. + /// + /// + /// The task. + /// + public void UpdateTask(EncodeTask task) + { + this.Task = task; + this.NotifyOfPropertyChange(() => this.Task.SubtitleTracks); + } + /// /// Setup this window for a new source /// diff --git a/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs index a520bf202..c5460b0ae 100644 --- a/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs @@ -487,7 +487,28 @@ namespace HandBrakeWPF.ViewModels // this.X264Profile = preset.Task.x264Profile; // this.X264Tune = preset.Task.X264Tune; //} + } + /// + /// Update all the UI controls based on the encode task passed in. + /// + /// + /// The task. + /// + public void UpdateTask(EncodeTask task) + { + this.Task = task; + this.NotifyOfPropertyChange(() => this.IsConstantFramerate); + this.NotifyOfPropertyChange(() => this.IsConstantQuantity); + this.NotifyOfPropertyChange(() => this.IsPeakFramerate); + this.NotifyOfPropertyChange(() => this.IsVariableFramerate); + this.NotifyOfPropertyChange(() => this.SelectedVideoEncoder); + this.NotifyOfPropertyChange(() => this.SelectedFramerate); + this.NotifyOfPropertyChange(() => this.RF); + this.NotifyOfPropertyChange(() => this.DisplayRF); + this.NotifyOfPropertyChange(() => this.Task.VideoBitrate); + this.NotifyOfPropertyChange(() => this.Task.TwoPass); + this.NotifyOfPropertyChange(() => this.Task.TurboFirstPass); } /// diff --git a/win/CS/HandBrakeWPF/ViewModels/ViewModelBase.cs b/win/CS/HandBrakeWPF/ViewModels/ViewModelBase.cs index dd992ef68..ac9098bac 100644 --- a/win/CS/HandBrakeWPF/ViewModels/ViewModelBase.cs +++ b/win/CS/HandBrakeWPF/ViewModels/ViewModelBase.cs @@ -75,10 +75,6 @@ namespace HandBrakeWPF.ViewModels /// public IUserSettingService UserSettingService { get; set; } - /// - /// Gets or sets JobContextService. - /// - public IJobContextService JobContextService { get; set; } #endregion #region Public Methods diff --git a/win/CS/HandBrakeWPF/Views/QueueView.xaml b/win/CS/HandBrakeWPF/Views/QueueView.xaml index 8b3b31f03..6c64557b1 100644 --- a/win/CS/HandBrakeWPF/Views/QueueView.xaml +++ b/win/CS/HandBrakeWPF/Views/QueueView.xaml @@ -8,7 +8,8 @@ xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:YourNamespace="clr-namespace:HandBrakeWPF.AttachedProperties" - xmlns:Audio="clr-namespace:HandBrakeWPF.Converters.Audio" Title="{Binding Title}" + xmlns:Audio="clr-namespace:HandBrakeWPF.Converters.Audio" + xmlns:Subtitles="clr-namespace:HandBrakeWPF.Converters.Subtitles" Title="{Binding Title}" Width="600" Height="400" MinWidth="600" @@ -24,6 +25,7 @@ + @@ -142,6 +144,7 @@ dd:DragDrop.IsDragSource="True" dd:DragDrop.IsDropTarget="True" ItemsSource="{Binding QueueJobs}" + SelectedItem="{Binding SelectedJob}" SelectionMode="Extended"> @@ -171,7 +174,12 @@ - + + + + + + @@ -251,36 +259,61 @@ - - + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + -- cgit v1.2.3