public bool FileOperation(FileOperations mode, string from, string to, string newName, bool recycle) { Application.Current.Properties[nameof(AppProps.FileOperationResult)] = new Dictionary<string, string>(); //Copy, Move or delete selected MediaItems or folder using (FileOperation fo = new FileOperation(new PicFileOperationProgressSink())) { var flags = FileOperationFlags.FOF_NOCONFIRMMKDIR | (recycle ? FileOperationFlags.FOFX_RECYCLEONDELETE : FileOperationFlags.FOF_WANTNUKEWARNING); fo.SetOperationFlags(flags); if (from == null) { //MediaItems foreach (var mi in MediaItems.Items.Where(x => x.IsSelected)) { switch (mode) { case FileOperations.Copy: { fo.CopyItem(mi.FilePath, to, mi.FileNameWithExt); break; } case FileOperations.Move: { fo.MoveItem(mi.FilePath, to, mi.FileNameWithExt); break; } case FileOperations.Delete: { fo.DeleteItem(mi.FilePath); break; } } } } else { //Folders switch (mode) { case FileOperations.Copy: { fo.CopyItem(from, to, newName); break; } case FileOperations.Move: { fo.MoveItem(from, to, newName); break; } case FileOperations.Delete: { fo.DeleteItem(from); break; } } } fo.PerformOperations(); } var foResult = (Dictionary<string, string>)Application.Current.Properties[nameof(AppProps.FileOperationResult)]; if (foResult.Count == 0) return false; //update DB and thumbnail cache using (FileOperation fo = new FileOperation()) { fo.SetOperationFlags(FileOperationFlags.FOF_SILENT | FileOperationFlags.FOF_NOCONFIRMATION | FileOperationFlags.FOF_NOERRORUI | FileOperationFlags.FOFX_KEEPNEWERFILE); var cachePath = @Settings.Default.CachePath; var mItems = Db.MediaItems; var dirs = Db.Directories; if (mode == FileOperations.Delete) { var itemsToDel = new List<DataModel.MediaItem>(); if (from == null) { //delete by file/s foreach (var mi in MediaItems.Items.Where(x => x.IsSelected)) { if (File.Exists(mi.FilePath)) continue; var cacheFilePath = mi.FilePath.Replace(":\\", cachePath); if (!File.Exists(cacheFilePath)) continue; fo.DeleteItem(cacheFilePath); itemsToDel.Add(mi.Data); } } else { //delete by folder foreach (var dir in dirs.Where(x => x.Path.Equals(from) || x.Path.StartsWith(from + "\\"))) { foreach (var mi in mItems.Where(x => x.DirectoryId.Equals(dir.Id))) { var miFilePath = Path.Combine(dir.Path, mi.FileName); if (File.Exists(miFilePath)) continue; var cacheFilePath = miFilePath.Replace(":\\", cachePath); if (!File.Exists(cacheFilePath)) continue; fo.DeleteItem(cacheFilePath); itemsToDel.Add(mi); } } } foreach (var mi in itemsToDel) { foreach(var mik in Db.MediaItemKeywords.Where(x => x.MediaItemId == mi.Id)) { Db.DeleteOnSubmit(mik); } foreach (var mip in Db.MediaItemPeople.Where(x => x.MediaItemId == mi.Id)) { Db.DeleteOnSubmit(mip); } Db.DeleteOnSubmit(mi); } } if (mode == FileOperations.Copy || mode == FileOperations.Move) { foreach (var item in foResult) { if (MediaItems.SuportedExts.Any(ext => item.Value.EndsWith(ext, StringComparison.OrdinalIgnoreCase))) { if (!File.Exists(item.Value)) continue; var srcDirId = dirs.SingleOrDefault(x => x.Path.Equals(Path.GetDirectoryName(item.Key)))?.Id; if (srcDirId == null) continue; var srcPic = mItems.SingleOrDefault(x => x.DirectoryId == srcDirId && x.FileName == Path.GetFileName(item.Key)); if (srcPic == null) continue; //get destination directory or create it if doesn't exists var dirPath = Path.GetDirectoryName(item.Value); var destDirId = Db.InsertDirecotryInToDb(dirPath); #region Copy files if (mode == FileOperations.Copy) { //duplicate Picture var destPicId = Db.GetNextIdFor<DataModel.MediaItem>(); Db.InsertOnSubmit(new DataModel.MediaItem { Id = destPicId, DirectoryId = destDirId, FileName = Path.GetFileName(item.Value), Rating = srcPic.Rating, Comment = srcPic.Comment, Orientation = srcPic.Orientation }); //duplicate Picture Keywords foreach (var mik in Db.MediaItemKeywords.Where(x => x.MediaItemId == srcPic.Id)) { Db.InsertOnSubmit(new DataModel.MediaItemKeyword { Id = Db.GetNextIdFor<DataModel.MediaItemKeyword>(), KeywordId = mik.KeywordId, MediaItemId = destPicId }); } //duplicate Picture People foreach (var mip in Db.MediaItemPeople.Where(x => x.MediaItemId == srcPic.Id)) { Db.InsertOnSubmit(new DataModel.MediaItemPerson { Id = Db.GetNextIdFor<DataModel.MediaItemPerson>(), PersonId = mip.PersonId, MediaItemId = destPicId }); } //duplicate thumbnail fo.CopyItem(item.Key.Replace(":\\", cachePath), Path.GetDirectoryName(item.Value)?.Replace(":\\", cachePath), Path.GetFileName(item.Value)); } #endregion #region Move files if (mode == FileOperations.Move) { //BUG: if the file already exists in the destination directory, FileOperation returns COPYENGINE_S_USER_IGNORED and source thumbnail file is not deleted srcPic.DirectoryId = destDirId; srcPic.FileName = Path.GetFileName(item.Value); Db.UpdateOnSubmit(srcPic); //delete empty directory if (mItems.Count(x => x.DirectoryId.Equals(srcDirId)) == 0) { var emptyDir = dirs.SingleOrDefault(x => x.Id.Equals(srcDirId)); if (emptyDir != null) { Db.DeleteOnSubmit(emptyDir); } } //move thumbnail fo.MoveItem(item.Key.Replace(":\\", cachePath), Path.GetDirectoryName(item.Value)?.Replace(":\\", cachePath), Path.GetFileName(item.Value)); } #endregion } else { #region Move directories if (mode == FileOperations.Move) { //test if it is directory if (!Directory.Exists(item.Value)) continue; foreach (var dir in dirs.Where(x => x.Path.Equals(item.Key) || x.Path.StartsWith(item.Key + "\\"))) { dir.Path = dir.Path.Replace(item.Key, item.Value); Db.UpdateOnSubmit(dir); } //move thumbnails var destPath = Path.GetDirectoryName(item.Value); if (destPath != null) fo.MoveItem(item.Key.Replace(":\\", cachePath), destPath.Replace(":\\", cachePath), item.Value.Substring(destPath.Length + 1)); } #endregion } } } fo.PerformOperations(); Db.SubmitChanges(); } return true; }
private void compress_DoWork(object sender, DoWorkEventArgs e) { var worker = (BackgroundWorker) sender; var mis = (List<ViewModel.BaseMediaItem>) e.Argument; var count = mis.Count; var done = 0; const BitmapCreateOptions createOptions = BitmapCreateOptions.PreservePixelFormat | BitmapCreateOptions.IgnoreColorProfile; foreach (var mi in mis) { if (worker.CancellationPending) { e.Cancel = true; break; } FileInfo original = new FileInfo(mi.FilePath); FileInfo newFile = new FileInfo(mi.FilePath.Replace(".", "_newFile.")); bool bSuccess = false; try { using (Stream originalFileStream = File.Open(original.FullName, FileMode.Open, FileAccess.Read)) { JpegBitmapEncoder encoder = new JpegBitmapEncoder { QualityLevel = _jpegQualityLevel }; //BitmapCreateOptions.PreservePixelFormat | BitmapCreateOptions.IgnoreColorProfile and BitmapCacheOption.None //is a KEY to lossless jpeg edit if the QualityLevel is the same encoder.Frames.Add(BitmapFrame.Create(originalFileStream, createOptions, BitmapCacheOption.None)); using (Stream newFileStream = File.Open(newFile.FullName, FileMode.Create, FileAccess.ReadWrite)) { encoder.Save(newFileStream); } bSuccess = true; } } catch (Exception) { // ignored } if (bSuccess) { try { long[] fileSizes = { original.Length, newFile.Length }; done++; newFile.CreationTime = original.CreationTime; using (FileOperation fo = new FileOperation()) { var flags = FileOperationFlags.FOF_SILENT | FileOperationFlags.FOFX_RECYCLEONDELETE | FileOperationFlags.FOF_NOERRORUI; fo.SetOperationFlags(flags); fo.DeleteItem(original.FullName); fo.PerformOperations(); } newFile.MoveTo(original.FullName); worker.ReportProgress(Convert.ToInt32(((double)done / count) * 100), fileSizes); } catch (Exception) { // ignored } } } }