public Initialize ( int cFiles, string sOldDir, string sNewDir, IHelpTopicProvider helpTopicProvider ) : void | ||
cFiles | int | |
sOldDir | string | |
sNewDir | string | |
helpTopicProvider | IHelpTopicProvider | |
return | void |
/// ------------------------------------------------------------------------------------ /// <summary> /// Handle changes to the LinkedFiles root directory for a language project. /// </summary> /// <param name="sOldLinkedFilesRootDir">The old LinkedFiles root directory.</param> /// <returns></returns> /// <remarks>This may not be the best place for this method, but I'm not sure there is a /// "best place".</remarks> /// ------------------------------------------------------------------------------------ public bool UpdateExternalLinks(string sOldLinkedFilesRootDir) { ILangProject lp = Cache.LanguageProject; string sNewLinkedFilesRootDir = lp.LinkedFilesRootDir; if (!FileUtils.PathsAreEqual(sNewLinkedFilesRootDir, sOldLinkedFilesRootDir)) { List<string> rgFilesToMove = new List<string>(); // TODO: offer to move or copy existing files. foreach (ICmFolder cf in lp.MediaOC) CollectMovableFilesFromFolder(cf, rgFilesToMove, sOldLinkedFilesRootDir, sNewLinkedFilesRootDir); foreach (ICmFolder cf in lp.PicturesOC) CollectMovableFilesFromFolder(cf, rgFilesToMove, sOldLinkedFilesRootDir, sNewLinkedFilesRootDir); //Get the files which are pointed to by links in TsStrings CollectMovableFilesFromFolder(lp.FilePathsInTsStringsOA, rgFilesToMove, sOldLinkedFilesRootDir, sNewLinkedFilesRootDir); var hyperlinks = StringServices.GetHyperlinksInFolder(Cache, sOldLinkedFilesRootDir); foreach (var linkInfo in hyperlinks) { if (!rgFilesToMove.Contains(linkInfo.RelativePath) && FileUtils.SimilarFileExists(Path.Combine(sOldLinkedFilesRootDir, linkInfo.RelativePath)) && !FileUtils.SimilarFileExists(Path.Combine(sNewLinkedFilesRootDir, linkInfo.RelativePath))) { rgFilesToMove.Add(linkInfo.RelativePath); } } if (rgFilesToMove.Count > 0) { FileLocationChoice action; using (MoveOrCopyFilesDlg dlg = new MoveOrCopyFilesDlg()) // REVIEW (Hasso) 2015.08: should this go in MoveOrCopyFilesController? { dlg.Initialize(rgFilesToMove.Count, sOldLinkedFilesRootDir, sNewLinkedFilesRootDir, this); DialogResult res = dlg.ShowDialog(); Debug.Assert(res == DialogResult.OK); if (res != DialogResult.OK) return false; // should never happen! action = dlg.Choice; } if (action == FileLocationChoice.Leave) // Expand path { NonUndoableUnitOfWorkHelper.Do(Cache.ActionHandlerAccessor, () => { foreach (ICmFolder cf in lp.MediaOC) ExpandToFullPath(cf, sOldLinkedFilesRootDir, sNewLinkedFilesRootDir); foreach (ICmFolder cf in lp.PicturesOC) ExpandToFullPath(cf, sOldLinkedFilesRootDir, sNewLinkedFilesRootDir); }); // Hyperlinks are always already full paths. return false; } List<string> rgLockedFiles = new List<string>(); foreach (string sFile in rgFilesToMove) { string sOldPathname = Path.Combine(sOldLinkedFilesRootDir, sFile); string sNewPathname = Path.Combine(sNewLinkedFilesRootDir, sFile); string sNewDir = Path.GetDirectoryName(sNewPathname); if (!Directory.Exists(sNewDir)) Directory.CreateDirectory(sNewDir); Debug.Assert(FileUtils.TrySimilarFileExists(sOldPathname, out sOldPathname)); if (FileUtils.TrySimilarFileExists(sNewPathname, out sNewPathname)) File.Delete(sNewPathname); try { if (action == FileLocationChoice.Move) { //LT-13343 do copy followed by delete to ensure the file gets put in the new location. //If the current FLEX record has a picture displayed the File.Delete will fail. File.Copy(sOldPathname, sNewPathname); File.Delete(sOldPathname); } else File.Copy(sOldPathname, sNewPathname); } catch (Exception ex) { Debug.WriteLine(String.Format("{0}: {1}", ex.Message, sOldPathname)); rgLockedFiles.Add(sFile); } } NonUndoableUnitOfWorkHelper.DoUsingNewOrCurrentUOW(Cache.ActionHandlerAccessor, () => StringServices.FixHyperlinkFolder(hyperlinks, sOldLinkedFilesRootDir, sNewLinkedFilesRootDir)); // If any files failed to be moved or copied above, try again now that we've // opened a new window and had more time elapse (and more demand to reuse // memory) since the failure. if (rgLockedFiles.Count > 0) { GC.Collect(); // make sure the window is disposed! Thread.Sleep(1000); foreach (string sFile in rgLockedFiles) { string sOldPathname = Path.Combine(sOldLinkedFilesRootDir, sFile); string sNewPathname = Path.Combine(sNewLinkedFilesRootDir, sFile); try { if (action == FileLocationChoice.Move) FileUtils.Move(sOldPathname, sNewPathname); else File.Copy(sOldPathname, sNewPathname); } catch (Exception ex) { Debug.WriteLine(String.Format("{0}: {1} (SECOND ATTEMPT)", ex.Message, sOldPathname)); } } } return true; } } return false; }
/// <summary> /// Handle changes to the external links root directory for a language project. /// </summary> /// <param name="sOldExtLinkRootDir"></param> /// <param name="proj"></param> /// <remarks>This may not be the best place for this method, but I'm not sure there is a /// "best place".</remarks> public static bool UpdateExternalLinks(string sOldExtLinkRootDir, ILangProject proj) { string sNewExtLinkRootDir = proj.ExtLinkRootDir; // caseless comparison may not be valid on non-Microsoft OS! if (!sNewExtLinkRootDir.Equals(sOldExtLinkRootDir, StringComparison.InvariantCultureIgnoreCase)) { List<string> rgFilesToMove = new List<string>(); // TODO: offer to move or copy existing files. foreach (ICmFolder cf in proj.MediaOC) CollectMovableFilesFromFolder(cf, rgFilesToMove, sOldExtLinkRootDir, sNewExtLinkRootDir); foreach (ICmFolder cf in proj.PicturesOC) CollectMovableFilesFromFolder(cf, rgFilesToMove, sOldExtLinkRootDir, sNewExtLinkRootDir); if (rgFilesToMove.Count > 0) { FileLocationChoice action; using (MoveOrCopyFilesDlg dlg = new MoveOrCopyFilesDlg()) { dlg.Initialize(rgFilesToMove.Count, sOldExtLinkRootDir, sNewExtLinkRootDir, FwApp.App); DialogResult res = dlg.ShowDialog(); Debug.Assert(res == DialogResult.OK); if (res != DialogResult.OK) return false; // should never happen! action = dlg.Choice; } if (action == FileLocationChoice.Leave) // Expand path { foreach (ICmFolder cf in proj.MediaOC) ExpandToFullPath(cf, sOldExtLinkRootDir, sNewExtLinkRootDir); foreach (ICmFolder cf in proj.PicturesOC) ExpandToFullPath(cf, sOldExtLinkRootDir, sNewExtLinkRootDir); return false; } // We need to ensure that none of the picture files is currently being // displayed, as that locks the file. The easiest way to achieve this is // to shutdown the main window while we're moving the files. string sServer = proj.Cache.ServerName; string sDbname = proj.Cache.DatabaseName; FwApp.App.CloseDbAndWindows(sServer, sDbname, false); GC.Collect(); // make sure the window is disposed! Thread.Sleep(1000); List<string> rgLockedFiles = new List<string>(); foreach (string sFile in rgFilesToMove) { string sOldPathname = Path.Combine(sOldExtLinkRootDir, sFile); string sNewPathname = Path.Combine(sNewExtLinkRootDir, sFile); string sNewDir = Path.GetDirectoryName(sNewPathname); if (!Directory.Exists(sNewDir)) Directory.CreateDirectory(sNewDir); Debug.Assert(File.Exists(sOldPathname)); Debug.Assert(!File.Exists(sNewPathname)); try { if (action == FileLocationChoice.Move) File.Move(sOldPathname, sNewPathname); else File.Copy(sOldPathname, sNewPathname); } catch (Exception ex) { Debug.WriteLine(String.Format("{0}: {1}", ex.Message, sOldPathname)); rgLockedFiles.Add(sFile); } } FwApp.App.ReopenDbAndOneWindow(sServer, sDbname); // If any files failed to be moved or copied above, try again now that we've // opened a new window and had more time elapse (and more demand to reuse // memory) since the failure. if (rgLockedFiles.Count > 0) { GC.Collect(); // make sure the window is disposed! Thread.Sleep(1000); foreach (string sFile in rgLockedFiles) { string sOldPathname = Path.Combine(sOldExtLinkRootDir, sFile); string sNewPathname = Path.Combine(sNewExtLinkRootDir, sFile); try { if (action == FileLocationChoice.Move) File.Move(sOldPathname, sNewPathname); else File.Copy(sOldPathname, sNewPathname); } catch (Exception ex) { Debug.WriteLine(String.Format("{0}: {1} (SECOND ATTEMPT)", ex.Message, sOldPathname)); } } } return true; } } return false; }