KMBatchOperateImageToPDFViewController.swift 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. //
  2. // KMBatchOperateImageToPDFViewController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by liujiajie on 2023/12/5.
  6. //
  7. import Cocoa
  8. class KMBatchOperateImageToPDFViewController: KMBatchOperateBaseViewController, KMImageToPDFMethodDelegate, NSPopoverDelegate{
  9. @IBOutlet var outputTypeLabel: NSTextField!
  10. @IBOutlet var createNewPDFBtn: NSButton!
  11. @IBOutlet var btnMerge: NSButton!
  12. @IBOutlet var appendPDFBtn: NSButton!
  13. @IBOutlet var appendTextField: NSTextField!
  14. @IBOutlet var appendOtherPDFBtn: NSButton!
  15. @IBOutlet var appendBackView: NSView!
  16. @IBOutlet var ocrLabel: NSTextField!
  17. @IBOutlet var ocrSelectBtn: NSButton!
  18. @IBOutlet var languaeBox: NSBox!
  19. @IBOutlet var languageButton: NSButton!
  20. @IBOutlet var saveAsButton: NSButton!
  21. @IBOutlet var planButton: NSButton!
  22. @IBOutlet var selectLanguageLabel: NSTextField!
  23. @IBOutlet var planBox: NSBox!
  24. @IBOutlet var actionButton: NSButton!
  25. var password: String = ""
  26. lazy var method: KMImageToPDFMethod = {
  27. let method = KMImageToPDFMethod()
  28. method.imageTopdfDelegate = self
  29. return method
  30. }()
  31. override var interfaceStatus: KMBatchOperateInterfaceStatus?{
  32. set{
  33. super.interfaceStatus = newValue
  34. if newValue == .PrepareProcess {
  35. DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
  36. let files = NSMutableArray()
  37. for url in self.successFilePathURLArray! {
  38. if FileManager.default.fileExists(atPath: url.path) {
  39. files.add(url)
  40. }
  41. }
  42. if files.count > 0 {
  43. let workspace = NSWorkspace.shared
  44. workspace.activateFileViewerSelecting(files as! [URL])
  45. }
  46. }
  47. self._updateActionButtonEnable(true)
  48. } else {
  49. self._updateActionButtonEnable(false)
  50. }
  51. }
  52. get{
  53. return super.interfaceStatus
  54. }
  55. }
  56. private func _updateActionButtonEnable(_ enabled: Bool) {
  57. if enabled {
  58. self.actionButton.tag = 1
  59. self.actionButton.title = NSLocalizedString("Save as PDF", comment: "")
  60. self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
  61. self.actionButton.isEnabled = true
  62. self.actionButton.layer?.backgroundColor = KMAppearance.Interactive.m0Color().cgColor
  63. } else {
  64. self.actionButton.tag = 0
  65. self.actionButton.layer?.backgroundColor = KMAppearance.Interactive.m0Color().cgColor
  66. self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
  67. self.actionButton.isEnabled = false
  68. }
  69. }
  70. deinit {
  71. NotificationCenter.default.removeObserver(self)
  72. DistributedNotificationCenter.default().removeObserver(self)
  73. }
  74. override func viewDidLoad() {
  75. super.viewDidLoad()
  76. self.localizedLanguage()
  77. self.configuUI()
  78. NotificationCenter.default.addObserver(self, selector: #selector(OCRSelectedLanguagesChangeNotification(notification:)), name: NSNotification.Name("KMOCRSelectedLanguagesChangeNotification"), object: nil)
  79. NotificationCenter.default.addObserver(self, selector: #selector(OCRSelectedPlanChangeNotification(notification:)), name: NSNotification.Name("KMOCRSelectedPlanChangeNotification"), object: nil)
  80. // NotificationCenter.default.addObserver(self, selector: #selector(themeChanged(notification:)), name: NSNotification.Name("AppleInterfaceThemeChangedNotification"), object: nil)
  81. DistributedNotificationCenter.default().addObserver(self, selector: #selector(themeChanged(notification:)), name: NSNotification.Name("AppleInterfaceThemeChangedNotification"), object: nil)
  82. NotificationCenter.default.addObserver(self, selector: #selector(batchFilesCountNotification(notification:)), name: NSNotification.Name("KMBatchFilesCountNotification"), object: nil)
  83. }
  84. func localizedLanguage() {
  85. self.outputTypeLabel.stringValue = KMLocalizedString("Output",nil)
  86. self.btnMerge.title = KMLocalizedString("Merge All", nil)
  87. self.createNewPDFBtn.title = KMLocalizedString("New PDF Document", nil)
  88. self.appendPDFBtn.title = KMLocalizedString("Append To Existing File", nil)
  89. self.appendTextField.placeholderString = KMLocalizedString("Select a File", nil)
  90. self.selectLanguageLabel.stringValue = KMLocalizedString("Select OCR Language:",nil)
  91. self.ocrSelectBtn.title = KMLocalizedString("OCR Plan",nil)
  92. self.updateLanguageButton((KMGOCRManager.default().selectedLanguages?.value(forKeyPath: KMGOCRLanguageStringKey) as? [String]))
  93. self.actionButton.title = KMLocalizedString("Save as PDF", nil)
  94. self.saveAsButton.title = KMLocalizedString("Save as TXT", nil)
  95. self.OCRSelectedPlanChangeAction()
  96. }
  97. func configuUI() {
  98. self.view.wantsLayer = true
  99. appendOtherPDFBtn.wantsLayer = true
  100. appendBackView.wantsLayer = true
  101. appendBackView.layer?.borderWidth = 0.5
  102. self.actionButton.wantsLayer = true
  103. self.actionButton.layer?.backgroundColor = KMAppearance.Interactive.m0Color().cgColor
  104. self.appendOtherPDFBtn.layer?.backgroundColor = KMAppearance.Interactive.s0Color().withAlphaComponent(0.4).cgColor
  105. self.actionButton.setTitleColor(KMAppearance.Layout.w0Color())
  106. self.actionButton.layer?.cornerRadius = 1.0
  107. self.createNewPDFBtn.setTitleColor(KMAppearance.Layout.h0Color())
  108. self.btnMerge.setTitleColor(KMAppearance.Layout.h0Color())
  109. self.appendPDFBtn.setTitleColor(KMAppearance.Layout.h0Color())
  110. self.ocrSelectBtn.setTitleColor(KMAppearance.Layout.h0Color())
  111. self.saveAsButton.setTitleColor(KMAppearance.Layout.h0Color())
  112. self.selectLanguageLabel.textColor = KMAppearance.Layout.h0Color()
  113. self.languageButton.isEnabled = false
  114. self.planButton.isEnabled = false
  115. self.saveAsButton.isEnabled = false
  116. appendTextField.backgroundColor = KMAppearance.Layout.l1Color()
  117. planButton.wantsLayer = true
  118. appendTextField.wantsLayer = true
  119. planButton.wantsLayer = true
  120. appendTextField.layer?.cornerRadius = 1.0
  121. languageButton.layer?.backgroundColor = NSColor.clear.cgColor
  122. languaeBox.borderColor = KMAppearance.Interactive.s0Color()
  123. planBox.borderColor = KMAppearance.Interactive.s0Color()
  124. languaeBox.fillColor = KMAppearance.Layout.l1Color()
  125. planBox.fillColor = KMAppearance.Layout.l1Color()
  126. self.updateViewColor()
  127. }
  128. func updateViewColor() {
  129. if KMAppearance.isDarkMode() {
  130. self.view.layer?.backgroundColor = NSColor(red: 0.055, green: 0.067, blue: 0.078, alpha: 1).cgColor
  131. appendBackView.layer?.borderColor = NSColor(red: 86/255.0, green: 88/255.0, blue: 90/255.0, alpha: 1).cgColor
  132. appendBackView.layer?.backgroundColor = NSColor(red: 57/255.0, green: 60/255.0, blue: 62/255.0, alpha: 1).cgColor
  133. } else {
  134. self.view.layer?.backgroundColor = NSColor(red: 0.922, green: 0.925, blue: 0.941, alpha: 1).cgColor
  135. appendBackView.layer?.borderColor = NSColor(red: 218/255.0, green: 219/255.0, blue: 222/255.0, alpha: 1).cgColor
  136. appendBackView.layer?.backgroundColor = NSColor.white.cgColor;
  137. }
  138. }
  139. func updateLanguageButton(_ languages: [String]?) {
  140. if languages?.count ?? 0 < 1 {
  141. self.languageButton.title = " " + KMLocalizedString("Auto Detection", nil)
  142. return
  143. }
  144. var languageName: String = ""
  145. if languages?.count ?? 0 > 0 {
  146. for i in 0..<(languages?.count ?? 0) {
  147. let language = languages?[i]
  148. if i == 0 {
  149. languageName = language ?? ""
  150. } else {
  151. languageName = languageName.appendingFormat(",%@", language ?? "")
  152. }
  153. }
  154. } else {
  155. languageName = ""
  156. }
  157. self.languageButton.title = " " + languageName
  158. }
  159. func converArrType(arr: Array<KMBatchOperateFile>, keyString: String) -> [String] {
  160. let newArr = NSMutableArray()
  161. for item in arr {
  162. newArr.add(item.filePath)
  163. }
  164. return newArr as! [String]
  165. }
  166. func isConnectionAvailable() -> Bool {
  167. // var isExistenceNetwork = true
  168. // let reach = Reachability(hostname: "www.apple.com")
  169. // let status: NetworkStatus = NetworkStatus(rawValue: (reach?.currentReachabilityStatus())!.rawValue)
  170. // switch status.rawValue {
  171. // case 0:
  172. // isExistenceNetwork = false
  173. // case 1:
  174. // isExistenceNetwork = true
  175. // case 2:
  176. // isExistenceNetwork = true
  177. // default:
  178. // break
  179. // }
  180. if Reachability.forInternetConnection().currentReachabilityStatus().rawValue == 0 {
  181. return false
  182. }
  183. return true
  184. }
  185. func beginImageToPDF() {
  186. if self.files?.count ?? 0 < 1 {
  187. return
  188. }
  189. let photoArray = converArrType(arr: self.files!, keyString: "")
  190. var path: String = ""
  191. var isMerge = false
  192. var isCreatNewPDF = false
  193. var isOCR = false
  194. if self.ocrSelectBtn.state == .on {
  195. isOCR = true
  196. }
  197. var isSaveAs = false
  198. if self.saveAsButton.state == .on {
  199. isSaveAs = true
  200. }
  201. let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
  202. if isOCR && !self.isConnectionAvailable() && plan == 0 {
  203. let alert = NSAlert()
  204. alert.alertStyle = .critical
  205. alert.messageText = NSLocalizedString("Connection Error", comment: "")
  206. alert.informativeText = NSLocalizedString("Please make sure your internet connection is available.", comment: "")
  207. alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  208. if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) {
  209. alert.beginSheetModal(for: self.view.window!, completionHandler: nil)
  210. } else {
  211. alert.runModal()
  212. }
  213. return
  214. }
  215. if self.createNewPDFBtn.state == .on {
  216. if (self.choosePath.count < 1) {
  217. let alert = NSAlert()
  218. alert.alertStyle = .critical
  219. alert.messageText = String(format: NSLocalizedString("Output Folder cannot be empty.", comment: ""))
  220. alert.runModal()
  221. return
  222. }
  223. path = self.choosePath
  224. if self.btnMerge.state == .on {
  225. isMerge = true
  226. }
  227. isCreatNewPDF = true
  228. } else {
  229. let appenString = self.appendTextField.stringValue
  230. if appenString.isEmpty {
  231. let alert = NSAlert()
  232. alert.alertStyle = .critical
  233. alert.messageText = String(format: NSLocalizedString("Select a File", comment: ""))
  234. alert.runModal()
  235. return
  236. }
  237. path = self.appendTextField.stringValue
  238. isMerge = true
  239. isCreatNewPDF = false
  240. }
  241. self.languageButton.isEnabled = false
  242. self.planButton.isEnabled = false
  243. self.method.password = self.password
  244. self.interfaceStatus = .Processing
  245. self.method.saveAsTestPath = self.choosePath
  246. self.method.exportPDFFile(fileArray: photoArray, savePath: path, isOCR: isOCR, isCreatPDF: isCreatNewPDF, isMerge: isMerge, isSaveAsText: isSaveAs) { [weak self] savePath, errorArr, errorOCRArray in
  247. self?.languageButton.isEnabled = true
  248. self?.planButton.isEnabled = true
  249. self?.interfaceStatus = .PrepareProcess
  250. if errorArr.count > 0 {
  251. let dict: [String: Any] = ["isMerge": false, "isSuccess": false]
  252. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "KMBatchOperateImageToPDFSuccessNotification"), object: self, userInfo: dict)
  253. let alert = NSAlert()
  254. alert.messageText = NSLocalizedString("Conversion Failed", comment: "")
  255. alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  256. alert.informativeText = "\(errorArr)"
  257. alert.alertStyle = .informational
  258. alert.runModal()
  259. } else {
  260. if errorOCRArray.count > 0 {
  261. var contextString = NSLocalizedString("Some problems occurred during the last operation:", comment: "")
  262. for filePath in errorOCRArray {
  263. contextString += "\n" + (filePath as AnyObject).lastPathComponent
  264. }
  265. let alert = NSAlert()
  266. alert.messageText = NSLocalizedString("Converted Successfully", comment: "")
  267. alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  268. alert.informativeText = contextString
  269. alert.alertStyle = .informational
  270. let response = alert.runModal()
  271. if response == .OK {
  272. self?.viewFileAtFinder(fileName: savePath)
  273. }
  274. } else {
  275. self?.viewFileAtFinder(fileName: savePath)
  276. }
  277. }
  278. }
  279. }
  280. func viewFileAtFinder(fileName: String) {
  281. let dict = ["isMerge": true, "isSuccess": true]
  282. NotificationCenter.default.post(name: Notification.Name("KMBatchOperateImageToPDFSuccessNotification"), object: self, userInfo: dict)
  283. let workspace = NSWorkspace.shared
  284. let url = URL(fileURLWithPath: fileName)
  285. workspace.activateFileViewerSelecting([url])
  286. }
  287. //MARK: Notification
  288. @objc func OCRSelectedLanguagesChangeNotification(notification: Notification) {
  289. let selectedLanguages = notification.object/* as? [KMBatchOperateFile]*/
  290. self.updateLanguageButton(selectedLanguages as? [String])
  291. }
  292. @objc func OCRSelectedPlanChangeNotification(notification: Notification) {
  293. self.OCRSelectedPlanChangeAction()
  294. }
  295. @objc func themeChanged(notification: Notification) {
  296. DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
  297. self.updateViewColor()
  298. }
  299. }
  300. func OCRSelectedPlanChangeAction() {
  301. let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
  302. if plan == 0 {
  303. self.planButton.title = " " + KMLocalizedString("Plan 1 (Online)", nil)
  304. } else {
  305. self.planButton.title = " " + KMLocalizedString("Plan 2 (Offline)", nil)
  306. }
  307. KMGOCRManager.default().selectedLanguages = NSMutableArray()
  308. self.updateLanguageButton(KMGOCRManager.default().selectedLanguages?.value(forKeyPath: KMGOCRLanguageStringKey) as? [String])
  309. }
  310. @objc func batchFilesCountNotification(notification: Notification) {
  311. let files: Array? = notification.object as? [KMBatchOperateFile]
  312. self.files? = files ?? []
  313. let cnt = self.files?.count ?? 0
  314. if cnt > 0 {
  315. self._updateActionButtonEnable(true)
  316. } else {
  317. self._updateActionButtonEnable(false)
  318. }
  319. }
  320. @IBAction func buttonClicked_CreateNewPDF(_ sender: NSButton) {
  321. if (sender.state == .on) {
  322. self.btnMerge.isEnabled = true
  323. self.appendPDFBtn.state = .off
  324. self.appendOtherPDFBtn.isEnabled = false
  325. }
  326. }
  327. @IBAction func buttonClicked_AppendOtherPDF(_ sender: NSButton) {
  328. if (sender.state == .on) {
  329. self.createNewPDFBtn.state = .off
  330. self.btnMerge.isEnabled = false
  331. self.appendOtherPDFBtn.isEnabled = true
  332. }
  333. }
  334. @IBAction func buttonClicked_OCRSelect(_ sender: NSButton) {
  335. //MARK: 判断是否付费用户
  336. if IAPProductsManager.default().isAvailableAllFunction() == false {
  337. KMPurchaseCompareWindowController.sharedInstance().showWindow(nil)
  338. self.ocrSelectBtn.state = .off
  339. return
  340. }
  341. if (sender.state == .on) {
  342. self.languageButton.isEnabled = true
  343. self.planButton.isEnabled = true
  344. self.saveAsButton.isEnabled = true
  345. } else {
  346. self.languageButton.isEnabled = false
  347. self.planButton.isEnabled = false
  348. self.saveAsButton.isEnabled = false
  349. }
  350. }
  351. @IBAction func buttonClicked_ChooseLanguage(_ sender: NSButton) {
  352. let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
  353. if plan == 0 {
  354. KMGOCRManager.default().ocrType = .google
  355. } else {
  356. KMGOCRManager.default().ocrType = .apple
  357. }
  358. let popover = NSPopover()
  359. popover.delegate = self
  360. popover.contentViewController = KMLanguageViewController(nibName: "KMLanguageViewController", bundle: Bundle.main)
  361. popover.animates = true
  362. popover.behavior = .transient
  363. popover.show(relativeTo: sender.bounds, of: sender as NSView, preferredEdge: .minX)
  364. }
  365. @IBAction func buttonClicked_ChoosePlan(_ sender: NSButton) {
  366. let popover = NSPopover()
  367. popover.delegate = self
  368. popover.contentViewController = KMPlanViewController(nibName: "KMPlanViewController", bundle: Bundle.main)
  369. popover.animates = true
  370. popover.behavior = .transient
  371. popover.show(relativeTo: sender.bounds, of: sender as NSView, preferredEdge: .minX)
  372. }
  373. @IBAction func buttonClicked_ImageToPDF(_ sender: NSButton) {
  374. //MARK: 判断是否付费用户,展示iap界面
  375. if self.files?.count ?? 0 < 1 {
  376. return
  377. }
  378. if IAPProductsManager.default().isAvailableAllFunction() == false && self.files?.count ?? 0 > 1{
  379. KMPurchaseCompareWindowController.sharedInstance().showWindow(nil)
  380. return
  381. }
  382. if sender.tag == 1 {
  383. self.choosePath = ""
  384. var hasTask = false
  385. for i in 0..<(self.files?.count ?? 0) {
  386. let file = self.files?[i]
  387. file?.currentOperateInfo?.resetState()
  388. if file?.fileType == .Image {
  389. hasTask = true
  390. }
  391. }
  392. if !hasTask {
  393. NSSound.beep()
  394. return
  395. }
  396. var isOCR = false
  397. if self.ocrSelectBtn.state == .on {
  398. isOCR = true
  399. }
  400. var isSaveAs = false
  401. if self.saveAsButton.state == .on {
  402. isSaveAs = true
  403. }
  404. let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
  405. if isOCR && !isConnectionAvailable() && plan == 0 {
  406. let alert = NSAlert()
  407. alert.alertStyle = .critical
  408. alert.messageText = NSLocalizedString("Connection Error", comment: "")
  409. alert.informativeText = NSLocalizedString("Please make sure your internet connection is available.", comment: "")
  410. alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  411. if let window = self.view.window {
  412. alert.beginSheetModal(for: window, completionHandler: nil)
  413. } else {
  414. alert.runModal()
  415. }
  416. return
  417. }
  418. if self.createNewPDFBtn.state == .off {
  419. let appenString = self.appendTextField.stringValue
  420. if appenString.isEmpty {
  421. let alert = NSAlert()
  422. alert.alertStyle = .critical
  423. alert.messageText = NSLocalizedString("Select a File", comment: "")
  424. alert.runModal()
  425. return
  426. }
  427. }
  428. let openPanel = NSOpenPanel()
  429. openPanel.canChooseFiles = false
  430. openPanel.canChooseDirectories = true
  431. openPanel.canCreateDirectories = true
  432. openPanel.beginSheetModal(for: self.view.window!) { (result) in
  433. if result == .OK {
  434. for fileURL in openPanel.urls {
  435. self.choosePath = fileURL.path
  436. self.beginImageToPDF()
  437. }
  438. }
  439. }
  440. } else { // Do something else }
  441. }
  442. }
  443. @IBAction func buttonItemClicked_AppendOtherPDF(_ sender: NSButton) {
  444. let openPanel = NSOpenPanel()
  445. openPanel.allowedFileTypes = ["pdf"]
  446. openPanel.canChooseDirectories = false
  447. openPanel.allowsMultipleSelection = false
  448. openPanel.beginSheetModal(for: self.view.window!) { (result) in
  449. if result == .OK {
  450. guard let url = openPanel.url else { return }
  451. guard let document = PDFDocument(url: url) else {
  452. let alert = NSAlert()
  453. alert.alertStyle = .critical
  454. alert.messageText = NSLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", comment: "")
  455. alert.runModal()
  456. return
  457. }
  458. if !document.allowsCopying || !document.allowsPrinting {
  459. let alert = NSAlert()
  460. alert.alertStyle = .critical
  461. alert.messageText = NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "")
  462. alert.runModal()
  463. return
  464. }
  465. if document.isLocked {
  466. KMBaseWindowController.checkPassword(url: url, type: .owner) { [weak self] success, resultPassword in
  467. if success {
  468. self?.password = resultPassword
  469. self?.appendTextField.stringValue = url.path
  470. }
  471. }
  472. } else {
  473. self.appendTextField.stringValue = url.path
  474. }
  475. }
  476. }
  477. }
  478. @IBAction func buttonClicked_Help(_ sender: NSButton) {
  479. let helpController = NSViewController()
  480. let textView = NSTextView(frame: NSRect(x: 0, y: 0, width: 300.0, height: 100.0))
  481. textView.backgroundColor = NSColor.clear
  482. textView.isEditable = false
  483. textView.layer?.cornerRadius = 6
  484. let tStrAuto = NSLocalizedString("Choose automatic language detection for better OCR results.", comment: "")
  485. let tStrVPN = NSLocalizedString("The OCR service works via an internet connection. We would suggest you to perform OCR using a VPN connection while the service is limited.", comment: "")
  486. let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
  487. if plan == 0 {
  488. textView.string = "\(tStrAuto)\n\n\(tStrVPN)"
  489. } else {
  490. textView.frame = NSRect(x: 0, y: 0, width: 300.0, height: 40.0)
  491. textView.string = tStrAuto
  492. }
  493. helpController.view = textView
  494. let popover = NSPopover()
  495. popover.delegate = self
  496. popover.contentViewController = helpController
  497. popover.animates = true
  498. popover.behavior = .transient
  499. popover.show(relativeTo: sender.bounds, of: sender as NSView, preferredEdge: .minY)
  500. }
  501. //MARK: KMImageToPDFMethodDelegate
  502. func imageToPDFMethod(_ method: KMImageToPDFMethod, progress: Float) {
  503. }
  504. }