KMBatchAddHeaderFooterOperation.swift 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. //
  2. // KMBatchAddHeaderFooterOperation.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by liujiajie on 2023/11/7.
  6. //
  7. import Foundation
  8. let supportDirectory = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).last
  9. let mainBundleIdentifier = Bundle.main.bundleIdentifier ?? ""
  10. let kTempSavePath = supportDirectory?.stringByAppendingPathComponent(mainBundleIdentifier)
  11. class KMBatchAddHeaderFooterOperation: KMBatchOperation{
  12. var headerFooter: KMHeaderFooterObject?
  13. var pdfDocument: CPDFDocument?
  14. var password: String?
  15. init(file: KMBatchOperateFile, headerFooter: KMHeaderFooterObject) {
  16. super.init(file: file)
  17. self.headerFooter = headerFooter
  18. }
  19. func currentParameter() -> KMBatchBaseParameter {
  20. return operateFile!.addHeaderFooterInfo
  21. }
  22. override func start() {
  23. self.pdfDocument = CPDFDocument(url: URL(fileURLWithPath: self.operateFile?.filePath ?? ""))
  24. self.password = self.operateFile?.password
  25. if let data = self.pdfDocument?.isLocked, data {
  26. self.pdfDocument?.unlock(withPassword: self.operateFile?.password)
  27. }
  28. if !self.isCancelled {
  29. self.delegate?.fileBeginOperate?(self.operateFile!, info: self.currentParameter())
  30. willChangeValue(forKey: "isExecuting")
  31. self.hasExcuting = true
  32. didChangeValue(forKey: "isExecuting")
  33. if !FileManager.default.fileExists(atPath: self.operateFile!.filePath) {
  34. self.delegate?.fileOperateFailed?(self.operateFile!, error: self.errorWithMsg(KMLocalizedString("File Not Exist")), info: self.operateFile!.removeBatesInfo)
  35. self.willChangeValue(forKey: "isFinished")
  36. self.hasFinished = true
  37. self.didChangeValue(forKey: "isFinished")
  38. return
  39. }
  40. if self.pdfDocument == nil {
  41. self.delegate?.fileOperateFailed?(self.operateFile!, error: self.errorWithMsg(KMLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.")), info: self.operateFile!.removeWatermarkInfo)
  42. self.willChangeValue(forKey: "isFinished")
  43. self.hasFinished = true
  44. self.didChangeValue(forKey: "isFinished")
  45. return
  46. }
  47. if !self.pdfDocument!.allowsPrinting || !self.pdfDocument!.allowsCopying {
  48. self.delegate?.fileOperateFailed?(self.operateFile!, error: self.errorWithMsg(KMLocalizedString("This is a secured document. Editing is not permitted.")), info: self.operateFile!.removeWatermarkInfo)
  49. self.willChangeValue(forKey: "isFinished")
  50. self.hasFinished = true
  51. self.didChangeValue(forKey: "isFinished")
  52. return
  53. }
  54. if let filepath = self.operateFile?.currentOperateInfo?.fetchDestinationFilepath() {
  55. self.saveAsPDFToPath(filepath)
  56. }
  57. }else {
  58. willChangeValue(forKey: "isFinished")
  59. willChangeValue(forKey: "isExecuting")
  60. hasExcuting = false
  61. hasFinished = true
  62. didChangeValue(forKey: "isExecuting")
  63. didChangeValue(forKey: "isFinished")
  64. }
  65. }
  66. override func cancel() {
  67. // super.cancel()
  68. if isExecuting {
  69. operateFile!.removeWatermarkInfo.status = .Waiting
  70. if FileManager.default.fileExists(atPath: self.currentParameter().outPutPath!) { try? FileManager.default.removeItem(atPath: self.currentParameter().outPutPath!)
  71. }
  72. self.delegate?.fileOperateCanceled?(self.operateFile!, info: self.currentParameter())
  73. willChangeValue(forKey: "isFinished")
  74. hasFinished = true
  75. didChangeValue(forKey: "isFinished")
  76. } else {
  77. willChangeValue(forKey: "isCancelled")
  78. hasCanceled = true
  79. didChangeValue(forKey: "isCancelled")
  80. }
  81. }
  82. func saveAsPDFToPath(_ path: String) {
  83. var filePath = self.pdfDocument?.documentURL?.path
  84. let password = self.password
  85. if filePath == nil {
  86. let str = String(format: "%@.pdf", KMLocalizedString("Untitled"))
  87. let writeSuccess = self.pdfDocument!.write(to: URL(fileURLWithPath: (kTempSavePath?.stringByAppendingPathComponent(str))!))
  88. if writeSuccess {
  89. let newDocument: CPDFDocument = CPDFDocument(url: URL(fileURLWithPath: (kTempSavePath?.stringByAppendingPathComponent(str))!))
  90. filePath = newDocument.documentURL?.path
  91. } else {
  92. NSSound.beep()
  93. return
  94. }
  95. }
  96. guard let document = CPDFDocument(url: URL(fileURLWithPath: filePath!)) else {
  97. return
  98. }
  99. if password?.count ?? 0 > 0 {
  100. document.unlock(withPassword: password)
  101. }
  102. // let font = NSFont.boldSystemFont(ofSize: self.headerFooter?.getTextFontSize() ?? 16)
  103. // let style = NSMutableParagraphStyle()
  104. // style.alignment = .center
  105. // style.lineBreakMode = .byCharWrapping
  106. // var dictionary = [NSAttributedString.Key: Any]()
  107. // dictionary[.paragraphStyle] = style
  108. // dictionary[.font] = font
  109. // let size = "text".boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: CGFloat(MAXFLOAT)), options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: dictionary).size
  110. //
  111. // if self.headerFooter!.isBates {
  112. // var bates: CPDFHeaderFooter = document.bates()
  113. // bates.margin = NSEdgeInsets(top: max(CGFloat(self.headerFooter!.topMargin) - size.height, 0), left: CGFloat(self.headerFooter!.leftMargin), bottom: max(CGFloat(self.headerFooter!.bottomMargin) - size.height, 0), right: CGFloat(self.headerFooter!.rightMargin))
  114. //
  115. // var arr = [NSNumber]()
  116. // for i in 0..<(self.operateFile?.addBatesInfo.pagesArray?.count ?? 0) {
  117. // var tmp = self.operateFile?.addBatesInfo.pagesArray?[i].intValue
  118. // tmp! -= 1
  119. // let number = NSNumber(value: tmp ?? 0)
  120. // arr.append(number)
  121. // }
  122. // if arr.count < 1 {
  123. // let error = NSError(domain: "LocalError", code: 0, userInfo: [NSLocalizedDescriptionKey: KMLocalizedString("Invalid page range or the page number is out of range. Please try again.")])
  124. // self.delegate?.fileOperateFailed?(self.operateFile!, error: error, info: self.operateFile!.addBatesInfo)
  125. //
  126. // willChangeValue(forKey: "isFinished")
  127. // self.hasFinished = true
  128. // didChangeValue(forKey: "isFinished")
  129. // return
  130. // }
  131. // let pagesString = arr.map{ "\($0)" }.joined(separator: ",")
  132. // if pagesString.count > 0 {
  133. // bates.pageString = pagesString
  134. // } else {
  135. // let pageString = String(format: "0-%ld", document.pageCount-1)
  136. // bates.pageString = pageString
  137. // }
  138. //
  139. // let topLeftString = self.headerFooter?.topLeftString
  140. // let topCenterString = self.headerFooter?.topCenterString
  141. // let topRightString = self.headerFooter?.topRightString
  142. // let bottomLeftString = self.headerFooter?.bottomLeftString
  143. // let bottomCenterString = self.headerFooter?.bottomCenterString
  144. // let bottomRightString = self.headerFooter?.bottomRightString
  145. // let items = [topLeftString, topCenterString, topRightString, bottomLeftString, bottomCenterString, bottomRightString]
  146. // for i in 0..<items.count {
  147. // let text = items[i]
  148. // bates.setText(text, at: UInt(Int(i)))
  149. // bates.setTextColor(self.headerFooter?.getTextColor(), at: UInt(Int(i)))
  150. // bates.setFontSize(self.headerFooter?.getTextFontSize() ?? 16.0, at: UInt(Int(i)))
  151. // }
  152. //
  153. // bates.update()
  154. // } else {
  155. // let headerFooterNew = document.headerFooter()
  156. // headerFooterNew?.margin = NSEdgeInsets(top: max(CGFloat(self.headerFooter!.topMargin)-size.height, 0), left: CGFloat(self.headerFooter!.leftMargin), bottom: max(CGFloat(self.headerFooter!.bottomMargin)-size.height, 0), right: CGFloat(self.headerFooter!.rightMargin))
  157. //
  158. // var arr = [NSNumber]()
  159. // for i in 0..<(self.operateFile?.addHeaderFooterInfo.pagesArray?.count ?? 0) {
  160. // var tmp = self.operateFile?.addHeaderFooterInfo.pagesArray?[i].intValue
  161. // tmp! -= 1
  162. // let number = NSNumber(value: tmp ?? 0)
  163. // arr.append(number)
  164. // }
  165. // if arr.count < 1 {
  166. // let error = NSError(domain: "LocalError", code: 0, userInfo: [NSLocalizedDescriptionKey: KMLocalizedString("Invalid page range or the page number is out of range. Please try again.")])
  167. // self.delegate?.fileOperateFailed?(self.operateFile!, error: error, info: self.operateFile!.addHeaderFooterInfo)
  168. // willChangeValue(forKey: "isFinished")
  169. // self.hasFinished = true
  170. // didChangeValue(forKey: "isFinished")
  171. // return
  172. // }
  173. // let pagesString = arr.map{ "\($0)" }.joined(separator: ",")
  174. // if pagesString.count > 0 {
  175. // headerFooterNew?.pageString = pagesString
  176. // } else {
  177. // let pageString = String(format: "0-%ld", document.pageCount-1)
  178. // headerFooterNew?.pageString = pageString
  179. // }
  180. // let num: Int = Int(self.headerFooter?.startString ?? "0") ?? 0
  181. // let pageCount = Int(document.pageCount) + num - 1
  182. //
  183. // let topLeftString = convertPageFormat(oldString: self.headerFooter!.topLeftString, startPage: self.headerFooter!.startString,pageCount: "\(pageCount)")
  184. // let topCenterString = convertPageFormat(oldString: self.headerFooter!.topCenterString, startPage: self.headerFooter!.startString,pageCount: "\(pageCount)")
  185. // let topRightString = convertPageFormat(oldString: self.headerFooter!.topRightString, startPage: self.headerFooter!.startString,pageCount: "\(pageCount)")
  186. // let bottomLeftString = convertPageFormat(oldString: self.headerFooter!.bottomLeftString, startPage: self.headerFooter!.startString, pageCount: "\(pageCount)")
  187. // let bottomCenterString = convertPageFormat(oldString: self.headerFooter!.bottomCenterString, startPage: self.headerFooter!.startString,pageCount: "\(pageCount)")
  188. // let bottomRightString = convertPageFormat(oldString: self.headerFooter!.bottomRightString, startPage: self.headerFooter!.startString,pageCount: "\(pageCount)")
  189. // let items = [topLeftString, topCenterString, topRightString, bottomLeftString, bottomCenterString, bottomRightString]
  190. // for i in 0..<items.count {
  191. // let text = items[i]
  192. // headerFooterNew?.setText(text, at: UInt(i))
  193. // headerFooterNew?.setTextColor(self.headerFooter!.getTextColor(), at: UInt(Int(i)))
  194. // headerFooterNew?.setFontSize(self.headerFooter!.getTextFontSize(), at: UInt(Int(i)))
  195. // }
  196. //
  197. // headerFooterNew?.update()
  198. // }
  199. //
  200. // let documentPath = NSTemporaryDirectory()
  201. // let tempPath = documentPath.appending(filePath!.lastPathComponent)
  202. // if FileManager.default.fileExists(atPath: tempPath) {
  203. // try? FileManager.default.removeItem(atPath: tempPath)
  204. // }
  205. //
  206. // let result = document.write(to: URL(fileURLWithPath: tempPath))
  207. // if result {
  208. // if FileManager.default.fileExists(atPath: path) {
  209. // try? FileManager.default.removeItem(atPath: path)
  210. // }
  211. // try? FileManager.default.moveItem(atPath: tempPath, toPath: path)
  212. // } else {
  213. // try? FileManager.default.removeItem(atPath: tempPath)
  214. // }
  215. // if result {
  216. // self.delegate?.fileOperateSuccessed?(self.operateFile!, info: self.currentParameter())
  217. // } else {
  218. // self.delegate?.fileOperateFailed?(self.operateFile!, error: self.defaultError(), info: self.currentParameter())
  219. // }
  220. //
  221. // willChangeValue(forKey: "isFinished")
  222. // self.hasFinished = true
  223. // didChangeValue(forKey: "isFinished")
  224. }
  225. func defaultError() -> NSError {
  226. return errorWithMsg(NSLocalizedString("Failed", comment: ""))
  227. }
  228. }
  229. func convertPageFormat(oldString: String, startPage: String, pageCount: String) -> String {
  230. let pageFormatArray = ["1", "1 of n", "1/n", "Page 1", "Page 1 of n"]
  231. var newString = oldString
  232. for pageFormat in pageFormatArray {
  233. let format = "<<(pageFormat)>>"
  234. if newString.contains(format) {
  235. var tString: String? = nil
  236. if pageFormat == "1" {
  237. tString = "<<\(startPage)>>"
  238. } else if pageFormat == "1 of n" {
  239. tString = "\(startPage) of \(pageCount)"
  240. } else if pageFormat == "1/n" {
  241. tString = "\(startPage)/\(pageCount)"
  242. } else if pageFormat == "Page 1" {
  243. tString = "Page <<\(startPage)>>"
  244. } else if pageFormat == "Page 1 of n" {
  245. tString = "Page <<\(startPage)>> of \(pageCount)"
  246. }
  247. newString = newString.replacingOccurrences(of: format, with: tString ?? "")
  248. }
  249. }
  250. newString = convertDateFormat(oldString: newString)
  251. return newString
  252. }
  253. func convertDateFormat(oldString: String) -> String {
  254. var newString = oldString
  255. for dateFormat in KMHeaderFooterManager.getdateFormatArray() {
  256. if newString.contains(dateFormat) {
  257. let formatString = dateFormat.replacingOccurrences(of: "m", with: "M")
  258. let replace = "<<\(dateFormat)>>"
  259. let date = Date()
  260. let dateFormatter = DateFormatter()
  261. dateFormatter.dateFormat = formatString
  262. let dateString = dateFormatter.string(from: date)
  263. newString = newString.replacingOccurrences(of: replace, with: dateString)
  264. }
  265. }
  266. return newString
  267. }