Added support for linked children

pull/702/head
Luke Pulverenti 11 years ago
parent f98b611deb
commit a19bfc8f07

@ -73,7 +73,7 @@ namespace MediaBrowser.Api.UserLibrary
if (request.UserId.HasValue) if (request.UserId.HasValue)
{ {
items = request.Recursive ? folder.GetRecursiveChildren(user) : folder.GetChildren(user); items = request.Recursive ? folder.GetRecursiveChildren(user) : folder.GetChildren(user, true);
} }
else else
{ {

@ -305,7 +305,7 @@ namespace MediaBrowser.Api.UserLibrary
return ((Folder)item).GetRecursiveChildren(user); return ((Folder)item).GetRecursiveChildren(user);
} }
return ((Folder)item).GetChildren(user, request.IndexBy); return ((Folder)item).GetChildren(user, true, request.IndexBy);
} }
/// <summary> /// <summary>
@ -433,7 +433,7 @@ namespace MediaBrowser.Api.UserLibrary
{ {
var item = DtoBuilder.GetItemByClientId(request.AdjacentTo, _userManager, _libraryManager); var item = DtoBuilder.GetItemByClientId(request.AdjacentTo, _userManager, _libraryManager);
var allSiblings = item.Parent.GetChildren(user).OrderBy(i => i.SortName).ToList(); var allSiblings = item.Parent.GetChildren(user, true).OrderBy(i => i.SortName).ToList();
var index = allSiblings.IndexOf(item); var index = allSiblings.IndexOf(item);

@ -127,7 +127,7 @@ namespace MediaBrowser.Controller.Dto
var folder = (Folder)item; var folder = (Folder)item;
// Skip sorting since all we want is a count // Skip sorting since all we want is a count
dto.ChildCount = folder.GetChildren(user).Count(); dto.ChildCount = folder.GetChildren(user, true).Count();
SetSpecialCounts(folder, user, dto, _userDataRepository); SetSpecialCounts(folder, user, dto, _userDataRepository);
} }
@ -555,7 +555,7 @@ namespace MediaBrowser.Controller.Dto
double totalPercentPlayed = 0; double totalPercentPlayed = 0;
// Loop through each recursive child // Loop through each recursive child
foreach (var child in folder.GetRecursiveChildren(user).Where(i => !i.IsFolder).ToList()) foreach (var child in folder.GetRecursiveChildren(user, true).Where(i => !i.IsFolder).ToList())
{ {
var userdata = userDataRepository.GetUserData(user.Id, child.GetUserDataKey()); var userdata = userDataRepository.GetUserData(user.Id, child.GetUserDataKey());
@ -610,11 +610,6 @@ namespace MediaBrowser.Controller.Dto
/// <returns>Task.</returns> /// <returns>Task.</returns>
private async Task AttachPeople(BaseItemDto dto, BaseItem item) private async Task AttachPeople(BaseItemDto dto, BaseItem item)
{ {
if (item.People == null)
{
return;
}
// Ordering by person type to ensure actors and artists are at the front. // Ordering by person type to ensure actors and artists are at the front.
// This is taking advantage of the fact that they both begin with A // This is taking advantage of the fact that they both begin with A
// This should be improved in the future // This should be improved in the future
@ -640,7 +635,7 @@ namespace MediaBrowser.Controller.Dto
)).ConfigureAwait(false); )).ConfigureAwait(false);
var dictionary = entities.ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); var dictionary = entities.Where(i => i != null).ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
for (var i = 0; i < people.Count; i++) for (var i = 0; i < people.Count; i++)
{ {
@ -698,7 +693,7 @@ namespace MediaBrowser.Controller.Dto
)).ConfigureAwait(false); )).ConfigureAwait(false);
var dictionary = entities.ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); var dictionary = entities.Where(i => i != null).ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
for (var i = 0; i < studios.Count; i++) for (var i = 0; i < studios.Count; i++)
{ {
@ -967,7 +962,7 @@ namespace MediaBrowser.Controller.Dto
values.RemoveRange(0, 2); values.RemoveRange(0, 2);
// Get the IndexFolder // Get the IndexFolder
var indexFolder = parentFolder.GetChildren(user, indexBy).FirstOrDefault(i => i.Id == indexFolderId) as Folder; var indexFolder = parentFolder.GetChildren(user, false, indexBy).FirstOrDefault(i => i.Id == indexFolderId) as Folder;
// Nested index folder // Nested index folder
if (values.Count > 0) if (values.Count > 0)

@ -617,6 +617,11 @@ namespace MediaBrowser.Controller.Entities
try try
{ {
resolveArgs = ResolveArgs; resolveArgs = ResolveArgs;
if (!resolveArgs.IsDirectory)
{
return new List<Trailer>();
}
} }
catch (IOException ex) catch (IOException ex)
{ {
@ -624,11 +629,6 @@ namespace MediaBrowser.Controller.Entities
return new List<Trailer>(); return new List<Trailer>();
} }
if (!resolveArgs.IsDirectory)
{
return new List<Trailer>();
}
var files = new List<FileSystemInfo>(); var files = new List<FileSystemInfo>();
var folder = resolveArgs.GetFileSystemEntryByName(TrailerFolderName); var folder = resolveArgs.GetFileSystemEntryByName(TrailerFolderName);
@ -687,6 +687,11 @@ namespace MediaBrowser.Controller.Entities
try try
{ {
resolveArgs = ResolveArgs; resolveArgs = ResolveArgs;
if (!resolveArgs.IsDirectory)
{
return new List<Audio.Audio>();
}
} }
catch (IOException ex) catch (IOException ex)
{ {
@ -694,11 +699,6 @@ namespace MediaBrowser.Controller.Entities
return new List<Audio.Audio>(); return new List<Audio.Audio>();
} }
if (!resolveArgs.IsDirectory)
{
return new List<Audio.Audio>();
}
var files = new List<FileSystemInfo>(); var files = new List<FileSystemInfo>();
var folder = resolveArgs.GetFileSystemEntryByName(ThemeSongsFolderName); var folder = resolveArgs.GetFileSystemEntryByName(ThemeSongsFolderName);
@ -747,6 +747,11 @@ namespace MediaBrowser.Controller.Entities
try try
{ {
resolveArgs = ResolveArgs; resolveArgs = ResolveArgs;
if (!resolveArgs.IsDirectory)
{
return new List<Video>();
}
} }
catch (IOException ex) catch (IOException ex)
{ {
@ -754,11 +759,6 @@ namespace MediaBrowser.Controller.Entities
return new List<Video>(); return new List<Video>();
} }
if (!resolveArgs.IsDirectory)
{
return new List<Video>();
}
var folder = resolveArgs.GetFileSystemEntryByName(ThemeVideosFolderName); var folder = resolveArgs.GetFileSystemEntryByName(ThemeVideosFolderName);
// Path doesn't exist. No biggie // Path doesn't exist. No biggie

@ -1,5 +1,6 @@
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Progress; using MediaBrowser.Common.Progress;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
@ -21,6 +22,11 @@ namespace MediaBrowser.Controller.Entities
/// </summary> /// </summary>
public class Folder : BaseItem public class Folder : BaseItem
{ {
public Folder()
{
LinkedChildren = new List<LinkedChild>();
}
/// <summary> /// <summary>
/// Gets a value indicating whether this instance is folder. /// Gets a value indicating whether this instance is folder.
/// </summary> /// </summary>
@ -83,6 +89,13 @@ namespace MediaBrowser.Controller.Entities
return (userId + DisplayPreferencesId.ToString()).GetMD5(); return (userId + DisplayPreferencesId.ToString()).GetMD5();
} }
public List<LinkedChild> LinkedChildren { get; set; }
protected virtual bool SupportsLinkedChildren
{
get { return false; }
}
/// <summary> /// <summary>
/// Adds the child. /// Adds the child.
/// </summary> /// </summary>
@ -878,10 +891,11 @@ namespace MediaBrowser.Controller.Entities
/// Gets allowed children of an item /// Gets allowed children of an item
/// </summary> /// </summary>
/// <param name="user">The user.</param> /// <param name="user">The user.</param>
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
/// <param name="indexBy">The index by.</param> /// <param name="indexBy">The index by.</param>
/// <returns>IEnumerable{BaseItem}.</returns> /// <returns>IEnumerable{BaseItem}.</returns>
/// <exception cref="System.ArgumentNullException"></exception> /// <exception cref="System.ArgumentNullException"></exception>
public virtual IEnumerable<BaseItem> GetChildren(User user, string indexBy = null) public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren, string indexBy = null)
{ {
if (user == null) if (user == null)
{ {
@ -889,7 +903,7 @@ namespace MediaBrowser.Controller.Entities
} }
//the true root should return our users root folder children //the true root should return our users root folder children
if (IsPhysicalRoot) return user.RootFolder.GetChildren(user, indexBy); if (IsPhysicalRoot) return user.RootFolder.GetChildren(user, includeLinkedChildren, indexBy);
IEnumerable<BaseItem> result = null; IEnumerable<BaseItem> result = null;
@ -898,24 +912,37 @@ namespace MediaBrowser.Controller.Entities
result = GetIndexedChildren(user, indexBy); result = GetIndexedChildren(user, indexBy);
} }
if (result != null)
{
return result;
}
var children = Children;
if (includeLinkedChildren)
{
children = children.Concat(GetLinkedChildren());
}
// If indexed is false or the indexing function is null // If indexed is false or the indexing function is null
return result ?? (Children.Where(c => c.IsVisible(user))); return children.Where(c => c.IsVisible(user));
} }
/// <summary> /// <summary>
/// Gets allowed recursive children of an item /// Gets allowed recursive children of an item
/// </summary> /// </summary>
/// <param name="user">The user.</param> /// <param name="user">The user.</param>
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
/// <returns>IEnumerable{BaseItem}.</returns> /// <returns>IEnumerable{BaseItem}.</returns>
/// <exception cref="System.ArgumentNullException"></exception> /// <exception cref="System.ArgumentNullException"></exception>
public IEnumerable<BaseItem> GetRecursiveChildren(User user) public IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = false)
{ {
if (user == null) if (user == null)
{ {
throw new ArgumentNullException(); throw new ArgumentNullException();
} }
foreach (var item in GetChildren(user)) foreach (var item in GetChildren(user, includeLinkedChildren))
{ {
yield return item; yield return item;
@ -923,7 +950,7 @@ namespace MediaBrowser.Controller.Entities
if (subFolder != null) if (subFolder != null)
{ {
foreach (var subitem in subFolder.GetRecursiveChildren(user)) foreach (var subitem in subFolder.GetRecursiveChildren(user, includeLinkedChildren))
{ {
yield return subitem; yield return subitem;
} }
@ -931,6 +958,81 @@ namespace MediaBrowser.Controller.Entities
} }
} }
/// <summary>
/// Gets the linked children.
/// </summary>
/// <returns>IEnumerable{BaseItem}.</returns>
public IEnumerable<BaseItem> GetLinkedChildren()
{
return LinkedChildren
.Select(i => LibraryManager.RootFolder.FindByPath(i.Path))
.Where(i => i != null);
}
public override async Task<bool> RefreshMetadata(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true, bool resetResolveArgs = true)
{
var changed = await base.RefreshMetadata(cancellationToken, forceSave, forceRefresh, allowSlowProviders, resetResolveArgs).ConfigureAwait(false);
return changed || (SupportsLinkedChildren && RefreshLinkedChildren());
}
/// <summary>
/// Refreshes the linked children.
/// </summary>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
private bool RefreshLinkedChildren()
{
ItemResolveArgs resolveArgs;
try
{
resolveArgs = ResolveArgs;
if (!resolveArgs.IsDirectory)
{
return false;
}
}
catch (IOException ex)
{
Logger.ErrorException("Error getting ResolveArgs for {0}", ex, Path);
return false;
}
var currentManualLinks = LinkedChildren.Where(i => i.Type == LinkedChildType.Manual).ToList();
var currentShortcutLinks = LinkedChildren.Where(i => i.Type == LinkedChildType.Shortcut).ToList();
var newShortcutLinks = resolveArgs.FileSystemChildren
.Where(i => (i.Attributes & FileAttributes.Directory) != FileAttributes.Directory && FileSystem.IsShortcut(i.FullName))
.Select(i =>
{
try
{
return new LinkedChild
{
Path = FileSystem.ResolveShortcut(i.FullName),
Type = LinkedChildType.Shortcut
};
}
catch (IOException ex)
{
Logger.ErrorException("Error resolving shortcut {0}", ex, i.FullName);
return null;
}
})
.Where(i => i != null)
.ToList();
if (!newShortcutLinks.SequenceEqual(currentShortcutLinks))
{
newShortcutLinks.AddRange(currentManualLinks);
LinkedChildren = newShortcutLinks;
return true;
}
return false;
}
/// <summary> /// <summary>
/// Folders need to validate and refresh /// Folders need to validate and refresh
/// </summary> /// </summary>
@ -954,7 +1056,7 @@ namespace MediaBrowser.Controller.Entities
public override async Task SetPlayedStatus(User user, bool wasPlayed, IUserDataRepository userManager) public override async Task SetPlayedStatus(User user, bool wasPlayed, IUserDataRepository userManager)
{ {
// Sweep through recursively and update status // Sweep through recursively and update status
var tasks = GetRecursiveChildren(user).Where(i => !i.IsFolder).Select(c => c.SetPlayedStatus(user, wasPlayed, userManager)); var tasks = GetRecursiveChildren(user, true).Where(i => !i.IsFolder).Select(c => c.SetPlayedStatus(user, wasPlayed, userManager));
await Task.WhenAll(tasks).ConfigureAwait(false); await Task.WhenAll(tasks).ConfigureAwait(false);
} }

@ -0,0 +1,38 @@
using System;
using System.Collections;
namespace MediaBrowser.Controller.Entities
{
public class LinkedChild
{
public string Path { get; set; }
public LinkedChildType Type { get; set; }
}
public enum LinkedChildType
{
Manual = 1,
Shortcut = 2
}
public class LinkedChildComparer : IComparer
{
public int Compare(object x, object y)
{
var a = (LinkedChild)x;
var b = (LinkedChild)y;
if (!string.Equals(a.Path, b.Path, StringComparison.OrdinalIgnoreCase))
{
return string.Compare(a.Path, b.Path, StringComparison.OrdinalIgnoreCase);
}
if (a.Type != b.Type)
{
return a.Type.CompareTo(b.Type);
}
return 0;
}
}
}

@ -6,6 +6,12 @@ namespace MediaBrowser.Controller.Entities.Movies
/// </summary> /// </summary>
public class BoxSet : Folder public class BoxSet : Folder
{ {
protected override bool SupportsLinkedChildren
{
get
{
return true;
}
}
} }
} }

