// // SplitWindowController.swift // PDF Master // // Created by tangchao on 2023/11/14. // import Cocoa class SplitWindowController: NSWindowController { /* @protocol SplitDelegate @optional - (void)didFinshedSplitWithURL:(NSURL*)url; @end @property (nonatomic,assign) id splitDelegate; */ var fileAttribute: KMFileAttribute? //转圈提示 @IBOutlet var progress: NSProgressIndicator! //分割后文档存储所在文件夹名称TextField容器View @IBOutlet var nameView: NSView! //分割后文档存储所在文件夹名称 TextField @IBOutlet var partFileNameLabel: NSTextField! @IBOutlet var originalFileButton: NSButton! //分割提示 Label @IBOutlet var splitLabel: NSTextField! @IBOutlet var splitMethodBox: NSBox! @IBOutlet var fileNameBox: NSBox! @IBOutlet var exampleLabel: NSTextField! //平均页数分割单位Pages Label @IBOutlet var pagesLabel: NSTextField! //平均分割为多少个PDF文件单位 Label @IBOutlet var filesLabel: NSTextField! //导出目录提示 Label @IBOutlet var labelingLabel: NSTextField! //按页分割页数输入 TextField @IBOutlet var byPageText: NSTextField! //按文档数量均分文档个数输入 TextField @IBOutlet var byFileText: NSTextField! //文档名称分割符输入 TextField @IBOutlet var separatorText: NSTextField! //新增文档命名拼接字段输入 TextField @IBOutlet var renameText: NSTextField! //按页分割 Button @IBOutlet var byPageButton: NSButton! //按分割文档个数分割 Button @IBOutlet var byFileButton: NSButton! //手动输入页分割 Button @IBOutlet var pageFromButton: NSButton! //取消 Button @IBOutlet var cancelButton: NSButton! //分割 Button @IBOutlet var splitButton: NSButton! //按文档个数分割,文档个数步进器 @IBOutlet var byFileStepper: NSStepper! //按页均分分割,单个文档页数步进器 @IBOutlet var byPageStepper: NSStepper! //新增文件夹名称拼接输入选择 Button @IBOutlet var renameButton: NSButton! //新增文件夹名字拼接 Button @IBOutlet var separatorButton: NSButton! //页面选择 ComboBox @IBOutlet var pageRangeComboBox: NSComboBox! @IBOutlet var splitMethodLabel: NSTextField! @IBOutlet var fileNameLabel: NSTextField! private var _fileURL: URL? private var _PDFDocument: CPDFDocument? private var _isSuccessfully = false /* //密码 @property (nonatomic,retain) NSString *password; */ //分割样式 private var _splitType: Int = 0 convenience init(document: CPDFDocument) { self.init(windowNibName: "SplitWindowController") self.fileAttribute = KMFileAttribute() self._fileURL = document.documentURL self._PDFDocument = document self.fileAttribute?.pdfDocument = document // if ([IAPProductsManager defaultManager].isAvailableAllFunction) { // self.splitType = 3; // } } convenience init(fileURL documentPath: URL) { self.init(windowNibName: "SplitWindowController") self.fileAttribute = KMFileAttribute() self._fileURL = documentPath self._PDFDocument = CPDFDocument(url: documentPath) } override func windowDidLoad() { super.windowDidLoad() self._localizedLanguage() self._setInputRange() self._configuViews() } @IBAction func byPageStepperAction(_ sender: AnyObject) { self.byPageText.stringValue = String(format: "%ld", self.byPageStepper.integerValue) } @IBAction func byFileStepperAction(_ sender: AnyObject) { self.byFileText.stringValue = String(format: "%ld", self.byFileStepper.integerValue) } @IBAction func buttonItemClicked_Cancel(_ sender: AnyObject) { self.window?.sheetParent?.endSheet(self.window!) } @IBAction func buttonItemClicked_ByPage(_ sender: AnyObject) { self.byFileButton.state = .off self.pageFromButton.state = .off self.byPageText.isEditable = true self.pageRangeComboBox.isEditable = false self.pageRangeComboBox.isEditable = false self.window?.makeFirstResponder(self) self.pageRangeComboBox.isEnabled = false self.byFileText.isEditable = false self.byFileStepper.isEnabled = false self.byPageStepper.isEnabled = false self.fileAttribute?.bAllPage = true } @IBAction func buttonItemClicked_ByFile(_ sender: AnyObject) { self.byPageButton.state = .off self.pageFromButton.state = .off self.byPageText.isEditable = false self.pageRangeComboBox.isEditable = false self.pageRangeComboBox.isSelectable = false self.window?.makeFirstResponder(self) self.pageRangeComboBox.isEnabled = false self.byFileText.isEditable = true self.byFileStepper.isEnabled = true self.byPageStepper.isEnabled = false self.fileAttribute?.bAllPage = true } @IBAction func buttonItemClicked_ByRange(_ sender: AnyObject) { // if (![IAPProductsManager defaultManager].isAvailableAllFunction) { // _pageFromButton.state = 0; // KMToolCompareWindowController * vc = [KMToolCompareWindowController toolCompareWithType:KMCompareWithToolType_PageEdit setSelectIndex:1]; // [vc showWindow:nil]; // return; // } self.byFileButton.state = .off self.byPageButton.state = .off self.byPageText.isEditable = false self.pageRangeComboBox.isEnabled = true if (self.pageRangeComboBox.indexOfSelectedItem == 2) { self.pageRangeComboBox.isSelectable = true self.pageRangeComboBox.isEditable = true self.pageRangeComboBox.stringValue = "" self.window?.makeFirstResponder(self.pageRangeComboBox) } self.byFileText.isEditable = false self.byFileStepper.isEnabled = false self.byPageStepper.isEnabled = false self.fileAttribute?.bAllPage = false } @IBAction func buttonItemClicked_Split(_ sender: AnyObject) { var fileAttribute: KMFileAttribute? if (self.pageFromButton.state == .on) { //选择page fileAttribute = self.fileAttribute fileAttribute?.filePath = self._fileURL?.path ?? "" fileAttribute?.bAllPage = false if self.pageRangeComboBox.stringValue == KMLocalizedString("Odd Pages Only", nil) { var tPagesString = "" for i in 0 ..< self._PDFDocument!.pageCount { if (i%2 == 0) { if (tPagesString.isEmpty) { tPagesString.append("\(i+1)") }else{ tPagesString.append(",\(i+1)") } } } fileAttribute?.pagesString = tPagesString } else if self.pageRangeComboBox.stringValue == KMLocalizedString("Even Pages Only", nil) { var tPagesString = "" for i in 0 ..< self._PDFDocument!.pageCount { if (i%2 == 1) { if (tPagesString.isEmpty) { tPagesString.append("\(i+1)") }else{ tPagesString.append(",\(i+1)") } } } fileAttribute?.pagesString = tPagesString } else { fileAttribute?.pagesString = self.pageRangeComboBox.stringValue } if let data = fileAttribute?.fetchSelectPages().isEmpty, data { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = KMLocalizedString("Invalid page range or the page number is out of range. Please try again.", nil) alert.runModal() return } } let panel = NSOpenPanel() panel.canChooseFiles = false panel.canChooseDirectories = true panel.canCreateDirectories = true panel.beginSheetModal(for: self.window!) { result in if (result == .OK) { let outputURL = panel.urls.first var tFolderPath = outputURL!.path var index = 0 let folderName = self.partFileNameLabel.stringValue.deletingPathExtension.lastPathComponent // String(format: "%@/", <#T##CVarArg...#>) var folderPath = "\(tFolderPath)" + "/" + "\(folderName)" //创建目录 while FileManager.default.fileExists(atPath: folderPath) { index += 1 folderPath = "\(tFolderPath)" + "/" + "\(folderName)_\(index)" } tFolderPath = folderPath try?FileManager.default.createDirectory(atPath: tFolderPath, withIntermediateDirectories: true) // if let data = { // let alert = NSAlert() // alert.alertStyle = .critical // alert.messageText = KMLocalizedString("Failed to split!", nil) // alert.runModal() // return // } self.progress.isHidden = false self.cancelButton.isEnabled = false self.splitButton.isEnabled = false self.progress.startAnimation(nil) if (self.byPageButton.state == .on) { let index = self.byPageStepper.integerValue; DispatchQueue.global().async { let successArray = self._PDFDocument?.splitByPagesWith(index, folerPath: tFolderPath, fileName: folderName) DispatchQueue.main.async { self.progress.isHidden = true self.cancelButton.isEnabled = true self.splitButton.isEnabled = true if (successArray?.isEmpty == false) { let alert = NSAlert() alert.messageText = KMLocalizedString("Splitting completed. Tap 'OK' to open the output folder.", nil) alert.addButton(withTitle: KMLocalizedString("OK",nil)) let response = alert.runModal() if (response == .alertFirstButtonReturn ) { self.window?.sheetParent?.endSheet(self.window!) DispatchQueue.main.asyncAfter(deadline: .now()+0.5) { let filePath = successArray?.first self._viewFileAtFinder(filePath!) } } } else { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = KMLocalizedString("Failed to split!", nil) let response = alert.runModal() if (response == .alertFirstButtonReturn ) { self.window?.sheetParent?.endSheet(self.window!) } } } } } else if (self.byFileButton.state == .on) { let dex = self.byFileStepper.integerValue DispatchQueue.global().async { let successArray = self._PDFDocument?.splitByPagesWith(dex, folerPath: tFolderPath, fileName: folderName) DispatchQueue.main.async { self.progress.isHidden = true self.cancelButton.isEnabled = true self.splitButton.isEnabled = true if (successArray?.isEmpty == false) { let alert = NSAlert() alert.messageText = KMLocalizedString("Splitting completed. Tap 'OK' to open the output folder.", nil) alert.addButton(withTitle: KMLocalizedString("OK",nil)) let response = alert.runModal() if (response == .alertFirstButtonReturn) { self.window?.sheetParent?.endSheet(self.window!) DispatchQueue.main.asyncAfter(deadline: .now()+0.5) { let filePath = successArray?.first self._viewFileAtFinder(filePath!) } } }else{ let alert = NSAlert() alert.alertStyle = .critical alert.messageText = KMLocalizedString("Failed to split!", nil) let response = alert.runModal() if (response == .alertFirstButtonReturn) { self.window?.sheetParent?.endSheet(self.window!) } } } } } else { DispatchQueue.global().async { [self] in var pdfDocument1 = CPDFDocument() var pdfDocument2 = CPDFDocument() for i in 0 ..< self._PDFDocument!.pageCount { var isSelected = false for number in fileAttribute!.fetchSelectPages() { if number.intValue == i+1 { isSelected = true let page = self._PDFDocument?.page(at: i).copy() pdfDocument1?.insertPageObject(page as! CPDFPage, at: pdfDocument1!.pageCount) } } if (!isSelected) { let page = self._PDFDocument?.page(at: i).copy() pdfDocument2?.insertPageObject(page as! CPDFPage, at: pdfDocument2!.pageCount) } } if (pdfDocument1!.pageCount > 0) { let tpath = "\(tFolderPath)\\\(folderName) 1.pdf" _isSuccessfully = pdfDocument1?.write(toFile:tpath) ?? false } if (pdfDocument2!.pageCount > 0) { let tPath = "\(tFolderPath)\\\(folderName) 2.pdf" pdfDocument2?.write(toFile: tPath) } DispatchQueue.main.async { self.progress.isHidden = true self.cancelButton.isEnabled = true self.splitButton.isEnabled = true if (_isSuccessfully) { // if ([_splitDelegate respondsToSelector:@selector(didFinshedSplitWithURL:)]) { // [_splitDelegate didFinshedSplitWithURL:_fileURL]; // } let alert = NSAlert() alert.messageText = KMLocalizedString("Splitting completed. Tap 'OK' to open the output folder.", nil) alert.addButton(withTitle: KMLocalizedString("OK",nil)) let response = alert.runModal() if (response == .alertFirstButtonReturn) { self.window?.sheetParent?.endSheet(self.window!) DispatchQueue.main.asyncAfter(deadline: .now()+0.5) { let filePath = "\(tFolderPath)\\\(folderName) 1.pdf" self._viewFileAtFinder(filePath) } } }else{ let alert = NSAlert() alert.alertStyle = .critical alert.messageText = KMLocalizedString("Failed to split!", nil) let response = alert.runModal() if (response == .alertFirstButtonReturn) { self.window?.sheetParent?.endSheet(self.window!) } } } } } } } } @IBAction func buttonItemClicked_OriginalName(_ sender: AnyObject) { self._updateSplitFileName() } @IBAction func buttonItemClicked_Rename(_ sender: AnyObject) { self._updateSplitFileName() } @IBAction func comboBoxClicked_PageRange(_ sender: NSComboBox) { if (sender.indexOfSelectedItem == 0) { //奇数页 sender.isEditable = false sender.isSelectable = false self.window?.makeFirstResponder(self) } else if (sender.indexOfSelectedItem == 1){ //偶数页 sender.isEditable = false sender.isSelectable = false self.window?.makeFirstResponder(self) } else { //手动输入页数 sender.isEditable = true sender.isSelectable = true self.pageRangeComboBox.stringValue = self.pageRangeComboBox.stringValue (sender.cell as? NSComboBoxCell)?.placeholderString = KMLocalizedString("e.g. 1,3-5,10", nil) self.window?.makeFirstResponder(sender) } } } // MARK: - Private Methods extension SplitWindowController { private func _localizedLanguage() { self.splitMethodLabel.stringValue = KMLocalizedString("Split Methods", nil) // self.splitLabel.stringValue = KMLocalizedString("Split Methods", nil) self.pagesLabel.stringValue = KMLocalizedString("page(s)", nil) self.filesLabel.stringValue = KMLocalizedString("PDF file(s)", nil) // self.labelingLabel.stringValue = KMLocalizedString("File Naming", nil) self.fileNameLabel.stringValue = KMLocalizedString("File Naming", nil) self.exampleLabel.stringValue = KMLocalizedString("example", nil) self.byPageButton.title = KMLocalizedString("Split by every", nil) self.byFileButton.title = KMLocalizedString("Split averagely to", nil) self.pageFromButton.title = KMLocalizedString("Split by page range", nil) self.cancelButton.title = KMLocalizedString("Cancel", nil) self.splitButton.title = KMLocalizedString("Split", nil) self.originalFileButton.title = KMLocalizedString("Keep the current file name in front of labels", nil) self.renameButton.title = KMLocalizedString("Label", nil) self.separatorButton.title = KMLocalizedString("Separator", nil) self.byPageButton.toolTip = KMLocalizedString("Split by every", nil) self.byFileButton.toolTip = KMLocalizedString("Split averagely to", nil) self.pageFromButton.toolTip = KMLocalizedString("Split by page range", nil) self.originalFileButton.toolTip = KMLocalizedString("Keep the current file name in front of labels", nil) } private func _setInputRange() { if let data = self._PDFDocument?.isLocked, data { // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // PasswordWindowController *com = [[PasswordWindowController alloc] initWithWindowNibName:@"PasswordWindowController"]; // com.fileURL = _fileURL; // [com beginSheetModalForWindow:self.window completionHandler:^(NSString *password) { // if (password) { // self.password = password; // [_PDFDocument unlockWithPassword:password]; // NSInteger pageNumber = [_PDFDocument pageCount]; // NSString *pdfName = [[[[_PDFDocument documentURL] path] lastPathComponent] stringByDeletingPathExtension]; // _byFileStepper.maxValue = pageNumber; // _byPageStepper.maxValue = pageNumber; // // _partFileNameLabel.stringValue = [[NSString stringWithFormat:@"%@%@%@",pdfName,_separatorText.stringValue,_renameText.stringValue] stringByAppendingPathExtension:@"pdf"]; // } else { // [NSApp endSheet:[self window]]; // [[self window] orderOut:self]; // [self release]; // } // }]; // [com release]; // }); } else { let pageNumber = self._PDFDocument?.pageCount ?? 0 let pdfName = self._PDFDocument?.documentURL.deletingPathExtension().path.lastPathComponent ?? "" self.byFileStepper.maxValue = Double(pageNumber) self.byPageStepper.maxValue = Double(pageNumber) if let data = self._PDFDocument?.documentURL.path.isEmpty, data == false { self.partFileNameLabel.stringValue = String(format: "%@%@%@", pdfName, self.separatorText.stringValue, "\(self.renameText.stringValue).pdf") } else { self.partFileNameLabel.stringValue = String(format: "%@%@%@", "Untitled", self.separatorText.stringValue, "\(self.renameText.stringValue).pdf") } } } private func _configuViews() { self.nameView.wantsLayer = true // _nameView.layer.backgroundColor = [KMAppearance KMColor_Layout_L1].CGColor; //初始化ComboBox self.pageRangeComboBox.removeAllItems() let pageRangeArray = [KMLocalizedString("Odd Pages Only", nil), KMLocalizedString("Even Pages Only", nil), KMLocalizedString("e.g. 1,3-5,10", nil)] (self.pageRangeComboBox.cell as? NSComboBoxCell)?.placeholderString = KMLocalizedString("e.g. 1,3-5,10", nil) self.pageRangeComboBox.addItems(withObjectValues: pageRangeArray) self.pageRangeComboBox.selectItem(at: 0) self.pageRangeComboBox.isSelectable = false self.pageRangeComboBox.isEditable = false self.byFileText.isEditable = false self.byFileStepper.isEnabled = false self.byPageText.isEditable = false self.byPageStepper.isEnabled = false if (self._splitType == 3) { self.pageRangeComboBox.selectItem(at: 2) if (self.fileAttribute!.pagesString.isEmpty == false) { self.pageRangeComboBox.stringValue = self.fileAttribute?.pagesString ?? "" self.byPageButton.state = .off self.pageFromButton.state = .on self.pageRangeComboBox.isEnabled = true } else { self.pageRangeComboBox.stringValue = "" self.byPageButton.state = .on self.byPageText.isEditable = true self.pageFromButton.state = .off self.pageRangeComboBox.isEnabled = false } self.pageRangeComboBox.isEditable = true self.pageRangeComboBox.isSelectable = true } else { self.pageRangeComboBox.stringValue = "" self.pageRangeComboBox.isEnabled = false self.byPageText.isEditable = true } self.byPageStepper.minValue = 1.0 self.byFileStepper.minValue = 1.0 self.byPageStepper.integerValue = 1 self.byFileStepper.integerValue = 1 self.renameText.stringValue = "part" self.separatorText.stringValue = "-" self.byPageText.stringValue = "1" self.byFileText.stringValue = "1" self.byPageText.formatter = TextFieldFormatter() self.byFileText.formatter = TextFieldFormatter() self.byPageText.delegate = self self.byFileText.delegate = self self.renameText.delegate = self self.separatorText.delegate = self self.progress.isHidden = true } private func _viewFileAtFinder(_ filePath: String) { let workspace = NSWorkspace.shared let url = URL(fileURLWithPath: filePath) workspace.activateFileViewerSelecting([url]) } private func _updateSplitFileName() { let pdfName = self._PDFDocument?.documentURL.deletingPathExtension().path.lastPathComponent ?? "" var splitPartString = "" var separatorString = "" if (self.renameButton.state == .on) { splitPartString = self.renameText.stringValue } if (self.separatorButton.state == .on) { separatorString = self.separatorText.stringValue } var partName = "" if (self.originalFileButton.state == .on) { if (separatorString.isEmpty == false) { if (partName.isEmpty == false) { partName.append(separatorString) } else { partName = separatorString } } if (splitPartString.isEmpty == false) { if (partName.isEmpty == false) { partName.append(splitPartString) } else { partName = splitPartString } } self.partFileNameLabel.stringValue = String(format: "%@%@.pdf", pdfName, partName) } else { if (splitPartString.isEmpty == false) { if (partName.isEmpty == false) { partName.append(splitPartString) } else { partName = splitPartString } } if (separatorString.isEmpty == false) { if (partName.isEmpty == false) { partName.append(separatorString) } else { partName = separatorString } } self.partFileNameLabel.stringValue = String(format: "%@%@.pdf", partName, pdfName) } } } extension SplitWindowController: NSTextFieldDelegate { func controlTextDidChange(_ obj: Notification) { let textField = obj.object as? NSTextField if (self.byPageText.isEqual(to: textField)) { if let data = Int(textField!.stringValue), data <= 0 { self.byPageText.stringValue = "1" self.byPageStepper.integerValue = 1 } else if (textField!.stringValue.stringToCGFloat() > self.byPageStepper.maxValue){ self.byPageText.stringValue = "\(self.byPageStepper.maxValue)" self.byPageStepper.integerValue = Int(self.byPageStepper.maxValue) } else { self.byPageStepper.integerValue = Int(self.byPageText.stringValue) ?? 0 } } else if (self.byFileText.isEqual(to: textField)){ if let data = Int(textField!.stringValue), data <= 0 { self.byFileText.stringValue = "1" self.byFileStepper.integerValue = 1 }else if (textField!.stringValue.stringToCGFloat() > self.byFileStepper.maxValue){ self.byFileText.stringValue = "\(self.byFileStepper.maxValue)" self.byFileStepper.integerValue = Int(self.byFileStepper.maxValue) }else{ self.byFileStepper.integerValue = Int(self.byFileText.stringValue) ?? 0 } } else if (self.renameText.isEqual(to: textField) || self.separatorText.isEqual(to: textField )) { self._updateSplitFileName() } } }