KMBatchOperateImageToPDFViewController.swift 34 KB

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