Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Leonardo Galli 2017-04-26 15:17:49 +02:00
commit 6f3118c142
34 changed files with 469 additions and 57 deletions

View file

@ -11,6 +11,8 @@ public class MediaManagementConfigResource : RestResource
public bool AutoDownloadPropers { get; set; } public bool AutoDownloadPropers { get; set; }
public bool CreateEmptySeriesFolders { get; set; } public bool CreateEmptySeriesFolders { get; set; }
public FileDateType FileDate { get; set; } public FileDateType FileDate { get; set; }
public bool AutoRenameFolders { get; set; }
public bool PathsDefaultStatic { get; set; }
public bool SetPermissionsLinux { get; set; } public bool SetPermissionsLinux { get; set; }
public string FileChmod { get; set; } public string FileChmod { get; set; }
@ -35,6 +37,8 @@ public static MediaManagementConfigResource ToResource(IConfigService model)
AutoDownloadPropers = model.AutoDownloadPropers, AutoDownloadPropers = model.AutoDownloadPropers,
CreateEmptySeriesFolders = model.CreateEmptySeriesFolders, CreateEmptySeriesFolders = model.CreateEmptySeriesFolders,
FileDate = model.FileDate, FileDate = model.FileDate,
AutoRenameFolders = model.AutoRenameFolders,
PathsDefaultStatic = model.PathsDefaultStatic,
SetPermissionsLinux = model.SetPermissionsLinux, SetPermissionsLinux = model.SetPermissionsLinux,
FileChmod = model.FileChmod, FileChmod = model.FileChmod,

View file

@ -46,11 +46,14 @@ private MovieFileResource GetMovieFile(int id)
return movie.ToResource(); return movie.ToResource();
} }
private void SetQuality(MovieFileResource movieFileResource) private void SetQuality(MovieFileResource movieFileResource)
{ {
var movieFile = _mediaFileService.GetMovie(movieFileResource.Id); var movieFile = _mediaFileService.GetMovie(movieFileResource.Id);
movieFile.Quality = movieFileResource.Quality; movieFile.Quality = movieFileResource.Quality;
_mediaFileService.Update(movieFile); _mediaFileService.Update(movieFile);
BroadcastResourceChange(ModelAction.Updated, movieFile.Id);
} }
private void DeleteMovieFile(int id) private void DeleteMovieFile(int id)

View file

@ -40,6 +40,7 @@ public MovieResource()
//View & Edit //View & Edit
public string Path { get; set; } public string Path { get; set; }
public int ProfileId { get; set; } public int ProfileId { get; set; }
public MoviePathState PathState { get; set; }
//Editing Only //Editing Only
public bool Monitored { get; set; } public bool Monitored { get; set; }
@ -131,6 +132,7 @@ public static MovieResource ToResource(this Core.Tv.Movie model)
Path = model.Path, Path = model.Path,
ProfileId = model.ProfileId, ProfileId = model.ProfileId,
PathState = model.PathState,
Monitored = model.Monitored, Monitored = model.Monitored,
MinimumAvailability = model.MinimumAvailability, MinimumAvailability = model.MinimumAvailability,
@ -187,6 +189,7 @@ public static Core.Tv.Movie ToModel(this MovieResource resource)
Path = resource.Path, Path = resource.Path,
ProfileId = resource.ProfileId, ProfileId = resource.ProfileId,
PathState = resource.PathState,
Monitored = resource.Monitored, Monitored = resource.Monitored,
MinimumAvailability = resource.MinimumAvailability, MinimumAvailability = resource.MinimumAvailability,
@ -217,6 +220,7 @@ public static Core.Tv.Movie ToModel(this MovieResource resource, Core.Tv.Movie m
movie.Path = resource.Path; movie.Path = resource.Path;
movie.ProfileId = resource.ProfileId; movie.ProfileId = resource.ProfileId;
movie.PathState = resource.PathState;
movie.Monitored = resource.Monitored; movie.Monitored = resource.Monitored;
movie.MinimumAvailability = resource.MinimumAvailability; movie.MinimumAvailability = resource.MinimumAvailability;

View file

@ -296,6 +296,7 @@
<Compile Include="OrganizerTests\FileNameBuilderTests\CleanTitleFixture.cs" /> <Compile Include="OrganizerTests\FileNameBuilderTests\CleanTitleFixture.cs" />
<Compile Include="OrganizerTests\FileNameBuilderTests\EpisodeTitleCollapseFixture.cs" /> <Compile Include="OrganizerTests\FileNameBuilderTests\EpisodeTitleCollapseFixture.cs" />
<Compile Include="OrganizerTests\FileNameBuilderTests\MultiEpisodeFixture.cs" /> <Compile Include="OrganizerTests\FileNameBuilderTests\MultiEpisodeFixture.cs" />
<Compile Include="OrganizerTests\GetMovieFolderFixture.cs" />
<Compile Include="ParserTests\MiniSeriesEpisodeParserFixture.cs" /> <Compile Include="ParserTests\MiniSeriesEpisodeParserFixture.cs" />
<Compile Include="ParserTests\RomanNumeralTests\RomanNumeralConversionFixture.cs" /> <Compile Include="ParserTests\RomanNumeralTests\RomanNumeralConversionFixture.cs" />
<Compile Include="Qualities\RevisionComparableFixture.cs" /> <Compile Include="Qualities\RevisionComparableFixture.cs" />

View file

@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using FizzWare.NBuilder; using FizzWare.NBuilder;
@ -734,5 +734,7 @@ public void should_use_existing_casing_for_release_group(string releaseGroup)
Subject.BuildFileName(new List<Episode> { _episode1 }, _series, _episodeFile) Subject.BuildFileName(new List<Episode> { _episode1 }, _series, _episodeFile)
.Should().Be(releaseGroup); .Should().Be(releaseGroup);
} }
} }
} }

View file

@ -0,0 +1,40 @@
using NUnit.Framework;
using NzbDrone.Core.Organizer;
using NzbDrone.Core.Test.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NzbDrone.Core.Tv;
using FluentAssertions;
namespace NzbDrone.Core.Test.OrganizerTests
{
[TestFixture]
public class GetMovieFolderFixture : CoreTest<FileNameBuilder>
{
private NamingConfig namingConfig;
[SetUp]
public void Setup()
{
namingConfig = NamingConfig.Default;
Mocker.GetMock<INamingConfigService>()
.Setup(c => c.GetConfig()).Returns(namingConfig);
}
[TestCase("Arrival", 2016, "{Movie Title} ({Release Year})", "Arrival (2016)")]
[TestCase("The Big Short", 2015, "{Movie TitleThe} ({Release Year})", "Big Short, The (2015)")]
[TestCase("The Big Short", 2015, "{Movie Title} ({Release Year})", "The Big Short (2015)")]
public void should_use_movieFolderFormat_to_build_folder_name(string movieTitle, int year, string format, string expected)
{
namingConfig.MovieFolderFormat = format;
var movie = new Movie { Title = movieTitle, Year = year };
Subject.GetMovieFolder(movie).Should().Be(expected);
}
}
}

