diff --git a/Packages/vChewing_LangModelAssembly/Sources/LangModelAssembly/LMInstantiator.swift b/Packages/vChewing_LangModelAssembly/Sources/LangModelAssembly/LMInstantiator.swift index 62b955a9..a50921d5 100644 --- a/Packages/vChewing_LangModelAssembly/Sources/LangModelAssembly/LMInstantiator.swift +++ b/Packages/vChewing_LangModelAssembly/Sources/LangModelAssembly/LMInstantiator.swift @@ -92,45 +92,51 @@ extension vChewingLM { // MARK: - 工具函式 + public func resetFactoryPlistModels() { + lmCore.clear() + lmMisc.clear() + Self.lmCNS.clear() + Self.lmSymbols.clear() + } + public var isCoreLMLoaded: Bool { lmCore.isLoaded } - public func loadLanguageModel(path: String) { - if FileManager.default.isReadableFile(atPath: path) { - lmCore.open(path) - vCLog("lmCore: \(lmCore.count) entries of data loaded from: \(path)") - } else { - vCLog("lmCore: File access failure: \(path)") + public func loadLanguageModel(plist: (dict: [String: [Data]]?, path: String)) { + guard let plistDict = plist.dict else { + vCLog("lmCore: File access failure: \(plist.path)") + return } + lmCore.load((dict: plistDict, path: plist.path)) + vCLog("lmCore: \(lmCore.count) entries of data loaded from: \(plist.path)") } public var isCNSDataLoaded: Bool { Self.lmCNS.isLoaded } - public func loadCNSData(path: String) { - if FileManager.default.isReadableFile(atPath: path) { - Self.lmCNS.open(path) - vCLog("lmCNS: \(Self.lmCNS.count) entries of data loaded from: \(path)") - } else { - vCLog("lmCNS: File access failure: \(path)") + public func loadCNSData(plist: (dict: [String: [Data]]?, path: String)) { + guard let plistDict = plist.dict else { + vCLog("lmCNS: File access failure: \(plist.path)") + return } + Self.lmCNS.load((dict: plistDict, path: plist.path)) + vCLog("lmCNS: \(Self.lmCNS.count) entries of data loaded from: \(plist.path)") } public var isMiscDataLoaded: Bool { lmMisc.isLoaded } - public func loadMiscData(path: String) { - if FileManager.default.isReadableFile(atPath: path) { - lmMisc.open(path) - vCLog("lmMisc: \(lmMisc.count) entries of data loaded from: \(path)") - } else { - vCLog("lmMisc: File access failure: \(path)") + public func loadMiscData(plist: (dict: [String: [Data]]?, path: String)) { + guard let plistDict = plist.dict else { + vCLog("lmCore: File access failure: \(plist.path)") + return } + lmMisc.load((dict: plistDict, path: plist.path)) + vCLog("lmMisc: \(lmMisc.count) entries of data loaded from: \(plist.path)") } public var isSymbolDataLoaded: Bool { Self.lmSymbols.isLoaded } - public func loadSymbolData(path: String) { - if FileManager.default.isReadableFile(atPath: path) { - Self.lmSymbols.open(path) - vCLog( - "lmSymbol: \(Self.lmSymbols.count) entries of data loaded from: \(path)") - } else { - vCLog("lmSymbols: File access failure: \(path)") + public func loadSymbolData(plist: (dict: [String: [Data]]?, path: String)) { + guard let plistDict = plist.dict else { + vCLog("lmCore: File access failure: \(plist.path)") + return } + Self.lmSymbols.load((dict: plistDict, path: plist.path)) + vCLog("lmSymbols: \(Self.lmSymbols.count) entries of data loaded from: \(plist.path)") } // 上述幾個函式不要加 Async,因為這些內容都被 LMMgr 負責用別的方法 Async 了、用 GCD 的多任務並行共結來完成。 diff --git a/Packages/vChewing_LangModelAssembly/Sources/LangModelAssembly/SubLMs/lmCoreNS.swift b/Packages/vChewing_LangModelAssembly/Sources/LangModelAssembly/SubLMs/lmCoreNS.swift index 22ca20d3..1509c977 100644 --- a/Packages/vChewing_LangModelAssembly/Sources/LangModelAssembly/SubLMs/lmCoreNS.swift +++ b/Packages/vChewing_LangModelAssembly/Sources/LangModelAssembly/SubLMs/lmCoreNS.swift @@ -55,6 +55,15 @@ extension vChewingLM { /// 檢測資料庫辭典內是否已經有載入的資料。 public var isLoaded: Bool { !dataMap.isEmpty } + /// 讀入資料辭典。 + /// - parameters: + /// - dictData: 辭典資料及對應的 URL 位置。 + public mutating func load(_ dictData: (dict: [String: [Data]], path: String)) { + if isLoaded { return } + filePath = dictData.path + dataMap = dictData.dict + } + /// 將資料從檔案讀入至資料庫辭典內。 /// - parameters: /// - path: 給定路徑。 diff --git a/Packages/vChewing_LangModelAssembly/Sources/LangModelAssembly/SubLMs/lmRevLookup.swift b/Packages/vChewing_LangModelAssembly/Sources/LangModelAssembly/SubLMs/lmRevLookup.swift index 86642375..346c4bf1 100644 --- a/Packages/vChewing_LangModelAssembly/Sources/LangModelAssembly/SubLMs/lmRevLookup.swift +++ b/Packages/vChewing_LangModelAssembly/Sources/LangModelAssembly/SubLMs/lmRevLookup.swift @@ -14,8 +14,13 @@ extension vChewingLM { public private(set) var dataMap: [String: [Data]] = [:] public private(set) var filePath: String = "" - public init(dataMap: [String: [Data]]) { - self.dataMap = dataMap + public init(data dictData: (dict: [String: [Data]]?, path: String)) { + guard let theDict = dictData.dict else { + vCLog("↑ Exception happened when reading plist file at: \(dictData.path).") + return + } + filePath = dictData.path + dataMap = theDict } public init(path: String) { diff --git a/Source/Modules/LMMgr.swift b/Source/Modules/LMMgr.swift index dc83e4ea..a126e03d 100644 --- a/Source/Modules/LMMgr.swift +++ b/Source/Modules/LMMgr.swift @@ -66,8 +66,7 @@ public class LMMgr { public static func loadCoreLanguageModelFile( filenameSansExtension: String, langModel lm: inout vChewingLM.LMInstantiator ) { - let dataPath: String = Self.getBundleDataPath(filenameSansExtension) - lm.loadLanguageModel(path: dataPath) + lm.loadLanguageModel(plist: Self.getDictionaryData(filenameSansExtension)) } public static func loadDataModelsOnAppDelegate() { @@ -77,22 +76,22 @@ public class LMMgr { group.enter() globalQueue.async { if !Self.lmCHT.isCNSDataLoaded { - Self.lmCHT.loadCNSData(path: getBundleDataPath("data-cns")) + Self.lmCHT.loadCNSData(plist: Self.getDictionaryData("data-cns")) } if !Self.lmCHT.isMiscDataLoaded { - Self.lmCHT.loadMiscData(path: getBundleDataPath("data-zhuyinwen")) + Self.lmCHT.loadMiscData(plist: Self.getDictionaryData("data-zhuyinwen")) } if !Self.lmCHT.isSymbolDataLoaded { - Self.lmCHT.loadSymbolData(path: getBundleDataPath("data-symbols")) + Self.lmCHT.loadSymbolData(plist: Self.getDictionaryData("data-symbols")) } if !Self.lmCHS.isCNSDataLoaded { - Self.lmCHS.loadCNSData(path: getBundleDataPath("data-cns")) + Self.lmCHS.loadCNSData(plist: Self.getDictionaryData("data-cns")) } if !Self.lmCHS.isMiscDataLoaded { - Self.lmCHS.loadMiscData(path: getBundleDataPath("data-zhuyinwen")) + Self.lmCHS.loadMiscData(plist: Self.getDictionaryData("data-zhuyinwen")) } if !Self.lmCHS.isSymbolDataLoaded { - Self.lmCHS.loadSymbolData(path: getBundleDataPath("data-symbols")) + Self.lmCHS.loadSymbolData(plist: Self.getDictionaryData("data-symbols")) } group.leave() } @@ -136,23 +135,23 @@ public class LMMgr { switch mode { case .imeModeCHS: if !Self.lmCHS.isCNSDataLoaded { - Self.lmCHS.loadCNSData(path: getBundleDataPath("data-cns")) + Self.lmCHS.loadCNSData(plist: Self.getDictionaryData("data-cns")) } if !Self.lmCHS.isMiscDataLoaded { - Self.lmCHS.loadMiscData(path: getBundleDataPath("data-zhuyinwen")) + Self.lmCHS.loadMiscData(plist: Self.getDictionaryData("data-zhuyinwen")) } if !Self.lmCHS.isSymbolDataLoaded { - Self.lmCHS.loadSymbolData(path: getBundleDataPath("data-symbols")) + Self.lmCHS.loadSymbolData(plist: Self.getDictionaryData("data-symbols")) } case .imeModeCHT: if !Self.lmCHT.isCNSDataLoaded { - Self.lmCHT.loadCNSData(path: getBundleDataPath("data-cns")) + Self.lmCHT.loadCNSData(plist: Self.getDictionaryData("data-cns")) } if !Self.lmCHT.isMiscDataLoaded { - Self.lmCHT.loadMiscData(path: getBundleDataPath("data-zhuyinwen")) + Self.lmCHT.loadMiscData(plist: Self.getDictionaryData("data-zhuyinwen")) } if !Self.lmCHT.isSymbolDataLoaded { - Self.lmCHT.loadSymbolData(path: getBundleDataPath("data-symbols")) + Self.lmCHT.loadSymbolData(plist: Self.getDictionaryData("data-symbols")) } default: break } @@ -194,6 +193,17 @@ public class LMMgr { } } + public static func reloadFactoryDictionaryPlists() { + FrmRevLookupWindow.reloadData() + LMMgr.lmCHS.resetFactoryPlistModels() + LMMgr.lmCHT.resetFactoryPlistModels() + if PrefMgr.shared.onlyLoadFactoryLangModelsIfNeeded { + LMMgr.loadDataModel(IMEApp.currentInputMode) + } else { + LMMgr.loadDataModelsOnAppDelegate() + } + } + /// 載入磁帶資料。 /// - Remark: cassettePath() 會在輸入法停用磁帶時直接返回 public static func loadCassetteData() { diff --git a/Source/Modules/WindowControllers/CtlRevLookupWindow.swift b/Source/Modules/WindowControllers/CtlRevLookupWindow.swift index 11ddccfa..8f3caeb9 100644 --- a/Source/Modules/WindowControllers/CtlRevLookupWindow.swift +++ b/Source/Modules/WindowControllers/CtlRevLookupWindow.swift @@ -29,15 +29,15 @@ class CtlRevLookupWindow: NSWindowController, NSWindowDelegate { class FrmRevLookupWindow: NSWindow { typealias LMRevLookup = vChewingLM.LMRevLookup - static let lmRevLookupCore = LMRevLookup(path: LMMgr.getBundleDataPath("data-bpmf-reverse-lookup")) + static var lmRevLookupCore = LMRevLookup(data: LMMgr.getDictionaryData("data-bpmf-reverse-lookup")) // 全字庫資料接近十萬筆索引,只放到單個 Dictionary 內的話、每次查詢時都會把輸入法搞崩潰。只能分卷處理。 - static let lmRevLookupCNS1 = LMRevLookup(path: LMMgr.getBundleDataPath("data-bpmf-reverse-lookup-CNS1")) - static let lmRevLookupCNS2 = LMRevLookup(path: LMMgr.getBundleDataPath("data-bpmf-reverse-lookup-CNS2")) - static let lmRevLookupCNS3 = LMRevLookup(path: LMMgr.getBundleDataPath("data-bpmf-reverse-lookup-CNS3")) - static let lmRevLookupCNS4 = LMRevLookup(path: LMMgr.getBundleDataPath("data-bpmf-reverse-lookup-CNS4")) - static let lmRevLookupCNS5 = LMRevLookup(path: LMMgr.getBundleDataPath("data-bpmf-reverse-lookup-CNS5")) - static let lmRevLookupCNS6 = LMRevLookup(path: LMMgr.getBundleDataPath("data-bpmf-reverse-lookup-CNS6")) + static var lmRevLookupCNS1 = LMRevLookup(data: LMMgr.getDictionaryData("data-bpmf-reverse-lookup-CNS1")) + static var lmRevLookupCNS2 = LMRevLookup(data: LMMgr.getDictionaryData("data-bpmf-reverse-lookup-CNS2")) + static var lmRevLookupCNS3 = LMRevLookup(data: LMMgr.getDictionaryData("data-bpmf-reverse-lookup-CNS3")) + static var lmRevLookupCNS4 = LMRevLookup(data: LMMgr.getDictionaryData("data-bpmf-reverse-lookup-CNS4")) + static var lmRevLookupCNS5 = LMRevLookup(data: LMMgr.getDictionaryData("data-bpmf-reverse-lookup-CNS5")) + static var lmRevLookupCNS6 = LMRevLookup(data: LMMgr.getDictionaryData("data-bpmf-reverse-lookup-CNS6")) public lazy var inputField = NSTextField() public lazy var resultView = NSTextView() @@ -46,6 +46,16 @@ class FrmRevLookupWindow: NSWindow { private lazy var button = NSButton() private lazy var view = NSView() + static func reloadData() { + DispatchQueue.main.async { lmRevLookupCore = .init(data: LMMgr.getDictionaryData("data-bpmf-reverse-lookup")) } + DispatchQueue.main.async { lmRevLookupCNS1 = .init(data: LMMgr.getDictionaryData("data-bpmf-reverse-lookup-CNS1")) } + DispatchQueue.main.async { lmRevLookupCNS2 = .init(data: LMMgr.getDictionaryData("data-bpmf-reverse-lookup-CNS2")) } + DispatchQueue.main.async { lmRevLookupCNS3 = .init(data: LMMgr.getDictionaryData("data-bpmf-reverse-lookup-CNS3")) } + DispatchQueue.main.async { lmRevLookupCNS4 = .init(data: LMMgr.getDictionaryData("data-bpmf-reverse-lookup-CNS4")) } + DispatchQueue.main.async { lmRevLookupCNS5 = .init(data: LMMgr.getDictionaryData("data-bpmf-reverse-lookup-CNS5")) } + DispatchQueue.main.async { lmRevLookupCNS6 = .init(data: LMMgr.getDictionaryData("data-bpmf-reverse-lookup-CNS6")) } + } + init() { super.init( contentRect: CGRect(x: 196, y: 240, width: 480, height: 340),