// // KMPDFInsertWindowController.swift // PDF Reader Pro // // Created by tangchao on 2023/12/7. // import Cocoa class KMPDFInsertWindowController: KMBaseWindowController { @IBOutlet weak var progress: NSProgressIndicator! @IBOutlet weak var pageCountLabel: NSTextField! @IBOutlet weak var insertTypeLabel: NSTextField! @IBOutlet weak var locationLabel: NSTextField! @IBOutlet weak var pageRangeLabel: NSTextField! @IBOutlet weak var pageLabel: NSTextField! @IBOutlet weak var pagesText: NSTextField! @IBOutlet weak var outputFolderText: NSTextField! @IBOutlet weak var blankButton: NSButton! @IBOutlet weak var outputFolderButton: NSButton! @IBOutlet weak var locationFirstButton: NSButton! @IBOutlet weak var locationLastButton: NSButton! @IBOutlet weak var rangeButton: NSButton! @IBOutlet weak var insertButton: NSButton! @IBOutlet weak var cancelButton: NSButton! @IBOutlet weak var selectedPathButton: NSButton! @IBOutlet weak var pageRangeBox: NSComboBox! @IBOutlet weak var byPageStepper: NSStepper! @IBOutlet weak var fromBackView: NSView! @IBOutlet weak var insertBox: NSBox! @IBOutlet weak var whereInsertBox: NSBox! @IBOutlet weak var insertLabel: NSTextField! @IBOutlet weak var whereInsertLabel: NSTextField! @IBOutlet weak var locationRangePopUpButton: NSPopUpButton! var insertLocation: Int = 0 var currentPage: Int = 0 private var _pdfDocument: CPDFDocument? private var _type: KMPDFEditInsertType = .management private var _insertPages: [CPDFPage] = [] private var _fromFilePath: URL? private var _password: String? private var _fromFilePassword: String? private var _insertPageIndex = 0 private var _fileAttri: KMFileAttribute? var callback: KMCommonClickBlock? convenience init(document: CPDFDocument) { self.init(windowNibName: "KMPDFInsertWindowController") self._type = .pageEdit self._pdfDocument = document } convenience init(fileURL documentPath: URL) { self.init(windowNibName: "KMPDFInsertWindowController") self._type = .management self.currentPage = 1 self._pdfDocument = CPDFDocument(url: documentPath) } override func windowDidLoad() { super.windowDidLoad() self._insertPages = [] self.fromBackView.wantsLayer = true self.fromBackView.layer?.borderWidth = 0.8 self.fromBackView.layer?.cornerRadius = 2.0 var viewColor = NSColor.white var viewborderColor = NSColor(red: 195.0/255.0, green: 195.0/255.0, blue: 195.0/255.0, alpha: 1) var textColor = NSColor(red: 51.0/255.0, green: 51.0/255.0, blue: 51.0/255.0, alpha: 1) if KMAppearance.isDarkMode() { viewColor = NSColor(red: 101.0/255.0, green: 101.0/255.0, blue: 101.0/255.0, alpha: 1) viewborderColor = .clear textColor = .white } self.fromBackView.layer?.backgroundColor = viewColor.cgColor self.fromBackView.layer?.borderColor = viewborderColor.cgColor self.outputFolderText.textColor = textColor self.selectedPathButton.title = KMLocalizedString("Choose...", nil) self.insertLabel.stringValue = KMLocalizedString("Insert",nil) self.whereInsertLabel.stringValue = KMLocalizedString("Where to insert?",nil) self.pageRangeLabel.stringValue = KMLocalizedString("Page Range:", nil) self.pageLabel.stringValue = KMLocalizedString("Page", nil) self.selectedPathButton.isEnabled = false self.progress.isHidden = true self.pageRangeBox.isEditable = false self.outputFolderText.isEditable = false self.pagesText.isEditable = false self.byPageStepper.isEnabled = false self.pageRangeLabel.isHidden = true self.pageRangeBox.isHidden = true self.blankButton.title = KMLocalizedString("Blank Page", nil) self.locationFirstButton.title = KMLocalizedString("First", nil) self.locationLastButton.title = KMLocalizedString("Last", nil) self.outputFolderButton.title = KMLocalizedString("From PDF", nil) self.cancelButton.title = KMLocalizedString("Cancel", nil) self.insertButton.title = KMLocalizedString("Insert", nil) self.pagesText.formatter = TextFieldFormatter() self.pagesText.delegate = self self.pageRangeBox.addItem(withObjectValue: KMLocalizedString("All Pages", nil)) self.pageRangeBox.addItem(withObjectValue: KMLocalizedString("Odd Pages Only", nil)) self.pageRangeBox.addItem(withObjectValue: KMLocalizedString("Even Pages Only", nil)) self.pageRangeBox.addItem(withObjectValue: KMLocalizedString("e.g. 1,3-5,10", nil)) (self.pageRangeBox.cell as? NSComboBoxCell)?.placeholderString = KMLocalizedString("e.g. 1,3-5,10", nil) self.pageRangeBox.selectItem(at: 0) let menu = NSMenu() _ = menu.addItem(title: KMLocalizedString("After", nil), action: #selector(after_Action), target: self) _ = menu.addItem(title: KMLocalizedString("Before", nil), action: #selector(before_Action), target: self) self.locationRangePopUpButton.menu = menu self.outputFolderText.placeholderString = KMLocalizedString("Select a File", nil) self.pageRangeBox.isEnabled = false self.locationRangePopUpButton.isEnabled = false if let data = self._pdfDocument?.isLocked, data { Self.checkPassword(url: self._pdfDocument!.documentURL, type: .owner) { [weak self] success, resultPassword in if success { self?._pdfDocument?.unlock(withPassword: resultPassword) self?._password = resultPassword self?.pageCountLabel.stringValue = "\(self?._pdfDocument?.pageCount ?? 0)" self?.byPageStepper.minValue = 1 self?.byPageStepper.maxValue = Double(self?.pdfDocument?.pageCount ?? 1) } } } else { self.byPageStepper.minValue = 1.0 self.byPageStepper.maxValue = Double(self._pdfDocument?.pageCount ?? 0) self.pageCountLabel.stringValue = String(format: "/%ld", self._pdfDocument?.pageCount ?? 0) } if (self.insertLocation == 2) { self.locationLastButton.state = .on } else if (self.insertLocation == 3) { self.rangeButton.state = .on self.locationRangePopUpButton.isEnabled = true self.pagesText.isEditable = true self.byPageStepper.isEnabled = true } else { self.locationFirstButton.state = .on } self.pagesText.stringValue = String(format: "%ld", self.currentPage) self.byPageStepper.integerValue = Int(self.pagesText.stringValue) ?? 0 } @IBAction func buttonItemClicked_Insert(_ sender: AnyObject?) { if let data = self._pdfDocument?.isLocked, data { self._pdfDocument?.unlock(withPassword: self._password ?? "") } let fromDocument = CPDFDocument(url: self._fromFilePath) if let data = fromDocument?.isLocked, data { fromDocument?.unlock(withPassword: self._fromFilePassword ?? "") } self.progress.isHidden = false self.cancelButton.isEnabled = false self.insertButton.isEnabled = false self.progress.startAnimation(nil) var pages: [CPDFPage] = [] var indexs = IndexSet() if (self.blankButton.state == .on) { let page = CPDFPage() page.setBounds(NSMakeRect(0, 0, 588, 832), for: .cropBox) pages.append(page) } else { if (self.outputFolderText.stringValue.isEmpty) { KMAlertTool.runModelForMainThread(message: KMLocalizedString("Select a File", nil)) self.progress.isHidden = true self.cancelButton.isEnabled = true self.insertButton.isEnabled = true self.progress.stopAnimation(nil) return } var fileAttribute = self._fileAttri if fileAttribute == nil { fileAttribute = KMFileAttribute() self._fileAttri = fileAttribute fileAttribute?.password = self._fromFilePassword ?? "" fileAttribute?.filePath = self.outputFolderText.stringValue } let item = self.pageRangeBox.indexOfSelectedItem if (0 == item) { fileAttribute?.bAllPage = true } else if(1 == item){ fileAttribute?.bAllPage = false fileAttribute?.pagesType = .odd let tDocument = CPDFDocument(url: URL(fileURLWithPath: fileAttribute?.filePath ?? "")) var tPagesString = "" for i in 0 ..< Int(tDocument?.pageCount ?? 0) { if (i%2 == 0) { if (tPagesString.isEmpty) { tPagesString.append("\(i+1)") } else { tPagesString.append(",\(i+1)") } } } fileAttribute?.pagesString = tPagesString } else if (2 == item){ fileAttribute?.bAllPage = false fileAttribute?.pagesType = .even let tDocument = CPDFDocument(url: URL(fileURLWithPath: fileAttribute?.filePath ?? "")) var tPagesString = "" for i in 0 ..< Int(tDocument?.pageCount ?? 0) { if (i%2 == 1) { if (tPagesString.isEmpty) { tPagesString.append("\(i+1)") } else { tPagesString.append(",\(i+1)") } } } fileAttribute?.pagesString = tPagesString } else { fileAttribute?.bAllPage = false fileAttribute?.pagesType = .custom fileAttribute?.pagesString = self.pageRangeBox.stringValue } if let data = fileAttribute?.fetchSelectPages().isEmpty, data { KMAlertTool.runModelForMainThread(message: String(format: "%@ %@", fileAttribute?.filePath.lastPathComponent ?? "", KMLocalizedString("Invalid page range or the page number is out of range. Please try again.", nil))) self.progress.isHidden = true self.cancelButton.isEnabled = true self.insertButton.isEnabled = true self.progress.stopAnimation(nil) return } else { let insertPDF = CPDFDocument(url: URL(fileURLWithPath: self.outputFolderText.stringValue)) if let data = insertPDF?.isLocked, data { insertPDF?.unlock(withPassword: self._fromFilePassword ?? "") } for number in fileAttribute?.fetchSelectPages() ?? [] { if let page = insertPDF?.page(at: UInt(number-1)).copy() as? CPDFPage { pages.append(page) indexs.insert(number-1) } } } } var index = 0 if (self.locationFirstButton.state == .on) { index = 0 } else if (self.locationLastButton.state == .on) { index = Int(self._pdfDocument?.pageCount ?? 0) } else { index = Int(self.pagesText.stringValue) ?? 0 if (1 == self.locationRangePopUpButton.indexOfSelectedItem) { index = index - 1 } } for page in pages { self._insertPages.append(page) } self._insertPageIndex = index self.progress.isHidden = true self.cancelButton.isEnabled = true self.insertButton.isEnabled = true self.progress.stopAnimation(nil) if (self.blankButton.state == .on) { // 插入空白页 _ = self._pdfDocument?.insertBlankPage(pageSize: NSMakeSize(588, 832), at: index) } else { // 插入文件 let insertPDF = CPDFDocument(url: URL(fileURLWithPath: self.outputFolderText.stringValue)) // let result = self._pdfDocument?.importPages(indexs, from: insertPDF, at: UInt(index)) if let data = insertPDF?.isLocked, data { insertPDF?.unlock(withPassword: self._fromFilePassword ?? "") } let cnt = insertPDF?.pageCount ?? 0 for i in indexs { if i < cnt { let page = insertPDF?.page(at: UInt(i)) self._pdfDocument?.insertPageObject(page, at: UInt(index+i)) } } } guard let block = self.callback else { return } block(1, self._pdfDocument, self._password, self._insertPages, self._insertPageIndex) } @IBAction func byPageStepperAction(_ sender: AnyObject?) { self.pagesText.stringValue = "\(self.byPageStepper.integerValue)" } @IBAction func buttonItemClicked_InsertType(_ sender: AnyObject?) { if self.blankButton.isEqual(to: sender) { self.selectedPathButton.isEnabled = false self.pageRangeBox.isEnabled = false self.pageRangeLabel.isHidden = true self.pageRangeBox.isHidden = true } else { self.pageRangeBox.isEnabled = true self.selectedPathButton.isEnabled = true self.pageRangeLabel.isHidden = false self.pageRangeBox.isHidden = false } } @IBAction func buttonItemClicked_Location(_ sender: AnyObject?) { if self.rangeButton.isEqual(to: sender) { self.pagesText.isEditable = true self.locationRangePopUpButton.isEnabled = true self.byPageStepper.isEnabled = true } else { self.pagesText.isEditable = false self.locationRangePopUpButton.isEnabled = false self.byPageStepper.isEnabled = false } } @IBAction func buttonItemClicked_Cancel(_ sender: AnyObject?) { self._pdfDocument = nil self.km_quick_endSheet() } @IBAction func buttonItemClicked_OutputFolder(_ sender: AnyObject?) { let openPanel = NSOpenPanel() openPanel.allowedFileTypes = ["pdf"] openPanel.beginSheetModal(for: self.window!) { result in if (result == .OK) { for fileURL in openPanel.urls { guard let pdfDoc = CPDFDocument(url: fileURL) else { continue } if (pdfDoc.isLocked) { Self.checkPassword(url: fileURL, type: .owner) { [weak self] success, resultPassword in if success { self?._fromFilePassword = resultPassword self?._fromFilePath = fileURL self?.outputFolderText.stringValue = self?._fromFilePath?.path ?? "" self?.pageRangeBox.selectItem(at: 0) self?.window?.makeFirstResponder(self) self?.pageRangeBox.isEditable = false self?.pagesText.stringValue = "1" self?.insertButton.isEnabled = true } } } else { self._fromFilePath = fileURL self.outputFolderText.stringValue = self._fromFilePath?.path ?? "" self.pageRangeBox.selectItem(at: 0) self.window?.makeFirstResponder(self) self.pageRangeBox.isEditable = false self.pagesText.stringValue = "1" self.insertButton.isEnabled = true } } } } } @IBAction func after_Action(_ sender: AnyObject?) { } @IBAction func before_Action(_ sender: AnyObject?) { } @IBAction func comboxClicked_PageRange(_ sender: AnyObject?) { if (0 == self.pageRangeBox.indexOfSelectedItem || 1 == self.pageRangeBox.indexOfSelectedItem || 2 == self.pageRangeBox.indexOfSelectedItem) { self.window?.makeFirstResponder(self) self.pageRangeBox.isEditable = false }else{ self.pageRangeBox.stringValue = self.pageRangeBox.stringValue self.pageRangeBox.isEditable = true self.window?.makeFirstResponder(self.pageRangeBox) } } } extension KMPDFInsertWindowController: NSTextFieldDelegate { func controlTextDidChange(_ obj: Notification) { if self.pagesText.isEqual(to: obj.object) { let pageNum = Int(self.pagesText.stringValue) ?? 0 if (pageNum <= 0) { self.pagesText.stringValue = "1" self.byPageStepper.integerValue = 1 } else if (pageNum > Int(self.byPageStepper.maxValue)) { self.pagesText.stringValue = String(format: "%.0f", self.byPageStepper.maxValue) self.byPageStepper.integerValue = Int(self.byPageStepper.maxValue) } else { self.byPageStepper.integerValue = pageNum } } } }