// // KMHomeViewController+Action.swift // PDF Master // // Created by wanjun on 2022/10/13. // import Foundation extension KMHomeViewController: NSMenuItemValidation { func validateMenuItem(_ menuItem: NSMenuItem) -> Bool { if (menuItem.action == #selector(menuItemAction_currentWindowName)) { menuItem.title = NSLocalizedString("Home", comment: "") return true } if (menuItem.action == #selector(menuItemAction_showForwardTagPage) || menuItem.action == #selector(menuItemAction_showNextTagPage)) { if (self.myDocument != nil && (self.myDocument is KMMainDocument)) { let browser = (self.myDocument as! KMMainDocument).browser if (menuItem.action == #selector(menuItemAction_showForwardTagPage)) { return (browser as! KMBrowser).canSelectPreviousTab() } if (menuItem.action == #selector(menuItemAction_showNextTagPage)) { return (browser as! KMBrowser).canSelectNextTab() } } } if (menuItem.action == #selector(menuItemAction_mergeAllWindow)) { if let _browserWindowC = ((self.myDocument as? KMMainDocument)?.browser.windowController as? KMBrowserWindowController) { return _browserWindowC.canMergeAllWindow() } } return true } } extension KMHomeViewController { // MARK: Action @objc func homeToolAction(_ sender: NSButton) -> Void { if sender == homeButtonVC.button { homeToolAction(homeToolState: KMHomeToolState.Home) } else if sender == pdfToolsButtonVC.button { homeToolAction(homeToolState: KMHomeToolState.PDFTools) } else if sender == cloudDocumentsButtonVC.button { homeToolAction(homeToolState: KMHomeToolState.CloudDocuments) } else if sender == openPDFButtonVC.button { homeToolAction(homeToolState: KMHomeToolState.OpenPDF) } else if sender == createPDFButtonVC.button { openSupportPDFButtonAction() } else if sender == createPDFImage.button { homeToolAction(homeToolState: KMHomeToolState.CreatePDF) } } func homeToolAction(homeToolState: KMHomeToolState) { switch homeToolState { case .OpenPDF: openPDFButtonAction() break case .CreatePDF: createPDFButtonAction() break case .Home: homeButtonAction() break case .PDFTools: pdfToolsButtonAction() break case .FavoriteDocuments: favoriteDocumentsButtonAction() break case .CloudDocuments: cloudDocumentsButtonAction() break default: print("error: 错误的传入枚举") break } } func fastToolItemAction(_ type: DataNavigationViewButtonActionType) { switch type { case .Batch: fastTool_Batch() break case .OCR: fastTool_OCR() break case .ConvertPDF: fastTool_ConvertPDF() break case .ImageToPDF: fastTool_ImageToPDF() break case .MergePDF: fastTool_MergePDF() break case .Compression: fastTool_Compression() break case .Security: fastTool_Security() break case .FileCompare: fastTool_FileCompare() break case .PDFToPPT: fastTool_PDFToPPT() break case .PDFToExcel: fastTool_PDFToExcel() break case .PDFToWord: fastTool_PDFToWord() break case .PDFToImage: fastTool_PDFToImage() break case .Watermark: fastTool_Watermark() break case .Background: fastTool_Background() break case .HeaderAndFooter: fastTool_HeaderAndFooter() break case .BatesCode: fastTool_BatesCode() break case .Print: fastTool_Print() break case .BatchRemove: fastTool_BatchRemove() break case .Insert: fastTool_Insert() break case .BreakUp: fastTool_BreakUp() break case .Extract: fastTool_Extract() break case .MarkCipher: fastTool_MarkCipher() break case .AutomaticFormRecognition: fastTool_AutomaticFormRecognition() break case .PageEdit: fastTool_PageEdit() break } } func openPDFButtonAction() { NSPanel.km_open_pdf_multi_success(self.view.window!, panel: nil) { urls in for url in urls { 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.runModal() } else { NSDocumentController.shared.openDocument(withContentsOf: url, display: true) { document, documentWasAlreadyOpen, error in if error != nil { NSApp.presentError(error!) } else { } } } } } } func openSupportPDFButtonAction() { let openPanel = NSOpenPanel() openPanel.allowedFileTypes = ["pdf", "PDF", "jpg", "cur", "bmp", "jpeg", "gif", "png", "tiff", "tif", "ico", "icns", "tga", "psd", "eps", "hdr", "jp2", "jpc", "pict", "sgi", "heic", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "pptx"] openPanel.allowsMultipleSelection = true var window = self.view.window if (window == nil) { window = NSApp.mainWindow } openPanel.beginSheetModal(for: window!) { [self] result in if result == .OK { var imageUrl: [URL] = [] for url in openPanel.urls { let type = url.pathExtension.lowercased() if (type == "pdf" || type == "PDF") { 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.runModal() } else { NSDocumentController.shared.openDocument(withContentsOf: url, display: true) { document, documentWasAlreadyOpen, error in if error != nil { NSApp.presentError(error!) return } } } } 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: url) } else if (type == "doc") || (type == "docx") || (type == "xls") || (type == "xlsx") || (type == "ppt") || (type == "pptx") || (type == "pptx") { self.openOfficeFile(url: url) } } } } } func createPDFButtonAction() { let popViewDataArr = [NSLocalizedString("New Blank Page", comment: ""), // NSLocalizedString("New From Web Page", comment: ""), NSLocalizedString("Import From Scanner", comment: "")] createPopoverAction(popViewDataArr) } func homeButtonAction() { refreshRightBoxUI(.Home) } func pdfToolsButtonAction() { refreshRightBoxUI(.PDFTools) } func favoriteDocumentsButtonAction() { print("Favorite Documents") } func cloudDocumentsButtonAction() { refreshRightBoxUI(.CloudDocuments) } // 产品推广 func productPromotionFoldOrUnfold(_ sender: NSButton) { var arr1: [NSString] = [] var arr2: [NSString] = [] if sender.isEqual(to: pdfSeriesButtonVC.button) { if self.pdfProSeriesBoxHeightConstraint.constant == 0 { arr1 = self.productPromotionPDFProSeries as! [NSString] } if self.othersBoxHeightConstraint.constant > 0 { arr2 = self.productPromotionOthers as! [NSString] } } if sender.isEqual(to: self.pdfOthersButtonVC.button) { if self.pdfProSeriesBoxHeightConstraint.constant > 0 { arr1 = self.productPromotionPDFProSeries as! [NSString] } if self.othersBoxHeightConstraint.constant == 0 { arr2 = self.productPromotionOthers as! [NSString] } } self.productPromotionShow(arr1 as NSArray, withOthers: arr2 as NSArray, isInitialize: false) refreshProductActiveSpacing() } func productPromotionClickAction(_ name: NSString) { var httpString: NSString = "" if name.isEqual(to: "Windows") { httpString = "https://www.pdfreaderpro.com/windows?utm_source=MacApp&utm_campaign=PDFProMac&utm_medium=pdfmac_promo" } else if name.isEqual(to: "iPhone / iPad") { #if VERSION_FREE #if VERSION_DMG httpString = "https://www.pdfreaderpro.com/product?utm_source=MacAppDmg&utm_campaign=ProductLinkLeftNav&utm_medium=PdfProduct" #else httpString = "https://www.pdfreaderpro.com/product?utm_source=MacAppLite&utm_campaign=ProductLinkLeftNav&utm_medium=PdfProduct" #endif #else httpString = "https://www.pdfreaderpro.com/product?utm_source=MacApp&utm_campaign=ProductLinkLeftNav&utm_medium=PdfProduct" #endif } else if name.isEqual(to: "Android") { httpString = "https://www.pdfreaderpro.com/pdfreaderpro-android?utm_source=MacAppDmg&utm_campaign=AndroidLink&utm_medium=PdfAndroid" } else if name.isEqual(to: "ComPDFKit") { httpString = "https://www.compdf.com?utm_source=macapp&utm_medium=pdfmac&utm_campaign=compdfkit-promp" } else if name.isEqual(to: "ComVideoKit") { httpString = "https://www.filmagepro.com/video-sdk?utm_source=macapp&utm_medium=pdfmac&utm_campaign=comvideosdk-promo" } else if name.isEqual(to: "SignFlow") { httpString = "https://apps.apple.com/app/apple-store/id1584624017?pt=118745145&ct=pdfmac-promo&mt=8" } else if name.isEqual(to: "FiImage Editor") { httpString = "https://apps.apple.com/app/apple-store/id1475051178?pt=118745145&ct=pdfmac-promo&mt=8" } else if name.isEqual(to: "FiImage Screen") { httpString = "https://apps.apple.com/app/apple-store/id1475049179?pt=118745145&ct=pdfmac-promo&mt=8" } else if name.isEqual(to: "Free PDF Templates") { httpString = "https://www.pdfreaderpro.com/templates?utm_source=MacApp&utm_campaign=PDFProMac&utm_medium=pdfmac_promo" } self.workSpaceOpenUrl(httpString) } func historyFile(deleteDocuments indexPaths: [URL]) { if UserDefaults.standard.bool(forKey: "kHistoryDeleteNOReminderKey") { historyFileDeleteAction(indexPaths) } else { let historyFileDeleteVC: KMHistoryFileDeleteWindowController = KMHistoryFileDeleteWindowController.init(windowNibName: NSNib.Name("KMHistoryFileDeleteWindowController")) historyFileDeleteVC.indexPaths = indexPaths self.currentWindowController = historyFileDeleteVC historyFileDeleteVC.deleteCallback = { [weak self](indexPaths: [URL], windowController: KMHistoryFileDeleteWindowController) -> Void in if self != nil { self?.currentWindowController = nil self!.historyFileDeleteAction(indexPaths) } } self.view.window?.beginSheet(historyFileDeleteVC.window!) } } func historyFileDeleteAction(_ indexPaths: [URL]) -> Void { // NSDocumentController.shared.clearRecentDocuments(nil) let urls: Array = NSDocumentController.shared.recentDocumentURLs NSDocumentController.shared.clearRecentDocuments(nil) DispatchQueue.main.asyncAfter(deadline: .now()) { [self] in for (_, url) in urls.enumerated() { if !indexPaths.contains(url) { NSDocumentController.shared.noteNewRecentDocumentURL(url) } } } historyFileViewController.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!) { [unowned self] result in self.historyFileViewController.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 { KMMainDocument().tryToUnlockDocument(pdfDoc!) var selectDocument: KMMainDocument? = nil if ((document?.isKind(of: KMMainDocument.self)) != nil) { selectDocument = (document as! KMMainDocument) } if selectDocument != nil { let currentIndex = selectDocument?.browser.tabStripModel.index(of: selectDocument) selectDocument?.browser.tabStripModel.selectTabContents(at: Int32(currentIndex!), userGesture: true) if (selectDocument?.browser.window.isVisible)! as Bool { selectDocument?.browser.window.orderFront(nil) } else if (selectDocument?.browser.window.isMiniaturized)! as Bool { selectDocument?.browser.window.orderFront(nil) } } else { 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.runModal() } else { NSDocumentController.shared.openDocument(withContentsOf: url, display: true) { document, documentWasAlreadyOpen, error in if error != nil { NSApp.presentError(error!) return } } } } } else { 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) selectDocument?.browser.tabStripModel.selectTabContents(at: Int32(currentIndex!), userGesture: true) if (selectDocument?.browser.window.isVisible)! as Bool { selectDocument?.browser.window.orderFront(nil) } else if (selectDocument?.browser.window.isMiniaturized)! as Bool { selectDocument?.browser.window.orderFront(nil) } } } else { 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.runModal() } else { NSDocumentController.shared.openDocument(withContentsOf: url, display: true) { document, documentWasAlreadyOpen, error in if error != nil { NSApp.presentError(error!) return } } } } } } 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!) { [unowned self] result in self.historyFileViewController.reloadData() } } } else { NSWorkspace.shared.open(url) } } func openFile(withFilePath path: URL) -> Void { let type = path.pathExtension.lowercased() if (type == "pdf") { if !path.path.isPDFValid() { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("This file format is not supported, please drag in PDF, picture, Office format files", comment: "") alert.runModal() return } NSDocumentController.shared.openDocument(withContentsOf: path, display: true) { document, documentWasAlreadyOpen, error in if error != nil { NSApp.presentError(error!) return } } } 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()) openOfficeFile(url: path) } } func openImageFile(url: URL) -> Void { var filePath = url.path let fileName: NSString = url.lastPathComponent as NSString let savePath = fetchUniquePath(fileName.kUrlToPDFFolderPath()).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 { print("Failed to load PNG image") return } // 创建 NSBitmapImageRep 对象,并将 PNG 图像绘制到其中 let bitmap = NSBitmapImageRep(data: pngImage.tiffRepresentation!) let rect = NSRect(origin: .zero, size: bitmap!.size) bitmap?.draw(in: rect) // 将 PNG 图像数据转换为 JPG 图像数据 guard let jpgData = bitmap?.representation(using: .jpeg, properties: [:]) else { print("Failed to convert PNG to JPG") return } // 保存 JPG 图像数据到文件 let fileURL = URL(fileURLWithPath: jpgPath) do { try jpgData.write(to: fileURL) filePath = fileURL.path print("JPG image saved successfully") } catch { print("Failed to save JPG image: \(error.localizedDescription)") } } //FIXME: 无法插入图片 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 { if !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 } NSDocumentController.shared.openDocument(withContentsOf: URL(fileURLWithPath: path), display: true) { document, documentWasAlreadyOpen, error in if error != nil { NSApp.presentError(error!) return } } } } func openOfficeFile(url: URL) -> Void { let filePath = url.path let folderPath = "convertToPDF.pdf" let savePath = folderPath.kUrlToPDFFolderPath() 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 } KMConvertPDFManagerOC.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 } if !savePath!.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 } NSDocumentController.shared.openDocument(withContentsOf: URL(fileURLWithPath: savePath!), display: true) { document, documentWasAlreadyOpen, error in if error != nil { NSApp.presentError(error!) return } } } } func aiTranslation(withFilePath path: String) -> Void { if !KMLightMemberManager.manager.isLogin() { KMLoginWindowController.show(window: NSApp.mainWindow!) return } let isExceedsLimit = self.isPDFPageCountExceedsLimit(filePath: path) if self.isFileGreaterThan10MB(atPath: path) { self.aiTranslationViewController.errorView.isHidden = false self.aiTranslationViewController.errorLabel.stringValue = NSLocalizedString("The uploaded file size cannot exceed 10MB", comment: "") } else if isExceedsLimit { self.aiTranslationViewController.errorView.isHidden = false self.aiTranslationViewController.errorLabel.stringValue = NSLocalizedString("Documents cannot exceed 30 pages", comment: "") } else { let url = URL(fileURLWithPath: path) if (url.pathExtension == "pdf") || url.pathExtension == "PDF" { if !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 } } let infoDictionary = Bundle .main.infoDictionary! let majorVersion = infoDictionary["CFBundleShortVersionString"] DispatchQueue.main.async { self.showProgressWindow() } KMRequestServerManager.manager.aiTranslationFileUpload(file: path, version: "1.0.1") { [unowned self] success, result in if success { let result: NSDictionary = result!.result let fileKey = result["fileKey"] let fileName = result["fileName"] let pageCount = result["pageCount"] if fileKey != nil { self.fileTranslateHandle(fileKey as! String) } } else { let result: String = result!.message DispatchQueue.main.async { self.hiddenProgressWindow() self.aiTranslationViewController.errorView.isHidden = false self.aiTranslationViewController.errorLabel.stringValue = result } } } } } func fileTranslateHandle(_ fileKey: String) -> Void { let infoDictionary = Bundle .main.infoDictionary! let majorVersion = infoDictionary["CFBundleShortVersionString"] KMRequestServerManager.manager.aiTranslationFileTranslateHandle(fileKey: fileKey, from: self.aiTranslationViewController.fromStr, to: self.aiTranslationViewController.toStr, version: "1.0.1") { success, result in if success { let result: NSDictionary = result!.result let fileUrl: String = result["fileUrl"] as! String let downFileUrl: String = result["downFileUrl"] as! String let ossDownUrl: String = result["ossDownUrl"] as! String let fileName: String = result["fileName"] as! String let downFileName: String = result["downFileName"] as! String let from: String = result["from"] as! String let to: String = result["to"] as! String self.downloadFile(filePath: ossDownUrl, downFileName: downFileName) } else { let result: String = result!.message DispatchQueue.main.async { self.hiddenProgressWindow() self.aiTranslationViewController.errorView.isHidden = false self.aiTranslationViewController.errorLabel.stringValue = result } } } } func downloadFile(filePath: String, downFileName: String) -> Void { guard let fileURL = URL(string: filePath) else { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Invalid file link", comment: "") alert.runModal() return } let destinationURL = FileManager.default.temporaryDirectory.appendingPathComponent(downFileName) if FileManager.default.fileExists(atPath: destinationURL.path) { do { try FileManager.default.removeItem(at: destinationURL) print("删除旧文件成功") } catch { print("删除旧文件失败:\(error)") } } let sessionConfiguration = URLSessionConfiguration.default let session = URLSession(configuration: sessionConfiguration) let downloadTask = session.downloadTask(with: fileURL) { (tempLocalURL, response, error) in if let error = error { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = String(format: "%@:\(error)", NSLocalizedString("Download failed", comment: "")) alert.runModal() return } guard let tempLocalURL = tempLocalURL else { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Invalid temporary directory", comment: "") alert.runModal() return } DispatchQueue.main.async { self.hiddenProgressWindow() } do { try FileManager.default.moveItem(at: tempLocalURL, to: destinationURL) NSDocumentController.shared.openDocument(withContentsOf: destinationURL, display: true) { document, documentWasAlreadyOpen, error in if error != nil { NSApp.presentError(error!) } else { } } } catch { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = String(format: "%@:\(error)", NSLocalizedString("Failed to save file", comment: "")) alert.runModal() } } downloadTask.resume() } override func otherMouseDown(with event: NSEvent) { if historyFileViewController.selectFiles.count > 0 { let eventPoint = event.locationInWindow as NSPoint let x = eventPoint.x - 270.0 if x >= 0 { let point = NSPoint(x: x, y: eventPoint.y) if historyFileViewController.historyFileCollectionView.frame.contains(point) || historyFileViewController.historyFileTableView.frame.contains(point) || historyFileViewController.deleteBox.frame.contains(point) || historyFileViewController.listBox.frame.contains(point) || historyFileViewController.thumbnailBox.frame.contains(point) { } else { self.historyFileViewController.selectFiles.removeAll() self.historyFileViewController.selectFiles_shift.removeAll() if self.historyFileViewController.showMode == .Thumbnail { self.historyFileViewController.historyFileCollectionView.reloadData() } else { self.historyFileViewController.historyFileTableView.reloadData() } } } else { self.historyFileViewController.selectFiles.removeAll() self.historyFileViewController.selectFiles_shift.removeAll() if self.historyFileViewController.showMode == .Thumbnail { self.historyFileViewController.historyFileCollectionView.reloadData() } else { self.historyFileViewController.historyFileTableView.reloadData() } } } } internal func showConvertWindow(type: KMPDFConvertType) { Task { @MainActor in if await (KMLightMemberManager.manager.canUseAdvanced() == false) { let _ = KMComparativeTableViewController.show(window: self.view.window!) return } NSOpenPanel.km_secure_openPanel_success(window: self.view.window!) { url, password in var windowController: KMConvertBaseWindowController? if (type == .word) { /// Word windowController = KMConvertWordWindowController() } else if (type == .excel) { windowController = KMConvertExcelWindowController() } else if (type == .ppt || type == .rtf || type == .html || type == .text) { windowController = KMConvertPPTsWindowController() if (type == .ppt) { windowController?.subType = 1 } else if (type == .rtf) { windowController?.subType = 2 } else if (type == .html) { windowController?.subType = 3 } else if (type == .text) { windowController?.subType = 4 } } else if (type == .csv) { windowController = KMConvertCSVWindowController() } else if (type == .image) { windowController = KMConvertImageWindowController() } let model = KMDocumentModel(url: url) if (password != nil) { let _ = model.unlock(password!) } windowController?.documentModel = model windowController?.itemClick = { [weak self] index in if (self?.currentWindowController == nil) { return } self?.view.window?.endSheet((self?.currentWindowController?.window)!) self?.currentWindowController = nil } self.view.window?.beginSheet((windowController?.window)!) self.currentWindowController = windowController } } } // MARK: PDF Tools // 插入 func insertPageAction(_ pdfDocument: CPDFDocument, _ password: String, _ pages: [CPDFPage], _ indexPage: Int) -> Void { if indexPage >= 0 { let insertPages: [CPDFPage] = pages for i in 0...insertPages.count-1 { let page = pages[i] // FIXME: 待底层库修改,使用 insertPageObject 插入,插入位置变为文档最后,暂用 insertPage 代替 pdfDocument.insertPageObject(page, at: UInt(indexPage + i)) } self.savePDFDocument(pdfDocument, password: password) } } 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) } } } } } } } } } } // MARK: 快捷工具 Action func fastToolDidSelectAllTools() { // 首页 快捷工具 Tools按钮 refreshRightBoxUI(.PDFTools) } func fastTool_Batch() { // Batch // KMBatchWindowController.openFile(nil, .Batch) } func fastTool_OCR() { // OCR // KMOCRWindowController.openFiles(window: self.view.window!) } func fastTool_ConvertPDF() { // 转换PDF // KMBatchWindowController.openFile(nil, .ConvertPDF) } func fastTool_ImageToPDF() { // 图片转PDF KMImageToPDFWindowController.openFiles(window: NSApp.mainWindow!) } func fastTool_MergePDF() { // MergePDF Task { @MainActor in if await (KMLightMemberManager.manager.canUseAdvanced() == false) { let _ = KMComparativeTableViewController.show(window: self.view.window!) return } NSPanel.km_open_pdf_multi_success(self.view.window!, panel: nil) { urls in DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { var filepaths: Array = [] for url in urls { filepaths.append(url.path) } let windowController = KMPDFEditAppendWindow(filePaths: filepaths) self.currentWindowController = windowController windowController?.beginSheetModal(for: self.view.window, completionHandler: { result, indexs in }) } } } } func fastTool_Compression() { // 压缩 Task { @MainActor in if await (KMLightMemberManager.manager.canUseAdvanced() == false) { let _ = KMComparativeTableViewController.show(window: self.view.window!) return } NSOpenPanel.km_secure_openPanel(window: self.view.window!) { url, result, passowrd in if (url == nil) { return } if (result != nil && result! == .cancel) { return } self.showCompressWindow(url!, passowrd) } } } func showCompressWindow(_ url: URL, _ password: String?) { Task { @MainActor in if await (KMLightMemberManager.manager.canUseAdvanced() == false) { let _ = KMComparativeTableViewController.show(window: self.view.window!) return } let windowController = KMCompressWindowController(windowNibName: "KMCompressWindowController") self.currentWindowController = windowController windowController.documentURL = url windowController.password = password windowController.itemClick = { [weak self] (index: Int) -> () in self!.view.window?.endSheet(self!.currentWindowController!.window!) self?.currentWindowController = nil } windowController.resultCallback = { [weak self] (result: Bool, openDocument: Bool, fileURL: URL, error: String) in if result { self!.view.window?.endSheet(self!.currentWindowController!.window!) self?.currentWindowController = nil if openDocument { if !fileURL.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 } NSDocumentController.shared.openDocument(withContentsOf: fileURL, display: true) { document, result, error in if error != nil { NSApp.presentError(error!) return } } } else { NSWorkspace.shared.activateFileViewerSelecting([fileURL]) } } else { let alert = NSAlert() alert.messageText = NSLocalizedString("Compress Faild", comment: "") alert.runModal() } } await self.view.window?.beginSheet(windowController.window!) } } func fastTool_Security() { // 安全 Task { @MainActor in if await (KMLightMemberManager.manager.canUseAdvanced() == false) { let _ = KMComparativeTableViewController.show(window: self.view.window!) return } NSOpenPanel.km_secure_openPanel(window: self.view.window!, needOwner: true) { url, result, passowrd in if (url == nil) { return } if (result != nil && result! == .cancel) { return } let windowController = KMSecureEncryptWindowController(windowNibName: "KMSecureEncryptWindowController") windowController.documentURL = url! windowController.myDocument = CPDFDocument(url: url!) if (passowrd != nil) { windowController.myDocument.unlock(withPassword: passowrd) } self.currentWindowController = windowController let newDocument: CPDFDocument = CPDFDocument(url: url!) windowController.itemClick = { [weak self] (index: Int) -> () in self!.view.window?.endSheet((self?.currentWindowController?.window!)!) self?.currentWindowController = nil } windowController.resultCallback = { [weak self] (result: Bool) -> () in let windowController_secure: KMSecureEncryptWindowController = self?.currentWindowController as! KMSecureEncryptWindowController self!.view.window?.endSheet((self?.currentWindowController?.window!)!) self!.currentWindowController = nil if (passowrd != nil) { newDocument.unlock(withPassword: passowrd) } newDocument.setPasswordOptions(windowController_secure.options) let result = KMPasswordInputWindow.saveDocument(newDocument) if result { NSWorkspace.shared.activateFileViewerSelecting([newDocument.documentURL]) } else { let alert = NSAlert() alert.messageText = NSLocalizedString("Failure", comment: "") alert.runModal() } } self.view.window?.beginSheet(windowController.window!) } } } func fastTool_FileCompare() { // 文件对比 print("选中 快捷工具 文件对比") } func fastTool_PDFToPPT() { // PDF转PPT Task { @MainActor in if await (KMLightMemberManager.manager.canUseAdvanced() == false) { let _ = KMComparativeTableViewController.show(window: self.view.window!) return } NSOpenPanel.km_secure_openPanel_success(window: self.view.window!) { url, password in let windowController = KMConvertPPTsWindowController(windowNibName: "KMConvertBaseWindowController") let model = KMDocumentModel(url: url) windowController.subType = 1 if (password != nil) { let _ = model.unlock(password!) } windowController.documentModel = model windowController.itemClick = { [weak self] (index: Int) in if (self?.currentWindowController == nil) { return } self?.view.window?.endSheet((self?.currentWindowController?.window)!) self?.currentWindowController = nil } self.view.window?.beginSheet(windowController.window!) self.currentWindowController = windowController } } } func fastTool_PDFToExcel() { // PDF转Excel Task { @MainActor in if await (KMLightMemberManager.manager.canUseAdvanced() == false) { let _ = KMComparativeTableViewController.show(window: self.view.window!) return } NSOpenPanel.km_secure_openPanel_success(window: self.view.window!) { url, password in let windowController = KMConvertExcelWindowController(windowNibName: "KMConvertBaseWindowController") let model = KMDocumentModel(url: url) if (password != nil) { let _ = model.unlock(password!) } windowController.documentModel = model windowController.itemClick = { [weak self] (index: Int) in if (self?.currentWindowController == nil) { return } self?.view.window?.endSheet((self?.currentWindowController?.window)!) self?.currentWindowController = nil } self.view.window?.beginSheet(windowController.window!) self.currentWindowController = windowController } } } func fastTool_PDFToWord() { // PDF转Word Task { @MainActor in if await (KMLightMemberManager.manager.canUseAdvanced() == false) { let _ = KMComparativeTableViewController.show(window: self.view.window!) return } NSOpenPanel.km_secure_openPanel_success(window: self.view.window!) { url, password in if (url.path.isPDFValid() == false) { 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 } let windowController = KMConvertWordWindowController(windowNibName: "KMConvertBaseWindowController") let model = KMDocumentModel(url: url) if (password != nil) { let _ = model.unlock(password!) } windowController.documentModel = model windowController.itemClick = { [weak self] (index: Int) in if (self?.currentWindowController == nil) { return } self?.view.window?.endSheet((self?.currentWindowController?.window)!) self?.currentWindowController = nil } self.view.window?.beginSheet(windowController.window!) self.currentWindowController = windowController } } } func fastTool_PDFToImage() { // PDF转图片 Task { @MainActor in if await (KMLightMemberManager.manager.canUseAdvanced() == false) { let _ = KMComparativeTableViewController.show(window: self.view.window!) return } NSOpenPanel.km_secure_openPanel_success(window: self.view.window!) { url, password in let windowController = KMConvertImageWindowController(windowNibName: "KMConvertBaseWindowController") let model = KMDocumentModel(url: url) if (password != nil) { let _ = model.unlock(password!) } windowController.documentModel = model windowController.itemClick = { [weak self] (index: Int) in if (self?.currentWindowController == nil) { return } self?.view.window?.endSheet((self?.currentWindowController?.window)!) self?.currentWindowController = nil } self.view.window?.beginSheet(windowController.window!) self.currentWindowController = windowController } } } func fastTool_Watermark() { // 水印 KMBatchWindowController.openFile(nil, .Watermark) } func fastTool_Background() { // 背景 KMBatchWindowController.openFile(nil, .Background) } func fastTool_HeaderAndFooter() { // 页眉页脚 KMBatchWindowController.openFile(nil, .HeaderAndFooter) } func fastTool_BatesCode() { // 贝茨码 KMBatchWindowController.openFile(nil, .BatesCode) } func fastTool_Print() { // 打印 KMPrintWindowController.openFiles(window: self.view.window!) } func fastTool_BatchRemove() { // 批量移除 KMBatchWindowController.openFile(nil, .BatchRemove) } func fastTool_Insert() { // 插入 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: .Insert) insertWindowController.beginSheetModal(for: self.view.window!) { pdfDocument, password, pages, indexPage in self.insertPageAction(pdfDocument, password, pages, indexPage) } } } } } func fastTool_BreakUp() { // 拆分 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 document = CPDFDocument(url: openPanel.url) let model = KMPageEditSplitSettingModel() model.documentURL = openPanel.url model.fileName = model.documentURL.lastPathComponent model.pathExtension = model.fileName.components(separatedBy: ".").last let windowController = KMPageEditSplitWindowController(model) windowController.hasPreView = true self.view.window?.beginSheet(windowController.window!) self.currentWindowController = windowController windowController.itemClick = { [weak self] index, value in if (index == 1) { /// 取消 self?.view.window?.endSheet((self?.currentWindowController!.window)!) self?.currentWindowController = nil return } /// 拆分 let windowController_split: KMPageEditSplitWindowController = self?.currentWindowController as! KMPageEditSplitWindowController let outputModel: KMPageEditSplitSettingModel = windowController_split.model! as! KMPageEditSplitSettingModel self?.view.window?.endSheet((self?.currentWindowController!.window)!) self?.currentWindowController = nil let panel = NSOpenPanel() panel.canChooseFiles = false panel.canChooseDirectories = true panel.canCreateDirectories = true panel.beginSheetModal(for: (self?.view.window)!) { response in KMPageEditTools.split(document!, outputModel, panel.url!.path, outputModel.outputFileNameDeletePathExtension) { result, outputDocuments, error in if (result) { } } } } } } } } 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 fastTool_MarkCipher() { // 标记密文 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 } DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { NSDocumentController.shared.openDocument(withContentsOf: openPanel.url!, display: true) { document, result, error in if (error != nil) { NSApp.presentError(error!) return } let toolbar = (document as! KMMainDocument).mainViewController?.toolbarController toolbar?.enterRedact() } } } } func fastTool_AutomaticFormRecognition() { // 表单自动识别 let openPanel = NSOpenPanel() openPanel.prompt = "表单自动识别" openPanel.allowsMultipleSelection = false openPanel.allowedFileTypes = ["pdf"] openPanel.beginSheetModal(for: NSApp.mainWindow!) { result in if result == .OK { } } } func fastTool_PageEdit() { // 页面编辑 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 } DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { NSDocumentController.shared.openDocument(withContentsOf: openPanel.url!, display: true) { document, result, error in if (error != nil) { NSApp.presentError(error!) return } let mainView = (document as! KMMainDocument).mainViewController mainView?.enterPageEdit() } } } } // MARK: MenuItem Action & PopoverItem Action func popoverItemAction(_ count: String) { if count == NSLocalizedString("New Blank Page", comment: "") { openBlankPage("") } else if count == NSLocalizedString("New From Web Page", comment: "") { importFromWebPage("") } else if count == NSLocalizedString("Import From Scanner", comment: "") { importFromScanner("") } } @IBAction func escButtonAction(_ sender: Any) { self.historyFileViewController.selectFiles.removeAll() if self.historyFileViewController.showMode == .Thumbnail { self.historyFileViewController.historyFileCollectionView.reloadData() } else { self.historyFileViewController.historyFileTableView.reloadData() } } @IBAction func importFromFile(_ sender: Any) { self.openSupportPDFButtonAction() } @IBAction func openBlankPage(_ sender: Any) { let fileName: NSString = String(format: "%@.pdf", NSLocalizedString("Untitled", comment: "")) as NSString let savePath = fetchUniquePath(fileName.kUrlToPDFFolderPath()) let pdfDocument = CPDFDocument() pdfDocument?.insertPage(CGSize(width: 595, height: 842), at: 0) pdfDocument?.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 } } } } @IBAction func importFromWebPage(_ sender: Any) { self.urlToPDFWindowController = KMURLToPDFWindowController.init(windowNibName: NSNib.Name("KMURLToPDFWindowController")) self.urlToPDFWindowController!.beginSheetModal(for: NSApp.mainWindow!) { filePath in if filePath != nil && FileManager.default.fileExists(atPath: filePath) { NSDocumentController.shared.openDocument(withContentsOf: URL(fileURLWithPath: filePath), display: true) { document, documentWasAlreadyOpen, error in if error != nil { NSApp.presentError(error!) } else { if document is KMMainDocument { (document as! KMMainDocument).isNewCreated = true } } } } } } @IBAction func importFromScanner(_ sender: Any) { deviceBrowserWC = KMDeviceBrowserWindowController.shared deviceBrowserWC?.type = .scanner deviceBrowserWC?.importScannerFileCallback = { [weak self](url: NSURL) -> Void in self?.openFile(withFilePath: url as URL) } deviceBrowserWC?.showWindow(NSApp.mainWindow) } @IBAction func menuItemClick_mergePDF(_ sender: Any) { fastTool_MergePDF() } @IBAction func menuItemClick_Compress(_ sender: Any) { fastTool_Compression() } @IBAction func menuItemClick_Convert(_ sender: Any) { fastTool_ConvertPDF() } @IBAction func menuItemClick_SettingPassword(_ sender: Any) { fastTool_Security() } @IBAction func menuItemClick_RemovePassword(_ sender: Any) { fastTool_Security() } 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 kNewDocumentTempSavePath(_ fileName: String) -> String { // let searchPath = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).last //// let append1 = searchPath?.stringByAppendingPathComponent(Bundle.main.bundleIdentifier!) // let append2 = searchPath!.stringByAppendingPathComponent(String(format: "%@", fileName)) // return append2 // } // MARK: Notification @objc func homeFileRectChange(_ notification: Notification) -> Void { let window = notification.object self.historyFileViewController.reloadData() } } // MARK: window Menu extension KMHomeViewController { @IBAction func menuItemAction_showForwardTagPage(_ sender: Any) { (self.myDocument as! KMMainDocument).browser.selectPreviousTab() } @IBAction func menuItemAction_showNextTagPage(_ sender: Any) { (self.myDocument as! KMMainDocument).browser.selectNextTab() } @IBAction func menuItemAction_newTagPageToNewWindow(_ sender: Any) { let browser = (self.myDocument as! KMMainDocument).browser ((browser as! KMBrowser).windowController as? KMBrowserWindowController)?.openNewWindow(sender) } @IBAction func menuItemAction_mergeAllWindow(_ sender: Any) { ((self.myDocument as? KMMainDocument)?.browser.windowController as? KMBrowserWindowController)?.mergeAllWindow(sender) } @IBAction func menuItemAction_currentWindowName(_ sender: Any) { } } // MARK: file Menu extension KMHomeViewController { @IBAction func menuItemAction_closeWindow(_ sender: Any) { self.view.window?.close() } @IBAction func menuItemAction_closeAllWindows(_ sender: Any) { for window in NSApp.windows { window.close() } } @IBAction func menuItemAction_ConvertToWord(_ sender: Any) { self.fastTool_PDFToWord() } @IBAction func menuItemAction_ConvertToExcel(_ sender: Any) { self.fastTool_PDFToExcel() } @IBAction func menuItemAction_ConvertToPPT(_ sender: Any) { self.fastTool_PDFToPPT() } @IBAction func menuItemAction_ConvertToRTF(_ sender: Any) { self.showConvertWindow(type: .rtf) } @IBAction func menuItemAction_ConvertToHTML(_ sender: Any) { self.showConvertWindow(type: .html) } @IBAction func menuItemAction_ConvertToText(_ sender: Any) { self.showConvertWindow(type: .text) } @IBAction func menuItemAction_ConvertToCSV(_ sender: Any) { self.showConvertWindow(type: .csv) } @IBAction func menuItemAction_ConvertToImage(_ sender: Any) { self.fastTool_PDFToImage() } } // MARK: help Menu extension KMHomeViewController { // @IBAction func menuItemAction_search(_ sender: Any) { // // } }