KMNHomeViewController.swift 42 KB

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