Warning, file /education/kiten/lib/dictionarymanager.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 This file is part of Kiten, a KDE Japanese Reference Tool 0003 SPDX-FileCopyrightText: 2006 Joseph Kerian <jkerian@gmail.com> 0004 SPDX-FileCopyrightText: 2011 Daniel E. Moctezuma <democtezuma@gmail.com> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include "dictionarymanager.h" 0010 0011 #include "dictfile.h" 0012 #include "dictionarypreferencedialog.h" 0013 #include "dictquery.h" 0014 #include "entry.h" 0015 #include "entrylist.h" 0016 #include "kitenmacros.h" 0017 0018 #include <KConfig> 0019 #include <KConfigSkeleton> 0020 0021 #include <QDebug> 0022 #include <QString> 0023 0024 /* Includes to handle various types of dictionaries 0025 IMPORTANT: To add a dictionary type, add the header file here and add it to the 0026 if statement under addDictionary() */ 0027 #include "DictEdict/dictfileedict.h" 0028 #include "DictKanjidic/dictfilekanjidic.h" 0029 0030 class DictionaryManager::Private 0031 { 0032 public: 0033 /** 0034 * List of dictionaries, indexed by name 0035 */ 0036 QHash<QString, DictFile *> dictManagers; 0037 }; 0038 0039 #if 0 0040 class debug_entry : public Entry 0041 { 0042 public: 0043 debug_entry(QString word) : Entry( QString( "libkiten" ), word 0044 , QStringList(), QStringList() ), count( counter++ ) 0045 { } 0046 virtual Entry * clone() const { return new debug_entry( *this ); } 0047 virtual bool loadEntry( const QString& ) { return false; } 0048 virtual QString dumpEntry() const { return ""; } 0049 virtual bool sort( const debug_entry &that, const QStringList &dicts, 0050 const QStringList &fields ) 0051 { return this->count < that.count; } 0052 0053 int count; 0054 static int counter; 0055 }; 0056 int debug_entry::counter = 0; 0057 #endif 0058 0059 /** 0060 * The constructor. Set autodelete on our dictionary list 0061 */ 0062 DictionaryManager::DictionaryManager() 0063 : d(new Private) 0064 { 0065 } 0066 0067 /** 0068 * Delete everything in our hash 0069 */ 0070 DictionaryManager::~DictionaryManager() 0071 { 0072 { 0073 QMutableHashIterator<QString, DictFile *> it(d->dictManagers); 0074 while (it.hasNext()) { 0075 it.next(); 0076 delete it.value(); 0077 it.remove(); 0078 } 0079 } 0080 0081 delete d; 0082 } 0083 0084 /** 0085 * Given a named Dict file/name/type... create and add the object if it 0086 * seems to work properly on creation. 0087 */ 0088 bool DictionaryManager::addDictionary(const QString &file, const QString &name, const QString &type) 0089 { 0090 if (d->dictManagers.contains(name)) // This name already exists in the list! 0091 { 0092 return false; 0093 } 0094 0095 DictFile *newDict = makeDictFile(type); 0096 if (newDict == nullptr) { 0097 return false; 0098 } 0099 0100 if (!newDict->loadDictionary(file, name)) { 0101 qDebug() << "Dictionary load FAILED: " << newDict->getName(); 0102 delete newDict; 0103 return false; 0104 } 0105 0106 qDebug() << "Dictionary Loaded : " << newDict->getName(); 0107 d->dictManagers.insert(name, newDict); 0108 return true; 0109 } 0110 0111 /** 0112 * Examine the DictQuery and farm out the search to the specialized dict 0113 * managers. Note that a global search limit will probably be implemented 0114 * either here or in the DictFile implementations... probably both 0115 * 0116 * @param query the query, see DictQuery documentation 0117 */ 0118 EntryList *DictionaryManager::doSearch(const DictQuery &query) const 0119 { 0120 EntryList *ret = new EntryList(); 0121 #if 0 0122 if( query.getMeaning() == "(libkiten)" ) 0123 { 0124 ret->append( new debug_entry( "Summary of libkiten data" ) ); 0125 foreach( const QString &dict, listDictionaries() ) 0126 { 0127 ret->append( new debug_entry( dict ) ); 0128 } 0129 return ret; 0130 } 0131 #endif 0132 0133 // There are two basic modes.... one in which the query 0134 // specifies the dictionary list, one in which it does not 0135 QStringList dictsFromQuery = query.getDictionaries(); 0136 if (dictsFromQuery.isEmpty()) { 0137 // None specified, search all 0138 foreach (DictFile *it, d->dictManagers) { 0139 qDebug() << "Searching in " << it->getName() << "dictionary."; 0140 EntryList *temp = it->doSearch(query); 0141 if (temp) { 0142 ret->appendList(temp); 0143 } 0144 delete temp; 0145 } 0146 } else { 0147 foreach (const QString &target, dictsFromQuery) { 0148 DictFile *newestFound = d->dictManagers.find(target).value(); 0149 if (newestFound != nullptr) { 0150 EntryList *temp = newestFound->doSearch(query); 0151 if (temp) { 0152 ret->appendList(temp); 0153 } 0154 delete temp; 0155 } 0156 } 0157 } 0158 0159 ret->setQuery(query); // Store the query for later use. 0160 qDebug() << "From query: '" << query.toString() << "' Found " << ret->count() << " results"; 0161 qDebug() << "Incoming match type: " << query.getMatchType() << " Outgoing: " << ret->getQuery().getMatchType(); 0162 return ret; 0163 } 0164 0165 /** 0166 * For this case, we let polymorphism do most of the work. We assume that the user wants 0167 * to pare down the results, so we let the individual entry matching methods run over the 0168 * new query and accept (and copy) any of those that pass. 0169 */ 0170 EntryList *DictionaryManager::doSearchInList(const DictQuery &query, const EntryList *list) const 0171 { 0172 EntryList *ret = new EntryList(); 0173 0174 foreach (Entry *it, *list) { 0175 if (it->matchesQuery(query)) { 0176 Entry *x = it->clone(); 0177 ret->append(x); 0178 } 0179 } 0180 0181 ret->setQuery(query + list->getQuery()); 0182 return ret; 0183 } 0184 0185 QMap<QString, QString> DictionaryManager::generateExtendedFieldsList() 0186 { 0187 QMap<QString, QString> result; 0188 const QStringList dictTypes = listDictFileTypes(); 0189 for (const QString &dictType : dictTypes) { 0190 DictFile *tempDictFile = makeDictFile(dictType); 0191 QMap<QString, QString> tempList = tempDictFile->getSearchableAttributes(); 0192 QMap<QString, QString>::const_iterator it = tempList.constBegin(); 0193 while (it != tempList.constEnd()) { 0194 if (!result.contains(it.key())) { 0195 result.insert(it.key(), it.value()); 0196 } 0197 ++it; 0198 } 0199 delete tempDictFile; 0200 } 0201 0202 return result; 0203 } 0204 0205 QMap<QString, DictionaryPreferenceDialog *> DictionaryManager::generatePreferenceDialogs(KConfigSkeleton *config, QWidget *parent) 0206 { 0207 QMap<QString, DictionaryPreferenceDialog *> result; 0208 const QStringList dictTypes = listDictFileTypes(); 0209 for (const QString &dictType : dictTypes) { 0210 DictFile *tempDictFile = makeDictFile(dictType); 0211 DictionaryPreferenceDialog *newDialog = tempDictFile->preferencesWidget(config, parent); 0212 0213 if (newDialog == nullptr) 0214 continue; 0215 result.insert(dictType, newDialog); 0216 delete tempDictFile; 0217 } 0218 0219 return result; 0220 } 0221 0222 /** 0223 * Return a list of the dictionaries by their name (our key) 0224 * Note that this dictionary name does not necessarily have to have anything 0225 * to do with the actual dictionary name... 0226 */ 0227 QStringList DictionaryManager::listDictionaries() const 0228 { 0229 QStringList ret; 0230 foreach (DictFile *it, d->dictManagers) { 0231 ret.append(it->getName()); 0232 } 0233 0234 return ret; 0235 } 0236 0237 /** 0238 * IMPORTANT: To add a dictionary type, you have to manually add the creation 0239 * step here, the prev method, and \#include your header file above. If you have 0240 * fully implemented the interface in DictionaryManager.h, It should simply work. 0241 */ 0242 QStringList DictionaryManager::listDictFileTypes() 0243 { 0244 QStringList list; 0245 list.append(EDICT); 0246 list.append(KANJIDIC); 0247 0248 // Add your dictionary type here! 0249 0250 return list; 0251 } 0252 0253 /** 0254 * Return the dictionary type and file used by a named dictionary. 0255 * returns a pair of empty QStrings if you specify an invalid name 0256 * 0257 * @param name the name of the dictionary, as given in the addDictionary method 0258 */ 0259 QPair<QString, QString> DictionaryManager::listDictionaryInfo(const QString &name) const 0260 { 0261 if (!d->dictManagers.contains(name)) // This name not in list! 0262 { 0263 return qMakePair(QString(), QString()); 0264 } 0265 0266 return qMakePair(d->dictManagers[name]->getName(), d->dictManagers[name]->getFile()); 0267 } 0268 0269 /** 0270 * Return a list of the names of each dictionary of a given type. 0271 * 0272 * @param type the type of the dictionary we want a list of 0273 */ 0274 QStringList DictionaryManager::listDictionariesOfType(const QString &type) const 0275 { 0276 QStringList ret; 0277 QHash<QString, DictFile *>::const_iterator it = d->dictManagers.constBegin(); 0278 while (it != d->dictManagers.constEnd()) { 0279 if (it.value()->getType() == type) { 0280 ret.append(it.key()); 0281 } 0282 0283 ++it; 0284 } 0285 0286 return ret; 0287 } 0288 0289 /** 0290 * Load preference settings for a particular dictionary 0291 */ 0292 void DictionaryManager::loadDictSettings(const QString &dictName, KConfigSkeleton *config) 0293 { 0294 DictFile *dict = this->makeDictFile(dictName); 0295 if (dict != nullptr) { 0296 config->setCurrentGroup("dicts_" + dictName.toLower()); 0297 dict->loadSettings(config); 0298 delete dict; 0299 } 0300 } 0301 0302 void DictionaryManager::loadSettings(const KConfig &config) 0303 { 0304 Q_UNUSED(config); 0305 // TODO 0306 } 0307 0308 /** 0309 * IMPORTANT: To add a dictionary type, you have to manually add the creation 0310 * step here, the next method, and \#include your header file above. If you have 0311 * fully implemented the interface in dictionarymanager.h, It should simply work. 0312 */ 0313 DictFile *DictionaryManager::makeDictFile(const QString &type) 0314 { 0315 if (type == EDICT) { 0316 return new DictFileEdict(); 0317 } else if (type == KANJIDIC) { 0318 return new DictFileKanjidic(); 0319 } 0320 0321 // Add new dictionary types here!!! 0322 0323 return NULL; 0324 } 0325 0326 void DictionaryManager::removeAllDictionaries() 0327 { 0328 qDeleteAll(d->dictManagers); 0329 d->dictManagers.clear(); 0330 } 0331 0332 /** 0333 * Remove a dictionary from the list, and delete the dictionary object 0334 * (it should close files, deallocate memory, etc). 0335 * 0336 * @param name the name of the dictionary, as given in the addDictionary method 0337 */ 0338 bool DictionaryManager::removeDictionary(const QString &name) 0339 { 0340 DictFile *file = d->dictManagers.take(name); 0341 delete file; 0342 return true; 0343 }