/*************************************************************************** KDBSearchEngine2.cpp - description ------------------- begin : Fri Sep 8 2000 copyright : (C) 2000-2003 by Andrea Rizzi email : rizzi@kde.org ***************************************************************************/ /* Translation search engine. Version II Copyright 2000-2003 Andrea Rizzi rizzi@kde.org License GPL v 2.0 * * * In addition, as a special exception, the copyright holders give * * permission to link the code of this program with any edition of * * the TQt library by Trolltech AS, Norway (or with modified versions * * of TQt that use the same license as TQt), and distribute linked * * combinations including the two. You must obey the GNU General * * Public License in all respects for all of the code used other than * * TQt. If you modify this file, you may extend this exception to * * your version of the file, but you are not obligated to do so. If * * you do not wish to do so, delete this exception statement from * * your version. * */ #include "algorithms.h" #include "chunk.h" #include "database.h" #include "KDBSearchEngine2.h" #include "dbscan.h" #include #include #include #include #include #include #include #include #include #include #define i18n (const char *) KDBSearchEngine2::KDBSearchEngine2(TQObject *parent,const char*name) : SearchEngine(parent,name) { pw=0; dbDirectory="."; di=0; //Database Interface is not yet initialized connect(this,TQT_SIGNAL(hasError(TQString)),TQT_SLOT(setLastError(TQString))); searching=false; // i'm not searching iAmReady=true; //there are no reason to say I'm not ready. } KDBSearchEngine2::~KDBSearchEngine2() { if(di) delete di; //delete database interface } bool KDBSearchEngine2::startSearch(TQString str) { kdDebug(0) << "Start a new search. Looking for: " << str << endl; static TQString queryString; queryString=str; //set the latest query string (note: it is static) if(autoupdate) { updateSettings(); } if(!init()) return false; //-check initialization di->stop(true); //stop all new emits from database interface emit started(); //say everybody we are starting if(searching) return true; //We already have a search loop, as soon as we come back //on the search loop we will start the new search (queryString). searching=true; //really start searching TQString searchingString; do //Search loop, it stops only when finished and latest searched string is the actual query string. { searchingString=queryString; //-set new search string di->stop(false); //-unlock searching if(numberOfResult<1) numberOfResult=1; // di->singleWordMatch(searchingString,0,true); GenericSearchAlgorithm strategy(di,&settings); //Let's create a search sequence: ExactSearchAlgorithm exact(di,&settings); AlphaSearchAlgorithm alpha(di,&settings); SentenceArchiveSearchAlgorithm sent(di,&settings); ChunkByChunkSearchAlgorithm sbys(di,&settings); ChunkByChunkSearchAlgorithm wbyw(di,&settings); CorrelationSearchAlgorithm corr(di,&settings); FuzzyChunkSearchAlgorithm fs(di,&settings); FuzzyChunkSearchAlgorithm fw(di,&settings); SentenceChunkFactory sf(di); sbys.setChunkFactory(&sf); fs.setChunkFactory(&sf); WordChunkFactory wf(di); wbyw.setChunkFactory(&wf); fw.setChunkFactory(&wf); strategy.addAlgorithm(&exact); strategy.addAlgorithm(&alpha); strategy.addAlgorithm(&sent); strategy.addAlgorithm(&sbys); //strategy.addAlgorithm(&fs); strategy.addAlgorithm(&fw); strategy.addAlgorithm(&corr); strategy.addAlgorithm(&wbyw); connect(&strategy,TQT_SIGNAL(newResult(QueryResult)),this,TQT_SLOT(receiveResult(QueryResult))); strategy.exec(searchingString); disconnect(&strategy,TQT_SIGNAL(newResult(QueryResult)),this,TQT_SLOT(receiveResult(QueryResult))); kdDebug(0) << "End of search for " << searchingString << endl; } while(searchingString!=queryString); kdDebug(0) << "Exiting the search loop" << endl; //if != someone asked a different string when we was searching //so we restart our search (maybe a cleanresult is needed?). di->stop(false); //-clean searching locks searching=false; //-clean searching locks emit finished(); //Finished return true; } bool KDBSearchEngine2::startSearchInTranslation(TQString str) { if(autoupdate) { updateSettings(); } //TODO!!!! return true; } bool KDBSearchEngine2::messagesForPackage(const TQString& package , TQValueList& resultList, TQString& error) { //FIXME implement this (needs filters) return true; } void KDBSearchEngine2::setLastError(TQString er) { lasterror=er; } TQString KDBSearchEngine2::translate(const TQString text) { ExactSearchAlgorithm exact(di,&settings); return exact.exec(text)[0].result(); } void KDBSearchEngine2::receiveResult(QueryResult r) { SearchResult se; // Create a new SearchResult for our QueryResult se.translation=r.richResult(); se.found=r.richOriginal(); se.plainTranslation=r.result(); se.plainFound=r.original(); se.score=r.score(); emit resultFound(&se); // dispatch the new SearchResult } /* A SEARCH RESULT CONTAINS (see searchengine.h) TQString requested; TQString found; TQString translation; TQString plainTranslation; TQString plainFound; TQString plainRequested; int score; TQPtrList descriptions; */ bool KDBSearchEngine2::init() { if(di!=0) return true; //if there already is a DBinterface we are ok else { di = new DataBaseInterface(dbDirectory,&settings); connect(di,TQT_SIGNAL(newResult(QueryResult)),this,TQT_SLOT(receiveResult(QueryResult))); //FIXME: what wbout ready() if(!di->mainOk()) return false; //check if the main DB is OK. return true; } } const TDEAboutData *KDBSearchEngine2::about() const { return DbSe2Factory::instance()->aboutData(); } void KDBSearchEngine2::stringChanged( TQString orig, TQString translated , TQString description) { if(!init()) return; //if(translated.isEmpty()) return; InputInfo ii; if(description.find("fuzzy",false)==-1) di->addEntry(orig,translated,&ii); } PrefWidget * KDBSearchEngine2::preferencesWidget(TQWidget *parent) { pw = new KDB2PreferencesWidget(parent); kdDebug(0) << "new KDB2 preferences widget" << endl; setSettings(); connect(pw,TQT_SIGNAL(restoreNow()),this,TQT_SLOT(setSettings())); connect(pw,TQT_SIGNAL(applyNow()),this,TQT_SLOT(updateSettings())); connect(pw,TQT_SIGNAL(destroyed()),this,TQT_SLOT(prefDestr())); connect(pw->dbpw->scanAll,TQT_SIGNAL(clicked()),this,TQT_SLOT(scanAllPressed())); connect(pw->dbpw->scanSource,TQT_SIGNAL(clicked()),this,TQT_SLOT(scanNowPressed())); connect(pw->dbpw->addSource,TQT_SIGNAL(clicked()),this,TQT_SLOT(addSource())); connect(pw->dbpw->editSource,TQT_SIGNAL(clicked()),this,TQT_SLOT(editSource())); connect(pw->dbpw->removeSource,TQT_SIGNAL(clicked()),this,TQT_SLOT(removeSource())); return pw; } void KDBSearchEngine2::saveSettings(TDEConfigBase *config) { TDEConfigGroupSaver cgs(config,"KDBSearchEngine2"); config->writeEntry("DBDirectory",dbDirectory); config->writeEntry("AutoAdd",autoAdd); config->writeEntry("UseSentence",useSentence); config->writeEntry("UseGlossary",useGlossary); config->writeEntry("UseExact",useExact); config->writeEntry("UseDivide",useDivide); config->writeEntry("UseAlpha",useAlpha); config->writeEntry("UseWordByWord",useWordByWord); config->writeEntry("UseDynamic",useDynamic); config->writeEntry("NumberOfResults",numberOfResult); config->writeEntry("ScoreDivide",settings.scoreDivide); config->writeEntry("ScoreExact",settings.scoreExact); config->writeEntry("ScoreSentence",settings.scoreSentence); config->writeEntry("ScoreWordByWord",settings.scoreWordByWord); config->writeEntry("ScoreGlossary",settings.scoreGlossary); config->writeEntry("ScoreAlpha",settings.scoreAlpha); config->writeEntry("ScoreDynamic",settings.scoreDynamic); config->writeEntry("MinimumScore",settings.minScore); config->writeEntry("FirstCapital",settings.firstCapital); config->writeEntry("AllCapital",settings.allCapital); config->writeEntry("Accelerator",settings.accelerator); config->writeEntry("SameLetter",settings.sameLetter); uint sourceNumber=0; config->writeEntry("NumberOfDBImportSources",sources.count()); for(TQMap::iterator sourceIt=sources.begin() ; sourceIt!=sources.end(); ++sourceIt) { sourceNumber++; config->setGroup("DBImportSource-"+TQString::number(sourceNumber)); config->writeEntry("Name",sourceIt.key()); sourceIt.data().writeConfig(config); } } void KDBSearchEngine2::readSettings(TDEConfigBase *config) { /*TQString defaultDir; TDEStandardDirs * dirs = TDEGlobal::dirs(); if(dirs) { defaultDir = dirs->saveLocation("data"); if(defaultDir.right(1)!="/") defaultDir+="/"; defaultDir += "kbabeldict/dbsearchengine2"; } */ TDEConfigGroupSaver cgs(config,"KDBSearchEngine2"); // dbDirectory=config->readEntry("DBDirectory",defaultDir); autoAdd=config->readBoolEntry("AutoAdd",true); useSentence=config->readBoolEntry("UseSentence",true); useGlossary=config->readBoolEntry("UseGlossary",true); useExact=config->readBoolEntry("UseExact",true); useDivide=config->readBoolEntry("UseDivide",true); useAlpha=config->readBoolEntry("UseAlpha",true); useWordByWord=config->readBoolEntry("UseWordByWord",true); useDynamic=config->readBoolEntry("UseDynamic",true); numberOfResult=config->readNumEntry("NumberOfResults",5); settings.scoreDivide=config->readNumEntry("ScoreDivide",90); settings.scoreExact=config->readNumEntry("ScoreExact",100); settings.scoreSentence=config->readNumEntry("ScoreSentence",90); settings.scoreWordByWord=config->readNumEntry("ScoreWordByWord",70); settings.scoreGlossary=config->readNumEntry("ScoreGlossary",98); settings.scoreAlpha=config->readNumEntry("ScoreAlpha",98); settings.scoreDynamic=config->readNumEntry("ScoreDynamic",80); settings.minScore=config->readNumEntry("MinimumScore",60); settings.firstCapital=config->readBoolEntry("FirstCapital",true); settings.allCapital=config->readBoolEntry("AllCapital",false); settings.accelerator=config->readBoolEntry("Accelerator",true); settings.sameLetter=config->readBoolEntry("SameLetter",true); uint numberOfSources=config->readNumEntry("NumberOfDBImportSources",0); kdDebug(0) << "Found "<< numberOfSources << " sources" << endl; for(uint sourceNumber=1;sourceNumber<=numberOfSources;sourceNumber++) { config->setGroup("DBImportSource-"+TQString::number(sourceNumber)); TQString name=config->readEntry("Name"); sources[name].readConfig(config); } if(pw) setSettings(); } void KDBSearchEngine2::setSettings() { if(pw) { pw->dbpw->dbDirectory->setURL(dbDirectory); pw->dbpw->autoUpdate->setChecked(autoAdd); pw->dbpw->useSentence->setChecked(useSentence); pw->dbpw->useGlossary->setChecked(useGlossary); pw->dbpw->useExact->setChecked(useExact); pw->dbpw->useDivide->setChecked(useDivide); pw->dbpw->useAlpha->setChecked(useAlpha); pw->dbpw->useWordByWord->setChecked(useWordByWord); pw->dbpw->useDynamic->setChecked(useDynamic); pw->dbpw->numberOfResult->setValue(numberOfResult); pw->dbpw->scoreDivide->setValue(settings.scoreDivide); pw->dbpw->scoreExact->setValue(settings.scoreExact); pw->dbpw->scoreSentence->setValue(settings.scoreSentence); pw->dbpw->scoreWordByWord->setValue(settings.scoreWordByWord); pw->dbpw->scoreGlossary->setValue(settings.scoreGlossary); pw->dbpw->scoreAlpha->setValue(settings.scoreAlpha); pw->dbpw->scoreDynamic->setValue(settings.scoreDynamic); pw->dbpw->minScore->setValue(settings.minScore); pw->dbpw->firstCapital->setChecked(settings.firstCapital); pw->dbpw->allCapital->setChecked(settings.allCapital); pw->dbpw->accelerator->setChecked(settings.accelerator); pw->dbpw->sameLetter->setChecked(settings.sameLetter); //pw->dbpw->checkLang->setChecked(true); //pw->dbpw->useFilters->setChecked(false); //pw->dbpw->dateToday->setChecked(false); pw->dbpw->sourceList->clear(); for(TQMap::iterator sourceIt=sources.begin() ; sourceIt!=sources.end(); ++sourceIt) { pw->dbpw->sourceList->insertItem(sourceIt.key()); } } } void KDBSearchEngine2::updateSettings() { if(!pw) return; TQString newdb = pw->dbpw->dbDirectory->url(); if(newdb !=dbDirectory) { kdDebug(0) << "Recreate DB-Interface cause dbdir is changed" << endl; dbDirectory=newdb; if (di!=0) delete di; di= new DataBaseInterface(dbDirectory,&settings); } autoAdd=pw->dbpw->autoUpdate->isChecked(); useSentence=pw->dbpw->useSentence->isChecked(); useGlossary=pw->dbpw->useGlossary->isChecked(); useExact=pw->dbpw->useExact->isChecked(); useDivide=pw->dbpw->useDivide->isChecked(); useAlpha=pw->dbpw->useAlpha->isChecked(); useWordByWord=pw->dbpw->useWordByWord->isChecked(); useDynamic=pw->dbpw->useDynamic->isChecked(); numberOfResult=pw->dbpw->numberOfResult->value(); settings.scoreWordByWord=pw->dbpw->scoreWordByWord->value(); settings.scoreGlossary=pw->dbpw->scoreGlossary->value(); settings.scoreDivide=pw->dbpw->scoreDivide->value(); settings.scoreExact=pw->dbpw->scoreExact->value(); settings.scoreSentence=pw->dbpw->scoreSentence->value(); settings.scoreAlpha=pw->dbpw->scoreAlpha->value(); settings.scoreDynamic=pw->dbpw->scoreDynamic->value(); settings.minScore=pw->dbpw->minScore->value(); settings.firstCapital=pw->dbpw->firstCapital->isChecked(); settings.allCapital=pw->dbpw->allCapital->isChecked(); settings.accelerator=pw->dbpw->accelerator->isChecked(); settings.sameLetter=pw->dbpw->sameLetter->isChecked(); //pw->dbpw->editRule-> //pw->dbpw->deleteRule-> //pw->dbpw->customRules-> /* pw->dbpw->checkLang-> pw->dbpw->useFilters-> pw->dbpw->dateToday-> pw->dbpw->removeSource-> pw->dbpw->scanSource-> pw->dbpw->addSource-> pw->dbpw->sourceDir-> pw->dbpw->scanAll-> pw->dbpw->sourceList-> */ } /*void KDBSearchEngine2::scanSource(TQString sourceName) { //FIXME: an error here would be nice if(!init()) return; for(TQValueList::iterator sourceIt=sources.begin() ; sourceIt!=sources.end(); sourceIt++) { if((*sourceIt).getName()==sourceName) { TQValueList urls=(*sourceIt).urls(); PoScanner ps(di); for(TQValueList::iterator urlIt=urls.begin();urlIt!=urls.end();urlIt++) ps.scanFile(*urlIt); //We suppose name are unique so no need for further scrolling return ; } } }*/ void KDBSearchEngine2::scanNowPressed() { if(!pw) { kdDebug(0) << "We should not be here, scanNow called without a pw!" << endl; return; } TQString sourceName; sourceName=pw->dbpw->sourceList->currentText(); if(!init()) return; if(sources.contains(sourceName)) { TQValueList urls=sources[sourceName].urls(); PoScanner ps(di); for(TQValueList::iterator urlIt=urls.begin();urlIt!=urls.end();++urlIt) ps.scanURL(*urlIt); } else { kdDebug(0) << "source name not found in our MAP. This is a bug." << endl; } } void KDBSearchEngine2::scanAllPressed() { //FIXME: an error here would be nice too if(!init()) return; PoScanner ps(di); for(TQMap::iterator sourceIt=sources.begin() ; sourceIt!=sources.end(); ++sourceIt) { TQValueList urls=(*sourceIt).urls(); for(TQValueList::iterator urlIt=urls.begin();urlIt!=urls.end();++urlIt) ps.scanURL(*urlIt); } } void KDBSearchEngine2::editSource() { if(!pw) { kdDebug(0) << "We should not be here, editSource called without a pw!" << endl; return; } TQString sourceName; sourceName=pw->dbpw->sourceList->currentText(); if(sources.contains(sourceName)) { bool nameIsNew; TQString newName; SourceDialog sd; do{ sources[sourceName].setDialogValues(&sd); sd.sourceName->setText(sourceName); if(sd.exec()==TQDialog::Accepted) { sources[sourceName].getDialogValues(&sd); newName= sd.sourceName->text(); } else { return; } nameIsNew=sources.contains(newName); if(newName!=sourceName && !nameIsNew) { KMessageBox::error(0, i18n("The name you chose is already used.\nPlease change the source name."), i18n("Name is Not Unique")); kdDebug(0) << "Name is not uniqe" << endl; } }while(newName!=sourceName && !nameIsNew); if(newName!=sourceName){ sources[newName]=sources[sourceName]; sources.remove(sourceName); } pw->dbpw->sourceList->changeItem(newName,pw->dbpw->sourceList->currentItem()); } else { kdDebug(0) << "source name not found in our MAP. This is a bug." << endl; } } void KDBSearchEngine2::removeSource() { if(!pw) { kdDebug(0) << "We should not be here, delteSource called without a pw!" << endl; return; } TQString sourceName; sourceName=pw->dbpw->sourceList->currentText(); sources.remove(sourceName); pw->dbpw->sourceList->removeItem(pw->dbpw->sourceList->currentItem()); } void KDBSearchEngine2::addSource() { TQString newName; SourceDialog sd; bool nameIsNew; do{ if(sd.exec()==TQDialog::Accepted) { newName= sd.sourceName->text(); nameIsNew=!sources.contains(newName); } else { return; } // nameIsNew=sources.contains(newName); if(!nameIsNew) { KMessageBox::error(0,i18n("The name you chose is already used.\nPlease change the source name."), i18n("Name is Not Unique")); kdDebug(0) << "Name is not uniqe" << endl; } else { sources[newName].getDialogValues(&sd); } }while(!nameIsNew); pw->dbpw->sourceList->insertItem(newName); } TQString KDBSearchEngine2::searchTranslation( const TQString text, int & score ) { GenericSearchAlgorithm strategy(di,&settings); strategy.setMaxResultNumber(1); ExactSearchAlgorithm exact(di,&settings); AlphaSearchAlgorithm alpha(di,&settings); SentenceArchiveSearchAlgorithm sent(di,&settings); strategy.addAlgorithm(&exact); strategy.addAlgorithm(&alpha); strategy.addAlgorithm(&sent); QueryResult firstRes=strategy.exec(text)[0]; score=firstRes.score(); return firstRes.result(); } TQString KDBSearchEngine2::fuzzyTranslation( const TQString text, int & score ) { GenericSearchAlgorithm strategy(di,&settings); strategy.setMaxResultNumber(1); ExactSearchAlgorithm exact(di,&settings); AlphaSearchAlgorithm alpha(di,&settings); SentenceArchiveSearchAlgorithm sent(di,&settings); ChunkByChunkSearchAlgorithm sbys(di,&settings); ChunkByChunkSearchAlgorithm wbyw(di,&settings); FuzzyChunkSearchAlgorithm fs(di,&settings); FuzzyChunkSearchAlgorithm fw(di,&settings); SentenceChunkFactory sf(di); sbys.setChunkFactory(&sf); fs.setChunkFactory(&sf); WordChunkFactory wf(di); wbyw.setChunkFactory(&wf); fw.setChunkFactory(&wf); strategy.addAlgorithm(&exact); strategy.addAlgorithm(&alpha); strategy.addAlgorithm(&sent); strategy.addAlgorithm(&sbys); //strategy.addAlgorithm(&fs); strategy.addAlgorithm(&fw); strategy.addAlgorithm(&wbyw); QueryResult firstRes=strategy.exec(text)[0]; score=firstRes.score(); return firstRes.result(); } //FIXME: ProgressBasr, progressbar,progressbasr #include "KDBSearchEngine2.moc"