Ejemplo n.º 1
0
    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;
    }
Ejemplo n.º 2
0
    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
          }
        }
      }
    }