View file

@ -294,6 +294,20 @@ public string ExtraFileExtensions
set { SetValue("ExtraFileExtensions", value); } set { SetValue("ExtraFileExtensions", value); }
} }
public bool AutoRenameFolders
{
get { return GetValueBoolean("AutoRenameFolders", false); }
set { SetValue("AutoRenameFolders", value); }
}
public bool PathsDefaultStatic
{
get { return GetValueBoolean("PathsDefaultStatic", true); }
set { SetValue("PathsDefaultStatic", value); }
}
public bool SetPermissionsLinux public bool SetPermissionsLinux
{ {
get { return GetValueBoolean("SetPermissionsLinux", false); } get { return GetValueBoolean("SetPermissionsLinux", false); }

View file

@ -33,6 +33,8 @@ public interface IConfigService
bool CopyUsingHardlinks { get; set; } bool CopyUsingHardlinks { get; set; }
bool EnableMediaInfo { get; set; } bool EnableMediaInfo { get; set; }
string ExtraFileExtensions { get; set; } string ExtraFileExtensions { get; set; }
bool AutoRenameFolders { get; set; }
bool PathsDefaultStatic { get; set; }
//Permissions (Media Management) //Permissions (Media Management)
bool SetPermissionsLinux { get; set; } bool SetPermissionsLinux { get; set; }

View file

@ -0,0 +1,16 @@
using System.Data;
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(136)]
public class add_pathstate_to_movies : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Alter.Table("Movies").AddColumn("PathState").AsInt32().WithDefaultValue(2);
}
}
}

View file

@ -0,0 +1,20 @@
using NzbDrone.Core.Messaging.Commands;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Core.MediaFiles.Commands
{
public class RenameMovieFolderCommand : Command
{
public List<int> MovieIds { get; set; }
public override bool SendUpdatesToClient => true;
public RenameMovieFolderCommand(List<int> ids)
{
MovieIds = ids;
}
}
}

View file

