KMNHomeViewController.swift 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076
  1. //
  2. // KMNHomeViewController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by Niehaoyu on 2024/10/8.
  6. //
  7. import Cocoa
  8. import KMComponentLibrary
  9. class KMNHomeViewController: KMNBaseViewController {
  10. @IBOutlet var leftContendBox: NSBox!
  11. @IBOutlet var leftDivider: ComponentDivider!
  12. @IBOutlet var homeOpenView: KMHomeOpenView!
  13. @IBOutlet var homeRecommondView: KMHomeRecommondView!
  14. @IBOutlet var rightContendBox: NSBox!
  15. @IBOutlet var rightInfoView: KMHomeRightView!
  16. @IBOutlet var homeDragView: KMHomeDragView!
  17. var demoVC: WCCompWindowController = WCCompWindowController(windowNibName: "WCCompWindowController")
  18. var createWC: KMURLCreatePDFWindowController = KMURLCreatePDFWindowController(windowNibName: "KMURLCreatePDFWindowController")
  19. var currentWindowController: NSWindowController?
  20. var currentController: NSWindowController?
  21. //合并
  22. var mergeWindowController: KMMergeWindowController?
  23. var extrackWindowController: KMExtractWindowController?
  24. deinit {
  25. NotificationCenter.default.removeObserver(self)
  26. }
  27. override func viewDidLoad() {
  28. super.viewDidLoad()
  29. // Do view setup here.
  30. self.configLeftContendView()
  31. self.configRightContendView()
  32. self.initAdvertisementData()
  33. homeDragView.delegate = self
  34. NotificationCenter.default.addObserver(self, selector: #selector(_handleWindowDidBecomeMainNotification), name: NSWindow.didBecomeMainNotification, object: nil)
  35. }
  36. override func viewDidAppear() {
  37. super.viewDidAppear()
  38. rightInfoView.resetScrollerStyle()
  39. rightInfoView.reloadData()
  40. }
  41. override func updateUIThemeColor() {
  42. super.updateUIThemeColor()
  43. leftContendBox.fillColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg/layout-middle")
  44. rightContendBox.fillColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg/layout-low")
  45. }
  46. func configLeftContendView() {
  47. leftDivider.properties = ComponentDividerProperty(type: .vertical, dash: false)
  48. homeOpenView.delegate = self
  49. self.homeRecommondView.reloadData()
  50. }
  51. func configRightContendView() {
  52. rightInfoView.delegate = self
  53. rightInfoView.reloadData()
  54. }
  55. func initAdvertisementData() {
  56. KMAdvertisementManager.manager.fetchDataWithResponseObject { [weak self] data, responseObject, error in
  57. KMPrint("获取广告数据成功")
  58. if data != nil {
  59. let content = data!.recommondContent
  60. let item = content?.recommondContentPDFPro
  61. var infos: [KMAdvertisementItemInfo] = []
  62. for info in item?.content ?? [] {
  63. if info.version == "recommondPDF-PDFtoOfficePack" {
  64. if IAPProductsManager.default().isAvailableAdvancedPDFToOffice() == false {
  65. infos.append(info)
  66. }
  67. } else {
  68. infos.append(info)
  69. }
  70. }
  71. item?.content = infos
  72. if KMAdvertisementManager.manager.infoDict.allKeys.count > 0 {
  73. if let adsInfo = KMAdvertisementManager.manager.infoDict["adsInfo"] {
  74. let infoDict: NSDictionary = KMAdvertisementManager.manager.infoDict["adsInfo"] as! NSDictionary
  75. let array: [[String: Any]] = infoDict["content"] as! [[String : Any]]
  76. let arrM = NSMutableArray.init()
  77. for dict in array {
  78. let adsInfo = KMAdsInfo.init()
  79. let mutableDictionary = NSMutableDictionary(dictionary: dict)
  80. adsInfo.infoDict = mutableDictionary
  81. arrM.add(adsInfo)
  82. }
  83. KMAdsInfoManager.shareInstance.adsInfoArrM = arrM
  84. }
  85. if let couponInfo = KMAdvertisementManager.manager.infoDict["couponContent"] {
  86. let infoDict: NSDictionary = KMAdvertisementManager.manager.infoDict["couponContent"] as! NSDictionary
  87. let array: [[String: Any]] = infoDict["content"] as! [[String : Any]]
  88. if array.isEmpty == false {
  89. let dict = array[0]
  90. let adsInfo = KMCouponInfo.init()
  91. let mutableDictionary = NSMutableDictionary(dictionary: dict)
  92. adsInfo.infoDict = mutableDictionary
  93. KMAdsInfoManager.shareInstance.couponInfo = adsInfo
  94. }
  95. }
  96. }
  97. }
  98. DispatchQueue.main.async {
  99. self?.homeRecommondView.reloadData()
  100. }
  101. }
  102. }
  103. @IBAction func showDemo(_ sender: Any) {
  104. demoVC.window?.center()
  105. demoVC.showWindow(nil)
  106. }
  107. func loadOpenFileFunctionGuide(_ showType: KMGuideInfoType) -> Void {
  108. if showType == .messageDiscount && KMGuideInfoWindowController.availableShow(.messageDiscount) {
  109. let guideInfoWindowController = KMGuideInfoWindowController.currentWC()
  110. guideInfoWindowController.type = .messageDiscount
  111. let winC = self.view.window?.windowController as? KMBrowserWindowController
  112. guard let item = winC?.rightMessageVC.discountItemView, item.isHidden == false else {
  113. return
  114. }
  115. guard let win = self.view.window else {
  116. return
  117. }
  118. guideInfoWindowController.targetRect = (win.contentView?.convert(item.frame, from: item.superview)) ?? .zero
  119. guideInfoWindowController.finishHandle = { [weak self] winC, type in
  120. if type == .getIt {
  121. // self?.showAITypeChooseView(aiConfigType: .none)
  122. return
  123. }
  124. }
  125. guideInfoWindowController.autoClose = true
  126. guideInfoWindowController.autoCloseTimeInterval = 5
  127. guideInfoWindowController.window?.collectionBehavior = [.canJoinAllSpaces]
  128. var rect = self.view.window!.frame
  129. rect.size.height += 20
  130. guideInfoWindowController.window?.setFrame(rect, display: false)
  131. guideInfoWindowController.window?.minSize = rect.size
  132. guideInfoWindowController.window?.maxSize = rect.size
  133. self.view.window?.addChildWindow(guideInfoWindowController.window!, ordered: .above)
  134. guideInfoWindowController.show()
  135. }
  136. }
  137. override func keyDown(with event: NSEvent) {
  138. let command = event.modifierFlags.contains(.command)
  139. let control = event.modifierFlags.contains(.control)
  140. let shift = event.modifierFlags.contains(.shift)
  141. let option = event.modifierFlags.contains(.option)
  142. if let _windowC = NSApp.mainWindow?.windowController as? KMBrowserWindowController {
  143. if command && event.keyCode == 17 {
  144. //新标签
  145. // _windowC.openDocumentWindow()
  146. } else {
  147. super.keyDown(with: event)
  148. }
  149. } else {
  150. super.keyDown(with: event)
  151. }
  152. }
  153. @objc func _handleWindowDidBecomeMainNotification(_ sender: Notification) {
  154. self.rightInfoView.reloadData()
  155. }
  156. }
  157. //MARK: - KMHomeOpenViewDelegate
  158. extension KMNHomeViewController: KMHomeOpenViewDelegate {
  159. func homeOpenViewDidChooseFileURL(_ view: KMHomeOpenView?, _ url: URL) {
  160. self.openFile(withFilePath: url)
  161. }
  162. }
  163. //MARK: - KMHomeRightViewDelegate
  164. extension KMNHomeViewController: KMHomeRightViewDelegate {
  165. //点击管理快捷工具按钮
  166. func homeRightViewDidManageQuickTools(_ view: KMHomeRightView) {
  167. let quickToolWindowController: KMNQuickToolWindowController = KMNQuickToolWindowController.init(windowNibName: "KMNQuickToolWindowController")
  168. quickToolWindowController.delegate = self
  169. quickToolWindowController.own_beginSheetModal(for: self.view.window) { string in
  170. }
  171. }
  172. //点击快捷工具列表中的某一项
  173. func homeRightViewDidQuickToolsItemClicked(_ view: KMHomeRightView, _ toolType: HomeQuickToolType) {
  174. self.quickToolsActionWith(toolType)
  175. }
  176. //最近文件列表删除更新结束后回调
  177. func homeRightViewDidRecentFilesUpdated(_ view: KMHomeRightView) {
  178. }
  179. //选择打开文件
  180. func homeRightViewDidChooseFileToOpen(_ view: KMHomeRightView, _ fileURL: URL) {
  181. self.openFile(withFilePath: fileURL)
  182. }
  183. }
  184. //MARK: - KMNQuickToolWindowDelegate
  185. extension KMNHomeViewController: KMNQuickToolWindowDelegate {
  186. func quickToolWindowControllerUpdate() {
  187. rightInfoView.reloadData()
  188. }
  189. }
  190. //MARK: - KMHomeDragViewDelegate
  191. extension KMNHomeViewController: KMHomeDragViewDelegate {
  192. func homeDragView(_ viewController: KMHomeDragView, filePath: URL) {
  193. self.openFile(withFilePath: filePath)
  194. }
  195. func homeDragView(_ viewController: KMHomeDragView, notSupport: Bool) {
  196. if notSupport {
  197. let alert = NSAlert()
  198. alert.alertStyle = .critical
  199. alert.messageText = KMLocalizedString("This file format is not supported. Please enter PDF, picture, or Office file")
  200. alert.runModal()
  201. }
  202. }
  203. }
  204. //MARK: - Open Files
  205. extension KMNHomeViewController {
  206. func openFile(withFilePath path: URL) -> Void {
  207. if let _windowC = NSApp.mainWindow?.windowController as? KMBrowserWindowController {
  208. _windowC.openFile(withFilePath: path)
  209. } else {
  210. for window in NSApp.windows {
  211. if let browseWindow = window as? KMBrowserWindow {
  212. if let browseWC = browseWindow.windowController as? KMBrowserWindowController {
  213. browseWC.openFile(withFilePath: path)
  214. break
  215. }
  216. }
  217. }
  218. }
  219. }
  220. func openImageToPdfWindow(urls: Array<URL>) {
  221. if let _windowC = NSApp.mainWindow?.windowController as? KMBrowserWindowController {
  222. _windowC.showBatchWindow(type: .imageToPDF, files: urls)
  223. } else {
  224. for window in NSApp.windows {
  225. if let browseWindow = window as? KMBrowserWindow {
  226. if let browseWC = browseWindow.windowController as? KMBrowserWindowController {
  227. browseWC.showBatchWindow(type: .imageToPDF, files: urls)
  228. break
  229. }
  230. }
  231. }
  232. }
  233. }
  234. func showLimitWindowAlert(url: URL?) {
  235. if !KMDataManager.default.isTabbingWin{
  236. KMDataManager.default.isTabbingWin = true
  237. let tabbingWin: KMTabbingHintWindowController = KMTabbingHintWindowController()
  238. tabbingWin.selectCallBack = {[weak self] continueOrNot in
  239. KMDataManager.default.isTabbingWin = false
  240. if continueOrNot {
  241. self?.reopenDocument(forPaths: url)
  242. } else {
  243. }
  244. }
  245. self.km_beginSheet(windowC: tabbingWin)
  246. }
  247. }
  248. func reopenDocument(forPaths path: URL?) -> Void {
  249. if path == nil {
  250. let browser = KMBrowser.init() as KMBrowser
  251. browser.windowController = KMBrowserWindowController.init(browser: browser)
  252. browser.addHomeTabContents()
  253. browser.windowController.showWindow(self)
  254. }else {
  255. let browser = KMBrowser.init() as KMBrowser
  256. browser.windowController = KMBrowserWindowController.init(browser: browser)
  257. browser.addHomeTabContents()
  258. browser.windowController.showWindow(self)
  259. NSDocumentController.shared.km_safe_openDocument(withContentsOf: path!, display: true) { doc, open, err in
  260. }
  261. }
  262. }
  263. func fetchUniquePath(_ originalPath: String) -> String {
  264. var path = originalPath
  265. let dManager = FileManager.default
  266. if !dManager.fileExists(atPath: path) {
  267. if path.extension.count < 1 {
  268. path = path.stringByAppendingPathExtension("pdf")
  269. }
  270. return path
  271. } else {
  272. let originalFullFileName = path.lastPathComponent
  273. let originalFileName = path.lastPathComponent.deletingPathExtension.lastPathComponent
  274. let originalExtension = path.extension
  275. let startIndex: Int = 0
  276. let endIndex: Int = startIndex + originalPath.count - originalFullFileName.count - 1
  277. let fileLocatePath = originalPath.substring(to: endIndex)
  278. var i = 1
  279. while (1 != 0) {
  280. var newName = String(format: "%@%ld", originalFileName, i)
  281. newName = String(format: "%@%@", newName, originalExtension)
  282. let newPath = fileLocatePath.stringByAppendingPathComponent(newName)
  283. if !dManager.fileExists(atPath: newPath) {
  284. return newPath
  285. } else {
  286. i+=1
  287. continue
  288. }
  289. }
  290. }
  291. }
  292. func fetchDifferentFilePath(filePath: String) -> String {
  293. var resultFilePath = filePath
  294. var index: Int = 0
  295. while (FileManager.default.fileExists(atPath: resultFilePath)) {
  296. index += 1
  297. let path = NSString(string: filePath).deletingPathExtension + "(" + String(index) + ")"
  298. resultFilePath = NSString(string: path).appendingPathExtension(NSString(string: filePath).pathExtension)!
  299. }
  300. return resultFilePath;
  301. }
  302. func isDamageImage(image: NSImage?, path: String) -> Bool {
  303. if (image == nil) {
  304. return true
  305. }
  306. let addImageAnnotation = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).last!.appendingPathComponent(Bundle.main.bundleIdentifier!).appendingPathComponent("addImageAnnotation")
  307. if !FileManager.default.fileExists(atPath: addImageAnnotation.path) {
  308. try? FileManager.default.createDirectory(atPath: addImageAnnotation.path, withIntermediateDirectories: false, attributes: nil)
  309. }
  310. guard let data = image!.tiffRepresentation else { return false }
  311. guard let imageRep = NSBitmapImageRep(data: data) else { return false }
  312. imageRep.size = image!.size
  313. var imageData: Data?
  314. if path.lowercased() == "png" {
  315. imageData = imageRep.representation(using: .png, properties: [:])
  316. } else {
  317. imageData = imageRep.representation(using: .jpeg, properties: [:])
  318. }
  319. let rPath: URL = addImageAnnotation.appendingPathComponent(tagString()).appendingPathExtension("png")
  320. if let data = imageData {
  321. try?data.write(to: rPath)
  322. return false
  323. } else {
  324. return true
  325. }
  326. }
  327. func tagString() -> String {
  328. let dateFormatter = DateFormatter()
  329. dateFormatter.dateFormat = "yyMMddHHmmss"
  330. let currentDate = Date()
  331. let randomNum = Int(arc4random_uniform(10000))
  332. let str = String(format: "%@%04d", dateFormatter.string(from: Date()),randomNum)
  333. return str
  334. }
  335. func convertTIFFDataToPDF(_ tiffData: Data) -> Data? {
  336. guard let imsrc = CGImageSourceCreateWithData(tiffData as CFData, [kCGImageSourceTypeIdentifierHint: kUTTypeTIFF] as CFDictionary), CGImageSourceGetCount(imsrc) > 0, let cgImage = CGImageSourceCreateImageAtIndex(imsrc, 0, nil) else { return nil }
  337. let pdfData = NSMutableData(capacity: tiffData.count)
  338. let consumer = CGDataConsumer(data: pdfData! as CFMutableData)!
  339. var rect = CGRect(x: 0, y: 0, width: CGFloat(cgImage.width), height: CGFloat(cgImage.height))
  340. let ctxt = CGContext(consumer: consumer, mediaBox: &rect, nil)
  341. ctxt!.beginPDFPage(nil)
  342. ctxt!.draw(cgImage, in: rect)
  343. ctxt!.endPDFPage()
  344. ctxt!.closePDF()
  345. return pdfData as? Data
  346. }
  347. }
  348. //MARK: - Quick Tools Action
  349. extension KMNHomeViewController {
  350. func quickToolsActionWith(_ type: HomeQuickToolType) {
  351. switch type {
  352. case .Batch:
  353. fastTool_Batch()
  354. break
  355. case .MergePDF:
  356. fastTool_MergePDF()
  357. break
  358. case .ImageToPDF:
  359. imageToPDFAction()
  360. break
  361. case .OCR:
  362. fastTool_OCR()
  363. break
  364. case .ConvertPDF:
  365. fastTool_ConvertPDF()
  366. break
  367. case .PDFToWord:
  368. fastTool_ConvertPDF()
  369. break
  370. case .PDFToExcel:
  371. fastTool_PDFToExcel()
  372. break
  373. case .Compression:
  374. fastTool_Compression()
  375. break
  376. case .PDFToPPT:
  377. fastTool_PDFToPPT()
  378. break
  379. case .Security:
  380. fastTool_Security()
  381. break
  382. case .FileCompare:
  383. fastTool_FileCompare()
  384. break
  385. case .Watermark:
  386. fastTool_Watermark()
  387. break
  388. case .Insert:
  389. fastTool_Insert()
  390. break
  391. case .Extract:
  392. fastTool_Extract()
  393. break
  394. case .DigitalSignature:
  395. break
  396. case .Print:
  397. fastTool_Print()
  398. break
  399. }
  400. }
  401. func imageToPDFAction() {
  402. let openPanel = NSOpenPanel()
  403. openPanel.allowedFileTypes = KMBatchManager.supportedImageTypes()
  404. //MARK: 允许多选还是单选,如果是付费用户允许多选
  405. openPanel.allowsMultipleSelection = true
  406. openPanel.message = KMLocalizedString("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: "")
  407. if KMMemberInfo.shared.isLogin == true {
  408. openPanel.allowsMultipleSelection = true
  409. } else {
  410. openPanel.allowsMultipleSelection = false
  411. }
  412. openPanel.beginSheetModal(for: NSWindow.currentWindow()) {[weak self] result in
  413. if result == NSApplication.ModalResponse.OK {
  414. guard let weakSelf = self else { return }
  415. let urls = openPanel.urls as [URL]
  416. weakSelf.openImageToPdfWindow(urls: urls)
  417. }
  418. }
  419. }
  420. func fastTool_Batch() { // Batch
  421. let batchWindowController = KMBatchWindowController.manager
  422. batchWindowController.type = .convertPDF
  423. batchWindowController.inputData = []
  424. batchWindowController.window?.makeKeyAndOrderFront("")
  425. }
  426. func fastTool_MergePDF() { // MergePDF
  427. mergeWindowController = KMMergeWindowController(windowNibName: "KMMergeWindowController")
  428. mergeWindowController!.type = .merge
  429. mergeWindowController!.cancelAction = { [unowned self] controller in
  430. self.view.window?.endSheet((self.mergeWindowController!.window)!)
  431. }
  432. view.window?.beginSheet(mergeWindowController!.window!)
  433. }
  434. func fastTool_OCR() { // OCR
  435. let openPanel = NSOpenPanel()
  436. var arr = KMBatchManager.supportedImageTypes()
  437. arr.append("pdf")
  438. openPanel.allowedFileTypes = arr
  439. openPanel.allowsMultipleSelection = false
  440. openPanel.beginSheetModal(for: NSWindow.currentWindow()) { [self] (result) in
  441. if result == NSApplication.ModalResponse.OK {
  442. quickOcr(urls: openPanel.urls)
  443. }
  444. }
  445. }
  446. func quickOcr(urls: Array<URL>) {
  447. showBatchWindow(type: .OCR, files: urls)
  448. }
  449. func fastTool_ConvertPDF() { // 转换PDF
  450. let openPanel = NSOpenPanel()
  451. var arr = KMBatchManager.supportedImageTypes()
  452. arr.append("pdf")
  453. openPanel.allowedFileTypes = ["pdf","PDF"]
  454. //MARK: 允许多选还是单选,如果是付费用户允许多选
  455. openPanel.allowsMultipleSelection = false
  456. openPanel.beginSheetModal(for: self.view.window!) { [self] (result) in
  457. if result == NSApplication.ModalResponse.OK {
  458. quickConvertPdf(urls: openPanel.urls, type: .WordAdvance)
  459. }
  460. }
  461. }
  462. func quickConvertPdf(urls: Array<URL>, type: KMConvertWithPDFType) {
  463. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
  464. self.showBatchWindow(type: .convertPDF, subType: type.rawValue,files: urls)
  465. }
  466. }
  467. func fastTool_PDFToPPT() {
  468. let openPanel = NSOpenPanel()
  469. openPanel.allowedFileTypes = ["pdf","PDF"]
  470. //MARK: 允许多选还是单选,如果是付费用户允许多选
  471. openPanel.allowsMultipleSelection = false
  472. openPanel.beginSheetModal(for: NSWindow.currentWindow()) { [self] (result) in
  473. if result == NSApplication.ModalResponse.OK {
  474. quickConvertPdf(urls: openPanel.urls, type: .PowerPoint)
  475. }
  476. }
  477. }
  478. func fastTool_PDFToExcel() {
  479. let openPanel = NSOpenPanel()
  480. openPanel.allowedFileTypes = ["pdf","PDF"]
  481. //MARK: 允许多选还是单选,如果是付费用户允许多选
  482. openPanel.allowsMultipleSelection = false
  483. openPanel.beginSheetModal(for: NSWindow.currentWindow()) { [self] (result) in
  484. if result == NSApplication.ModalResponse.OK {
  485. quickConvertPdf(urls: openPanel.urls, type: .Excel)
  486. }
  487. }
  488. }
  489. // 压缩
  490. func fastTool_Compression() {
  491. let openPanel = NSOpenPanel()
  492. openPanel.allowedFileTypes = ["pdf","PDF"]
  493. //MARK: 允许多选还是单选,如果是付费用户允许多选
  494. openPanel.allowsMultipleSelection = false
  495. openPanel.beginSheetModal(for: NSWindow.currentWindow()) { [self] (result) in
  496. if result == NSApplication.ModalResponse.OK {
  497. quickCompressPdf(urls: openPanel.urls)
  498. }
  499. }
  500. }
  501. func quickCompressPdf(urls: Array<URL>) {
  502. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
  503. self.showBatchWindow(type: .compress, files: urls)
  504. }
  505. }
  506. // 安全
  507. func fastTool_Security() {
  508. let openPanel = NSOpenPanel()
  509. openPanel.allowedFileTypes = ["pdf","PDF"]
  510. //MARK: 允许多选还是单选,如果是付费用户允许多选
  511. openPanel.allowsMultipleSelection = true
  512. openPanel.message = KMLocalizedString("To select multiple files press cmd ⌘ button on keyboard and click on the target files one by one.", comment: "")
  513. openPanel.beginSheetModal(for: NSWindow.currentWindow()) { [self] (result) in
  514. if result == NSApplication.ModalResponse.OK {
  515. quickPassword(urls: openPanel.urls)
  516. }
  517. }
  518. }
  519. func quickPassword(urls: Array<URL>) {
  520. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
  521. self.showBatchWindow(type: .security, files: urls)
  522. }
  523. }
  524. func fastTool_FileCompare() { // 文件对比
  525. let openPanel = NSOpenPanel()
  526. openPanel.allowsMultipleSelection = false
  527. openPanel.allowedFileTypes = ["pdf"]
  528. openPanel.beginSheetModal(for: NSApp.mainWindow!) { result in
  529. if result == .cancel {
  530. return
  531. }
  532. if !openPanel.url!.path.isPDFValid() {
  533. let alert = NSAlert()
  534. alert.alertStyle = .critical
  535. alert.messageText = KMLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", comment: "")
  536. alert.runModal()
  537. return
  538. }
  539. NSWindowController.checkPassword(url: URL(fileURLWithPath: openPanel.url!.path), type: .owner) { [unowned self] success, resultPassword in
  540. if success {
  541. DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
  542. let controller = KMCompareWindowController(windowNibName: "KMCompareWindowController")
  543. controller.password = resultPassword
  544. controller.filePath = openPanel.url!.path
  545. controller.cancelAction = { [unowned self] contr in
  546. self.view.window?.endSheet((controller.window)!)
  547. }
  548. controller.contentComplete = { [unowned self] controller, pdfCompareContent, result, oldDocument, document in
  549. self.view.window?.endSheet((controller.window)!)
  550. self.openContentCompareVC(with: pdfCompareContent, results: result, oldDocument: oldDocument, document: document)
  551. }
  552. controller.coveringComplete = { [unowned self] controller, document in
  553. self.openCoveringCompareVC(with: document)
  554. self.view.window?.endSheet((controller.window)!)
  555. }
  556. controller.fileType = .content
  557. NSWindow.currentWindow().beginSheet(controller.window!)
  558. }
  559. } else {
  560. }
  561. }
  562. }
  563. }
  564. func fastTool_Watermark() { // 水印
  565. let openPanel = NSOpenPanel()
  566. openPanel.allowedFileTypes = ["pdf","PDF"]
  567. //MARK: 允许多选还是单选,如果是付费用户允许多选
  568. openPanel.allowsMultipleSelection = false
  569. openPanel.beginSheetModal(for: NSWindow.currentWindow()) { [self] (result) in
  570. if result == NSApplication.ModalResponse.OK {
  571. quickWaterMark(urls: openPanel.urls)
  572. }
  573. }
  574. }
  575. func quickWaterMark(urls: Array<URL>) {
  576. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
  577. self.showBatchWindow(type: .watermark, files: urls)
  578. }
  579. }
  580. func fastTool_Background() { // 背景
  581. let openPanel = NSOpenPanel()
  582. openPanel.allowedFileTypes = ["pdf","PDF"]
  583. //MARK: 允许多选还是单选,如果是付费用户允许多选
  584. openPanel.allowsMultipleSelection = false
  585. openPanel.beginSheetModal(for: NSWindow.currentWindow()) { [self] (result) in
  586. if result == NSApplication.ModalResponse.OK {
  587. quickBackgroudMark(urls: openPanel.urls)
  588. }
  589. }
  590. }
  591. func quickBackgroudMark(urls: Array<URL>) {
  592. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
  593. self.showBatchWindow(type: .background, files: urls)
  594. }
  595. }
  596. //MARK: 打印
  597. func fastTool_Print() {
  598. let openPanel = NSOpenPanel()
  599. openPanel.allowedFileTypes = ["pdf","PDF"]
  600. openPanel.allowsMultipleSelection = false
  601. openPanel.beginSheetModal(for: NSWindow.currentWindow()) { [self] (result) in
  602. if result == NSApplication.ModalResponse.OK {
  603. if let url = openPanel.url {
  604. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
  605. self.showPrintWindowWithURL(url)
  606. }
  607. }
  608. }
  609. }
  610. }
  611. func showPrintWindowWithURL(_ url: URL) {
  612. if let cPDFDocument = CPDFDocument(url: url) {
  613. KMPrintWindowController.openDocument(inputDocument: cPDFDocument, inputPageRange: KMPrintPageRange(type: .allPage, selectPages: []))
  614. }
  615. }
  616. func fastTool_Insert() { // 插入
  617. let openPanel = NSOpenPanel()
  618. openPanel.prompt = KMLocalizedString("Insert", comment: "")
  619. openPanel.allowsMultipleSelection = false
  620. openPanel.allowedFileTypes = ["pdf"]
  621. openPanel.beginSheetModal(for: NSApp.mainWindow!) { result in
  622. if result == .OK {
  623. let windowC = KMPDFInsertWindowController(fileURL: openPanel.url!)
  624. windowC.callback = { [weak self] idx, params in
  625. if params.count >= 4 {
  626. if let doc = params.first as? CPDFDocument {
  627. self?.savePDFDocument(doc, password: params[1] as? String ?? "")
  628. }
  629. }
  630. windowC.own_closeEndSheet()
  631. }
  632. windowC.own_beginSheetModal(for: self.view.window) { result in
  633. }
  634. }
  635. }
  636. }
  637. func savePDFDocument(_ pdf: CPDFDocument, password: String) -> Void {
  638. DispatchQueue.global(qos: .`default`).async {
  639. var isSuccessfully = false
  640. if pdf.isEncrypted {
  641. let dic = [
  642. CPDFDocumentWriteOption.userPasswordOption : password,
  643. CPDFDocumentWriteOption.ownerPasswordOption : password
  644. ]
  645. isSuccessfully = pdf.write(to: pdf.documentURL, withOptions: dic)
  646. } else {
  647. isSuccessfully = pdf.write(to: pdf.documentURL)
  648. }
  649. if !isSuccessfully {
  650. if let data = pdf.dataRepresentation() {
  651. isSuccessfully = NSData(data: data).write(to: pdf.documentURL, atomically: true)
  652. }
  653. }
  654. DispatchQueue.main.sync {
  655. if isSuccessfully {
  656. let workspace = NSWorkspace.shared
  657. let url = URL(fileURLWithPath: pdf.documentURL?.path ?? "")
  658. workspace.activateFileViewerSelecting([url])
  659. } else {
  660. let alert = NSAlert()
  661. alert.alertStyle = .critical
  662. alert.messageText = KMLocalizedString("Failed to insert page(s)!", comment: "")
  663. alert.runModal()
  664. }
  665. }
  666. }
  667. }
  668. func fastTool_Extract() { // 提取
  669. let openPanel = NSOpenPanel()
  670. openPanel.prompt = "提取"
  671. openPanel.allowsMultipleSelection = false
  672. openPanel.allowedFileTypes = ["pdf"]
  673. openPanel.beginSheetModal(for: NSApp.mainWindow!) { result in
  674. if result == .OK {
  675. DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
  676. if self.extrackWindowController == nil {
  677. self.extrackWindowController = KMExtractWindowController(windowNibName: "KMExtractWindowController")
  678. }
  679. self.extrackWindowController?.fileURL = openPanel.url
  680. self.extrackWindowController?.own_beginSheetModal(for: self.view.window, completionHandler: { result in
  681. })
  682. }
  683. }
  684. }
  685. }
  686. func extractPageAction(_ pdfDocument: CPDFDocument, _ pages: [CPDFPage], _ oneDocumentPerPage: Bool, _ isDeletePage: Bool) -> Void {
  687. if pages.count < 1 {
  688. let alert = NSAlert()
  689. alert.alertStyle = .critical
  690. alert.messageText = KMLocalizedString("Please select two or more pages first to organize.", comment: "")
  691. alert.runModal()
  692. return
  693. }
  694. if !oneDocumentPerPage {
  695. let fileName = pdfDocument.getFileNameAccordingSelctPages(pages)
  696. let outputSavePanel = NSSavePanel()
  697. outputSavePanel.allowedFileTypes = ["pdf"]
  698. outputSavePanel.nameFieldStringValue = fileName
  699. outputSavePanel.beginSheetModal(for: self.view.window!) { result in
  700. if result == .OK {
  701. DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
  702. let saveFilePath = outputSavePanel.url?.path
  703. DispatchQueue.global().async {
  704. let pdf = CPDFDocument.init()
  705. let success = (pdf!.extractAsOneDocument(withPages: pages, savePath: saveFilePath)) as Bool
  706. DispatchQueue.main.async {
  707. if success {
  708. let workspace = NSWorkspace.shared
  709. let url = URL(fileURLWithPath: saveFilePath!)
  710. workspace.activateFileViewerSelecting([url])
  711. if isDeletePage {
  712. for page in pages {
  713. let indexPage = pdfDocument.index(for: page)
  714. pdfDocument.removePage(at: indexPage)
  715. }
  716. }
  717. }
  718. }
  719. }
  720. }
  721. }
  722. }
  723. } else {
  724. let panel = NSOpenPanel()
  725. panel.canChooseFiles = false
  726. panel.canChooseDirectories = true
  727. panel.canCreateDirectories = true
  728. panel.allowsMultipleSelection = false
  729. panel.beginSheetModal(for: self.view.window!) { result in
  730. if result == .OK {
  731. DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
  732. let outputURL = panel.url
  733. DispatchQueue.global().async {
  734. let folderName = String(pdfDocument.documentURL!.lastPathComponent.split(separator: ".")[0]) + "_extract"
  735. var filePath = URL(fileURLWithPath: outputURL!.path).appendingPathComponent(folderName).path
  736. var i = 1
  737. let testFilePath = filePath
  738. while FileManager.default.fileExists(atPath: filePath) {
  739. filePath = testFilePath + "\(i)"
  740. i += 1
  741. }
  742. try? FileManager.default.createDirectory(atPath: filePath, withIntermediateDirectories: false, attributes: nil)
  743. let successArray = pdfDocument.extractPerPageDocument(withPages: pages, folerPath: filePath)
  744. DispatchQueue.main.async {
  745. if successArray!.count > 0 {
  746. NSWorkspace.shared.activateFileViewerSelecting(successArray!)
  747. if !isDeletePage {
  748. for page in pages {
  749. let indexPage = pdfDocument.index(for: page)
  750. pdfDocument.removePage(at: indexPage)
  751. }
  752. }
  753. }
  754. }
  755. }
  756. }
  757. }
  758. }
  759. }
  760. }
  761. //MARK: Batch
  762. func showBatchWindow(type: KMBatchCollectionViewType, subType: Int = 0, files: [URL]?) {
  763. let batchWindowController = KMBatchWindowController.manager
  764. batchWindowController.window?.makeKeyAndOrderFront("")
  765. // var datas: [KMBatchProcessingTableViewModel] = []
  766. // for file in files! {
  767. // let data = KMBatchProcessingTableViewModel.initWithFilePath(url: file)
  768. // datas.append(data)
  769. // }
  770. batchWindowController.inputData = files ?? []
  771. batchWindowController.type = type
  772. batchWindowController.inputSubType = subType
  773. }
  774. }
  775. extension KMNHomeViewController {
  776. //文件对比
  777. func openContentCompareVC(with pdfCompareContent: CPDFCompareContent?, results: [CPDFCompareResults], oldDocument: CPDFDocument, document: CPDFDocument) {
  778. let compareContentController = KMCompareContentWindowController(document: document, oldDocument: oldDocument, results: results)
  779. self.currentController = compareContentController
  780. compareContentController.saveHandle = { [unowned self] view in
  781. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.25) { [unowned self] in
  782. let saveController = KMCompareSaveWindow(windowNibName: "KMCompareSaveWindow")
  783. self.currentWindowController = saveController
  784. let window = NSWindow.currentWindow()
  785. window.beginSheet(saveController.window!)
  786. saveController.cancelHandle = { [weak self] controller in
  787. window.endSheet(saveController.window!)
  788. self?.currentWindowController = nil
  789. }
  790. saveController.saveHandle = { [unowned self] controller, saveType in
  791. let folderPath = controller.fileSaveFolderPath
  792. if folderPath != nil {
  793. if !FileManager.default.fileExists(atPath: folderPath) {
  794. try? FileManager.default.createDirectory(atPath: folderPath, withIntermediateDirectories: true, attributes: nil)
  795. }
  796. var savePath: String
  797. #if VERSION_DMG
  798. #else
  799. let url = URL(fileURLWithPath: folderPath)
  800. let fileAccess = AppSandboxFileAccess()
  801. fileAccess?.persistPermissionURL(url)
  802. if let bookmarkData = try?url.bookmarkData(options: [.withSecurityScope]) {
  803. fileAccess?.bookmarkPersistanceDelegate.setBookmarkData(bookmarkData, for: url)
  804. let urlString = url.path
  805. let _url = URL(fileURLWithPath: urlString)
  806. fileAccess?.bookmarkPersistanceDelegate.setBookmarkData(bookmarkData, for: _url)
  807. }
  808. #endif
  809. switch saveType {
  810. case 0:
  811. let filePath = oldDocument.documentURL.path
  812. let fileName = filePath.deletingPathExtension.lastPathComponent
  813. savePath = "\(folderPath)/\(fileName)_compare\(filePath.extension)"
  814. savePath = self.getValidFilePath(savePath)
  815. oldDocument.write(to: URL(fileURLWithPath: savePath))
  816. NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: savePath)])
  817. case 1:
  818. let filePath = document.documentURL.path
  819. let fileName = filePath.deletingPathExtension.lastPathComponent
  820. savePath = "\(folderPath)/\(fileName)_compare\(filePath.extension)"
  821. savePath = self.getValidFilePath(savePath)
  822. document.write(to: URL(fileURLWithPath: savePath))
  823. NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: savePath)])
  824. case 2:
  825. let filePath = oldDocument.documentURL.path
  826. let fileName = filePath.deletingPathExtension.lastPathComponent
  827. savePath = "\(folderPath)/MergedCompareFile\(filePath.extension)"
  828. savePath = self.getValidFilePath(savePath)
  829. pdfCompareContent!.saveAsComparisonDocument(withFilePath: savePath)
  830. NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: savePath)])
  831. default:
  832. break
  833. }
  834. }
  835. window.endSheet(saveController.window!)
  836. self.currentWindowController = nil
  837. }
  838. }
  839. }
  840. compareContentController.closeHandle = { [weak self] controller in
  841. self?.view.window?.endSheet(controller.window!)
  842. self?.currentController = nil
  843. }
  844. self.view.window?.beginSheet(compareContentController.window!)
  845. }
  846. func getValidFilePath(_ oldPath: String) -> String {
  847. let fileManager = FileManager.default
  848. do {
  849. let fileAttributes = try fileManager.attributesOfItem(atPath: oldPath)
  850. guard let fileType = fileAttributes[FileAttributeKey.type] as? String else {
  851. return oldPath
  852. }
  853. var i = 1
  854. var newPath = oldPath
  855. while fileManager.fileExists(atPath: newPath) {
  856. if fileType == FileAttributeType.typeDirectory.rawValue {
  857. newPath = oldPath + "(\(i))"
  858. } else {
  859. let fileExtension = (oldPath as NSString).pathExtension
  860. newPath = ((oldPath as NSString).deletingPathExtension as NSString).appendingFormat("(\(i)).\(fileExtension)" as NSString) as String
  861. }
  862. i += 1
  863. }
  864. return newPath
  865. } catch {
  866. print("Error getting file attributes: \(error)")
  867. return oldPath
  868. }
  869. }
  870. func openCoveringCompareVC(with pdfDocument: CPDFDocument) {
  871. let controller = KMCompareCoveringWindowController(document: pdfDocument)
  872. self.currentController = controller
  873. controller.closeHandle = { [weak self] controller in
  874. self?.view.window?.endSheet(controller.window!)
  875. self?.currentController = nil
  876. }
  877. controller.saveHandle = { [weak self] controller in
  878. let savePanel = NSSavePanel()
  879. savePanel.nameFieldStringValue = "untitled"
  880. savePanel.allowedFileTypes = ["pdf"]
  881. savePanel.beginSheetModal(for: NSWindow.currentWindow()) { result in
  882. if result == .OK {
  883. pdfDocument.write(to: savePanel.url!)
  884. NSWorkspace.shared.activateFileViewerSelecting([savePanel.url!])
  885. }
  886. }
  887. }
  888. self.view.window?.beginSheet(controller.window!)
  889. }
  890. }