// // KMBatchAddHeaderFooterOperation.swift // PDF Reader Pro // // Created by liujiajie on 2023/11/7. // import Foundation let supportDirectory = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).last let mainBundleIdentifier = Bundle.main.bundleIdentifier ?? "" let kTempSavePath = supportDirectory?.stringByAppendingPathComponent(mainBundleIdentifier) class KMBatchAddHeaderFooterOperation: KMBatchOperation{ var headerFooter: KMHeaderFooterObject? var pdfDocument: CPDFDocument? var password: String? init(file: KMBatchOperateFile, headerFooter: KMHeaderFooterObject) { super.init(file: file) self.headerFooter = headerFooter } func currentParameter() -> KMBatchBaseParameter { return operateFile!.addHeaderFooterInfo } override func start() { self.pdfDocument = CPDFDocument(url: URL(fileURLWithPath: self.operateFile?.filePath ?? "")) self.password = self.operateFile?.password if let data = self.pdfDocument?.isLocked, data { self.pdfDocument?.unlock(withPassword: self.operateFile?.password) } if !self.isCancelled { self.delegate?.fileBeginOperate?(self.operateFile!, info: self.currentParameter()) willChangeValue(forKey: "isExecuting") self.hasExcuting = true didChangeValue(forKey: "isExecuting") if !FileManager.default.fileExists(atPath: self.operateFile!.filePath) { self.delegate?.fileOperateFailed?(self.operateFile!, error: self.errorWithMsg(KMLocalizedString("File Not Exist")), info: self.operateFile!.removeBatesInfo) self.willChangeValue(forKey: "isFinished") self.hasFinished = true self.didChangeValue(forKey: "isFinished") return } if self.pdfDocument == nil { 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) self.willChangeValue(forKey: "isFinished") self.hasFinished = true self.didChangeValue(forKey: "isFinished") return } if !self.pdfDocument!.allowsPrinting || !self.pdfDocument!.allowsCopying { self.delegate?.fileOperateFailed?(self.operateFile!, error: self.errorWithMsg(KMLocalizedString("This is a secured document. Editing is not permitted.")), info: self.operateFile!.removeWatermarkInfo) self.willChangeValue(forKey: "isFinished") self.hasFinished = true self.didChangeValue(forKey: "isFinished") return } if let filepath = self.operateFile?.currentOperateInfo?.fetchDestinationFilepath() { self.saveAsPDFToPath(filepath) } }else { willChangeValue(forKey: "isFinished") willChangeValue(forKey: "isExecuting") hasExcuting = false hasFinished = true didChangeValue(forKey: "isExecuting") didChangeValue(forKey: "isFinished") } } override func cancel() { // super.cancel() if isExecuting { operateFile!.removeWatermarkInfo.status = .Waiting if FileManager.default.fileExists(atPath: self.currentParameter().outPutPath!) { try? FileManager.default.removeItem(atPath: self.currentParameter().outPutPath!) } self.delegate?.fileOperateCanceled?(self.operateFile!, info: self.currentParameter()) willChangeValue(forKey: "isFinished") hasFinished = true didChangeValue(forKey: "isFinished") } else { willChangeValue(forKey: "isCancelled") hasCanceled = true didChangeValue(forKey: "isCancelled") } } func saveAsPDFToPath(_ path: String) { var filePath = self.pdfDocument?.documentURL?.path let password = self.password if filePath == nil { let str = String(format: "%@.pdf", KMLocalizedString("Untitled")) let writeSuccess = self.pdfDocument!.write(to: URL(fileURLWithPath: (kTempSavePath?.stringByAppendingPathComponent(str))!)) if writeSuccess { let newDocument: CPDFDocument = CPDFDocument(url: URL(fileURLWithPath: (kTempSavePath?.stringByAppendingPathComponent(str))!)) filePath = newDocument.documentURL?.path } else { NSSound.beep() return } } guard let document = CPDFDocument(url: URL(fileURLWithPath: filePath!)) else { return } if password?.count ?? 0 > 0 { document.unlock(withPassword: password) } // let font = NSFont.boldSystemFont(ofSize: self.headerFooter?.getTextFontSize() ?? 16) // let style = NSMutableParagraphStyle() // style.alignment = .center // style.lineBreakMode = .byCharWrapping // var dictionary = [NSAttributedString.Key: Any]() // dictionary[.paragraphStyle] = style // dictionary[.font] = font // let size = "text".boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: CGFloat(MAXFLOAT)), options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: dictionary).size // // if self.headerFooter!.isBates { // var bates: CPDFHeaderFooter = document.bates() // 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)) // // var arr = [NSNumber]() // for i in 0..<(self.operateFile?.addBatesInfo.pagesArray?.count ?? 0) { // var tmp = self.operateFile?.addBatesInfo.pagesArray?[i].intValue // tmp! -= 1 // let number = NSNumber(value: tmp ?? 0) // arr.append(number) // } // if arr.count < 1 { // let error = NSError(domain: "LocalError", code: 0, userInfo: [NSLocalizedDescriptionKey: KMLocalizedString("Invalid page range or the page number is out of range. Please try again.")]) // self.delegate?.fileOperateFailed?(self.operateFile!, error: error, info: self.operateFile!.addBatesInfo) // // willChangeValue(forKey: "isFinished") // self.hasFinished = true // didChangeValue(forKey: "isFinished") // return // } // let pagesString = arr.map{ "\($0)" }.joined(separator: ",") // if pagesString.count > 0 { // bates.pageString = pagesString // } else { // let pageString = String(format: "0-%ld", document.pageCount-1) // bates.pageString = pageString // } // // let topLeftString = self.headerFooter?.topLeftString // let topCenterString = self.headerFooter?.topCenterString // let topRightString = self.headerFooter?.topRightString // let bottomLeftString = self.headerFooter?.bottomLeftString // let bottomCenterString = self.headerFooter?.bottomCenterString // let bottomRightString = self.headerFooter?.bottomRightString // let items = [topLeftString, topCenterString, topRightString, bottomLeftString, bottomCenterString, bottomRightString] // for i in 0.. 0 { // headerFooterNew?.pageString = pagesString // } else { // let pageString = String(format: "0-%ld", document.pageCount-1) // headerFooterNew?.pageString = pageString // } // let num: Int = Int(self.headerFooter?.startString ?? "0") ?? 0 // let pageCount = Int(document.pageCount) + num - 1 // // let topLeftString = convertPageFormat(oldString: self.headerFooter!.topLeftString, startPage: self.headerFooter!.startString,pageCount: "\(pageCount)") // let topCenterString = convertPageFormat(oldString: self.headerFooter!.topCenterString, startPage: self.headerFooter!.startString,pageCount: "\(pageCount)") // let topRightString = convertPageFormat(oldString: self.headerFooter!.topRightString, startPage: self.headerFooter!.startString,pageCount: "\(pageCount)") // let bottomLeftString = convertPageFormat(oldString: self.headerFooter!.bottomLeftString, startPage: self.headerFooter!.startString, pageCount: "\(pageCount)") // let bottomCenterString = convertPageFormat(oldString: self.headerFooter!.bottomCenterString, startPage: self.headerFooter!.startString,pageCount: "\(pageCount)") // let bottomRightString = convertPageFormat(oldString: self.headerFooter!.bottomRightString, startPage: self.headerFooter!.startString,pageCount: "\(pageCount)") // let items = [topLeftString, topCenterString, topRightString, bottomLeftString, bottomCenterString, bottomRightString] // for i in 0.. NSError { return errorWithMsg(NSLocalizedString("Failed", comment: "")) } } func convertPageFormat(oldString: String, startPage: String, pageCount: String) -> String { let pageFormatArray = ["1", "1 of n", "1/n", "Page 1", "Page 1 of n"] var newString = oldString for pageFormat in pageFormatArray { let format = "<<(pageFormat)>>" if newString.contains(format) { var tString: String? = nil if pageFormat == "1" { tString = "<<\(startPage)>>" } else if pageFormat == "1 of n" { tString = "\(startPage) of \(pageCount)" } else if pageFormat == "1/n" { tString = "\(startPage)/\(pageCount)" } else if pageFormat == "Page 1" { tString = "Page <<\(startPage)>>" } else if pageFormat == "Page 1 of n" { tString = "Page <<\(startPage)>> of \(pageCount)" } newString = newString.replacingOccurrences(of: format, with: tString ?? "") } } newString = convertDateFormat(oldString: newString) return newString } func convertDateFormat(oldString: String) -> String { var newString = oldString for dateFormat in KMHeaderFooterManager.getdateFormatArray() { if newString.contains(dateFormat) { let formatString = dateFormat.replacingOccurrences(of: "m", with: "M") let replace = "<<\(dateFormat)>>" let date = Date() let dateFormatter = DateFormatter() dateFormatter.dateFormat = formatString let dateString = dateFormatter.string(from: date) newString = newString.replacingOccurrences(of: replace, with: dateString) } } return newString }