|
@@ -0,0 +1,786 @@
|
|
|
+//
|
|
|
+// KMBatchOperateLeftViewController.swift
|
|
|
+// PDF Master
|
|
|
+//
|
|
|
+// Created by kdanmobile on 2023/10/26.
|
|
|
+//
|
|
|
+
|
|
|
+import Cocoa
|
|
|
+
|
|
|
+let KMBatchDragType = "KMBatchDragType"
|
|
|
+
|
|
|
+class KMBatchOperateLeftViewController: NSViewController,NSTableViewDelegate,NSTableViewDataSource{
|
|
|
+
|
|
|
+ @IBOutlet var selectFileButton: KMLongerButton!
|
|
|
+
|
|
|
+ @IBOutlet var deleteFileButton: NSButton!
|
|
|
+
|
|
|
+ @IBOutlet var tableView: NSTableView!
|
|
|
+
|
|
|
+ @IBOutlet var indexTableColumn: NSTableColumn!
|
|
|
+
|
|
|
+ @IBOutlet var fileNameTableColumn: NSTableColumn!
|
|
|
+
|
|
|
+ @IBOutlet var pageRangeTableColumn: NSTableColumn!
|
|
|
+
|
|
|
+ @IBOutlet var sizeTableColumn: NSTableColumn!
|
|
|
+
|
|
|
+ @IBOutlet var stateTableColumn: NSTableColumn!
|
|
|
+
|
|
|
+ @IBOutlet var DPIColumn: NSTableColumn!
|
|
|
+
|
|
|
+ @IBOutlet var dimensionsTableColumn: NSTableColumn!
|
|
|
+
|
|
|
+ @IBOutlet var headerOperateView: NSView!
|
|
|
+
|
|
|
+ @IBOutlet var showInFinderMenuItem: NSMenuItem!
|
|
|
+
|
|
|
+ @IBOutlet var deleteMenuItem: NSMenuItem!
|
|
|
+
|
|
|
+ @IBOutlet var blankView: KMBlankView!
|
|
|
+
|
|
|
+ var files: [KMBatchOperateFile] = []
|
|
|
+ var type: KMBatchOperationType?
|
|
|
+ var lockFilePathArr: NSMutableArray?
|
|
|
+ var lockFileIndex: Int = 0
|
|
|
+ var popOver: NSPopover?
|
|
|
+ var progressInt: Int = 0
|
|
|
+
|
|
|
+ override func viewDidLoad() {
|
|
|
+ super.viewDidLoad()
|
|
|
+ NotificationCenter.default.addObserver(self.tableView!, selector: #selector(self.reloadData), name: NSNotification.Name(kNeedChangePageRangeNotification), object: nil)
|
|
|
+ NotificationCenter.default.addObserver(self, selector: #selector(imageToPDFSuccessNotification(aNotification:)), name: NSNotification.Name("KMBatchOperateImageToPDFSuccessNotification"), object: nil)
|
|
|
+ DistributedNotificationCenter.default.addObserver(self, selector: #selector(themeChanged(notification:)), name: NSNotification.Name("AppleInterfaceThemeChangedNotification"), object: nil)
|
|
|
+
|
|
|
+ for i in 0..<self.tableView.tableColumns.count {
|
|
|
+ let column = self.tableView.tableColumns[i]
|
|
|
+ column.headerCell = KMTableHeaderCell(textCell: column.title)
|
|
|
+ }
|
|
|
+
|
|
|
+ self.deleteFileButton.addHoverEffect = true
|
|
|
+
|
|
|
+ self.indexTableColumn.resizingMask = []
|
|
|
+ self.fileNameTableColumn.resizingMask = .autoresizingMask
|
|
|
+ self.pageRangeTableColumn.resizingMask = []
|
|
|
+ self.sizeTableColumn.resizingMask = []
|
|
|
+ self.stateTableColumn.resizingMask = []
|
|
|
+ self.DPIColumn.resizingMask = []
|
|
|
+ self.dimensionsTableColumn.resizingMask = []
|
|
|
+ self.tableView.moveColumn(5, toColumn: 2)
|
|
|
+
|
|
|
+ self.indexTableColumn.title = " \(NSLocalizedString("Index", comment: ""))"
|
|
|
+ self.fileNameTableColumn.title = NSLocalizedString("File Name", comment: "")
|
|
|
+ self.pageRangeTableColumn.title = NSLocalizedString("Page Range", comment: "")
|
|
|
+ self.sizeTableColumn.title = NSLocalizedString("Size", comment: "")
|
|
|
+ self.stateTableColumn.title = NSLocalizedString("Status", comment: "")
|
|
|
+ self.DPIColumn.title = NSLocalizedString("DPI", comment: "")
|
|
|
+ self.dimensionsTableColumn.title = NSLocalizedString("Dimensions", comment: "")
|
|
|
+
|
|
|
+ self.DPIColumn.isHidden = true
|
|
|
+ self.tableView.intercellSpacing = CGSize(width: 0, height: 0)
|
|
|
+ self.tableView.backgroundColor = KMAppearance.Layout.bgColor()
|
|
|
+ self.tableView.allowsColumnReordering = false
|
|
|
+ self.tableView.allowsMultipleSelection = true
|
|
|
+ self.tableView.enclosingScrollView?.borderType = .noBorder
|
|
|
+
|
|
|
+ self.headerOperateView.wantsLayer = true
|
|
|
+
|
|
|
+ self.tableView.registerForDraggedTypes([NSPasteboard.PasteboardType.string,NSPasteboard.PasteboardType.fileURL]) //[KMBatchDragType,NSFilenamesPboardType]
|
|
|
+ self.lockFilePathArr = NSMutableArray()
|
|
|
+ self.lockFileIndex = 0
|
|
|
+ self.progressInt = 0
|
|
|
+
|
|
|
+ self.selectFileButton.title = NSLocalizedString("Add Files", comment: "")
|
|
|
+ self.selectFileButton.wantsLayer = true
|
|
|
+ self.selectFileButton.layer?.borderWidth = 1.0
|
|
|
+ self.selectFileButton.layer?.borderColor = KMAppearance.Interactive.m0Color().cgColor
|
|
|
+ self.selectFileButton.layer?.cornerRadius = 1.0
|
|
|
+ self.selectFileButton.setTitleColor(KMAppearance.Layout.mColor())
|
|
|
+ self.selectFileButton.containerViewController = self
|
|
|
+
|
|
|
+ self.showInFinderMenuItem.title = NSLocalizedString("Show in Finder", comment: "")
|
|
|
+ self.deleteMenuItem.title = NSLocalizedString("Delete", comment: "")
|
|
|
+ self.blankView.wantsLayer = true
|
|
|
+ self.blankView.layer?.backgroundColor = NSColor.clear.cgColor
|
|
|
+ self.blankView.titleLabel.stringValue = NSLocalizedString("Select Files", comment: "")
|
|
|
+ self.blankView.secondTitleLabel.stringValue = NSLocalizedString("Drop files here or Click Add Files at upper left corner. You can drag files to reorder as you need.", comment: "")
|
|
|
+ self.blankView.mouseActionCallBack = { [weak self] mouseType in
|
|
|
+ guard let self = self else { return }
|
|
|
+ if mouseType == .mouseEnter {
|
|
|
+ self.blankView.imageView.image = NSImage(named: "KMImageNameEmptyListHov")
|
|
|
+ } else if mouseType == .mouseExit {
|
|
|
+ self.blankView.imageView.image = NSImage(named: "KMImageNameEmptyListNor")
|
|
|
+ } else if mouseType == .mouseDown {
|
|
|
+ self.blankView.imageView.image = NSImage(named: "KMImageNameEmptyListPre")
|
|
|
+ self.chooseFile()
|
|
|
+ } else if mouseType == .mouseUp {
|
|
|
+ self.blankView.imageView.image = NSImage(named: "KMImageNameEmptyListHov")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ updateViewColor()
|
|
|
+ }
|
|
|
+ @objc func reloadData() {
|
|
|
+ if Thread.isMainThread {
|
|
|
+ tableView.reloadData()
|
|
|
+ } else {
|
|
|
+ DispatchQueue.main.async {
|
|
|
+ self.tableView.reloadData()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @objc func imageToPDFSuccessNotification(aNotification: Notification) {
|
|
|
+ guard let dict = aNotification.userInfo, let isSuccess = dict["isSuccess"] as? Bool else { return }
|
|
|
+ if isSuccess {
|
|
|
+ progressInt = 1
|
|
|
+ } else {
|
|
|
+ progressInt = -1
|
|
|
+ }
|
|
|
+
|
|
|
+ DispatchQueue.main.async {
|
|
|
+ self.tableView.reloadData()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ @objc func themeChanged(notification: Notification) {
|
|
|
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: {
|
|
|
+ self.updateViewColor()
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ func updateViewColor() {
|
|
|
+ self.view.wantsLayer = true
|
|
|
+ if KMAppearance.isDarkMode() {
|
|
|
+ self.headerOperateView.layer?.backgroundColor = NSColor(red: 0.055, green: 0.067, blue: 0.078, alpha: 1).cgColor
|
|
|
+ } else {
|
|
|
+ self.headerOperateView.layer?.backgroundColor = NSColor(red: 0.922, green: 0.925, blue: 0.941, alpha: 1).cgColor
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func chooseFile() {
|
|
|
+#if VERSION_FREE
|
|
|
+ // KMToolCompareWindowController *vc = [KMToolCompareWindowController toolCompareWithType:KMCompareWithToolType_Convert setSelectIndex:1];
|
|
|
+ // [vc showWindow:nil];
|
|
|
+// if !IAPProductsManager.defaultManager().isAvailableAllFunction() {
|
|
|
+// if files.count >= 1 {
|
|
|
+// KMPurchaseCompareWindowController.sharedInstance().showWindow(nil)
|
|
|
+// return
|
|
|
+// }
|
|
|
+// }
|
|
|
+ //展示升级页面
|
|
|
+#endif
|
|
|
+ self.progressInt = 0
|
|
|
+ let panel = NSOpenPanel()
|
|
|
+ if type == .CreatePDF {
|
|
|
+ panel.allowedFileTypes = KMImageToPDFMethod.supportedImageTypes()
|
|
|
+ } else {
|
|
|
+ panel.allowedFileTypes = ["pdf", "PDF"]
|
|
|
+ }
|
|
|
+// if IAPProductsManager.defaultManager().isAvailableAllFunction() {
|
|
|
+ panel.allowsMultipleSelection = true
|
|
|
+ panel.canChooseDirectories = true
|
|
|
+// }
|
|
|
+ panel.canChooseFiles = true
|
|
|
+#if VERSION_FREE
|
|
|
+#else
|
|
|
+ panel.message = NSLocalizedString("To select multiple files press cmd ⌘ button on keyboard and click on the target files one by one.", comment: "")
|
|
|
+#endif
|
|
|
+ panel.beginSheetModal(for: self.view.window!) {
|
|
|
+ (result) in
|
|
|
+ if result.rawValue == NSApplication.ModalResponse.OK.rawValue {
|
|
|
+ var addArray = NSMutableArray()
|
|
|
+ for fileURL in panel.urls {
|
|
|
+ let filePath = fileURL.path
|
|
|
+ var isDirectory = ObjCBool(false)
|
|
|
+ FileManager.default.fileExists(atPath: filePath, isDirectory: &isDirectory)
|
|
|
+ if isDirectory.boolValue {
|
|
|
+ let containFiles = self.fetchAvailableFiles(in: filePath)
|
|
|
+ addArray.add(containFiles)
|
|
|
+ } else {
|
|
|
+ let UTTypeString = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, filePath.extension as CFString, nil)
|
|
|
+ let TypeCFString = UTTypeString as! CFString
|
|
|
+ if self.type == .CreatePDF {
|
|
|
+ if UTTypeConformsTo(TypeCFString, kUTTypeImage) {
|
|
|
+ addArray.add(filePath)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if UTTypeConformsTo(TypeCFString, kUTTypePDF) {
|
|
|
+ addArray.add(filePath)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ self.addFilesToList(addArray: addArray)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ func fetchAvailableFiles(in folderPath: String) -> [String] {
|
|
|
+ var array = NSMutableArray()
|
|
|
+ let subFileArray = (FileManager.default.subpaths(atPath: folderPath)! as NSArray).mutableCopy() as? NSMutableArray
|
|
|
+ for i in 0..<subFileArray!.count {
|
|
|
+ if let path = (folderPath as NSString).appendingPathComponent(subFileArray!.object(at: i) as! String) as String? {
|
|
|
+ if let UTTypeString = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, path.extension as CFString, nil)?.takeRetainedValue() as String? {
|
|
|
+ let TypeCFString = UTTypeString as CFString
|
|
|
+ if self.type == .CreatePDF {
|
|
|
+ if UTTypeConformsTo(TypeCFString, kUTTypeImage) {
|
|
|
+ array.add(path)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if UTTypeConformsTo(TypeCFString, kUTTypePDF) {
|
|
|
+ array.add(path)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return array as! [String]
|
|
|
+ }
|
|
|
+ func addFilesToList(addArray: NSMutableArray) {
|
|
|
+ self.lockFilePathArr!.removeAllObjects()
|
|
|
+ self.lockFileIndex = 0
|
|
|
+ for i in 0..<addArray.count {
|
|
|
+ let filePath = addArray[i] as! String
|
|
|
+ let UTTypeString = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, filePath.extension as CFString, nil)!.takeRetainedValue() as String
|
|
|
+ let TypeCFString = UTTypeString as CFString
|
|
|
+ if UTTypeConformsTo(TypeCFString, kUTTypePDF) {
|
|
|
+ let document = PDFDocument(url: URL(fileURLWithPath: filePath))
|
|
|
+ if document?.isLocked == true {
|
|
|
+ var isContaint = false
|
|
|
+ for file in self.files {
|
|
|
+ if (file as AnyObject).filePath == filePath {
|
|
|
+ isContaint = true
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if !isContaint {
|
|
|
+ self.lockFilePathArr!.add(filePath)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ let file = KMBatchOperateFile(filePath: addArray[i] as! String, type: self.type!)
|
|
|
+ if !self.files.contains(file) {
|
|
|
+ self.files.append(file)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ let file = KMBatchOperateFile(filePath: addArray[i] as! String, type: self.type!)
|
|
|
+ if !self.files.contains(file) {
|
|
|
+ self.files.append(file)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ self.tableView.reloadData()
|
|
|
+ if self.lockFilePathArr!.count > 0 {
|
|
|
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
|
|
+ self.openPasswordWindow()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ func openPasswordWindow() {
|
|
|
+
|
|
|
+// if lockFilePathArr!.count > lockFileIndex {
|
|
|
+// let filePath = lockFilePathArr![lockFileIndex] as! String
|
|
|
+// let com = PasswordWindowController(windowNibName: "PasswordWindowController")
|
|
|
+// com.fileURL = URL(fileURLWithPath: filePath)
|
|
|
+// com.beginSheetModal
|
|
|
+// (for: self.view.window!) {
|
|
|
+// password in
|
|
|
+// if let password = password {
|
|
|
+// let file = KMBatchOperateFile(filePath: filePath, type: self.type)
|
|
|
+// file.password = password
|
|
|
+// self.files.add(file)
|
|
|
+// self.tableView.reloadData()
|
|
|
+// }
|
|
|
+// self.lockFileIndex += 1
|
|
|
+// if self.lockFilePathArr.count > self.lockFileIndex {
|
|
|
+// DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
|
|
+// self.openPasswordWindow()
|
|
|
+// }
|
|
|
+// } else {
|
|
|
+// self.tableView.reloadData()
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+ }
|
|
|
+ func chooseFileFromCamera() {
|
|
|
+ self.progressInt = 0
|
|
|
+ let vc = KMDeviceBrowserWindowController()
|
|
|
+ vc.type = ICDeviceType.camera
|
|
|
+ vc.importCameraFileCallback = { [weak self](url: NSURL) -> Void in
|
|
|
+ self!.addFilesToList(addArray: [url.path!])
|
|
|
+ }
|
|
|
+ vc.showWindow(nil)
|
|
|
+ }
|
|
|
+ func chooseFileFromScanner() {
|
|
|
+ self.progressInt = 0
|
|
|
+ let vc = KMDeviceBrowserWindowController()
|
|
|
+ vc.type = .scanner
|
|
|
+ vc.importScannerFileCallback = { [weak self](url: NSURL) -> Void in
|
|
|
+ self!.addFilesToList(addArray: [url.path!])
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @IBAction func buttonClicked_SelectFile(_ sender: Any) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @IBAction func buttonClicked_DeleteFile(_ sender: Any) {
|
|
|
+ let set = self.tableView.selectedRowIndexes
|
|
|
+ let newArr: NSMutableArray = self.files as! NSMutableArray
|
|
|
+ let arr = newArr.objects(at: set)
|
|
|
+ if arr.count > 0 {
|
|
|
+ newArr.removeObjects(in: arr)
|
|
|
+ self.files = newArr as! [KMBatchOperateFile]
|
|
|
+ self.tableView.reloadData()
|
|
|
+ } else {
|
|
|
+ if KMAlertWindowController.needShowRemoveAllFilesHint() {
|
|
|
+ let alert = NSAlert()
|
|
|
+ alert.alertStyle = .critical
|
|
|
+ alert.messageText = NSLocalizedString("Clear All Recents", comment: "")+"?"
|
|
|
+ alert.addButton(withTitle: NSLocalizedString("Delete", comment: ""))
|
|
|
+ alert.addButton(withTitle: NSLocalizedString("Cancel", comment: ""))
|
|
|
+ alert.beginSheetModal(for: self.view.window!) {[weak self] response in
|
|
|
+ if response == NSApplication.ModalResponse.alertFirstButtonReturn {
|
|
|
+ self?.files.removeAll()
|
|
|
+ self?.tableView.reloadData()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ self.files.removeAll()
|
|
|
+ self.tableView.reloadData()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ func fetchAvailableFilesInFolder(_ folderPath: String) -> [String] {
|
|
|
+ var array: [String] = []
|
|
|
+ var subFileArray = FileManager().subpaths(atPath: folderPath)
|
|
|
+ for i in 0..<subFileArray!.count {
|
|
|
+ let path = folderPath.stringByAppendingPathComponent(subFileArray![i])
|
|
|
+ let UTTypeString = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, path.extension as CFString, nil)
|
|
|
+ let TypeCFString = UTTypeString as! CFString?
|
|
|
+ if self.type == .CreatePDF {
|
|
|
+ if UTTypeConformsTo(TypeCFString!, kUTTypeImage) {
|
|
|
+ array.append(path)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if UTTypeConformsTo(TypeCFString!, kUTTypePDF) {
|
|
|
+ array.append(path)
|
|
|
+ }
|
|
|
+ }
|
|
|
+// UTTypeString?.release()
|
|
|
+ }
|
|
|
+ return array
|
|
|
+ }
|
|
|
+ func folderContainAvailableFile(_ folderPath: String) -> Bool {
|
|
|
+ var containFile = false
|
|
|
+ let subFileArray = FileManager.default.subpaths(atPath: folderPath) as? NSMutableArray
|
|
|
+ for i in 0..<subFileArray!.count {
|
|
|
+ let path = folderPath.stringByAppendingPathComponent(subFileArray![i] as! String)
|
|
|
+ let UTTypeString = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, path.extension as CFString, nil)
|
|
|
+ let TypeCFString = UTTypeString as! CFString?
|
|
|
+ if type == .CreatePDF {
|
|
|
+ if UTTypeConformsTo(TypeCFString!, kUTTypeImage) {
|
|
|
+ containFile = true
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if UTTypeConformsTo(TypeCFString!, kUTTypePDF) {
|
|
|
+ containFile = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+// UTTypeString?.release()
|
|
|
+ if containFile {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return containFile
|
|
|
+ }
|
|
|
+ func switchToOperateType(_ type: KMBatchOperationType) {
|
|
|
+ self.type = type
|
|
|
+ self.indexTableColumn.isHidden = false
|
|
|
+ self.fileNameTableColumn.isHidden = false
|
|
|
+ self.pageRangeTableColumn.isHidden = false
|
|
|
+ self.sizeTableColumn.isHidden = false
|
|
|
+ self.stateTableColumn.isHidden = false
|
|
|
+ self.DPIColumn.isHidden = true
|
|
|
+ self.dimensionsTableColumn.isHidden = true
|
|
|
+ if type == .Compress || type == .AddPassword || type == .RemovePassword || type == .RemoveWatermark || type == .RemoveBackground || type == .RemoveHeaderFooter || type == .RemoveBates || type == .CreatePDF {
|
|
|
+ self.pageRangeTableColumn.isHidden = true
|
|
|
+ } else {
|
|
|
+ self.pageRangeTableColumn.isHidden = false
|
|
|
+ }
|
|
|
+
|
|
|
+ self.selectFileButton.isImageToPDF = type == .CreatePDF
|
|
|
+ if type == .CreatePDF {
|
|
|
+ self.pageRangeTableColumn.isHidden = false
|
|
|
+ self.pageRangeTableColumn.title = NSLocalizedString("Dimensions", comment: "")
|
|
|
+ }
|
|
|
+
|
|
|
+ for i in 0..<self.files.count {
|
|
|
+ let file = self.files[i]
|
|
|
+ file.currentOperateType = type
|
|
|
+ }
|
|
|
+ self.tableView.sizeToFit()
|
|
|
+ self.tableView.reloadData()
|
|
|
+ }
|
|
|
+
|
|
|
+ @IBAction func menuItem_ShowInFinder(_ sender: Any) {
|
|
|
+ var row = self.tableView.clickedRow
|
|
|
+ var file: KMBatchOperateFile = self.files[row]
|
|
|
+ if file.currentOperateInfo?.status == .Success {
|
|
|
+ NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: file.currentOperateInfo!.outPutPath!)])
|
|
|
+ }else {
|
|
|
+ NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: file.filePath)])
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @IBAction func menuItem_Delete(_ sender: Any) {
|
|
|
+ var row = self.tableView.clickedRow
|
|
|
+ self.files.remove(at: row)
|
|
|
+ self.tableView.reloadData()
|
|
|
+ }
|
|
|
+
|
|
|
+ func validateMenuItem(menuItem: NSMenuItem) -> Bool {
|
|
|
+ let action = menuItem.action
|
|
|
+ if action == #selector(menuItem_ShowInFinder(_:)) || action == #selector(menuItem_Delete(_:)) {
|
|
|
+ if tableView.clickedRow == -1 {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ func addOpendFile() {
|
|
|
+ let documentArray = NSDocumentController.shared.documents
|
|
|
+ var pdfArray = NSMutableArray()
|
|
|
+ for i in 0..<documentArray.count {
|
|
|
+ let document = documentArray[i]
|
|
|
+ let path = document.fileURL?.path
|
|
|
+ var UTTypeString = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, path!.extension as CFString, nil)
|
|
|
+ let TypeCFString = UTTypeString as! CFString
|
|
|
+ if UTTypeConformsTo(TypeCFString, kUTTypePDF) {
|
|
|
+ pdfArray.add(path as Any)
|
|
|
+// UTTypeString?.release()
|
|
|
+ } else {
|
|
|
+// UTTypeString?.release()
|
|
|
+ }
|
|
|
+ }
|
|
|
+// if !IAPProductsManager.defaultManager.isAvailableAllFunction() {
|
|
|
+ if self.files.count < 1 {
|
|
|
+ pdfArray = [pdfArray.first].compactMap { $0 } as! NSMutableArray
|
|
|
+ } else {
|
|
|
+// KMPurchaseCompareWindowController.sharedInstance.showWindow(nil)
|
|
|
+// return
|
|
|
+ }
|
|
|
+// }
|
|
|
+ addFilesToList(addArray: pdfArray)
|
|
|
+ }
|
|
|
+ func numberOfRows(in tableView: NSTableView) -> Int {
|
|
|
+ NotificationCenter.default.post(name: NSNotification.Name(rawValue: "KMBatchFilesCountNotification"), object: self.files)
|
|
|
+ self.deleteFileButton.isEnabled = self.files.count > 0
|
|
|
+ self.blankView.isHidden = self.files.count > 0
|
|
|
+ return self.files.count;
|
|
|
+ }
|
|
|
+ func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
|
|
|
+ let identifier = tableColumn!.identifier
|
|
|
+ let file = self.files[row]
|
|
|
+
|
|
|
+ if identifier.rawValue == "index" {
|
|
|
+ var cellView = KMBatchTableCellView(type: .Size)
|
|
|
+ cellView.textField?.stringValue = "(row + 1)";
|
|
|
+ return cellView;
|
|
|
+ } else if identifier.rawValue == "pageRange"{
|
|
|
+ if (file.currentOperateType == .CreatePDF) {
|
|
|
+ var cellView = KMBatchTableCellView(type: .Size)
|
|
|
+
|
|
|
+ if (file.fileType == .Image) {
|
|
|
+ var image = NSImage(contentsOfFile: file.filePath)
|
|
|
+ cellView.textField?.stringValue = "(Int(image.size.width)) x (Int(image.size.height))"
|
|
|
+ }
|
|
|
+
|
|
|
+ return cellView;
|
|
|
+ } else {
|
|
|
+ var cellView = KMBatchTableCellView(type: .PageRange)
|
|
|
+ cellView.updateInterface(file)
|
|
|
+ return cellView;
|
|
|
+ }
|
|
|
+ } else if identifier.rawValue == "status"{
|
|
|
+ var cellView = KMBatchTableCellView(type: .Status)
|
|
|
+ if (file.currentOperateType == .CreatePDF) {
|
|
|
+ cellView.updateInterface(file: file, progress: file.progress ?? 0)
|
|
|
+ } else {
|
|
|
+ cellView.updateInterface(file: file, progress: file.progress ?? 0)
|
|
|
+ }
|
|
|
+ cellView.removeFileCallBack = { [weak self] file in
|
|
|
+ self?.files.removeObject(file)
|
|
|
+ self?.tableView.reloadData()
|
|
|
+ }
|
|
|
+ return cellView;
|
|
|
+ } else if identifier.rawValue == "size"{
|
|
|
+ var cellView = KMBatchTableCellView(type: .Size)
|
|
|
+ cellView.updateInterface(file)
|
|
|
+ return cellView;
|
|
|
+ } else if identifier.rawValue == "fileName"{
|
|
|
+ var cellView = KMBatchTableCellView(type: .FileName)
|
|
|
+ cellView.updateInterface(file)
|
|
|
+ var rowView = tableView.rowView(atRow: row, makeIfNecessary: true)
|
|
|
+ if ((file.error) != nil) {
|
|
|
+ rowView?.backgroundColor = KMAppearance.Status.errBGColor();
|
|
|
+ }
|
|
|
+ return cellView;
|
|
|
+ } else if identifier.rawValue == "dpi"{
|
|
|
+ var cellView = KMBatchTableCellView(type: .DPI)
|
|
|
+ cellView.updateInterface(file)
|
|
|
+ return cellView;
|
|
|
+ } else if identifier.rawValue == "dimensions"{
|
|
|
+ var cellView = KMBatchTableCellView(type: .Size)
|
|
|
+
|
|
|
+ if (file.fileType == .Image) {
|
|
|
+ var image = NSImage(contentsOfFile: file.filePath)
|
|
|
+ cellView.textField?.stringValue = "(Int(image.size.width)) x (Int(image.size.height))"
|
|
|
+ }
|
|
|
+
|
|
|
+ return cellView;
|
|
|
+ }
|
|
|
+ return nil;
|
|
|
+ }
|
|
|
+ func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
|
|
|
+ let file = self.files[row]
|
|
|
+ if self.type == .CreatePDF {
|
|
|
+ if (file.error != nil) {
|
|
|
+ return 64
|
|
|
+ } else {
|
|
|
+ return 40
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if file.fileType == .PDF {
|
|
|
+ if (file.error != nil) {
|
|
|
+ return 64
|
|
|
+ } else {
|
|
|
+ return 40
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return 0.0000001
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
|
|
|
+ let rowView = KMBatchTableRowView()
|
|
|
+ return rowView
|
|
|
+ }
|
|
|
+ func tableView(_ tableView: NSTableView, writeRowsWith rowIndexes: IndexSet, to pboard: NSPasteboard) -> Bool {
|
|
|
+ let indexSetData = try? NSKeyedArchiver.archivedData(withRootObject: rowIndexes, requiringSecureCoding: true)
|
|
|
+ pboard.declareTypes([NSPasteboard.PasteboardType.string], owner: self)
|
|
|
+ pboard.setData(indexSetData, forType: NSPasteboard.PasteboardType(rawValue: KMBatchDragType) )
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ func tableView(_ tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int, proposedDropOperation dropOperation: NSTableView.DropOperation) -> NSDragOperation {
|
|
|
+ var isCanDrag = false
|
|
|
+ var result: NSDragOperation = []
|
|
|
+ let pboard = info.draggingPasteboard
|
|
|
+ if pboard.availableType(from: [.fileURL]) != nil {
|
|
|
+ if let fileURLs = pboard.propertyList(forType: .fileURL) as? [URL] {
|
|
|
+ for url in fileURLs {
|
|
|
+ var isDirectory: ObjCBool = false
|
|
|
+ let fileExists = FileManager.default.fileExists(atPath: url.path, isDirectory: &isDirectory)
|
|
|
+ if fileExists && isDirectory.boolValue {
|
|
|
+ let containFile = folderContainAvailableFile(url.path)
|
|
|
+ if containFile {
|
|
|
+ isCanDrag = true
|
|
|
+ break
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if let UTType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, url.pathExtension as CFString, nil)?.takeRetainedValue() as String? {
|
|
|
+ if self.type == .CreatePDF {
|
|
|
+ if UTTypeConformsTo(UTType as CFString, kUTTypeImage) {
|
|
|
+ isCanDrag = true
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if UTTypeConformsTo(UTType as CFString, kUTTypePDF) {
|
|
|
+ isCanDrag = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if isCanDrag {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if isCanDrag {
|
|
|
+ result = .copy
|
|
|
+ }
|
|
|
+ return result
|
|
|
+ } else {
|
|
|
+ return .move
|
|
|
+ }
|
|
|
+ }
|
|
|
+ func tableView(_ tableView: NSTableView, acceptDrop info: NSDraggingInfo, row: Int, dropOperation: NSTableView.DropOperation) -> Bool {
|
|
|
+ let pboard = info.draggingPasteboard
|
|
|
+ if pboard.availableType(from: [.init(KMBatchDragType)]) != nil {
|
|
|
+ guard let rowData = pboard.data(forType: .init(KMBatchDragType)),
|
|
|
+ let rowIndexes = NSKeyedUnarchiver.unarchiveObject(with: rowData) as? NSIndexSet else { return false }
|
|
|
+ var backUpArray = self.files
|
|
|
+ var referenceIndex = -1
|
|
|
+ rowIndexes.enumerate(options: .reverse, using: { (idx, stop) in
|
|
|
+ var sortFile = backUpArray[idx]
|
|
|
+ if referenceIndex < 0 {
|
|
|
+ if idx > row {
|
|
|
+ self.files.remove(at: idx)
|
|
|
+ self.files.insert(sortFile, at: row)
|
|
|
+ } else if idx < row {
|
|
|
+ if row > self.files.count {
|
|
|
+ self.files.remove(at: idx)
|
|
|
+ self.files.append(sortFile)
|
|
|
+ } else {
|
|
|
+ self.files.remove(at: idx)
|
|
|
+ self.files.insert(sortFile, at: row - 1)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ referenceIndex = self.files.firstIndex(of: sortFile) ?? -1
|
|
|
+ } else {
|
|
|
+ let currentIndex = self.files.firstIndex(of: sortFile) ?? -1
|
|
|
+ if currentIndex > referenceIndex {
|
|
|
+ self.files.remove(at: currentIndex)
|
|
|
+ self.files.insert(sortFile, at: referenceIndex)
|
|
|
+ } else {
|
|
|
+ referenceIndex -= 1
|
|
|
+ self.files.remove(at: currentIndex)
|
|
|
+ self.files.insert(sortFile, at: referenceIndex)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ self.tableView.reloadData()
|
|
|
+ return true
|
|
|
+ } else if pboard.availableType(from: [.fileURL]) != nil {
|
|
|
+ guard let fileNames = pboard.propertyList(forType: .fileURL) as? [String]
|
|
|
+ else {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ var allFilesArray = NSMutableArray()
|
|
|
+ for path in fileNames {
|
|
|
+ var isFolder = ObjCBool(false)
|
|
|
+ FileManager.default.fileExists(atPath: path, isDirectory: &isFolder)
|
|
|
+ if isFolder.boolValue {
|
|
|
+ let containFiles = fetchAvailableFilesInFolder(path)
|
|
|
+ allFilesArray.addObjects(from: containFiles)
|
|
|
+ } else {
|
|
|
+ var UTTypeString = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, path.extension as CFString, nil)
|
|
|
+ let TypeCFString = UTTypeString as! CFString
|
|
|
+
|
|
|
+ if self.type == .CreatePDF {
|
|
|
+ if UTTypeConformsTo(TypeCFString, kUTTypeImage) {
|
|
|
+ allFilesArray.add(path)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if UTTypeConformsTo(TypeCFString, kUTTypePDF) {
|
|
|
+ allFilesArray.add(path)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ var insertArray = NSMutableArray()
|
|
|
+ lockFilePathArr?.removeAllObjects()
|
|
|
+ lockFileIndex = 0
|
|
|
+ for i in 0..<allFilesArray.count {
|
|
|
+ let filePath: String = allFilesArray[i] as! String
|
|
|
+ var UTTypeString = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, filePath.extension as CFString, nil)
|
|
|
+ let TypeCFString = UTTypeString as! CFString
|
|
|
+ if UTTypeConformsTo(TypeCFString, kUTTypePDF) {
|
|
|
+ let document = PDFDocument(url: URL(fileURLWithPath: filePath))
|
|
|
+ if let pdf = PDFDocument(url: URL(fileURLWithPath: filePath)) {
|
|
|
+ if !pdf.allowsPrinting || !pdf.allowsCopying {
|
|
|
+ let alert = NSAlert()
|
|
|
+ alert.alertStyle = .critical
|
|
|
+ alert.messageText = NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "")
|
|
|
+ alert.runModal()
|
|
|
+ continue
|
|
|
+ } else if document?.isLocked ?? false {
|
|
|
+ lockFilePathArr?.add(filePath)
|
|
|
+ } else {
|
|
|
+ let file = KMBatchOperateFile(filePath: filePath, type: self.type!)
|
|
|
+ if !(self.files.contains(file) ) {
|
|
|
+ insertArray.add(file)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ let file = KMBatchOperateFile(filePath: filePath, type: self.type!)
|
|
|
+ if !(self.files.contains(file) ) {
|
|
|
+ insertArray.add(file)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // if !(IAPProductsManager.defaultManager.isAvailableAllFunction) {
|
|
|
+ if self.files.count < 1 {
|
|
|
+ insertArray = [insertArray.first].compactMap { $0 } as! NSMutableArray
|
|
|
+ } else {
|
|
|
+ // KMPurchaseCompareWindowController.sharedInstance.showWindow(nil)
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ // }
|
|
|
+ for i in 0..<insertArray.count {
|
|
|
+ self.files.insert(insertArray[i] as! KMBatchOperateFile, at: row + i)
|
|
|
+ }
|
|
|
+ self.tableView.reloadData()
|
|
|
+ if lockFilePathArr!.count > 0 {
|
|
|
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
|
|
+ self.openPasswordWindow()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ func switchToOperateType(_ operateType: KMBatchOperationType, files: [KMBatchOperateFile]) {
|
|
|
+ switchToOperateType(operateType)
|
|
|
+ self.files = files
|
|
|
+ self.tableView.reloadData()
|
|
|
+ }
|
|
|
+ func checkNeedPasswordSwitchToOperateType(_ operateType: KMBatchOperationType, files: [KMBatchOperateFile]) {
|
|
|
+ switchToOperateType(operateType)
|
|
|
+ var arr: [String] = []
|
|
|
+ for i in 0..<files.count {
|
|
|
+ let file = files[i]
|
|
|
+ arr.append(file.filePath)
|
|
|
+ }
|
|
|
+
|
|
|
+ self.files = files
|
|
|
+ self.files.removeAll()
|
|
|
+ addFilesToList(addArray: arr as! NSMutableArray)
|
|
|
+ self.tableView.reloadData()
|
|
|
+ }
|
|
|
+ func reloadFile(_ file: KMBatchOperateFile) {
|
|
|
+ var rowIndexSet = IndexSet()
|
|
|
+ for i in 0..<self.files.count {
|
|
|
+ if file.filePath == self.files[i].filePath {
|
|
|
+ rowIndexSet.insert(i)
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ var columnIndexSet = IndexSet()
|
|
|
+ for i in 0..<self.tableView.numberOfColumns {
|
|
|
+ let identifier = self.tableView.tableColumns[i].identifier
|
|
|
+ if identifier.rawValue == "status" {
|
|
|
+ columnIndexSet.insert(i)
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if Thread.isMainThread {
|
|
|
+ self.tableView.reloadData(forRowIndexes: rowIndexSet, columnIndexes: columnIndexSet)
|
|
|
+ } else {
|
|
|
+ DispatchQueue.main.async {
|
|
|
+ self.tableView.reloadData(forRowIndexes: rowIndexSet, columnIndexes: columnIndexSet)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ func refreshConvertProgress(_ progress: CGFloat, file: KMBatchOperateFile) {
|
|
|
+ self.tableView.reloadData()
|
|
|
+ }
|
|
|
+ func reloadConvertInterface(withType type: KMConvertWithPDFType) {
|
|
|
+ if type == .WordAdvance || type == .WordStandard || type == .Excel || type == .PowerPoint || type == .RTF || type == .CSV || type == .HTML || type == .Text {
|
|
|
+ self.DPIColumn.isHidden = true
|
|
|
+ } else {
|
|
|
+ self.DPIColumn.isHidden = false
|
|
|
+ }
|
|
|
+ self.tableView.reloadData()
|
|
|
+ }
|
|
|
+}
|