@ -45,6 +45,7 @@ public class DiskScanService :
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private readonly IMovieService _movieService; private readonly IMovieService _movieService;
private readonly IMovieFileRepository _movieFileRepository; private readonly IMovieFileRepository _movieFileRepository;
private readonly IRenameMovieFileService _renameMovieFiles;
private readonly Logger _logger; private readonly Logger _logger;
public DiskScanService(IDiskProvider diskProvider, public DiskScanService(IDiskProvider diskProvider,
@ -57,6 +58,7 @@ public DiskScanService(IDiskProvider diskProvider,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
IMovieService movieService, IMovieService movieService,
IMovieFileRepository movieFileRepository, IMovieFileRepository movieFileRepository,
IRenameMovieFileService renameMovieFiles,
Logger logger) Logger logger)
{ {
_diskProvider = diskProvider; _diskProvider = diskProvider;
@ -69,6 +71,7 @@ public DiskScanService(IDiskProvider diskProvider,
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_movieService = movieService; _movieService = movieService;
_movieFileRepository = movieFileRepository; _movieFileRepository = movieFileRepository;
_renameMovieFiles = renameMovieFiles;
_logger = logger; _logger = logger;
} }
@ -135,6 +138,9 @@ public void Scan(Series series)
public void Scan(Movie movie) public void Scan(Movie movie)
{ {
//Try renaming the movie path in case anything changed such as year, title or something else.
_renameMovieFiles.RenameMoviePath(movie, true);
var rootFolder = _diskProvider.GetParentFolder(movie.Path); var rootFolder = _diskProvider.GetParentFolder(movie.Path);
if (!_diskProvider.FolderExists(rootFolder)) if (!_diskProvider.FolderExists(rootFolder))

View file

@ -0,0 +1,18 @@
using NzbDrone.Common.Messaging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Core.MediaFiles.Events
{
public class MovieFileUpdatedEvent : IEvent
{
public MovieFile MovieFile { get; private set; }
public MovieFileUpdatedEvent(MovieFile movieFile)
{
MovieFile = movieFile;
}
}
}

View file

@ -30,6 +30,7 @@ public class MovieFileMovingService : IMoveMovieFiles
private readonly IDiskTransferService _diskTransferService; private readonly IDiskTransferService _diskTransferService;
private readonly IDiskProvider _diskProvider; private readonly IDiskProvider _diskProvider;
private readonly IMediaFileAttributeService _mediaFileAttributeService; private readonly IMediaFileAttributeService _mediaFileAttributeService;
private readonly IRecycleBinProvider _recycleBinProvider;
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private readonly IConfigService _configService; private readonly IConfigService _configService;
private readonly Logger _logger; private readonly Logger _logger;
@ -40,6 +41,7 @@ public MovieFileMovingService(IMovieService movieService,
IDiskTransferService diskTransferService, IDiskTransferService diskTransferService,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IMediaFileAttributeService mediaFileAttributeService, IMediaFileAttributeService mediaFileAttributeService,
IRecycleBinProvider recycleBinProvider,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
IConfigService configService, IConfigService configService,
Logger logger) Logger logger)
@ -50,6 +52,7 @@ public MovieFileMovingService(IMovieService movieService,
_diskTransferService = diskTransferService; _diskTransferService = diskTransferService;
_diskProvider = diskProvider; _diskProvider = diskProvider;
_mediaFileAttributeService = mediaFileAttributeService; _mediaFileAttributeService = mediaFileAttributeService;
_recycleBinProvider = recycleBinProvider;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_configService = configService; _configService = configService;
_logger = logger; _logger = logger;
@ -116,6 +119,15 @@ private MovieFile TransferFile(MovieFile movieFile, Movie movie, string destinat
_diskTransferService.TransferFile(movieFilePath, destinationFilePath, mode); _diskTransferService.TransferFile(movieFilePath, destinationFilePath, mode);
var oldMoviePath = movie.Path;
var newMoviePath = new OsPath(destinationFilePath).Directory.FullPath.TrimEnd(Path.DirectorySeparatorChar);
movie.Path = newMoviePath;
if (oldMoviePath != newMoviePath)
{
_movieService.UpdateMovie(movie);
}
movieFile.RelativePath = movie.Path.GetRelativePath(destinationFilePath); movieFile.RelativePath = movie.Path.GetRelativePath(destinationFilePath);
_updateMovieFileService.ChangeFileDateForFile(movieFile, movie); _updateMovieFileService.ChangeFileDateForFile(movieFile, movie);
@ -132,6 +144,14 @@ private MovieFile TransferFile(MovieFile movieFile, Movie movie, string destinat
_mediaFileAttributeService.SetFilePermissions(destinationFilePath); _mediaFileAttributeService.SetFilePermissions(destinationFilePath);
if(oldMoviePath != newMoviePath)
{
if (_diskProvider.GetFiles(oldMoviePath, SearchOption.AllDirectories).Count() == 0)
{
_recycleBinProvider.DeleteFolder(oldMoviePath);
}
}
return movieFile; return movieFile;
} }
@ -143,7 +163,9 @@ private void EnsureMovieFolder(MovieFile movieFile, LocalMovie localMovie, strin
private void EnsureMovieFolder(MovieFile movieFile, Movie movie, string filePath) private void EnsureMovieFolder(MovieFile movieFile, Movie movie, string filePath)
{ {
var movieFolder = Path.GetDirectoryName(filePath); var movieFolder = Path.GetDirectoryName(filePath);
movie.Path = movieFolder;
var rootFolder = new OsPath(movieFolder).Directory.FullPath; var rootFolder = new OsPath(movieFolder).Directory.FullPath;
var fileName = Path.GetFileName(filePath);
if (!_diskProvider.FolderExists(rootFolder)) if (!_diskProvider.FolderExists(rootFolder))
{ {
@ -156,7 +178,7 @@ private void EnsureMovieFolder(MovieFile movieFile, Movie movie, string filePath
if (!_diskProvider.FolderExists(movieFolder)) if (!_diskProvider.FolderExists(movieFolder))
{ {
CreateFolder(movieFolder); CreateFolder(movieFolder);
newEvent.SeriesFolder = movieFolder; newEvent.MovieFolder = movieFolder;
changed = true; changed = true;
} }

View file

@ -13,23 +13,29 @@
using NzbDrone.Common.Instrumentation.Extensions; using NzbDrone.Common.Instrumentation.Extensions;
using NzbDrone.Core.Organizer; using NzbDrone.Core.Organizer;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Core.MediaFiles namespace NzbDrone.Core.MediaFiles
{ {
public interface IRenameMovieFileService public interface IRenameMovieFileService
{ {
List<RenameMovieFilePreview> GetRenamePreviews(int movieId); List<RenameMovieFilePreview> GetRenamePreviews(int movieId);
void RenameMoviePath(Movie movie, bool shouldRenameFiles);
} }
public class RenameMovieFileService : IRenameMovieFileService, public class RenameMovieFileService : IRenameMovieFileService,
IExecute<RenameMovieFilesCommand>, IExecute<RenameMovieFilesCommand>,
IExecute<RenameMovieCommand> IExecute<RenameMovieCommand>,
IExecute<RenameMovieFolderCommand>
{ {
private readonly IMovieService _movieService; private readonly IMovieService _movieService;
private readonly IMediaFileService _mediaFileService; private readonly IMediaFileService _mediaFileService;
private readonly IMoveMovieFiles _movieFileMover; private readonly IMoveMovieFiles _movieFileMover;
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private readonly IBuildFileNames _filenameBuilder; private readonly IBuildFileNames _filenameBuilder;
private readonly IConfigService _configService;
private readonly IDiskProvider _diskProvider;
private readonly IRecycleBinProvider _recycleBinProvider;
private readonly Logger _logger; private readonly Logger _logger;
public RenameMovieFileService(IMovieService movieService, public RenameMovieFileService(IMovieService movieService,
@ -37,6 +43,9 @@ public RenameMovieFileService(IMovieService movieService,
IMoveMovieFiles movieFileMover, IMoveMovieFiles movieFileMover,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
IBuildFileNames filenameBuilder, IBuildFileNames filenameBuilder,
IConfigService configService,
IRecycleBinProvider recycleBinProvider,
IDiskProvider diskProvider,
Logger logger) Logger logger)
{ {
_movieService = movieService; _movieService = movieService;
@ -44,6 +53,9 @@ public RenameMovieFileService(IMovieService movieService,
_movieFileMover = movieFileMover; _movieFileMover = movieFileMover;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_filenameBuilder = filenameBuilder; _filenameBuilder = filenameBuilder;
_configService = configService;
_recycleBinProvider = recycleBinProvider;
_diskProvider = diskProvider;
_logger = logger; _logger = logger;
} }
@ -71,8 +83,9 @@ private IEnumerable<RenameMovieFilePreview> GetPreviews(Movie movie, List<MovieF
{ {
MovieId = movie.Id, MovieId = movie.Id,
MovieFileId = file.Id, MovieFileId = file.Id,
ExistingPath = file.RelativePath, ExistingPath = movieFilePath,
NewPath = movie.Path.GetRelativePath(newPath) //NewPath = movie.Path.GetRelativePath(newPath)
NewPath = newPath
}; };
} }
@ -80,13 +93,19 @@ private IEnumerable<RenameMovieFilePreview> GetPreviews(Movie movie, List<MovieF
} }
private void RenameFiles(List<MovieFile> movieFiles, Movie movie) private void RenameFiles(List<MovieFile> movieFiles, Movie movie, string oldMoviePath = null)
{ {
var renamed = new List<MovieFile>(); var renamed = new List<MovieFile>();
foreach(var movieFile in movieFiles) if (oldMoviePath == null)
{ {
var movieFilePath = Path.Combine(movie.Path, movieFile.RelativePath); oldMoviePath = movie.Path;
}
foreach (var movieFile in movieFiles)
{
var oldMovieFilePath = Path.Combine(oldMoviePath, movieFile.RelativePath);
movieFile.Path = oldMovieFilePath;
try try
{ {
@ -94,22 +113,64 @@ private void RenameFiles(List<MovieFile> movieFiles, Movie movie)
_movieFileMover.MoveMovieFile(movieFile, movie); _movieFileMover.MoveMovieFile(movieFile, movie);
_mediaFileService.Update(movieFile); _mediaFileService.Update(movieFile);
_movieService.UpdateMovie(movie);
renamed.Add(movieFile); renamed.Add(movieFile);
_logger.Debug("Renamed movie file: {0}", movieFile); _logger.Debug("Renamed movie file: {0}", movieFile);
} }
catch(SameFilenameException ex) catch (SameFilenameException ex)
{ {
_logger.Debug("File not renamed, source and destination are the same: {0}", ex.Filename); _logger.Debug("File not renamed, source and destination are the same: {0}", ex.Filename);
} }
catch(Exception ex) catch (Exception ex)
{ {
_logger.Error(ex, "Failed to rename file: " + movieFilePath); _logger.Error(ex, "Failed to rename file: " + oldMovieFilePath);
} }
} }
} }
public void RenameMoviePath(Movie movie, bool shouldRenameFiles = true)
{
var newFolder = _filenameBuilder.BuildMoviePath(movie);
if (newFolder != movie.Path && movie.PathState == MoviePathState.Dynamic)
{
if (!_configService.AutoRenameFolders)
{
_logger.Info("{0}'s movie should be {1} according to your naming config.", movie, newFolder);
return;
}
_logger.Info("{0}'s movie folder changed to: {1}", movie, newFolder);
var oldFolder = movie.Path;
movie.Path = newFolder;
if (shouldRenameFiles)
{
var movieFiles = _mediaFileService.GetFilesByMovie(movie.Id);
_logger.ProgressInfo("Renaming movie files for {0}", movie.Title);
RenameFiles(movieFiles, movie, oldFolder);
_logger.ProgressInfo("All movie files renamed for {0}", movie.Title);
}
_movieService.UpdateMovie(movie);
if (_diskProvider.GetFiles(oldFolder, SearchOption.AllDirectories).Count() == 0)
{
_recycleBinProvider.DeleteFolder(oldFolder);
}
}
if (movie.PathState == MoviePathState.StaticOnce)
{
movie.PathState = MoviePathState.Dynamic;
_movieService.UpdateMovie(movie);
}
}
public void Execute(RenameMovieFilesCommand message) public void Execute(RenameMovieFilesCommand message)
{ {
var movie = _movieService.GetMovie(message.MovieId); var movie = _movieService.GetMovie(message.MovieId);
@ -134,5 +195,17 @@ public void Execute(RenameMovieCommand message)
} }
} }
public void Execute(RenameMovieFolderCommand message)
{
_logger.Debug("Renaming movie folder for selected movie if necessary");
var moviesToRename = _movieService.GetMovies(message.MovieIds);
foreach(var movie in moviesToRename)
{
var movieFiles = _mediaFileService.GetFilesByMovie(movie.Id);
_logger.ProgressInfo("Renaming movie folder for {0}", movie.Title);
RenameMoviePath(movie);
}
}
} }
} }

View file

@ -18,6 +18,7 @@ public class UpgradeMediaFileService : IUpgradeMediaFiles
private readonly IMediaFileService _mediaFileService; private readonly IMediaFileService _mediaFileService;
private readonly IMoveEpisodeFiles _episodeFileMover; private readonly IMoveEpisodeFiles _episodeFileMover;
private readonly IMoveMovieFiles _movieFileMover; private readonly IMoveMovieFiles _movieFileMover;
private readonly IRenameMovieFileService _movieFileRenamer;
private readonly IDiskProvider _diskProvider; private readonly IDiskProvider _diskProvider;
private readonly Logger _logger; private readonly Logger _logger;
@ -26,6 +27,7 @@ public UpgradeMediaFileService(IRecycleBinProvider recycleBinProvider,
IMoveEpisodeFiles episodeFileMover, IMoveEpisodeFiles episodeFileMover,
IMoveMovieFiles movieFileMover, IMoveMovieFiles movieFileMover,
IDiskProvider diskProvider, IDiskProvider diskProvider,
IRenameMovieFileService movieFileRenamer,
Logger logger) Logger logger)
{ {
_recycleBinProvider = recycleBinProvider; _recycleBinProvider = recycleBinProvider;
@ -33,6 +35,7 @@ public UpgradeMediaFileService(IRecycleBinProvider recycleBinProvider,
_episodeFileMover = episodeFileMover; _episodeFileMover = episodeFileMover;
_movieFileMover = movieFileMover; _movieFileMover = movieFileMover;
_diskProvider = diskProvider; _diskProvider = diskProvider;
_movieFileRenamer = movieFileRenamer;
_logger = logger; _logger = logger;
} }
@ -57,6 +60,10 @@ public MovieFileMoveResult UpgradeMovieFile(MovieFile movieFile, LocalMovie loca
_mediaFileService.Delete(existingFile, DeleteMediaFileReason.Upgrade); _mediaFileService.Delete(existingFile, DeleteMediaFileReason.Upgrade);
} }
//Temporary for correctly getting path
localMovie.Movie.MovieFileId = 1;
localMovie.Movie.MovieFile = movieFile;
if (copyOnly) if (copyOnly)
{ {
moveFileResult.MovieFile = _movieFileMover.CopyMovieFile(movieFile, localMovie); moveFileResult.MovieFile = _movieFileMover.CopyMovieFile(movieFile, localMovie);
@ -66,6 +73,8 @@ public MovieFileMoveResult UpgradeMovieFile(MovieFile movieFile, LocalMovie loca
moveFileResult.MovieFile = _movieFileMover.MoveMovieFile(movieFile, localMovie); moveFileResult.MovieFile = _movieFileMover.MoveMovieFile(movieFile, localMovie);
} }
//_movieFileRenamer.RenameMoviePath(localMovie.Movie, false);
return moveFileResult; return moveFileResult;
} }

View file

@ -125,6 +125,7 @@
<Compile Include="Authentication\UserRepository.cs" /> <Compile Include="Authentication\UserRepository.cs" />
<Compile Include="Authentication\UserService.cs" /> <Compile Include="Authentication\UserService.cs" />
<Compile Include="Datastore\Migration\123_create_netimport_table.cs" /> <Compile Include="Datastore\Migration\123_create_netimport_table.cs" />
<Compile Include="MediaFiles\Events\MovieFileUpdatedEvent.cs" />
<Compile Include="Datastore\Migration\134_add_remux_qualities_for_the_wankers.cs" /> <Compile Include="Datastore\Migration\134_add_remux_qualities_for_the_wankers.cs" />
<Compile Include="Datastore\Migration\129_add_parsed_movie_info_to_pending_release.cs" /> <Compile Include="Datastore\Migration\129_add_parsed_movie_info_to_pending_release.cs" />
<Compile Include="Datastore\Migration\128_remove_kickass.cs" /> <Compile Include="Datastore\Migration\128_remove_kickass.cs" />
@ -1275,7 +1276,9 @@
<Compile Include="Datastore\Migration\131_make_parsed_episode_info_nullable.cs" /> <Compile Include="Datastore\Migration\131_make_parsed_episode_info_nullable.cs" />
<Compile Include="Housekeeping\Housekeepers\FixWronglyMatchedMovieFiles.cs" /> <Compile Include="Housekeeping\Housekeepers\FixWronglyMatchedMovieFiles.cs" />
<Compile Include="Datastore\Migration\135_add_haspredbentry_to_movies.cs" /> <Compile Include="Datastore\Migration\135_add_haspredbentry_to_movies.cs" />
<Compile Include="MediaFiles\Commands\RenameMovieFolderCommand.cs" />
<Compile Include="Tv\QueryExtensions.cs" /> <Compile Include="Tv\QueryExtensions.cs" />
<Compile Include="Datastore\Migration\136_add_pathstate_to_movies.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client"> <BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">

View file

@ -20,6 +20,7 @@ public interface IBuildFileNames
string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namingConfig = null); string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namingConfig = null);
string BuildFilePath(Movie movie, string fileName, string extension); string BuildFilePath(Movie movie, string fileName, string extension);
string BuildFilePath(Series series, int seasonNumber, string fileName, string extension); string BuildFilePath(Series series, int seasonNumber, string fileName, string extension);
string BuildMoviePath(Movie movie, NamingConfig namingConfig = null);
string BuildSeasonPath(Series series, int seasonNumber); string BuildSeasonPath(Series series, int seasonNumber);
BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec); BasicNamingConfig GetBasicNamingConfig(NamingConfig nameSpec);
string GetSeriesFolder(Series series, NamingConfig namingConfig = null); string GetSeriesFolder(Series series, NamingConfig namingConfig = null);
@ -158,12 +159,11 @@ public string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namin
return GetOriginalTitle(movieFile); return GetOriginalTitle(movieFile);
} }
//TODO: Update namingConfig for Movies!
var pattern = namingConfig.StandardMovieFormat; var pattern = namingConfig.StandardMovieFormat;
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance); var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
AddMovieTokens(tokenHandlers, movie); AddMovieTokens(tokenHandlers, movie);
AddReleaseDateTokens(tokenHandlers, movie.Year); //In case we want to separate the year AddReleaseDateTokens(tokenHandlers, movie.Year);
AddImdbIdTokens(tokenHandlers, movie.ImdbId); AddImdbIdTokens(tokenHandlers, movie.ImdbId);
AddQualityTokens(tokenHandlers, movie, movieFile); AddQualityTokens(tokenHandlers, movie, movieFile);
AddMediaInfoTokens(tokenHandlers, movieFile); AddMediaInfoTokens(tokenHandlers, movieFile);
@ -190,11 +190,61 @@ public string BuildFilePath(Movie movie, string fileName, string extension)
{ {
Ensure.That(extension, () => extension).IsNotNullOrWhiteSpace(); Ensure.That(extension, () => extension).IsNotNullOrWhiteSpace();
var path = movie.Path; var path = "";
if (movie.PathState > 0)
{
path = movie.Path;
}
else
{
path = BuildMoviePath(movie);
}
return Path.Combine(path, fileName + extension); return Path.Combine(path, fileName + extension);
} }
public string BuildMoviePath(Movie movie, NamingConfig namingConfig = null)
{
if (namingConfig == null)
{
namingConfig = _namingConfigService.GetConfig();
}
var path = movie.Path;
var directory = new DirectoryInfo(path).Name;
var parentDirectoryPath = new DirectoryInfo(path).Parent.FullName;
var movieFile = movie.MovieFile;
var pattern = namingConfig.MovieFolderFormat;
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
AddMovieTokens(tokenHandlers, movie);
AddReleaseDateTokens(tokenHandlers, movie.Year);
AddImdbIdTokens(tokenHandlers, movie.ImdbId);
if(movie.MovieFileId != 0)
{
movieFile.LazyLoad();
AddQualityTokens(tokenHandlers, movie, movieFile);
AddMediaInfoTokens(tokenHandlers, movieFile);
AddMovieFileTokens(tokenHandlers, movieFile);
AddTagsTokens(tokenHandlers, movieFile);
}
else
{
AddMovieFileTokens(tokenHandlers, new MovieFile { SceneName = $"{movie.Title} {movie.Year}", RelativePath = $"{movie.Title} {movie.Year}" });
}
var directoryName = ReplaceTokens(pattern, tokenHandlers, namingConfig).Trim();
directoryName = FileNameCleanupRegex.Replace(directoryName, match => match.Captures[0].Value[0].ToString());
directoryName = TrimSeparatorsRegex.Replace(directoryName, string.Empty);
return Path.Combine(parentDirectoryPath, directoryName);
}
public string BuildSeasonPath(Series series, int seasonNumber) public string BuildSeasonPath(Series series, int seasonNumber)
{ {
var path = series.Path; var path = series.Path;
@ -302,12 +352,28 @@ public string GetMovieFolder(Movie movie, NamingConfig namingConfig = null)
namingConfig = _namingConfigService.GetConfig(); namingConfig = _namingConfigService.GetConfig();
} }
var movieFile = movie.MovieFile;
var pattern = namingConfig.MovieFolderFormat;
var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance); var tokenHandlers = new Dictionary<string, Func<TokenMatch, string>>(FileNameBuilderTokenEqualityComparer.Instance);
AddMovieTokens(tokenHandlers, movie); AddMovieTokens(tokenHandlers, movie);
AddReleaseDateTokens(tokenHandlers, movie.Year); AddReleaseDateTokens(tokenHandlers, movie.Year);
AddImdbIdTokens(tokenHandlers, movie.ImdbId); AddImdbIdTokens(tokenHandlers, movie.ImdbId);
if (movie.MovieFileId != 0)
{
movieFile.LazyLoad();
AddQualityTokens(tokenHandlers, movie, movieFile);
AddMediaInfoTokens(tokenHandlers, movieFile);
AddMovieFileTokens(tokenHandlers, movieFile);
AddTagsTokens(tokenHandlers, movieFile);
}
else
{
AddMovieFileTokens(tokenHandlers, new MovieFile { SceneName = $"{movie.Title} {movie.Year}", RelativePath = $"{movie.Title} {movie.Year}"});
}
return CleanFolderName(ReplaceTokens(namingConfig.MovieFolderFormat, tokenHandlers, namingConfig)); return CleanFolderName(ReplaceTokens(namingConfig.MovieFolderFormat, tokenHandlers, namingConfig));
} }

