// // 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 createWC: KMURLCreatePDFWindowController = KMURLCreatePDFWindowController(windowNibName: "KMURLCreatePDFWindowController") //合并 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) } } //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 = KMLocalizedString("This file format is not supported. Please enter PDF, picture, or Office file") alert.runModal() } } } //MARK: - Open Files extension KMNHomeViewController { func openFile(withFilePath path: URL) -> Void { if let _windowC = NSApp.mainWindow?.windowController as? KMBrowserWindowController { _windowC.openFile(withFilePath: path) } } func openImageToPdfWindow(urls: Array) { if let _windowC = NSApp.mainWindow?.windowController as? KMBrowserWindowController { _windowC.showBatchWindow(type: .imageToPDF, files: urls) } } 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 = KMBatchWindowController(windowNibName: "KMBatchWindowController") 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) { showBatchWindow(type: .OCR, files: urls) } 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) { self.showBatchWindow(type: .convertPDF, subType: type.rawValue,files: urls) } } 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) { self.showBatchWindow(type: .compress, files: urls) } } // 安全 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) { self.showBatchWindow(type: .security, files: urls) } } 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 } NSWindowController.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)!) } } controller.coveringComplete = { [unowned self] controller, document in self.view.window?.endSheet((controller.window)!) } 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) { self.showBatchWindow(type: .watermark, files: urls) } } 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) { self.showBatchWindow(type: .background, files: urls) } } //MARK: 打印 func fastTool_Print() { let openPanel = NSOpenPanel() openPanel.allowedFileTypes = ["pdf","PDF"] openPanel.allowsMultipleSelection = false openPanel.beginSheetModal(for: NSWindow.currentWindow()) { [self] (result) in if result == NSApplication.ModalResponse.OK { if let url = openPanel.url { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) { self.showPrintWindowWithURL(url) } } } } } func showPrintWindowWithURL(_ url: URL) { if let cPDFDocument = CPDFDocument(url: url) { KMPrintWindowController.openDocument(inputDocument: cPDFDocument, inputPageRange: KMPrintPageRange(type: .allPage, selectPages: [])) } } 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 ?? "") } } windowC.own_closeEndSheet() } windowC.own_beginSheetModal(for: self.view.window) { result in } } } } 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 { let 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) } } } } } } } } } } //MARK: Batch func showBatchWindow(type: KMBatchCollectionViewType, subType: Int = 0, files: [URL]?) { let batchWindowController = KMBatchWindowController.init(windowNibName: "KMBatchWindowController") batchWindowController.window?.makeKeyAndOrderFront("") // var datas: [KMBatchProcessingTableViewModel] = [] // for file in files! { // let data = KMBatchProcessingTableViewModel.initWithFilePath(url: file) // datas.append(data) // } batchWindowController.inputData = files ?? [] batchWindowController.type = type batchWindowController.inputSubType = subType } }