KMCompareWindowController.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. //
  2. // KMCompareWindowController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by lizhe on 2023/11/14.
  6. //
  7. import Cocoa
  8. typealias KMCompareWindowControllerContentComplete = (_ controller: KMCompareWindowController, _ pdfCompareContent: CPDFCompareContent, _ results: [CPDFCompareResults] ,_ oldDocument: CPDFDocument, _ document: CPDFDocument) -> Void
  9. typealias KMCompareWindowControllerCoveringComplete = (_ controller: KMCompareWindowController, _ document: CPDFDocument) -> Void
  10. class KMCompareWindowController: KMBaseWindowController {
  11. @IBOutlet weak var compareView: KMCompareView!
  12. var pdfCompareContent: CPDFCompareContent?
  13. var maskView: KMBookletMaskView?
  14. var progressController: SKProgressController?
  15. var filePath: String = "" {
  16. didSet {
  17. if compareView != nil {
  18. compareView.filePath = filePath
  19. }
  20. }
  21. }
  22. var fileType: KMCompareFilesType = .content {
  23. didSet {
  24. if compareView != nil {
  25. compareView.fileType = fileType
  26. }
  27. }
  28. }
  29. var password: String = "" {
  30. didSet {
  31. if compareView != nil {
  32. self.compareView.password = password
  33. }
  34. }
  35. }
  36. var contentComplete: KMCompareWindowControllerContentComplete?
  37. var coveringComplete :KMCompareWindowControllerCoveringComplete?
  38. override func windowDidLoad() {
  39. super.windowDidLoad()
  40. // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
  41. compareView.password = password
  42. compareView.filePath = filePath
  43. compareView.fileType = fileType
  44. compareView.cancelAction = { [unowned self] view in
  45. cancelAction?(self)
  46. }
  47. compareView.doneAction = { [unowned self] view, config in
  48. self.compareAction(config: config)
  49. }
  50. }
  51. func compareAction(config: KMCompareFilesConfig) {
  52. self.showWaitting()
  53. guard let pdfOldDocument = config.fileOldAttribute.pdfDocument, let pdfNewDocument = config.fileNewAttribute.pdfDocument else {
  54. let alert = NSAlert()
  55. alert.alertStyle = .critical
  56. alert.messageText = NSLocalizedString("Please select two files to compare", comment: "")
  57. alert.runModal()
  58. self.hideWaitting()
  59. return
  60. }
  61. let fileManager = FileManager.default
  62. let fileOldPath = config.fileOldAttribute.pdfDocument?.documentURL.path
  63. let fileNewPath = config.fileNewAttribute.pdfDocument?.documentURL.path
  64. if !fileManager.fileExists(atPath: fileOldPath!) || !fileManager.fileExists(atPath: fileNewPath!){
  65. let alert = NSAlert()
  66. alert.alertStyle = .critical
  67. alert.messageText = NSLocalizedString("The file has been deleted, please reselect a file.", comment: "")
  68. alert.runModal()
  69. self.hideWaitting()
  70. return
  71. }
  72. if (config.fileNewAttribute.fetchSelectPages().count == 0) ||
  73. (!config.fileNewAttribute.bAllPage && config.fileNewAttribute.pagesString.count < 1) {
  74. let alert = NSAlert()
  75. alert.alertStyle = .critical
  76. alert.messageText = String(format: "%@ %@", (config.fileNewAttribute.pdfDocument?.documentURL.path.lastPathComponent.lastPathComponent)!, NSLocalizedString("Invalid page range. Please reselect the page range.", comment: ""))
  77. alert.runModal()
  78. config.fileNewAttribute.bAllPage = true
  79. config.fileNewAttribute.pagesType = .all
  80. compareView.reloadData()
  81. self.hideWaitting()
  82. return
  83. }
  84. if (config.fileOldAttribute.fetchSelectPages().count == 0) || (!config.fileOldAttribute.bAllPage && config.fileOldAttribute.pagesString.count < 1) {
  85. let alert = NSAlert()
  86. alert.alertStyle = .critical
  87. alert.messageText = String(format: "%@ %@", (config.fileOldAttribute.pdfDocument?.documentURL.path.lastPathComponent.lastPathComponent)!, NSLocalizedString("Invalid page range. Please reselect the page range.", comment: ""))
  88. alert.runModal()
  89. config.fileOldAttribute.bAllPage = true
  90. config.fileOldAttribute.pagesType = .all
  91. compareView.reloadData()
  92. self.hideWaitting()
  93. return
  94. }
  95. let filePath = config.fileOldAttribute.pdfDocument?.documentURL.path
  96. let pdfDocument = CPDFDocument(url: URL(fileURLWithPath: filePath!))
  97. let filePath1 = config.fileNewAttribute.pdfDocument?.documentURL.path
  98. let pdfDocument1 = CPDFDocument(url: URL(fileURLWithPath: filePath1!))
  99. DispatchQueue.global().async {
  100. let oldDoc = CPDFDocument(url: config.fileOldAttribute.pdfDocument?.documentURL)
  101. oldDoc!.unlock(withPassword: config.fileOldAttribute.password)
  102. let doc = CPDFDocument(url: config.fileNewAttribute.pdfDocument?.documentURL)
  103. doc!.unlock(withPassword: config.fileNewAttribute.password)
  104. if self.compareView.fileType == .coverting {
  105. let pdfCompareOverlay = CPDFCompareOverlay(oldDocument: oldDoc, oldPageRange: config.fileOldAttribute.pagesString, newDocument: doc, newPageRange: config.fileNewAttribute.pagesString)
  106. let oldStrokeColor = config.oldStrokeColor
  107. pdfCompareOverlay?.setOldDocumentStroke(oldStrokeColor())
  108. pdfCompareOverlay?.setOldDocumentStrokeOpacity(config.oldStrokeOpacity())
  109. let newStrokeColor = config.newStrokeColor
  110. pdfCompareOverlay?.setNewDocumentStroke(newStrokeColor())
  111. pdfCompareOverlay?.setNewDocumentStrokeOpacity(config.newStrokeOpacity())
  112. pdfCompareOverlay?.setNewDocumentFillOpacity(config.newFillOpacity())
  113. pdfCompareOverlay?.setOldDocumentFillOpacity(config.oldFillOpacity())
  114. pdfCompareOverlay?.setNoFill(config.isNOFill())
  115. pdfCompareOverlay?.setBlendMod(config.blendMod())
  116. if (pdfCompareOverlay?.compare() == true) {
  117. DispatchQueue.main.async {
  118. self.progressController?.doubleValue = 30.0
  119. }
  120. guard let document = pdfCompareOverlay?.comparisonDocument() else {
  121. DispatchQueue.main.async {
  122. let alert = NSAlert()
  123. alert.alertStyle = .critical
  124. alert.messageText = NSLocalizedString("Failure", comment: "")
  125. alert.runModal()
  126. self.hideWaitting()
  127. }
  128. return
  129. }
  130. DispatchQueue.main.async {
  131. self.hideWaitting()
  132. self.coveringComplete?(self, document)
  133. }
  134. debugPrint("合并成功")
  135. }
  136. } else {
  137. var results: [CPDFCompareResults] = []
  138. var pdfCompareContent: CPDFCompareContent? = nil
  139. // if let _pdfCompareContent = self._pdfCompareContent {
  140. // pdfCompareContent = _pdfCompareContent
  141. // }
  142. //
  143. // if self._compareCancel {
  144. // return
  145. // }
  146. pdfCompareContent = CPDFCompareContent(oldDocument: oldDoc, newDocument: doc)
  147. pdfCompareContent?.setDelete(config.deleteColor())
  148. pdfCompareContent?.setReplace(config.replaceColor())
  149. pdfCompareContent?.setInsert(config.insertColor())
  150. pdfCompareContent?.setDeleteOpacity(config.deleteOpacity())
  151. pdfCompareContent?.setReplaceOpacity(config.replaceOpacity())
  152. pdfCompareContent?.setInsertOpacity(config.insertOpacity())
  153. let maxIndex = max(config.fileOldAttribute.fetchSelectPages().count, config.fileNewAttribute.fetchSelectPages().count)
  154. var compareType: CPDFCompareType = .all
  155. if config.isCompareText() && !config.isCompareImage() {
  156. compareType = .text
  157. } else if !config.isCompareText() && config.isCompareImage() {
  158. compareType = .image
  159. }
  160. // if self._compareCancel {
  161. // return
  162. // }
  163. DispatchQueue.main.async {
  164. self.progressController?.doubleValue = 30.0
  165. }
  166. for i in 0..<maxIndex {
  167. let oldPageIndex: Int
  168. if i >= config.fileOldAttribute.fetchSelectPages().count {
  169. oldPageIndex = Int(oldDoc!.pageCount) + i
  170. } else {
  171. oldPageIndex = Int(truncating: config.fileOldAttribute.fetchSelectPages()[i] as NSNumber) - 1
  172. }
  173. let newPageIndex: Int
  174. if i >= config.fileNewAttribute.fetchSelectPages().count {
  175. newPageIndex = Int(doc!.pageCount) + i
  176. } else {
  177. newPageIndex = Int(truncating: config.fileNewAttribute.fetchSelectPages()[i] as NSNumber) - 1
  178. }
  179. if let compareResults = pdfCompareContent?.compareOldPageIndex(oldPageIndex, newPageIndex: newPageIndex, type: compareType, isDrawHighlight: true) {
  180. results.append(compareResults)
  181. }
  182. // DispatchQueue.main.async {
  183. // if let compareLoadingWVC = self.compareLoadingWVC {
  184. // compareLoadingWVC.progress = CGFloat(i) / CGFloat(maxIndex)
  185. // }
  186. // }
  187. }
  188. DispatchQueue.main.async {
  189. self.hideWaitting()
  190. self.contentComplete?(self, pdfCompareContent!, results, oldDoc!, doc!)
  191. if results.count > 0 {
  192. // Handle success case
  193. } else {
  194. let alert = NSAlert()
  195. alert.alertStyle = .critical
  196. alert.messageText = NSLocalizedString("There is no difference between the two documents.", comment: "")
  197. alert.runModal()
  198. }
  199. }
  200. }
  201. }
  202. }
  203. }
  204. extension KMCompareWindowController {
  205. func showWaitting() {
  206. compareView.doneButton.isEnabled = false
  207. if self.maskView == nil {
  208. self.maskView = KMBookletMaskView(frame: CGRect(x: 0, y: 0, width: self.window?.frame.size.width ?? 0, height: self.window?.frame.size.height ?? 0))
  209. }
  210. self.window?.contentView?.addSubview(self.maskView!)
  211. let progress = SKProgressController()
  212. progress.window?.backgroundColor = NSColor.km_init(hex: "#36383B")
  213. progress.window?.contentView?.wantsLayer = true
  214. progress.window?.contentView?.layer?.backgroundColor = NSColor.km_init(hex: "#36383B").cgColor
  215. progress.progressField.textColor = NSColor.white
  216. progress.message = NSLocalizedString("Comparing documents...", comment: "")
  217. progress.closeBlock = { [unowned self] in
  218. }
  219. self.progressController = progress
  220. self.window?.beginSheet(progress.window!)
  221. }
  222. func hideWaitting() {
  223. compareView.doneButton.isEnabled = true
  224. DispatchQueue.main.async {
  225. self.progressController?.doubleValue = 99.0
  226. }
  227. self.maskView?.removeFromSuperview()
  228. if (self.progressController != nil) {
  229. self.window?.endSheet((self.progressController?.window)!)
  230. self.progressController = nil
  231. }
  232. }
  233. }