QuickImage – Diff between revs 8 and 9

Subversion Repositories:
Rev:
Show entire fileIgnore whitespace
Rev 8 Rev 9
Line 1... Line 1...
1 using System; 1 using System;
2 using System.Collections.Concurrent; 2 using System.Collections.Concurrent;
3 using System.Collections.Generic; 3 using System.Collections.Generic;
-   4 using System.Collections.Specialized;
4 using System.ComponentModel; 5 using System.ComponentModel;
5 using System.Diagnostics; 6 using System.Diagnostics;
6 using System.Drawing; 7 using System.Drawing;
7 using System.IO; 8 using System.IO;
8 using System.Linq; 9 using System.Linq;
Line 241... Line 242...
241 var bufferBlock = new BufferBlock<(string Name, ConcurrentBag<string> Tags)>(new DataflowBlockOptions{ CancellationToken = _cancellationToken }); 242 var bufferBlock = new BufferBlock<(string Name, ConcurrentBag<string> Tags)>(new DataflowBlockOptions{ CancellationToken = _cancellationToken });
242 var broadcastBlock = new BroadcastBlock<(string Name, ConcurrentBag<string> Tags)>(x => x, new DataflowBlockOptions { CancellationToken = _cancellationToken }); 243 var broadcastBlock = new BroadcastBlock<(string Name, ConcurrentBag<string> Tags)>(x => x, new DataflowBlockOptions { CancellationToken = _cancellationToken });
243 var databaseActionBlock = new ActionBlock<(string Name, ConcurrentBag<string> Tags)>( 244 var databaseActionBlock = new ActionBlock<(string Name, ConcurrentBag<string> Tags)>(
244 async file => 245 async file =>
245 { 246 {
246 await Task.WhenAll(_quickImageDatabase.AddTagsAsync(file.Name, file.Tags, _cancellationToken), _tagManager.AddIptcKeywords(file.Name, file.Tags, _cancellationToken)); 247 await _quickImageDatabase.AddTagsAsync(file.Name, file.Tags, _cancellationToken);
-   248 await _tagManager.AddIptcKeywords(file.Name, file.Tags, _cancellationToken);
247 }, new ExecutionDataflowBlockOptions { CancellationToken = _cancellationToken }); 249 }, new ExecutionDataflowBlockOptions { CancellationToken = _cancellationToken });
248 var taggingActionBlock = new ActionBlock<(string Name, ConcurrentBag<string> Tags)>(file => 250 var taggingActionBlock = new ActionBlock<(string Name, ConcurrentBag<string> Tags)>(file =>
249 { 251 {
250 foreach (var tag in file.Tags) 252 foreach (var tag in file.Tags)
251 { 253 {
Line 299... Line 301...
299 bufferBlock.Complete(); 301 bufferBlock.Complete();
Line 300... Line 302...
300   302  
301 await bufferBlock.Completion; 303 await bufferBlock.Completion;
302 await databaseActionBlock.Completion; 304 await databaseActionBlock.Completion;
-   305 await taggingActionBlock.Completion;
-   306  
303 await taggingActionBlock.Completion; 307 this.InvokeIfRequired(form => { form.toolStripStatusLabel1.Text = "Tags balanced."; });
304 } 308 }
305 catch (Exception exception) 309 catch (Exception exception)
306 { 310 {
-   311 Log.Warning(exception, "Could not balance tags.");
-   312  
307 Log.Warning(exception, "Could not balance tags."); 313 this.InvokeIfRequired(form => { form.toolStripStatusLabel1.Text = "Error balancing tags..."; });
308 } 314 }
Line 309... Line 315...
309 } 315 }
310   316  
Line 722... Line 728...
722 toolStripProgressBar1.MarqueeAnimationSpeed = 0; 728 toolStripProgressBar1.MarqueeAnimationSpeed = 0;
723 _imageListViewLock.Release(); 729 _imageListViewLock.Release();
724 toolStripStatusLabel1.Text = "Done removing images."; 730 toolStripStatusLabel1.Text = "Done removing images.";
725 } 731 }
726 } 732 }
-   733
-   734 private async Task LoadDataObjectAsync(IDataObject dataObject)
-   735 {
-   736 var inputBlock = new BufferBlock<(string File, Stream Data, Definition Mime)>(
-   737 new ExecutionDataflowBlockOptions
-   738 { CancellationToken = _cancellationToken });
-   739  
-   740 var transformBlock = new TransformBlock<(string File, Stream Data, Definition Mime), string>(async tuple =>
-   741 {
-   742 try
-   743 {
-   744 var (_, data, _) = tuple;
-   745 data.Position = 0L;
-   746  
-   747 var path = Path.GetTempPath();
-   748 var name = Path.GetTempFileName();
-   749  
-   750 using var memoryStream = new MemoryStream();
-   751 switch (Configuration.InboundDragDrop.DragDropConvertType)
-   752 {
-   753 case "image/jpeg":
-   754 {
-   755 using var convertStream =
-   756 await _imageTool.ConvertTo(data, MagickFormat.Jpeg, _cancellationToken);
-   757 await convertStream.CopyToAsync(memoryStream);
-   758 name = Path.ChangeExtension(name, "jpg");
-   759 break;
-   760 }
-   761 case "image/png":
-   762 {
-   763 using var convertStream =
-   764 await _imageTool.ConvertTo(data, MagickFormat.Png, _cancellationToken);
-   765 await convertStream.CopyToAsync(memoryStream);
-   766 name = Path.ChangeExtension(name, "png");
-   767 break;
-   768 }
-   769 case "image/bmp":
-   770 {
-   771 using var convertStream =
-   772 await _imageTool.ConvertTo(data, MagickFormat.Bmp, _cancellationToken);
-   773 await convertStream.CopyToAsync(memoryStream);
-   774 name = Path.ChangeExtension(name, "bmp");
-   775 break;
-   776 }
-   777 case "image/gif":
-   778 {
-   779 using var convertStream =
-   780 await _imageTool.ConvertTo(data, MagickFormat.Gif, _cancellationToken);
-   781 await convertStream.CopyToAsync(memoryStream);
-   782 name = Path.ChangeExtension(name, "gif");
-   783 break;
-   784 }
-   785 // create a copy for files that do not have to be converted
-   786 default:
-   787 throw new ArgumentException(
-   788 "Unsupported conversion type for image.");
-   789 }
-   790  
-   791 var destinationFile = Path.Combine(path, name);
-   792  
-   793 memoryStream.Position = 0L;
-   794 await Miscellaneous.CopyFileAsync(memoryStream, destinationFile, _cancellationToken);
-   795  
-   796 return destinationFile;
-   797 }
-   798 catch (Exception exception)
-   799 {
-   800 Log.Warning(exception, "Unable to convert input file.");
-   801 return null;
-   802 }
-   803 }, new ExecutionDataflowBlockOptions { CancellationToken = _cancellationToken });
-   804  
-   805 var copyTransformBlock = new TransformBlock<(string File, Stream Data, Definition Mime), string>(
-   806 async tuple =>
-   807 {
-   808 try
-   809 {
-   810 var (_, data, mime) = tuple;
-   811 data.Position = 0L;
-   812  
-   813 var path = Path.GetTempPath();
-   814 var name = Path.GetTempFileName();
-   815 var extension = mime.File.Extensions.FirstOrDefault();
-   816 name = Path.ChangeExtension(name, extension);
-   817 var destinationFile = Path.Combine(path, name);
-   818  
-   819 await Miscellaneous.CopyFileAsync(data, destinationFile, _cancellationToken);
-   820  
-   821 return destinationFile;
-   822 }
-   823 catch (Exception exception)
-   824 {
-   825 Log.Warning(exception, "Unable to create a copy of the file.");
-   826  
-   827 return null;
-   828 }
-   829 }, new ExecutionDataflowBlockOptions { CancellationToken = _cancellationToken });
-   830  
-   831 var importTransformBlock =
-   832 new TransformBlock<(string File, Stream Data, Definition Mime), string>(
-   833 tuple => Task.FromResult(tuple.File),
-   834 new ExecutionDataflowBlockOptions { CancellationToken = _cancellationToken });
-   835  
-   836 var outputBlock = new BufferBlock<string>(new ExecutionDataflowBlockOptions
-   837 { CancellationToken = _cancellationToken });
-   838  
-   839 using var _1 = inputBlock.LinkTo(transformBlock,
-   840 tuple => Configuration.InboundDragDrop.ConvertOnDragDrop &&
-   841 Configuration.SupportedFormats.IsSupportedImage(tuple.Mime.File.MimeType) &&
-   842 !Configuration.InboundDragDrop.DragDropConvertExclude
-   843 .IsExcludedImage(tuple.Mime.File.MimeType));
-   844 using var _2 = transformBlock.LinkTo(outputBlock, file => !string.IsNullOrEmpty(file));
-   845 using var _3 = transformBlock.LinkTo(DataflowBlock.NullTarget<string>());
-   846  
-   847 using var _4 = inputBlock.LinkTo(copyTransformBlock, tuple => Configuration.InboundDragDrop.CopyOnDragDrop);
-   848 using var _5 = copyTransformBlock.LinkTo(outputBlock);
-   849 using var _6 = copyTransformBlock.LinkTo(DataflowBlock.NullTarget<string>());
-   850  
-   851 using var _7 = inputBlock.LinkTo(importTransformBlock,
-   852 tuple => !Configuration.InboundDragDrop.ConvertOnDragDrop &&
-   853 !Configuration.InboundDragDrop.CopyOnDragDrop);
-   854 using var _8 = importTransformBlock.LinkTo(outputBlock);
-   855 using var _9 = importTransformBlock.LinkTo(DataflowBlock.NullTarget<string>());
-   856  
-   857 var tasks = new List<Task>();
-   858 await foreach (var (file, data, mime) in GetDragDropFiles(dataObject, _magicMime, _cancellationToken))
-   859 {
-   860 if (!Configuration.SupportedFormats.IsSupported(mime.File.MimeType))
-   861 {
-   862 continue;
-   863 }
-   864  
-   865 tasks.Add(inputBlock.SendAsync((File: file, Data: data, Mime: mime), _cancellationToken));
-   866 }
-   867  
-   868 await Task.WhenAll(tasks);
-   869 inputBlock.Complete();
-   870  
-   871 await inputBlock.Completion.ContinueWith(_ =>
-   872 {
-   873 transformBlock.Complete();
-   874 copyTransformBlock.Complete();
-   875 importTransformBlock.Complete();
-   876 }, _cancellationToken);
-   877  
-   878 await Task.WhenAll(transformBlock.Completion, copyTransformBlock.Completion, importTransformBlock.Completion).ContinueWith(_ => { outputBlock.Complete(); }, _cancellationToken);
-   879  
-   880 var set = new HashSet<string>();
-   881 while (await outputBlock.OutputAvailableAsync(_cancellationToken))
-   882 {
-   883 if (!outputBlock.TryReceiveAll(out var items))
-   884 {
-   885 continue;
-   886 }
-   887  
-   888 set.UnionWith(items);
-   889 }
-   890  
-   891 await LoadFilesAsync(set, _magicMime, _cancellationToken);
-   892 }
Line 727... Line 893...
727   893  
728 private async Task LoadFilesAsync(IEnumerable<string> files, MagicMime magicMime, 894 private async Task LoadFilesAsync(IEnumerable<string> files, MagicMime magicMime,
729 CancellationToken cancellationToken) 895 CancellationToken cancellationToken)
730 { 896 {
Line 1886... Line 2052...
1886 catch (Exception exception) 2052 catch (Exception exception)
1887 { 2053 {
1888 progress.Report(new ImageListViewItemProgressFailure<ListViewItem>(item, exception)); 2054 progress.Report(new ImageListViewItemProgressFailure<ListViewItem>(item, exception));
1889 } 2055 }
1890 } 2056 }
-   2057 }
-   2058  
-   2059  
-   2060 private void collapseToolStripMenuItem_Click(object sender, EventArgs e)
-   2061 {
-   2062 var items = imageListView.SelectedItems.OfType<ListViewItem>();
-   2063  
-   2064 var listViewItems = items as ListViewItem[] ?? items.ToArray();
-   2065  
-   2066 foreach(var item in listViewItems)
-   2067 {
-   2068 var group = item.Group;
-   2069  
-   2070 if (!imageListView.GetCollapsed(group))
-   2071 {
-   2072 imageListView.SetCollapsed(group, true);
-   2073 }
-   2074 }
1891 } 2075 }
Line 1892... Line 2076...
1892   2076  
1893 private void collapseAllToolStripMenuItem_Click(object sender, EventArgs e) 2077 private void collapseAllToolStripMenuItem_Click(object sender, EventArgs e)
1894 { 2078 {
Line 3184... Line 3368...
3184 _aboutForm.Show(); 3368 _aboutForm.Show();
3185 } 3369 }
Line 3186... Line 3370...
3186   3370  
3187 private async void imageListView_DragDrop(object sender, DragEventArgs e) 3371 private async void imageListView_DragDrop(object sender, DragEventArgs e)
3188 { -  
3189 var inputBlock = new BufferBlock<(string File, Stream Data, Definition Mime)>( -  
3190 new ExecutionDataflowBlockOptions -  
3191 { CancellationToken = _cancellationToken }); -  
3192   -  
3193 var transformBlock = new TransformBlock<(string File, Stream Data, Definition Mime), string>(async tuple => -  
3194 { -  
3195 try -  
3196 { -  
3197 var (_, data, _) = tuple; -  
3198 data.Position = 0L; -  
3199   -  
3200 var path = Path.GetTempPath(); -  
3201 var name = Path.GetTempFileName(); -  
3202   -  
3203 using var memoryStream = new MemoryStream(); -  
3204 switch (Configuration.InboundDragDrop.DragDropConvertType) -  
3205 { -  
3206 case "image/jpeg": -  
3207 { -  
3208 using var convertStream = -  
3209 await _imageTool.ConvertTo(data, MagickFormat.Jpeg, _cancellationToken); -  
3210 await convertStream.CopyToAsync(memoryStream); -  
3211 name = Path.ChangeExtension(name, "jpg"); -  
3212 break; -  
3213 } -  
3214 case "image/png": -  
3215 { -  
3216 using var convertStream = -  
3217 await _imageTool.ConvertTo(data, MagickFormat.Png, _cancellationToken); -  
3218 await convertStream.CopyToAsync(memoryStream); -  
3219 name = Path.ChangeExtension(name, "png"); -  
3220 break; -  
3221 } -  
3222 case "image/bmp": -  
3223 { -  
3224 using var convertStream = -  
3225 await _imageTool.ConvertTo(data, MagickFormat.Bmp, _cancellationToken); -  
3226 await convertStream.CopyToAsync(memoryStream); -  
3227 name = Path.ChangeExtension(name, "bmp"); -  
3228 break; -  
3229 } -  
3230 case "image/gif": -  
3231 { -  
3232 using var convertStream = -  
3233 await _imageTool.ConvertTo(data, MagickFormat.Gif, _cancellationToken); -  
3234 await convertStream.CopyToAsync(memoryStream); -  
3235 name = Path.ChangeExtension(name, "gif"); -  
3236 break; -  
3237 } -  
3238 // create a copy for files that do not have to be converted -  
3239 default: -  
3240 throw new ArgumentException( -  
3241 "Unsupported conversion type for inbound drag and drop image."); -  
3242 } -  
3243   -  
3244 var destinationFile = Path.Combine(path, name); -  
3245   -  
3246 memoryStream.Position = 0L; -  
3247 await Miscellaneous.CopyFileAsync(memoryStream, destinationFile, _cancellationToken); -  
3248   -  
3249 return destinationFile; -  
3250 } -  
3251 catch (Exception exception) -  
3252 { -  
3253 Log.Warning(exception, "Unable to convert drag drop input file."); -  
3254 return null; -  
3255 } -  
3256 }, new ExecutionDataflowBlockOptions { CancellationToken = _cancellationToken }); -  
3257   -  
3258 var copyTransformBlock = new TransformBlock<(string File, Stream Data, Definition Mime), string>( -  
3259 async tuple => -  
3260 { -  
3261 try -  
3262 { -  
3263 var (_, data, mime) = tuple; -  
3264 data.Position = 0L; -  
3265   -  
3266 var path = Path.GetTempPath(); -  
3267 var name = Path.GetTempFileName(); -  
3268 var extension = mime.File.Extensions.FirstOrDefault(); -  
3269 name = Path.ChangeExtension(name, extension); -  
3270 var destinationFile = Path.Combine(path, name); -  
3271   -  
3272 await Miscellaneous.CopyFileAsync(data, destinationFile, _cancellationToken); -  
3273   -  
3274 return destinationFile; -  
3275 } -  
3276 catch (Exception exception) -  
3277 { -  
3278 Log.Warning(exception, "Unable to create a copy of file."); -  
3279 return null; -  
3280 } -  
3281 }, new ExecutionDataflowBlockOptions { CancellationToken = _cancellationToken }); -  
3282   -  
3283 var importTransformBlock = -  
3284 new TransformBlock<(string File, Stream Data, Definition Mime), string>( -  
3285 tuple => Task.FromResult(tuple.File), -  
3286 new ExecutionDataflowBlockOptions { CancellationToken = _cancellationToken }); -  
3287   -  
3288 var outputBlock = new BufferBlock<string>(new ExecutionDataflowBlockOptions -  
3289 { CancellationToken = _cancellationToken }); -  
3290   -  
3291 using var _1 = inputBlock.LinkTo(transformBlock, -  
3292 tuple => Configuration.InboundDragDrop.ConvertOnDragDrop && -  
3293 Configuration.SupportedFormats.IsSupportedImage(tuple.Mime.File.MimeType) && -  
3294 !Configuration.InboundDragDrop.DragDropConvertExclude -  
3295 .IsExcludedImage(tuple.Mime.File.MimeType)); -  
3296 using var _2 = transformBlock.LinkTo(outputBlock, file => !string.IsNullOrEmpty(file)); -  
3297 using var _3 = transformBlock.LinkTo(DataflowBlock.NullTarget<string>()); -  
3298   -  
3299 using var _4 = inputBlock.LinkTo(copyTransformBlock, tuple => Configuration.InboundDragDrop.CopyOnDragDrop); -  
3300 using var _5 = copyTransformBlock.LinkTo(outputBlock); -  
3301 using var _6 = copyTransformBlock.LinkTo(DataflowBlock.NullTarget<string>()); -  
3302   -  
3303 using var _7 = inputBlock.LinkTo(importTransformBlock, -  
3304 tuple => !Configuration.InboundDragDrop.ConvertOnDragDrop && -  
3305 !Configuration.InboundDragDrop.CopyOnDragDrop); -  
3306 using var _8 = importTransformBlock.LinkTo(outputBlock); -  
3307 using var _9 = importTransformBlock.LinkTo(DataflowBlock.NullTarget<string>()); -  
3308   -  
3309 var tasks = new List<Task>(); -  
3310 await foreach (var (file, data, mime) in GetDragDropFiles(e.Data, _magicMime, _cancellationToken)) -  
3311 { -  
3312 if (!Configuration.SupportedFormats.IsSupported(mime.File.MimeType)) -  
3313 { -  
3314 continue; -  
3315 } -  
3316   -  
3317 tasks.Add(inputBlock.SendAsync((File: file, Data: data, Mime: mime), _cancellationToken)); -  
3318 } -  
3319   3372 {
3320 await Task.WhenAll(tasks); -  
3321 inputBlock.Complete(); -  
3322   -  
3323 await inputBlock.Completion.ContinueWith(_ => -  
3324 { -  
3325 transformBlock.Complete(); -  
3326 copyTransformBlock.Complete(); -  
3327 importTransformBlock.Complete(); -  
3328 }, _cancellationToken); -  
3329   -  
3330 await Task.WhenAll(transformBlock.Completion, copyTransformBlock.Completion, importTransformBlock.Completion).ContinueWith(_ => { outputBlock.Complete(); }, _cancellationToken); -  
3331   -  
3332 var set = new HashSet<string>(); -  
3333 while (await outputBlock.OutputAvailableAsync(_cancellationToken)) -  
3334 { -  
3335 if (!outputBlock.TryReceiveAll(out var items)) -  
3336 { -  
3337 continue; -  
3338 } -  
3339   -  
3340 set.UnionWith(items); -  
3341 } -  
3342   -  
3343 await LoadFilesAsync(set, _magicMime, _cancellationToken); 3373 await LoadDataObjectAsync(e.Data);
Line 3344... Line 3374...
3344 } 3374 }
3345   3375  
3346 private void imageListView_DragEnter(object sender, DragEventArgs e) 3376 private void imageListView_DragEnter(object sender, DragEventArgs e)
Line 4038... Line 4068...
4038 ToggleMenuItemsRecursive(directoryToolStripMenuItem, MenuItemsToggleOperation.DISABLE); 4068 ToggleMenuItemsRecursive(directoryToolStripMenuItem, MenuItemsToggleOperation.DISABLE);
4039 ToggleMenuItemsRecursive(fileToolStripMenuItem1, MenuItemsToggleOperation.DISABLE); 4069 ToggleMenuItemsRecursive(fileToolStripMenuItem1, MenuItemsToggleOperation.DISABLE);
4040 ToggleMenuItemsRecursive(imageToolStripMenuItem, MenuItemsToggleOperation.DISABLE); 4070 ToggleMenuItemsRecursive(imageToolStripMenuItem, MenuItemsToggleOperation.DISABLE);
4041 ToggleMenuItemsRecursive(taggingToolStripMenuItem, MenuItemsToggleOperation.DISABLE); 4071 ToggleMenuItemsRecursive(taggingToolStripMenuItem, MenuItemsToggleOperation.DISABLE);
4042 } 4072 }
-   4073  
-   4074 private void copyCtrlToolStripMenuItem_Click(object sender, EventArgs e)
-   4075 {
-   4076 var items = imageListView.SelectedItems.OfType<ListViewItem>().ToArray();
-   4077 switch(items.Length)
-   4078 {
-   4079 case 0:
-   4080 break;
-   4081 default:
-   4082 // copy file paths as the default for multiple files selected
-   4083 var paths = new StringCollection();
-   4084 foreach (var item in items)
-   4085 {
-   4086 paths.Add(item.Name);
-   4087 }
-   4088  
-   4089 Clipboard.SetFileDropList(paths);
-   4090 break;
-   4091 }
-   4092 }
-   4093  
-   4094 private async void copyAsMediaToolStripMenuItem_Click(object sender, EventArgs e)
-   4095 {
-   4096 var items = imageListView.SelectedItems.OfType<ListViewItem>().ToArray();
-   4097  
-   4098 switch (items.Length)
-   4099 {
-   4100 case 1:
-   4101  
-   4102 {
-   4103 var file = items[0].Name;
-   4104  
-   4105 using var memoryStream = new MemoryStream();
-   4106 using var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);
-   4107 await fileStream.CopyToAsync(memoryStream);
-   4108 memoryStream.Position = 0L;
-   4109  
-   4110 var mime = _magicMime.Identify(file, memoryStream, _cancellationToken);
-   4111 if (Configuration.SupportedFormats.IsSupportedVideo(mime.Definition.File.MimeType))
-   4112 {
-   4113  
-   4114  
-   4115 Clipboard.SetDataObject(memoryStream);
-   4116 break;
-   4117 }
-   4118  
-   4119 if (!Configuration.SupportedFormats.IsSupportedImage(mime.Definition.File.MimeType))
-   4120 {
-   4121 using var image = Image.FromFile(file);
-   4122 Clipboard.SetImage(image);
-   4123 break;
-   4124 }
-   4125 }
-   4126  
-   4127 break;
-   4128 case 0:
-   4129 break;
-   4130 default:
-   4131 // copy file paths as the default for multiple files selected
-   4132 var paths = new StringCollection();
-   4133 foreach (var item in items)
-   4134 {
-   4135 paths.Add(item.Name);
-   4136 }
-   4137  
-   4138 Clipboard.SetFileDropList(paths);
-   4139 break;
-   4140 }
-   4141  
-   4142 }
-   4143  
-   4144 private async void pasteCtrlCToolStripMenuItem_Click(object sender, EventArgs e)
-   4145 {
-   4146 var dataObject = Clipboard.GetDataObject();
-   4147  
-   4148 await LoadDataObjectAsync(dataObject);
-   4149 }
-   4150  
-   4151  
4043 } 4152 }
4044 } 4153 }
4045   4154