View file

@ -44,13 +44,6 @@ public FileNameSampleService(IBuildFileNames buildFileNames)
{ {
_buildFileNames = buildFileNames; _buildFileNames = buildFileNames;
_movie = new Movie
{
Title = "The Movie Title",
Year = 2010,
ImdbId = "tt0066921"
};
_standardSeries = new Series _standardSeries = new Series
{ {
SeriesType = SeriesTypes.Standard, SeriesType = SeriesTypes.Standard,
@ -122,13 +115,22 @@ public FileNameSampleService(IBuildFileNames buildFileNames)
_movieFile = new MovieFile _movieFile = new MovieFile
{ {
Quality = new QualityModel(Quality.Bluray1080p, new Revision(2)), Quality = new QualityModel(Quality.Bluray1080p, new Revision(2)),
RelativePath = "Movie.Title.2010.1080p.BluRay.DTS.x264-EVOLVE.mkv", RelativePath = "The.Movie.Title.2010.1080p.BluRay.DTS.x264-EVOLVE.mkv",
SceneName = "Movie.Title.2010.1080p.BluRay.DTS.x264-EVOLVE", SceneName = "The.Movie.Title.2010.1080p.BluRay.DTS.x264-EVOLVE",
ReleaseGroup = "RlsGrp", ReleaseGroup = "EVOLVE",
MediaInfo = mediaInfo, MediaInfo = mediaInfo,
Edition = "Ultimate extended edition", Edition = "Ultimate extended edition",
}; };
_movie = new Movie
{
Title = "The Movie: Title",
Year = 2010,
ImdbId = "tt0066921",
MovieFile = _movieFile,
MovieFileId = 1,
};
_singleEpisodeFile = new EpisodeFile _singleEpisodeFile = new EpisodeFile
{ {
Quality = new QualityModel(Quality.HDTV720p, new Revision(2)), Quality = new QualityModel(Quality.HDTV720p, new Revision(2)),

View file

@ -41,6 +41,7 @@ public Movie()
public List<Actor> Actors { get; set; } public List<Actor> Actors { get; set; }
public string Certification { get; set; } public string Certification { get; set; }
public string RootFolderPath { get; set; } public string RootFolderPath { get; set; }
public MoviePathState PathState { get; set; }
public DateTime Added { get; set; } public DateTime Added { get; set; }
public DateTime? InCinemas { get; set; } public DateTime? InCinemas { get; set; }
public DateTime? PhysicalRelease { get; set; } public DateTime? PhysicalRelease { get; set; }
@ -117,4 +118,11 @@ public class AddMovieOptions : MonitoringOptions
{ {
public bool SearchForMovie { get; set; } public bool SearchForMovie { get; set; }
} }
public enum MoviePathState
{
Dynamic,
StaticOnce,
Static,
}
} }

View file

@ -150,13 +150,23 @@ public Movie AddMovie(Movie newMovie)
{ {
Ensure.That(newMovie, () => newMovie).IsNotNull(); Ensure.That(newMovie, () => newMovie).IsNotNull();
MoviePathState defaultState = MoviePathState.Static;
if (!_configService.PathsDefaultStatic)
{
defaultState = MoviePathState.Dynamic;
}
if (string.IsNullOrWhiteSpace(newMovie.Path)) if (string.IsNullOrWhiteSpace(newMovie.Path))
{ {
var folderName = _fileNameBuilder.GetMovieFolder(newMovie); var folderName = _fileNameBuilder.GetMovieFolder(newMovie);
newMovie.Path = Path.Combine(newMovie.RootFolderPath, folderName); newMovie.Path = Path.Combine(newMovie.RootFolderPath, folderName);
newMovie.PathState = defaultState;
}
else
{
newMovie.PathState = defaultState == MoviePathState.Dynamic ? MoviePathState.StaticOnce : MoviePathState.Static;
} }
_logger.Info("Adding Movie {0} Path: [{1}]", newMovie, newMovie.Path); _logger.Info("Adding Movie {0} Path: [{1}]", newMovie, newMovie.Path);
newMovie.CleanTitle = newMovie.Title.CleanSeriesTitle(); newMovie.CleanTitle = newMovie.Title.CleanSeriesTitle();
newMovie.SortTitle = MovieTitleNormalizer.Normalize(newMovie.Title, newMovie.TmdbId); newMovie.SortTitle = MovieTitleNormalizer.Normalize(newMovie.Title, newMovie.TmdbId);
@ -174,10 +184,20 @@ public List<Movie> AddMovies(List<Movie> newMovies)
newMovies.ForEach(m => newMovies.ForEach(m =>
{ {
MoviePathState defaultState = MoviePathState.Static;
if (!_configService.PathsDefaultStatic)
{
defaultState = MoviePathState.Dynamic;
}
if (string.IsNullOrWhiteSpace(m.Path)) if (string.IsNullOrWhiteSpace(m.Path))
{ {
var folderName = _fileNameBuilder.GetMovieFolder(m); var folderName = _fileNameBuilder.GetMovieFolder(m);
m.Path = Path.Combine(m.RootFolderPath, folderName); m.Path = Path.Combine(m.RootFolderPath, folderName);
m.PathState = defaultState;
}
else
{
m.PathState = defaultState == MoviePathState.Dynamic ? MoviePathState.StaticOnce : MoviePathState.Static;
} }
m.CleanTitle = m.Title.CleanSeriesTitle(); m.CleanTitle = m.Title.CleanSeriesTitle();

View file

@ -13,6 +13,7 @@
using NzbDrone.Core.MetadataSource; using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Tv.Commands; using NzbDrone.Core.Tv.Commands;
using NzbDrone.Core.Tv.Events; using NzbDrone.Core.Tv.Events;
using NzbDrone.Core.MediaFiles.Commands;
namespace NzbDrone.Core.Tv namespace NzbDrone.Core.Tv
{ {
@ -22,6 +23,7 @@ public class RefreshMovieService : IExecute<RefreshMovieCommand>
private readonly IMovieService _movieService; private readonly IMovieService _movieService;
private readonly IRefreshEpisodeService _refreshEpisodeService; private readonly IRefreshEpisodeService _refreshEpisodeService;
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private readonly IManageCommandQueue _commandQueueManager;
private readonly IDiskScanService _diskScanService; private readonly IDiskScanService _diskScanService;
private readonly ICheckIfMovieShouldBeRefreshed _checkIfMovieShouldBeRefreshed; private readonly ICheckIfMovieShouldBeRefreshed _checkIfMovieShouldBeRefreshed;
private readonly Logger _logger; private readonly Logger _logger;
@ -32,12 +34,14 @@ public RefreshMovieService(IProvideMovieInfo movieInfo,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
IDiskScanService diskScanService, IDiskScanService diskScanService,
ICheckIfMovieShouldBeRefreshed checkIfMovieShouldBeRefreshed, ICheckIfMovieShouldBeRefreshed checkIfMovieShouldBeRefreshed,
IManageCommandQueue commandQueue,
Logger logger) Logger logger)
{ {
_movieInfo = movieInfo; _movieInfo = movieInfo;
_movieService = movieService; _movieService = movieService;
_refreshEpisodeService = refreshEpisodeService; _refreshEpisodeService = refreshEpisodeService;
_eventAggregator = eventAggregator; _eventAggregator = eventAggregator;
_commandQueueManager = commandQueue;
_diskScanService = diskScanService; _diskScanService = diskScanService;
_checkIfMovieShouldBeRefreshed = checkIfMovieShouldBeRefreshed; _checkIfMovieShouldBeRefreshed = checkIfMovieShouldBeRefreshed;
_logger = logger; _logger = logger;
@ -136,6 +140,7 @@ public void Execute(RefreshMovieCommand message)
try try
{ {
_logger.Info("Skipping refresh of movie: {0}", movie.Title); _logger.Info("Skipping refresh of movie: {0}", movie.Title);
_commandQueueManager.Push(new RenameMovieFolderCommand(new List<int>{movie.Id}));
_diskScanService.Scan(movie); _diskScanService.Scan(movie);
} }
catch (Exception e) catch (Exception e)

View file

@ -47,27 +47,29 @@
</div> </div>
</div> </div>
<!--<div class="form-group"> <div class="form-group">
<label class="col-sm-4 control-label">Use Season Folder</label> <label class="col-sm-4 control-label">Static Path</label>
<div class="col-sm-8"> <div class="col-sm-6">
<div class="input-group"> <div class="input-group">
<label class="checkbox toggle well"> <label class="checkbox toggle well">
<input type="checkbox" name="seasonFolder"/> <input type="checkbox" name="pathState"/>
<p> <p>
<span>Yes</span> <span>Yes</span>
<span>No</span> <span>No</span>
</p> </p>
<div class="btn btn-primary slide-button"/> <div class="btn btn-primary slide-button">
</div>
</label> </label>
<span class="help-inline-checkbox"> <span class="help-inline-checkbox">
<i class="icon-sonarr-form-info" title="Should downloaded episodes be stored in season folders?"/> <i class="icon-sonarr-form-info" title="Should movie path stay static or should it change on each disk scan according to your naming config? Note: Auto Rename Folders under Settings -&gt; Media Management must be enabled too."/>
</span> </span>
</div> </div>
</div> </div>
</div>--> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-4 control-label">Profile</label> <label class="col-sm-4 control-label">Profile</label>

View file

@ -22,6 +22,12 @@ var view = Marionette.ItemView.extend({
initialize : function() { initialize : function() {
this.model.set('profiles', Profiles); this.model.set('profiles', Profiles);
var pathState = this.model.get("pathState");
if (pathState == "static") {
this.model.set("pathState", true);
} else {
this.model.set("pathState", false);
}
}, },
onRender : function() { onRender : function() {
@ -30,11 +36,18 @@ var view = Marionette.ItemView.extend({
model : this.model, model : this.model,
property : 'tags' property : 'tags'
}); });
}, },
_onBeforeSave : function() { _onBeforeSave : function() {
var profileId = this.ui.profile.val(); var profileId = this.ui.profile.val();
this.model.set({ profileId : profileId }); this.model.set({ profileId : profileId });
var pathState = this.model.get("pathState");
if (pathState === true) {
this.model.set("pathState", "static");
} else {
this.model.set("pathState", "dynamic");
}
}, },
_onAfterSave : function() { _onAfterSave : function() {

View file

@ -15,7 +15,7 @@ module.exports = Marionette.ItemView.extend({
monitored : '.x-monitored', monitored : '.x-monitored',
profile : '.x-profiles', profile : '.x-profiles',
minimumAvailability : '.x-minimumavailability', minimumAvailability : '.x-minimumavailability',
seasonFolder : '.x-season-folder', staticPath : '.x-static-path',
rootFolder : '.x-root-folder', rootFolder : '.x-root-folder',
selectedCount : '.x-selected-count', selectedCount : '.x-selected-count',
container : '.series-editor-footer', container : '.series-editor-footer',
@ -71,7 +71,7 @@ module.exports = Marionette.ItemView.extend({
var monitored = this.ui.monitored.val(); var monitored = this.ui.monitored.val();
var minAvail = this.ui.minimumAvailability.val(); var minAvail = this.ui.minimumAvailability.val();
var profile = this.ui.profile.val(); var profile = this.ui.profile.val();
var seasonFolder = this.ui.seasonFolder.val(); var staticPath = this.ui.staticPath.val();
var rootFolder = this.ui.rootFolder.val(); var rootFolder = this.ui.rootFolder.val();
var i = 0; var i = 0;
@ -94,10 +94,8 @@ module.exports = Marionette.ItemView.extend({
model.set('profileId', parseInt(profile, 10)); model.set('profileId', parseInt(profile, 10));
} }
if (seasonFolder === 'true') { if (staticPath !== 'noChange') {
model.set('seasonFolder', true); model.set('pathState', staticPath);
} else if (seasonFolder === 'false') {
model.set('seasonFolder', false);
} }
if (rootFolder !== 'noChange') { if (rootFolder !== 'noChange') {
@ -129,10 +127,8 @@ module.exports = Marionette.ItemView.extend({
m.set('profileId', parseInt(profile, 10)); m.set('profileId', parseInt(profile, 10));
} }
if (seasonFolder === 'true') { if (staticPath !== 'noChange') {
m.set('seasonFolder', true); m.set('pathState', staticPath);
} else if (seasonFolder === 'false') {
m.set('seasonFolder', false);
} }
if (rootFolder !== 'noChange') { if (rootFolder !== 'noChange') {

View file

@ -1,6 +1,6 @@
<div class="series-editor-footer"> <div class="series-editor-footer">
<div class="row"> <div class="row">
<div class="form-group col-md-2"> <div class="form-group col-md-1">
<label>Monitored</label> <label>Monitored</label>
<select class="form-control x-action x-monitored"> <select class="form-control x-action x-monitored">
@ -33,15 +33,15 @@
</select> </select>
</div> </div>
{{!--<div class="form-group col-md-2"> <div class="form-group col-md-2">
<label>Season Folder</label> <label>Static Path</label>
<select class="form-control x-action x-season-folder"> <select class="form-control x-action x-static-path">
<option value="noChange">No change</option> <option value="noChange">No change</option>
<option value="true">Yes</option> <option value="static">Yes</option>
<option value="false">No</option> <option value="dynamic">No</option>
</select> </select>
</div>--}} </div>
<div class="form-group col-md-3"> <div class="form-group col-md-3">
<label>Root Folder</label> <label>Root Folder</label>
@ -55,7 +55,7 @@
</select> </select>
</div> </div>
<div class="form-group col-md-3 actions"> <div class="form-group col-md-2 actions">
<label class="x-selected-count">0 movies selected</label> <label class="x-selected-count">0 movies selected</label>
<div> <div>
<button class="btn btn-primary x-action x-save">Save</button> <button class="btn btn-primary x-action x-save">Save</button>

View file

@ -48,6 +48,7 @@ var view = Marionette.ItemView.extend({
_onAfterSave : function() { _onAfterSave : function() {
this.trigger('saved'); this.trigger('saved');
vent.trigger(vent.Commands.MovieFileEdited);
vent.trigger(vent.Commands.CloseModalCommand); vent.trigger(vent.Commands.CloseModalCommand);
}, },

View file

@ -87,7 +87,7 @@ module.exports = Marionette.Layout.extend({
} }
}); });
vent.on(vent.Commands.CloseModalCommand, this._refreshClose, this); vent.on(vent.Commands.MovieFileEdited, this._showGrid, this);
}, },
_refresh : function(model) { _refresh : function(model) {
@ -105,7 +105,7 @@ module.exports = Marionette.Layout.extend({
this.filesCollection = new FilesCollection(); this.filesCollection = new FilesCollection();
var file = this.movie.model.get("movieFile"); var file = this.movie.model.get("movieFile");
this.filesCollection.add(file); this.filesCollection.add(file);
this.onShow(); this._showGrid();
}, },
onShow : function() { onShow : function() {
@ -117,6 +117,15 @@ module.exports = Marionette.Layout.extend({
})); }));
}, },
_showGrid : function() {
this.regionManager.get('grid').show(new Backgrid.Grid({
row : Backgrid.Row,
columns : this.columns,
collection : this.filesCollection,
className : 'table table-hover'
}));
},
_showMainView : function() { _showMainView : function() {
this.main.show(this.mainView); this.main.show(this.mainView);
}, },

View file

@ -9,6 +9,7 @@ module.exports = Marionette.ItemView.extend({
//var type = this.model.get('seriesType'); //var type = this.model.get('seriesType');
return { return {
rename : this.naming.get('renameEpisodes'), rename : this.naming.get('renameEpisodes'),
folderFormat: this.naming.get('movieFolderFormat'),
format : this.naming.get('standardMovieFormat') format : this.naming.get('standardMovieFormat')
}; };
}, },

View file

@ -1,3 +1,4 @@
{{#if rename}} {{#if rename}}
Folder Naming pattern: {{folderFormat}}<br>
Naming pattern: {{format}} Naming pattern: {{format}}
{{/if}} {{/if}}

View file

@ -9,7 +9,7 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="alert alert-info"> <div class="alert alert-info">
<div class="path-info x-path-info">All paths are relative to: <strong>{{path}}</strong></div> <div class="path-info x-path-info">Your movie may be moved; see the paths below</strong></div>
<div class="x-format-region"></div> <div class="x-format-region"></div>
</div> </div>

View file

@ -162,6 +162,10 @@
<ul class="dropdown-menu"> <ul class="dropdown-menu">
{{> MovieTitleNamingPartial}} {{> MovieTitleNamingPartial}}
{{> ReleaseYearNamingPartial}} {{> ReleaseYearNamingPartial}}
{{> QualityNamingPartial}}
{{> MediaInfoNamingPartial}}
{{> ReleaseGroupNamingPartial}}
{{> OriginalTitleNamingPartial}}
{{> ImdbIdNamingPartial}} {{> ImdbIdNamingPartial}}
</ul> </ul>
</div> </div>

View file

@ -23,6 +23,52 @@
</div> </div>
</div> </div>
</div> </div>
<div class="form-group">
<label class="col-sm-3 control-label">Automatically Rename Folders</label>
<div class="col-sm-9">
<div class="input-group">
<label class="checkbox toggle well">
<input type="checkbox" name="autoRenameFolders"/>
<p>
<span>Yes</span>
<span>No</span>
</p>
<div class="btn btn-primary slide-button"/>
</label>
<span class="help-inline-checkbox">
<i class="icon-sonarr-form-warning" title="CURRENTLY ALPHA! This feature must be enabled for namings schemes beyond '{Movie Title} {Year}' to work. With it folders are automatically renamed according to your naming scheme on each disk scan. If your folder naming scheme contains things such as quality, etc., the movie folder will be automatcially adjusted for that regardless of this setting."/>
</span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Movie Paths Default to Static</label>
<div class="col-sm-9">
<div class="input-group">
<label class="checkbox toggle well">
<input type="checkbox" name="pathsDefaultStatic"/>
<p>
<span>Yes</span>
<span>No</span>
</p>
<div class="btn btn-primary slide-button"/>
</label>
<span class="help-inline-checkbox">
<i class="icon-sonarr-form-warning" title="CURRENTLY ALPHA! If enabled, the path of new movies is static and won't change."/>
</span>
</div>
</div>
</div>
</fieldset> </fieldset>
<fieldset class="advanced-setting"> <fieldset class="advanced-setting">

View file

@ -32,7 +32,8 @@ vent.Commands = {
CloseFileBrowser : 'closeFileBrowser', CloseFileBrowser : 'closeFileBrowser',
OpenControlPanelCommand : 'OpenControlPanelCommand', OpenControlPanelCommand : 'OpenControlPanelCommand',
CloseControlPanelCommand : 'CloseControlPanelCommand', CloseControlPanelCommand : 'CloseControlPanelCommand',
ShowExistingCommand : 'ShowExistingCommand' ShowExistingCommand : 'ShowExistingCommand',
MovieFileEdited : 'MovieFileEdited'
}; };
vent.Hotkeys = { vent.Hotkeys = {