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 }