public OrgItemEditorWindow(OrgItem item) { InitializeComponent(); viewModel = new OrgItemEditorWindowViewModel(item); this.DataContext = viewModel; viewModel.ResultsSet += viewModel_ResultsSet; }
/// <summary> /// Run through all TV shows all looks for episodes that may need to be renamed and for missing episodes. /// For missing episodes it attempts to match them to files from the search directories. /// </summary> /// <param name="shows">Shows to scan</param> /// <param name="queuedItems">Items currently in queue (to be skipped)</param> /// <returns></returns> public List<OrgItem> RunScan(List<ContentRootFolder> folders, List<OrgItem> queuedItems, bool fast) { // Set running flag scanRunning = true; cancelRequested = false; // Convert all TV folder to scan folders so we can do a scan of them List<OrgFolder> tvFoldersAsOrgFolders = new List<OrgFolder>(); foreach (ContentRootFolder tvFolder in folders) { OrgFolder orgFolder = new OrgFolder(tvFolder.FullPath, false, false, false, false); tvFoldersAsOrgFolders.Add(orgFolder); } // Do directory scan on all TV folders DirectoryScan dirScan = new DirectoryScan(false); dirScan.ProgressChange += dirScan_ProgressChange; dirScan.RunScan(tvFoldersAsOrgFolders, queuedItems, 90, true, false, fast, true); List<OrgItem> results = dirScan.Items; // Check if show folder needs to be renamed! int number = results.Count; foreach (ContentRootFolder tvFolder in folders) for (int i = 0; i < Organization.Shows.Count; i++) { TvShow show = (TvShow)Organization.Shows[i]; if (show.Id <= 0 || show.RootFolder != tvFolder.FullPath) continue; string builtFolder = Path.Combine(show.RootFolder, FileHelper.GetSafeFileName(show.DatabaseName)); if (show.Path != builtFolder) { OrgItem newItem = new OrgItem(OrgStatus.Organization, OrgAction.Rename, show.Path, builtFolder, new TvEpisode("", show, -1, -1, "", ""), null, FileCategory.Folder, null); newItem.Enable = true; newItem.Number = number++; results.Add(newItem); } } // Update progress OnProgressChange(ScanProcess.TvFolder, string.Empty, 100); // Clear flags scanRunning = false; // Return results return results; }
public OrgItemEditorWindowViewModel(OrgItem item) { this.OriginalItem = item; this.Item = new OrgItem(item); this.Item.PropertyChanged += Item_PropertyChanged; this.SourceEditingAllowed = string.IsNullOrEmpty(this.Item.SourcePath); // Set path for movie to item source path (for filling in search box) if (string.IsNullOrEmpty(this.Item.Movie.Path)) this.Item.Movie.Path = System.IO.Path.GetFileNameWithoutExtension(item.SourcePath); // Create view model for movie content editor this.MovieViewModel = new ContentEditorControlViewModel(this.Item.Movie, true); this.MovieViewModel.Content.PropertyChanged += ItemSubProperty_PropertyChanged; ContentRootFolder movieFolder; if (string.IsNullOrEmpty(this.Item.Movie.RootFolder) && Settings.GetMovieFolderForContent(this.Item.Movie, out movieFolder)) this.Item.Movie.RootFolder = movieFolder.FullPath; // tv number update int season, episode1, episode2; if (this.Item.TvEpisode.DatabaseNumber == -1 && FileHelper.GetEpisodeInfo(item.SourcePath, string.Empty, out season, out episode1, out episode2)) { this.Item.TvEpisode.Season = season; this.Item.TvEpisode.DatabaseNumber = episode1; this.Item.TvEpisode2.Season = season; this.Item.TvEpisode2.DatabaseNumber = episode2; } // Setup avilable shows this.Shows = new ObservableCollection<TvShow>(); foreach (TvShow show in Organization.Shows) this.Shows.Add(show); if (string.IsNullOrEmpty(this.Item.TvEpisode.Show.DatabaseName) && this.Shows.Count > 0) this.Item.TvEpisode.Show = this.Shows[0]; if (!string.IsNullOrEmpty(this.Item.TvEpisode.Show.DatabaseName) && !this.Shows.Contains(this.Item.TvEpisode.Show)) this.Shows.Add(this.Item.TvEpisode.Show); this.Item.TvEpisode.PropertyChanged += ItemSubProperty_PropertyChanged; }
public bool BuildFileMoveItem(string filePath, OrgFolder scanDir, out OrgItem item) { item = null; foreach (string fileType in this.FileTypes) if (FileHelper.FileTypeMatch(fileType, filePath)) { item = new OrgItem(filePath, this, scanDir, false); if (File.Exists(item.DestinationPath)) { item.Action = OrgAction.AlreadyExists; item.Enable = false; } return true; } return false; }
private OrgItem UpdateItemFromPrevious(OrgPath orgPath, OrgItem reuseItem, bool threaded, bool fast, bool skipMatching) { switch (reuseItem.Action) { case OrgAction.Delete: OrgItem copyItem = new OrgItem(reuseItem); copyItem.SourcePath = orgPath.Path; copyItem.BuildDestination(); return copyItem; case OrgAction.Move: case OrgAction.Copy: if (reuseItem.Category == FileCategory.MovieVideo) { OrgItem item; CreateMovieAction(orgPath, orgPath.Path, out item, threaded, fast, skipMatching, reuseItem.Movie); return item; } else if (reuseItem.Category == FileCategory.TvVideo) { if (!Organization.Shows.Contains(reuseItem.TvEpisode.Show) && !temporaryShows.Contains(reuseItem.TvEpisode.Show)) lock (directoryScanLock) temporaryShows.Add(reuseItem.TvEpisode.Show); } break; default: break; } return null; }
/// <summary> /// Tries to create a movie action item for a scan from a file. /// </summary> /// <param name="file">The file to create movie action from</param> /// <param name="item">The resulting movie action</param> /// <returns>Whether the file was matched to a movie</returns> private bool CreateMovieAction(OrgPath file, string matchString, out OrgItem item, bool threaded, bool fast, bool skipMatching, Movie knownMovie) { // Initialize item item = new OrgItem(OrgAction.None, file.Path, FileCategory.MovieVideo, file.OrgFolder); // Check if sample! if (matchString.ToLower().Contains("sample")) { item.Action = OrgAction.Delete; return false; } // Try to match file to movie string search = Path.GetFileNameWithoutExtension(matchString); // Search for match to movie Movie searchResult = null; bool searchSucess = false; if (!skipMatching) searchSucess = SearchHelper.MovieSearch.ContentMatch(search, string.Empty, string.Empty, fast, threaded, out searchResult, knownMovie); // Add closest match item if (searchSucess) { // Get root folder ContentRootFolder rootFolder; string path; if (Settings.GetMovieFolderForContent(searchResult, out rootFolder)) searchResult.RootFolder = rootFolder.FullPath; else { searchResult.RootFolder = NO_MOVIE_FOLDER; item.Action = OrgAction.NoRootFolder; } if (item.Action != OrgAction.NoRootFolder) item.Action = file.Copy ? OrgAction.Copy : OrgAction.Move; item.DestinationPath = searchResult.BuildFilePath(file.Path); if (File.Exists(item.DestinationPath)) item.Action = OrgAction.AlreadyExists; searchResult.Path = searchResult.BuildFolderPath(); item.Movie = searchResult; if (item.Action == OrgAction.AlreadyExists || item.Action == OrgAction.NoRootFolder) item.Enable = false; else item.Enable = true; return true; } return false; }
public OrgItem ProcessPath(OrgPath orgPath, bool tvOnlyCheck, bool skipMatching, bool fast, bool threaded, int procNumber, bool allowFromLog, out bool fromLog) { fromLog = false; FileCategory fileCat = FileHelper.CategorizeFile(orgPath, orgPath.Path); // Search through dir scan log for matching source if(allowFromLog) for (int i = 0; i < Organization.DirScanLog.Count; i++) { if (Organization.DirScanLog[i].SourcePath == orgPath.Path) { fromLog = true; if (fileCat != Organization.DirScanLog[i].Category) break; OrgItem newItem = UpdateItemFromPrevious(orgPath, Organization.DirScanLog[i], threaded, false, false); if (newItem != null && newItem.Action != OrgAction.None) { if (newItem.CanEnable) newItem.Enable = true; return newItem; } } } // If similar to earlier item, wait for it to complete before continuing while (!skipMatching && orgPath.SimilarTo >= 0 && orgPath.SimilarTo < this.Items.Count && (this.Items[orgPath.SimilarTo].Action == OrgAction.TBD || this.Items[orgPath.SimilarTo].Action == OrgAction.Processing)) { // Check for cancellation if (scanCanceled || procNumber < scanNumber) return null; Thread.Sleep(50); } // If similar to earlier item, check if we can use it's info if (orgPath.SimilarTo > 0 && orgPath.SimilarTo < this.Items.Count) { OrgItem newItem = UpdateItemFromPrevious(orgPath, this.Items[orgPath.SimilarTo], threaded, fast, skipMatching); if (newItem != null) return newItem; } // Create default none item OrgItem noneItem = new OrgItem(OrgAction.None, orgPath.Path, fileCat, orgPath.OrgFolder); // Setup match to filename and folder name (if it's in a folder inside of downloads) string pathBase; if (!string.IsNullOrEmpty(orgPath.OrgFolder.FolderPath)) pathBase = orgPath.Path.Replace(orgPath.OrgFolder.FolderPath, ""); else pathBase = orgPath.Path; string[] pathSplit; if (!string.IsNullOrEmpty(orgPath.OrgFolder.FolderPath)) pathSplit = pathBase.Split('\\'); else pathSplit = orgPath.Path.Split('\\'); pathSplit[pathSplit.Length - 1] = Path.GetFileNameWithoutExtension(pathSplit[pathSplit.Length - 1]); List<string> possibleMatchPaths = new List<string>(); // Looking to remove dummy video files by rip (e.g. "ERTG.mp4" inside "The Matrix 1999 hd ERGT rip/" folder) List<string> validSplits = new List<string>(); for (int i = pathSplit.Length - 1; i > 0; i--) { if (string.IsNullOrWhiteSpace(pathSplit[i])) continue; bool containedInOther = false; for (int j = i - 1; j > 0; j--) { if (pathSplit[j].Length > pathSplit[i].Length && pathSplit[j].ToLower().Contains(pathSplit[i].ToLower())) { containedInOther = true; break; } } if (!containedInOther) { validSplits.Add(pathSplit[i]); possibleMatchPaths.Add(pathSplit[i] + Path.GetExtension(orgPath.Path)); } } for (int i = validSplits.Count - 1; i >= 0; i--) { string build = string.Empty; for (int j = validSplits.Count - 1; j >=i ; j--) build += validSplits[j] + " "; build = build.Trim(); build += Path.GetExtension(orgPath.Path); if (!possibleMatchPaths.Contains(build)) possibleMatchPaths.Add(build); } // Try to match to each string foreach (string matchString in possibleMatchPaths) { OnDebugNotificationd("Attempting to match to path: \" " + matchString + "\""); // Get simple file name string simpleFile = FileHelper.BasicSimplify(Path.GetFileNameWithoutExtension(matchString), false); OnDebugNotificationd("Simplifies to: \" " + simpleFile + "\""); // Categorize current match string FileCategory matchFileCat = FileHelper.CategorizeFile(orgPath, matchString); OnDebugNotificationd("Classified as: " + matchFileCat); // Check tv if (tvOnlyCheck && matchFileCat != FileCategory.TvVideo) continue; // Check for cancellation if (scanCanceled || procNumber < scanNumber) return null; // Set whether item is for new show bool newShow = false; // Check for cancellation if (scanCanceled || procNumber < scanNumber) return null; // Add appropriate action based on file category switch (matchFileCat) { // TV item case FileCategory.TvVideo: // Try to match file to existing show Dictionary<TvShow, MatchCollection> matches = new Dictionary<TvShow, MatchCollection>(); for (int j = 0; j < Organization.Shows.Count; j++) { MatchCollection match = Organization.Shows[j].MatchFileToContent(matchString); if (match != null && match.Count > 0) matches.Add((TvShow)Organization.Shows[j], match); } // Try to match to temporary show lock (directoryScanLock) foreach (TvShow show in temporaryShows) { MatchCollection match = show.MatchFileToContent(matchString); if (match != null && match.Count > 0 && !matches.ContainsKey(show)) matches.Add(show, match); } // Debug notification for show matches string matchNotification = "Show name matches found: "; if (matches.Count == 0) matchNotification += "NONE"; else { foreach (TvShow match in matches.Keys) matchNotification += match.DisplayName + ", "; matchNotification = matchNotification.Substring(0, matchNotification.Length - 2); } OnDebugNotificationd(matchNotification); // Check for matches to existing show TvShow bestMatch = null; if (matches.Count > 0) { // Find best match, based on length int longestMatch = 2; // minimum of 3 letters must match (acronym) foreach (KeyValuePair<TvShow, MatchCollection> match in matches) foreach (Match m in match.Value) { // Check that match is not part of a word int matchWordCnt = 0; for (int l = m.Index; l < simpleFile.Length; l++) { if (simpleFile[l] == ' ') break; else ++matchWordCnt; } if (m.Value.Trim().Length > longestMatch && m.Length >= matchWordCnt) { longestMatch = m.Length; bestMatch = match.Key; } } if (bestMatch != null) OnDebugNotificationd("Matched to show " + bestMatch.DisplayName); } // Episode not matched to a TV show, search database! if (bestMatch == null && !skipMatching) { OnDebugNotificationd("Not matched to existing show; searching database."); // Setup search string string showFile = Path.GetFileNameWithoutExtension(matchString); // Perform search for matching TV show if (SearchHelper.TvShowSearch.ContentMatch(showFile, string.Empty, string.Empty, fast, threaded, out bestMatch)) { ContentRootFolder defaultTvFolder; string path = NO_TV_FOLDER; if (Settings.GetTvFolderForContent(bestMatch, out defaultTvFolder)) path = defaultTvFolder.FullPath; bestMatch.RootFolder = path; bestMatch.Path = bestMatch.BuildFolderPath(); // Save show in temporary shows list (in case there are more files that may match to it during scan) lock (directoryScanLock) if (!temporaryShows.Contains(bestMatch)) temporaryShows.Add(bestMatch); newShow = true; } else bestMatch = null; } else if (temporaryShows.Contains(bestMatch)) newShow = true; // Episode has been matched to a TV show if (bestMatch != null) { // Try to get episode information from file int seasonNum, episodeNum1, episodeNum2; if (FileHelper.GetEpisodeInfo(matchString, bestMatch.DatabaseName, out seasonNum, out episodeNum1, out episodeNum2)) { // No season match means file only had episode number, allow this for single season shows if (seasonNum == -1) { int maxSeason = 0; foreach (int season in bestMatch.Seasons) if (season > maxSeason) maxSeason = season; if (maxSeason == 1) seasonNum = 1; } // Try to get the episode from the show TvEpisode episode1, episode2 = null; if (bestMatch.FindEpisode(seasonNum, episodeNum1, false, out episode1)) { if (episodeNum2 != -1) bestMatch.FindEpisode(seasonNum, episodeNum2, false, out episode2); OrgAction action = orgPath.Copy ? OrgAction.Copy : OrgAction.Move; // If item episode already exists set action to duplicate if (episode1.Missing == MissingStatus.Located) action = OrgAction.AlreadyExists; // Build action and add it to results string destination = bestMatch.BuildFilePath(episode1, episode2, Path.GetExtension(orgPath.Path)); OrgItem newItem = new OrgItem(action, orgPath.Path, destination, episode1, episode2, fileCat, orgPath.OrgFolder); if (destination.StartsWith(NO_TV_FOLDER)) newItem.Action = OrgAction.NoRootFolder; if (newItem.Action == OrgAction.AlreadyExists || newItem.Action == OrgAction.NoRootFolder) newItem.Enable = false; else newItem.Enable = true; newItem.Category = matchFileCat; newItem.IsNewShow = newShow; return newItem; } else OnDebugNotificationd("Couldn't find episode for season " + seasonNum + " episods " + episodeNum1); } } // No match to TV show if (!tvOnlyCheck && !fast) { // Try to match to a movie OrgItem movieItem; if (CreateMovieAction(orgPath, matchString, out movieItem, threaded, fast, skipMatching, null)) noneItem.Clone(movieItem); } break; // Movie item case FileCategory.MovieVideo: // Create action OrgItem item; CreateMovieAction(orgPath, matchString, out item, threaded, fast, skipMatching, null); // If delete action created (for sample file) if (item.Action == OrgAction.Delete) return BuildDeleteAction(orgPath, fileCat); else if (item.Action != OrgAction.None) return item; break; // Trash case FileCategory.Trash: return BuildDeleteAction(orgPath, matchFileCat); // Ignore case FileCategory.Ignored: return new OrgItem(OrgAction.None, orgPath.Path, matchFileCat, orgPath.OrgFolder); // Unknown default: return new OrgItem(OrgAction.None, orgPath.Path, matchFileCat, orgPath.OrgFolder); } // Check for cancellation if (scanCanceled || procNumber < scanNumber) return noneItem; } // If no match on anything set none action return noneItem; }
/// <summary> /// Recursively run a scan on a set of movie folders and their sub-folders /// </summary> /// <param name="folders">Movie folder to perform scan on</param> /// <param name="scanResults">Scan results to build on.</param> /// <param name="queuedItems">Items already in the queue</param> private void RunScan(List<ContentRootFolder> folders, List<OrgItem> scanResults, List<OrgItem> queuedItems) { // Get unknown files (files not in content folder) from root folders OnProgressChange(ScanProcess.FileCollect, string.Empty, 0); List<OrgPath> files = GetUnknownFiles(folders); // Initialize item numbering int number = 0; // Go through unknwon files and try to match each file to a movie for (int i = 0; i < files.Count; i++) { // Check for cancellation if (scanCanceled) break; // Update progress OnProgressChange(ScanProcess.Movie, files[i].Path, (int)Math.Round((double)i / files.Count * 70)); // Categorize the file FileCategory fileCat = FileHelper.CategorizeFile(files[i], files[i].Path); // Check that video file (tv is okay, may match incorrectly) if (fileCat != FileCategory.MovieVideo && fileCat != FileCategory.TvVideo && fileCat != FileCategory.Trash) continue; // Check that file is not already in the queue bool alreadyQueued = false; foreach (OrgItem queued in queuedItems) if (queued.SourcePath == files[i].Path) { OrgItem newItem = new OrgItem(queued); newItem.Action = OrgAction.Queued; newItem.Number = number++; scanResults.Add(newItem); alreadyQueued = true; break; } if (alreadyQueued) continue; // Check for trash if (fileCat == FileCategory.Trash) { OrgItem delItem = new OrgItem(OrgAction.Delete, files[i].Path, fileCat, files[i].OrgFolder); scanResults.Add(delItem); continue; } // Try to match file to movie string search = Path.GetFileNameWithoutExtension(files[i].Path); Movie searchResult; bool searchSucess = SearchHelper.MovieSearch.ContentMatch(search, files[i].RootFolder.FullPath, string.Empty, false, true, out searchResult, null); // Add closest match item OrgItem item = new OrgItem(OrgAction.None, files[i].Path, fileCat, files[i].OrgFolder); item.Number = number++; if (searchSucess && !string.IsNullOrEmpty(searchResult.DatabaseName)) { item.Action = OrgAction.Move; item.DestinationPath = searchResult.BuildFilePath(files[i].Path); searchResult.Path = searchResult.BuildFolderPath(); item.Movie = searchResult; item.Enable = true; } scanResults.Add(item); } // Get knwon movie files (files from within content folders) files = GetKnownFiles(folders); // Go through each known file and check if renaming is needed for (int i = 0; i < files.Count; i++) { // Check for cancellation if (scanCanceled) break; // Update progress OnProgressChange(ScanProcess.Movie, files[i].Path, (int)Math.Round((double)i / files.Count * 20) + 70); // Categorize the file FileCategory fileCat = FileHelper.CategorizeFile(files[i], files[i].Path); // Check that video file (tv is okay, may match incorrectly) if (fileCat != FileCategory.MovieVideo && fileCat != FileCategory.TvVideo && fileCat != FileCategory.Trash) continue; // Check that movie is valide Movie movie = (Movie)files[i].Content; if (movie == null || string.IsNullOrEmpty(movie.DatabaseName)) continue; // Check that file is not already in the queue bool alreadyQueued = false; foreach (OrgItem queued in queuedItems) if (queued.SourcePath == files[i].Path) { alreadyQueued = true; break; } if (alreadyQueued) continue; // Check for trash if (fileCat == FileCategory.Trash) { OrgItem delItem = new OrgItem(OrgAction.Delete, files[i].Path, fileCat, files[i].OrgFolder); scanResults.Add(delItem); continue; } // Check if file needs to be renamed string newPath = movie.BuildFilePathNoFolderChanges(files[i].Path); if (newPath != files[i].Path && !File.Exists(newPath)) { // Add rename to results OrgItem item = new OrgItem(OrgAction.Rename, files[i].Path, FileCategory.MovieVideo, files[i].OrgFolder); item.Number = number++; if (Path.GetDirectoryName(newPath) != Path.GetDirectoryName(files[i].Path)) item.Action = OrgAction.Move; item.DestinationPath = newPath; item.Movie = movie; item.Enable = true; scanResults.Add(item); } } // Check if any movie folders need to be renamed! foreach (Movie movie in Organization.GetContentFromRootFolders(folders)) { if (!string.IsNullOrEmpty(movie.DatabaseName) && movie.Path != movie.BuildFolderPath()) { OrgItem item = new OrgItem(OrgAction.Rename, movie.Path, FileCategory.Folder, movie, movie.BuildFolderPath(), null); item.Enable = true; item.Number = number++; scanResults.Add(item); } } // Update progress OnProgressChange(ScanProcess.Movie, string.Empty, 100); }
/// <summary> /// Compares two OrgItem instances by the movie /// </summary> /// <param name="x">The first item</param> /// <param name="y">The second item</param> /// <returns>Compare results of two items</returns> public static int CompareByMovie(OrgItem x, OrgItem y) { int sortResult; if (x == null) { if (y == null) sortResult = 0; else sortResult = -1; } else { if (y == null) sortResult = 1; else sortResult = Path.GetDirectoryName(x.Movie.DatabaseName).CompareTo(Path.GetDirectoryName(y.Movie.DatabaseName)); } if (sortResult == 0) return CompareBySourceFile(x, y); return SetSort(sortResult); }
/// <summary> /// Compares two OrgItem instances by the tv episode's show name /// </summary> /// <param name="x">The first item</param> /// <param name="y">The second item</param> /// <returns>Compare results of two items</returns> public static int CompareByShowName(OrgItem x, OrgItem y) { int sortResult; if (x == null) { if (y == null) sortResult = 0; else sortResult = -1; } else { if (y == null) sortResult = 1; else sortResult = x.TvEpisode.Show.CompareTo(y.TvEpisode.Show); } if (sortResult == 0) return CompareBySeasonNumber(x, y); return SetSort(sortResult); }
/// <summary> /// Action log loading work /// </summary> private static void LoadActionLog(object sender, DoWorkEventArgs e) { try { string path = Path.Combine(GetBasePath(false), ACTION_LOG_XML + ".xml"); if (File.Exists(path)) lock (ActionLogFileLock) { // Load XML XmlTextReader reader = new XmlTextReader(path); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(reader); // Load movies data List<OrgItem> loadActionLog = new List<OrgItem>(); XmlNodeList logNodes = xmlDoc.DocumentElement.ChildNodes; for (int i = 0; i < logNodes.Count; i++) { OnActionLogLoadProgressChange((int)(((double)i / logNodes.Count) * 100)); OrgItem item = new OrgItem(); if (item.Load(logNodes[i])) loadActionLog.Add(item); } reader.Close(); OnActionLogLoadProgressChange(100); lock (ActionLogLock) { ActionLog.Clear(); foreach (OrgItem item in loadActionLog) ActionLog.Add(item); } } } catch { } OnActionLogLoadComplete(); }
/// <summary> /// Action log loading work /// </summary> public static void LoadScanDirLog(object sender, DoWorkEventArgs e) { try { string path = Path.Combine(GetBasePath(false), DIR_SCAN_LOG_XML + ".xml"); List<OrgItem> loadScanDirLog = new List<OrgItem>(); if (File.Exists(path)) { lock (DirScanLogFileLock) { // Load XML XmlTextReader reader = new XmlTextReader(path); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(reader); // Load movies data XmlNodeList logNodes = xmlDoc.DocumentElement.ChildNodes; for (int i = 0; i < logNodes.Count; i++) { OrgItem item = new OrgItem(); if (item.Load(logNodes[i])) { if (File.Exists(item.SourcePath)) { for (int j = 0; j < Settings.ScanDirectories.Count; j++) if (item.sourcePath.ToLower().Contains(Settings.ScanDirectories[j].FolderPath.ToLower())) { loadScanDirLog.Add(item); break; } } } } reader.Close(); } lock (DirScanLogLock) { DirScanLog.Clear(); foreach (OrgItem item in loadScanDirLog) DirScanLog.Add(item); } } } catch { } }
/// <summary> /// Adds item to log. /// </summary> /// <param name="item"></param> public static void AddDirScanLogItem(OrgItem item) { lock (DirScanLogLock) DirScanLog.Insert(0, item); SaveDirScanLog(); }
/// <summary> /// Adds item to log. /// </summary> /// <param name="item"></param> public static void AddActionLogItem(OrgItem item) { lock (ActionLogLock) ActionLog.Insert(0, item); SaveActionLog(); }
public bool BuildFolderMoveItem(string folderPath, OrgFolder scanDir, out OrgItem item) { item = new OrgItem(folderPath, this, scanDir, true); if (!this.MoveFolder) return false; string[] fileList = Directory.GetFiles(folderPath); foreach (string file in fileList) { OrgItem fileItem; if (this.BuildFileMoveItem(file, scanDir, out fileItem)) return true; } string[] subDirs = Directory.GetDirectories(folderPath); foreach (string subDir in subDirs) { OrgItem subItem; if (this.BuildFolderMoveItem(subDir, scanDir, out subItem)) return true; } return false; }
/// <summary> /// Compares two OrgItem instances by the folder of destination path /// </summary> /// <param name="x">The first item</param> /// <param name="y">The second item</param> /// <returns>Compare results of two items</returns> public static int CompareByDestinationFolder(OrgItem x, OrgItem y) { int sortResult; if (x == null) { if (y == null) sortResult = 0; else sortResult = -1; } else { if (y == null) sortResult = 1; else { string xStr = "", yStr = ""; if (x.DestinationPath != FileHelper.DELETE_DIRECTORY) xStr = Path.GetFileName(x.DestinationPath); else xStr = x.DestinationPath; if (y.DestinationPath != FileHelper.DELETE_DIRECTORY) yStr = Path.GetFileName(y.DestinationPath); else yStr = y.DestinationPath; sortResult = xStr.CompareTo(yStr); } } if (sortResult == 0) return CompareByDestinationFile(x, y); return SetSort(sortResult); }
/// <summary> /// Compares two OrgItem instances by the tv episode's number /// </summary> /// <param name="x">The first item</param> /// <param name="y">The second item</param> /// <returns>Compare results of two items</returns> public static int CompareByEpisodeNumber(OrgItem x, OrgItem y) { int sortResult; if (x == null) { if (y == null) sortResult = 0; else sortResult = -1; } else { if (y == null) sortResult = 1; else sortResult = x.TvEpisode.DisplayNumber.CompareTo(y.TvEpisode.DisplayNumber); } if (sortResult == 0) return CompareBySourceFile(x, y); return SetSort(sortResult); }
/// <summary> /// Compares two OrgItem instances by the source path /// </summary> /// <param name="x">The first item</param> /// <param name="y">The second item</param> /// <returns>Compare results of two items</returns> public static int CompareBySourceFile(OrgItem x, OrgItem y) { int sortResult; if (x == null) { if (y == null) sortResult = 0; else sortResult = -1; } else { if (y == null) sortResult = 1; else sortResult = Path.GetFileName(x.SourcePath).CompareTo(Path.GetFileName(y.SourcePath)); } return SetSort(sortResult); }
/// <summary> /// Compares two OrgItem instances by the action /// </summary> /// <param name="x">The first item</param> /// <param name="y">The second item</param> /// <returns>Compare results of two items</returns> public static int CompareByNumber(OrgItem x, OrgItem y) { int sortResult; if (x == null) { if (y == null) sortResult = 0; else sortResult = -1; } else { if (y == null) sortResult = 1; else sortResult = x.Number.CompareTo(y.Number); } return SetSort(sortResult); }
/// <summary> /// Compares two OrgItem instances by the folder of source /// </summary> /// <param name="x">The first item</param> /// <param name="y">The second item</param> /// <returns>Compare results of two items</returns> public static int CompareBySourceFolder(OrgItem x, OrgItem y) { int sortResult; if (x == null || string.IsNullOrEmpty(x.SourcePath)) { if (y == null || string.IsNullOrEmpty(y.SourcePath)) sortResult = 0; else sortResult = -1; } else { if (y == null || string.IsNullOrEmpty(y.SourcePath)) sortResult = 1; else sortResult = Path.GetDirectoryName(x.SourcePath).CompareTo(Path.GetDirectoryName(y.SourcePath)); } if (sortResult == 0) return CompareBySourceFile(x, y); return SetSort(sortResult); }
private void DeleteContent() { if (MessageBox.Show("Are you want to delete the selected items? This operation cannot be undone", "Sure?", MessageBoxButton.YesNo) == MessageBoxResult.Yes) { List<OrgItem> items = new List<OrgItem>(); foreach (Content content in this.SelectedContents) { OrgItem item = new OrgItem(OrgAction.Delete, content.Path, content, null); items.Add(item); } OnItemsToQueue(items); } }
/// <summary> /// Compares two OrgItem instances by the status /// </summary> /// <param name="x">The first item</param> /// <param name="y">The second item</param> /// <returns>Compare results of two items</returns> public static int CompareByStatus(OrgItem x, OrgItem y) { int sortResult; if (x == null) { if (y == null) sortResult = 0; else sortResult = -1; } else { if (y == null) sortResult = 1; else sortResult = x.Status.ToString().CompareTo(y.Status.ToString()); } if (sortResult == 0) return CompareByShowName(x, y); return SetSort(sortResult); }
/// <summary> /// Open file dialog so user can locate episode in file directory. /// </summary> /// <param name="showActionModifer">Whether to display action modifier after path is selected</param> /// <param name="copyAction">Whether to copy file, move otherwise</param> /// <param name="items">Organization items to add move/copy action to once located</param> /// <returns>true if locate was sucessful</returns> public bool UserLocate(bool showActionModifer, bool copyAction, out List<OrgItem> items) { // Initialize org items items = new List<OrgItem>(); // Open file dialog VistaOpenFileDialog ofd = new VistaOpenFileDialog(); ofd.Filter = "All Files|*.*"; if (!(bool)ofd.ShowDialog()) return false; // Try to get episode information from file int fileEpSeason, fileEpNumber1, fileEpNumber2; bool fileInfoFound = FileHelper.GetEpisodeInfo(ofd.FileName, this.Show.DatabaseName, out fileEpSeason, out fileEpNumber1, out fileEpNumber2); // Assign episodes TvEpisode ep1 = this; TvEpisode ep2 = null; // Locate could be for double episode file, only taken if one of the episode from file matches selected if (fileInfoFound && fileEpSeason == this.Season) { if (fileEpNumber1 == this.DisplayNumber) { if (fileEpNumber2 > 0) show.FindEpisode(ep1.Season, fileEpNumber2, false, out ep2); else ep2 = null; } else if (fileEpNumber2 == this.DisplayNumber) { if (fileEpNumber1 > 0 && show.FindEpisode(this.Season, fileEpNumber1, false, out ep1)) ep2 = this; else ep1 = this; } } // Build org item OrgAction action = copyAction ? OrgAction.Copy : OrgAction.Move; string destination = show.BuildFilePath(ep1, ep2, Path.GetExtension(ofd.FileName)); OrgItem item = new OrgItem(OrgStatus.Found, action, ofd.FileName, destination, ep1, ep2, FileCategory.TvVideo, null); // Display modifier if (showActionModifer) { OrgItemEditorWindow editor = new OrgItemEditorWindow(item); editor.ShowDialog(); // Add results if valid if (editor.Results == null) return false; items.Add(editor.Results); return true; } items.Add(item); return true; }
/// <summary> /// Update current update from another item's data /// </summary> /// <param name="item">item to be copied</param> public void Clone(OrgItem item) { this.Status = item.Status; this.Progress = 0; this.Action = item.Action; this.SourcePath = item.SourcePath; this.DestinationPath = item.DestinationPath; this.TvEpisode = item.TvEpisode; this.TvEpisode2 = item.TvEpisode2; this.TorrentTvEpisode = item.TorrentTvEpisode; this.Category = item.Category; this.Enable = item.Enable; this.Movie = item.Movie; this.ScanDirectory = item.ScanDirectory; this.Replace = item.Replace; this.Number = item.Number; this.QueueStatus = item.QueueStatus; this.ActionComplete = item.ActionComplete; this.Notes = item.Notes; this.ActionTime = item.ActionTime; }
/// <summary> /// Creates a delete action for a file. /// </summary> /// <param name="scanResults">The current scan action list to add action to.</param> /// <param name="file">The file to be deleted</param> /// <param name="fileCat">The category of the file</param> private OrgItem BuildDeleteAction(OrgPath file, FileCategory fileCat) { OrgItem newItem; if (file.AllowDelete) { newItem = new OrgItem(OrgAction.Delete, file.Path, fileCat, file.OrgFolder); newItem.Enable = true; } else { newItem = new OrgItem(OrgAction.None, file.Path, fileCat, file.OrgFolder); } return newItem; }
/// <summary> /// Constructor for copying item. /// </summary> /// <param name="item">item to be copied</param> public OrgItem(OrgItem item) { Clone(item); }
/// <summary> /// Directory scan processing method (thread) for a single file path. /// </summary> /// <param name="orgPath">Organization path instance to be processed</param> /// <param name="pathNum">The path's number out of total being processed</param> /// <param name="totalPaths">Total number of paths being processed</param> /// <param name="updateNumber">The identifier for the OrgProcessing instance</param> /// <param name="background">Whether processing is running as a background operation</param> /// <param name="subSearch">Whether processing is sub-search(TV only)</param> /// <param name="processComplete">Delegate to be called by processing when completed</param> /// <param name="numItemsProcessed">Number of paths that have been processed - used for progress updates</param> private void ThreadProcess(OrgPath orgPath, int pathNum, int totalPaths, int updateNumber, ref int numItemsProcessed, ref int numItemsStarted, object processSpecificArgs) { // Process specific arguments object[] args = (object[])processSpecificArgs; bool tvOnlyCheck = (bool)args[0]; bool skipMatching = (bool)args[1]; bool fast = (bool)args[2]; int procNumber = (int)args[3]; int pass = (int)args[4]; bool reuseResults = (bool)args[5]; // Check if item is already processed if (this.Items[pathNum].Action != OrgAction.TBD) return; // Check if file is in the queue bool alreadyQueued = false; if (itemsInQueue != null) for (int i = 0; i < itemsInQueue.Count; i++) if (itemsInQueue[i].SourcePath == orgPath.Path) { OrgItem newItem = new OrgItem(itemsInQueue[i]); newItem.Action = OrgAction.Queued; newItem.Enable = true; UpdateResult(newItem, pathNum, procNumber); alreadyQueued = true; break; } // If item is already in the queue, skip it if (alreadyQueued) ProcessUpdate(orgPath.Path, totalPaths, pass); else { // Update progress lock (directoryScanLock) this.Items[pathNum].Action = OrgAction.Processing; // Process path bool fromLog; OrgItem results = ProcessPath(orgPath, tvOnlyCheck, skipMatching || (!fast && pass == 0), fast || pass == 0, true, procNumber, reuseResults, out fromLog); // Update results and progress if (results != null && (results.Action != OrgAction.None || results.Category == FileCategory.Ignored || fast || pass == 1)) { UpdateResult(results, pathNum, procNumber); ProcessUpdate(orgPath.Path, totalPaths, pass); if (!fromLog && (results.Action != OrgAction.None && (results.Category == FileCategory.MovieVideo || results.Category == FileCategory.TvVideo))) { Organization.AddDirScanLogItem(new OrgItem(results)); } } else lock (directoryScanLock) this.Items[pathNum].Action = OrgAction.TBD; } }
/// <summary> /// Compares two OrgItem instances by the category /// </summary> /// <param name="x">The first item</param> /// <param name="y">The second item</param> /// <returns>Compare results of two items</returns> public static int CompareByCategory(OrgItem x, OrgItem y) { int sortResult; if (x == null) { if (y == null) sortResult = 0; else sortResult = -1; } else { if (y == null) sortResult = 1; else sortResult = x.Category.ToString().CompareTo(y.Category.ToString()); } if (sortResult == 0) return CompareBySourceFile(x, y); return SetSort(sortResult); }
/// <summary> /// Add item to directory scan results list in dictionary. Variables accessed by multiple threads, so controlled. /// </summary> /// <param name="scanNum">The scan number to add item to</param> /// <param name="item">Item to add to results list</param> private void UpdateResult(OrgItem item, int pathNum, int procNum) { if (scanCanceled || procNum < scanNumber) return; lock (directoryScanLock) this.Items[pathNum].Clone(item); }
/// <summary> /// Compares two OrgItem instances by the date time of action /// </summary> /// <param name="x">The first item</param> /// <param name="y">The second item</param> /// <returns>Compare results of two items</returns> public static int CompareByDateTime(OrgItem x, OrgItem y) { int sortResult; if (x == null) { if (y == null) sortResult = 0; else sortResult = -1; } else { if (y == null) sortResult = 1; else sortResult = x.ActionTime.CompareTo(y.ActionTime); } return SetSort(sortResult); }