KMBatchOperateImageToPDFViewController.swift 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. //
  2. // KMBatchOperateImageToPDFViewController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by liujiajie on 2023/12/5.
  6. //
  7. import Cocoa
  8. import KMComponentLibrary
  9. class KMBatchOperateImageToPDFViewController: KMBatchOperateBaseViewController, KMImageToPDFMethodDelegate, NSPopoverDelegate{
  10. @IBOutlet weak var headerBox: NSBox!
  11. @IBOutlet weak var titleLabel: NSTextField!
  12. @IBOutlet weak var headerBottomLine: ComponentDivider!
  13. @IBOutlet var outputTypeLabel: NSTextField!
  14. @IBOutlet var createNewPDFBtn: NSButton!
  15. @IBOutlet var btnMerge: NSButton!
  16. @IBOutlet var appendPDFBtn: NSButton!
  17. @IBOutlet var appendTextField: NSTextField!
  18. @IBOutlet var appendOtherPDFBtn: NSButton!
  19. @IBOutlet var appendBackView: NSView!
  20. @IBOutlet var ocrLabel: NSTextField!
  21. @IBOutlet var ocrSelectBtn: NSButton!
  22. @IBOutlet var languaeBox: NSBox!
  23. @IBOutlet var languageButton: NSButton!
  24. @IBOutlet var saveAsButton: NSButton!
  25. @IBOutlet var planButton: NSButton!
  26. @IBOutlet var selectLanguageLabel: NSTextField!
  27. @IBOutlet var planBox: NSBox!
  28. @IBOutlet var actionButton: NSButton!
  29. @IBOutlet weak var newPDFBox: NSBox!
  30. @IBOutlet weak var mergeAllBox: NSBox!
  31. @IBOutlet weak var appendBox: NSBox!
  32. @IBOutlet weak var appendBackBox: NSBox!
  33. @IBOutlet weak var ocrSelectBox: NSBox!
  34. @IBOutlet weak var languageBox: NSBox!
  35. @IBOutlet weak var ocrPlanBox: NSBox!
  36. @IBOutlet weak var ocrPlan2Box: NSBox!
  37. @IBOutlet weak var hLine: NSView!
  38. @IBOutlet weak var extractTextBox: NSBox!
  39. @IBOutlet weak var bottomBox: NSBox!
  40. @IBOutlet weak var bottomTopLine: ComponentDivider!
  41. @IBOutlet weak var applyButton: ComponentButton!
  42. var password: String = ""
  43. lazy var method: KMImageToPDFMethod = {
  44. let method = KMImageToPDFMethod()
  45. method.imageTopdfDelegate = self
  46. return method
  47. }()
  48. private var createNewPDFRadio_: ComponentRadio = {
  49. let view = ComponentRadio()
  50. view.properties = ComponentCheckBoxProperty(size: .s,
  51. state: .normal,
  52. isDisabled: false,
  53. showhelp: false,
  54. text: NSLocalizedString("New PDF Document", comment: ""),
  55. checkboxType: .normal)
  56. return view
  57. }()
  58. private lazy var mergeAllCheckBox_: ComponentCheckBox = {
  59. let view = ComponentCheckBox()
  60. view.properties = ComponentCheckBoxProperty(size: .s,
  61. state: .normal,
  62. isDisabled: false,
  63. showhelp: false,
  64. text: NSLocalizedString("Merge All", comment: ""),
  65. checkboxType: .normal)
  66. return view
  67. }()
  68. private var appendRadio_: ComponentRadio = {
  69. let view = ComponentRadio()
  70. view.properties = ComponentCheckBoxProperty(size: .s,
  71. state: .normal,
  72. isDisabled: false,
  73. showhelp: false,
  74. text: NSLocalizedString("Append To Existing File", comment: ""),
  75. checkboxType: .normal)
  76. return view
  77. }()
  78. private var appendBackInput: ComponentInputWithAddon = {
  79. let view = ComponentInputWithAddon()
  80. view.properties = ComponentInputWithAddonProperty(size: .s, isDisabled: true, addonType: .button)
  81. return view
  82. }()
  83. private lazy var ocrCheckBox_: ComponentCheckBox = {
  84. let view = ComponentCheckBox()
  85. view.properties = ComponentCheckBoxProperty(size: .s,
  86. state: .normal,
  87. isDisabled: false,
  88. showhelp: false,
  89. text: NSLocalizedString("Recognize text if needed", comment: ""),
  90. checkboxType: .normal)
  91. return view
  92. }()
  93. private lazy var languageView_: ComponentSelect = {
  94. let view = ComponentSelect()
  95. view.properties = ComponentSelectProperties(size: .s,
  96. state: .normal,
  97. isDisabled: false,
  98. isError: false,
  99. leftIcon: false,
  100. placeholder: nil,
  101. errorText: nil,
  102. creatable: false,
  103. text: KMLocalizedString("", comment: ""))
  104. // view.delegate = self
  105. return view
  106. }()
  107. private var ocrPlanRadio_: ComponentRadio = {
  108. let view = ComponentRadio()
  109. view.properties = ComponentCheckBoxProperty(size: .s,
  110. state: .normal,
  111. isDisabled: false,
  112. showhelp: true,
  113. text: KMLocalizedString("OCR Plan 1-Online", comment: ""),
  114. checkboxType: .normal)
  115. return view
  116. }()
  117. private var ocrPlanRadio2_: ComponentRadio = {
  118. let view = ComponentRadio()
  119. view.properties = ComponentCheckBoxProperty(size: .s,
  120. state: .normal,
  121. isDisabled: false,
  122. showhelp: true,
  123. text: KMLocalizedString("OCR Plan 2-Online", comment: ""),
  124. checkboxType: .normal)
  125. return view
  126. }()
  127. private var vLine_: ComponentDivider = {
  128. let view = ComponentDivider()
  129. view.properties = ComponentDividerProperty(type: .horizontal, dash: false)
  130. return view
  131. }()
  132. private lazy var extractTextCheckBox_: ComponentCheckBox = {
  133. let view = ComponentCheckBox()
  134. view.properties = ComponentCheckBoxProperty(size: .s,
  135. state: .normal,
  136. isDisabled: false,
  137. showhelp: false,
  138. text: KMLocalizedString("Extract Text (.txt)", comment: ""),
  139. checkboxType: .normal)
  140. return view
  141. }()
  142. override var interfaceStatus: KMBatchOperateInterfaceStatus?{
  143. set{
  144. super.interfaceStatus = newValue
  145. if newValue == .PrepareProcess {
  146. DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
  147. let files = NSMutableArray()
  148. for url in self.successFilePathURLArray! {
  149. if FileManager.default.fileExists(atPath: url.path) {
  150. files.add(url)
  151. }
  152. }
  153. if files.count > 0 {
  154. let workspace = NSWorkspace.shared
  155. workspace.activateFileViewerSelecting(files as! [URL])
  156. }
  157. }
  158. self._updateActionButtonEnable(true)
  159. } else {
  160. self._updateActionButtonEnable(false)
  161. }
  162. }
  163. get{
  164. return super.interfaceStatus
  165. }
  166. }
  167. private func _updateActionButtonEnable(_ enabled: Bool) {
  168. if enabled {
  169. self.actionButton.tag = 1
  170. applyButton.properties.isDisabled = false
  171. applyButton.reloadData()
  172. } else {
  173. self.actionButton.tag = 0
  174. applyButton.properties.isDisabled = true
  175. applyButton.reloadData()
  176. }
  177. }
  178. deinit {
  179. NotificationCenter.default.removeObserver(self)
  180. DistributedNotificationCenter.default().removeObserver(self)
  181. }
  182. override func viewDidLoad() {
  183. super.viewDidLoad()
  184. headerBox.borderWidth = 0
  185. titleLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-m-bold")
  186. createNewPDFRadio_.properties.checkboxType = .selected
  187. createNewPDFRadio_.reloadData()
  188. ocrLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-medium")
  189. ocrSelectBox.borderWidth = 0
  190. ocrSelectBox.contentView = ocrCheckBox_
  191. ocrCheckBox_.setTarget(self, action: #selector(buttonClicked_OCRSelect))
  192. languageView_.properties.isDisabled = true
  193. languageView_.reloadData()
  194. ocrPlanRadio_.setTarget(self, action: #selector(ocrPlanAction))
  195. ocrPlanRadio_.properties.isDisabled = true
  196. ocrPlanRadio_.reloadData()
  197. ocrPlanRadio2_.setTarget(self, action: #selector(ocrPlanAction))
  198. ocrPlanRadio2_.properties.isDisabled = true
  199. ocrPlanRadio2_.reloadData()
  200. extractTextCheckBox_.properties.isDisabled = true
  201. extractTextCheckBox_.reloadData()
  202. bottomBox.borderWidth = 0
  203. applyButton.properties = ComponentButtonProperty(type: .primary, size: .m, onlyIcon: false, buttonText: KMLocalizedString("Apply"))
  204. self.localizedLanguage()
  205. self.configuUI()
  206. if let cnt = self.files?.count, cnt > 0 {
  207. self._updateActionButtonEnable(true)
  208. } else {
  209. self._updateActionButtonEnable(false)
  210. }
  211. NotificationCenter.default.addObserver(self, selector: #selector(OCRSelectedLanguagesChangeNotification(notification:)), name: NSNotification.Name("KMOCRSelectedLanguagesChangeNotification"), object: nil)
  212. NotificationCenter.default.addObserver(self, selector: #selector(OCRSelectedPlanChangeNotification(notification:)), name: NSNotification.Name("KMOCRSelectedPlanChangeNotification"), object: nil)
  213. // NotificationCenter.default.addObserver(self, selector: #selector(themeChanged(notification:)), name: NSNotification.Name("AppleInterfaceThemeChangedNotification"), object: nil)
  214. DistributedNotificationCenter.default().addObserver(self, selector: #selector(themeChanged(notification:)), name: NSNotification.Name("AppleInterfaceThemeChangedNotification"), object: nil)
  215. NotificationCenter.default.addObserver(self, selector: #selector(batchFilesCountNotification(notification:)), name: NSNotification.Name("KMBatchFilesCountNotification"), object: nil)
  216. }
  217. override func updateUILanguage() {
  218. super.updateUILanguage()
  219. KMMainThreadExecute {
  220. self.titleLabel.stringValue = KMLocalizedString("Image to PDF")
  221. self.ocrLabel.stringValue = KMLocalizedString("Text Recognition Settings")
  222. }
  223. }
  224. override func updateUIThemeColor() {
  225. super.updateUIThemeColor()
  226. KMMainThreadExecute {
  227. let titleColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
  228. self.titleLabel.textColor = titleColor
  229. self.headerBottomLine.properties = ComponentDividerProperty()
  230. self.ocrLabel.textColor = titleColor
  231. self.bottomTopLine.properties = ComponentDividerProperty()
  232. }
  233. }
  234. func localizedLanguage() {
  235. self.outputTypeLabel.stringValue = KMLocalizedString("Output")
  236. self.btnMerge.title = KMLocalizedString("Merge All")
  237. self.createNewPDFBtn.title = KMLocalizedString("New PDF Document")
  238. self.appendPDFBtn.title = KMLocalizedString("Append To Existing File")
  239. self.appendTextField.placeholderString = KMLocalizedString("Select a File")
  240. self.selectLanguageLabel.stringValue = KMLocalizedString("Select OCR Language:")
  241. self.selectLanguageLabel.isHidden = true
  242. self.ocrSelectBtn.title = KMLocalizedString("OCR Plan")
  243. let languages = KMGOCRManager.languages() as NSArray
  244. let strings = languages.value(forKeyPath: KMGOCRLanguageStringKey) as? [String]
  245. var menuItemArr: [ComponentMenuitemProperty] = []
  246. for language in strings ?? [] {
  247. let itemProperty: ComponentMenuitemProperty = ComponentMenuitemProperty(multipleSelect: false,
  248. itemSelected: false,
  249. isDisabled: false,
  250. keyEquivalent: nil,
  251. text: language)
  252. menuItemArr.append(itemProperty)
  253. }
  254. languageView_.updateMenuItemsArr(menuItemArr)
  255. languageView_.selectItemAtIndex(0)
  256. languageView_.properties.creatable = false
  257. languageView_.properties.text = menuItemArr.first?.text
  258. languageView_.reloadData()
  259. self.updateLanguageButton((KMGOCRManager.default().selectedLanguages?.value(forKeyPath: KMGOCRLanguageStringKey) as? [String]))
  260. self.actionButton.title = KMLocalizedString("Save as PDF")
  261. self.saveAsButton.title = KMLocalizedString("Save as TXT")
  262. self.OCRSelectedPlanChangeAction()
  263. }
  264. func configuUI() {
  265. self.view.wantsLayer = true
  266. appendOtherPDFBtn.wantsLayer = true
  267. appendBackView.wantsLayer = true
  268. appendBackView.layer?.borderWidth = 0.5
  269. self.appendOtherPDFBtn.layer?.backgroundColor = KMAppearance.Interactive.s0Color().withAlphaComponent(0.4).cgColor
  270. createNewPDFBtn.setTitleColor(KMAppearance.Layout.h0Color())
  271. newPDFBox.borderWidth = 0
  272. newPDFBox.contentView = createNewPDFRadio_
  273. createNewPDFRadio_.setTarget(self, action: #selector(buttonClicked_CreateNewPDF))
  274. createNewPDFBtn.isHidden = true
  275. self.btnMerge.setTitleColor(KMAppearance.Layout.h0Color())
  276. self.appendPDFBtn.setTitleColor(KMAppearance.Layout.h0Color())
  277. appendBackBox.contentView = appendBackInput
  278. btnMerge.isHidden = true
  279. mergeAllBox.borderWidth = 0
  280. mergeAllBox.contentView = mergeAllCheckBox_
  281. appendPDFBtn.isHidden = true
  282. appendBox.borderWidth = 0
  283. appendBox.contentView = appendRadio_
  284. appendRadio_.setTarget(self, action: #selector(buttonClicked_AppendOtherPDF))
  285. self.ocrSelectBtn.setTitleColor(KMAppearance.Layout.h0Color())
  286. self.saveAsButton.setTitleColor(KMAppearance.Layout.h0Color())
  287. self.selectLanguageLabel.textColor = KMAppearance.Layout.h0Color()
  288. saveAsButton.isHidden = true
  289. ocrSelectBtn.isHidden = true
  290. languageBox.borderWidth = 0
  291. languageBox.contentView = languageView_
  292. ocrPlanBox.borderWidth = 0
  293. ocrPlanBox.contentView = ocrPlanRadio_
  294. ocrPlan2Box.borderWidth = 0
  295. ocrPlan2Box.contentView = ocrPlanRadio2_
  296. hLine.addSubview(vLine_)
  297. vLine_.frame = hLine.bounds
  298. vLine_.autoresizingMask = [.width, .height]
  299. extractTextBox.borderWidth = 0
  300. extractTextBox.contentView = extractTextCheckBox_
  301. appendTextField.backgroundColor = KMAppearance.Layout.l1Color()
  302. appendTextField.wantsLayer = true
  303. appendTextField.layer?.cornerRadius = 1.0
  304. languageButton.layer?.backgroundColor = NSColor.clear.cgColor
  305. languaeBox.borderColor = KMAppearance.Interactive.s0Color()
  306. planBox.borderColor = KMAppearance.Interactive.s0Color()
  307. languaeBox.fillColor = KMAppearance.Layout.l1Color()
  308. planBox.fillColor = KMAppearance.Layout.l1Color()
  309. languaeBox.isHidden = true
  310. self.updateViewColor()
  311. }
  312. func updateViewColor() {
  313. if KMAppearance.isDarkMode() {
  314. self.view.layer?.backgroundColor = NSColor(red: 0.055, green: 0.067, blue: 0.078, alpha: 1).cgColor
  315. appendBackView.layer?.borderColor = NSColor(red: 86/255.0, green: 88/255.0, blue: 90/255.0, alpha: 1).cgColor
  316. appendBackView.layer?.backgroundColor = NSColor(red: 57/255.0, green: 60/255.0, blue: 62/255.0, alpha: 1).cgColor
  317. } else {
  318. self.view.layer?.backgroundColor = NSColor(red: 0.922, green: 0.925, blue: 0.941, alpha: 1).cgColor
  319. appendBackView.layer?.borderColor = NSColor(red: 218/255.0, green: 219/255.0, blue: 222/255.0, alpha: 1).cgColor
  320. appendBackView.layer?.backgroundColor = NSColor.white.cgColor;
  321. }
  322. }
  323. func updateLanguageButton(_ languages: [String]?) {
  324. if languages?.count ?? 0 < 1 {
  325. self.languageButton.title = " " + KMLocalizedString("Auto Detection")
  326. self.languageView_.properties.text = " " + KMLocalizedString("Auto Detection")
  327. self.languageView_.reloadData()
  328. return
  329. }
  330. var languageName: String = ""
  331. if languages?.count ?? 0 > 0 {
  332. for i in 0..<(languages?.count ?? 0) {
  333. let language = languages?[i]
  334. if i == 0 {
  335. languageName = language ?? ""
  336. } else {
  337. languageName = languageName.appendingFormat(",%@", language ?? "")
  338. }
  339. }
  340. } else {
  341. languageName = ""
  342. }
  343. self.languageButton.title = " " + languageName
  344. self.languageView_.properties.text = " " + languageName
  345. self.languageView_.reloadData()
  346. }
  347. func converArrType(arr: Array<KMBatchOperateFile>, keyString: String) -> [String] {
  348. let newArr = NSMutableArray()
  349. for item in arr {
  350. newArr.add(item.filePath)
  351. }
  352. return newArr as! [String]
  353. }
  354. func isConnectionAvailable() -> Bool {
  355. // var isExistenceNetwork = true
  356. // let reach = Reachability(hostname: "www.apple.com")
  357. // let status: NetworkStatus = NetworkStatus(rawValue: (reach?.currentReachabilityStatus())!.rawValue)
  358. // switch status.rawValue {
  359. // case 0:
  360. // isExistenceNetwork = false
  361. // case 1:
  362. // isExistenceNetwork = true
  363. // case 2:
  364. // isExistenceNetwork = true
  365. // default:
  366. // break
  367. // }
  368. if Reachability.forInternetConnection().currentReachabilityStatus().rawValue == 0 {
  369. return false
  370. }
  371. return true
  372. }
  373. func beginImageToPDF() {
  374. if self.files?.count ?? 0 < 1 {
  375. return
  376. }
  377. let photoArray = converArrType(arr: self.files!, keyString: "")
  378. var path: String = ""
  379. var isMerge = false
  380. var isCreatNewPDF = false
  381. var isOCR = false
  382. if ocrCheckBox_.properties.checkboxType == .selected {
  383. isOCR = true
  384. }
  385. var isSaveAs = false
  386. if extractTextCheckBox_.properties.checkboxType == .selected {
  387. isSaveAs = true
  388. }
  389. let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
  390. if isOCR && !self.isConnectionAvailable() && plan == 0 {
  391. let alert = NSAlert()
  392. alert.alertStyle = .critical
  393. alert.messageText = NSLocalizedString("Connection Error", comment: "")
  394. alert.informativeText = NSLocalizedString("Please make sure your internet connection is available.", comment: "")
  395. alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  396. if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) {
  397. alert.beginSheetModal(for: self.view.window!, completionHandler: nil)
  398. } else {
  399. alert.runModal()
  400. }
  401. return
  402. }
  403. if createNewPDFRadio_.properties.checkboxType == .selected {
  404. if (self.choosePath.count < 1) {
  405. let alert = NSAlert()
  406. alert.alertStyle = .critical
  407. alert.messageText = String(format: NSLocalizedString("Output Folder cannot be empty.", comment: ""))
  408. alert.runModal()
  409. return
  410. }
  411. path = self.choosePath
  412. if mergeAllCheckBox_.properties.checkboxType == .selected {
  413. isMerge = true
  414. }
  415. isCreatNewPDF = true
  416. } else {
  417. let appenString = self.appendTextField.stringValue
  418. if appenString.isEmpty {
  419. let alert = NSAlert()
  420. alert.alertStyle = .critical
  421. alert.messageText = String(format: NSLocalizedString("Select a File", comment: ""))
  422. alert.runModal()
  423. return
  424. }
  425. path = self.appendTextField.stringValue
  426. isMerge = true
  427. isCreatNewPDF = false
  428. }
  429. self.languageButton.isEnabled = false
  430. ocrPlanRadio_.properties.isDisabled = true
  431. ocrPlanRadio_.reloadData()
  432. ocrPlanRadio2_.properties.isDisabled = true
  433. ocrPlanRadio2_.reloadData()
  434. self.method.password = self.password
  435. self.interfaceStatus = .Processing
  436. self.method.saveAsTestPath = self.choosePath
  437. self.method.exportPDFFile(fileArray: photoArray, savePath: path, isOCR: isOCR, isCreatPDF: isCreatNewPDF, isMerge: isMerge, isSaveAsText: isSaveAs) { [weak self] savePath, errorArr, errorOCRArray in
  438. self?.languageButton.isEnabled = true
  439. self?.ocrPlanRadio_.properties.isDisabled = false
  440. self?.ocrPlanRadio_.reloadData()
  441. self?.ocrPlanRadio2_.properties.isDisabled = false
  442. self?.ocrPlanRadio2_.reloadData()
  443. self?.interfaceStatus = .PrepareProcess
  444. if errorArr.count > 0 {
  445. let dict: [String: Any] = ["isMerge": false, "isSuccess": false]
  446. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "KMBatchOperateImageToPDFSuccessNotification"), object: self, userInfo: dict)
  447. let alert = NSAlert()
  448. alert.messageText = NSLocalizedString("Conversion Failed", comment: "")
  449. alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  450. alert.informativeText = "\(errorArr)"
  451. alert.alertStyle = .informational
  452. alert.runModal()
  453. } else {
  454. if errorOCRArray.count > 0 {
  455. var contextString = NSLocalizedString("Some problems occurred during the last operation:", comment: "")
  456. for filePath in errorOCRArray {
  457. contextString += "\n" + (filePath as AnyObject).lastPathComponent
  458. }
  459. let alert = NSAlert()
  460. alert.messageText = NSLocalizedString("Converted Successfully", comment: "")
  461. alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  462. alert.informativeText = contextString
  463. alert.alertStyle = .informational
  464. let response = alert.runModal()
  465. if response == .OK {
  466. self?.viewFileAtFinder(fileName: savePath)
  467. }
  468. } else {
  469. self?.viewFileAtFinder(fileName: savePath)
  470. }
  471. }
  472. }
  473. }
  474. func viewFileAtFinder(fileName: String) {
  475. let dict = ["isMerge": true, "isSuccess": true]
  476. NotificationCenter.default.post(name: Notification.Name("KMBatchOperateImageToPDFSuccessNotification"), object: self, userInfo: dict)
  477. let workspace = NSWorkspace.shared
  478. let url = URL(fileURLWithPath: fileName)
  479. workspace.activateFileViewerSelecting([url])
  480. }
  481. // MARK: - Actions
  482. @objc func ocrPlanAction(_ sender: ComponentRadio) {
  483. for radio in [ocrPlanRadio_, ocrPlanRadio2_] {
  484. if radio.isEqual(to: sender) {
  485. radio.properties.checkboxType = .selected
  486. radio.reloadData()
  487. } else {
  488. radio.properties.checkboxType = .normal
  489. radio.reloadData()
  490. }
  491. }
  492. }
  493. //MARK: Notification
  494. @objc func OCRSelectedLanguagesChangeNotification(notification: Notification) {
  495. let selectedLanguages = notification.object/* as? [KMBatchOperateFile]*/
  496. self.updateLanguageButton(selectedLanguages as? [String])
  497. }
  498. @objc func OCRSelectedPlanChangeNotification(notification: Notification) {
  499. self.OCRSelectedPlanChangeAction()
  500. }
  501. @objc func themeChanged(notification: Notification) {
  502. DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
  503. self.updateViewColor()
  504. }
  505. }
  506. func OCRSelectedPlanChangeAction() {
  507. let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
  508. if plan == 0 {
  509. // self.planButton.title = " " + KMLocalizedString("Plan 1 (Online)")
  510. ocrPlanRadio_.properties.checkboxType = .selected
  511. ocrPlanRadio_.reloadData()
  512. ocrPlanRadio2_.properties.checkboxType = .normal
  513. ocrPlanRadio2_.reloadData()
  514. } else {
  515. // self.planButton.title = " " + KMLocalizedString("Plan 2 (Offline)")
  516. ocrPlanRadio_.properties.checkboxType = .normal
  517. ocrPlanRadio_.reloadData()
  518. ocrPlanRadio2_.properties.checkboxType = .selected
  519. ocrPlanRadio2_.reloadData()
  520. }
  521. KMGOCRManager.default().selectedLanguages = NSMutableArray()
  522. self.updateLanguageButton(KMGOCRManager.default().selectedLanguages?.value(forKeyPath: KMGOCRLanguageStringKey) as? [String])
  523. }
  524. @objc func batchFilesCountNotification(notification: Notification) {
  525. let files: Array? = notification.object as? [KMBatchOperateFile]
  526. self.files? = files ?? []
  527. let cnt = self.files?.count ?? 0
  528. if cnt > 0 {
  529. self._updateActionButtonEnable(true)
  530. } else {
  531. self._updateActionButtonEnable(false)
  532. }
  533. }
  534. @IBAction func buttonClicked_CreateNewPDF(_ sender: ComponentRadio) {
  535. if (sender.properties.checkboxType == .selected) {
  536. mergeAllCheckBox_.properties.isDisabled = false
  537. mergeAllCheckBox_.reloadData()
  538. appendRadio_.properties.checkboxType = .normal
  539. appendRadio_.reloadData()
  540. self.appendOtherPDFBtn.isEnabled = false
  541. }
  542. }
  543. @IBAction func buttonClicked_AppendOtherPDF(_ sender: ComponentRadio) {
  544. if (sender.properties.checkboxType == .selected) {
  545. createNewPDFRadio_.properties.checkboxType = .normal
  546. createNewPDFRadio_.reloadData()
  547. mergeAllCheckBox_.properties.checkboxType = .normal
  548. mergeAllCheckBox_.properties.isDisabled = true
  549. mergeAllCheckBox_.reloadData()
  550. self.appendOtherPDFBtn.isEnabled = true
  551. }
  552. }
  553. @IBAction func buttonClicked_OCRSelect(_ sender: ComponentCheckBox) {
  554. //MARK: 判断是否付费用户
  555. if IAPProductsManager.default().isAvailableAllFunction() == false {
  556. KMPurchaseCompareWindowController.sharedInstance().showWindow(nil)
  557. ocrCheckBox_.properties.checkboxType = .normal
  558. ocrCheckBox_.reloadData()
  559. return
  560. }
  561. if (sender.properties.checkboxType == .selected) {
  562. languageView_.properties.isDisabled = false
  563. languageView_.reloadData()
  564. ocrPlanRadio_.properties.isDisabled = false
  565. ocrPlanRadio_.reloadData()
  566. ocrPlanRadio2_.properties.isDisabled = false
  567. ocrPlanRadio2_.reloadData()
  568. extractTextCheckBox_.properties.isDisabled = false
  569. extractTextCheckBox_.reloadData()
  570. } else {
  571. languageView_.properties.isDisabled = true
  572. languageView_.reloadData()
  573. ocrPlanRadio_.properties.isDisabled = true
  574. ocrPlanRadio_.reloadData()
  575. ocrPlanRadio2_.properties.isDisabled = true
  576. ocrPlanRadio2_.reloadData()
  577. extractTextCheckBox_.properties.isDisabled = true
  578. extractTextCheckBox_.reloadData()
  579. }
  580. }
  581. @IBAction func buttonClicked_ChooseLanguage(_ sender: NSButton) {
  582. let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
  583. if plan == 0 {
  584. KMGOCRManager.default().ocrType = .google
  585. } else {
  586. KMGOCRManager.default().ocrType = .apple
  587. }
  588. let popover = NSPopover()
  589. popover.delegate = self
  590. popover.contentViewController = KMLanguageViewController(nibName: "KMLanguageViewController", bundle: Bundle.main)
  591. popover.animates = true
  592. popover.behavior = .transient
  593. popover.show(relativeTo: sender.bounds, of: sender as NSView, preferredEdge: .minX)
  594. }
  595. @IBAction func buttonClicked_ChoosePlan(_ sender: NSButton) {
  596. let popover = NSPopover()
  597. popover.delegate = self
  598. popover.contentViewController = KMPlanViewController(nibName: "KMPlanViewController", bundle: Bundle.main)
  599. popover.animates = true
  600. popover.behavior = .transient
  601. popover.show(relativeTo: sender.bounds, of: sender as NSView, preferredEdge: .minX)
  602. }
  603. @IBAction func buttonClicked_ImageToPDF(_ sender: NSButton) {
  604. //MARK: 判断是否付费用户,展示iap界面
  605. if self.files?.count ?? 0 < 1 {
  606. return
  607. }
  608. if IAPProductsManager.default().isAvailableAllFunction() == false && self.files?.count ?? 0 > 1{
  609. KMPurchaseCompareWindowController.sharedInstance().showWindow(nil)
  610. return
  611. }
  612. if sender.tag == 1 {
  613. self.choosePath = ""
  614. var hasTask = false
  615. for i in 0..<(self.files?.count ?? 0) {
  616. let file = self.files?[i]
  617. file?.currentOperateInfo?.resetState()
  618. if file?.fileType == .Image {
  619. hasTask = true
  620. }
  621. }
  622. if !hasTask {
  623. NSSound.beep()
  624. return
  625. }
  626. var isOCR = false
  627. if ocrCheckBox_.properties.checkboxType == .selected {
  628. isOCR = true
  629. }
  630. var isSaveAs = false
  631. if extractTextCheckBox_.properties.checkboxType == .selected {
  632. isSaveAs = true
  633. }
  634. let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
  635. if isOCR && !isConnectionAvailable() && plan == 0 {
  636. let alert = NSAlert()
  637. alert.alertStyle = .critical
  638. alert.messageText = NSLocalizedString("Connection Error", comment: "")
  639. alert.informativeText = NSLocalizedString("Please make sure your internet connection is available.", comment: "")
  640. alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  641. if let window = self.view.window {
  642. alert.beginSheetModal(for: window, completionHandler: nil)
  643. } else {
  644. alert.runModal()
  645. }
  646. return
  647. }
  648. if createNewPDFRadio_.properties.checkboxType != .selected {
  649. let appenString = self.appendTextField.stringValue
  650. if appenString.isEmpty {
  651. let alert = NSAlert()
  652. alert.alertStyle = .critical
  653. alert.messageText = NSLocalizedString("Select a File", comment: "")
  654. alert.runModal()
  655. return
  656. }
  657. }
  658. let openPanel = NSOpenPanel()
  659. openPanel.canChooseFiles = false
  660. openPanel.canChooseDirectories = true
  661. openPanel.canCreateDirectories = true
  662. openPanel.beginSheetModal(for: self.view.window!) { (result) in
  663. if result == .OK {
  664. for fileURL in openPanel.urls {
  665. self.choosePath = fileURL.path
  666. self.beginImageToPDF()
  667. }
  668. }
  669. }
  670. } else { // Do something else }
  671. }
  672. }
  673. @IBAction func buttonItemClicked_AppendOtherPDF(_ sender: NSButton) {
  674. let openPanel = NSOpenPanel()
  675. openPanel.allowedFileTypes = ["pdf"]
  676. openPanel.canChooseDirectories = false
  677. openPanel.allowsMultipleSelection = false
  678. openPanel.beginSheetModal(for: self.view.window!) { (result) in
  679. if result == .OK {
  680. guard let url = openPanel.url else { return }
  681. guard let document = PDFDocument(url: url) else {
  682. let alert = NSAlert()
  683. alert.alertStyle = .critical
  684. alert.messageText = NSLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", comment: "")
  685. alert.runModal()
  686. return
  687. }
  688. if !document.allowsCopying || !document.allowsPrinting {
  689. let alert = NSAlert()
  690. alert.alertStyle = .critical
  691. alert.messageText = NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "")
  692. alert.runModal()
  693. return
  694. }
  695. if document.isLocked {
  696. KMBaseWindowController.checkPassword(url: url, type: .owner) { [weak self] success, resultPassword in
  697. if success {
  698. self?.password = resultPassword
  699. self?.appendTextField.stringValue = url.path
  700. }
  701. }
  702. } else {
  703. self.appendTextField.stringValue = url.path
  704. }
  705. }
  706. }
  707. }
  708. @IBAction func buttonClicked_Help(_ sender: NSButton) {
  709. let helpController = NSViewController()
  710. let textView = NSTextView(frame: NSRect(x: 0, y: 0, width: 300.0, height: 100.0))
  711. textView.backgroundColor = NSColor.clear
  712. textView.isEditable = false
  713. textView.layer?.cornerRadius = 6
  714. let tStrAuto = NSLocalizedString("Choose automatic language detection for better OCR results.", comment: "")
  715. 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: "")
  716. let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
  717. if plan == 0 {
  718. textView.string = "\(tStrAuto)\n\n\(tStrVPN)"
  719. } else {
  720. textView.frame = NSRect(x: 0, y: 0, width: 300.0, height: 40.0)
  721. textView.string = tStrAuto
  722. }
  723. helpController.view = textView
  724. let popover = NSPopover()
  725. popover.delegate = self
  726. popover.contentViewController = helpController
  727. popover.animates = true
  728. popover.behavior = .transient
  729. popover.show(relativeTo: sender.bounds, of: sender as NSView, preferredEdge: .minY)
  730. }
  731. //MARK: KMImageToPDFMethodDelegate
  732. func imageToPDFMethod(_ method: KMImageToPDFMethod, progress: Float) {
  733. }
  734. }