2013-05-04 15:03:38 +00:00
|
|
|
|
using MahApps.Metro.Controls;
|
|
|
|
|
using MediaBrowser.Common;
|
2013-02-21 01:33:05 +00:00
|
|
|
|
using MediaBrowser.Controller.Entities;
|
|
|
|
|
using MediaBrowser.Controller.Entities.Movies;
|
|
|
|
|
using MediaBrowser.Controller.Entities.TV;
|
|
|
|
|
using MediaBrowser.Controller.Library;
|
|
|
|
|
using MediaBrowser.Controller.Localization;
|
2013-06-18 19:16:27 +00:00
|
|
|
|
using MediaBrowser.Controller.Persistence;
|
2013-03-10 04:22:36 +00:00
|
|
|
|
using MediaBrowser.Model.Dto;
|
2013-02-21 01:33:05 +00:00
|
|
|
|
using MediaBrowser.Model.Entities;
|
2013-02-24 21:53:54 +00:00
|
|
|
|
using MediaBrowser.Model.Logging;
|
2013-03-10 05:36:39 +00:00
|
|
|
|
using MediaBrowser.Model.Querying;
|
2013-02-24 21:53:54 +00:00
|
|
|
|
using MediaBrowser.Model.Serialization;
|
2013-02-21 01:33:05 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Globalization;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Windows;
|
|
|
|
|
using System.Windows.Controls;
|
|
|
|
|
using System.Windows.Data;
|
|
|
|
|
using System.Windows.Input;
|
|
|
|
|
using System.Windows.Media.Imaging;
|
|
|
|
|
|
|
|
|
|
namespace MediaBrowser.ServerApplication
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Interaction logic for LibraryExplorer.xaml
|
|
|
|
|
/// </summary>
|
2013-05-04 15:03:38 +00:00
|
|
|
|
public partial class LibraryExplorer : MetroWindow
|
2013-02-21 01:33:05 +00:00
|
|
|
|
{
|
2013-02-24 21:53:54 +00:00
|
|
|
|
private readonly ILogger _logger;
|
2013-02-21 20:26:35 +00:00
|
|
|
|
|
2013-02-24 21:53:54 +00:00
|
|
|
|
private readonly IJsonSerializer _jsonSerializer;
|
2013-02-28 19:32:41 +00:00
|
|
|
|
private readonly ILibraryManager _libraryManager;
|
2013-06-18 19:16:27 +00:00
|
|
|
|
private readonly IDisplayPreferencesRepository _displayPreferencesManager;
|
2013-04-02 17:37:49 +00:00
|
|
|
|
|
2013-02-21 01:33:05 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// The current user
|
|
|
|
|
/// </summary>
|
|
|
|
|
private User CurrentUser;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initializes a new instance of the <see cref="LibraryExplorer" /> class.
|
|
|
|
|
/// </summary>
|
2013-04-05 19:34:33 +00:00
|
|
|
|
/// <param name="jsonSerializer">The json serializer.</param>
|
|
|
|
|
/// <param name="logger">The logger.</param>
|
|
|
|
|
/// <param name="appHost">The app host.</param>
|
|
|
|
|
/// <param name="userManager">The user manager.</param>
|
|
|
|
|
/// <param name="libraryManager">The library manager.</param>
|
|
|
|
|
/// <param name="displayPreferencesManager">The display preferences manager.</param>
|
2013-06-18 19:16:27 +00:00
|
|
|
|
public LibraryExplorer(IJsonSerializer jsonSerializer, ILogger logger, IApplicationHost appHost, IUserManager userManager, ILibraryManager libraryManager, IDisplayPreferencesRepository displayPreferencesManager)
|
2013-02-21 01:33:05 +00:00
|
|
|
|
{
|
2013-02-21 20:26:35 +00:00
|
|
|
|
_logger = logger;
|
2013-02-24 21:53:54 +00:00
|
|
|
|
_jsonSerializer = jsonSerializer;
|
2013-03-03 20:55:02 +00:00
|
|
|
|
_libraryManager = libraryManager;
|
2013-04-05 19:34:33 +00:00
|
|
|
|
_displayPreferencesManager = displayPreferencesManager;
|
2013-02-21 20:26:35 +00:00
|
|
|
|
|
2013-02-21 01:33:05 +00:00
|
|
|
|
InitializeComponent();
|
2013-02-26 03:43:04 +00:00
|
|
|
|
lblVersion.Content = "Version: " + appHost.ApplicationVersion;
|
2013-02-27 20:25:45 +00:00
|
|
|
|
foreach (var user in userManager.Users)
|
2013-02-21 01:33:05 +00:00
|
|
|
|
ddlProfile.Items.Add(user);
|
|
|
|
|
ddlProfile.Items.Insert(0,new User {Name = "Physical"});
|
|
|
|
|
ddlProfile.SelectedIndex = 0;
|
|
|
|
|
ddlIndexBy.Visibility = ddlSortBy.Visibility = lblIndexBy.Visibility = lblSortBy.Visibility = Visibility.Hidden;
|
2013-02-28 19:32:41 +00:00
|
|
|
|
|
2013-02-21 01:33:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Handles the Click event of the btnLoad control.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender">The source of the event.</param>
|
|
|
|
|
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
|
|
|
|
|
private void btnLoad_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Loads the tree.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>Task.</returns>
|
|
|
|
|
private async Task LoadTree()
|
|
|
|
|
{
|
|
|
|
|
tvwLibrary.Items.Clear();
|
|
|
|
|
lblLoading.Visibility = Visibility.Visible;
|
|
|
|
|
//grab UI context so we can update within the below task
|
|
|
|
|
var ui = TaskScheduler.FromCurrentSynchronizationContext();
|
|
|
|
|
//this whole async thing doesn't really work in this instance since all my work pretty much needs to be on the UI thread...
|
|
|
|
|
Cursor = Cursors.Wait;
|
|
|
|
|
await Task.Run(() =>
|
2013-03-04 05:43:06 +00:00
|
|
|
|
{
|
2013-07-05 13:47:10 +00:00
|
|
|
|
IEnumerable<BaseItem> children = CurrentUser.Name == "Physical" ? _libraryManager.RootFolder.Children : _libraryManager.RootFolder.GetChildren(CurrentUser, true);
|
2013-03-10 04:22:36 +00:00
|
|
|
|
children = OrderByName(children, CurrentUser);
|
2013-02-21 01:33:05 +00:00
|
|
|
|
|
2013-03-04 05:43:06 +00:00
|
|
|
|
foreach (Folder folder in children)
|
2013-02-21 01:33:05 +00:00
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
var currentFolder = folder;
|
|
|
|
|
Task.Factory.StartNew(() =>
|
|
|
|
|
{
|
2013-06-18 19:16:27 +00:00
|
|
|
|
var prefs = ddlProfile.SelectedItem != null ? _displayPreferencesManager.GetDisplayPreferences(currentFolder.GetDisplayPreferencesId((ddlProfile.SelectedItem as User).Id)) ?? new DisplayPreferences { SortBy = ItemSortBy.SortName } : new DisplayPreferences { SortBy = ItemSortBy.SortName };
|
2013-02-21 01:33:05 +00:00
|
|
|
|
var node = new TreeViewItem { Tag = currentFolder };
|
2013-03-10 04:22:36 +00:00
|
|
|
|
|
2013-07-05 13:47:10 +00:00
|
|
|
|
var subChildren = currentFolder.GetChildren(CurrentUser, true, prefs.IndexBy);
|
2013-03-10 04:22:36 +00:00
|
|
|
|
subChildren = OrderByName(subChildren, CurrentUser);
|
|
|
|
|
AddChildren(node, subChildren, CurrentUser);
|
2013-02-21 01:33:05 +00:00
|
|
|
|
node.Header = currentFolder.Name + " (" +
|
|
|
|
|
node.Items.Count + ")";
|
|
|
|
|
tvwLibrary.Items.Add(node);
|
|
|
|
|
}, CancellationToken.None, TaskCreationOptions.None, ui);
|
|
|
|
|
}
|
2013-03-04 05:43:06 +00:00
|
|
|
|
});
|
2013-02-21 01:33:05 +00:00
|
|
|
|
lblLoading.Visibility = Visibility.Hidden;
|
|
|
|
|
Cursor = Cursors.Arrow;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-10 04:22:36 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Orders the name of the by.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="items">The items.</param>
|
|
|
|
|
/// <param name="user">The user.</param>
|
|
|
|
|
/// <returns>IEnumerable{BaseItem}.</returns>
|
|
|
|
|
private IEnumerable<BaseItem> OrderByName(IEnumerable<BaseItem> items, User user)
|
|
|
|
|
{
|
|
|
|
|
return OrderBy(items, user, ItemSortBy.SortName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Orders the name of the by.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="items">The items.</param>
|
|
|
|
|
/// <param name="user">The user.</param>
|
|
|
|
|
/// <returns>IEnumerable{BaseItem}.</returns>
|
|
|
|
|
private IEnumerable<BaseItem> OrderBy(IEnumerable<BaseItem> items, User user, string order)
|
|
|
|
|
{
|
|
|
|
|
return _libraryManager.Sort(items, user, new[] { order }, SortOrder.Ascending);
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-21 01:33:05 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Adds the children.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="parent">The parent.</param>
|
|
|
|
|
/// <param name="children">The children.</param>
|
|
|
|
|
/// <param name="user">The user.</param>
|
|
|
|
|
private void AddChildren(TreeViewItem parent, IEnumerable<BaseItem> children, User user)
|
|
|
|
|
{
|
|
|
|
|
foreach (var item in children)
|
|
|
|
|
{
|
|
|
|
|
var node = new TreeViewItem { Tag = item };
|
|
|
|
|
var subFolder = item as Folder;
|
|
|
|
|
if (subFolder != null)
|
|
|
|
|
{
|
2013-06-18 19:16:27 +00:00
|
|
|
|
var prefs = _displayPreferencesManager.GetDisplayPreferences(subFolder.GetDisplayPreferencesId(user.Id));
|
2013-07-05 13:47:10 +00:00
|
|
|
|
|
|
|
|
|
AddChildren(node, OrderBy(subFolder.GetChildren(user, true), user, prefs.SortBy), user);
|
2013-02-21 01:33:05 +00:00
|
|
|
|
node.Header = item.Name + " (" + node.Items.Count + ")";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
node.Header = item.Name;
|
|
|
|
|
}
|
|
|
|
|
parent.Items.Add(node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// TVWs the library_ selected item changed.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender">The sender.</param>
|
|
|
|
|
/// <param name="e">The e.</param>
|
|
|
|
|
private async void tvwLibrary_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
|
|
|
|
{
|
|
|
|
|
if (tvwLibrary.SelectedItem != null)
|
|
|
|
|
{
|
|
|
|
|
var item = (BaseItem)(tvwLibrary.SelectedItem as TreeViewItem).Tag;
|
|
|
|
|
lblObjType.Content = "Type: " + item.GetType().Name;
|
2013-05-08 20:58:52 +00:00
|
|
|
|
|
2013-02-21 01:33:05 +00:00
|
|
|
|
var movie = item as Movie;
|
2013-05-08 20:58:52 +00:00
|
|
|
|
|
2013-02-21 01:33:05 +00:00
|
|
|
|
var folder = item as Folder;
|
|
|
|
|
if (folder != null)
|
|
|
|
|
{
|
|
|
|
|
lblIndexBy.Visibility = ddlIndexBy.Visibility = ddlSortBy.Visibility = lblSortBy.Visibility = Visibility.Visible;
|
|
|
|
|
ddlIndexBy.ItemsSource = folder.IndexByOptionStrings;
|
2013-03-10 04:22:36 +00:00
|
|
|
|
|
|
|
|
|
ddlSortBy.ItemsSource = new []
|
|
|
|
|
{
|
|
|
|
|
ItemSortBy.SortName,
|
|
|
|
|
ItemSortBy.Album,
|
|
|
|
|
ItemSortBy.AlbumArtist,
|
|
|
|
|
ItemSortBy.Artist,
|
|
|
|
|
ItemSortBy.CommunityRating,
|
|
|
|
|
ItemSortBy.DateCreated,
|
|
|
|
|
ItemSortBy.DatePlayed,
|
|
|
|
|
ItemSortBy.PremiereDate,
|
|
|
|
|
ItemSortBy.ProductionYear,
|
|
|
|
|
ItemSortBy.Random,
|
|
|
|
|
ItemSortBy.Runtime
|
|
|
|
|
};
|
|
|
|
|
|
2013-06-18 19:16:27 +00:00
|
|
|
|
var prefs = _displayPreferencesManager.GetDisplayPreferences(folder.GetDisplayPreferencesId((ddlProfile.SelectedItem as User).Id));
|
2013-04-05 19:02:48 +00:00
|
|
|
|
|
2013-02-21 01:33:05 +00:00
|
|
|
|
ddlIndexBy.SelectedItem = prefs != null
|
|
|
|
|
? prefs.IndexBy ?? LocalizedStrings.Instance.GetString("NoneDispPref")
|
|
|
|
|
: LocalizedStrings.Instance.GetString("NoneDispPref");
|
|
|
|
|
ddlSortBy.SelectedItem = prefs != null
|
2013-03-10 04:22:36 +00:00
|
|
|
|
? prefs.SortBy ?? ItemSortBy.SortName
|
|
|
|
|
: ItemSortBy.SortName;
|
2013-02-21 01:33:05 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
lblIndexBy.Visibility = ddlIndexBy.Visibility = ddlSortBy.Visibility = lblSortBy.Visibility = Visibility.Hidden;
|
|
|
|
|
|
|
|
|
|
}
|
2013-05-08 20:58:52 +00:00
|
|
|
|
txtData.Text = FormatJson(_jsonSerializer.SerializeToString(item));
|
2013-02-21 01:33:05 +00:00
|
|
|
|
|
|
|
|
|
var previews = new List<PreviewItem>();
|
|
|
|
|
await Task.Run(() =>
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrEmpty(item.PrimaryImagePath))
|
|
|
|
|
{
|
|
|
|
|
previews.Add(new PreviewItem(item.PrimaryImagePath, "Primary"));
|
|
|
|
|
}
|
|
|
|
|
if (item.HasImage(ImageType.Banner))
|
|
|
|
|
{
|
|
|
|
|
previews.Add(new PreviewItem(item.GetImage(ImageType.Banner), "Banner"));
|
|
|
|
|
}
|
|
|
|
|
if (item.HasImage(ImageType.Logo))
|
|
|
|
|
{
|
|
|
|
|
previews.Add(new PreviewItem(item.GetImage(ImageType.Logo), "Logo"));
|
|
|
|
|
}
|
|
|
|
|
if (item.HasImage(ImageType.Art))
|
|
|
|
|
{
|
|
|
|
|
previews.Add(new PreviewItem(item.GetImage(ImageType.Art), "Art"));
|
|
|
|
|
}
|
|
|
|
|
if (item.HasImage(ImageType.Thumb))
|
|
|
|
|
{
|
|
|
|
|
previews.Add(new PreviewItem(item.GetImage(ImageType.Thumb), "Thumb"));
|
|
|
|
|
}
|
|
|
|
|
if (item.BackdropImagePaths != null)
|
|
|
|
|
previews.AddRange(
|
|
|
|
|
item.BackdropImagePaths.Select(
|
|
|
|
|
image => new PreviewItem(image, "Backdrop")));
|
|
|
|
|
});
|
|
|
|
|
lstPreviews.ItemsSource = previews;
|
|
|
|
|
lstPreviews.Items.Refresh();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The INDEN t_ STRING
|
|
|
|
|
/// </summary>
|
|
|
|
|
private const string INDENT_STRING = " ";
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Formats the json.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="str">The STR.</param>
|
|
|
|
|
/// <returns>System.String.</returns>
|
|
|
|
|
private static string FormatJson(string str)
|
|
|
|
|
{
|
|
|
|
|
var indent = 0;
|
|
|
|
|
var quoted = false;
|
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
|
for (var i = 0; i < str.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
var ch = str[i];
|
|
|
|
|
switch (ch)
|
|
|
|
|
{
|
|
|
|
|
case '{':
|
|
|
|
|
case '[':
|
|
|
|
|
sb.Append(ch);
|
|
|
|
|
if (!quoted)
|
|
|
|
|
{
|
|
|
|
|
sb.AppendLine();
|
|
|
|
|
Enumerable.Range(0, ++indent).ForEach(item => sb.Append(INDENT_STRING));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '}':
|
|
|
|
|
case ']':
|
|
|
|
|
if (!quoted)
|
|
|
|
|
{
|
|
|
|
|
sb.AppendLine();
|
|
|
|
|
Enumerable.Range(0, --indent).ForEach(item => sb.Append(INDENT_STRING));
|
|
|
|
|
}
|
|
|
|
|
sb.Append(ch);
|
|
|
|
|
break;
|
|
|
|
|
case '"':
|
|
|
|
|
sb.Append(ch);
|
|
|
|
|
bool escaped = false;
|
|
|
|
|
var index = i;
|
|
|
|
|
while (index > 0 && str[--index] == '\\')
|
|
|
|
|
escaped = !escaped;
|
|
|
|
|
if (!escaped)
|
|
|
|
|
quoted = !quoted;
|
|
|
|
|
break;
|
|
|
|
|
case ',':
|
|
|
|
|
sb.Append(ch);
|
|
|
|
|
if (!quoted)
|
|
|
|
|
{
|
|
|
|
|
sb.AppendLine();
|
|
|
|
|
Enumerable.Range(0, indent).ForEach(item => sb.Append(INDENT_STRING));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case ':':
|
|
|
|
|
sb.Append(ch);
|
|
|
|
|
if (!quoted)
|
|
|
|
|
sb.Append(" ");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
sb.Append(ch);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return sb.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Handles the SelectionChanged event of the ddlProfile control.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender">The source of the event.</param>
|
|
|
|
|
/// <param name="e">The <see cref="SelectionChangedEventArgs" /> instance containing the event data.</param>
|
|
|
|
|
private void ddlProfile_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
CurrentUser = ddlProfile.SelectedItem as User;
|
|
|
|
|
if (CurrentUser != null)
|
|
|
|
|
LoadTree().ConfigureAwait(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Handles the Click event of the btnRefresh control.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender">The source of the event.</param>
|
|
|
|
|
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
|
|
|
|
|
private void btnRefresh_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (tvwLibrary.SelectedItem != null)
|
|
|
|
|
{
|
|
|
|
|
var item = ((TreeViewItem)tvwLibrary.SelectedItem).Tag as BaseItem;
|
|
|
|
|
if (item != null)
|
|
|
|
|
{
|
|
|
|
|
item.RefreshMetadata(CancellationToken.None, forceRefresh: cbxForce.IsChecked.Value);
|
|
|
|
|
tvwLibrary_SelectedItemChanged(this, null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Handles the SelectionChanged event of the ddlIndexBy control.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender">The source of the event.</param>
|
|
|
|
|
/// <param name="e">The <see cref="SelectionChangedEventArgs" /> instance containing the event data.</param>
|
|
|
|
|
private async void ddlIndexBy_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (ddlIndexBy.SelectedItem != null)
|
|
|
|
|
{
|
|
|
|
|
var treeItem = tvwLibrary.SelectedItem as TreeViewItem;
|
|
|
|
|
var folder = treeItem != null
|
|
|
|
|
? treeItem.Tag as Folder
|
|
|
|
|
: null;
|
2013-06-18 19:16:27 +00:00
|
|
|
|
var prefs = folder != null ? _displayPreferencesManager.GetDisplayPreferences(folder.GetDisplayPreferencesId(CurrentUser.Id)) : new DisplayPreferences { SortBy = ItemSortBy.SortName };
|
2013-02-21 01:33:05 +00:00
|
|
|
|
if (folder != null && prefs.IndexBy != ddlIndexBy.SelectedItem as string)
|
|
|
|
|
{
|
|
|
|
|
//grab UI context so we can update within the below task
|
|
|
|
|
var ui = TaskScheduler.FromCurrentSynchronizationContext();
|
|
|
|
|
Cursor = Cursors.Wait;
|
|
|
|
|
await Task.Factory.StartNew(() =>
|
|
|
|
|
{
|
|
|
|
|
using (
|
|
|
|
|
new Profiler("Explorer full index expansion for " +
|
2013-02-21 20:26:35 +00:00
|
|
|
|
folder.Name, _logger))
|
2013-02-21 01:33:05 +00:00
|
|
|
|
{
|
|
|
|
|
//re-build the current item's children as an index
|
|
|
|
|
prefs.IndexBy = ddlIndexBy.SelectedItem as string;
|
|
|
|
|
treeItem.Items.Clear();
|
2013-07-05 13:47:10 +00:00
|
|
|
|
AddChildren(treeItem, OrderBy(folder.GetChildren(CurrentUser, true, prefs.IndexBy), CurrentUser, prefs.SortBy), CurrentUser);
|
2013-02-21 01:33:05 +00:00
|
|
|
|
treeItem.Header = folder.Name + "(" +
|
|
|
|
|
treeItem.Items.Count + ")";
|
|
|
|
|
Cursor = Cursors.Arrow;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}, CancellationToken.None, TaskCreationOptions.None,
|
|
|
|
|
ui);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Handles the SelectionChanged event of the ddlSortBy control.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sender">The source of the event.</param>
|
|
|
|
|
/// <param name="e">The <see cref="SelectionChangedEventArgs" /> instance containing the event data.</param>
|
|
|
|
|
private async void ddlSortBy_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (ddlSortBy.SelectedItem != null)
|
|
|
|
|
{
|
|
|
|
|
var treeItem = tvwLibrary.SelectedItem as TreeViewItem;
|
|
|
|
|
var folder = treeItem != null
|
|
|
|
|
? treeItem.Tag as Folder
|
|
|
|
|
: null;
|
2013-06-18 19:16:27 +00:00
|
|
|
|
var prefs = folder != null ? _displayPreferencesManager.GetDisplayPreferences(folder.GetDisplayPreferencesId(CurrentUser.Id)) : new DisplayPreferences();
|
2013-02-21 01:33:05 +00:00
|
|
|
|
if (folder != null && prefs.SortBy != ddlSortBy.SelectedItem as string)
|
|
|
|
|
{
|
|
|
|
|
//grab UI context so we can update within the below task
|
|
|
|
|
var ui = TaskScheduler.FromCurrentSynchronizationContext();
|
|
|
|
|
Cursor = Cursors.Wait;
|
|
|
|
|
await Task.Factory.StartNew(() =>
|
|
|
|
|
{
|
|
|
|
|
using (
|
|
|
|
|
new Profiler("Explorer sorting by " + ddlSortBy.SelectedItem + " for " +
|
2013-02-21 20:26:35 +00:00
|
|
|
|
folder.Name, _logger))
|
2013-02-21 01:33:05 +00:00
|
|
|
|
{
|
|
|
|
|
//re-sort
|
|
|
|
|
prefs.SortBy = ddlSortBy.SelectedItem as string;
|
|
|
|
|
treeItem.Items.Clear();
|
2013-07-05 13:47:10 +00:00
|
|
|
|
AddChildren(treeItem, OrderBy(folder.GetChildren(CurrentUser, true, prefs.IndexBy), CurrentUser, prefs.SortBy ?? ItemSortBy.SortName), CurrentUser);
|
2013-02-21 01:33:05 +00:00
|
|
|
|
treeItem.Header = folder.Name + "(" +
|
|
|
|
|
treeItem.Items.Count + ")";
|
|
|
|
|
Cursor = Cursors.Arrow;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}, CancellationToken.None, TaskCreationOptions.None,
|
|
|
|
|
ui);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Class PreviewItem
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class PreviewItem
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The preview
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly string preview;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The name
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly string name;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the preview.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The preview.</value>
|
|
|
|
|
public string Preview
|
|
|
|
|
{
|
|
|
|
|
get { return preview; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the name.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The name.</value>
|
|
|
|
|
public string Name
|
|
|
|
|
{
|
|
|
|
|
get { return name; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initializes a new instance of the <see cref="PreviewItem" /> class.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="p">The p.</param>
|
|
|
|
|
/// <param name="n">The n.</param>
|
|
|
|
|
public PreviewItem(string p, string n)
|
|
|
|
|
{
|
|
|
|
|
preview = p;
|
|
|
|
|
name = n;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Class Extensions
|
|
|
|
|
/// </summary>
|
|
|
|
|
static class Extensions
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Fors the each.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <typeparam name="T"></typeparam>
|
|
|
|
|
/// <param name="ie">The ie.</param>
|
|
|
|
|
/// <param name="action">The action.</param>
|
|
|
|
|
public static void ForEach<T>(this IEnumerable<T> ie, Action<T> action)
|
|
|
|
|
{
|
|
|
|
|
foreach (var i in ie)
|
|
|
|
|
{
|
|
|
|
|
action(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#region ItemToImageConverter
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Class ItemToImageConverter
|
|
|
|
|
/// </summary>
|
|
|
|
|
[ValueConversion(typeof(string), typeof(bool))]
|
|
|
|
|
public class ItemToImageConverter : IValueConverter
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// The instance
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static ItemToImageConverter Instance =
|
|
|
|
|
new ItemToImageConverter();
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Converts a value.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="value">The value produced by the binding source.</param>
|
|
|
|
|
/// <param name="targetType">The type of the binding target property.</param>
|
|
|
|
|
/// <param name="parameter">The converter parameter to use.</param>
|
|
|
|
|
/// <param name="culture">The culture to use in the converter.</param>
|
|
|
|
|
/// <returns>A converted value. If the method returns null, the valid null value is used.</returns>
|
|
|
|
|
public object Convert(object value, Type targetType,
|
|
|
|
|
object parameter, CultureInfo culture)
|
|
|
|
|
{
|
|
|
|
|
var item = value as BaseItem ?? new Folder();
|
|
|
|
|
switch (item.DisplayMediaType)
|
|
|
|
|
{
|
|
|
|
|
case "DVD":
|
|
|
|
|
case "HD DVD":
|
|
|
|
|
case "Blu-ray":
|
|
|
|
|
case "Blu-Ray":
|
|
|
|
|
case "Movie":
|
|
|
|
|
{
|
|
|
|
|
var uri = new Uri
|
|
|
|
|
("pack://application:,,,/Resources/Images/movie.png");
|
|
|
|
|
var source = new BitmapImage(uri);
|
|
|
|
|
return source;
|
|
|
|
|
}
|
|
|
|
|
case "Series":
|
|
|
|
|
{
|
|
|
|
|
var uri = new Uri
|
|
|
|
|
("pack://application:,,,/Resources/Images/series.png");
|
|
|
|
|
var source = new BitmapImage(uri);
|
|
|
|
|
return source;
|
|
|
|
|
}
|
|
|
|
|
case "Season":
|
|
|
|
|
{
|
|
|
|
|
var uri = new Uri
|
|
|
|
|
("pack://application:,,,/Resources/Images/season.png");
|
|
|
|
|
var source = new BitmapImage(uri);
|
|
|
|
|
return source;
|
|
|
|
|
}
|
|
|
|
|
case "Episode":
|
|
|
|
|
{
|
|
|
|
|
var uri = new Uri
|
|
|
|
|
("pack://application:,,,/Resources/Images/episode.png");
|
|
|
|
|
var source = new BitmapImage(uri);
|
|
|
|
|
return source;
|
|
|
|
|
}
|
|
|
|
|
case "BoxSet":
|
|
|
|
|
{
|
|
|
|
|
var uri = new Uri
|
|
|
|
|
("pack://application:,,,/Resources/Images/boxset.png");
|
|
|
|
|
var source = new BitmapImage(uri);
|
|
|
|
|
return source;
|
|
|
|
|
}
|
|
|
|
|
case "Audio":
|
|
|
|
|
{
|
|
|
|
|
var uri = new Uri
|
|
|
|
|
("pack://application:,,,/Resources/Images/audio.png");
|
|
|
|
|
var source = new BitmapImage(uri);
|
|
|
|
|
return source;
|
|
|
|
|
}
|
|
|
|
|
case "Person":
|
|
|
|
|
{
|
|
|
|
|
var uri = new Uri
|
|
|
|
|
("pack://application:,,,/Resources/Images/persons.png");
|
|
|
|
|
var source = new BitmapImage(uri);
|
|
|
|
|
return source;
|
|
|
|
|
}
|
|
|
|
|
case "MusicArtist":
|
|
|
|
|
{
|
|
|
|
|
var uri = new Uri
|
|
|
|
|
("pack://application:,,,/Resources/Images/artist.png");
|
|
|
|
|
var source = new BitmapImage(uri);
|
|
|
|
|
return source;
|
|
|
|
|
}
|
|
|
|
|
case "MusicAlbum":
|
|
|
|
|
{
|
|
|
|
|
var uri = new Uri
|
|
|
|
|
("pack://application:,,,/Resources/Images/album.png");
|
|
|
|
|
var source = new BitmapImage(uri);
|
|
|
|
|
return source;
|
|
|
|
|
}
|
|
|
|
|
case "Trailer":
|
|
|
|
|
{
|
|
|
|
|
var uri = new Uri
|
|
|
|
|
("pack://application:,,,/Resources/Images/trailer.png");
|
|
|
|
|
var source = new BitmapImage(uri);
|
|
|
|
|
return source;
|
|
|
|
|
}
|
|
|
|
|
case "None":
|
|
|
|
|
{
|
|
|
|
|
Uri uri;
|
|
|
|
|
if (item is Movie)
|
|
|
|
|
uri = new Uri("pack://application:,,,/Resources/Images/movie.png");
|
|
|
|
|
else if (item is Series)
|
|
|
|
|
uri = new Uri("pack://application:,,,/Resources/Images/series.png");
|
|
|
|
|
else if (item is BoxSet)
|
|
|
|
|
uri = new Uri("pack://application:,,,/Resources/Images/boxset.png");
|
|
|
|
|
else
|
|
|
|
|
uri = new Uri("pack://application:,,,/Resources/Images/folder.png");
|
|
|
|
|
|
|
|
|
|
return new BitmapImage(uri);
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
var uri = new Uri("pack://application:,,,/Resources/Images/folder.png");
|
|
|
|
|
var source = new BitmapImage(uri);
|
|
|
|
|
return source;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Converts a value.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="value">The value that is produced by the binding target.</param>
|
|
|
|
|
/// <param name="targetType">The type to convert to.</param>
|
|
|
|
|
/// <param name="parameter">The converter parameter to use.</param>
|
|
|
|
|
/// <param name="culture">The culture to use in the converter.</param>
|
|
|
|
|
/// <returns>A converted value. If the method returns null, the valid null value is used.</returns>
|
|
|
|
|
/// <exception cref="System.NotSupportedException">Cannot convert back</exception>
|
|
|
|
|
public object ConvertBack(object value, Type targetType,
|
|
|
|
|
object parameter, CultureInfo culture)
|
|
|
|
|
{
|
|
|
|
|
throw new NotSupportedException("Cannot convert back");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion // ItemToImageConverter
|
|
|
|
|
}
|