@ -78,6 +78,7 @@
<Compile Include="Entities\GameGenre.cs" /> <Compile Include="Entities\GameGenre.cs" />
<Compile Include="Entities\IByReferenceItem.cs" /> <Compile Include="Entities\IByReferenceItem.cs" />
<Compile Include="Entities\IItemByName.cs" /> <Compile Include="Entities\IItemByName.cs" />
<Compile Include="Entities\LinkedChild.cs" />
<Compile Include="Entities\MusicVideo.cs" /> <Compile Include="Entities\MusicVideo.cs" />
<Compile Include="Library\ILibraryPostScanTask.cs" /> <Compile Include="Library\ILibraryPostScanTask.cs" />
<Compile Include="Library\ILibraryPrescanTask.cs" /> <Compile Include="Library\ILibraryPrescanTask.cs" />

@ -72,6 +72,7 @@ namespace MediaBrowser.Model.Dto
public ImageOptions() public ImageOptions()
{ {
Quality = 100; Quality = 100;
EnableImageEnhancers = true;
} }
} }
} }

@ -229,7 +229,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
{ {
var user = _userManager.GetUserById(userId); var user = _userManager.GetUserById(userId);
var collections = user.RootFolder.GetChildren(user).ToList(); var collections = user.RootFolder.GetChildren(user, true).ToList();
var allRecursiveChildren = user.RootFolder.GetRecursiveChildren(user).ToDictionary(i => i.Id); var allRecursiveChildren = user.RootFolder.GetRecursiveChildren(user).ToDictionary(i => i.Id);

@ -255,7 +255,14 @@ namespace MediaBrowser.ServerApplication
process.Exited += ProcessExited; process.Exited += ProcessExited;
process.Start(); try
{
process.Start();
}
catch (Exception ex)
{
MessageBox.Show("There was an error launching your web browser. Please check your defualt browser settings.");
}
} }
/// <summary> /// <summary>

