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); }
void worker_DoWork(object sender, DoWorkEventArgs e) { bool custom = (bool)e.Argument; OrgPath path; if (custom) { string matchTo = this.MatchString; if (!this.MatchString.Contains('.')) { matchTo += ".avi"; } path = new OrgPath(matchTo, false, true, new OrgFolder()); } else { path = this.SelectedScanDirPath; } App.Current.Dispatcher.BeginInvoke((Action) delegate { this.MatchProcessing.Clear(); }); bool fromLog; OrgItem item = scan.ProcessPath(path, false, false, false, false, 0, false, out fromLog); App.Current.Dispatcher.BeginInvoke((Action) delegate { this.MatchProcessing.Add("Final result: " + item.ToString()); }); }
private void GetTorrent() { List <TvEpisode> selEpisodes = new List <TvEpisode>(); foreach (TvEpisode episode in this.SelectedEpisodes) { selEpisodes.Add(episode); } List <string> unmatchedEps = new List <string>(); List <OrgItem> items = new List <OrgItem>(); for (int i = 0; i < selEpisodes.Count; i++) { OrgItem newItem = new OrgItem(OrgStatus.Missing, OrgAction.Torrent, selEpisodes[i], null, FileCategory.TvVideo, null); newItem.BuildDestination(); items.Add(newItem); } if (items.Count > 0) { OnItemsToQueue(items); } }
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); }
public void MoveDownSelectedItems() { if (this.SelectedOrgItems == null) { return; } bool roomToMove = false; for (int i = this.OrgItems.Count - 1; i >= 0; i--) { OrgItem item = this.OrgItems[i]; if (this.SelectedOrgItems.Contains(item)) { if (!roomToMove) { continue; } this.OrgItems.Remove(item); this.OrgItems.Insert(i + 1, item); } else { roomToMove = true; } } }
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); }
/// <summary> /// Triggers QueueItemsComplete event. /// </summary> /// <param name="item"></param> protected void OnQueueItemsComplete(OrgItem item) { OrgItem newItem = new OrgItem(item); newItem.QueueStatus = OrgQueueStatus.Enabled; if (QueueItemsComplete != null) { QueueItemsComplete(this, new QueueItemsCompleteArgs(newItem)); } }
/// <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); }
private bool RemoveQueueItemIfNeeded(OrgItem item) { bool doRemove = item.QueueStatus == OrgQueueStatus.Completed && Settings.GuiControl.AutoClearCompleted; if (doRemove) { RemoveQueueItem(item); } return(doRemove); }
/// <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 { } }
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); } }
private void RemoveQueueItemSafe(OrgItem item) { if (App.Current.Dispatcher.CheckAccess()) { RemoveQueueItem(item); } else { App.Current.Dispatcher.BeginInvoke((Action) delegate { RemoveQueueItem(item); }); } }
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; }
private void RemoveSelectedItems() { Organization.ActionLog.CollectionChanged -= ActionLog_CollectionChanged; for (int i = this.SelectedOrgItems.Count - 1; i >= 0; i--) { OrgItem item = this.SelectedOrgItems[i] as OrgItem; if (Organization.ActionLog.Contains(item)) { Organization.ActionLog.Remove(item); } this.OrgItems.Remove(item); } Organization.SaveActionLog(); Organization.ActionLog.CollectionChanged += ActionLog_CollectionChanged; }
public IList <OrgValue> AddOrgItem(IList <OrgValue> source, OrgItem item, string parentCode, int deep) { if (source == null) { source = new List <OrgValue>(); } source.Add(new OrgValue { Code = item.Idx.ToString(), Name = item.Name, Deep = deep, Parent = parentCode }); return(source); }
/// <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); }
private bool RemoveQueueItemIfNeededSafe(OrgItem item) { if (App.Current.Dispatcher.CheckAccess()) { return(RemoveQueueItemIfNeeded(item)); } else { bool removed = false; App.Current.Dispatcher.Invoke((Action) delegate { removed = RemoveQueueItemIfNeeded(item); }); return(removed); } }
/// <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(); }
protected bool FilterItem(object obj) { OrgItem item = obj as OrgItem; // Action filter if ((int)(item.Action & this.ActionFilter) == 0) { return(false); } // Category filter if ((int)(item.Category & this.CategoryFilter) == 0) { return(false); } return(true); }
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); }
/// <summary> /// Update progress bar when queue item action progress changes /// </summary> /// <param name="sender">OrgItem</param> /// <param name="e">Progress args</param> private void item_ActionProgressChanged(object sender, ProgressChangedEventArgs e) { // Set progress bar message OrgItem item = (OrgItem)sender; string actionStr = string.Empty; switch (item.Action) { case OrgAction.Copy: actionStr = "Copying"; break; case OrgAction.Delete: actionStr = "Deleting"; break; case OrgAction.Move: actionStr = "Moving"; break; case OrgAction.Rename: actionStr = "Renaming"; break; default: actionStr = "Processing"; break; } string msg = actionStr + " '" + System.IO.Path.GetFileName(item.SourcePath) + "'"; if (e.ProgressPercentage == this.Progress && msg == this.ProgressMessage) { return; } this.UpdateProgressSafe(e.ProgressPercentage, msg); }
private void EditSelectedItem() { OrgItem selItem = (this.SelectedOrgItems[0] as OrgItem); OrgItemEditorWindow editor = new OrgItemEditorWindow(selItem); editor.ShowDialog(); if (editor.Results != null) { selItem.Clone(editor.Results); } else { return; } if (selItem.Action != OrgAction.None) { selItem.Enable = true; } // Automatically apply the movie to unknown items with similar names if (lastRunScan == ScanType.Directory && selItem.Category == FileCategory.MovieVideo && (selItem.Action == OrgAction.Move || selItem.Action == OrgAction.Copy)) { foreach (OrgItem item in this.OrgItems) { if (FileHelper.PathsVerySimilar(item.SourcePath, selItem.SourcePath)) { item.Movie = selItem.Movie; item.DestinationPath = item.Movie.BuildFilePath(item.SourcePath); item.Action = selItem.Action; item.Enable = true; } } } }
public void MoveSelectedItemToTop() { if (this.SelectedOrgItems == null) { return; } int topPos = 0; for (int i = 0; i < this.OrgItems.Count; i++) { OrgItem item = this.OrgItems[i]; if (!this.SelectedOrgItems.Contains(item)) { continue; } if (i != topPos) { this.OrgItems.Remove(item); this.OrgItems.Insert(topPos++, item); } } }
public void MoveSelectedItemToBottom() { if (this.SelectedOrgItems == null) { return; } int botPos = this.OrgItems.Count - 1; for (int i = this.OrgItems.Count - 1; i >= 0; i--) { OrgItem item = this.OrgItems[i]; if (!this.SelectedOrgItems.Contains(item)) { continue; } if (i != botPos) { this.OrgItems.Remove(item); this.OrgItems.Insert(botPos--, item); } } }
private void UndoSelectedItems() { string message = string.Empty; List <OrgItem> undoActions = new List <OrgItem>(); for (int i = 0; i < this.SelectedOrgItems.Count; i++) { // Get item OrgItem logItem = this.SelectedOrgItems[i] as OrgItem; // Create action with reversed source and destination OrgItem undoAction = new OrgItem(logItem); undoAction.SourcePath = logItem.DestinationPath; undoAction.DestinationPath = logItem.SourcePath; switch (logItem.Action) { //If original file still exists, just delete the copy, otherwise move back to original case OrgAction.Copy: if (System.IO.File.Exists(logItem.SourcePath)) { undoAction.Action = OrgAction.Delete; undoAction.DestinationPath = string.Empty; } else { undoAction.Action = OrgAction.Move; } break; // Move and rename need no changes case OrgAction.Move: case OrgAction.Rename: break; // All other actions are not revesible default: undoAction = null; string fileName = logItem.Action == OrgAction.Delete ? logItem.SourcePath : logItem.DestinationPath; message += "Action for file '" + fileName + "' cannot be undone -" + logItem.Action.ToString() + " actions are not reversible" + Environment.NewLine; break; } // Check that undo item is valid if (undoAction != null) { // Verify that file still exists if (System.IO.File.Exists(undoAction.SourcePath)) { // Check that file is already added to undo list bool alreadyAdded = false; foreach (OrgItem item in undoActions) { if (item.SourcePath == undoAction.SourcePath) { alreadyAdded = true; break; } } if (!alreadyAdded) { undoActions.Add(undoAction); } } else { message += "Action for file '" + logItem.DestinationPath + "' cannot be undone - file no longer exists!" + Environment.NewLine; } } } if (!string.IsNullOrWhiteSpace(message)) { MessageBox.Show(message.TrimEnd()); } if (undoActions.Count > 0) { OnItemsToQueue(undoActions); } }
/// <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 <Content> shows, List <OrgItem> queuedItems, bool fast) { // Set running flag scanRunning = true; cancelRequested = false; // Do directory check on all directories (to look for missing episodes) while (!TvItemInScanDirHelper.Initialized) { Thread.Sleep(100); } List <OrgItem> directoryItems = TvItemInScanDirHelper.Items; // Initialiaze scan items List <OrgItem> missingCheckItem = new List <OrgItem>(); // Initialize item numbers int number = 0; double progressPerShow = 1D / shows.Count * 100D; // Go through each show for (int i = 0; i < shows.Count; i++) { TvShow show = (TvShow)shows[i]; if (cancelRequested) { break; } double showsProgress = (double)i * progressPerShow; OnProgressChange(ScanProcess.TvMissing, shows[i].DatabaseName, (int)Math.Round(showsProgress)); double progressPerEp = 1D / show.Episodes.Count * progressPerShow; // Go through missing episodes for (int j = 0; j < show.Episodes.Count; j++) { // Get episode TvEpisode ep = show.Episodes[j]; // Update progress OnProgressChange(ScanProcess.TvMissing, shows[i].DatabaseName, (int)Math.Round(showsProgress + j * progressPerEp)); // Check for cancellation if (cancelRequested) { break; } // Skipped ignored episodes if (ep.Ignored || !show.DoMissingCheck) { continue; } // Init found flag bool found = false; // Check if episode is missing if (ep.Missing == MissingStatus.Missing || ep.Missing == MissingStatus.InScanDirectory) { // Check directory item for episode foreach (OrgItem item in directoryItems) { if ((item.Action == OrgAction.Move || item.Action == OrgAction.Copy) && item.TvEpisode != null && item.TvEpisode.Show.DatabaseName == show.DatabaseName) { // Only add item for first part of multi-part file if (ep.Equals(item.TvEpisode)) { OrgItem newItem = new OrgItem(OrgStatus.Found, item.Action, item.SourcePath, item.DestinationPath, ep, item.TvEpisode2, FileCategory.TvVideo, item.ScanDirectory); newItem.Enable = true; newItem.Number = number++; if (!show.DoMissingCheck) { newItem.Category = FileCategory.Ignored; } missingCheckItem.Add(newItem); found = true; break; } else if (ep.Equals(item.TvEpisode2)) { found = true; break; } } } } else { continue; } // Add empty item for missing if (!found && ep.Aired && show.DoMissingCheck) { OrgItem newItem; TvEpisodeTorrent ezTvEpisode = TvTorrentHelper.GetEpisodeTorrent(ep); if (ezTvEpisode != null) { newItem = new OrgItem(OrgStatus.Missing, OrgAction.Torrent, ep, null, FileCategory.TvVideo, null); newItem.BuildDestination(); } else { newItem = new OrgItem(OrgStatus.Missing, OrgAction.None, ep, null, FileCategory.TvVideo, null); } newItem.Number = number++; missingCheckItem.Add(newItem); } } } // Update progress OnProgressChange(ScanProcess.TvMissing, string.Empty, 100); // Clear flags scanRunning = false; // Return results return(missingCheckItem); }
/// <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> /// 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; } } }
public OrgListItem(OrgItem orgItem, Dictionary<OrgColumnType, OrgItemColumn> lvColumns) { this.OrgItem = orgItem; this.ListItem = new ListViewItem(); UpdateListViewItem(lvColumns); }