KMBatchOperateImageToPDFViewController.swift 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  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 ocrLabel: NSTextField!
  15. @IBOutlet weak var newPDFBox: NSBox!
  16. @IBOutlet weak var mergeAllBox: NSBox!
  17. @IBOutlet weak var appendBox: NSBox!
  18. @IBOutlet weak var appendBackBox: NSBox!
  19. @IBOutlet weak var ocrSelectBox: NSBox!
  20. @IBOutlet weak var languageBox: NSBox!
  21. @IBOutlet weak var ocrPlanBox: NSBox!
  22. @IBOutlet weak var ocrPlan2Box: NSBox!
  23. @IBOutlet weak var hLine: NSView!
  24. @IBOutlet weak var extractTextBox: NSBox!
  25. @IBOutlet weak var bottomBox: NSBox!
  26. @IBOutlet weak var bottomTopLine: ComponentDivider!
  27. @IBOutlet weak var applyButton: ComponentButton!
  28. var password: String = ""
  29. lazy var method: KMImageToPDFMethod = {
  30. let method = KMImageToPDFMethod()
  31. method.imageTopdfDelegate = self
  32. return method
  33. }()
  34. private lazy var topLine: NSView = {
  35. let view = NSView()
  36. view.wantsLayer = true
  37. return view
  38. }()
  39. private var createNewPDFRadio_: ComponentRadio = {
  40. let view = ComponentRadio()
  41. view.properties = ComponentCheckBoxProperty(size: .s, state: .normal, isDisabled: false, showhelp: false, text: KMLocalizedString("New PDF Document", comment: ""), checkboxType: .normal)
  42. return view
  43. }()
  44. private lazy var mergeAllCheckBox_: ComponentCheckBox = {
  45. let view = ComponentCheckBox()
  46. view.properties = ComponentCheckBoxProperty(size: .s, state: .normal, isDisabled: false, showhelp: false, text: KMLocalizedString("Merge All", comment: ""),checkboxType: .normal)
  47. return view
  48. }()
  49. private var appendRadio_: ComponentRadio = {
  50. let view = ComponentRadio()
  51. view.properties = ComponentCheckBoxProperty(size: .s, state: .normal, isDisabled: false, showhelp: false, text: KMLocalizedString("Append To Existing File", comment: ""), checkboxType: .normal)
  52. return view
  53. }()
  54. private var appendBackInput: ComponentInputWithAddon = {
  55. let view = ComponentInputWithAddon()
  56. view.properties = ComponentInputWithAddonProperty(size: .s, isDisabled: true, addonType: .button)
  57. return view
  58. }()
  59. private lazy var appendBackInput_: ComponentInput = {
  60. let view = ComponentInput()
  61. return view
  62. }()
  63. private lazy var appendBackButtonInput_: ComponentInputAddon = {
  64. let view = ComponentInputAddon()
  65. return view
  66. }()
  67. private lazy var ocrCheckBox_: ComponentCheckBox = {
  68. let view = ComponentCheckBox()
  69. view.properties = ComponentCheckBoxProperty(size: .s, state: .normal, isDisabled: false, showhelp: false, text: KMLocalizedString("Recognize text if needed", comment: ""), checkboxType: .normal)
  70. return view
  71. }()
  72. private lazy var languageView_: ComponentSelect = {
  73. let view = ComponentSelect()
  74. view.properties = ComponentSelectProperties(size: .s, state: .normal, isDisabled: false, isError: false, leftIcon: false, placeholder: nil, errorText: nil, creatable: false, text: KMLocalizedString("", comment: ""))
  75. view.delegate = self
  76. return view
  77. }()
  78. private var ocrPlanRadio_: ComponentRadio = {
  79. let view = ComponentRadio()
  80. view.properties = ComponentCheckBoxProperty(size: .s, state: .normal, isDisabled: false, showhelp: true, text: KMLocalizedString("OCR Plan 1-Online", comment: ""), checkboxType: .normal)
  81. view.toolTip = KMLocalizedString("The OCR service works via an internet connection. We would suggest you to perform OCR using a VPN connection while the service is limited.")
  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. view.toolTip = KMLocalizedString("The OCR service works via an internet connection. We would suggest you to perform OCR using a VPN connection while the service is limited.")
  88. return view
  89. }()
  90. private var vLine_: ComponentDivider = {
  91. let view = ComponentDivider()
  92. view.properties = ComponentDividerProperty(type: .horizontal, dash: false)
  93. return view
  94. }()
  95. private lazy var extractTextCheckBox_: ComponentCheckBox = {
  96. let view = ComponentCheckBox()
  97. view.properties = ComponentCheckBoxProperty(size: .s, state: .normal, isDisabled: false, showhelp: false, text: KMLocalizedString("Extract Text (.txt)", comment: ""), checkboxType: .normal)
  98. return view
  99. }()
  100. override var interfaceStatus: KMBatchOperateInterfaceStatus?{
  101. set{
  102. super.interfaceStatus = newValue
  103. if newValue == .PrepareProcess {
  104. DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
  105. let files = NSMutableArray()
  106. for url in self.successFilePathURLArray! {
  107. if FileManager.default.fileExists(atPath: url.path) {
  108. files.add(url)
  109. }
  110. }
  111. if files.count > 0 {
  112. let workspace = NSWorkspace.shared
  113. workspace.activateFileViewerSelecting(files as! [URL])
  114. }
  115. }
  116. self._updateActionButtonEnable(true)
  117. } else {
  118. self._updateActionButtonEnable(false)
  119. }
  120. }
  121. get{
  122. return super.interfaceStatus
  123. }
  124. }
  125. private func _updateActionButtonEnable(_ enabled: Bool) {
  126. applyButton.properties.isDisabled = !enabled
  127. applyButton.reloadData()
  128. }
  129. override func viewDidLoad() {
  130. super.viewDidLoad()
  131. headerBox.borderWidth = 0
  132. titleLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-m-bold")
  133. createNewPDFRadio_.properties.checkboxType = .selected
  134. createNewPDFRadio_.reloadData()
  135. appendBackBox.borderWidth = 0
  136. let color = KMNColorTools.compField_colorBorderDis()
  137. appendBackBox.borderColor = color
  138. let inputWithAddonProperty = ComponentInputProperty(size: .s,
  139. state: .normal,
  140. isError: false,
  141. showPrefix: false,
  142. showSuffix: false,
  143. showClear: false,
  144. isDisabled: true,
  145. placeholder: KMLocalizedString("Select File..."),
  146. text: "",
  147. creatable: false)
  148. appendBackInput_.properties = inputWithAddonProperty
  149. appendBackInput_.properties.propertyInfo.cornerRadius_topRight = 0
  150. appendBackInput_.properties.propertyInfo.cornerRadius_bottomRight = 0
  151. appendBackInput_.properties.isDisabled = true
  152. appendBackInput_.reloadData()
  153. appendBackButtonInput_.properties = ComponentInputAddonProperty(size: .s,
  154. state: .normal,
  155. addOnBefore: false,
  156. onlyRead: false,
  157. addonType: .imageWithColor,
  158. iconImage: NSImage(named: "KMFolderIcon"))
  159. appendBackButtonInput_.properties.isDisabled = true
  160. appendBackButtonInput_.reloadData()
  161. appendBackButtonInput_.setTarget(self, action: #selector(buttonItemClicked_AppendOtherPDF))
  162. appendBackBox.contentView?.addSubview(appendBackInput_)
  163. appendBackBox.contentView?.addSubview(appendBackButtonInput_)
  164. let boxH: CGFloat = 30
  165. appendBackInput_.frame = NSMakeRect(0, 0, 204, boxH)
  166. appendBackButtonInput_.frame = NSMakeRect(NSMaxX(appendBackInput_.frame), 0, boxH+2, boxH)
  167. let hView = NSView()
  168. appendBackBox.contentView?.addSubview(hView)
  169. hView.frame = NSMakeRect(NSMaxX(appendBackInput_.frame), 0, 1, 32)
  170. hView.wantsLayer = true
  171. hView.layer?.backgroundColor = color.cgColor
  172. hView.isHidden = true
  173. ocrLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-s-medium")
  174. ocrSelectBox.borderWidth = 0
  175. ocrSelectBox.contentView = ocrCheckBox_
  176. ocrCheckBox_.setTarget(self, action: #selector(buttonClicked_OCRSelect))
  177. languageView_.properties.isDisabled = true
  178. languageView_.reloadData()
  179. ocrPlanRadio_.setTarget(self, action: #selector(ocrPlanAction))
  180. ocrPlanRadio_.properties.isDisabled = true
  181. ocrPlanRadio_.properties.checkboxType = .selected
  182. ocrPlanRadio_.reloadData()
  183. ocrPlanRadio2_.setTarget(self, action: #selector(ocrPlanAction))
  184. ocrPlanRadio2_.properties.isDisabled = true
  185. ocrPlanRadio2_.reloadData()
  186. extractTextCheckBox_.properties.isDisabled = true
  187. extractTextCheckBox_.reloadData()
  188. bottomBox.borderWidth = 0
  189. applyButton.properties = ComponentButtonProperty(type: .primary, size: .m, onlyIcon: false, buttonText: KMLocalizedString("Apply"))
  190. applyButton.setTarget(self, action: #selector(buttonClicked_ImageToPDF))
  191. view.addSubview(topLine)
  192. topLine.km_add_top_constraint()
  193. topLine.km_add_height_constraint(constant: 1)
  194. topLine.km_add_left_constraint()
  195. topLine.km_add_right_constraint()
  196. self.localizedLanguage()
  197. self.configuUI()
  198. if let cnt = self.files?.count, cnt > 0 {
  199. self._updateActionButtonEnable(true)
  200. } else {
  201. self._updateActionButtonEnable(false)
  202. }
  203. }
  204. override func addNotifations() {
  205. super.addNotifations()
  206. NotificationCenter.default.addObserver(self, selector: #selector(batchFilesCountNotification(notification:)), name: NSNotification.Name("KMBatchFilesCountNotification"), object: nil)
  207. }
  208. override func updateUILanguage() {
  209. super.updateUILanguage()
  210. KMMainThreadExecute {
  211. self.titleLabel.stringValue = KMLocalizedString("Image to PDF")
  212. self.ocrLabel.stringValue = KMLocalizedString("Text Recognition Settings")
  213. }
  214. }
  215. override func updateUIThemeColor() {
  216. super.updateUIThemeColor()
  217. KMMainThreadExecute {
  218. self.topLine.layer?.backgroundColor = KMNColorTools.colorBorder_divider().cgColor
  219. let titleColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
  220. self.titleLabel.textColor = titleColor
  221. self.headerBottomLine.properties = ComponentDividerProperty()
  222. self.ocrLabel.textColor = titleColor
  223. self.languageBox.borderColor = KMNColorTools.compField_colorBorderDis()
  224. self.bottomTopLine.properties = ComponentDividerProperty()
  225. self.updateViewColor()
  226. }
  227. }
  228. func localizedLanguage() {
  229. self.outputTypeLabel.stringValue = KMLocalizedString("Output")
  230. let languages = KMGOCRManager.languages() as NSArray
  231. let strings = languages.value(forKeyPath: KMGOCRLanguageStringKey) as? [String]
  232. var menuItemArr: [ComponentMenuitemProperty] = []
  233. for language in strings ?? [] {
  234. let itemProperty: ComponentMenuitemProperty = ComponentMenuitemProperty(multipleSelect: false,
  235. itemSelected: false,
  236. isDisabled: false,
  237. keyEquivalent: nil,
  238. text: language)
  239. menuItemArr.append(itemProperty)
  240. }
  241. languageView_.updateMenuItemsArr(menuItemArr)
  242. languageView_.selectItemAtIndex(0)
  243. languageView_.properties.creatable = false
  244. languageView_.properties.text = menuItemArr.first?.text
  245. languageView_.reloadData()
  246. self.updateLanguageButton((KMGOCRManager.default().selectedLanguages?.value(forKeyPath: KMGOCRLanguageStringKey) as? [String]))
  247. self.OCRSelectedPlanChangeAction()
  248. }
  249. func configuUI() {
  250. self.view.wantsLayer = true
  251. newPDFBox.borderWidth = 0
  252. newPDFBox.contentView = createNewPDFRadio_
  253. createNewPDFRadio_.setTarget(self, action: #selector(buttonClicked_CreateNewPDF))
  254. mergeAllBox.borderWidth = 0
  255. mergeAllBox.contentView = mergeAllCheckBox_
  256. appendBox.borderWidth = 0
  257. appendBox.contentView = appendRadio_
  258. appendRadio_.setTarget(self, action: #selector(buttonClicked_AppendOtherPDF))
  259. languageBox.borderWidth = 1
  260. languageBox.cornerRadius = ComponentLibrary.shared.getComponentValueFromKey("comp-field/radius") as? CGFloat ?? 4
  261. languageBox.contentView = languageView_
  262. ocrPlanBox.borderWidth = 0
  263. ocrPlanBox.contentView?.addSubview(ocrPlanRadio_)
  264. ocrPlanRadio_.km_add_leading_constraint()
  265. ocrPlanRadio_.km_add_centerY_constraint()
  266. ocrPlanRadio_.km_add_height_constraint(equalTo: ocrPlanBox.contentView)
  267. ocrPlanRadio_.km_add_width_constraint(constant: ocrPlanRadio_.properties.propertyInfo.viewWidth + 10)
  268. ocrPlan2Box.borderWidth = 0
  269. ocrPlan2Box.contentView?.addSubview(ocrPlanRadio2_)
  270. ocrPlanRadio2_.km_add_leading_constraint()
  271. ocrPlanRadio2_.km_add_centerY_constraint()
  272. ocrPlanRadio2_.km_add_height_constraint(equalTo: ocrPlan2Box.contentView)
  273. ocrPlanRadio2_.km_add_width_constraint(constant: ocrPlanRadio2_.properties.propertyInfo.viewWidth + 10)
  274. hLine.addSubview(vLine_)
  275. vLine_.frame = hLine.bounds
  276. vLine_.autoresizingMask = [.width, .height]
  277. extractTextBox.borderWidth = 0
  278. extractTextBox.contentView = extractTextCheckBox_
  279. }
  280. func updateViewColor() {
  281. self.view.layer?.backgroundColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg-layout-middle").cgColor
  282. }
  283. func updateLanguageButton(_ languages: [String]?) {
  284. if languages?.count ?? 0 < 1 {
  285. self.languageView_.properties.text = " " + KMLocalizedString("Auto Detection")
  286. self.languageView_.reloadData()
  287. return
  288. }
  289. var languageName: String = ""
  290. if languages?.count ?? 0 > 0 {
  291. for i in 0..<(languages?.count ?? 0) {
  292. let language = languages?[i]
  293. if i == 0 {
  294. languageName = language ?? ""
  295. } else {
  296. languageName = languageName.appendingFormat(",%@", language ?? "")
  297. }
  298. }
  299. } else {
  300. languageName = ""
  301. }
  302. self.languageView_.properties.text = " " + languageName
  303. self.languageView_.reloadData()
  304. }
  305. func converArrType(arr: Array<KMBatchOperateFile>, keyString: String) -> [String] {
  306. let newArr = NSMutableArray()
  307. for item in arr {
  308. newArr.add(item.filePath)
  309. }
  310. return newArr as! [String]
  311. }
  312. func isConnectionAvailable() -> Bool {
  313. if Reachability.forInternetConnection().currentReachabilityStatus().rawValue == 0 {
  314. return false
  315. }
  316. return true
  317. }
  318. func beginImageToPDF() {
  319. if self.files?.count ?? 0 < 1 {
  320. return
  321. }
  322. let photoArray = converArrType(arr: self.files!, keyString: "")
  323. var path: String = ""
  324. var isMerge = false
  325. var isCreatNewPDF = false
  326. var isOCR = false
  327. if ocrCheckBox_.properties.checkboxType == .selected {
  328. isOCR = true
  329. }
  330. var isSaveAs = false
  331. if extractTextCheckBox_.properties.checkboxType == .selected {
  332. isSaveAs = true
  333. }
  334. let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
  335. if isOCR && !self.isConnectionAvailable() && plan == 0 {
  336. let alert = NSAlert()
  337. alert.alertStyle = .critical
  338. alert.messageText = KMLocalizedString("Connection Error", comment: "")
  339. alert.informativeText = KMLocalizedString("Please make sure your internet connection is available.", comment: "")
  340. alert.addButton(withTitle: KMLocalizedString("OK", comment: ""))
  341. if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) {
  342. alert.beginSheetModal(for: self.view.window!, completionHandler: nil)
  343. } else {
  344. alert.runModal()
  345. }
  346. return
  347. }
  348. if createNewPDFRadio_.properties.checkboxType == .selected {
  349. if (self.choosePath.count < 1) {
  350. let alert = NSAlert()
  351. alert.alertStyle = .critical
  352. alert.messageText = String(format: KMLocalizedString("Output Folder cannot be empty.", comment: ""))
  353. alert.runModal()
  354. return
  355. }
  356. path = self.choosePath
  357. if mergeAllCheckBox_.properties.checkboxType == .selected {
  358. isMerge = true
  359. }
  360. isCreatNewPDF = true
  361. } else {
  362. let appenString = appendBackInput_.properties.text
  363. if appenString.isEmpty {
  364. let alert = NSAlert()
  365. alert.alertStyle = .critical
  366. alert.messageText = String(format: KMLocalizedString("Select a File", comment: ""))
  367. alert.runModal()
  368. return
  369. }
  370. path = appenString
  371. isMerge = true
  372. isCreatNewPDF = false
  373. }
  374. let planDisabled = ocrPlanRadio_.properties.isDisabled
  375. ocrPlanRadio_.properties.isDisabled = true
  376. ocrPlanRadio_.reloadData()
  377. ocrPlanRadio2_.properties.isDisabled = true
  378. ocrPlanRadio2_.reloadData()
  379. self.method.password = self.password
  380. self.interfaceStatus = .Processing
  381. self.method.saveAsTestPath = self.choosePath
  382. self.method.exportPDFFile(fileArray: photoArray, savePath: path, isOCR: isOCR, isCreatPDF: isCreatNewPDF, isMerge: isMerge, isSaveAsText: isSaveAs) { [weak self] savePath, errorArr, errorOCRArray in
  383. self?.ocrPlanRadio_.properties.isDisabled = planDisabled
  384. self?.ocrPlanRadio_.reloadData()
  385. self?.ocrPlanRadio2_.properties.isDisabled = planDisabled
  386. self?.ocrPlanRadio2_.reloadData()
  387. self?.applyButton.properties.isDisabled = false
  388. self?.applyButton.properties.state = .normal
  389. self?.applyButton.reloadData()
  390. self?.interfaceStatus = .PrepareProcess
  391. if errorArr.count > 0 {
  392. let dict: [String: Any] = ["isMerge": false, "isSuccess": false]
  393. NotificationCenter.default.post(name: NSNotification.Name(rawValue: "KMBatchOperateImageToPDFSuccessNotification"), object: self, userInfo: dict)
  394. let alert = NSAlert()
  395. alert.messageText = KMLocalizedString("Conversion Failed", comment: "")
  396. alert.addButton(withTitle: KMLocalizedString("OK", comment: ""))
  397. alert.informativeText = "\(errorArr)"
  398. alert.alertStyle = .informational
  399. alert.runModal()
  400. } else {
  401. if errorOCRArray.count > 0 {
  402. var contextString = KMLocalizedString("Some problems occurred during the last operation:", comment: "")
  403. for filePath in errorOCRArray {
  404. contextString += "\n" + (filePath as AnyObject).lastPathComponent
  405. }
  406. let alert = NSAlert()
  407. alert.messageText = KMLocalizedString("Converted Successfully", comment: "")
  408. alert.addButton(withTitle: KMLocalizedString("OK", comment: ""))
  409. alert.informativeText = contextString
  410. alert.alertStyle = .informational
  411. let response = alert.runModal()
  412. if response == .OK {
  413. self?.viewFileAtFinder(fileName: savePath)
  414. }
  415. } else {
  416. self?.viewFileAtFinder(fileName: savePath)
  417. }
  418. }
  419. }
  420. }
  421. func viewFileAtFinder(fileName: String) {
  422. let dict = ["isMerge": true, "isSuccess": true]
  423. NotificationCenter.default.post(name: Notification.Name("KMBatchOperateImageToPDFSuccessNotification"), object: self, userInfo: dict)
  424. let workspace = NSWorkspace.shared
  425. let url = URL(fileURLWithPath: fileName)
  426. workspace.activateFileViewerSelecting([url])
  427. }
  428. // MARK: - Actions
  429. @objc func ocrPlanAction(_ sender: ComponentRadio) {
  430. for radio in [ocrPlanRadio_, ocrPlanRadio2_] {
  431. if radio.isEqual(to: sender) {
  432. radio.properties.checkboxType = .selected
  433. radio.reloadData()
  434. KMGOCRManager.default().ocrType = .google
  435. KMDataManager.ud_set(0, forKey: "KMOCRCurrentPlanKey")
  436. } else {
  437. radio.properties.checkboxType = .normal
  438. radio.reloadData()
  439. KMGOCRManager.default().ocrType = .apple
  440. KMDataManager.ud_set(1, forKey: "KMOCRCurrentPlanKey")
  441. }
  442. }
  443. self.OCRSelectedPlanChangeAction()
  444. }
  445. @IBAction func buttonClicked_CreateNewPDF(_ sender: ComponentRadio) {
  446. if (sender.properties.checkboxType == .selected) {
  447. mergeAllCheckBox_.properties.isDisabled = false
  448. mergeAllCheckBox_.reloadData()
  449. appendRadio_.properties.checkboxType = .normal
  450. appendRadio_.reloadData()
  451. appendBackInput_.properties.isDisabled = true
  452. appendBackInput_.reloadData()
  453. appendBackButtonInput_.properties.isDisabled = true
  454. appendBackButtonInput_.reloadData()
  455. }
  456. }
  457. @IBAction func buttonClicked_AppendOtherPDF(_ sender: ComponentRadio) {
  458. if (sender.properties.checkboxType == .selected) {
  459. createNewPDFRadio_.properties.checkboxType = .normal
  460. createNewPDFRadio_.reloadData()
  461. mergeAllCheckBox_.properties.checkboxType = .normal
  462. mergeAllCheckBox_.properties.isDisabled = true
  463. mergeAllCheckBox_.reloadData()
  464. appendBackInput_.properties.isDisabled = false
  465. appendBackInput_.reloadData()
  466. appendBackButtonInput_.properties.isDisabled = false
  467. appendBackButtonInput_.reloadData()
  468. }
  469. }
  470. @IBAction func buttonClicked_OCRSelect(_ sender: ComponentCheckBox) {
  471. //MARK: 判断是否付费用户
  472. if IAPProductsManager.default().isAvailableAllFunction() == false {
  473. KMPurchaseCompareWindowController.sharedInstance().showWindow(nil)
  474. ocrCheckBox_.properties.checkboxType = .normal
  475. ocrCheckBox_.reloadData()
  476. return
  477. }
  478. if (sender.properties.checkboxType == .selected) {
  479. languageView_.properties.isDisabled = false
  480. languageView_.reloadData()
  481. ocrPlanRadio_.properties.isDisabled = false
  482. ocrPlanRadio_.reloadData()
  483. ocrPlanRadio2_.properties.isDisabled = false
  484. ocrPlanRadio2_.reloadData()
  485. extractTextCheckBox_.properties.isDisabled = false
  486. extractTextCheckBox_.reloadData()
  487. } else {
  488. languageView_.properties.isDisabled = true
  489. languageView_.reloadData()
  490. ocrPlanRadio_.properties.isDisabled = true
  491. ocrPlanRadio_.reloadData()
  492. ocrPlanRadio2_.properties.isDisabled = true
  493. ocrPlanRadio2_.reloadData()
  494. extractTextCheckBox_.properties.isDisabled = true
  495. extractTextCheckBox_.reloadData()
  496. }
  497. }
  498. @IBAction func buttonClicked_ImageToPDF(_ sender: ComponentButton) {
  499. //MARK: 判断是否付费用户,展示iap界面
  500. if self.files?.count ?? 0 < 1 {
  501. return
  502. }
  503. if IAPProductsManager.default().isAvailableAllFunction() == false && self.files?.count ?? 0 > 1{
  504. KMPurchaseCompareWindowController.sharedInstance().showWindow(nil)
  505. return
  506. }
  507. if sender.properties.state == .pressed {
  508. self.choosePath = ""
  509. var hasTask = false
  510. for i in 0..<(self.files?.count ?? 0) {
  511. let file = self.files?[i]
  512. file?.currentOperateInfo?.resetState()
  513. if file?.fileType == .Image {
  514. hasTask = true
  515. }
  516. }
  517. if !hasTask {
  518. NSSound.beep()
  519. return
  520. }
  521. var isOCR = false
  522. if ocrCheckBox_.properties.checkboxType == .selected {
  523. isOCR = true
  524. }
  525. var isSaveAs = false
  526. if extractTextCheckBox_.properties.checkboxType == .selected {
  527. isSaveAs = true
  528. }
  529. let plan = UserDefaults.standard.integer(forKey: "KMOCRCurrentPlanKey")
  530. if isOCR && !isConnectionAvailable() && plan == 0 {
  531. let alert = NSAlert()
  532. alert.alertStyle = .critical
  533. alert.messageText = KMLocalizedString("Connection Error", comment: "")
  534. alert.informativeText = KMLocalizedString("Please make sure your internet connection is available.", comment: "")
  535. alert.addButton(withTitle: KMLocalizedString("OK", comment: ""))
  536. if let window = self.view.window {
  537. alert.beginSheetModal(for: window, completionHandler: nil)
  538. } else {
  539. alert.runModal()
  540. }
  541. return
  542. }
  543. if createNewPDFRadio_.properties.checkboxType != .selected {
  544. let appenString = appendBackInput_.properties.text
  545. if appenString.isEmpty {
  546. let alert = NSAlert()
  547. alert.alertStyle = .critical
  548. alert.messageText = KMLocalizedString("Select a File", comment: "")
  549. alert.runModal()
  550. return
  551. }
  552. }
  553. let openPanel = NSOpenPanel()
  554. openPanel.canChooseFiles = false
  555. openPanel.canChooseDirectories = true
  556. openPanel.canCreateDirectories = true
  557. openPanel.beginSheetModal(for: self.view.window!) { (result) in
  558. if result == .OK {
  559. for fileURL in openPanel.urls {
  560. self.choosePath = fileURL.path
  561. self.beginImageToPDF()
  562. }
  563. }
  564. }
  565. } else { // Do something else }
  566. }
  567. }
  568. @IBAction func buttonItemClicked_AppendOtherPDF(_ sender: NSButton) {
  569. let isDisabled = appendBackButtonInput_.properties.isDisabled
  570. if isDisabled {
  571. return
  572. }
  573. let openPanel = NSOpenPanel()
  574. openPanel.allowedFileTypes = ["pdf"]
  575. openPanel.canChooseDirectories = false
  576. openPanel.allowsMultipleSelection = false
  577. openPanel.beginSheetModal(for: self.view.window!) { (result) in
  578. if result == .OK {
  579. guard let url = openPanel.url else { return }
  580. guard let document = PDFDocument(url: url) else {
  581. let alert = NSAlert()
  582. alert.alertStyle = .critical
  583. alert.messageText = KMLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", comment: "")
  584. alert.runModal()
  585. return
  586. }
  587. if !document.allowsCopying || !document.allowsPrinting {
  588. let alert = NSAlert()
  589. alert.alertStyle = .critical
  590. alert.messageText = KMLocalizedString("This is a secured document. Editing is not permitted.", comment: "")
  591. alert.runModal()
  592. return
  593. }
  594. if document.isLocked {
  595. NSWindowController.checkPassword(url: url, type: .owner) { [weak self] success, resultPassword in
  596. if success {
  597. self?.password = resultPassword
  598. self?.appendBackInput_.properties.text = url.path
  599. self?.appendBackInput_.reloadData()
  600. }
  601. }
  602. } else {
  603. self.appendBackInput_.properties.text = url.path
  604. self.appendBackInput_.reloadData()
  605. }
  606. }
  607. }
  608. }
  609. // "Choose automatic language detection for better OCR results."
  610. //MARK: -Notification
  611. @objc func batchFilesCountNotification(notification: Notification) {
  612. let files: Array? = notification.object as? [KMBatchOperateFile]
  613. self.files? = files ?? []
  614. let cnt = self.files?.count ?? 0
  615. if cnt > 0 {
  616. self._updateActionButtonEnable(true)
  617. } else {
  618. self._updateActionButtonEnable(false)
  619. }
  620. }
  621. func OCRSelectedPlanChangeAction() {
  622. KMGOCRManager.default().selectedLanguages = NSMutableArray()
  623. self.updateLanguageButton(KMGOCRManager.default().selectedLanguages?.value(forKeyPath: KMGOCRLanguageStringKey) as? [String])
  624. }
  625. }
  626. // MARK: - KMImageToPDFMethodDelegate
  627. extension KMBatchOperateImageToPDFViewController: KMImageToPDFMethodDelegate {
  628. func imageToPDFMethod(_ method: KMImageToPDFMethod, progress: Float) {
  629. }
  630. }
  631. // MARK: - ComponentSelectDelegate
  632. extension KMBatchOperateImageToPDFViewController: ComponentSelectDelegate {
  633. func componentSelectDidSelect(view: ComponentSelect?, menuItemProperty: ComponentMenuitemProperty?) {
  634. let idx = view?.indexOfSelect() ?? 0
  635. let languages = KMGOCRManager.languages() as NSArray
  636. let lanuage = languages[idx]
  637. KMGOCRManager.default().selectedLanguages = [lanuage]
  638. }
  639. }