@ -90,7 +90,7 @@ namespace MediaBrowser.ServerApplication
Cursor = Cursors.Wait; Cursor = Cursors.Wait;
await Task.Run(() => await Task.Run(() =>
{ {
IEnumerable<BaseItem> children = CurrentUser.Name == "Physical" ? _libraryManager.RootFolder.Children : _libraryManager.RootFolder.GetChildren(CurrentUser); IEnumerable<BaseItem> children = CurrentUser.Name == "Physical" ? _libraryManager.RootFolder.Children : _libraryManager.RootFolder.GetChildren(CurrentUser, true);
children = OrderByName(children, CurrentUser); children = OrderByName(children, CurrentUser);
foreach (Folder folder in children) foreach (Folder folder in children)
@ -102,7 +102,7 @@ namespace MediaBrowser.ServerApplication
var prefs = ddlProfile.SelectedItem != null ? _displayPreferencesManager.GetDisplayPreferences(currentFolder.GetDisplayPreferencesId((ddlProfile.SelectedItem as User).Id)) ?? new DisplayPreferences { SortBy = ItemSortBy.SortName } : new DisplayPreferences { SortBy = ItemSortBy.SortName }; var prefs = ddlProfile.SelectedItem != null ? _displayPreferencesManager.GetDisplayPreferences(currentFolder.GetDisplayPreferencesId((ddlProfile.SelectedItem as User).Id)) ?? new DisplayPreferences { SortBy = ItemSortBy.SortName } : new DisplayPreferences { SortBy = ItemSortBy.SortName };
var node = new TreeViewItem { Tag = currentFolder }; var node = new TreeViewItem { Tag = currentFolder };
var subChildren = currentFolder.GetChildren(CurrentUser, prefs.IndexBy); var subChildren = currentFolder.GetChildren(CurrentUser, true, prefs.IndexBy);
subChildren = OrderByName(subChildren, CurrentUser); subChildren = OrderByName(subChildren, CurrentUser);
AddChildren(node, subChildren, CurrentUser); AddChildren(node, subChildren, CurrentUser);
node.Header = currentFolder.Name + " (" + node.Header = currentFolder.Name + " (" +
@ -154,7 +154,7 @@ namespace MediaBrowser.ServerApplication
{ {
var prefs = _displayPreferencesManager.GetDisplayPreferences(subFolder.GetDisplayPreferencesId(user.Id)); var prefs = _displayPreferencesManager.GetDisplayPreferences(subFolder.GetDisplayPreferencesId(user.Id));
AddChildren(node, OrderBy(subFolder.GetChildren(user), user, prefs.SortBy), user); AddChildren(node, OrderBy(subFolder.GetChildren(user, true), user, prefs.SortBy), user);
node.Header = item.Name + " (" + node.Items.Count + ")"; node.Header = item.Name + " (" + node.Items.Count + ")";
} }
else else
@ -374,7 +374,7 @@ namespace MediaBrowser.ServerApplication
//re-build the current item's children as an index //re-build the current item's children as an index
prefs.IndexBy = ddlIndexBy.SelectedItem as string; prefs.IndexBy = ddlIndexBy.SelectedItem as string;
treeItem.Items.Clear(); treeItem.Items.Clear();
AddChildren(treeItem, OrderBy(folder.GetChildren(CurrentUser, prefs.IndexBy), CurrentUser, prefs.SortBy), CurrentUser); AddChildren(treeItem, OrderBy(folder.GetChildren(CurrentUser, true, prefs.IndexBy), CurrentUser, prefs.SortBy), CurrentUser);
treeItem.Header = folder.Name + "(" + treeItem.Header = folder.Name + "(" +
treeItem.Items.Count + ")"; treeItem.Items.Count + ")";
Cursor = Cursors.Arrow; Cursor = Cursors.Arrow;
@ -415,7 +415,7 @@ namespace MediaBrowser.ServerApplication
//re-sort //re-sort
prefs.SortBy = ddlSortBy.SelectedItem as string; prefs.SortBy = ddlSortBy.SelectedItem as string;
treeItem.Items.Clear(); treeItem.Items.Clear();
AddChildren(treeItem, OrderBy(folder.GetChildren(CurrentUser, prefs.IndexBy), CurrentUser, prefs.SortBy ?? ItemSortBy.SortName), CurrentUser); AddChildren(treeItem, OrderBy(folder.GetChildren(CurrentUser, true, prefs.IndexBy), CurrentUser, prefs.SortBy ?? ItemSortBy.SortName), CurrentUser);
treeItem.Header = folder.Name + "(" + treeItem.Header = folder.Name + "(" +
treeItem.Items.Count + ")"; treeItem.Items.Count + ")";
Cursor = Cursors.Arrow; Cursor = Cursors.Arrow;

Loading…
Cancel
Save