Skip to content

Commit

Permalink
WinGui: Implement a Start Timer option for the queue. (HandBrake#586)
Browse files Browse the repository at this point in the history
  • Loading branch information
sr55 committed Jun 29, 2024
1 parent e0b210f commit e882fcd
Show file tree
Hide file tree
Showing 9 changed files with 364 additions and 9 deletions.
16 changes: 16 additions & 0 deletions win/CS/HandBrakeWPF/Controls/SimpleTimeControl.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<UserControl x:Class="HandBrakeWPF.Controls.SimpleTimeControl"
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"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:HandBrakeWPF.Controls"
mc:Ignorable="d"
d:DesignHeight="30" d:DesignWidth="90">
<Grid>
<StackPanel Orientation="Horizontal">
<ComboBox x:Name="hour" Width="40" VerticalAlignment="Center" SelectionChanged="Hour_OnSelectionChanged" />
<TextBlock Text=":" Margin="3,0,3,0" VerticalAlignment="Center" FontSize="14" FontWeight="Bold" />
<ComboBox x:Name="minute" Width="40" VerticalAlignment="Center" SelectionChanged="Minute_OnSelectionChanged" />
</StackPanel>
</Grid>
</UserControl>
105 changes: 105 additions & 0 deletions win/CS/HandBrakeWPF/Controls/SimpleTimeControl.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="SimpleTimeControl.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>
// --------------------------------------------------------------------------------------------------------------------

namespace HandBrakeWPF.Controls
{
using System.Windows;
using System.Windows.Controls;

/// <summary>
/// Interaction logic for SimpleTimeControl.xaml
/// </summary>
public partial class SimpleTimeControl : UserControl
{
public static readonly DependencyProperty HourProperty = DependencyProperty.Register(
"Hour", typeof(int), typeof(SimpleTimeControl), new PropertyMetadata(0, OnHourChanged));

public static readonly DependencyProperty MinuteProperty = DependencyProperty.Register(
"Minute", typeof(int), typeof(SimpleTimeControl), new PropertyMetadata(0, OnMinuteChanged));

public SimpleTimeControl()
{
InitializeComponent();
this.DataContext = this;
this.hour.SelectedItem = 0;
this.minute.SelectedItem = 1;

for (int i = 0; i <= 23; i++)
{
this.hour.Items.Add(i);
}

for (int i = 0; i <= 59; i++)
{
this.minute.Items.Add(i);
}
}

public int Hour
{
get
{
return (int)this.GetValue(HourProperty);
}
set
{
this.SetValue(HourProperty, value);
}
}

public int Minute
{
get
{
return (int)this.GetValue(MinuteProperty);
}
set
{
this.SetValue(MinuteProperty, value);
}
}

private static void OnHourChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is SimpleTimeControl)
{
SimpleTimeControl ctlControl = (SimpleTimeControl)d;
ctlControl.hour.SelectedItem = (int)e.NewValue;
}
}


private static void OnMinuteChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is SimpleTimeControl)
{
SimpleTimeControl ctlControl = (SimpleTimeControl)d;
ctlControl.minute.SelectedItem = (int)e.NewValue;
}
}


private void Hour_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (this.hour.SelectedItem == null || this.minute.SelectedItem == null)
{
return;
}

this.Hour = (int)this.hour.SelectedItem;
}

private void Minute_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (this.hour.SelectedItem == null || this.minute.SelectedItem == null)
{
return;
}

this.Minute = (int)this.minute.SelectedItem;
}
}
}
18 changes: 18 additions & 0 deletions win/CS/HandBrakeWPF/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions win/CS/HandBrakeWPF/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -2840,4 +2840,10 @@ To allow multiple simultaneous encodes, turn on "Process Isolation" in Tools Men
<data name="AddToQueue_RangeLimitError" xml:space="preserve">
<value>Some titles could not be added to the queue due to being outside of the selected range limits.</value>
</data>
<data name="QueueView_StartAtTime" xml:space="preserve">
<value>Start Later</value>
</data>
<data name="QueueView_QueueStartTime" xml:space="preserve">
<value>Queue Start Time:</value>
</data>
</root>
56 changes: 56 additions & 0 deletions win/CS/HandBrakeWPF/Utilities/TaskExecutor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TaskScheduler.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>
// --------------------------------------------------------------------------------------------------------------------
namespace HandBrakeWPF.Utilities
{
using System;
using System.Threading;

public class TaskExecutor
{
private Timer timer;

private Action action;

public void ScheduleTask(int hour, int min, Action task)
{
if (timer != null)
{
this.CancelTask();
}

DateTime now = DateTime.Now;
DateTime firstRun = new DateTime(now.Year, now.Month, now.Day, hour, min, 0, 0);
if (now > firstRun)
{
firstRun = firstRun.AddDays(1);
}

TimeSpan timeToGo = firstRun - now;
if (timeToGo <= TimeSpan.Zero)
{
timeToGo = TimeSpan.Zero;
}

action = task;

timer = new Timer(x =>
{
action.Invoke();
}, null, timeToGo, TimeSpan.FromSeconds(60));


}

public void CancelTask()
{
if (this.timer != null)
{
this.timer.Dispose();
this.timer = null;
}
}
}
}
6 changes: 4 additions & 2 deletions win/CS/HandBrakeWPF/ViewModels/Interfaces/IQueueViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@

