// // KMNHomeViewController.swift // PDF Reader Pro // // Created by Niehaoyu on 2024/10/8. // import Cocoa import KMComponentLibrary class KMNHomeViewController: NSViewController { @IBOutlet var leftContendBox: NSBox! @IBOutlet var leftDivider: ComponentDivider! @IBOutlet var homeOpenView: KMHomeOpenView! @IBOutlet var homeRecommondView: KMHomeRecommondView! @IBOutlet var rightContendBox: NSBox! @IBOutlet var rightInfoView: KMHomeRightView! @IBOutlet var homeDragView: KMHomeDragView! var demoVC: WCCompWindowController = WCCompWindowController(windowNibName: "WCCompWindowController") //合并 var mergeWindowController: KMMergeWindowController? override func viewDidLoad() { super.viewDidLoad() // Do view setup here. self.configLeftContendView() self.configRightContendView() self.initAdvertisementData() homeDragView.delegate = self } override func viewDidAppear() { super.viewDidAppear() rightInfoView.resetScrollerStyle() rightInfoView.reloadData() } func configLeftContendView() { leftContendBox.fillColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg/layout-middle") leftDivider.properties = ComponentDividerProperty(type: .vertical, dash: false) homeOpenView.delegate = self self.homeRecommondView.reloadData() } func configRightContendView() { rightContendBox.fillColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg/layout-low") rightInfoView.delegate = self rightInfoView.reloadData() } func initAdvertisementData() { KMAdvertisementManager.manager.fetchDataWithResponseObject { [weak self] data, responseObject, error in KMPrint("获取广告数据成功") if data != nil { let content = data!.recommondContent let item = content?.recommondContentPDFPro var infos: [KMAdvertisementItemInfo] = [] for info in item?.content ?? [] { if info.version == "recommondPDF-PDFtoOfficePack" { if IAPProductsManager.default().isAvailableAdvancedPDFToOffice() == false { infos.append(info) } } else { infos.append(info) } } item?.content = infos if KMAdvertisementManager.manager.infoDict.allKeys.count > 0 { if let adsInfo = KMAdvertisementManager.manager.infoDict["adsInfo"] { let infoDict: NSDictionary = KMAdvertisementManager.manager.infoDict["adsInfo"] as! NSDictionary let array: [[String: Any]] = infoDict["content"] as! [[String : Any]] let arrM = NSMutableArray.init() for dict in array { let adsInfo = KMAdsInfo.init() let mutableDictionary = NSMutableDictionary(dictionary: dict) adsInfo.infoDict = mutableDictionary arrM.add(adsInfo) } KMAdsInfoManager.shareInstance.adsInfoArrM = arrM } if let couponInfo = KMAdvertisementManager.manager.infoDict["couponContent"] { let infoDict: NSDictionary = KMAdvertisementManager.manager.infoDict["couponContent"] as! NSDictionary let array: [[String: Any]] = infoDict["content"] as! [[String : Any]] if array.isEmpty == false { let dict = array[0] let adsInfo = KMCouponInfo.init() let mutableDictionary = NSMutableDictionary(dictionary: dict) adsInfo.infoDict = mutableDictionary KMAdsInfoManager.shareInstance.couponInfo = adsInfo } } } } DispatchQueue.main.async { self?.homeRecommondView.reloadData() } } } @IBAction func showDemo(_ sender: Any) { demoVC.window?.center() demoVC.showWindow(nil) } } //MARK: - KMHomeOpenViewDelegate extension KMNHomeViewController: KMHomeOpenViewDelegate { func homeOpenViewDidChooseFileURL(_ view: KMHomeOpenView?, _ url: URL) { self.openFile(withFilePath: url) } func homeOpenViewDidChooseImageURLs(_ view: KMHomeOpenView?, _ urls: [URL]) { self.openImageToPdfWindow(urls: urls) } func homeOpenViewDidChooseCreateFromClipboard(_ view: KMHomeOpenView?) { var error: NSError? let pboard = NSPasteboard.general var document = openDocumentWithImageFromPasteboard(pboard, error: &error) if document == nil{ document = openDocument(withURLFromPasteboard: pboard, showNotes: false, error: &error) } } } //MARK: - KMHomeRightViewDelegate extension KMNHomeViewController: KMHomeRightViewDelegate { //点击管理快捷工具按钮 func homeRightViewDidManageQuickTools(_ view: KMHomeRightView) { let quickToolWindowController: KMNQuickToolWindowController = KMNQuickToolWindowController.init(windowNibName: "KMNQuickToolWindowController") quickToolWindowController.delegate = self quickToolWindowController.own_beginSheetModal(for: self.view.window) { string in } } //点击快捷工具列表中的某一项 func homeRightViewDidQuickToolsItemClicked(_ view: KMHomeRightView, _ toolType: HomeQuickToolType) { self.quickToolsActionWith(toolType) } //最近文件列表删除更新结束后回调 func homeRightViewDidRecentFilesUpdated(_ view: KMHomeRightView) { } //选择打开文件 func homeRightViewDidChooseFileToOpen(_ view: KMHomeRightView, _ fileURL: URL) { self.openFile(withFilePath: fileURL) } } //MARK: - KMNQuickToolWindowDelegate extension KMNHomeViewController: KMNQuickToolWindowDelegate { func quickToolWindowControllerUpdate() { rightInfoView.reloadData() } } //MARK: - KMHomeDragViewDelegate extension KMNHomeViewController: KMHomeDragViewDelegate { func homeDragView(_ viewController: KMHomeDragView, filePath: URL) { self.openFile(withFilePath: filePath) } func homeDragView(_ viewController: KMHomeDragView, notSupport: Bool) { if notSupport { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("This file format is not supported. Please enter PDF, picture, or Office file", comment: "") alert.runModal() } } } //MARK: - Open Files extension KMNHomeViewController { func openFile(withFilePath path: URL) -> Void { let type = path.pathExtension.lowercased() if (type == "pdf") { self.openHistoryFilePath(url: path) } else if (type == "jpg") || (type == "cur") || (type == "bmp") || (type == "jpeg") || (type == "gif") || (type == "png") || (type == "tiff") || (type == "tif") || (type == "ico") || (type == "icns") || (type == "tga") || (type == "psd") || (type == "eps") || (type == "hdr") || (type == "jp2") || (type == "jpc") || (type == "pict") || (type == "sgi") || (type == "heic") { openImageFile(url: path) } else if (type == "doc") || (type == "docx") || (type == "xls") || (type == "xlsx") || (type == "ppt") || (type == "pptx") || (type == "pptx") { let fileName: NSString = String(format: "%@.pdf", NSLocalizedString("Untitled", comment: "")) as NSString let savePath = fetchUniquePath(fileName.kUrlToPDFFolderPath() as String) openOfficeFile(url: path) } DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) { self.rightInfoView.reloadData() } } func openHistoryFilePath(url: URL) -> Void { if !url.path.isPDFValid() { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", comment: "") alert.beginSheetModal(for: view.window!) { [weak self] result in self?.rightInfoView.reloadData() } return } if url.pathExtension.lowercased() == "pdf" { let pdfDoc = CPDFDocument.init(url: url) if pdfDoc != nil { let document = NSDocumentController.shared.document(for: url) var alreadyOpen = false for openDocument in NSDocumentController.shared.documents { if document == openDocument { alreadyOpen = true } } if !alreadyOpen { let controll: KMBrowserWindowController? = self.view.window?.windowController as? KMBrowserWindowController if controll?.browser?.tabCount() ?? 0 > 1{ if !IAPProductsManager.default().isAvailableAllFunction() { showLimitWindowAlert(url: url) return }else { } } } KMMainDocument().tryToUnlockDocument(pdfDoc!) var selectDocument: KMMainDocument? = nil if ((document?.isKind(of: KMMainDocument.self)) != nil) { selectDocument = (document as! KMMainDocument) } if selectDocument != nil { if selectDocument?.browser != nil { let currentIndex = selectDocument?.browser.tabStripModel.index(of: selectDocument) ?? 0 selectDocument?.browser.tabStripModel.selectTabContents(at: Int32(currentIndex), userGesture: true) let isVisible: Bool = selectDocument?.browser.window.isVisible ?? false let isMiniaturized: Bool = selectDocument?.browser.window.isMiniaturized ?? false if isVisible { selectDocument?.browser.window.orderFront(nil) } else if isMiniaturized { selectDocument?.browser.window.orderFront(nil) } } } else { NSDocumentController.shared.km_safe_openDocument(withContentsOf: url, display: true) { _, _, _ in } } } else { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", comment: "") alert.beginSheetModal(for: view.window!) { [weak self] result in self?.rightInfoView.reloadData() } } } else { NSWorkspace.shared.open(url) } } func openImageFile(url: URL) -> Void { var filePath = url.path let fileName: NSString = url.lastPathComponent as NSString let savePath = fetchUniquePath(fileName.kUrlToPDFFolderPath() as String).deletingLastPathComponent let imageName = NSString(string: NSString(string: filePath).lastPathComponent).deletingPathExtension let path = self.fetchDifferentFilePath(filePath: savePath + "/" + imageName + ".pdf") if (!FileManager.default.fileExists(atPath: path.deletingLastPathComponent as String)) { try?FileManager.default.createDirectory(atPath: path.deletingLastPathComponent as String, withIntermediateDirectories: true, attributes: nil) } if (!FileManager.default.fileExists(atPath: path as String)) { FileManager.default.createFile(atPath: path as String, contents: nil) } let document = CPDFDocument.init() var success = false if NSString(string: NSString(string: filePath).lastPathComponent).pathExtension == "png" || NSString(string: NSString(string: filePath).lastPathComponent).pathExtension == "PNG" { let jpgPath = self.fetchDifferentFilePath(filePath: savePath + "/" + imageName + ".jpg") if (!FileManager.default.fileExists(atPath: jpgPath as String)) { FileManager.default.createFile(atPath: jpgPath as String, contents: nil) } // 加载 PNG 图像 guard let pngImage = NSImage(contentsOfFile: filePath) else { KMPrint("Failed to load PNG image") return } // 创建 NSBitmapImageRep 对象,并将 PNG 图像绘制到其中 let bitmap = NSBitmapImageRep(data: pngImage.tiffRepresentation!) guard let bitmap = bitmap else { return } let rect = NSRect(origin: .zero, size: bitmap.size) bitmap.draw(in: rect) // 将 PNG 图像数据转换为 JPG 图像数据 guard let jpgData = bitmap.representation(using: .jpeg, properties: [:]) else { KMPrint("Failed to convert PNG to JPG") return } // 保存 JPG 图像数据到文件 let fileURL = URL(fileURLWithPath: jpgPath) do { try jpgData.write(to: fileURL) filePath = fileURL.path KMPrint("JPG image saved successfully") } catch { KMPrint("Failed to save JPG image: \(error.localizedDescription)") } } let image = NSImage(contentsOfFile: filePath) let insertPageSuccess = document?.insertPage(image!.size, withImage: filePath, at: document!.pageCount) if insertPageSuccess != nil { //信号量控制异步 let semaphore = DispatchSemaphore(value: 0) DispatchQueue.global().async { success = ((document?.write(toFile: path)) != nil) semaphore.signal() } semaphore.wait() } else { } if success { NSDocumentController.shared.km_safe_openDocument(withContentsOf: URL(fileURLWithPath: path), display: true) { document, isOpened, error in if error != nil { NSApp.presentError(error!) } else { if FileManager.default.fileExists(atPath: filePath) { try? FileManager.default.removeItem(atPath: filePath) } if document is KMMainDocument { let newDocument = document (newDocument as! KMMainDocument).isNewCreated = true } } } } } func openOfficeFile(url: URL) -> Void { let filePath = url.path let folderPath = "convertToPDF.pdf" let savePath: String? = folderPath.kUrlToPDFFolderPath() as String if (!FileManager.default.fileExists(atPath: savePath!.deletingLastPathComponent as String)) { try?FileManager.default.createDirectory(atPath: savePath!.deletingLastPathComponent as String, withIntermediateDirectories: true, attributes: nil) } if (!FileManager.default.fileExists(atPath: savePath! as String)) { FileManager.default.createFile(atPath: savePath! as String, contents: nil) } if savePath == nil { return } KMConvertPDFManager.convertFile(filePath, savePath: savePath!) { success, errorDic in if errorDic != nil || !success || !FileManager.default.fileExists(atPath: savePath!) { if FileManager.default.fileExists(atPath: savePath!) { try?FileManager.default.removeItem(atPath: savePath!) } let alert = NSAlert.init() alert.alertStyle = .critical var infoString = "" if errorDic != nil { for key in (errorDic! as Dictionary).keys { infoString = infoString.appendingFormat("%@\n", errorDic![key] as! CVarArg) } } alert.informativeText = NSLocalizedString("Please install Microsoft Office to create PDFs from Office files", comment: "") alert.messageText = NSLocalizedString("Failed to Create PDF", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) alert.runModal() return } NSDocumentController.shared.km_safe_openDocument(withContentsOf: URL(fileURLWithPath: savePath!), display: true) { _, _, _ in } } } func openImageToPdfWindow(urls: Array) { var arr: Array = Array() for fileURL in urls { let img = NSImage(contentsOfFile: fileURL.path) if self.isDamageImage(image: img, path: fileURL.path) { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = String(format: NSLocalizedString("The file \"%@\" could not be opened.", comment: ""), fileURL.path.lastPathComponent) alert.informativeText = NSLocalizedString("It may be damaged or use a file format that PDF Reader Pro doesn’t recognize.", comment: "") alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) alert.beginSheetModal(for: NSApp.mainWindow!) { (response) in if response == .alertFirstButtonReturn { // Handle cancel action } } continue } let file = KMBatchOperateFile(filePath: fileURL.path, type: .CreatePDF) arr.append(file) } let baseWindowController = KMBatchOperateBaseWindowController(windowNibName: "KMBatchOperateBaseWindowController") if #available(macOS 10.13, *) { baseWindowController.window?.makeKeyAndOrderFront(nil) } else { baseWindowController.showWindow(nil) } if arr.count > 0 { baseWindowController.checkNeedPasswordSwitchToOperateType(operateType: .CreatePDF, files: arr) } } func openDocumentWithImageFromPasteboard(_ pboard: NSPasteboard, error outError: AutoreleasingUnsafeMutablePointer?) -> Any? { var document: CPDFDocument? = nil var data: Data? = nil if pboard.canReadItem(withDataConformingToTypes: [NSPasteboard.PasteboardType.pdf.rawValue]) { // pboard.types data = pboard.data(forType: NSPasteboard.PasteboardType.pdf) } else if pboard.canReadItem(withDataConformingToTypes: [NSPasteboard.PasteboardType.postScript.rawValue]) { // pboard.types data = pboard.data(forType: NSPasteboard.PasteboardType.postScript) } else if pboard.canReadItem(withDataConformingToTypes: [NSPasteboard.PasteboardType.tiff.rawValue]) { // pboard.types data = convertTIFFDataToPDF(pboard.data(forType: NSPasteboard.PasteboardType.tiff) ?? Data()) } else { let images = pboard.readObjects(forClasses: [NSImage.self], options: [:]) let strings = pboard.readObjects(forClasses: [NSAttributedString.self], options: [:]) if images?.count ?? 0 > 0 { data = convertTIFFDataToPDF((images![0] as AnyObject).tiffRepresentation!) } else if strings?.count ?? 0 > 0 { data = KMOCTool.convertStringsToPDF(withString: strings ?? [""]) // convertStringsToPDF(strings!) } } if let data = data { _ = NSDocumentController.shared document = CPDFDocument(data: data) let fileName: NSString = String(format: "%@.pdf", NSLocalizedString("Untitled", comment: "")) as NSString let savePath = fetchUniquePath(fileName.kUrlToPDFFolderPath() as String) let filePath = savePath.deletingLastPathComponent if FileManager.default.fileExists(atPath: filePath) == false { try?FileManager.default.createDirectory(atPath: filePath, withIntermediateDirectories: false) } document?.write(to: URL(fileURLWithPath: savePath)) NSDocumentController.shared.openDocument(withContentsOf: URL(fileURLWithPath: savePath), display: true) { document, documentWasAlreadyOpen, error in if error != nil { NSApp.presentError(error!) } else { if document is KMMainDocument { let newDocument = document (newDocument as! KMMainDocument).isNewCreated = true } } } } else if let outError = outError { outError.pointee = NSError(domain: "SKDocumentErrorDomain", code: 3, userInfo: [NSLocalizedDescriptionKey: NSLocalizedString("Unable to load data from clipboard", comment: "Error description")]) } return document } func openDocument(withURLFromPasteboard pboard: NSPasteboard, showNotes: Bool, error outError: inout NSError?) -> Any? { let theURLs = NSURL.readURLs(from: pboard) let url = theURLs?.count ?? 0 > 0 ? theURLs?[0] : nil let theURL: NSURL? = url as? NSURL let documentC = NSDocumentController.shared var document: NSDocument? = nil if (theURL as AnyObject).isFileURL == true { var _: NSError? = nil let type = try? documentC.typeForContents(of: theURL as! URL)//ForContents(ofURL: theURL, error: &error) if showNotes == false || NSDocument.readableTypes.contains(type ?? "") { documentC.openDocument(withContentsOf: theURL as! URL, display: true, completionHandler: { resultDocument, success, err in document = resultDocument }) } else if NSDocument.readableTypes.contains(type ?? "") { for doc in documentC.documents { let sel = NSSelectorFromString("sourceFileURL") if doc.responds(to: sel) && doc.fileURL == theURL as? URL { document = doc break } } if let document: NSDocument = document { document.showWindows() } else { if let document = try? documentC.makeUntitledDocument(ofType: KMNotesDocumentType) { document.fileURL = URL(fileURLWithPath: theURL?.path ?? "") documentC.addDocument(document) document.makeWindowControllers() document.showWindows() } } } } return document } func showLimitWindowAlert(url: URL?) { if !KMDataManager.default.isTabbingWin{ KMDataManager.default.isTabbingWin = true let tabbingWin: KMTabbingHintWindowController = KMTabbingHintWindowController() tabbingWin.selectCallBack = {[weak self] continueOrNot in KMDataManager.default.isTabbingWin = false if continueOrNot { self?.reopenDocument(forPaths: url) } else { } } self.km_beginSheet(windowC: tabbingWin) } } func reopenDocument(forPaths path: URL?) -> Void { if path == nil { let browser = KMBrowser.init() as KMBrowser browser.windowController = KMBrowserWindowController.init(browser: browser) browser.addHomeTabContents() browser.windowController.showWindow(self) }else { let browser = KMBrowser.init() as KMBrowser browser.windowController = KMBrowserWindowController.init(browser: browser) browser.addHomeTabContents() browser.windowController.showWindow(self) NSDocumentController.shared.km_safe_openDocument(withContentsOf: path!, display: true) { doc, open, err in } } } func fetchUniquePath(_ originalPath: String) -> String { var path = originalPath let dManager = FileManager.default if !dManager.fileExists(atPath: path) { if path.extension.count < 1 { path = path.stringByAppendingPathExtension("pdf") } return path } else { let originalFullFileName = path.lastPathComponent let originalFileName = path.lastPathComponent.deletingPathExtension.lastPathComponent let originalExtension = path.extension let startIndex: Int = 0 let endIndex: Int = startIndex + originalPath.count - originalFullFileName.count - 1 let fileLocatePath = originalPath.substring(to: endIndex) var i = 1 while (1 != 0) { var newName = String(format: "%@%ld", originalFileName, i) newName = String(format: "%@%@", newName, originalExtension) let newPath = fileLocatePath.stringByAppendingPathComponent(newName) if !dManager.fileExists(atPath: newPath) { return newPath } else { i+=1 continue } } } } func fetchDifferentFilePath(filePath: String) -> String { var resultFilePath = filePath var index: Int = 0 while (FileManager.default.fileExists(atPath: resultFilePath)) { index += 1 let path = NSString(string: filePath).deletingPathExtension + "(" + String(index) + ")" resultFilePath = NSString(string: path).appendingPathExtension(NSString(string: filePath).pathExtension)! } return resultFilePath; } func isDamageImage(image: NSImage?, path: String) -> Bool { if (image == nil) { return true } let addImageAnnotation = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).last!.appendingPathComponent(Bundle.main.bundleIdentifier!).appendingPathComponent("addImageAnnotation") if !FileManager.default.fileExists(atPath: addImageAnnotation.path) { try? FileManager.default.createDirectory(atPath: addImageAnnotation.path, withIntermediateDirectories: false, attributes: nil) } guard let data = image!.tiffRepresentation else { return false } guard let imageRep = NSBitmapImageRep(data: data) else { return false } imageRep.size = image!.size var imageData: Data? if path.lowercased() == "png" { imageData = imageRep.representation(using: .png, properties: [:]) } else { imageData = imageRep.representation(using: .jpeg, properties: [:]) } let rPath: URL = addImageAnnotation.appendingPathComponent(tagString()).appendingPathExtension("png") if let data = imageData { try?data.write(to: rPath) return false } else { return true } } func tagString() -> String { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyMMddHHmmss" let currentDate = Date() let randomNum = Int(arc4random_uniform(10000)) let str = String(format: "%@%04d", dateFormatter.string(from: Date()),randomNum) return str } func convertTIFFDataToPDF(_ tiffData: Data) -> Data? { guard let imsrc = CGImageSourceCreateWithData(tiffData as CFData, [kCGImageSourceTypeIdentifierHint: kUTTypeTIFF] as CFDictionary), CGImageSourceGetCount(imsrc) > 0, let cgImage = CGImageSourceCreateImageAtIndex(imsrc, 0, nil) else { return nil } let pdfData = NSMutableData(capacity: tiffData.count) let consumer = CGDataConsumer(data: pdfData! as CFMutableData)! var rect = CGRect(x: 0, y: 0, width: CGFloat(cgImage.width), height: CGFloat(cgImage.height)) let ctxt = CGContext(consumer: consumer, mediaBox: &rect, nil) ctxt!.beginPDFPage(nil) ctxt!.draw(cgImage, in: rect) ctxt!.endPDFPage() ctxt!.closePDF() return pdfData as? Data } } //MARK: - Quick Tools Action extension KMNHomeViewController { func quickToolsActionWith(_ type: HomeQuickToolType) { switch type { case .Batch: fastTool_Batch() break case .MergePDF: fastTool_MergePDF() break case .ImageToPDF: imageToPDFAction() break case .OCR: fastTool_OCR() break case .ConvertPDF: fastTool_ConvertPDF() break case .PDFToWord: fastTool_ConvertPDF() break case .PDFToExcel: fastTool_PDFToExcel() break case .Compression: fastTool_Compression() break case .PDFToPPT: fastTool_PDFToPPT() break case .Security: fastTool_Security() break case .FileCompare: fastTool_FileCompare() break case .Watermark: fastTool_Watermark() break case .Insert: fastTool_Insert() break case .Extract: fastTool_Extract() break case .DigitalSignature: break case .Print: fastTool_Print() break } } func imageToPDFAction() { let openPanel = NSOpenPanel() openPanel.allowedFileTypes = KMImageToPDFMethod.supportedImageTypes() //MARK: 允许多选还是单选,如果是付费用户允许多选 openPanel.allowsMultipleSelection = true openPanel.message = NSLocalizedString("Select images to create a new document. To select multiple files press cmd ⌘ button on keyboard and click on the target files one by one.", comment: "") if IAPProductsManager.default().isAvailableAllFunction(){ openPanel.allowsMultipleSelection = true } else { openPanel.allowsMultipleSelection = false } openPanel.beginSheetModal(for: NSWindow.currentWindow()) {[weak self] result in if result == NSApplication.ModalResponse.OK { guard let weakSelf = self else { return } let urls = openPanel.urls as [URL] weakSelf.openImageToPdfWindow(urls: urls) } } } func fastTool_Batch() { // Batch if !IAPProductsManager.default().isAvailableAllFunction(){ KMPurchaseCompareWindowController.sharedInstance().showWindow(nil) return } let batchWindowController = KMBatchOperateWindowController.sharedWindowController batchWindowController.window?.makeKeyAndOrderFront("") } func fastTool_MergePDF() { // MergePDF mergeWindowController = KMMergeWindowController(windowNibName: "KMMergeWindowController") mergeWindowController!.type = .merge mergeWindowController!.cancelAction = { [unowned self] controller in self.view.window?.endSheet((self.mergeWindowController!.window)!) } view.window?.beginSheet(mergeWindowController!.window!) } func fastTool_OCR() { // OCR if !IAPProductsManager.default().isAvailableAllFunction(){ let winC = KMPurchaseCompareWindowController.sharedInstance() winC?.showWindow(nil) return } let openPanel = NSOpenPanel() var arr = KMImageToPDFMethod.supportedImageTypes() arr.append("pdf") openPanel.allowedFileTypes = arr openPanel.allowsMultipleSelection = false openPanel.beginSheetModal(for: NSWindow.currentWindow()) { [self] (result) in if result == NSApplication.ModalResponse.OK { quickOcr(urls: openPanel.urls) } } } func quickOcr(urls: Array) { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) { var document: CPDFDocument? for fileURL in urls { if fileURL.lastPathComponent.pathExtension == "pdf"{ document = CPDFDocument(url: fileURL) }else{ document = CPDFDocument() let image = NSImage(contentsOfFile: fileURL.path) _ = document?.km_insertPage(image!.size, withImage: fileURL.path, at: 0) } break } if document == nil{ let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", comment: "") alert.beginSheetModal(for: NSApp.mainWindow!) { (response) in if response == .alertFirstButtonReturn { // Handle cancel action } } return } let com = KMOCRPDFWindowController(cpdfDocument: document!, pwd: document!.password) self.km_beginSheet(windowC: com) } } func fastTool_ConvertPDF() { // 转换PDF let openPanel = NSOpenPanel() var arr = KMImageToPDFMethod.supportedImageTypes() arr.append("pdf") openPanel.allowedFileTypes = ["pdf","PDF"] //MARK: 允许多选还是单选,如果是付费用户允许多选 openPanel.allowsMultipleSelection = false openPanel.beginSheetModal(for: self.view.window!) { [self] (result) in if result == NSApplication.ModalResponse.OK { quickConvertPdf(urls: openPanel.urls, type: .WordAdvance) } } } func quickConvertPdf(urls: Array, type: KMConvertWithPDFType) { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) { var arr: Array = Array() for fileURL in urls { let img = NSImage(contentsOfFile: fileURL.path) if self.isDamageImage(image: img, path: fileURL.path) { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = String(format: NSLocalizedString("The file \"%@\" could not be opened.", comment: ""), fileURL.path.lastPathComponent) alert.informativeText = NSLocalizedString("It may be damaged or use a file format that PDF Reader Pro doesn’t recognize.", comment: "") alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) alert.beginSheetModal(for: NSApp.mainWindow!) { (response) in if response == .alertFirstButtonReturn { // Handle cancel action } } continue } let file = KMBatchOperateFile(filePath: fileURL.path, type: .Convert) arr.append(file) } let baseWindowController = KMBatchOperateBaseWindowController(windowNibName: "KMBatchOperateBaseWindowController") if #available(macOS 10.13, *) { baseWindowController.window?.makeKeyAndOrderFront(nil) } else { baseWindowController.showWindow(nil) } if arr.count > 0 { baseWindowController.checkNeedPasswordSwitchToOperateType(operateType: .Convert, files: arr) } baseWindowController.switchToConvertType(convertType: type) } } func fastTool_PDFToPPT() { let openPanel = NSOpenPanel() openPanel.allowedFileTypes = ["pdf","PDF"] //MARK: 允许多选还是单选,如果是付费用户允许多选 openPanel.allowsMultipleSelection = false openPanel.beginSheetModal(for: NSWindow.currentWindow()) { [self] (result) in if result == NSApplication.ModalResponse.OK { quickConvertPdf(urls: openPanel.urls, type: .PowerPoint) } } } func fastTool_PDFToExcel() { let openPanel = NSOpenPanel() openPanel.allowedFileTypes = ["pdf","PDF"] //MARK: 允许多选还是单选,如果是付费用户允许多选 openPanel.allowsMultipleSelection = false openPanel.beginSheetModal(for: NSWindow.currentWindow()) { [self] (result) in if result == NSApplication.ModalResponse.OK { quickConvertPdf(urls: openPanel.urls, type: .Excel) } } } // 压缩 func fastTool_Compression() { let openPanel = NSOpenPanel() openPanel.allowedFileTypes = ["pdf","PDF"] //MARK: 允许多选还是单选,如果是付费用户允许多选 openPanel.allowsMultipleSelection = false openPanel.beginSheetModal(for: NSWindow.currentWindow()) { [self] (result) in if result == NSApplication.ModalResponse.OK { quickCompressPdf(urls: openPanel.urls) } } } func quickCompressPdf(urls: Array) { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) { var arr: Array = Array() for fileURL in urls { let file = KMBatchOperateFile(filePath: fileURL.path, type: .Compress) arr.append(file) } let baseWindowController = KMBatchOperateBaseWindowController(windowNibName: "KMBatchOperateBaseWindowController") if #available(macOS 10.13, *) { baseWindowController.window?.makeKeyAndOrderFront(nil) } else { baseWindowController.showWindow(nil) } if arr.count > 0 { baseWindowController.checkNeedPasswordSwitchToOperateType(operateType: .Compress, files: arr) } } } // 安全 func fastTool_Security() { let openPanel = NSOpenPanel() openPanel.allowedFileTypes = ["pdf","PDF"] //MARK: 允许多选还是单选,如果是付费用户允许多选 openPanel.allowsMultipleSelection = true openPanel.message = NSLocalizedString("To select multiple files press cmd ⌘ button on keyboard and click on the target files one by one.", comment: "") openPanel.beginSheetModal(for: NSWindow.currentWindow()) { [self] (result) in if result == NSApplication.ModalResponse.OK { quickPassword(urls: openPanel.urls) } } } func quickPassword(urls: Array) { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) { var arr: Array = Array() for fileURL in urls { // let file = KMBatchOperateFile(filePath: fileURL.path, type: KMBatchQuickActionManager.defaultManager.actionType == .add ? .AddPassword : .RemovePassword) // arr.append(file) } let baseWindowController = KMBatchOperateBaseWindowController(windowNibName: "KMBatchOperateBaseWindowController") if #available(macOS 10.13, *) { baseWindowController.window?.makeKeyAndOrderFront(nil) } else { baseWindowController.showWindow(nil) } if arr.count > 0 { // baseWindowController.checkNeedPasswordSwitchToOperateType(operateType: KMBatchQuickActionManager.defaultManager.actionType == .add ? .AddPassword : .RemovePassword, files: arr) } } } func fastTool_FileCompare() { // 文件对比 if !IAPProductsManager.default().isAvailableAllFunction(){ let winC = KMPurchaseCompareWindowController.sharedInstance() winC?.showWindow(nil) return } let openPanel = NSOpenPanel() openPanel.allowsMultipleSelection = false openPanel.allowedFileTypes = ["pdf"] openPanel.beginSheetModal(for: NSApp.mainWindow!) { result in if result == .cancel { return } if !openPanel.url!.path.isPDFValid() { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", comment: "") alert.runModal() return } KMBaseWindowController.checkPassword(url: URL(fileURLWithPath: openPanel.url!.path), type: .owner) { [unowned self] success, resultPassword in if success { DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { let controller = KMCompareWindowController(windowNibName: "KMCompareWindowController") controller.password = resultPassword controller.filePath = openPanel.url!.path controller.cancelAction = { [unowned self] contr in self.view.window?.endSheet((controller.window)!) } controller.contentComplete = { [unowned self] controller, pdfCompareContent, result, oldDocument, document in DispatchQueue.main.async { self.view.window?.endSheet((controller.window)!) // self.openContentCompareVC(with: pdfCompareContent, results: result, oldDocument: oldDocument, document: document) } } controller.coveringComplete = { [unowned self] controller, document in self.view.window?.endSheet((controller.window)!) // self.openCoveringCompareVC(with: document) } controller.fileType = .content NSWindow.currentWindow().beginSheet(controller.window!) } } else { } } } } func fastTool_Watermark() { // 水印 if !IAPProductsManager.default().isAvailableAllFunction(){ let winC = KMPurchaseCompareWindowController.sharedInstance() winC?.showWindow(nil) return } let openPanel = NSOpenPanel() openPanel.allowedFileTypes = ["pdf","PDF"] //MARK: 允许多选还是单选,如果是付费用户允许多选 openPanel.allowsMultipleSelection = false openPanel.beginSheetModal(for: NSWindow.currentWindow()) { [self] (result) in if result == NSApplication.ModalResponse.OK { quickWaterMark(urls: openPanel.urls) } } } func quickWaterMark(urls: Array) { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) { var arr: Array = Array() for fileURL in urls { let pdf = CPDFDocument(url: fileURL) if !pdf!.allowsPrinting || !pdf!.allowsCopying { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "") alert.runModal() return } // let file = KMBatchOperateFile(filePath: fileURL.path, type: KMBatchQuickActionManager.defaultManager.actionType == .add ? .AddWatermark : .RemoveWatermark) // arr.append(file) } let baseWindowController = KMBatchOperateBaseWindowController(windowNibName: "KMBatchOperateBaseWindowController") if #available(macOS 10.13, *) { baseWindowController.window?.makeKeyAndOrderFront(nil) } else { baseWindowController.showWindow(nil) } if arr.count > 0 { // baseWindowController.checkNeedPasswordSwitchToOperateType(operateType: KMBatchQuickActionManager.defaultManager.actionType == .add ? .AddWatermark : .RemoveWatermark, files: arr) } } } func fastTool_Background() { // 背景 if !IAPProductsManager.default().isAvailableAllFunction(){ let winC = KMPurchaseCompareWindowController.sharedInstance() winC?.showWindow(nil) return } let openPanel = NSOpenPanel() openPanel.allowedFileTypes = ["pdf","PDF"] //MARK: 允许多选还是单选,如果是付费用户允许多选 openPanel.allowsMultipleSelection = false openPanel.beginSheetModal(for: NSWindow.currentWindow()) { [self] (result) in if result == NSApplication.ModalResponse.OK { quickBackgroudMark(urls: openPanel.urls) } } } func quickBackgroudMark(urls: Array) { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) { var arr: Array = Array() for fileURL in urls { let pdf = CPDFDocument(url: fileURL) if !pdf!.allowsPrinting || !pdf!.allowsCopying { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "") alert.runModal() return } // let file = KMBatchOperateFile(filePath: fileURL.path, type: KMBatchQuickActionManager.defaultManager.actionType == .add ? .AddBackground : .RemoveBackground) // arr.append(file) } let baseWindowController = KMBatchOperateBaseWindowController(windowNibName: "KMBatchOperateBaseWindowController") if #available(macOS 10.13, *) { baseWindowController.window?.makeKeyAndOrderFront(nil) } else { baseWindowController.showWindow(nil) } if arr.count > 0 { // baseWindowController.checkNeedPasswordSwitchToOperateType(operateType: KMBatchQuickActionManager.defaultManager.actionType == .add ? .AddBackground : .RemoveBackground, files: arr) } } } func fastTool_Print() { // 打印 KMPrintWindowController.openFiles(window: self.view.window!) } func fastTool_Insert() { // 插入 if !IAPProductsManager.default().isAvailableAllFunction(){ KMPurchaseCompareWindowController.sharedInstance().showWindow(nil) return } let openPanel = NSOpenPanel() openPanel.prompt = NSLocalizedString("Insert", comment: "") openPanel.allowsMultipleSelection = false openPanel.allowedFileTypes = ["pdf"] openPanel.beginSheetModal(for: NSApp.mainWindow!) { result in if result == .OK { let windowC = KMPDFInsertWindowController(fileURL: openPanel.url!) windowC.callback = { [weak self] idx, params in if params.count >= 4 { if let doc = params.first as? CPDFDocument { self?.savePDFDocument(doc, password: params[1] as? String ?? "") } } self?.km_endSheet() } self.km_beginSheet(windowC: windowC) } } } func savePDFDocument(_ pdf: CPDFDocument, password: String) -> Void { DispatchQueue.global(qos: .`default`).async { var isSuccessfully = false if pdf.isEncrypted { let dic = [ CPDFDocumentWriteOption.userPasswordOption : password, CPDFDocumentWriteOption.ownerPasswordOption : password ] isSuccessfully = pdf.write(to: pdf.documentURL, withOptions: dic) } else { isSuccessfully = pdf.write(to: pdf.documentURL) } if !isSuccessfully { if let data = pdf.dataRepresentation() { isSuccessfully = NSData(data: data).write(to: pdf.documentURL, atomically: true) } } DispatchQueue.main.sync { if isSuccessfully { let workspace = NSWorkspace.shared let url = URL(fileURLWithPath: pdf.documentURL?.path ?? "") workspace.activateFileViewerSelecting([url]) } else { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Failed to insert page(s)!", comment: "") alert.runModal() } } } } func fastTool_Extract() { // 提取 let openPanel = NSOpenPanel() openPanel.prompt = "提取" openPanel.allowsMultipleSelection = false openPanel.allowedFileTypes = ["pdf"] openPanel.beginSheetModal(for: NSApp.mainWindow!) { result in if result == .OK { DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { let insertWindowController: KMPDFInsertPageWindow = KMPDFInsertPageWindow.init(documentPath: openPanel.url!, toolType: .Extract) insertWindowController.beginSheetExtractModal(for: self.view.window!) { pdfDocument, pages, oneDocumentPerPage, isDeletePage in self.extractPageAction(pdfDocument, pages, oneDocumentPerPage, isDeletePage) } } } } } func extractPageAction(_ pdfDocument: CPDFDocument, _ pages: [CPDFPage], _ oneDocumentPerPage: Bool, _ isDeletePage: Bool) -> Void { if pages.count < 1 { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Please select two or more pages first to organize.", comment: "") alert.runModal() return } if !oneDocumentPerPage { let fileName = pdfDocument.getFileNameAccordingSelctPages(pages) let outputSavePanel = NSSavePanel() outputSavePanel.allowedFileTypes = ["pdf"] outputSavePanel.nameFieldStringValue = fileName outputSavePanel.beginSheetModal(for: self.view.window!) { result in if result == .OK { DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { let saveFilePath = outputSavePanel.url?.path DispatchQueue.global().async { var pdf = CPDFDocument.init() let success = (pdf!.extractAsOneDocument(withPages: pages, savePath: saveFilePath)) as Bool DispatchQueue.main.async { if success { let workspace = NSWorkspace.shared let url = URL(fileURLWithPath: saveFilePath!) workspace.activateFileViewerSelecting([url]) if isDeletePage { for page in pages { let indexPage = pdfDocument.index(for: page) pdfDocument.removePage(at: indexPage) } } } } } } } } } else { let panel = NSOpenPanel() panel.canChooseFiles = false panel.canChooseDirectories = true panel.canCreateDirectories = true panel.allowsMultipleSelection = false panel.beginSheetModal(for: self.view.window!) { result in if result == .OK { DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { let outputURL = panel.url DispatchQueue.global().async { let folderName = String(pdfDocument.documentURL!.lastPathComponent.split(separator: ".")[0]) + "_extract" var filePath = URL(fileURLWithPath: outputURL!.path).appendingPathComponent(folderName).path var i = 1 let testFilePath = filePath while FileManager.default.fileExists(atPath: filePath) { filePath = testFilePath + "\(i)" i += 1 } try? FileManager.default.createDirectory(atPath: filePath, withIntermediateDirectories: false, attributes: nil) let successArray = pdfDocument.extractPerPageDocument(withPages: pages, folerPath: filePath) DispatchQueue.main.async { if successArray!.count > 0 { NSWorkspace.shared.activateFileViewerSelecting(successArray!) if !isDeletePage { for page in pages { let indexPage = pdfDocument.index(for: page) pdfDocument.removePage(at: indexPage) } } } } } } } } } } }