FolderQuestionedImageBrowser.xaml.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. using AIPlatform.Protocol.Model;
  2. using AIPlatform.Protocol.Utilities;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Collections.ObjectModel;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Threading.Tasks;
  9. using System.Windows;
  10. using System.Windows.Controls;
  11. using System.Windows.Input;
  12. using System.Windows.Media;
  13. using System.Windows.Media.Imaging;
  14. namespace aipdev
  15. {
  16. /// <summary>
  17. /// Interaction logic for FolderQuestionedImageBrowser.xaml
  18. /// </summary>
  19. public partial class FolderQuestionedImageBrowser : UserControl, IContentPage
  20. {
  21. private ScrollViewer _scrollViewer;
  22. private string _keyword;
  23. private int _pageSize { get; set; } = 45;
  24. private int _totalPages { get; set; }
  25. private int _preloadedPage { get; set; }
  26. private bool _scrollDown { get; set; }
  27. private bool _isLoadPreviousImages { get; set; }
  28. private bool _isLoadNextImages { get; set; }
  29. private double _oldVerticalOffset { get; set; }
  30. private int _browseImageIndex { get; set; }
  31. private int _browsePage { get; set; }
  32. private int _imageCount { get; set; }
  33. private int _groupCount { get; set; }
  34. private ImageFolderExtend _folder;
  35. private readonly ObservableCollection<FolderImageEx> _images = new ObservableCollection<FolderImageEx>();
  36. public string PageName { get; set; }
  37. public bool IsHomePage { get; set; }
  38. public bool IsModalPage { get; set; }
  39. private bool _stopLoading { get; set; }
  40. private bool _isPendingConfirmed { get; set; }
  41. public FolderQuestionedImageBrowser()
  42. {
  43. InitializeComponent();
  44. PageName = "FolderQuestionedImageBrowser";
  45. IsHomePage = false;
  46. IsModalPage = true;
  47. FolderImages.ItemsSource = _images;
  48. }
  49. private T FindVisualChild<T>(DependencyObject element) where T : class
  50. {
  51. try
  52. {
  53. while (element != null)
  54. {
  55. if (element is T)
  56. return element as T;
  57. element = VisualTreeHelper.GetChild(element, 0);
  58. }
  59. }
  60. catch (Exception)
  61. {
  62. //DoNothing
  63. }
  64. return null;
  65. }
  66. private void OnFolderImagesScrollChanged(object sender, ScrollChangedEventArgs e)
  67. {
  68. var scrollViewer = (ScrollViewer)sender;
  69. if (IsOnScrollViewBottom(scrollViewer))
  70. {
  71. if (_preloadedPage < _totalPages)
  72. {
  73. try
  74. {
  75. Task.Run(async () =>
  76. {
  77. await LoadImagesAsync(_preloadedPage).ConfigureAwait(false);
  78. });
  79. }
  80. catch (Exception ex)
  81. {
  82. MessageBox.Show(Application.Current.MainWindow, $"加载文件夹图像失败:{ex.Translate()}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  83. }
  84. }
  85. }
  86. }
  87. private bool IsOnScrollViewBottom(ScrollViewer view)
  88. {
  89. var onBottom = false;
  90. var verticalOffset = view.VerticalOffset;
  91. var scrollableHeight = view.ScrollableHeight;
  92. var extentHeight = view.ExtentHeight;
  93. _scrollDown = verticalOffset >= _oldVerticalOffset;
  94. #region 滚动条从上往下翻看,加载之面页数
  95. if (_scrollDown && verticalOffset / extentHeight > 0.7 && _stopLoading && _preloadedPage < _totalPages - 1)
  96. {
  97. _isLoadNextImages = true;
  98. _isLoadPreviousImages = false;
  99. onBottom = true;
  100. verticalOffset = 2;
  101. _preloadedPage++;
  102. }
  103. #endregion 滚动条从上往下翻看,加载之面页数
  104. #region 有上一次的浏览记录时,滚动条从下往上翻看,加载之前页数
  105. else if (_browsePage > 0 && !_scrollDown && verticalOffset / extentHeight < 0.3 && _stopLoading && _preloadedPage > 0)
  106. {
  107. _isLoadPreviousImages = true;
  108. _isLoadNextImages = false;
  109. onBottom = true;
  110. verticalOffset = scrollableHeight;
  111. _preloadedPage--;
  112. }
  113. #endregion 有上一次的浏览记录时,滚动条从下往上翻看,加载之前页数
  114. _oldVerticalOffset = verticalOffset;
  115. return onBottom;
  116. }
  117. public void Close()
  118. {
  119. ClearImages();
  120. }
  121. private string GetConclusions(List<LabelConclusion> labelConclusions, ref string trimmingConclusions)
  122. {
  123. var conclusions = string.Empty;
  124. for (int i = 0; i < labelConclusions.Count; i++)
  125. {
  126. var item = labelConclusions[i];
  127. conclusions += $"{item.Title} {item.Content}";
  128. if (i < labelConclusions.Count - 1)
  129. conclusions += Environment.NewLine;
  130. if (i < 5)
  131. {
  132. trimmingConclusions = conclusions;
  133. }
  134. else if (i == 5)
  135. {
  136. trimmingConclusions += "......";
  137. }
  138. }
  139. return conclusions;
  140. }
  141. private async Task LoadImagesAsync(int page = 0)
  142. {
  143. try
  144. {
  145. Dispatcher.Invoke(() =>
  146. {
  147. ContentManager.ShowLoading();
  148. });
  149. _stopLoading = false;
  150. if (_folder is ImageFolderExtend imageFolder)
  151. {
  152. var labeledFileInfos = await DeveloperManager.Shared.GetLatestLabeledFileInfosAsync(imageFolder.Id, _keyword, true, _isPendingConfirmed, page, _pageSize);
  153. if (_isLoadPreviousImages)
  154. {
  155. labeledFileInfos = labeledFileInfos.OrderByDescending(x => x).ToList();
  156. }
  157. foreach (var fileInfo in labeledFileInfos)
  158. {
  159. var labeledUltrasoundFile = fileInfo.LabeledUltrasoundFile;
  160. if (_images.Any(x => x.LabeledUltrasoundFile.Id == labeledUltrasoundFile.Id))
  161. {
  162. continue;
  163. }
  164. var previewImage = new BitmapImage();
  165. previewImage.BeginInit();
  166. previewImage.StreamSource = new MemoryStream(fileInfo.ImageData);
  167. previewImage.EndInit();
  168. previewImage.Freeze();
  169. var trimmingConclusions = string.Empty;
  170. var conclusions = GetConclusions(fileInfo.LabelConclusions, ref trimmingConclusions);
  171. var folderImageEx = new FolderImageEx(labeledUltrasoundFile, previewImage, false, fileInfo.LabeledResult, conclusions, trimmingConclusions, page, imageFolder.Id, fileInfo.HasQuestioned);
  172. if (_stopLoading)
  173. {
  174. break;
  175. }
  176. if (_isLoadPreviousImages)
  177. {
  178. Dispatcher.Invoke(() =>
  179. {
  180. _images.Insert(0, folderImageEx);
  181. });
  182. }
  183. else
  184. {
  185. Dispatcher.Invoke(() =>
  186. {
  187. _images.Add(folderImageEx);
  188. });
  189. }
  190. }
  191. }
  192. _stopLoading = true;
  193. Dispatcher.Invoke(() =>
  194. {
  195. if (_scrollViewer == null)
  196. {
  197. _scrollViewer = FindVisualChild<ScrollViewer>(FolderImages);
  198. if (_scrollViewer != null)
  199. {
  200. if (_browseImageIndex == 0)
  201. {
  202. _scrollViewer.ScrollToTop();
  203. }
  204. else
  205. {
  206. var rowHeight = _scrollViewer.ExtentHeight / Math.Ceiling((double)_images.Count / 3);
  207. var count = _browseImageIndex % _pageSize;
  208. var verticalOffset = Math.Floor((double)count / 3) * rowHeight;
  209. _scrollViewer.ScrollToVerticalOffset(verticalOffset);
  210. }
  211. _scrollViewer.ScrollChanged += OnFolderImagesScrollChanged;
  212. }
  213. }
  214. else if (_isLoadPreviousImages)
  215. {
  216. var rowHeight = _scrollViewer.ExtentHeight / Math.Ceiling((double)_images.Count / 3);
  217. var verticalOffset = _pageSize / 3 * rowHeight + _scrollViewer.VerticalOffset;
  218. _scrollViewer.ScrollToVerticalOffset(verticalOffset);
  219. }
  220. });
  221. }
  222. catch (Exception ex)
  223. {
  224. Dispatcher.Invoke(() =>
  225. {
  226. MessageBox.Show(Application.Current.MainWindow, $"加载文件夹图像失败:{ex.Translate()}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  227. });
  228. }
  229. finally
  230. {
  231. Dispatcher.Invoke(() =>
  232. {
  233. ContentManager.HideLoading();
  234. });
  235. }
  236. }
  237. private void ClearImages()
  238. {
  239. Reset();
  240. _folder = null;
  241. FolderName.Text = string.Empty;
  242. FolderName.ToolTip = string.Empty;
  243. _keyword = txtFileName.Text = string.Empty;
  244. _totalPages = 0;
  245. _imageCount = 0;
  246. _groupCount = 0;
  247. chbIsConfirmed.IsChecked = false;
  248. _isPendingConfirmed = false;
  249. }
  250. public async void OnShow(object arg)
  251. {
  252. try
  253. {
  254. if (arg is ImageFolderExtend imageFolder)
  255. {
  256. _folder = imageFolder;
  257. FolderName.Text = _folder.Name;
  258. FolderName.ToolTip = _folder.Name;
  259. _imageCount = _folder.ImageCount;
  260. _groupCount = _folder.GroupCount;
  261. _totalPages = (int)Math.Ceiling((double)_groupCount / _pageSize);
  262. await LoadImagesAsync(_preloadedPage).ConfigureAwait(false);
  263. }
  264. else
  265. {
  266. throw new InvalidOperationException("无效的文件夹路径。");
  267. }
  268. }
  269. catch (Exception ex)
  270. {
  271. MessageBox.Show(Application.Current.MainWindow, $"加载文件夹图像失败:{ex.Translate()}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  272. }
  273. }
  274. public void OnHide()
  275. {
  276. ClearImages();
  277. }
  278. private async void OnImageClick(object sender, RoutedEventArgs e)
  279. {
  280. FolderImageEx folderImageEx = null;
  281. if (sender is MenuItem menuItem)
  282. {
  283. folderImageEx = (FolderImageEx)menuItem.DataContext;
  284. }
  285. else if (sender is Button button)
  286. {
  287. folderImageEx = (FolderImageEx)button.DataContext;
  288. }
  289. if (folderImageEx != null)
  290. {
  291. if (folderImageEx.LabeledUltrasoundFile != null)
  292. {
  293. var lstFileId = _images.Select(x => x.LabeledUltrasoundFile.UltrasoundFileId).ToList();
  294. var lstLabeledFileId = _images.Select(x => x.LabeledUltrasoundFile.Id).ToList();
  295. var index = lstFileId.IndexOf(folderImageEx.LabeledUltrasoundFile.UltrasoundFileId);
  296. var folderImageViewer = new FolderQuestionedImageViewer(folderImageEx.SourceFolderId, index, folderImageEx.LabeledUltrasoundFile, lstFileId, lstLabeledFileId) { Owner = Application.Current.MainWindow };
  297. folderImageViewer.ShowDialog();
  298. }
  299. }
  300. }
  301. private void OnCloseClick(object sender, RoutedEventArgs e)
  302. {
  303. ClearImages();
  304. this.Hide();
  305. }
  306. private void OnSearchFiles(object sender, RoutedEventArgs e)
  307. {
  308. _keyword = txtFileName.Text;
  309. Reset();
  310. Task.Run(async () =>
  311. {
  312. await LoadImagesAsync().ConfigureAwait(false);
  313. });
  314. }
  315. private void Reset()
  316. {
  317. _scrollViewer ??= FindVisualChild<ScrollViewer>(FolderImages);
  318. if (_scrollViewer != null)
  319. {
  320. //#region 保存历史查看位置
  321. //if (_folder is DeveloperImageFolder developerImageFolder)
  322. //{
  323. // try
  324. // {
  325. // var rowHeight = _scrollViewer.ExtentHeight / Math.Ceiling((double)_images.Count / 3);
  326. // var currRows = Math.Ceiling(_scrollViewer.VerticalOffset / rowHeight);
  327. // _browseImageIndex = (int)currRows * 3;
  328. // _browsePage = _images[_browseImageIndex].Page;
  329. // await DeveloperManager.Shared.UpdateDeveloperFolderBrowseHistoricalInfo(_folder.Id, _browseImageIndex, _browsePage);
  330. // }
  331. // catch (Exception ex)
  332. // {
  333. // MessageBox.Show(Application.Current.MainWindow, $"保存文件夹浏览记录失败:{ex.Translate()}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  334. // }
  335. //}
  336. //#endregion
  337. _scrollViewer.ScrollChanged -= OnFolderImagesScrollChanged;
  338. }
  339. _stopLoading = true;
  340. _scrollViewer = null;
  341. _images.Clear();
  342. _preloadedPage = 0;
  343. _isLoadPreviousImages = false;
  344. _isLoadNextImages = false;
  345. _scrollDown = false;
  346. _oldVerticalOffset = 0;
  347. _browseImageIndex = 0;
  348. _browsePage = 0;
  349. }
  350. private void OnClearAndSearchFiles(object sender, RoutedEventArgs e)
  351. {
  352. _keyword = txtFileName.Text = string.Empty;
  353. OnSearchFiles(sender, e);
  354. }
  355. private void txtFileName_PreviewKeyDown(object sender, KeyEventArgs e)
  356. {
  357. if (e.Key == Key.Enter)
  358. {
  359. OnSearchFiles(sender, e);
  360. }
  361. }
  362. private async void OnSuspectedMislabelingFileClick(object sender, RoutedEventArgs e)
  363. {
  364. var menuItem = (MenuItem)sender;
  365. var folderImageEx = (FolderImageEx)menuItem.DataContext;
  366. try
  367. {
  368. CopyImageWindow copyImageWindow;
  369. if (folderImageEx.DeveloperFolderFile != null)
  370. {
  371. copyImageWindow = new CopyImageWindow(folderImageEx.DeveloperFolderFile.ImageCategoryId) { Owner = Application.Current.MainWindow };
  372. }
  373. else
  374. {
  375. copyImageWindow = new CopyImageWindow(folderImageEx.LabeledUltrasoundFile.ImageCategoryId) { Owner = Application.Current.MainWindow };
  376. }
  377. copyImageWindow.ShowDialog();
  378. var selectedFolder = copyImageWindow.SelectedFolder;
  379. if (selectedFolder != null)
  380. {
  381. Dispatcher.Invoke(() =>
  382. {
  383. ContentManager.ShowLoading();
  384. });
  385. try
  386. {
  387. if (folderImageEx.DeveloperFolderFile != null)
  388. {
  389. await DeveloperManager.Shared.CopyDeveloperFolderGroupAsync(selectedFolder.Id, folderImageEx.SourceFolderId, folderImageEx.DeveloperFolderFile.UltrasoundGroupId);
  390. }
  391. else
  392. {
  393. await DeveloperManager.Shared.CopyFolderGroupAsync(selectedFolder.Id, folderImageEx.SourceFolderId, folderImageEx.LabeledUltrasoundFile.UltrasoundGroupId);
  394. }
  395. }
  396. catch (Exception ex)
  397. {
  398. MessageBox.Show(Application.Current.MainWindow, $"复制图片失败:{ex.Translate()}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  399. }
  400. finally
  401. {
  402. Dispatcher.Invoke(() =>
  403. {
  404. ContentManager.HideLoading();
  405. });
  406. }
  407. }
  408. }
  409. catch (Exception ex)
  410. {
  411. MessageBox.Show(Application.Current.MainWindow, $"获取文件夹列表失败:{ex.Translate()}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  412. }
  413. }
  414. private void OnConfirmedFilesClick(object sender, RoutedEventArgs e)
  415. {
  416. _isPendingConfirmed = (bool)chbIsConfirmed.IsChecked;
  417. OnSearchFiles(sender, e);
  418. }
  419. }
  420. }