namespace HandBrakeWPF.ViewModels.Interfaces
{
using HandBrakeWPF.Model.Options;

/// <summary>
/// The Queue View Model Interface
/// </summary>
Expand All @@ -27,6 +25,10 @@ public interface IQueueViewModel
/// </param>
void WhenDone(int action, bool saveChange);

void StartQueue();

void StartQueueAtTime();

/// <summary>
/// The import.
/// </summary>
Expand Down
93 changes: 92 additions & 1 deletion win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace HandBrakeWPF.ViewModels
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

Expand All @@ -32,6 +33,7 @@ namespace HandBrakeWPF.ViewModels
using HandBrakeWPF.Services.Interfaces;
using HandBrakeWPF.Services.Queue.Interfaces;
using HandBrakeWPF.Services.Queue.Model;
using HandBrakeWPF.Utilities;
using HandBrakeWPF.Utilities.FileDialogs;
using HandBrakeWPF.ViewModels.Interfaces;

Expand All @@ -45,7 +47,11 @@ public class QueueViewModel : ViewModelBase, IQueueViewModel
private QueueTask selectedTask;
private bool isQueueRunning;
private bool extendedQueueDisplay;

private TaskExecutor queueStartRunner;
private bool isStartTimeEnabled;
private int startHour;
private int startMinute;

public QueueViewModel(IUserSettingService userSettingService, IQueueService queueProcessor, IErrorService errorService)
{
this.userSettingService = userSettingService;
Expand All @@ -64,6 +70,8 @@ public QueueViewModel(IUserSettingService userSettingService, IQueueService queu
this.WhenDoneCommand = new SimpleRelayCommand<int>(this.WhenDone);
this.RetryCommand = new SimpleRelayCommand<QueueTask>(this.RetryJob);
this.EditCommand = new SimpleRelayCommand<QueueTask>(this.EditJob);

this.queueStartRunner = new TaskExecutor();
}

public event EventHandler SimpleViewChanged;
Expand Down Expand Up @@ -188,6 +196,53 @@ public bool ExtendedQueueDisplay
}
}

public int StartHour
{
get => this.startHour;
set
{
if (value == this.startHour)
{
return;
}

this.startHour = value;
this.NotifyOfPropertyChange(() => this.StartHour);
this.UpdateDelayedQueueStart();
}
}

public int StartMinute
{
get => this.startMinute;
set
{
if (value == this.startMinute)
{
return;
}

this.startMinute = value;
this.NotifyOfPropertyChange(() => this.StartMinute);
this.UpdateDelayedQueueStart();
}
}

public bool IsStartTimeEnabled
{
get => this.isStartTimeEnabled;
set
{
if (value == this.isStartTimeEnabled)
{
return;
}

this.isStartTimeEnabled = value;
this.NotifyOfPropertyChange(() => this.IsStartTimeEnabled);
}
}

public void WhenDone(int action)
{
this.WhenDone(action, true);
Expand Down Expand Up @@ -405,6 +460,42 @@ public void StartQueue()
this.queueProcessor.Start();
}

public void StartQueueAtTime()
{
this.IsStartTimeEnabled = true;
DateTime start = DateTime.Now.AddHours(1);
this.startHour = start.Hour;
this.startMinute = start.Minute;
this.NotifyOfPropertyChange(() => this.StartHour);
this.NotifyOfPropertyChange(() => this.StartMinute);

UpdateDelayedQueueStart();
}

public void UpdateDelayedQueueStart()
{
queueStartRunner.ScheduleTask(this.StartHour, StartMinute,
() =>
{
queueStartRunner.CancelTask();
ThreadHelper.OnUIThread(
() =>
{
if (!this.IsQueueRunning)
{
this.queueProcessor.Start();
this.IsStartTimeEnabled = false;
}
});
});
}

public void CancelDelayedStart()
{
this.IsStartTimeEnabled = false;
queueStartRunner.CancelTask();
}

public void ExportCli()
{
SaveFileDialog dialog = new SaveFileDialog
Expand Down
Loading

0 comments on commit e882fcd

Please sign in to comment.