// // KMBatchAddBackgroundOperation.swift // PDF Reader Pro // // Created by liujiajie on 2023/12/11. // import Foundation class KMBatchAddBackgroundOperation: KMBatchOperation{ var background: KMBackgroundModel? var pdfDocument: CPDFDocument! var password: String = "" init(file: KMBatchOperateFile, backgroundM: KMBackgroundModel) { super.init(file: file) self.background = backgroundM self.password = file.password } override func start() { self.pdfDocument = CPDFDocument(url: URL(fileURLWithPath: self.operateFile?.filePath ?? "")) if let data = self.pdfDocument?.isLocked, data { self.pdfDocument?.unlock(withPassword: self.operateFile?.password) } if !self.isCancelled { self.delegate?.fileBeginOperate?(self.operateFile!, info: self.operateFile!.addBackgroundInfo) willChangeValue(forKey: "isExecuting") self.hasExcuting = true didChangeValue(forKey: "isExecuting") let newArr = NSMutableArray() for i in 0..<(self.operateFile?.addBackgroundInfo.pagesArray?.count ?? 0) { let number = self.operateFile?.addBackgroundInfo.pagesArray![i] newArr.add(number!.intValue - 1) } if !FileManager.default.fileExists(atPath: self.operateFile!.filePath) { self.delegate?.fileOperateFailed?(self.operateFile!, error: self.errorWithMsg(KMLocalizedString("File Not Exist", nil)), info: self.operateFile!.addBackgroundInfo) 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.", nil)), info: self.operateFile!.addBackgroundInfo) 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.", nil)), info: self.operateFile!.addBackgroundInfo) self.willChangeValue(forKey: "isFinished") self.hasFinished = true self.didChangeValue(forKey: "isFinished") return } if newArr.count < 1 { let err = NSError(domain: "LocalError", code: 0, userInfo: [NSLocalizedDescriptionKey: KMLocalizedString("Invalid page range or the page number is out of range. Please try again.", nil)]) self.delegate?.fileOperateFailed?(self.operateFile!, error: err, info: self.operateFile!.addBackgroundInfo) self.willChangeValue(forKey: "isFinished") self.hasFinished = true self.didChangeValue(forKey: "isFinished") } self.background?.pagesString = newArr.componentsJoined(by: ",") self.saveAsPDF(background: self.background!, path: (self.operateFile?.addBackgroundInfo.fetchDestinationFilepath())!) }else { willChangeValue(forKey: "isFinished") willChangeValue(forKey: "isExecuting") hasExcuting = false hasFinished = true didChangeValue(forKey: "isExecuting") didChangeValue(forKey: "isFinished") } } func saveAsPDF(background: KMBackgroundModel, path: String) { var filePath = self.pdfDocument?.documentURL?.path let password = self.password if filePath?.count ?? 0 < 1 { let str = String(format: "%@.pdf", KMLocalizedString("Untitled", nil)) 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 { document.unlock(withPassword: password) } let tBackground: CPDFBackground = document.background() tBackground.opacity = background.opacity tBackground.scale = background.scale tBackground.rotation = CGFloat(-background.rotation) tBackground.horizontalAlignment = UInt(background.horizontalMode) tBackground.verticalAlignment = UInt(background.verticalMode) tBackground.xOffset = background.horizontalSpace tBackground.yOffset = background.verticalSpace if background.imagePath.count != 0 { let image = NSImage(contentsOfFile: background.imagePath)! tBackground.setImage(image) tBackground.type = .image } else if let color = background.color { tBackground.color = color tBackground.type = .color } if background.pagesString.count != 0 { tBackground.pageString = background.pagesString } else { let pageString = "0-\(document.pageCount - 1)" tBackground.pageString = pageString } tBackground.update() // Save to temporary path let documentPath = NSTemporaryDirectory() let tempPath = (documentPath as NSString).appendingPathComponent((path as NSString).lastPathComponent) try? FileManager.default.removeItem(atPath: tempPath) let result = document.write(to: URL(fileURLWithPath: tempPath)) if result { if FileManager.default.fileExists(atPath: path) { try? FileManager.default.removeItem(atPath: path) } try? FileManager.default.moveItem(atPath: tempPath, toPath: path) } else { try? FileManager.default.removeItem(atPath: tempPath) } if result { self.delegate?.fileOperateSuccessed?(self.operateFile!, info: self.operateFile!.addBackgroundInfo) }else { self.delegate?.fileOperateFailed?(self.operateFile!, error: self.errorWithMsg(KMLocalizedString("Failed", nil)), info: self.operateFile!.addBackgroundInfo) } self.willChangeValue(forKey: "isFinished") self.hasFinished = true self.didChangeValue(forKey: "isFinished") } override func cancel() { // super.cancel() if isExecuting { operateFile!.removeWatermarkInfo.status = .Waiting if FileManager.default.fileExists(atPath: (self.operateFile?.addBackgroundInfo.outPutPath)!) { try? FileManager.default.removeItem(atPath: (self.operateFile?.addBackgroundInfo.outPutPath)!) } self.delegate?.fileOperateCanceled?(self.operateFile!, info: self.operateFile!.addBackgroundInfo) willChangeValue(forKey: "isFinished") hasFinished = true didChangeValue(forKey: "isFinished") } else { willChangeValue(forKey: "isCancelled") hasCanceled = true didChangeValue(forKey: "isCancelled") } } }