KMBackgroundManager.swift 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. //
  2. // KMBackgroundManager.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by tangchao on 2022/12/23.
  6. //
  7. import Cocoa
  8. class KMBackgroundManager: NSObject, NSCoding {
  9. let kBackgroundFolderPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last?.stringByAppendingPathComponent(Bundle.main.bundleIdentifier!).stringByAppendingPathComponent("background")
  10. let kBackgroundPlistPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last?.stringByAppendingPathComponent(Bundle.main.bundleIdentifier!).stringByAppendingPathComponent("background").stringByAppendingPathComponent("background.plist")
  11. var datas: Array<KMBackgroundModel> = []
  12. var backgroundObjects: [KMBackgroundObject] = []
  13. static let defaultManager = KMBackgroundManager()
  14. override init() {
  15. super.init()
  16. if let storedData = UserDefaults.standard.value(forKey: "kBackgroundInfoSaveKey") as? Data {
  17. NSKeyedUnarchiver.setClass(KMBackgroundObject.self, forClassName: "KMBackgroundObject")
  18. NSKeyedUnarchiver.setClass(KMBackgroundManager.self, forClassName: "KMBackgroundManager")
  19. if let man = NSKeyedUnarchiver.unarchiveObject(with: storedData) as? KMBackgroundManager {
  20. for object in man.backgroundObjects {
  21. let model = self.parseObject(object: object)
  22. self.datas.append(model)
  23. }
  24. }
  25. }
  26. if (FileManager.default.fileExists(atPath: kBackgroundPlistPath!)) {
  27. let dataDict = NSDictionary(contentsOfFile: kBackgroundPlistPath!)
  28. if (dataDict == nil) {
  29. return
  30. }
  31. var deleteKeys: Array<String> = []
  32. for keyIndex in 0 ..< (dataDict?.allKeys.count)! {
  33. let key: String = dataDict?.allKeys[keyIndex] as! String
  34. let backgroundDict: NSDictionary = dataDict?.object(forKey: key) as! NSDictionary
  35. let model = parseDictionary(dict: backgroundDict)
  36. /// 赋值id
  37. model.backgroundID = key
  38. if (model.type == .file) {
  39. if (model.image == nil) {
  40. deleteKeys.append(key)
  41. } else {
  42. self.datas.append(model)
  43. }
  44. } else {
  45. self.datas.append(model)
  46. }
  47. }
  48. if (deleteKeys.count > 0) {
  49. let newDict: NSMutableDictionary = NSMutableDictionary(dictionary: dataDict!)
  50. for key in deleteKeys {
  51. newDict.removeObject(forKey: key)
  52. }
  53. newDict.write(toFile: kBackgroundPlistPath!, atomically: true)
  54. }
  55. }
  56. }
  57. required init?(coder: NSCoder) {
  58. if let data = coder.decodeObject(forKey: "backgroundObjects") {
  59. self.backgroundObjects = data as? [KMBackgroundObject] ?? []
  60. }
  61. }
  62. func encode(with coder: NSCoder) {
  63. coder.encode(self.backgroundObjects, forKey: "backgroundObjects")
  64. }
  65. func addTemplate(model: KMBackgroundModel) -> Bool {
  66. if (!FileManager.default.fileExists(atPath: kBackgroundFolderPath!)) {
  67. let create: ()? = try?FileManager.default.createDirectory(atPath: kBackgroundFolderPath!, withIntermediateDirectories: false)
  68. if (create == nil) {
  69. return false
  70. }
  71. }
  72. if (!FileManager.default.fileExists(atPath: kBackgroundPlistPath!)) {
  73. let create = try?FileManager.default.createFile(atPath: kBackgroundPlistPath!, contents: nil)
  74. if (create == nil) {
  75. return false
  76. }
  77. }
  78. let dict = NSDictionary(contentsOfFile: kBackgroundPlistPath!)
  79. var newDict:NSMutableDictionary!
  80. if (dict != nil) {
  81. newDict = NSMutableDictionary(dictionary: dict!)
  82. } else {
  83. newDict = NSMutableDictionary()
  84. }
  85. let backgroundDict = self.parseModel(model: model)
  86. if (backgroundDict.isEmpty) {
  87. let alert = NSAlert()
  88. alert.alertStyle = .critical
  89. alert.messageText = NSLocalizedString("文件\(model.imagePath.lastPathComponent)已损坏", comment: "")
  90. alert.runModal()
  91. return false
  92. }
  93. let tag = fetchAvailableName()//tagString()
  94. newDict.addEntries(from: [tag : backgroundDict])
  95. model.backgroundID = tag
  96. let result = newDict.write(toFile: kBackgroundPlistPath!, atomically: true)
  97. if (result) {
  98. if (self.datas.count < 1) {
  99. self.datas.append(model)
  100. } else {
  101. self.datas.insert(model, at: 0)
  102. }
  103. }
  104. return result
  105. }
  106. func deleteTemplate(model: KMBackgroundModel) -> Bool {
  107. if (model.backgroundID.isEmpty) {
  108. return false
  109. }
  110. if (!FileManager.default.fileExists(atPath: kBackgroundPlistPath!)) {
  111. return false
  112. }
  113. let key: String = model.backgroundID
  114. let dictionary = NSDictionary(contentsOfFile: kBackgroundPlistPath!)
  115. var newDictionary: NSMutableDictionary!
  116. if (dictionary != nil) {
  117. newDictionary = NSMutableDictionary(dictionary: dictionary!)
  118. } else {
  119. newDictionary = NSMutableDictionary()
  120. }
  121. newDictionary.removeObject(forKey: key)
  122. let result = newDictionary.write(toFile: kBackgroundPlistPath!, atomically: true)
  123. if (result) {
  124. if (model.type == .file) {
  125. let filePath: String = model.imagePath
  126. try?FileManager.default.removeItem(atPath: filePath)
  127. }
  128. if (self.datas.contains(model)) {
  129. self.datas.removeObject(model)
  130. }
  131. }
  132. return result
  133. }
  134. func deleteAllTemplates() -> Bool {
  135. if (!FileManager.default.fileExists(atPath: kBackgroundPlistPath!)) {
  136. return false
  137. }
  138. let dictionary = NSDictionary(contentsOfFile: kBackgroundPlistPath!)
  139. var newDictionary: NSMutableDictionary!
  140. if (dictionary != nil) {
  141. newDictionary = NSMutableDictionary(dictionary: dictionary!)
  142. } else {
  143. newDictionary = NSMutableDictionary()
  144. }
  145. newDictionary.removeAllObjects()
  146. let result = newDictionary.write(toFile: kBackgroundPlistPath!, atomically: true)
  147. if (result) {
  148. self.datas.removeAll()
  149. }
  150. return result
  151. }
  152. func deleteAllColorTemplates() -> Bool {
  153. if (!FileManager.default.fileExists(atPath: kBackgroundPlistPath!)) {
  154. return false
  155. }
  156. let dictionary = NSDictionary(contentsOfFile: kBackgroundPlistPath!)
  157. var newDictionary: NSMutableDictionary!
  158. if (dictionary != nil) {
  159. newDictionary = NSMutableDictionary(dictionary: dictionary!)
  160. } else {
  161. newDictionary = NSMutableDictionary()
  162. }
  163. let count = self.datas.count-1
  164. var deleteArray: Array<KMBackgroundModel> = []
  165. for i in 0 ... count {
  166. let model = self.datas[i]
  167. if (model.type == .color) {
  168. newDictionary.removeObject(forKey: model.backgroundID as Any)
  169. deleteArray.append(model)
  170. }
  171. }
  172. let result = newDictionary.write(toFile: kBackgroundPlistPath!, atomically: true)
  173. if (result) {
  174. for model in deleteArray {
  175. self.datas.removeObject(model)
  176. }
  177. }
  178. return result
  179. }
  180. func deleteAllFileTemplates() -> Bool {
  181. if (!FileManager.default.fileExists(atPath: kBackgroundPlistPath!)) {
  182. return false
  183. }
  184. let dictionary = NSDictionary(contentsOfFile: kBackgroundPlistPath!)
  185. var newDictionary: NSMutableDictionary!
  186. if (dictionary != nil) {
  187. newDictionary = NSMutableDictionary(dictionary: dictionary!)
  188. } else {
  189. newDictionary = NSMutableDictionary()
  190. }
  191. let count = self.datas.count-1
  192. var deleteArray: Array<KMBackgroundModel> = []
  193. for i in 0 ... count {
  194. let model = self.datas[i]
  195. if (model.type == .file) {
  196. newDictionary.removeObject(forKey: model.backgroundID as Any)
  197. deleteArray.append(model)
  198. }
  199. }
  200. let result = newDictionary.write(toFile: kBackgroundPlistPath!, atomically: true)
  201. if (result) {
  202. for model in deleteArray {
  203. self.datas.removeObject(model)
  204. }
  205. }
  206. return result
  207. }
  208. func updateTemplate(model: KMBackgroundModel) -> Bool {
  209. if (!FileManager.default.fileExists(atPath: kBackgroundFolderPath!)) {
  210. let create = try?FileManager.default.createDirectory(atPath: kBackgroundFolderPath!, withIntermediateDirectories: false)
  211. if (create == nil) {
  212. return false
  213. }
  214. }
  215. if (!FileManager.default.fileExists(atPath: kBackgroundPlistPath!)) {
  216. let create = try?FileManager.default.createFile(atPath: kBackgroundPlistPath!, contents: nil)
  217. if (create == nil) {
  218. return false
  219. }
  220. }
  221. var flagModel: KMBackgroundModel!
  222. for model_ in self.datas {
  223. if (model_.backgroundID == model.backgroundID) {
  224. flagModel = model_
  225. break
  226. }
  227. }
  228. if (flagModel == nil) {
  229. return false
  230. }
  231. let dict = NSDictionary(contentsOfFile: kBackgroundPlistPath!)
  232. var newDict:NSMutableDictionary!
  233. if (dict != nil) {
  234. newDict = NSMutableDictionary(dictionary: dict!)
  235. } else {
  236. newDict = NSMutableDictionary()
  237. }
  238. let modelDict = self.parseModel(model: model)
  239. if (modelDict.isEmpty) {
  240. let alert = NSAlert()
  241. alert.alertStyle = .critical
  242. alert.messageText = NSLocalizedString("文件\(model.imagePath.lastPathComponent)已损坏", comment: "")
  243. alert.runModal()
  244. return false
  245. }
  246. newDict.setObject(modelDict, forKey: flagModel.backgroundID as NSCopying)
  247. let result = newDict.write(toFile: kBackgroundPlistPath!, atomically: true)
  248. if (result) {
  249. let index = self.datas.index(of: flagModel)
  250. self.datas[index!] = model
  251. }
  252. return result
  253. }
  254. /**
  255. `Private Methods`
  256. */
  257. private func parseModel(model: KMBackgroundModel) -> Dictionary<String, Any> {
  258. let tag = tagString()
  259. var dict: [String : Any] = [:]
  260. if (model.type == .color) {
  261. var red: CGFloat = 0.0
  262. var green: CGFloat = 0.0
  263. var blue: CGFloat = 0.0
  264. model.color!.usingColorSpaceName(NSColorSpaceName.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: nil)
  265. dict["red"] = red
  266. dict["green"] = green
  267. dict["blue"] = blue
  268. } else {
  269. if (!FileManager.default.fileExists(atPath: kBackgroundFolderPath!)) {
  270. try?FileManager.default.createDirectory(atPath: kBackgroundFolderPath!, withIntermediateDirectories: false)
  271. }
  272. let path = kBackgroundFolderPath?.stringByAppendingPathComponent("\(tag).png")
  273. let image = model.image
  274. let data = image?.tiffRepresentation
  275. let imageRep = NSBitmapImageRep(data: data!)
  276. imageRep?.size = image!.size
  277. var imageData: Data!
  278. let pathExtension = model.imagePath.components(separatedBy: ".").last
  279. if (pathExtension?.lowercased() == "png") {
  280. imageData = imageRep?.representation(using: NSBitmapImageRep.FileType.png, properties: [:])
  281. } else {
  282. imageData = imageRep?.representation(using: NSBitmapImageRep.FileType.jpeg, properties: [:])
  283. }
  284. do {
  285. try imageData.write(to: URL(fileURLWithPath: path!))
  286. dict["imagePath"] = path?.lastPathComponent
  287. }
  288. catch {
  289. KMPrint("Failed to write to disk.")
  290. return [:]
  291. }
  292. }
  293. dict["type"] = model.type.rawValue
  294. dict["scale"] = model.scale
  295. dict["opacity"] = model.opacity
  296. dict["rotation"] = model.rotation
  297. dict["horizontalMode"] = model.horizontalMode
  298. dict["horizontalSpace"] = model.horizontalSpace
  299. dict["verticalMode"] = model.verticalMode
  300. dict["verticalSpace"] = model.verticalSpace
  301. dict["pageRangeType"] = model.pageRangeType.rawValue
  302. dict["pagesString"] = model.pagesString
  303. return dict
  304. }
  305. private func parseDictionary(dict: NSDictionary) -> KMBackgroundModel {
  306. let model = KMBackgroundModel()
  307. model.type = KMBackgroundType(rawValue: dict.object(forKey: "type") as! Int)!
  308. if (model.type == .file) {
  309. let path = kBackgroundFolderPath?.stringByAppendingPathComponent(dict.object(forKey: "imagePath") as! String)
  310. if (FileManager.default.fileExists(atPath: path!)) {
  311. model.image = NSImage(contentsOfFile: path!)
  312. model.imagePath = path!
  313. } else {
  314. model.image = nil
  315. }
  316. } else {
  317. let red: CGFloat = dict.object(forKey: "red") as! CGFloat
  318. let green: CGFloat = dict.object(forKey: "green") as! CGFloat
  319. let blue: CGFloat = dict.object(forKey: "blue") as! CGFloat
  320. model.color = NSColor(red: red, green: green, blue: blue, alpha: 1.0)
  321. }
  322. model.scale = dict.object(forKey: "scale") as! CGFloat
  323. model.rotation = CGFloat(Int(dict.object(forKey: "rotation") as! CGFloat))
  324. model.opacity = (dict.object(forKey: "opacity") as! CGFloat)
  325. model.verticalMode = (dict.object(forKey: "verticalMode") as! Int)
  326. model.verticalSpace = (dict.object(forKey: "verticalSpace") as! CGFloat)
  327. model.horizontalMode = (dict.object(forKey: "horizontalMode") as! Int)
  328. model.horizontalSpace = (dict.object(forKey: "horizontalSpace") as! CGFloat)
  329. model.pageRangeType = KMWatermarkeModelPageRangeType.init(rawValue: (dict.object(forKey: "pageRangeType") as! Int))!
  330. model.pagesString = (dict.object(forKey: "pagesString") as! String)
  331. return model
  332. }
  333. private func parseObject(object: KMBackgroundObject) -> KMBackgroundModel {
  334. let model = KMBackgroundModel()
  335. model.type = object.type
  336. if (model.type == .file) {
  337. model.image = object.image
  338. model.imagePath = object.imagePath ?? ""
  339. } else {
  340. model.color = object.color
  341. }
  342. model.scale = object.scale
  343. model.rotation = object.rotation.cgFloat
  344. model.opacity = object.opacity
  345. model.verticalMode = object.verticalMode
  346. model.verticalSpace = object.verticalSpace.cgFloat
  347. model.horizontalMode = object.horizontalMode
  348. model.horizontalSpace = object.horizontalSpace.cgFloat
  349. model.pageRangeType = KMWatermarkeModelPageRangeType.init(rawValue: object.pageRangeType.rawValue) ?? .all
  350. model.pagesString = object.pagesString
  351. return model
  352. }
  353. private func tagString() -> String {
  354. var result: String = ""
  355. let dateFormatter = DateFormatter()
  356. dateFormatter.dateFormat = "yyMMddHHmmss"
  357. result.append(dateFormatter.string(from: Date()))
  358. result = result.appendingFormat("%04d", arc4random()%10000)
  359. return result
  360. }
  361. func fetchAvailableName() -> String {
  362. var availableIndex = 0
  363. for item in datas {
  364. if item.backgroundID.hasPrefix("Background") {
  365. if let index = Int(item.backgroundID.dropFirst("Background".count)), index >= availableIndex {
  366. availableIndex = index + 1
  367. }
  368. }
  369. }
  370. return "Background\(availableIndex)"
  371. }
  372. }