KMPDFInsertWindowController.swift 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. //
  2. // KMPDFInsertWindowController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by tangchao on 2023/12/7.
  6. //
  7. import Cocoa
  8. class KMPDFInsertWindowController: KMNBaseWindowController {
  9. @IBOutlet weak var progress: NSProgressIndicator!
  10. @IBOutlet weak var pageCountLabel: NSTextField!
  11. @IBOutlet weak var insertTypeLabel: NSTextField!
  12. @IBOutlet weak var locationLabel: NSTextField!
  13. @IBOutlet weak var pageRangeLabel: NSTextField!
  14. @IBOutlet weak var pageLabel: NSTextField!
  15. @IBOutlet weak var pagesText: NSTextField!
  16. @IBOutlet weak var outputFolderText: NSTextField!
  17. @IBOutlet weak var blankButton: NSButton!
  18. @IBOutlet weak var outputFolderButton: NSButton!
  19. @IBOutlet weak var locationFirstButton: NSButton!
  20. @IBOutlet weak var locationLastButton: NSButton!
  21. @IBOutlet weak var rangeButton: NSButton!
  22. @IBOutlet weak var insertButton: NSButton!
  23. @IBOutlet weak var cancelButton: NSButton!
  24. @IBOutlet weak var selectedPathButton: NSButton!
  25. @IBOutlet weak var pageRangeBox: NSComboBox!
  26. @IBOutlet weak var byPageStepper: NSStepper!
  27. @IBOutlet weak var fromBackView: NSView!
  28. @IBOutlet weak var insertBox: NSBox!
  29. @IBOutlet weak var whereInsertBox: NSBox!
  30. @IBOutlet weak var insertLabel: NSTextField!
  31. @IBOutlet weak var whereInsertLabel: NSTextField!
  32. @IBOutlet weak var locationRangePopUpButton: NSPopUpButton!
  33. var insertLocation: Int = 0
  34. var currentPage: Int = 0
  35. private var _pdfDocument: CPDFDocument?
  36. private var _type: KMPDFEditInsertType = .management
  37. private var _insertPages: [CPDFPage] = []
  38. private var _fromFilePath: URL?
  39. private var _password: String?
  40. private var _fromFilePassword: String?
  41. private var _insertPageIndex = 0
  42. var pdfDocument: CPDFDocument?
  43. private var _fileAttri: KMFileAttribute?
  44. var callback: KMCommonClickBlock?
  45. convenience init(document: CPDFDocument) {
  46. self.init(windowNibName: "KMPDFInsertWindowController")
  47. self._type = .pageEdit
  48. self._pdfDocument = document
  49. }
  50. convenience init(fileURL documentPath: URL) {
  51. self.init(windowNibName: "KMPDFInsertWindowController")
  52. self._type = .management
  53. self.currentPage = 1
  54. self._pdfDocument = CPDFDocument(url: documentPath)
  55. }
  56. override func windowDidLoad() {
  57. super.windowDidLoad()
  58. self._insertPages = []
  59. self.fromBackView.wantsLayer = true
  60. self.fromBackView.layer?.borderWidth = 0.8
  61. self.fromBackView.layer?.cornerRadius = 2.0
  62. var viewColor = NSColor.white
  63. var viewborderColor = NSColor(red: 195.0/255.0, green: 195.0/255.0, blue: 195.0/255.0, alpha: 1)
  64. var textColor = NSColor(red: 51.0/255.0, green: 51.0/255.0, blue: 51.0/255.0, alpha: 1)
  65. if KMAppearance.isDarkMode() {
  66. viewColor = NSColor(red: 101.0/255.0, green: 101.0/255.0, blue: 101.0/255.0, alpha: 1)
  67. viewborderColor = .clear
  68. textColor = .white
  69. }
  70. self.fromBackView.layer?.backgroundColor = viewColor.cgColor
  71. self.fromBackView.layer?.borderColor = viewborderColor.cgColor
  72. self.outputFolderText.textColor = textColor
  73. self.selectedPathButton.title = KMLocalizedString("Choose...")
  74. self.insertLabel.stringValue = KMLocalizedString("Insert")
  75. self.whereInsertLabel.stringValue = KMLocalizedString("Where to insert?")
  76. self.pageRangeLabel.stringValue = KMLocalizedString("Page Range:")
  77. self.pageLabel.stringValue = KMLocalizedString("Page")
  78. self.selectedPathButton.isEnabled = false
  79. self.progress.isHidden = true
  80. self.pageRangeBox.isEditable = false
  81. self.outputFolderText.isEditable = false
  82. self.pagesText.isEditable = false
  83. self.byPageStepper.isEnabled = false
  84. self.pageRangeLabel.isHidden = true
  85. self.pageRangeBox.isHidden = true
  86. self.blankButton.title = KMLocalizedString("Blank Page")
  87. self.locationFirstButton.title = KMLocalizedString("First")
  88. self.locationLastButton.title = KMLocalizedString("Last")
  89. self.outputFolderButton.title = KMLocalizedString("From PDF")
  90. self.cancelButton.title = KMLocalizedString("Cancel")
  91. self.insertButton.title = KMLocalizedString("Insert")
  92. self.pagesText.formatter = TextFieldFormatter()
  93. self.pagesText.delegate = self
  94. self.pageRangeBox.addItem(withObjectValue: KMLocalizedString("All Pages"))
  95. self.pageRangeBox.addItem(withObjectValue: KMLocalizedString("Odd Pages Only"))
  96. self.pageRangeBox.addItem(withObjectValue: KMLocalizedString("Even Pages Only"))
  97. self.pageRangeBox.addItem(withObjectValue: KMLocalizedString("e.g. 1,3-5,10"))
  98. (self.pageRangeBox.cell as? NSComboBoxCell)?.placeholderString = KMLocalizedString("e.g. 1,3-5,10")
  99. self.pageRangeBox.selectItem(at: 0)
  100. let menu = NSMenu()
  101. _ = menu.addItem(title: KMLocalizedString("After"), action: #selector(after_Action), target: self)
  102. _ = menu.addItem(title: KMLocalizedString("Before"), action: #selector(before_Action), target: self)
  103. self.locationRangePopUpButton.menu = menu
  104. self.outputFolderText.placeholderString = KMLocalizedString("Select a File")
  105. self.pageRangeBox.isEnabled = false
  106. self.locationRangePopUpButton.isEnabled = false
  107. if let data = self._pdfDocument?.isLocked, data {
  108. Self.checkPassword(url: self._pdfDocument!.documentURL, type: .owner) { [weak self] success, resultPassword in
  109. if success {
  110. self?._pdfDocument?.unlock(withPassword: resultPassword)
  111. self?._password = resultPassword
  112. self?.pageCountLabel.stringValue = "\(self?._pdfDocument?.pageCount ?? 0)"
  113. self?.byPageStepper.minValue = 1
  114. self?.byPageStepper.maxValue = Double(self?.pdfDocument?.pageCount ?? 1)
  115. }
  116. }
  117. } else {
  118. self.byPageStepper.minValue = 1.0
  119. self.byPageStepper.maxValue = Double(self._pdfDocument?.pageCount ?? 0)
  120. self.pageCountLabel.stringValue = String(format: "/%ld", self._pdfDocument?.pageCount ?? 0)
  121. }
  122. if (self.insertLocation == 2) {
  123. self.locationLastButton.state = .on
  124. } else if (self.insertLocation == 3) {
  125. self.rangeButton.state = .on
  126. self.locationRangePopUpButton.isEnabled = true
  127. self.pagesText.isEditable = true
  128. self.byPageStepper.isEnabled = true
  129. } else {
  130. self.locationFirstButton.state = .on
  131. }
  132. self.pagesText.stringValue = String(format: "%ld", self.currentPage)
  133. self.byPageStepper.integerValue = Int(self.pagesText.stringValue) ?? 0
  134. }
  135. @IBAction func buttonItemClicked_Insert(_ sender: AnyObject?) {
  136. if KMMemberInfo.shared.isLogin == false {
  137. KMLoginWindowsController.shared.showWindow(nil)
  138. return
  139. }
  140. if let data = self._pdfDocument?.isLocked, data {
  141. self._pdfDocument?.unlock(withPassword: self._password ?? "")
  142. }
  143. let fromDocument = CPDFDocument(url: self._fromFilePath)
  144. if let data = fromDocument?.isLocked, data {
  145. fromDocument?.unlock(withPassword: self._fromFilePassword ?? "")
  146. }
  147. self.progress.isHidden = false
  148. self.cancelButton.isEnabled = false
  149. self.insertButton.isEnabled = false
  150. self.progress.startAnimation(nil)
  151. var pages: [CPDFPage] = []
  152. var indexs = IndexSet()
  153. if (self.blankButton.state == .on) {
  154. let page = CPDFPage()
  155. page.setBounds(NSMakeRect(0, 0, 588, 832), for: .cropBox)
  156. pages.append(page)
  157. } else {
  158. if (self.outputFolderText.stringValue.isEmpty) {
  159. KMAlertTool.runModelForMainThread(message: KMLocalizedString("Select a File"))
  160. self.progress.isHidden = true
  161. self.cancelButton.isEnabled = true
  162. self.insertButton.isEnabled = true
  163. self.progress.stopAnimation(nil)
  164. return
  165. }
  166. var fileAttribute = self._fileAttri
  167. if fileAttribute == nil {
  168. fileAttribute = KMFileAttribute()
  169. self._fileAttri = fileAttribute
  170. fileAttribute?.password = self._fromFilePassword ?? ""
  171. fileAttribute?.filePath = self.outputFolderText.stringValue
  172. }
  173. let item = self.pageRangeBox.indexOfSelectedItem
  174. if (0 == item) {
  175. fileAttribute?.bAllPage = true
  176. } else if(1 == item){
  177. fileAttribute?.bAllPage = false
  178. fileAttribute?.pagesType = .odd
  179. let tDocument = CPDFDocument(url: URL(fileURLWithPath: fileAttribute?.filePath ?? ""))
  180. var tPagesString = ""
  181. for i in 0 ..< Int(tDocument?.pageCount ?? 0) {
  182. if (i%2 == 0) {
  183. if (tPagesString.isEmpty) {
  184. tPagesString.append("\(i+1)")
  185. } else {
  186. tPagesString.append(",\(i+1)")
  187. }
  188. }
  189. }
  190. fileAttribute?.pagesString = tPagesString
  191. } else if (2 == item){
  192. fileAttribute?.bAllPage = false
  193. fileAttribute?.pagesType = .even
  194. let tDocument = CPDFDocument(url: URL(fileURLWithPath: fileAttribute?.filePath ?? ""))
  195. var tPagesString = ""
  196. for i in 0 ..< Int(tDocument?.pageCount ?? 0) {
  197. if (i%2 == 1) {
  198. if (tPagesString.isEmpty) {
  199. tPagesString.append("\(i+1)")
  200. } else {
  201. tPagesString.append(",\(i+1)")
  202. }
  203. }
  204. }
  205. fileAttribute?.pagesString = tPagesString
  206. } else {
  207. fileAttribute?.bAllPage = false
  208. fileAttribute?.pagesType = .custom
  209. fileAttribute?.pagesString = self.pageRangeBox.stringValue
  210. }
  211. if let data = fileAttribute?.fetchSelectPages().isEmpty, data {
  212. KMAlertTool.runModelForMainThread(message: String(format: "%@ %@", fileAttribute?.filePath.lastPathComponent ?? "", KMLocalizedString("Invalid page range or the page number is out of range. Please try again.")))
  213. self.progress.isHidden = true
  214. self.cancelButton.isEnabled = true
  215. self.insertButton.isEnabled = true
  216. self.progress.stopAnimation(nil)
  217. return
  218. } else {
  219. let insertPDF = CPDFDocument(url: URL(fileURLWithPath: self.outputFolderText.stringValue))
  220. if let data = insertPDF?.isLocked, data {
  221. insertPDF?.unlock(withPassword: self._fromFilePassword ?? "")
  222. }
  223. for number in fileAttribute?.fetchSelectPages() ?? [] {
  224. if let page = insertPDF?.page(at: UInt(number-1))?.copy() as? CPDFPage {
  225. pages.append(page)
  226. indexs.insert(number-1)
  227. }
  228. }
  229. }
  230. }
  231. var index = 0
  232. if (self.locationFirstButton.state == .on) {
  233. index = 0
  234. } else if (self.locationLastButton.state == .on) {
  235. index = Int(self._pdfDocument?.pageCount ?? 0)
  236. } else {
  237. index = Int(self.pagesText.stringValue) ?? 0
  238. if (1 == self.locationRangePopUpButton.indexOfSelectedItem) {
  239. index = index - 1
  240. }
  241. }
  242. for page in pages {
  243. self._insertPages.append(page)
  244. }
  245. self._insertPageIndex = index
  246. self.progress.isHidden = true
  247. self.cancelButton.isEnabled = true
  248. self.insertButton.isEnabled = true
  249. self.progress.stopAnimation(nil)
  250. if (self.blankButton.state == .on) { // 插入空白页
  251. _ = self._pdfDocument?.insertBlankPage(pageSize: NSMakeSize(588, 832), at: index)
  252. } else { // 插入文件
  253. let insertPDF = CPDFDocument(url: URL(fileURLWithPath: self.outputFolderText.stringValue))
  254. // let result = self._pdfDocument?.importPages(indexs, from: insertPDF, at: UInt(index))
  255. if let data = insertPDF?.isLocked, data {
  256. insertPDF?.unlock(withPassword: self._fromFilePassword ?? "")
  257. }
  258. let cnt = insertPDF?.pageCount ?? 0
  259. for i in indexs {
  260. if i < cnt {
  261. let page = insertPDF?.page(at: UInt(i))
  262. self._pdfDocument?.insertPageObject(page, at: UInt(index+i))
  263. }
  264. }
  265. }
  266. guard let block = self.callback else {
  267. return
  268. }
  269. block(1, self._pdfDocument, self._password, self._insertPages, self._insertPageIndex)
  270. }
  271. @IBAction func byPageStepperAction(_ sender: AnyObject?) {
  272. self.pagesText.stringValue = "\(self.byPageStepper.integerValue)"
  273. }
  274. @IBAction func buttonItemClicked_InsertType(_ sender: AnyObject?) {
  275. if self.blankButton.isEqual(to: sender) {
  276. self.selectedPathButton.isEnabled = false
  277. self.pageRangeBox.isEnabled = false
  278. self.pageRangeLabel.isHidden = true
  279. self.pageRangeBox.isHidden = true
  280. } else {
  281. self.pageRangeBox.isEnabled = true
  282. self.selectedPathButton.isEnabled = true
  283. self.pageRangeLabel.isHidden = false
  284. self.pageRangeBox.isHidden = false
  285. }
  286. }
  287. @IBAction func buttonItemClicked_Location(_ sender: AnyObject?) {
  288. if self.rangeButton.isEqual(to: sender) {
  289. self.pagesText.isEditable = true
  290. self.locationRangePopUpButton.isEnabled = true
  291. self.byPageStepper.isEnabled = true
  292. } else {
  293. self.pagesText.isEditable = false
  294. self.locationRangePopUpButton.isEnabled = false
  295. self.byPageStepper.isEnabled = false
  296. }
  297. }
  298. @IBAction func buttonItemClicked_Cancel(_ sender: AnyObject?) {
  299. self._pdfDocument = nil
  300. self.own_closeEndSheet()
  301. }
  302. @IBAction func buttonItemClicked_OutputFolder(_ sender: AnyObject?) {
  303. let openPanel = NSOpenPanel()
  304. openPanel.allowedFileTypes = ["pdf"]
  305. openPanel.beginSheetModal(for: self.window!) { result in
  306. if (result == .OK) {
  307. for fileURL in openPanel.urls {
  308. guard let pdfDoc = CPDFDocument(url: fileURL) else {
  309. continue
  310. }
  311. if (pdfDoc.isLocked) {
  312. Self.checkPassword(url: fileURL, type: .owner) { [weak self] success, resultPassword in
  313. if success {
  314. self?._fromFilePassword = resultPassword
  315. self?._fromFilePath = fileURL
  316. self?.outputFolderText.stringValue = self?._fromFilePath?.path ?? ""
  317. self?.pageRangeBox.selectItem(at: 0)
  318. self?.window?.makeFirstResponder(self)
  319. self?.pageRangeBox.isEditable = false
  320. self?.pagesText.stringValue = "1"
  321. self?.insertButton.isEnabled = true
  322. }
  323. }
  324. } else {
  325. self._fromFilePath = fileURL
  326. self.outputFolderText.stringValue = self._fromFilePath?.path ?? ""
  327. self.pageRangeBox.selectItem(at: 0)
  328. self.window?.makeFirstResponder(self)
  329. self.pageRangeBox.isEditable = false
  330. self.pagesText.stringValue = "1"
  331. self.insertButton.isEnabled = true
  332. }
  333. }
  334. }
  335. }
  336. }
  337. @IBAction func after_Action(_ sender: AnyObject?) {
  338. }
  339. @IBAction func before_Action(_ sender: AnyObject?) {
  340. }
  341. @IBAction func comboxClicked_PageRange(_ sender: AnyObject?) {
  342. if (0 == self.pageRangeBox.indexOfSelectedItem ||
  343. 1 == self.pageRangeBox.indexOfSelectedItem ||
  344. 2 == self.pageRangeBox.indexOfSelectedItem) {
  345. self.window?.makeFirstResponder(self)
  346. self.pageRangeBox.isEditable = false
  347. }else{
  348. self.pageRangeBox.stringValue = self.pageRangeBox.stringValue
  349. self.pageRangeBox.isEditable = true
  350. self.window?.makeFirstResponder(self.pageRangeBox)
  351. }
  352. }
  353. }
  354. extension KMPDFInsertWindowController: NSTextFieldDelegate {
  355. func controlTextDidChange(_ obj: Notification) {
  356. if self.pagesText.isEqual(to: obj.object) {
  357. let pageNum = Int(self.pagesText.stringValue) ?? 0
  358. if (pageNum <= 0) {
  359. self.pagesText.stringValue = "1"
  360. self.byPageStepper.integerValue = 1
  361. } else if (pageNum > Int(self.byPageStepper.maxValue)) {
  362. self.pagesText.stringValue = String(format: "%.0f", self.byPageStepper.maxValue)
  363. self.byPageStepper.integerValue = Int(self.byPageStepper.maxValue)
  364. } else {
  365. self.byPageStepper.integerValue = pageNum
  366. }
  367. }
  368. }
  369. }