KMNHomeViewController.swift 42 KB

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