CompareViewController.swift 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. //
  2. // CompareViewController.swift
  3. // KdanAuto
  4. //
  5. // Created by 朱东勇 on 2023/2/2.
  6. //
  7. import Foundation
  8. import AppKit
  9. import PDFKit
  10. class CompareViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate, NSPopoverDelegate {
  11. @IBOutlet var listView : NSTableView!
  12. @IBOutlet var filterBtn : NSButton!
  13. @IBOutlet var closeBtn : NSButton!
  14. @IBOutlet var progressIndicator : NSProgressIndicator!
  15. var _files : NSArray!
  16. var _showFiles : NSMutableArray!
  17. var _popover: NSPopover!
  18. static var sharedCViewController : CompareViewController? = nil
  19. class func shared() -> CompareViewController {
  20. if nil == sharedCViewController {
  21. var objects : NSArray!
  22. Bundle.main.loadNibNamed("CompareViewController", owner: nil, topLevelObjects: &objects)
  23. for tView in objects {
  24. if let tv = tView as? CompareViewController {
  25. sharedCViewController = tv
  26. }
  27. }
  28. }
  29. return sharedCViewController!
  30. }
  31. override func viewDidLoad() {
  32. self.listView.register(NSNib.init(nibNamed: NSNib.Name.init(NSString(string: "ImageCompareCellView")),
  33. bundle: Bundle.main), forIdentifier: NSUserInterfaceItemIdentifier.init("ImageCompareCellView"))
  34. }
  35. // IBAction
  36. @IBAction func filterSimilarItemAction(_ sender:NSButton) {
  37. self.setFiles(_files);
  38. }
  39. @IBAction func exportAction(_ sender:NSButton) {
  40. if (_files.count == 0) {
  41. let alert = NSAlert.init()
  42. alert.messageText = "无测试对比项导出";
  43. alert.runModal();
  44. return
  45. }else if (_showFiles.count == 0) {
  46. let alert = NSAlert.init()
  47. alert.messageText = "所有对比项均无差异";
  48. alert.runModal();
  49. return
  50. }
  51. let savePanel = NSSavePanel.init();
  52. let checkBox = NSButton(checkboxWithTitle: "过滤无差异项", target: self, action: nil);
  53. checkBox.state = self.filterBtn.state;
  54. checkBox.frame = CGRectMake(0, 0, 150, 45);
  55. if #available(macOS 11.0, *) {
  56. savePanel.allowedContentTypes = [.pdf]
  57. } else {
  58. savePanel.allowedFileTypes = ["pdf", "PDF"]
  59. }
  60. savePanel.accessoryView = checkBox
  61. if (savePanel.runModal() == .OK) {
  62. var exportFiles = NSMutableArray()
  63. if (checkBox.state == .on) {
  64. for tfile in NSArray(array: _files) {
  65. let file = tfile as! NSMutableDictionary;
  66. let degree = file.degree()
  67. if (fabs(degree - 100) > 0) {
  68. exportFiles.add(file);
  69. }
  70. }
  71. if (exportFiles.count == 0) {
  72. let alert = NSAlert.init()
  73. alert.messageText = "所有对比项均无差异";
  74. alert.runModal();
  75. return
  76. }
  77. }else {
  78. exportFiles = NSMutableArray(array: _files)
  79. }
  80. let url = savePanel.url!;
  81. NSLog("\(url)")
  82. let pdf = PDFDocument.init();
  83. let needFilter = checkBox.state == .on
  84. self.progressIndicator.isHidden = false;
  85. self.progressIndicator.doubleValue = 0;
  86. processNextImages(pdf, index: 0, files:exportFiles, url: url, needFilter: needFilter)
  87. }
  88. }
  89. // Save PDF
  90. func processNextImages(_ pdf:PDFDocument, index:Int32, files:NSMutableArray, url:URL, needFilter:Bool) -> Void {
  91. let file = files[Int(index)] as! NSMutableDictionary
  92. // NSLog("处理第\(index)页")
  93. // 所有文档均导出
  94. let cell = ImageCompareCellView.shared()
  95. cell?.frame = CGRectMake(0, 0, CGRectGetWidth(self.listView.frame), 900);
  96. cell?.setFileInfo(file);
  97. self.closeBtn.isEnabled = false;
  98. DispatchQueue.global().async {
  99. autoreleasepool {
  100. let image = cell?.processCompareImage()
  101. if (image != nil) {
  102. let page = PDFPage.init(image: image!)
  103. let nPage = page?.copy() as! PDFPage
  104. pdf.insert(nPage, at: pdf.pageCount)
  105. }
  106. }
  107. let degree = file.degree()
  108. if (abs(degree - 100) > 0) {
  109. autoreleasepool {
  110. let image = cell?.processCoverImage()
  111. if (image != nil) {
  112. let page = PDFPage.init(image: image!)
  113. let nPage = page?.copy() as! PDFPage
  114. pdf.insert(nPage, at: pdf.pageCount)
  115. }
  116. }
  117. }
  118. if ((index+1) < files.count) {
  119. DispatchQueue.main.asyncAfter(deadline: DispatchTime.init(uptimeNanoseconds: 100)) {
  120. self.progressIndicator.doubleValue = Double(Int(index) * 100/files.count);
  121. self.processNextImages(pdf, index: index+1, files: files, url: url, needFilter: needFilter);
  122. };
  123. }else {
  124. DispatchQueue.global().async {
  125. autoreleasepool {
  126. pdf.write(to: url)
  127. DispatchQueue.main.async {
  128. self.progressIndicator.isHidden = true;
  129. self.progressIndicator.doubleValue = 100.0;
  130. self.closeBtn.isEnabled = true;
  131. NSWorkspace.shared.activateFileViewerSelecting([url])
  132. }
  133. }
  134. }
  135. }
  136. }
  137. }
  138. // Show
  139. func showIn(_ view:NSView, rect:NSRect) {
  140. if _popover == nil {
  141. _popover = NSPopover.init()
  142. _popover.contentViewController = self;
  143. _popover.delegate = self
  144. }
  145. _popover.contentSize = self.view.frame.size
  146. _popover.show(relativeTo: CGRectMake(rect.origin.x,
  147. rect.origin.y - rect.size.height, rect.size.width, rect.size.height/2),
  148. of: view, preferredEdge: NSRectEdge.minY)
  149. }
  150. // Getter & Setter
  151. func setFiles(_ files:NSArray) {
  152. _files = files
  153. if (self.filterBtn.state == .on) {
  154. _showFiles = NSMutableArray()
  155. for tfile in NSArray(array: _files) {
  156. let file = tfile as! NSMutableDictionary;
  157. let degree = file.degree()
  158. if (fabs(degree - 100) > 0) {
  159. _showFiles.add(file);
  160. }
  161. }
  162. }else {
  163. _showFiles = NSMutableArray (array: _files);
  164. }
  165. listView.reloadData()
  166. }
  167. // IBAction
  168. @IBAction func closeAction(_ sender: NSButton) {
  169. _popover.close()
  170. }
  171. // TableView Delegate
  172. func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
  173. return autoreleasepool {
  174. var cellView = tableView.makeView(withIdentifier: .init("ImageCompareCellView"), owner: nil) as! ImageCompareCellView?
  175. if (nil == cellView) {
  176. cellView = ImageCompareCellView.shared() ?? nil
  177. }
  178. if (_showFiles.count >= row) {
  179. let fileInfo = _showFiles[row] as! NSMutableDictionary
  180. cellView?.setFileInfo(fileInfo)
  181. }
  182. return cellView
  183. }
  184. }
  185. func selectionShouldChange(in tableView: NSTableView) -> Bool {
  186. return true
  187. }
  188. func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool {
  189. return false
  190. }
  191. func tableView(_ tableView: NSTableView, shouldSelect tableColumn: NSTableColumn?) -> Bool {
  192. return false
  193. }
  194. func tableView(_ tableView: NSTableView, mouseDownInHeaderOf tableColumn: NSTableColumn) {
  195. }
  196. func tableView(_ tableView: NSTableView, didClick tableColumn: NSTableColumn) {
  197. }
  198. func tableView(_ tableView: NSTableView, didDrag tableColumn: NSTableColumn) {
  199. }
  200. func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
  201. return 900
  202. }
  203. func tableView(_ tableView: NSTableView, isGroupRow row: Int) -> Bool {
  204. return false
  205. }
  206. func tableView(_ tableView: NSTableView, sizeToFitWidthOfColumn column: Int) -> CGFloat {
  207. return tableView.frame.width
  208. }
  209. func tableView(_ tableView: NSTableView, rowActionsForRow row: Int, edge: NSTableView.RowActionEdge) -> [NSTableViewRowAction] {
  210. return []
  211. }
  212. func tableViewSelectionDidChange(_ notification: Notification) {
  213. }
  214. // TableView Data Source
  215. func numberOfRows(in tableView: NSTableView) -> Int {
  216. if nil == _showFiles {
  217. return 0
  218. }
  219. return _showFiles.count
  220. }
  221. //
  222. func popoverShouldClose(_ popover: NSPopover) -> Bool {
  223. return true
  224. }
  225. }